KickJava   Java API By Example, From Geeks To Geeks.

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


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 javassist.CannotCompileException;
25 import javassist.CtClass;
26 import javassist.CtConstructor;
27 import javassist.CtField;
28 import javassist.CtMethod;
29 import javassist.CtNewConstructor;
30 import javassist.CtNewMethod;
31 import javassist.Modifier;
32 import javassist.NotFoundException;
33
34 import org.jboss.aop.AspectManager;
35 import org.jboss.aop.ClassAdvisor;
36 import org.jboss.aop.ConByMethodInfo;
37 import org.jboss.aop.FieldInfo;
38 import org.jboss.aop.GeneratedClassAdvisor;
39 import org.jboss.aop.JoinPointInfo;
40 import org.jboss.aop.MethodByMethodInfo;
41 import org.jboss.aop.MethodInfo;
42 import org.jboss.aop.classpool.AOPClassPool;
43
44 /**
45  * Comment
46  *
47  * @author <a HREF="mailto:kabir.khan@jboss.org">Kabir Khan</a>
48  * @version $Revision$
49  */

50 public class GeneratedAdvisorInstrumentor extends Instrumentor
51 {
52    //field names in advised class
53
private static final String JavaDoc CURRENT_ADVISOR = "currentAdvisor$aop";
54    private static final String JavaDoc INSTANCE_ADVISOR = "instanceAdvisor$aop";
55    private static final String JavaDoc GET_CURRENT_ADVISOR_NAME = "getCurrentAdvisor$aop";
56    public static final String JavaDoc GET_CURRENT_ADVISOR = GET_CURRENT_ADVISOR_NAME + "()";
57
58    //field names in advisor
59
// private static final String ADVISED_CLASS = "advisedClass";
60
private static final String JavaDoc DOMAIN = "domain";
61    private static final String JavaDoc VERSION = "version";
62    private static final String JavaDoc CHECK_VERSION = "checkVersion";
63    private static final String JavaDoc ADVICES_UPDATED = "advicesUpdated";
64    private static final String JavaDoc INSTANCE_ADVISOR_MIXIN = "instanceAdvisorMixin";
65
66    //method names in advisor or GeneratedClassAdvisor
67
private static final String JavaDoc CREATE_INSTANCE_ADVISOR = "createInstanceAdvisor";
68    private static final String JavaDoc INITIALISE_CALLERS = "initialiseCallers";
69    private static final String JavaDoc INITIALISE_FIELD_WRITES = "initialiseFieldWrites";
70    private static final String JavaDoc INITIALISE_FIELD_READS = "initialiseFieldReads";
71    private static final String JavaDoc INITIALISE_CONSTRUCTIONS = "initialiseConstructions";
72    private static final String JavaDoc INITIALISE_CONSTRUCTORS = "initialiseConstructors";
73    private static final String JavaDoc INITIALISE_METHODS = "initialiseMethods";
74    public static final String JavaDoc GET_CLASS_ADVISOR = "_getClassAdvisor";
75
76    private static final String JavaDoc DECLARING_CLASS = "this.getClass().getDeclaringClass()";
77    private static final String JavaDoc CONTAINER_CLASS = "this.getClass().getDeclaringClass()";
78
79
80    private static final CtClass[] EMPTY_EXCEPTIONS = new CtClass[0];
81    private static final CtClass[] EMPTY_SIG = new CtClass[0];
82
83    CtClass clazz;
84    CtClass genadvisor;
85    CtClass genInstanceAdvisor;
86
87
88    public GeneratedAdvisorInstrumentor(AOPClassPool pool, AspectManager manager, JoinpointClassifier joinpointClassifier, DynamicTransformationObserver observer)
89    {
90       super(pool, manager, joinpointClassifier, observer);
91    }
92
93    public GeneratedAdvisorInstrumentor(AspectManager manager, JoinpointClassifier joinpointClassifier)
94    {
95       super(manager, joinpointClassifier);
96    }
97
98    protected CtClass getGenadvisor()
99    {
100       return genadvisor;
101    }
102
103    protected CtClass getGenInstanceadvisor()
104    {
105       return genInstanceAdvisor;
106    }
107
108    public boolean transform(CtClass clazz, ClassAdvisor advisor)
109    {
110       try
111       {
112          this.clazz = clazz;
113          super.transform(clazz, advisor);
114
115          if (genadvisor != null)
116          {
117             addInstanceAdvisorWrappers(clazz);
118             TransformerCommon.compileOrLoadClass(clazz, genadvisor);
119             TransformerCommon.compileOrLoadClass(clazz, genInstanceAdvisor);
120          }
121          return true;
122       }
123       catch (Throwable JavaDoc e)
124       {
125          if (AspectManager.suppressTransformationErrors)
126          {
127             System.err.println("[warn] AOP Instrumentor failed to transform " + clazz.getName());
128             e.printStackTrace();
129             return false;
130          }
131          else
132          {
133             if (e instanceof TransformationException)
134             {
135                throw ((TransformationException) e);
136             }
137             else
138             {
139                e.printStackTrace();
140                throw new RuntimeException JavaDoc("failed to transform: " + clazz.getName(), e);
141             }
142          }
143
144       }
145    }
146
147    protected void intitialiseTransformers()
148    {
149       callerTransformer = new GeneratedAdvisorCallerTransformer(this, manager);
150       fieldAccessTransformer = new GeneratedAdvisorFieldAccessTransformer(this);
151       constructorExecutionTransformer = new GeneratedAdvisorConstructorExecutionTransformer(this);
152       constructionTransformer = new GeneratedAdvisorConstructionTransformer(this);
153       methodExecutionTransformer = new GeneratedAdvisorMethodExecutionTransformer(this);
154    }
155
156    protected CtMethod createMixinInvokeMethod(CtClass clazz, CtClass mixinClass, String JavaDoc initializer, CtMethod method, long hash)
157    throws CannotCompileException, NotFoundException, Exception JavaDoc
158    {
159       return ((GeneratedAdvisorMethodExecutionTransformer)methodExecutionTransformer).addMixinWrappersAndInfo(this, clazz, mixinClass, initializer, genadvisor, method);
160    }
161
162    protected static String JavaDoc getAdvisorName(CtClass clazz)
163    {
164       //Strip away the package from classname
165
String JavaDoc className = clazz.getName();
166       return className.substring(className.lastIndexOf('.') + 1) + "Advisor";
167    }
168
169    protected static String JavaDoc getInstanceAdvisorName(CtClass clazz)
170    {
171       //Strip away the package from classname
172
String JavaDoc className = clazz.getName();
173       return className.substring(className.lastIndexOf('.') + 1) + "InstanceAdvisor";
174    }
175
176    protected static String JavaDoc getAdvisorFQN(CtClass clazz)
177    {
178       return clazz.getName() + "$" + getAdvisorName(clazz);
179    }
180
181    protected static String JavaDoc getInstanceAdvisorFQN(CtClass clazz)
182    {
183       return clazz.getName() + "$" + getInstanceAdvisorName(clazz);
184    }
185
186    protected CtClass createAdvisorClass(CtClass clazz) throws NotFoundException, CannotCompileException
187    {
188       String JavaDoc innerClassName = getAdvisorName(clazz);
189
190       //Only static nested classes are supported
191
final boolean classStatic = true;
192       genadvisor = TransformerCommon.makeNestedClass(clazz, innerClassName, classStatic);
193       //The advisor needs to be public in case children are in a child/scoped ucl
194
//genadvisor.setModifiers(Modifier.setPublic(genadvisor.getModifiers()));
195

196       //Make super class Advisor
197
final CtClass superAdvisor = getSuperClassAdvisor(clazz.getSuperclass());
198       if (superAdvisor == null)
199       {
200          genadvisor.setSuperclass(forName(GeneratedClassAdvisor.class.getName()));
201       }
202       else
203       {
204          genadvisor.setSuperclass(superAdvisor);
205       }
206
207       //Make Untransformable
208
final CtClass untransformable = getClassPool().get("org.jboss.aop.instrument.Untransformable");
209       genadvisor.addInterface(untransformable);
210
211       //Add version field
212
CtField version = new CtField(CtClass.intType, VERSION, genadvisor);
213       genadvisor.addField(version);
214
215       //Add domain
216
CtField domain = new CtField(forName("org.jboss.aop.Domain"), DOMAIN, genadvisor);
217       domain.setModifiers(Modifier.PROTECTED);
218       genadvisor.addField(domain);
219       CtMethod getter = CtNewMethod.getter("getDomain", domain);
220       genadvisor.addMethod(getter);
221
222       if (isBaseClass(clazz))
223       {
224          CtMethod rebuildInterceptors = CtNewMethod.make(
225                Modifier.PROTECTED,
226                CtClass.voidType,
227                "rebuildInterceptors",
228                EMPTY_SIG,
229                EMPTY_EXCEPTIONS,
230                "{" + VERSION + "++;super.rebuildInterceptors();}",
231                genadvisor);
232          genadvisor.addMethod(rebuildInterceptors);
233
234          //Will be called by instance advisors when version ids are out of sync
235
CtMethod internalRebuildInterceptors = CtNewMethod.make(
236                Modifier.PROTECTED,
237                CtClass.voidType,
238                "internalRebuildInterceptors",
239                EMPTY_SIG,
240                EMPTY_EXCEPTIONS,
241                "{super.rebuildInterceptors();}",
242                genadvisor);
243          genadvisor.addMethod(internalRebuildInterceptors);
244       }
245
246       CtMethod initialiseMethods = CtNewMethod.make(
247             Modifier.PROTECTED,
248             CtClass.voidType,
249             INITIALISE_METHODS,
250             EMPTY_SIG,
251             EMPTY_EXCEPTIONS,
252             (isBaseClass(clazz)) ?
253                   null : "{super." + INITIALISE_METHODS + "();}",
254             genadvisor);
255       genadvisor.addMethod(initialiseMethods);
256
257       CtMethod initialiseConstructors = CtNewMethod.make(
258             Modifier.PROTECTED,
259             CtClass.voidType,
260             INITIALISE_CONSTRUCTORS,
261             EMPTY_SIG,
262             EMPTY_EXCEPTIONS,
263             null,
264             genadvisor);
265       genadvisor.addMethod(initialiseConstructors);
266
267       CtMethod initialiseConstructions = CtNewMethod.make(
268             Modifier.PROTECTED,
269             CtClass.voidType,
270             INITIALISE_CONSTRUCTIONS,
271             EMPTY_SIG,
272             EMPTY_EXCEPTIONS,
273             (isBaseClass(clazz)) ?
274                   null : "{super." + INITIALISE_CONSTRUCTIONS + "();}",
275             genadvisor);
276       genadvisor.addMethod(initialiseConstructions);
277
278       CtMethod initialiseFieldReads = CtNewMethod.make(
279             Modifier.PROTECTED,
280             CtClass.voidType,
281             INITIALISE_FIELD_READS,
282             EMPTY_SIG,
283             EMPTY_EXCEPTIONS,
284             (isBaseClass(clazz)) ?
285                   null : "{super." + INITIALISE_FIELD_READS + "();}",
286             genadvisor);
287       genadvisor.addMethod(initialiseFieldReads);
288
289       CtMethod initialiseFieldWrites = CtNewMethod.make(
290             Modifier.PROTECTED,
291             CtClass.voidType,
292             INITIALISE_FIELD_WRITES,
293             EMPTY_SIG,
294             EMPTY_EXCEPTIONS,
295             (isBaseClass(clazz)) ?
296                   null : "{super." + INITIALISE_FIELD_WRITES + "();}",
297             genadvisor);
298       genadvisor.addMethod(initialiseFieldWrites);
299
300       CtMethod initialiseCallers = CtNewMethod.make(
301             Modifier.PROTECTED,
302             CtClass.voidType,
303             INITIALISE_CALLERS,
304             EMPTY_SIG,
305             EMPTY_EXCEPTIONS,
306             null, //"{" + GeneratedClassAdvisor.CLEAR_CALLERS + "();}",
307
genadvisor);
308       genadvisor.addMethod(initialiseCallers);
309
310       createAdvisorCtors(clazz);
311
312       return genadvisor;
313    }
314
315    protected CtClass createInstanceAdvisorClass(CtClass clazz) throws NotFoundException, CannotCompileException
316    {
317       String JavaDoc innerClassName = getInstanceAdvisorName(clazz);
318
319       //Only static nested classes are supported
320
final boolean classStatic = true;
321       genInstanceAdvisor = TransformerCommon.makeNestedClass(clazz, innerClassName, classStatic);
322       //The advisor needs to be public in case children are in a child/scoped ucl
323
genInstanceAdvisor.setModifiers(Modifier.setPublic(genInstanceAdvisor.getModifiers()));
324
325       //Make super class Advisor
326
genInstanceAdvisor.setSuperclass(getGenadvisor());
327
328       //Make Untransformable
329
final CtClass untransformable = getClassPool().get("org.jboss.aop.instrument.Untransformable");
330       genInstanceAdvisor.addInterface(untransformable);
331
332       //Add reference to parent advisor
333
CtField classAdvisor = new CtField(genadvisor, "classAdvisor", genInstanceAdvisor);
334       genInstanceAdvisor.addField(classAdvisor);
335
336       CtMethod advicesUpdated = CtNewMethod.make(
337             Modifier.PROTECTED,
338             CtClass.voidType,
339             ADVICES_UPDATED,
340             EMPTY_SIG,
341             EMPTY_EXCEPTIONS,
342             null,
343             genInstanceAdvisor);
344       genInstanceAdvisor.addMethod(advicesUpdated);
345
346       implementInstanceAdvisorMethods();
347
348       String JavaDoc cvBody =
349          "{" +
350          " if (classAdvisor." + VERSION + " != super." + VERSION + ") " +
351          " { " +
352          " super." + VERSION + " = classAdvisor." + VERSION +";" +
353          " internalRebuildInterceptors(); " +
354          " if (" + INSTANCE_ADVISOR_MIXIN + ".hasInterceptors())" +
355          " {" +
356          " " + ADVICES_UPDATED + "();" +
357          " }" +
358          " } " +
359          "}";
360       CtMethod checkVersion = CtNewMethod.make(
361             Modifier.PROTECTED,
362             CtClass.voidType,
363             CHECK_VERSION,
364             EMPTY_SIG,
365             EMPTY_EXCEPTIONS,
366             cvBody,
367             genInstanceAdvisor);
368       genInstanceAdvisor.addMethod(checkVersion);
369
370       String JavaDoc body =
371          "{" +
372          " super($2);" +
373          " " + INSTANCE_ADVISOR_MIXIN + " = new org.jboss.aop.GeneratedInstanceAdvisorMixin($1, $2);" +
374          " this.classAdvisor = $2;" +
375          " super." + VERSION + " = classAdvisor." + VERSION + ";" +
376          "}";
377       CtConstructor ctor = CtNewConstructor.make(new CtClass[]{forName("java.lang.Object"), genadvisor}, new CtClass[0], body, genInstanceAdvisor);
378       genInstanceAdvisor.addConstructor(ctor);
379
380       return genInstanceAdvisor;
381    }
382
383    protected void createAdvisorCtors(CtClass clazz)throws CannotCompileException, NotFoundException
384    {
385       String JavaDoc initBody =
386          "{" +
387          " " + DOMAIN + "= new org.jboss.aop.GeneratedAdvisorDomain($1, " + DECLARING_CLASS + ", false); " +
388          " ((org.jboss.aop.Domain)" + DOMAIN + ").setInheritsBindings(true); " +
389          " " + INITIALISE_METHODS + "();" +
390          " " + INITIALISE_CONSTRUCTORS + "();" +
391          " " + INITIALISE_CONSTRUCTIONS + "();" +
392          " " + INITIALISE_FIELD_READS + "();" +
393          " " + INITIALISE_FIELD_WRITES + "();" +
394          " super.initialise(" + DECLARING_CLASS + ", " + DOMAIN + ");" +
395          " " + INITIALISE_CALLERS + "();" +
396          "}";
397
398          CtMethod initialise = CtNewMethod.make(
399             Modifier.PROTECTED,
400             CtClass.voidType,
401             "initialise",
402             new CtClass[]{forName("org.jboss.aop.AspectManager")},
403             EMPTY_EXCEPTIONS,
404             initBody,
405             genadvisor);
406       genadvisor.addMethod(initialise);
407
408
409       //This will be called when a class instantiates its advisor
410
CtConstructor ctor = CtNewConstructor.defaultConstructor(genadvisor);
411       ctor.setBody(
412             "{" +
413             " super(\"" + clazz.getName() + "\"); " +
414             " initialise(org.jboss.aop.AspectManager.instance(this.getClass().getClassLoader()));" + //Use the CL of the class, since we may be in a scoped loader
415
"}");
416       genadvisor.addConstructor(ctor);
417
418       //This is called by instance advisors
419
String JavaDoc instanceBody =
420          "{" +
421          " super(\"" + clazz.getName() + "\"); " +
422          " super.setParentAdvisor($1);" +
423          " initialise($1.getDomain());" +
424          "}";
425       CtConstructor ctorWithParentAdvisor = CtNewConstructor.make(new CtClass[]{genadvisor}, EMPTY_EXCEPTIONS, instanceBody, genadvisor);
426       genadvisor.addConstructor(ctorWithParentAdvisor);
427
428
429       //This will be called by sub advisors
430
CtConstructor ctorForSubAdvisors = CtNewConstructor.make(new CtClass[]{forName("java.lang.String")}, new CtClass[0], "{super($1);}", genadvisor);
431       genadvisor.addConstructor(ctorForSubAdvisors);
432       ctorForSubAdvisors.setModifiers(Modifier.PROTECTED);
433    }
434
435    protected CtClass getSuperClassAdvisor(CtClass superclass)throws NotFoundException
436    {
437       if (superclass != null)
438       {
439          try
440          {
441             if (isAdvised(superclass))
442             {
443                return forName(superclass.getClassPool(), getAdvisorFQN(superclass));
444             }
445          }
446          catch (NotFoundException e)
447          {
448          }
449
450          return getSuperClassAdvisor(superclass.getSuperclass());
451       }
452       return null;
453
454    }
455
456    protected void implementInstanceAdvisorMethods() throws NotFoundException, CannotCompileException
457    {
458       final CtClass instanceAdvisor = getClassPool().get("org.jboss.aop.InstanceAdvisor");
459       genInstanceAdvisor.addInterface(instanceAdvisor);
460
461       CtField instanceAdvisorMixin = new CtField(
462             getClassPool().get("org.jboss.aop.GeneratedInstanceAdvisorMixin"),
463             INSTANCE_ADVISOR_MIXIN,
464             genInstanceAdvisor);
465       genInstanceAdvisor.addField(instanceAdvisorMixin);
466
467       CtMethod[] instanceAdvisorMethods = instanceAdvisor.getDeclaredMethods();
468       for (int i = 0 ; i < instanceAdvisorMethods.length ; i++)
469       {
470          final String JavaDoc name = instanceAdvisorMethods[i].getName();
471          if (name.equals("hasAspects"))
472          {
473             //hasAspects is declared final in Advisor, which we inherit from so we cannot override that
474
continue;
475          }
476          else if (name.equals("getDomain"))
477          {
478             //We've already implemented this method and don't want to delgate this to the mixin
479
continue;
480          }
481
482          String JavaDoc ret = (instanceAdvisorMethods[i].getReturnType().equals(CtClass.voidType)) ? "" : "return ";
483          StringBuffer JavaDoc delegatingBody = new StringBuffer JavaDoc();
484          delegatingBody.append("{");
485          if (name.startsWith("insertInterceptor") || name.startsWith("removeInterceptor") || name.startsWith("appendInterceptor"))
486          {
487             delegatingBody.append(ADVICES_UPDATED + "();");
488          }
489          if (!instanceAdvisorMethods[i].getReturnType().equals(CtClass.voidType))
490          {
491             delegatingBody.append("return ");
492          }
493          delegatingBody.append(INSTANCE_ADVISOR_MIXIN + "." + instanceAdvisorMethods[i].getName() + "($$);}");
494
495          CtMethod m = CtNewMethod.make(
496                Modifier.PUBLIC,
497                instanceAdvisorMethods[i].getReturnType(),
498                instanceAdvisorMethods[i].getName(),
499                instanceAdvisorMethods[i].getParameterTypes(),
500                instanceAdvisorMethods[i].getExceptionTypes(),
501                delegatingBody.toString(),
502                genInstanceAdvisor);
503          genInstanceAdvisor.addMethod(m);
504       }
505    }
506
507    private void addCreateInstanceAdvisorToGenAdvisor(CtClass clazz) throws NotFoundException, CannotCompileException
508    {
509       CtMethod createInstanceAdvisor = CtNewMethod.make(
510             Modifier.PUBLIC,
511             forName("org.jboss.aop.Advisor"),
512             CREATE_INSTANCE_ADVISOR,
513             new CtClass[]{forName("java.lang.Object")},
514             EMPTY_EXCEPTIONS,
515             "{return new " + getInstanceAdvisorFQN(clazz) + "($1, this);}",
516             genadvisor);
517       genadvisor.addMethod(createInstanceAdvisor);
518    }
519
520    protected void doSetupBasics(CtClass clazz) throws CannotCompileException, NotFoundException
521    {
522       createAdvisorClass(clazz);
523       createInstanceAdvisorClass(clazz);
524       addCreateInstanceAdvisorToGenAdvisor(clazz);
525       createAdvisorFieldsAndGetter(clazz);
526    }
527
528    private void createAdvisorFieldsAndGetter(CtClass clazz)throws NotFoundException, CannotCompileException
529    {
530       CtField classAdvisor = new CtField(
531             forName("org.jboss.aop.Advisor"),
532             Instrumentor.HELPER_FIELD_NAME,
533             clazz);
534       classAdvisor.setModifiers(Modifier.PRIVATE | Modifier.STATIC | Modifier.TRANSIENT);
535       clazz.addField(classAdvisor, CtField.Initializer.byExpr("new " + getAdvisorFQN(clazz) + "()"));
536 // clazz.addField(classAdvisor, CtField.Initializer.byExpr("this.getClass().getClassLoader().loadClass(" + getAdvisorFQN(clazz) + ").newInstance()"));
537

538       CtMethod getAdvisor = CtNewMethod.getter("_getAdvisor", classAdvisor);
539       getAdvisor.setModifiers(Modifier.PUBLIC);
540       clazz.addMethod(getAdvisor);
541
542       CtMethod getClassAdvisor = CtNewMethod.getter(GET_CLASS_ADVISOR, classAdvisor);
543       getClassAdvisor.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
544       clazz.addMethod(getClassAdvisor);
545
546       if (isBaseClass(clazz))
547       {
548          CtField currentAdvisor = new CtField(
549             forName("org.jboss.aop.Advisor"),
550             CURRENT_ADVISOR,
551             clazz);
552          currentAdvisor.setModifiers(Modifier.VOLATILE | Modifier.PROTECTED | Modifier.TRANSIENT);
553          clazz.addField(currentAdvisor, CtField.Initializer.byExpr("_getAdvisor()"));
554
555          String JavaDoc body =
556             "{" +
557             " if (" + CURRENT_ADVISOR + " == null)" +
558             " {" +
559             " " + CURRENT_ADVISOR + " = _getAdvisor();" +
560             " }" +
561             " return " + CURRENT_ADVISOR + ";"+
562             "}";
563          CtMethod getCurrentAdvisor = CtNewMethod.make(
564                Modifier.PROTECTED,
565                forName("org.jboss.aop.Advisor"),
566                GET_CURRENT_ADVISOR_NAME,
567                EMPTY_SIG,
568                EMPTY_EXCEPTIONS,
569                body,
570                clazz);
571          clazz.addMethod(getCurrentAdvisor);
572
573          CtField instanceAdvisor = new CtField(
574                forName("org.jboss.aop.InstanceAdvisor"),
575                INSTANCE_ADVISOR,
576                clazz);
577          instanceAdvisor.setModifiers(Modifier.PROTECTED | Modifier.TRANSIENT);
578          clazz.addField(instanceAdvisor);
579       }
580
581       //Add _getInstanceAdvisor() method
582
String JavaDoc body =
583          "{ " +
584          " if (" + INSTANCE_ADVISOR + " == null) " +
585          " { " +
586          " synchronized(this) " +
587          " { " +
588          " if (" + INSTANCE_ADVISOR + " == null) " +
589          " { " +
590          " org.jboss.aop.Advisor advisor = ((" + getAdvisorFQN(clazz) + ")" + Instrumentor.HELPER_FIELD_NAME + ").createInstanceAdvisor(this); " +
591          " " + CURRENT_ADVISOR + " = advisor; " +
592          " " + INSTANCE_ADVISOR + " = (org.jboss.aop.InstanceAdvisor)advisor; " +
593          " } " +
594          " } " +
595          " } " +
596          " return " + INSTANCE_ADVISOR +";" +
597          "}";
598       CtMethod getInstanceAdvisor = CtNewMethod.make(
599             forName("org.jboss.aop.InstanceAdvisor"),
600             "_getInstanceAdvisor",
601             new CtClass[0],
602             new CtClass[0],
603             body,
604             clazz);
605       clazz.addMethod(getInstanceAdvisor);
606    }
607
608    public static String JavaDoc updatedAdvicesName(String JavaDoc infoName)
609    {
610       return infoName + "_updated";
611    }
612
613
614    /** Make sure that instance advisors have wrappers for all super advisors
615     */

616    private void addInstanceAdvisorWrappers(CtClass clazz)throws CannotCompileException, NotFoundException
617    {
618       CtClass superClass = clazz;
619       CtClass superAdvisor = genadvisor;
620       boolean isSuper = false;
621
622       StringBuffer JavaDoc advicesUpdatedCode = new StringBuffer JavaDoc();
623
624       while (true)
625       {
626          CtField[] fields = superAdvisor.getDeclaredFields();
627
628          for (int i = 0 ; i < fields.length ; i++)
629          {
630             if (Modifier.isStatic(fields[i].getModifiers())) continue;
631
632             GeneratedAdvisorNameExtractor names = GeneratedAdvisorNameExtractor.extractNames(superAdvisor, fields[i]);
633             if (names == null) continue;
634
635             //Add marker to keep track of if advice has interceptors appended
636
String JavaDoc infoName = fields[i].getName();
637             String JavaDoc updatedJoinpointAdvicesName = addAdvicesUpdatedForJoinpointField(infoName);
638             advicesUpdatedCode.append(updatedJoinpointAdvicesName + " = true;");
639             addWrapperDelegatorMethodToInstanceAdvisor(names, updatedJoinpointAdvicesName);
640          }
641
642          if (isBaseClass(superClass))
643          {
644             break;
645          }
646
647          isSuper = true;
648          superClass = superClass.getSuperclass();
649          superAdvisor = superAdvisor.getSuperclass();
650       }
651
652       CtMethod advicesUpdated = genInstanceAdvisor.getDeclaredMethod(ADVICES_UPDATED);
653       advicesUpdated.insertAfter(advicesUpdatedCode.toString());
654    }
655
656    private String JavaDoc addAdvicesUpdatedForJoinpointField(String JavaDoc infoName) throws NotFoundException, CannotCompileException
657    {
658       String JavaDoc updatedAdvicesName = updatedAdvicesName(infoName);
659       try
660       {
661          genInstanceAdvisor.getDeclaredField(updatedAdvicesName);
662       }
663       catch(NotFoundException e)
664       {
665          //Field did not exist - add it
666
CtField updatedAdvice = new CtField(CtClass.booleanType, updatedAdvicesName, genInstanceAdvisor);
667          updatedAdvice.setModifiers(Modifier.PROTECTED);
668          genInstanceAdvisor.addField(updatedAdvice);
669       }
670
671       return updatedAdvicesName;
672    }
673
674    private void addWrapperDelegatorMethodToInstanceAdvisor(GeneratedAdvisorNameExtractor names, String JavaDoc updatedAdvicesFieldName) throws NotFoundException, CannotCompileException
675    {
676       try
677       {
678          genInstanceAdvisor.getDeclaredMethod(names.getWrapper().getName());
679       }
680       catch(NotFoundException e)
681       {
682          //Method did not exist - add it
683
CtMethod instanceAdvisorMethod = CtNewMethod.delegator(names.getWrapper(), genInstanceAdvisor);
684          String JavaDoc code =
685             CHECK_VERSION + "();" +
686             "if (" + updatedAdvicesFieldName + ")" +
687             "{ " +
688             " " + JoinPointInfo.class.getName() + " copy = " + names.getInfoFieldName() + ".copy();" +
689             " copy.setInterceptors( " + INSTANCE_ADVISOR_MIXIN + ".getWrappers(copy.getInterceptors()) );" +
690             " " + updatedAdvicesFieldName + " = false;" +
691             " " + names.getJoinPointField().getName() + " = null;" +
692             " if (" + names.getGeneratorField().getName() + " == null)" +
693             " {" +
694             " " + names.getGeneratorField().getName() + " = super.getJoinPointGenerator(" + names.getInfoFieldName() + ");" +
695             " }" +
696             " " + names.getGeneratorField().getName() + ".rebindJoinpoint(copy);" +
697             "}";
698
699          instanceAdvisorMethod.insertBefore(code);
700          genInstanceAdvisor.addMethod(instanceAdvisorMethod);
701       }
702    }
703
704    boolean initialisedMethods = false;
705    protected void initaliseMethodInfo(String JavaDoc infoName, long hash, long unadvisedHash)throws NotFoundException
706    {
707       String JavaDoc code =
708          infoName + " = new " + MethodExecutionTransformer.METHOD_INFO_CLASS_NAME + "(" +
709                "java.lang.Class.forName(\"" + clazz.getName() + "\")," +
710                hash + "L, " +
711                unadvisedHash + "L, this);" +
712          GeneratedClassAdvisor.ADD_METHOD_INFO + "(" + infoName + ");";
713
714       addCodeToInitialiseMethod(code, INITIALISE_METHODS);
715    }
716
717    protected void initialiseFieldReadInfoField(String JavaDoc infoName, int index, String JavaDoc fieldName, long wrapperHash) throws NotFoundException
718    {
719       String JavaDoc code =
720          infoName + " = new " + FieldAccessTransformer.FIELD_INFO_CLASS_NAME + "(" +
721             "java.lang.Class.forName(\"" + clazz.getName() + "\")," +
722             index + ", " +
723             "\"" + fieldName + "\", " +
724             wrapperHash + "L, this, true);" +
725          GeneratedClassAdvisor.ADD_FIELD_READ_INFO + "(" + infoName + ");";
726
727       addCodeToInitialiseMethod(code, INITIALISE_FIELD_READS);
728    }
729
730    protected void initialiseFieldWriteInfoField(String JavaDoc infoName, int index, String JavaDoc fieldName, long wrapperHash) throws NotFoundException
731    {
732       String JavaDoc code =
733          infoName + " = new " + FieldAccessTransformer.FIELD_INFO_CLASS_NAME + "(" +
734             "java.lang.Class.forName(\"" + clazz.getName() + "\")," +
735             index + ", " +
736             "\"" + fieldName + "\", " +
737             wrapperHash + "L, this, false);" +
738          GeneratedClassAdvisor.ADD_FIELD_WRITE_INFO + "(" + infoName + ");";
739
740       addCodeToInitialiseMethod(code, INITIALISE_FIELD_WRITES);
741    }
742
743    protected void initialiseConstructorInfoField(String JavaDoc infoName, int index, long constructorHash, long wrapperHash) throws NotFoundException
744    {
745       String JavaDoc code =
746          infoName + " = new " + ConstructorExecutionTransformer.CONSTRUCTOR_INFO_CLASS_NAME + "(" +
747             "java.lang.Class.forName(\"" + clazz.getName() + "\")," +
748             index + ", " +
749             wrapperHash + "L, " +
750             constructorHash + "L, this);" +
751          GeneratedClassAdvisor.ADD_CONSTRUCTOR_INFO + "(" + infoName + ");";
752
753       addCodeToInitialiseMethod(code, INITIALISE_CONSTRUCTORS);
754    }
755
756    protected void initialiseConstructionInfoField(String JavaDoc infoName, int index, long constructorHash) throws NotFoundException
757    {
758       String JavaDoc code =
759          infoName + " = new " + ConstructionTransformer.CONSTRUCTION_INFO_CLASS_NAME + "(" +
760             "java.lang.Class.forName(\"" + clazz.getName() + "\")," +
761             index + ", " +
762             constructorHash + "L, this);" +
763          GeneratedClassAdvisor.ADD_CONSTRUCTION_INFO + "(" + infoName + ");";
764
765       addCodeToInitialiseMethod(code, INITIALISE_CONSTRUCTIONS);
766
767    }
768
769    protected void initialiseCallerInfoField(String JavaDoc infoName, String JavaDoc init)throws CannotCompileException, NotFoundException
770    {
771       addCodeToInitialiseMethod(infoName + " = " + init + ";", INITIALISE_CALLERS);
772    }
773
774
775    private void addCodeToInitialiseMethod(String JavaDoc code, String JavaDoc methodName) throws NotFoundException
776    {
777       CtMethod method = genadvisor.getDeclaredMethod(methodName);
778       try
779       {
780          method.insertAfter(code);
781       }
782       catch (CannotCompileException e)
783       {
784          e.printStackTrace();
785          throw new RuntimeException JavaDoc("code was: " + code + " for method " + method.getName());
786       }
787    }
788
789    protected void addJoinPointGeneratorFieldToGenAdvisor(String JavaDoc name) throws CannotCompileException, NotFoundException
790    {
791       CtField field = new CtField(forName(JoinPointGenerator.class.getName()), name, genadvisor);
792       genadvisor.addField(field);
793    }
794
795    private static class GeneratedAdvisorNameExtractor
796    {
797       //TODO This kind of sucks. We need a better way to link names of wrapper methods, generators, infos and joinpoints
798
String JavaDoc infoName;
799       CtMethod wrapper;
800       CtField joinPointField;
801       CtField generatorField;
802
803       private GeneratedAdvisorNameExtractor(String JavaDoc infoName, CtMethod wrapper, CtField joinPointField, CtField generatorField)
804       {
805          this.infoName = infoName;
806          this.wrapper = wrapper;
807          this.joinPointField = joinPointField;
808          this.generatorField = generatorField;
809       }
810
811       private static GeneratedAdvisorNameExtractor extractNames(CtClass genadvisor, CtField infoField) throws NotFoundException
812       {
813          String JavaDoc infoName = infoField.getName();
814
815          if (infoField.getType().getName().equals(FieldInfo.class.getName()))
816          {
817             boolean isWrite = infoName.startsWith("aop$FieldInfo_w_");
818             if (!isWrite && !infoName.startsWith("aop$FieldInfo_r_"))
819             {
820                throw new RuntimeException JavaDoc("Bad FieldInfo name: '" + infoName + "'");
821             }
822             String JavaDoc fieldName = infoName.substring("aop$FieldInfo_w_".length());
823
824             String JavaDoc wrapperName = (isWrite) ?
825                   GeneratedAdvisorFieldAccessTransformer.advisorFieldWrite(genadvisor, fieldName) :
826                   GeneratedAdvisorFieldAccessTransformer.advisorFieldRead(genadvisor, fieldName);
827
828             CtMethod wrapper = genadvisor.getDeclaredMethod(wrapperName);
829
830             String JavaDoc joinPointName = (isWrite) ?
831                   FieldJoinPointGenerator.WRITE_JOINPOINT_FIELD_PREFIX + fieldName :
832                      FieldJoinPointGenerator.READ_JOINPOINT_FIELD_PREFIX + fieldName;
833             CtField joinPointField = genadvisor.getDeclaredField(joinPointName);
834
835             String JavaDoc generatorName =
836                (isWrite) ?
837                      FieldJoinPointGenerator.WRITE_GENERATOR_PREFIX + fieldName :
838                         FieldJoinPointGenerator.READ_GENERATOR_PREFIX + fieldName;
839                CtField generatorField = genadvisor.getDeclaredField(generatorName);
840
841             return new GeneratedAdvisorNameExtractor(infoName, wrapper, joinPointField, generatorField);
842          }
843          else if (infoField.getType().getName().equals(MethodInfo.class.getName()))
844          {
845             if (!infoName.startsWith("aop$MethodInfo_"))
846             {
847                throw new RuntimeException JavaDoc("Bad MethodInfo name: '" + infoName + "'");
848             }
849             String JavaDoc methodNameHash = infoName.substring("aop$MethodInfo_".length());
850             CtMethod wrapper = genadvisor.getDeclaredMethod(methodNameHash);
851
852             String JavaDoc joinPointName = JoinPointGenerator.JOINPOINT_FIELD_PREFIX + methodNameHash;
853             CtField joinPointField = genadvisor.getDeclaredField(joinPointName);
854
855             String JavaDoc generatorName = JoinPointGenerator.GENERATOR_PREFIX + methodNameHash;
856             CtField generatorField = genadvisor.getDeclaredField(generatorName);
857
858             return new GeneratedAdvisorNameExtractor(infoName, wrapper, joinPointField, generatorField);
859          }
860          else if (infoField.getType().getName().equals(ConByMethodInfo.class.getName()))
861          {
862             if (!infoName.startsWith("aop$constructorCall_"))
863             {
864                throw new RuntimeException JavaDoc("Bad ConByMethodInfo name: '" + infoName + "'");
865             }
866
867             CtMethod wrapper = genadvisor.getDeclaredMethod(infoName);
868
869             String JavaDoc joinPointName = ConByMethodJoinPointGenerator.JOINPOINT_FIELD_PREFIX + infoName.substring("aop$constructorCall_".length());
870             CtField joinPointField = genadvisor.getDeclaredField(joinPointName);
871
872             String JavaDoc generatorName = ConByMethodJoinPointGenerator.GENERATOR_PREFIX + infoName.substring("aop$constructorCall_".length());
873             CtField generatorField = genadvisor.getDeclaredField(generatorName);
874
875             return new GeneratedAdvisorNameExtractor(infoName, wrapper, joinPointField, generatorField);
876          }
877          else if (infoField.getType().getName().equals(MethodByMethodInfo.class.getName()))
878          {
879             if (!infoName.startsWith("aop$methodCall_"))
880             {
881                throw new RuntimeException JavaDoc("Bad MethodByMethodInfo name: '" + infoName + "'");
882             }
883
884             CtMethod wrapper = genadvisor.getDeclaredMethod(infoName);
885
886             String JavaDoc joinPointName = MethodByMethodJoinPointGenerator.JOINPOINT_FIELD_PREFIX + infoName.substring("aop$methodCall_".length());
887             CtField joinPointField = genadvisor.getDeclaredField(joinPointName);
888
889             String JavaDoc generatorName = MethodByMethodJoinPointGenerator.GENERATOR_PREFIX + infoName.substring("aop$methodCall_".length());
890             CtField generatorField = genadvisor.getDeclaredField(generatorName);
891
892             return new GeneratedAdvisorNameExtractor(infoName, wrapper, joinPointField, generatorField);
893          }
894
895          return null;
896       }
897
898       public CtField getJoinPointField()
899       {
900          return joinPointField;
901       }
902
903       public CtField getGeneratorField()
904       {
905          return generatorField;
906       }
907
908       public CtMethod getWrapper()
909       {
910          return wrapper;
911       }
912
913       public String JavaDoc getInfoFieldName()
914       {
915          return infoName;
916       }
917    }
918 }
919
Popular Tags