KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > aop > advice > PerVmAdvice


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.advice;
23
24 import javassist.ClassPool;
25 import javassist.CtClass;
26 import javassist.CtField;
27 import javassist.CtMethod;
28 import javassist.CtNewMethod;
29 import org.jboss.aop.AspectManager;
30 import org.jboss.aop.instrument.OptimizedMethodInvocations;
31 import org.jboss.aop.instrument.TransformerCommon;
32 import org.jboss.aop.joinpoint.Invocation;
33 import org.jboss.aop.joinpoint.Joinpoint;
34 import org.jboss.aop.joinpoint.MethodJoinpoint;
35
36 import java.lang.reflect.Field JavaDoc;
37 import java.lang.reflect.Method JavaDoc;
38 import java.util.ArrayList JavaDoc;
39
40 /**
41  * Comment
42  *
43  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
44  * @version $Revision: 46033 $
45  */

46 public class PerVmAdvice
47 {
48    private static long counter = 0;
49
50    public static synchronized Interceptor generateOptimized(Joinpoint joinpoint, AspectManager manager, String JavaDoc adviceName, AspectDefinition a) throws Exception JavaDoc
51    {
52       Object JavaDoc aspect = manager.getPerVMAspect(a);
53       return generateInterceptor(joinpoint, aspect, adviceName);
54
55    }
56
57    public static Interceptor generateInterceptor(Joinpoint joinpoint, Object JavaDoc aspect, String JavaDoc adviceName) throws Exception JavaDoc
58    {
59       ClassLoader JavaDoc cl = aspect.getClass().getClassLoader();
60       String JavaDoc name = "org.jboss.aop.advice." + aspect.getClass().getName() + "_z_" + adviceName + "_" + System.identityHashCode(cl);
61       Class JavaDoc iclass = null;
62       
63       if (cl == null)
64       {
65          //The classloader will be null if loader by the booststrap classloader
66
cl = Thread.currentThread().getContextClassLoader();
67       }
68       synchronized (PerVmAdvice.class)
69       {
70          try
71          {
72             iclass = cl.loadClass(name);
73          }
74          catch(Exception JavaDoc e)
75          {
76          }
77
78          ClassPool pool;
79          try
80          {
81             pool = AspectManager.instance().findClassPool(cl);
82          }
83          catch (RuntimeException JavaDoc e)
84          {
85             // AutoGenerated
86
throw new RuntimeException JavaDoc(e);
87          }
88
89          if (iclass == null)
90          {
91             Method[] methods = aspect.getClass().getMethods();
92             ArrayList JavaDoc matches = new ArrayList JavaDoc();
93             for (int i = 0; i < methods.length; i++)
94             {
95                if (methods[i].getName().equals(adviceName)) matches.add(methods[i]);
96             }
97       
98             // todo: Need to have checks on whether the advice is overloaded and it is an argument type interception
99
if (matches.size() == 1)
100             {
101                Method method = (Method) matches.get(0);
102                if (joinpoint instanceof MethodJoinpoint)
103                {
104                   if (method.getParameterTypes().length == 0 || method.getParameterTypes().length > 1 || !Invocation.class.isAssignableFrom(method.getParameterTypes()[0]))
105                   {
106                      return generateArgsInterceptor(aspect, method, joinpoint);
107                   }
108                }
109             }
110       
111 // ClassPool pool = AspectManager.instance().findClassPool(cl);
112
CtClass clazz = TransformerCommon.makeClass(pool, name);
113             
114             // We need to know whether this Interceptor is actually advice.
115
CtClass interceptorInterface = pool.get("org.jboss.aop.advice.Interceptor");
116             CtClass abstractAdviceClass = pool.get("org.jboss.aop.advice.AbstractAdvice");
117             clazz.setSuperclass(abstractAdviceClass);
118       
119             // aspect field
120
CtClass aspectClass = pool.get(aspect.getClass().getName());
121             CtField field = new CtField(aspectClass, "aspectField", clazz);
122             field.setModifiers(javassist.Modifier.PUBLIC);
123             clazz.addField(field);
124             // getName()
125
CtMethod getNameTemplate = interceptorInterface.getDeclaredMethod("getName");
126             String JavaDoc getNameBody =
127             "{ " +
128             " return \"" + aspect.getClass().getName() + "." + adviceName + "\"; " +
129             "}";
130             CtMethod getName = CtNewMethod.make(getNameTemplate.getReturnType(), "getName", getNameTemplate.getParameterTypes(), getNameTemplate.getExceptionTypes(), getNameBody, clazz);
131             getName.setModifiers(javassist.Modifier.PUBLIC);
132             clazz.addMethod(getName);
133       
134             // invoke
135
CtMethod invokeTemplate = interceptorInterface.getDeclaredMethod("invoke");
136             StringBuffer JavaDoc invokeBody = new StringBuffer JavaDoc();
137             invokeBody.append("{ ");
138             if (matches.size() > 1)
139             {
140                for (int i = 0; i < matches.size(); i++)
141                {
142                   Method advice = (Method) matches.get(i);
143                   String JavaDoc param = advice.getParameterTypes()[0].getName();
144                   invokeBody.append(" if ($1 instanceof " + param + ") return aspectField." + adviceName + "((" + param + ")$1); ");
145                }
146                invokeBody.append(" return (org.jboss.aop.joinpoint.Invocation)null; ");
147             }
148             else
149             {
150                Method advice = (Method) matches.get(0);
151                String JavaDoc param = advice.getParameterTypes()[0].getName();
152                invokeBody.append("return aspectField." + adviceName + "((" + param + ")$1); ");
153             }
154             invokeBody.append("}");
155             CtMethod invoke = CtNewMethod.make(invokeTemplate.getReturnType(), "invoke", invokeTemplate.getParameterTypes(), invokeTemplate.getExceptionTypes(), invokeBody.toString(), clazz);
156             invoke.setModifiers(javassist.Modifier.PUBLIC);
157             clazz.addMethod(invoke);
158          
159             iclass = TransformerCommon.toClass(clazz, cl);
160          }
161       }
162       Interceptor rtn = (Interceptor) iclass.newInstance();
163       Field f = iclass.getField("aspectField");
164       f.set(rtn, aspect);
165       return rtn;
166    }
167
168    public static Interceptor generateArgsInterceptor(Object JavaDoc aspect, Method advice, Joinpoint joinpoint) throws Exception JavaDoc
169    {
170       Method method = ((MethodJoinpoint) joinpoint).getMethod();
171       String JavaDoc optimized = OptimizedMethodInvocations.getOptimizedInvocationClassName(method);
172
173
174       ClassPool pool = AspectManager.instance().findClassPool(aspect.getClass().getClassLoader());
175       CtClass clazz = TransformerCommon.makeClass(pool, "org.jboss.aop.advice." + aspect.getClass().getName() + counter++);
176
177       // We need to know whether this Interceptor is actually advice.
178
CtClass interceptorInterface = pool.get("org.jboss.aop.advice.Interceptor");
179       clazz.addInterface(interceptorInterface);
180
181       // aspect field
182
CtClass aspectClass = pool.get(aspect.getClass().getName());
183       CtField field = new CtField(aspectClass, "aspectField", clazz);
184       field.setModifiers(javassist.Modifier.PUBLIC);
185       clazz.addField(field);
186       // getName()
187
CtMethod getNameTemplate = interceptorInterface.getDeclaredMethod("getName");
188       String JavaDoc getNameBody =
189       "{ " +
190       " return \"" + aspect.getClass().getName() + "." + advice.getName() + "\"; " +
191       "}";
192       CtMethod getName = CtNewMethod.make(getNameTemplate.getReturnType(), "getName", getNameTemplate.getParameterTypes(), getNameTemplate.getExceptionTypes(), getNameBody, clazz);
193       getName.setModifiers(javassist.Modifier.PUBLIC);
194       clazz.addMethod(getName);
195
196       // invoke
197
String JavaDoc invokeBody = null;
198       if (Invocation.class.isAssignableFrom(advice.getParameterTypes()[0]))
199       {
200          invokeBody = getInvocationBody(optimized, advice, method);
201       }
202       else
203       {
204          invokeBody = getThreadStackBody(optimized, advice, method);
205       }
206       CtMethod invoke = CtNewMethod.make(invokeBody, clazz);
207       invoke.setModifiers(javassist.Modifier.PUBLIC);
208       clazz.addMethod(invoke);
209       Class JavaDoc iclass = TransformerCommon.toClass(clazz);
210
211       Interceptor rtn = (Interceptor) iclass.newInstance();
212       Field f = iclass.getField("aspectField");
213       f.set(rtn, aspect);
214       return rtn;
215    }
216
217    private static String JavaDoc getThreadStackBody(String JavaDoc optimized, Method advice, Method method)
218    {
219       String JavaDoc invokeBody =
220       "public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws java.lang.Throwable " +
221       "{ " +
222       " " + optimized + " optimized = (" + optimized + ")invocation; " +
223       " org.jboss.aop.joinpoint.CurrentInvocation.push(invocation); " +
224       " try {";
225       invokeBody += "return ($w)aspectField." + advice.getName() + "(";
226       Class JavaDoc[] adviceParams = advice.getParameterTypes();
227       Class JavaDoc[] params = method.getParameterTypes();
228       boolean first = true;
229       if (adviceParams.length > 0)
230       {
231          int adviceParam = 0;
232          for (int i = 0; i < params.length && adviceParam < adviceParams.length; i++)
233          {
234             if (adviceParams[adviceParam].equals(params[i]))
235             {
236                adviceParam++;
237                if (first)
238                {
239                   first = false;
240                }
241                else
242                {
243                   invokeBody += ", ";
244                }
245                invokeBody += "optimized.arg" + i;
246             }
247          }
248       }
249       invokeBody += "); ";
250       invokeBody +=
251       " } finally { org.jboss.aop.joinpoint.CurrentInvocation.pop(); }";
252       invokeBody +=
253       "}";
254       return invokeBody;
255    }
256
257    private static String JavaDoc getInvocationBody(String JavaDoc optimized, Method advice, Method method)
258    {
259       String JavaDoc invokeBody =
260       "public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws java.lang.Throwable " +
261       "{ " +
262       " " + optimized + " optimized = (" + optimized + ")invocation; " +
263       " return ($w)aspectField." + advice.getName() + "(optimized";
264       Class JavaDoc[] adviceParams = advice.getParameterTypes();
265       Class JavaDoc[] params = method.getParameterTypes();
266       if (adviceParams.length > 0)
267       {
268          int adviceParam = 1;
269          for (int i = 0; i < params.length && adviceParam < adviceParams.length; i++)
270          {
271             if (adviceParams[adviceParam].equals(params[i]))
272             {
273                adviceParam++;
274                invokeBody += ", ";
275                invokeBody += "optimized.arg" + i;
276             }
277          }
278       }
279       invokeBody += "); ";
280       invokeBody +=
281       "}";
282       return invokeBody;
283    }
284 }
285
Popular Tags