001: /* ====================================================================
002: The Jicarilla Software License
003:
004: Copyright (c) 2003 Leo Simons.
005: All rights reserved.
006:
007: Permission is hereby granted, free of charge, to any person obtaining
008: a copy of this software and associated documentation files (the
009: "Software"), to deal in the Software without restriction, including
010: without limitation the rights to use, copy, modify, merge, publish,
011: distribute, sublicense, and/or sell copies of the Software, and to
012: permit persons to whom the Software is furnished to do so, subject to
013: the following conditions:
014:
015: The above copyright notice and this permission notice shall be
016: included in all copies or substantial portions of the Software.
017:
018: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
019: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
020: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
021: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
022: CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
023: TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
024: SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
025: ==================================================================== */
026: package org.jicarilla.lang;
027:
028: import java.lang.reflect.Method;
029: import java.util.HashMap;
030: import java.util.Map;
031:
032: /**
033: * <p>A simple bean modelling a method invocation. It can be used as part of a
034: * simple method interception model, or to redirect method calls elsewhere. See
035: * the {@link AsyncEnabled AsyncEnabled} interface, which accepts an invocation
036: * object to support asynchronous method invocation.</p>
037: *
038: * <p><b>Implementation notes</b></p> <p>Since this class is performance
039: * critical, everything is marked final, and we don't use an interface.
040: * Performs no state validation of any kind.</p>
041: *
042: * @author <a href="lsimons at jicarilla dot org">Leo Simons</a>
043: * @version $Id: Invocation.java,v 1.1 2004/03/23 13:37:56 lsimons Exp $
044: */
045: public final class Invocation implements Recyclable {
046: // ----------------------------------------------------------------------
047: // Properties
048: // ----------------------------------------------------------------------
049:
050: protected Object m_proxy;
051: protected Object m_target;
052: protected Method m_method;
053: protected Object[] m_args;
054: protected Object m_result;
055: protected Throwable m_throwable;
056:
057: protected Map m_invocationContext;
058:
059: // ----------------------------------------------------------------------
060: // Constructors
061: // ----------------------------------------------------------------------
062:
063: /**
064: * Create an empty invocation instance.
065: */
066: public Invocation() {
067: m_invocationContext = new HashMap();
068: }
069:
070: /**
071: * Create a fully populated invocation instance.
072: *
073: * @param target the actual recipient of the invocation
074: * @param proxy the proxy around the target
075: * @param method the method to call on the target
076: * @param args the arguments to the method
077: */
078: public Invocation(final Object target, final Object proxy,
079: final Method method, final Object[] args) {
080: this ();
081: m_target = target;
082: m_proxy = proxy;
083: m_method = method;
084: m_args = args;
085: }
086:
087: // ----------------------------------------------------------------------
088: // Methods
089: // ----------------------------------------------------------------------
090:
091: /**
092: * Recycle the invocation.
093: *
094: * @see Recyclable#recycle()
095: */
096: public final void recycle() {
097: m_target = null;
098: m_proxy = null;
099: m_method = null;
100: m_args = null;
101: m_result = null;
102: m_throwable = null;
103:
104: if (m_invocationContext != null) {
105: try {
106: m_invocationContext.clear();
107: } catch (UnsupportedOperationException uoe) {
108: m_invocationContext = new HashMap();
109: }
110: } else {
111: m_invocationContext = new HashMap();
112: }
113: }
114:
115: /**
116: * Get the proxy around the target.
117: *
118: * @return the proxy
119: */
120: public final Object getProxy() {
121: return m_proxy;
122: }
123:
124: /**
125: * Set the proxy around the target.
126: *
127: * @param proxy the proxy
128: */
129: public final void setProxy(final Object proxy) {
130: m_proxy = proxy;
131: }
132:
133: /**
134: * Get the recipient of the invocation.
135: *
136: * @return the recipient
137: */
138: public final Object getTarget() {
139: return m_target;
140: }
141:
142: /**
143: * Set the recipient of the invocation.
144: *
145: * @param target the recipient
146: */
147: public final void setTarget(final Object target) {
148: m_target = target;
149: }
150:
151: /**
152: * Get the method to invoke on the recipient.
153: *
154: * @return the method to invoke
155: */
156: public final Method getMethod() {
157: return m_method;
158: }
159:
160: /**
161: * Set the method to invoke on the recipient.
162: *
163: * @param method the method to invoke
164: */
165: public final void setMethod(final Method method) {
166: m_method = method;
167: }
168:
169: /**
170: * Get the arguments to the method.
171: *
172: * @return the arguments
173: */
174: public final Object[] getArgs() {
175: return m_args;
176: }
177:
178: /**
179: * Set the arguments to the method.
180: *
181: * @param args the arguments
182: */
183: public final void setArgs(final Object[] args) {
184: m_args = args;
185: }
186:
187: /**
188: * Get the result of the invocation.
189: *
190: * @return the result
191: */
192: public final Object getResult() {
193: return m_result;
194: }
195:
196: /**
197: * Set the result of the invocation.
198: *
199: * @param result the result
200: */
201: public final void setResult(final Object result) {
202: m_result = result;
203: }
204:
205: /**
206: * Get the exception or error caused by the invocation.
207: *
208: * @return the exception or error
209: */
210: public final Throwable getThrowable() {
211: return m_throwable;
212: }
213:
214: /**
215: * Set the exception or error caused by the invocation.
216: *
217: * @param throwable the exception or error
218: */
219: public final void setThrowable(final Throwable throwable) {
220: m_throwable = throwable;
221: }
222:
223: /**
224: * Get the map of arbitrary values associated with this invocation, the
225: * invocation context.
226: *
227: * @return the map containing the invocation context
228: */
229: public final Map getInvocationContext() {
230: return m_invocationContext;
231: }
232:
233: /**
234: * Set the map of arbitrary values associated with this invocation, the
235: * invocation context.
236: *
237: * @param invocationContext the map containing the invocation context
238: */
239: public final void setInvocationContext(final Map invocationContext) {
240: m_invocationContext = invocationContext;
241: }
242:
243: // ----------------------------------------------------------------------
244: // equals, hashcode, clone
245: // ----------------------------------------------------------------------
246:
247: /**
248: * Compares objects for equality.
249: *
250: * @param object the object to test against this one
251: *
252: * @return true if the two objects are equal, false otherwise
253: * @see java.lang.Object#equals(Object)
254: */
255: public boolean equals(final Object object) {
256: if (object == null) {
257: return false;
258: }
259: if (super .equals(object)) {
260: return true;
261: }
262:
263: if (!(object instanceof Invocation)) {
264: return false;
265: }
266:
267: final Invocation other = (Invocation) object;
268:
269: if (equalField(this .getArgs(), other.getArgs())
270: && equalField(this .getInvocationContext(), other
271: .getInvocationContext())
272: && equalField(this .getMethod(), other.getMethod())
273: && equalField(this .getProxy(), other.getProxy())
274: && equalField(this .getResult(), other.getResult())
275: && equalField(this .getTarget(), other.getTarget())
276: && equalField(this .getThrowable(), other.getThrowable())) {
277: return true;
278: }
279:
280: return false;
281: }
282:
283: /**
284: * Test whether two fields are the same. A helper method for equals().
285: *
286: * @param thisF the first field to test
287: * @param otherF the second field to test
288: *
289: * @return true if the arguments are equal, false otherwise
290: */
291: protected boolean equalField(final Object this F, final Object otherF) {
292: if (otherF == null) {
293: if (this F != null) {
294: return false;
295: }
296: } else {
297: if (this F == null) {
298: return false;
299: }
300: if (!this F.equals(otherF)) {
301: return false;
302: }
303: }
304: return true;
305: }
306:
307: /**
308: * Return a code for placing the invocation in a hash.
309: *
310: * @return a code hash for use in hash mapping
311: * @see Object#hashCode()
312: */
313: public int hashCode() {
314: int code = 0;
315:
316: if (m_proxy != null) {
317: code = m_proxy.hashCode();
318: }
319: if (m_target != null) {
320: code = code | m_proxy.hashCode();
321: }
322: if (m_method != null) {
323: code = code | m_method.hashCode();
324: }
325: if (m_args != null) {
326: code = code | m_args.hashCode();
327: }
328: if (m_result != null) {
329: code = code | m_result.hashCode();
330: }
331: if (m_throwable != null) {
332: code = code | m_throwable.hashCode();
333: }
334:
335: return code;
336: }
337: }
|