KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > aop > joinpoint > MethodInvocation


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.aop.joinpoint;
23
24 import java.io.IOException JavaDoc;
25 import java.io.ObjectInput JavaDoc;
26 import java.io.ObjectOutput JavaDoc;
27 import java.lang.reflect.InvocationTargetException JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.rmi.MarshalledObject JavaDoc;
30 import java.util.ArrayList JavaDoc;
31
32 import org.jboss.aop.Advisor;
33 import org.jboss.aop.MethodInfo;
34 import org.jboss.aop.advice.Interceptor;
35 import org.jboss.aop.metadata.SimpleMetaData;
36
37 /**
38  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
39  * @version $Revision: 46058 $
40  */

41 public class MethodInvocation extends InvocationBase implements java.io.Externalizable JavaDoc
42 {
43    static final long serialVersionUID = -1313717554016611763L;
44    /**
45     * arguments of the method call expressed as an array of objects
46     */

47    protected java.lang.Object JavaDoc[] arguments;
48    protected long methodHash; // needs to be member variable as MethodInfo is not serializable across the wire.
49
protected MarshalledObject JavaDoc marshalledArguments;
50    protected Method JavaDoc advisedMethod;
51    protected Method JavaDoc unadvisedMethod;
52
53    public String JavaDoc toString()
54    {
55       StringBuffer JavaDoc sb = new StringBuffer JavaDoc(100);
56       sb.append("[");
57       sb.append("advisedMethod=").append(advisedMethod);
58       sb.append(", unadvisedMethod=").append(unadvisedMethod);
59       sb.append(", metadata=").append(metadata);
60       sb.append(", targetObject=").append(targetObject);
61       sb.append(", arguments=").append(arguments);
62       sb.append("]");
63       return sb.toString();
64    }
65
66
67    public MethodInvocation(MethodInfo info, org.jboss.aop.advice.Interceptor[] interceptors)
68    {
69       this(interceptors, info.getHash(), info.getAdvisedMethod(), info.getUnadvisedMethod(), info.getAdvisor());
70    }
71
72    public MethodInvocation(Interceptor[] interceptors, long methodHash, Method JavaDoc advisedMethod, Method JavaDoc unadvisedMethod, Advisor advisor)
73    {
74       super(interceptors);
75       this.advisor = advisor;
76       this.methodHash = methodHash;
77       this.advisedMethod = advisedMethod;
78       this.unadvisedMethod = unadvisedMethod;
79    }
80
81    protected MethodInvocation(org.jboss.aop.advice.Interceptor[] interceptors)
82    {
83       super(interceptors);
84    }
85
86    public MethodInvocation()
87    {
88    }
89
90    /**
91     * Invoke on the next interceptor in the chain. If this is already
92     * the end of the chain, reflection will call the constructor, field, or
93     * method you are invoking on.
94     */

95    public Object JavaDoc invokeNext() throws Throwable JavaDoc
96    {
97       if (interceptors != null && currentInterceptor < interceptors.length)
98       {
99          try
100          {
101             return interceptors[currentInterceptor++].invoke(this);
102          }
103          finally
104          {
105             // so that interceptors like clustering can reinvoke down the chain
106
currentInterceptor--;
107          }
108       }
109
110       return invokeTarget();
111    }
112    
113    /**
114     * Invokes the target joinpoint for this invocation skipping any subsequent
115     * interceptors in the chain.
116     */

117    public Object JavaDoc invokeTarget() throws Throwable JavaDoc
118    {
119       try
120       {
121          return getActualMethod().invoke(getTargetObject(), arguments);
122       }
123       catch (Throwable JavaDoc t)
124       {
125          throw handleErrors(getTargetObject(), getMethod(), arguments, t);
126       }
127    }
128
129
130    /**
131     * Handle invocation errors
132     *
133     * @param target the target
134     * @param method the method
135     * @param arguments the arguments
136     * @param t the error
137     * @return never
138     * @throws Throwable the throwable
139     */

140    public static Throwable JavaDoc handleErrors(Object JavaDoc target, Method JavaDoc method, Object JavaDoc[] arguments, Throwable JavaDoc t) throws Throwable JavaDoc
141    {
142       if (t instanceof IllegalArgumentException JavaDoc)
143       {
144          if (target == null)
145
146             throw new IllegalArgumentException JavaDoc("Null target for method " + method);
147          Class JavaDoc methodClass = method.getClass();
148          Class JavaDoc targetClass = target.getClass();
149          if (methodClass.isAssignableFrom(targetClass) == false)
150             throw new IllegalArgumentException JavaDoc("Wrong target. " + targetClass + " for " + method);
151          ArrayList JavaDoc expected = new ArrayList JavaDoc();
152          Class JavaDoc[] parameterTypes = method.getParameterTypes();
153          for (int i = 0; i < parameterTypes.length; ++i)
154             expected.add(parameterTypes[i].getName());
155          ArrayList JavaDoc actual = new ArrayList JavaDoc();
156          if (arguments != null)
157          {
158             for (int i = 0; i < arguments.length; ++i)
159             {
160                if (arguments[i] == null)
161                   actual.add(null);
162                else
163                   actual.add(arguments[i].getClass().getName());
164             }
165          }
166          throw new IllegalArgumentException JavaDoc("Wrong arguments. " + method.getName() + " expected=" + expected + " actual=" + actual);
167       }
168       else if (t instanceof InvocationTargetException JavaDoc)
169       {
170          throw ((InvocationTargetException JavaDoc) t).getTargetException();
171       }
172       throw t;
173    }
174
175    /**
176     * This method resolves an annotation based on the context of the invocation.
177     */

178    public Object JavaDoc resolveAnnotation(Class JavaDoc annotation)
179    {
180       Object JavaDoc val = super.resolveAnnotation(annotation);
181       if (val != null) return val;
182
183       if (getAdvisor() != null)
184       {
185          val = getAdvisor().resolveAnnotation(getMethod(), annotation);
186          if (val != null) return val;
187       }
188
189       return null;
190    }
191
192    /**
193     * This method resolves an annotation based on the context of the invocation.
194     */

195    public Object JavaDoc resolveAnnotation(Class JavaDoc[] annotations)
196    {
197       Object JavaDoc val = super.resolveAnnotation(annotations);
198       if (val != null) return val;
199
200       if (getAdvisor() != null)
201       {
202          val = getAdvisor().resolveAnnotation(getMethod(), annotations);
203          if (val != null) return val;
204       }
205
206       return null;
207    }
208
209    /**
210     * This method resolves metadata based on the context of the invocation.
211     * It iterates through its list of MetaDataResolvers to find out the
212     * value of the metadata desired.
213     * <p/>
214     * This list usually is ThreadMetaData, InstanceAdvisor.getMetaData
215     * ClassAdvisor.getMethodMetaData (or field, or constructor)
216     * ClassAdvisor.getDefaultMetaData
217     */

218    public Object JavaDoc getMetaData(Object JavaDoc group, Object JavaDoc attr)
219    {
220       Object JavaDoc val = super.getMetaData(group, attr);
221       if (val != null) return val;
222
223       if (getAdvisor() != null)
224       {
225          val = getAdvisor().getMethodMetaData().resolve(this, group, attr);
226          if (val != null) return val;
227       }
228
229       if (getAdvisor() != null)
230       {
231          val = getAdvisor().getDefaultMetaData().resolve(this, group, attr);
232          if (val != null) return val;
233       }
234
235       return null;
236    }
237
238    /**
239     * Get a wrapper invocation object that can insert a new chain of interceptors
240     * at runtime to the invocation flow. CFlow makes use of this.
241     * When the wrapper object finishes its invocation chain it delegates back to
242     * the wrapped invocation.
243     *
244     * @param newchain
245     * @return
246     */

247    public Invocation getWrapper(Interceptor[] newchain)
248    {
249       MethodInvocationWrapper wrapper = new MethodInvocationWrapper(this, newchain);
250       return wrapper;
251    }
252
253    /**
254     * Copies complete state of Invocation object.
255     *
256     * @return
257     */

258    public Invocation copy()
259    {
260       MethodInvocation wrapper = new MethodInvocation(interceptors, methodHash, advisedMethod, unadvisedMethod, advisor);
261       wrapper.metadata = this.metadata;
262       wrapper.currentInterceptor = this.currentInterceptor;
263       wrapper.instanceResolver = this.instanceResolver;
264       wrapper.setTargetObject(this.getTargetObject());
265       wrapper.setArguments(this.getArguments());
266       return wrapper;
267    }
268
269
270    public Object JavaDoc[] getArguments()
271    {
272       if (arguments == null && marshalledArguments != null)
273       {
274          try
275          {
276             arguments = (Object JavaDoc[]) marshalledArguments.get();
277             marshalledArguments = null;
278          }
279          catch (IOException JavaDoc e)
280          {
281             throw new RuntimeException JavaDoc(e);
282          }
283          catch (ClassNotFoundException JavaDoc e)
284          {
285             throw new RuntimeException JavaDoc(e);
286          }
287       }
288       return arguments;
289    }
290
291
292    public void setArguments(Object JavaDoc[] arguments)
293    {
294       this.arguments = arguments;
295    }
296
297    public Method JavaDoc getMethod()
298    {
299       return advisedMethod;
300    }
301
302    public Method JavaDoc getActualMethod()
303    {
304       return unadvisedMethod;
305    }
306
307    public long getMethodHash()
308    {
309       return methodHash;
310    }
311
312    public Advisor getAdvisor()
313    {
314       return advisor;
315    }
316
317
318    public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc
319    {
320       out.writeLong(methodHash);
321       if (getArguments() == null)
322       {
323          out.writeObject(null);
324       }
325       else
326       {
327          MarshalledObject JavaDoc mo = new MarshalledObject JavaDoc(getArguments());
328          out.writeObject(mo);
329       }
330       out.writeObject(metadata);
331    }
332
333    public void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc
334    {
335       methodHash = in.readLong();
336       marshalledArguments = (MarshalledObject JavaDoc) in.readObject();
337       metadata = (SimpleMetaData) in.readObject();
338    }
339
340 }
341
Popular Tags