KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > aop > instrument > GeneratedAdvisorMethodExecutionTransformer


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.instrument;
23
24 import org.jboss.aop.ClassAdvisor;
25 import org.jboss.aop.util.JavassistMethodHashing;
26
27 import javassist.CannotCompileException;
28 import javassist.CtClass;
29 import javassist.CtField;
30 import javassist.CtMethod;
31 import javassist.CtNewMethod;
32 import javassist.Modifier;
33 import javassist.NotFoundException;
34
35 /**
36  * Used with GeneratedAdvisorInstrumentor
37  *
38  * @author <a HREF="mailto:kabir.khan@jboss.org">Kabir Khan</a>
39  * @version $Revision$
40  */

41 public class GeneratedAdvisorMethodExecutionTransformer extends
42       MethodExecutionTransformer
43 {
44    public GeneratedAdvisorMethodExecutionTransformer(GeneratedAdvisorInstrumentor instrumentor)
45    {
46       super(instrumentor);
47    }
48
49    private String JavaDoc addMethodInfoFieldToGenAdvisor(MethodTransformation trans)throws NotFoundException, CannotCompileException
50    {
51       GeneratedAdvisorInstrumentor instrumentor = (GeneratedAdvisorInstrumentor)trans.getInstrumentor();
52       CtClass genadvisor = instrumentor.getGenadvisor();
53       String JavaDoc miname = addMethodInfoField(
54             Modifier.PROTECTED,
55             genadvisor,
56             trans);
57
58       addJoinpoint(miname, trans);
59
60       instrumentor.initaliseMethodInfo(miname, trans.getHash(), JavassistMethodHashing.methodHash(trans.getMethod()));
61       return miname;
62    }
63
64    protected boolean addInfoAsWeakReference()
65    {
66       return false;
67    }
68
69    public static String JavaDoc getJoinPointFieldName(MethodTransformation trans)
70    {
71       return MethodJoinPointGenerator.getInfoFieldName(trans.getOriginalName(), trans.getHash());
72    }
73
74    public static String JavaDoc getJoinPointGeneratorFieldName(MethodTransformation trans)
75    {
76       return MethodJoinPointGenerator.getJoinPointGeneratorFieldName(trans.getOriginalName(), trans.getHash());
77    }
78
79    private void addJoinpoint(String JavaDoc miname, MethodTransformation trans)throws CannotCompileException, NotFoundException
80    {
81       CtClass joinpoint = createJoinpointClass(miname, trans);
82       CtClass genadvisor = ((GeneratedAdvisorInstrumentor)trans.getInstrumentor()).getGenadvisor();
83       CtField field = new CtField(
84             joinpoint,
85             getJoinPointFieldName(trans),
86             genadvisor);
87       field.setModifiers(Modifier.PROTECTED);
88       genadvisor.addField(field);
89    }
90
91    private CtClass createJoinpointClass(String JavaDoc miname, MethodTransformation trans) throws CannotCompileException, NotFoundException
92    {
93       return MethodJoinPointGenerator.createJoinpointBaseClass(
94             (GeneratedAdvisorInstrumentor)trans.getInstrumentor(),
95             trans.getClazz(),
96             trans.getMethod(),
97             miname,
98             trans.getOriginalName(),
99             trans.getWrappedName(),
100             trans.getHash());
101    }
102
103    public CtMethod addMixinWrappersAndInfo(
104          GeneratedAdvisorInstrumentor instrumentor,
105          CtClass clazz,
106          CtClass mixinClass,
107          String JavaDoc initializer,
108          CtClass genadvisor,
109          CtMethod mixinMethod) throws CannotCompileException, NotFoundException
110    {
111       String JavaDoc originalName = mixinMethod.getName();
112       String JavaDoc originalBody =
113          "{" +
114          " " + getReturnStr(mixinMethod) + " " + Instrumentor.mixinFieldName(mixinClass) + "." + mixinMethod.getName() + "($$);" +
115          "}";
116
117       CtMethod original = CtNewMethod.make(
118             Modifier.PUBLIC,
119             mixinMethod.getReturnType(),
120             mixinMethod.getName(),
121             mixinMethod.getParameterTypes(),
122             mixinMethod.getExceptionTypes(),
123             originalBody,
124             clazz);
125       clazz.addMethod(original);
126       long hash = JavassistMethodHashing.methodHash(original);
127       copyAnnotations(mixinMethod, original);
128
129       String JavaDoc wrappedName = ClassAdvisor.notAdvisedMethodName(clazz.getName(), originalName);
130       CtMethod wmethod = CtNewMethod.copy(original, clazz, null);
131
132       wmethod.setName(wrappedName);
133       clazz.addMethod(wmethod);
134       copyAnnotations(original, wmethod);
135
136       original.setName(wrappedName);
137       wmethod.setName(originalName);
138
139       MethodTransformation trans = new MethodTransformation(instrumentor, clazz, original, originalName, wmethod, wrappedName, hash);
140
141       String JavaDoc methodInfoField = addMethodInfoFieldToGenAdvisor(trans);
142       addMethodToGeneratedAdvisor(trans, methodInfoField);
143
144       String JavaDoc wrapperBody =
145          "{" +
146          " if (" + Instrumentor.mixinFieldName(mixinClass) + " == null)" +
147          " {" +
148          " " + Instrumentor.mixinFieldName(mixinClass) + " = " + initializer + ";" +
149          " }" +
150          " " + getReturnStr(trans.getMethod()) + " ((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(trans.getClazz()) + ")" + GeneratedAdvisorInstrumentor.GET_CURRENT_ADVISOR + ")." + getAdvisorMethodName(trans) + "(this,$$);" +
151          "}";
152       wmethod.setBody(wrapperBody);
153       return wmethod;
154    }
155
156    protected void transformMethod(MethodTransformation trans, boolean wrap)
157          throws CannotCompileException, NotFoundException
158    {
159       // generate Wrapper
160
String JavaDoc wrappedName = ClassAdvisor.notAdvisedMethodName(trans.getClazzName(),
161                                                              trans.getMethod().getName());
162       CtMethod wmethod = CtNewMethod.copy(trans.getMethod(), trans.getClazz(), null);
163
164       String JavaDoc originalName = trans.getOriginalName();
165       wmethod.setName(wrappedName);
166       trans.getClazz().addMethod(wmethod);
167       copyAnnotations(trans.getMethod(), wmethod);
168       trans.getMethod().setName(wrappedName);
169       wmethod.setName(originalName);
170
171       trans.setWMethod(wmethod, wrappedName);
172
173       String JavaDoc methodInfoField = addMethodInfoFieldToGenAdvisor(trans);
174       addMethodToGeneratedAdvisor(trans, methodInfoField);
175
176       // prepareForWrapping
177
getWrapper().prepareForWrapping(wmethod, WrapperTransformer.SINGLE_TRANSFORMATION_INDEX);
178
179
180       if (wrap)
181       {
182          // wrap
183
getWrapper().wrap(wmethod, WrapperTransformer.SINGLE_TRANSFORMATION_INDEX);
184
185          // executeWrapping
186
setWrapperBody(trans, methodInfoField);
187       }
188    }
189
190    protected void doWrap(MethodTransformation trans, String JavaDoc methodInfoFieldName) throws NotFoundException,
191          Exception JavaDoc
192    {
193       // TODO Auto-generated method stub
194

195    }
196
197    private void setWrapperBody(MethodTransformation trans, String JavaDoc methodInfoField) throws NotFoundException
198    {
199       String JavaDoc code = null;
200       final String JavaDoc className =
201          GeneratedAdvisorInstrumentor.getAdvisorFQN(trans.getClazz());
202
203       try
204       {
205          if (Modifier.isStatic(trans.getMethod().getModifiers()))
206          {
207             code =
208                "{" +
209                " " + getReturnStr(trans.getMethod()) + " ((" + className + ")" + Instrumentor.HELPER_FIELD_NAME + ")." + getAdvisorMethodName(trans) + "($$);" +
210                "}";
211             trans.setWMethodBody(code);
212          }
213          else
214          {
215             code =
216                "{" +
217                " " + getReturnStr(trans.getMethod()) + " ((" + className + ")" + GeneratedAdvisorInstrumentor.GET_CURRENT_ADVISOR + ")." + getAdvisorMethodName(trans) + "(this,$$);" +
218                "}";
219
220             trans.setWMethodBody(code);
221          }
222       }
223       catch (CannotCompileException e)
224       {
225          e.printStackTrace();
226          throw new RuntimeException JavaDoc("code was: " + code + " for method " + trans.getOriginalName());
227       }
228    }
229    
230    protected static CtClass[] addTargetToParamsForNonStaticMethod(CtClass outer, CtMethod method)throws NotFoundException
231    {
232       CtClass[] params = method.getParameterTypes();
233
234       if (!Modifier.isStatic(method.getModifiers()))
235       {
236          CtClass[] tempParams = params;
237          params = new CtClass[params.length + 1];
238          params[0] = outer;
239          System.arraycopy(tempParams, 0, params, 1, tempParams.length);
240       }
241
242       return params;
243    }
244
245    /**
246     * Generates the method name for the inner advisor class. It cannot have the same
247     * name/signature as the original in the outer class, or javassist gets
248     * confused (Jira: JASSIST-12)
249     *
250     */

251    private String JavaDoc getAdvisorMethodName(MethodTransformation trans)
252    {
253       if (trans.getHash() >= 0)
254       {
255          return trans.getOriginalName() + trans.getHash();
256       }
257       else
258       {
259          return trans.getOriginalName() + "_N_" + Math.abs(trans.getHash());
260       }
261    }
262
263    private void addMethodToGeneratedAdvisor(MethodTransformation trans, String JavaDoc methodInfoField)throws CannotCompileException, NotFoundException
264    {
265       CtClass genadvisor = ((GeneratedAdvisorInstrumentor)trans.getInstrumentor()).getGenadvisor();
266
267       CtClass[] params = addTargetToParamsForNonStaticMethod(trans.getClazz(), trans.getWMethod());
268
269       String JavaDoc code = createAdvisorMethodBody(trans, genadvisor/*kill*/);
270       try
271       {
272          CtMethod advisorMethod = CtNewMethod.make(
273                Modifier.PROTECTED,
274                trans.getWMethod().getReturnType(),
275                getAdvisorMethodName(trans),
276                params,
277                trans.getWMethod().getExceptionTypes(),
278                code,
279                genadvisor);
280
281          genadvisor.addMethod(advisorMethod);
282          advisorMethod.setModifiers(Modifier.setProtected(advisorMethod.getModifiers()));
283       }
284       catch (CannotCompileException e)
285       {
286          throw new RuntimeException JavaDoc("code was: " + code + " for method " + getAdvisorMethodName(trans), e);
287       }
288    }
289
290    private String JavaDoc createAdvisorMethodBody(MethodTransformation trans, CtClass ga/*kill*/)throws NotFoundException
291    {
292       if (Modifier.isStatic(trans.getWMethod().getModifiers()))
293       {
294          return createStaticAdvisorMethodBody(trans);
295       }
296       else
297       {
298          return createNonStaticAdvisorMethodBody(trans, ga);
299       }
300    }
301
302    private String JavaDoc createStaticAdvisorMethodBody(MethodTransformation trans)throws NotFoundException
303    {
304       String JavaDoc infoName = getJoinPointFieldName(trans);
305       String JavaDoc generatorName = getJoinPointGeneratorFieldName(trans);
306       String JavaDoc code =
307          "{" +
308          " if (" + infoName + " == null && " + generatorName + " != null)" +
309          " {" +
310          " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
311          " }" +
312          " if (" + infoName + " == null)" +
313          " { " +
314          " " + getReturnStr(trans.getWMethod()) + trans.getClazzName() + "." + trans.getWrappedName() +"($$);" +
315          " }" +
316          " else" +
317          " {" +
318          " " + getAopReturnStr(trans.getWMethod()) + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);" +
319          " }" +
320          "}";
321
322       return code;
323    }
324
325    private String JavaDoc createNonStaticAdvisorMethodBody(MethodTransformation trans, CtClass ga/*kill*/)throws NotFoundException
326    {
327       String JavaDoc infoName = getJoinPointFieldName(trans);
328       String JavaDoc generatorName = getJoinPointGeneratorFieldName(trans);
329       String JavaDoc code =
330          "{" +
331          " if (" + infoName + " == null && " + generatorName + " != null)" +
332          " {" +
333          " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
334          " }" +
335          " if (" + infoName + " == null)" +
336          " { " +
337          " " + getAopReturnStr(trans.getWMethod()) + "$1." + trans.getWrappedName() + "(" + getNonStaticJavasistParamString(trans.getWMethod().getParameterTypes().length) + ");" +
338          " }" +
339          " else" +
340          " {" +
341          " " + getAopReturnStr(trans.getWMethod()) + infoName + "." + MethodJoinPointGenerator.INVOKE_JOINPOINT + "($$);" +
342          " }" +
343          "}";
344
345       return code;
346    }
347
348    public static String JavaDoc getNonStaticJavasistParamString(long parameterLength)throws NotFoundException
349    {
350       StringBuffer JavaDoc str = new StringBuffer JavaDoc();
351
352       for (int i = 0 ; i < parameterLength ; i++)
353       {
354          if (i > 0)
355          {
356             str.append(", ");
357          }
358          str.append("$" + (i + 2));
359       }
360
361       return str.toString();
362    }
363 }
364
Popular Tags