KickJava   Java API By Example, From Geeks To Geeks.

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


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.CtField;
27 import javassist.CtMethod;
28 import javassist.CtNewMethod;
29 import javassist.Modifier;
30 import javassist.NotFoundException;
31 import javassist.bytecode.AccessFlag;
32
33 import org.jboss.aop.AspectManager;
34 import org.jboss.aop.ClassAdvisor;
35 import org.jboss.aop.classpool.AOPClassPool;
36
37 /**
38  * Comment
39  *
40  * @author <a HREF="mailto:kabir.khan@jboss.org">Kabir Khan</a>
41  * @version $Revision$
42  */

43 public class ClassicInstrumentor extends Instrumentor
44 {
45    /**
46     * Name of helper class.
47     */

48    public static final String JavaDoc HELPER_CLASS_NAME =
49            Instrumentor.AOP_PACKAGE + ".ClassAdvisor";
50    
51    public ClassicInstrumentor(AOPClassPool pool, AspectManager manager, JoinpointClassifier joinpointClassifier, DynamicTransformationObserver observer)
52    {
53       super(pool,
54             manager,
55             joinpointClassifier,
56             observer);
57    }
58
59    public ClassicInstrumentor(AspectManager manager, JoinpointClassifier joinpointClassifier)
60    {
61       super(manager, joinpointClassifier);
62    }
63
64    protected void intitialiseTransformers()
65    {
66       
67       if (AspectManager.optimize)
68       {
69          methodExecutionTransformer = new OptimizedMethodExecutionTransformer(this);
70          constructorExecutionTransformer = new OptimizedConstructorExecutionTransformer(this);
71          fieldAccessTransformer = new OptimizedFieldAccessTransformer(this);
72          constructionTransformer = new OptimizedConstructionTransformer(this);
73          callerTransformer = new OptimizedCallerTransformer(this, manager);
74       }
75       else
76       {
77          methodExecutionTransformer = new NonOptimizedMethodExecutionTransformer(this);
78          constructorExecutionTransformer = new NonOptimizedConstructorExecutionTransformer(this);
79          fieldAccessTransformer = new NonOptimizedFieldAccessTransformer(this);
80          constructionTransformer = new NonOptimizedConstructionTransformer(this);
81          callerTransformer = new NonOptimizedCallerTransformer(this, manager);
82       }
83    }
84    
85    protected CtMethod createMixinInvokeMethod(CtClass clazz, CtClass mixinClass, String JavaDoc initializer, CtMethod method, long hash)
86    throws CannotCompileException, NotFoundException, Exception JavaDoc
87    {
88       String JavaDoc code = null;
89       String JavaDoc aopReturnStr = (method.getReturnType().equals(CtClass.voidType)) ? "" : "return ($r)";
90       String JavaDoc returnStr = (method.getReturnType().equals(CtClass.voidType)) ? "" : "return ";
91       String JavaDoc args = "null";
92       if (method.getParameterTypes().length > 0) args = "$args";
93       //If a call to a method introduced is intercepted, this original code uses the mixin class as the target
94
//object. This causes a ClassCastException in PerInstanceAdvice since the mixin class does not implement
95
//Advised
96
// code =
97
// "{ " +
98
// " if (" + mixinFieldName(mixinClass) + " == null) { " +
99
// " this." + mixinFieldName(mixinClass) + " = " + initializer + "; " +
100
// " } " +
101
// " if (" + HELPER_FIELD_NAME + ".doesHaveAspects || (_instanceAdvisor != null && _instanceAdvisor.hasInstanceAspects)) " +
102
// " { " +
103
// " Object[] ags = " + args + "; " +
104
// " " + aopReturnStr + HELPER_FIELD_NAME + ".invokeMethod(_instanceAdvisor, this." + mixinFieldName(mixinClass) + ", " + hash + "L, ags); " +
105
// " } " +
106
// " else " +
107
// " {" +
108
// " " + returnStr + " " + mixinFieldName(mixinClass) + "." + method.getName() + "($$); " +
109
// " }" +
110
// "}";
111

112       
113       
114       //1) add a not advised method that performs the call to the mixin class
115
code =
116       "{ " +
117       "" + returnStr + " " + mixinFieldName(mixinClass) + "." + method.getName() + "($$); " +
118       "}";
119       String JavaDoc wrappedName = ClassAdvisor.notAdvisedMethodName(clazz.getName(), method.getName());
120       CtMethod nmethod = CtNewMethod.make(method.getReturnType(), wrappedName, method.getParameterTypes(),
121                                         method.getExceptionTypes(), code, clazz);
122       int modifier = method.getModifiers();
123       if ((modifier & AccessFlag.ABSTRACT) == AccessFlag.ABSTRACT)
124       {
125          modifier &= ~AccessFlag.ABSTRACT;
126       }
127       nmethod.setModifiers(modifier);
128       clazz.addMethod(nmethod);
129       
130       
131       
132       //2 make the wrapped invocation call through to the helper method, using this as the target object
133
code =
134       "{ " +
135       " if (" + mixinFieldName(mixinClass) + " == null) { " +
136       " this." + mixinFieldName(mixinClass) + " = " + initializer + "; " +
137       " } " +
138       " org.jboss.aop.ClassInstanceAdvisor instAdv = (org.jboss.aop.ClassInstanceAdvisor)_getInstanceAdvisor();" +
139       " if (" + HELPER_FIELD_NAME + ".hasAspects() || (instAdv != null && instAdv.hasInstanceAspects)) " +
140       " { " +
141       " Object[] ags = " + args + "; " +
142       " " + aopReturnStr + HELPER_FIELD_NAME + ".invokeMethod(instAdv, this, " + hash + "L, ags); " +
143       " } " +
144       " else " +
145       " {" +
146       " " + returnStr + " " + mixinFieldName(mixinClass) + "." + method.getName() + "($$); " +
147       " }" +
148       "}";
149       
150       CtMethod wmethod = null;
151       try
152       {
153          wmethod = CtNewMethod.make(method.getReturnType(), method.getName(), method.getParameterTypes(),
154                method.getExceptionTypes(), code, clazz);
155          wmethod.setModifiers(modifier);
156       }
157       catch (CannotCompileException e)
158       {
159          throw new RuntimeException JavaDoc("<mixin> construction may have syntax error: '" + initializer + "'", e);
160       }
161       clazz.addMethod(wmethod);
162       
163       return wmethod;
164    
165    }
166    
167    protected void doSetupBasics(CtClass clazz) throws CannotCompileException, NotFoundException
168    {
169       // add aop helper class.
170
addHelperClass(clazz);
171
172       if (isBaseClass(clazz))
173       {
174          addBaseElements(clazz);
175       }
176    }
177    
178    private void addHelperField(CtClass clazz) throws CannotCompileException, NotFoundException
179    {
180       addStaticField(clazz,
181                      ClassicInstrumentor.HELPER_FIELD_NAME,
182                      ClassicInstrumentor.HELPER_CLASS_NAME,
183                      CtField.Initializer.byExpr(ASPECT_MANAGER_CLASS_NAME + ".instance().getAdvisor(java.lang.Class#forName(\"" +
184                                                 clazz.getName() + "\"))"));
185    }
186
187    /**
188     * Adds a static helper class instance to passed class.
189     */

190    private void addHelperClass(CtClass clazz)
191            throws CannotCompileException, NotFoundException
192    {
193       addHelperField(clazz);
194       // To make sure that correct Advisor gets called
195
CtMethod getter = CtNewMethod.make("public org.jboss.aop.Advisor _getAdvisor()" +
196                                          "{ " +
197                                          " return " + ClassicInstrumentor.HELPER_FIELD_NAME + ";" +
198                                          "}",
199                                          clazz);
200       clazz.addMethod(getter);
201    }
202    
203    private void addBaseElements(CtClass clazz)
204    throws NotFoundException, CannotCompileException
205    {
206       addProtectedField(clazz,
207                 "_instanceAdvisor",
208                 "org.jboss.aop.ClassInstanceAdvisor", null
209                 //CtField.Initializer.byExpr("new org.jboss.aop.ClassInstanceAdvisor(this)")
210
);
211
212          CtMethod getter = CtNewMethod.make("public org.jboss.aop.InstanceAdvisor _getInstanceAdvisor()" +
213                                  "{ " +
214                                  " synchronized(this) {" +
215                                  " if (_instanceAdvisor == null) { _instanceAdvisor = new org.jboss.aop.ClassInstanceAdvisor(this); }" +
216                                  " return _instanceAdvisor;" +
217                                  " } " +
218                                  "}",
219                                  clazz);
220          clazz.addMethod(getter);
221
222          CtMethod setter = CtNewMethod.make("public void _setInstanceAdvisor(org.jboss.aop.InstanceAdvisor newAdvisor)" +
223                                  "{ " +
224                                  " synchronized(this) {" +
225                                  " _instanceAdvisor = (org.jboss.aop.ClassInstanceAdvisor)newAdvisor;" +
226                                  " } " +
227                                  "}",
228                                  clazz);
229          clazz.addMethod(setter);
230
231 }
232
233    
234    
235 }
236
Popular Tags