KickJava   Java API By Example, From Geeks To Geeks.

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


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

42 public class GeneratedAdvisorCallerTransformer extends CallerTransformer
43 {
44    public GeneratedAdvisorCallerTransformer(Instrumentor instrumentor, AspectManager manager)
45    {
46       super(instrumentor, manager, true, new GeneratedAdvisorCallerInfoAdder(instrumentor));
47    }
48
49    private GeneratedAdvisorInstrumentor getInstrumentor()
50    {
51       return (GeneratedAdvisorInstrumentor)instrumentor;
52    }
53
54    private CtClass getGenadvisor()
55    {
56       return getInstrumentor().getGenadvisor();
57    }
58
59    protected CallerExprEditor callerExprEditorFactory(ClassAdvisor advisor, CtClass clazz)
60    {
61       return new GeneratedAdvisorCallerExprEditor(advisor, clazz);
62    }
63
64    class GeneratedAdvisorCallerExprEditor extends CallerExprEditor
65    {
66       public GeneratedAdvisorCallerExprEditor(ClassAdvisor advisor, CtClass callingClass)
67       {
68          super(advisor, callingClass);
69       }
70
71       protected void setupConstructor(ConstructorDetail cd)throws NotFoundException, CannotCompileException
72       {
73          if (callerInfos.get(cd.callerInfoField) == null)
74          {
75             callerInfos.put(cd.callerInfoField, NonOptimizedCallerTransformer.PLACEHOLDER);
76             callerInfoAdder.addMethodByConInfoField(getGenadvisor(), cd.callerInfoField, cd.callingIndex, cd.classname, cd.calledHash);
77             addJoinpoint(cd);
78             createGenAdvisorMethodByConMethod(cd);
79          }
80       }
81
82       private void addJoinpoint(ConstructorDetail cd)throws CannotCompileException, NotFoundException
83       {
84          CtClass joinpoint = createJoinpointClass(cd);
85          CtClass genadvisor = getInstrumentor().getGenadvisor();
86          CtField field = new CtField(
87                joinpoint,
88                MethodByConJoinPointGenerator.getInfoFieldName(cd.callingIndex, cd.classname, cd.calledHash),
89                genadvisor);
90          field.setModifiers(Modifier.PROTECTED);
91          genadvisor.addField(field);
92       }
93
94       private CtClass createJoinpointClass(ConstructorDetail cd) throws CannotCompileException, NotFoundException
95       {
96          return MethodByConJoinPointGenerator.createJoinpointBaseClass(
97                getInstrumentor(),
98                cd.callingIndex,
99                callingClass,
100                cd.calledMethod,
101                cd.classname,
102                cd.calledHash,
103                cd.callerInfoField);
104       }
105
106       private void createGenAdvisorMethodByConMethod(ConstructorDetail cd) throws NotFoundException, CannotCompileException
107       {
108          final boolean hasTargetObject = !Modifier.isStatic(cd.calledMethod.getModifiers());
109          final int originalLength = cd.calledMethod.getParameterTypes().length;
110          CtClass[] params = null;
111
112          if (hasTargetObject)
113          {
114             params = new CtClass[originalLength + 1];
115             params[0] = instrumentor.forName(cd.classname); //target object
116
System.arraycopy(cd.calledMethod.getParameterTypes(), 0, params, 1, originalLength);
117          }
118          else
119          {
120             params = cd.calledMethod.getParameterTypes();
121          }
122
123          String JavaDoc proceed = null;
124
125          if (hasTargetObject)
126          {
127             proceed = MethodExecutionTransformer.getAopReturnStr(cd.calledMethod) + "$1." + cd.calledMethod.getName() + "(" + getArguments(params.length, 1) +");";
128          }
129          else
130          {
131             proceed = MethodExecutionTransformer.getAopReturnStr(cd.calledMethod) + cd.classname + "." + cd.calledMethod.getName() + "($$);";
132          }
133
134          String JavaDoc infoName = MethodByConJoinPointGenerator.getInfoFieldName(cd.callingIndex, cd.classname, cd.calledHash);
135          String JavaDoc generatorName = MethodByConJoinPointGenerator.getJoinPointGeneratorFieldName(cd.callingIndex, cd.classname, cd.calledHash);
136          String JavaDoc code =
137                "{" +
138                " if (" + infoName + " == null && " + generatorName + " != null)" +
139                " {" +
140                " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
141                " }" +
142                " if (" + infoName + " == null)" +
143                " { " +
144                " " + proceed +
145                " }" +
146                " else" +
147                " {" +
148                " return " + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);" +
149                " }" +
150                "}";
151
152          try
153          {
154             CtMethod method = CtNewMethod.make(
155                   cd.calledMethod.getReturnType(),
156                   cd.callerInfoField,
157                   params,
158                   cd.calledMethod.getExceptionTypes(),
159                   code,
160                   getGenadvisor());
161             getGenadvisor().addMethod(method);
162          }
163          catch(CannotCompileException e)
164          {
165             System.out.println("Error for " + cd.callingIndex + " code:" + code);
166             throw e;
167          }
168       }
169
170
171       protected void setupMethod(MethodDetail md) throws NotFoundException, CannotCompileException
172       {
173          if (callerInfos.get(md.callerInfoField) == null)
174          {
175             callerInfos.put(md.callerInfoField, NonOptimizedCallerTransformer.PLACEHOLDER);
176             callerInfoAdder.addMethodByMethodInfoField(getGenadvisor(), md.callerInfoField, md.callingHash, md.classname, md.calledHash);
177             addJoinpoint(md);
178             createGenAdvisorMethodByMethodMethod(md);
179          }
180       }
181
182       private void addJoinpoint(MethodDetail md)throws CannotCompileException, NotFoundException
183       {
184          CtClass joinpoint = createJoinpointClass(md);
185          CtClass genadvisor = getInstrumentor().getGenadvisor();
186          CtField field = new CtField(
187                joinpoint,
188                MethodByMethodJoinPointGenerator.getInfoFieldName(md.callingHash, md.classname, md.calledHash),
189                genadvisor);
190          field.setModifiers(Modifier.PROTECTED);
191          genadvisor.addField(field);
192       }
193
194       private CtClass createJoinpointClass(MethodDetail md) throws CannotCompileException, NotFoundException
195       {
196          return MethodByMethodJoinPointGenerator.createJoinpointBaseClass(
197                getInstrumentor(),
198                md.callingHash,
199                !Modifier.isStatic(md.where.getModifiers()),
200                callingClass,
201                md.calledMethod,
202                md.classname,
203                md.calledHash,
204                md.callerInfoField);
205       }
206
207       private void createGenAdvisorMethodByMethodMethod(MethodDetail md) throws NotFoundException, CannotCompileException
208       {
209
210          final boolean hasCallingObject = !Modifier.isStatic(md.where.getModifiers());
211          final boolean hasTargetObject = !Modifier.isStatic(md.calledMethod.getModifiers());
212          final int originalLength = md.calledMethod.getParameterTypes().length;
213
214          int offset = 0;
215          if (hasTargetObject) offset++;
216          if (hasCallingObject) offset++;
217
218
219          CtClass[] params = new CtClass[originalLength + offset];
220          int index = 0;
221          if (hasTargetObject) params[index++] = instrumentor.forName(md.classname); //target
222
if (hasCallingObject) params[index++] = callingClass;
223
224          System.arraycopy(md.calledMethod.getParameterTypes(), 0, params, offset, originalLength);
225
226          String JavaDoc proceed = null;
227          if (hasTargetObject)
228          {
229             proceed = MethodExecutionTransformer.getAopReturnStr(md.calledMethod) + "$1." + md.calledMethod.getName() + "(" + getArguments(params.length, hasCallingObject ? 2 : 1) +");";
230          }
231          else
232          {
233             proceed = MethodExecutionTransformer.getAopReturnStr(md.calledMethod) + md.classname + "." + md.calledMethod.getName() + "(" + getArguments(params.length, hasCallingObject ? 1 : 0) +");";
234          }
235
236          String JavaDoc infoName = MethodByMethodJoinPointGenerator.getInfoFieldName(md.callingHash, md.classname, md.calledHash);
237          String JavaDoc generatorName = MethodByMethodJoinPointGenerator.getJoinPointGeneratorFieldName(md.callingHash, md.classname, md.calledHash);
238          String JavaDoc code =
239                "{" +
240                " if (" + infoName + " == null && " + generatorName + " != null)" +
241                " {" +
242                " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
243                " }" +
244                " if (" + infoName + " == null)" +
245                " { " +
246                " " + proceed +
247                " }" +
248                " else" +
249                " {" +
250                " " + MethodExecutionTransformer.getReturnStr(md.calledMethod) + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);" +
251                " }" +
252                "}";
253
254
255          try
256          {
257             CtMethod method = CtNewMethod.make(
258                   md.calledMethod.getReturnType(),
259                   md.callerInfoField,
260                   params,
261                   md.calledMethod.getExceptionTypes(),
262                   code,
263                   getGenadvisor());
264             getGenadvisor().addMethod(method);
265          }
266          catch(CannotCompileException e)
267          {
268             System.out.println("Error for " + md.where + " code:" + code);
269             throw e;
270          }
271       }
272
273       protected void setupMethod(ConByMethodDetail cd) throws NotFoundException, CannotCompileException
274       {
275          if (callerInfos.get(cd.callerInfoField) == null)
276          {
277             callerInfos.put(cd.callerInfoField, NonOptimizedCallerTransformer.PLACEHOLDER);
278             callerInfoAdder.addConByMethodInfoField(getGenadvisor(), cd.callerInfoField, cd.callingHash, cd.classname, cd.calledHash);
279             addJoinpoint(cd);
280             createGenAdvisorConByMethodMethod(cd);
281          }
282       }
283
284       private void addJoinpoint(ConByMethodDetail cd)throws CannotCompileException, NotFoundException
285       {
286          CtClass joinpoint = createJoinpointClass(cd);
287          CtClass genadvisor = getInstrumentor().getGenadvisor();
288          CtField field = new CtField(
289                joinpoint,
290                ConByMethodJoinPointGenerator.getInfoFieldName(cd.callingHash, cd.classname, cd.calledHash),
291                genadvisor);
292          field.setModifiers(Modifier.PROTECTED);
293          genadvisor.addField(field);
294       }
295
296       private CtClass createJoinpointClass(ConByMethodDetail cd) throws CannotCompileException, NotFoundException
297       {
298          return ConByMethodJoinPointGenerator.createJoinpointBaseClass(
299                getInstrumentor(),
300                cd.callingHash,
301                !Modifier.isStatic(cd.where.getModifiers()),
302                callingClass,
303                cd.calledConstructor,
304                cd.classname,
305                cd.calledHash,
306                cd.callerInfoField);
307       }
308
309       private void createGenAdvisorConByMethodMethod(ConByMethodDetail cd) throws NotFoundException, CannotCompileException
310       {
311          final boolean hasCallingObject = !Modifier.isStatic(cd.where.getModifiers());
312          final String JavaDoc info = cd.callerInfoField;
313
314          final int originalLength = cd.calledConstructor.getParameterTypes().length;
315          CtClass[] params = null;
316
317          if (hasCallingObject)
318          {
319             params = new CtClass[originalLength + 1];
320             params[0] = callingClass;
321             System.arraycopy(cd.calledConstructor.getParameterTypes(), 0, params, 1, originalLength);
322          }
323          else
324          {
325             params = cd.calledConstructor.getParameterTypes();
326          }
327
328          String JavaDoc infoName = ConByMethodJoinPointGenerator.getInfoFieldName(cd.callingHash, cd.classname, cd.calledHash);
329          String JavaDoc generatorName = ConByMethodJoinPointGenerator.getJoinPointGeneratorFieldName(cd.callingHash, cd.classname, cd.calledHash);
330          StringBuffer JavaDoc code = new StringBuffer JavaDoc();
331          code.append("{");
332          code.append(" if (" + infoName + " == null && " + generatorName + " != null)");
333          code.append(" {");
334          code.append(" " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();");
335          code.append(" }");
336          code.append(" if (" + infoName + " == null)");
337          code.append(" { ");
338          code.append(" return new " + cd.calledConstructor.getDeclaringClass().getName() + "(" + getArguments(params.length, hasCallingObject ? 1 : 0) + "); ");
339          code.append(" }");
340          code.append(" else");
341          code.append(" {");
342          code.append(" return " + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);");
343          code.append(" }");
344          code.append("}");
345
346          try
347          {
348             CtMethod method = CtNewMethod.make(
349                   cd.calledConstructor.getDeclaringClass(),
350                   info,
351                   params,
352                   cd.calledConstructor.getExceptionTypes(),
353                   code.toString(),
354                   getGenadvisor());
355             getGenadvisor().addMethod(method);
356          }
357          catch(CannotCompileException e)
358          {
359             System.out.println("Error for " + cd.where + ": code:" + code);
360             throw e;
361          }
362       }
363
364
365       protected void setupConstructor(ConByConDetail cd)throws NotFoundException, CannotCompileException
366       {
367          if (callerInfos.get(cd.callerInfoField) == null)
368          {
369             callerInfos.put(cd.callerInfoField, NonOptimizedCallerTransformer.PLACEHOLDER);
370             callerInfoAdder.addConByConInfoField(getGenadvisor(), cd.callerInfoField, cd.callingIndex, cd.classname, cd.calledHash);
371             addJoinpoint(cd);
372             createGenAdvisorConByConMethod(cd);
373          }
374       }
375
376       private void addJoinpoint(ConByConDetail cd)throws CannotCompileException, NotFoundException
377       {
378          CtClass joinpoint = createJoinpointClass(cd);
379          CtClass genadvisor = getInstrumentor().getGenadvisor();
380          CtField field = new CtField(
381                joinpoint,
382                ConByConJoinPointGenerator.getInfoFieldName(cd.callingIndex, cd.classname, cd.calledHash),
383                genadvisor);
384          field.setModifiers(Modifier.PROTECTED);
385          genadvisor.addField(field);
386       }
387
388       private CtClass createJoinpointClass(ConByConDetail cd) throws CannotCompileException, NotFoundException
389       {
390          return ConByConJoinPointGenerator.createJoinpointBaseClass(
391                getInstrumentor(),
392                cd.callingIndex,
393                callingClass,
394                cd.calledConstructor,
395                cd.classname,
396                cd.calledHash,
397                cd.callerInfoField);
398       }
399
400
401       private void createGenAdvisorConByConMethod(ConByConDetail cd)throws CannotCompileException, NotFoundException
402       {
403          String JavaDoc infoName = ConByConJoinPointGenerator.getInfoFieldName(cd.callingIndex, cd.classname, cd.calledHash);
404          String JavaDoc generatorName = ConByConJoinPointGenerator.getJoinPointGeneratorFieldName(cd.callingIndex, cd.classname, cd.calledHash);
405          String JavaDoc code =
406                "{" +
407                " if (" + infoName + " == null && " + generatorName + " != null)" +
408                " {" +
409                " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
410                " }" +
411                " if (" + infoName + " == null)" +
412                " { " +
413                " return new " + cd.calledConstructor.getDeclaringClass().getName() + "($$); " +
414                " }" +
415                " else" +
416                " {" +
417                " return " + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($$);" +
418                " }" +
419                "}";
420    
421          try
422          {
423             CtMethod method = CtNewMethod.make(
424                   cd.calledConstructor.getDeclaringClass(),
425                   cd.callerInfoField,
426                   cd.calledConstructor.getParameterTypes(),
427                   cd.calledConstructor.getExceptionTypes(),
428                   code,
429                   getGenadvisor());
430             getGenadvisor().addMethod(method);
431          }
432          catch(CannotCompileException e)
433          {
434             System.out.println("Error for " + cd.callingIndex + " code:" + code);
435             throw e;
436          }
437       }
438
439       protected void replaceMethodCallInCon(ConstructorDetail cd)throws CannotCompileException, NotFoundException
440       {
441          final String JavaDoc advisor = " ((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + Instrumentor.HELPER_FIELD_NAME + ")";
442          final int paramsLength = cd.calledMethod.getParameterTypes().length;
443          String JavaDoc args = null;
444          if (Modifier.isStatic(cd.calledMethod.getModifiers()))
445          {
446             args = (paramsLength > 0) ? "$$" : "";
447          }
448          else
449          {
450             args = "$0" + ((paramsLength > 0) ? ", $$" : "");
451          }
452
453          final String JavaDoc ret = (!cd.calledMethod.getReturnType().equals(CtClass.voidType)) ? "$_ = " : "";
454
455          String JavaDoc replaced = ret + advisor + "." + cd.callerInfoField + "(" + args + ");";
456
457          try
458          {
459             cd.call.replace(replaced);
460          }
461          catch(CannotCompileException e)
462          {
463             System.out.println("Error for " + cd.con + " code:" + replaced);
464             throw e;
465          }
466       }
467
468       protected void replaceMethodCallInMethod(MethodDetail md)throws NotFoundException, CannotCompileException
469       {
470          final boolean hasCallingObject = !Modifier.isStatic(md.where.getModifiers());
471          final boolean hasTargetObject = !Modifier.isStatic(md.calledMethod.getModifiers());
472          final int paramsLength = md.calledMethod.getParameterTypes().length;
473          String JavaDoc args = null;
474          if (hasCallingObject && hasTargetObject)
475          {
476             args = "$0, this" + ((paramsLength > 0 ) ? ", $$" : "");
477          }
478          else if (!hasCallingObject && hasTargetObject)
479          {
480             args = "$0" + ((paramsLength > 0 ) ? ", $$" : "");
481          }
482          else if (hasCallingObject && !hasTargetObject)
483          {
484             args = "this" + ((paramsLength > 0 ) ? ", $$" : "");
485          }
486          else
487          {
488             args = "$$";
489          }
490
491          String JavaDoc advisor;
492          if (hasCallingObject)
493          {
494             advisor = "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" +
495                GeneratedAdvisorInstrumentor.GET_CURRENT_ADVISOR + ")";
496          }
497          else
498          {
499             advisor = " ((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + Instrumentor.HELPER_FIELD_NAME + ")";
500          }
501          final String JavaDoc ret = (md.calledMethod.getReturnType().equals(CtClass.voidType)) ? "" : "$_ = ";
502
503          String JavaDoc replaced = ret + advisor + "." + md.callerInfoField + "(" + args + ");";
504
505          try
506          {
507             md.call.replace(replaced);
508          }
509          catch(CannotCompileException e)
510          {
511             System.out.println("Error for " + md.where + " code:" + replaced);
512             throw e;
513          }
514       }
515
516
517       protected void replaceConCallInMethod(ConByMethodDetail cd) throws NotFoundException, CannotCompileException
518       {
519          final int paramsLength = cd.calledConstructor.getParameterTypes().length;
520          String JavaDoc args = null;
521          String JavaDoc advisor = null;
522          if (!Modifier.isStatic(cd.where.getModifiers()))
523          {
524             args = "this" + ((paramsLength > 0) ? ", $$" : "");
525             advisor = "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" +
526                GeneratedAdvisorInstrumentor.GET_CURRENT_ADVISOR + ")";
527          }
528          else
529          {
530             args = ((paramsLength > 0) ? "$$" : "");
531             advisor = " ((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" + Instrumentor.HELPER_FIELD_NAME + ")";
532          }
533
534          String JavaDoc replaced = "$_ = " + advisor + "." + cd.callerInfoField + "(" + args + ");";
535
536          try
537          {
538             cd.call.replace(replaced);
539          }
540          catch(CannotCompileException e)
541          {
542             System.out.println("Error for " + cd.where + " code:" + replaced);
543             throw e;
544          }
545       }
546
547       protected void replaceConCallInCon(ConByConDetail cd)throws CannotCompileException, NotFoundException
548       {
549          String JavaDoc advisor = "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(callingClass) + ")" +
550                      Instrumentor.HELPER_FIELD_NAME + ")";
551
552          String JavaDoc replaced = "$_ = " + advisor + "." + cd.callerInfoField + "($$);";
553
554          try
555          {
556             cd.call.replace(replaced);
557          }
558          catch(CannotCompileException e)
559          {
560             System.out.println("Error for " + cd.callingIndex + " code:" + replaced);
561             throw e;
562          }
563       }
564    }
565
566
567    private String JavaDoc getArguments(int length, int offset)
568    {
569       StringBuffer JavaDoc sb = new StringBuffer JavaDoc("");
570       for (int i = 0 ; i < length - offset; i++)
571       {
572          if (i > 0)
573          {
574             sb.append(", ");
575          }
576          sb.append("$" + (i + 1 + offset));
577       }
578       return sb.toString();
579    }
580
581 }
582
Popular Tags