KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.lang.reflect.Constructor JavaDoc;
25 import java.lang.reflect.Modifier JavaDoc;
26
27 import javassist.CannotCompileException;
28 import javassist.CtClass;
29 import javassist.CtConstructor;
30 import javassist.CtField;
31 import javassist.CtMethod;
32 import javassist.CtNewConstructor;
33 import javassist.CtNewMethod;
34 import javassist.NotFoundException;
35
36 import org.jboss.aop.Advisor;
37 import org.jboss.aop.ConstructionInfo;
38 import org.jboss.aop.GeneratedClassAdvisor;
39 import org.jboss.aop.JoinPointInfo;
40 import org.jboss.aop.advice.AdviceMethodProperties;
41 import org.jboss.aop.joinpoint.ConstructionInvocation;
42 import org.jboss.aop.util.ReflectToJavassist;
43
44 /**
45  *
46  * @author <a HREF="kabir.khan@jboss.com">Kabir Khan</a>
47  * @version $Revision$
48  */

49 public class ConstructionJoinPointGenerator extends JoinPointGenerator
50 {
51    public static final String JavaDoc GENERATOR_PREFIX = JoinPointGenerator.GENERATOR_PREFIX + "construction_";
52    public static final String JavaDoc JOINPOINT_CLASS_PREFIX = JoinPointGenerator.JOINPOINT_CLASS_PREFIX + "construction_";
53    public static final String JavaDoc JOINPOINT_FIELD_PREFIX = JoinPointGenerator.JOINPOINT_FIELD_PREFIX + "construction_";
54    private static final Class JavaDoc INVOCATION_TYPE = ConstructionInvocation.class;
55    private static final CtClass INVOCATION_CT_TYPE;
56    static
57    {
58       try
59       {
60          INVOCATION_CT_TYPE = ReflectToJavassist.classToJavassist(INVOCATION_TYPE);
61       }
62       catch (NotFoundException e)
63       {
64          throw new RuntimeException JavaDoc(e);
65       }
66    }
67
68    public ConstructionJoinPointGenerator(GeneratedClassAdvisor advisor, JoinPointInfo info)
69    {
70       super(advisor, info);
71    }
72
73
74    protected void initialiseJoinPointNames()
75    {
76       joinpointClassName = getInfoClassName(
77                classSimpleName(),
78                index());
79
80       joinpointFieldName = getInfoFieldName(
81                classSimpleName(),
82                index());
83    }
84
85    private String JavaDoc classSimpleName()
86    {
87       Constructor JavaDoc ctor = ((ConstructionInfo)info).getConstructor();
88       return Advisor.getSimpleName(ctor.getDeclaringClass());
89    }
90
91    private int index()
92    {
93       return ((ConstructionInfo)info).getIndex();
94    }
95
96    protected boolean isVoid()
97    {
98       return true;
99    }
100
101    protected Class JavaDoc getReturnType()
102    {
103       return null;
104    }
105
106    protected AdviceMethodProperties getAdviceMethodProperties(AdviceSetup setup)
107    {
108       Constructor JavaDoc ctor = ((ConstructionInfo)info).getConstructor();
109       return new AdviceMethodProperties(
110             setup.getAspectClass(),
111             setup.getAdviceName(),
112             info.getClass(),
113             INVOCATION_TYPE,
114             ctor.getDeclaringClass(),
115             ctor.getParameterTypes(),
116             ctor.getExceptionTypes());
117    }
118
119    protected boolean hasTargetObject()
120    {
121       return true;
122    }
123
124    protected String JavaDoc getInfoName()
125    {
126       return ConstructionTransformer.getConstructionInfoFieldName(
127             Advisor.getSimpleName(advisor.getClazz()), ((ConstructionInfo)info).getIndex());
128    }
129
130
131    protected static CtClass createJoinpointBaseClass(
132          GeneratedAdvisorInstrumentor instrumentor,
133          CtClass advisedClass,
134          CtConstructor advisedCtor,
135          String JavaDoc ciname,
136          int index)throws NotFoundException, CannotCompileException
137    {
138       instrumentor.addJoinPointGeneratorFieldToGenAdvisor(
139             getJoinPointGeneratorFieldName(advisedClass.getSimpleName(), index));
140
141       BaseClassGenerator generator = new BaseClassGenerator(instrumentor, advisedClass, advisedCtor, ciname, index);
142       return generator.generate();
143    }
144
145    protected String JavaDoc getJoinPointGeneratorFieldName()
146    {
147       return getJoinPointGeneratorFieldName(
148             classSimpleName(),
149             index());
150    }
151
152    protected static String JavaDoc getInfoFieldName(String JavaDoc className, int index)
153    {
154       return JOINPOINT_FIELD_PREFIX + className + "_" + index;
155    }
156
157    private static String JavaDoc getInfoClassName(String JavaDoc className, int index)
158    {
159       return JOINPOINT_CLASS_PREFIX + className + "_" + index;
160    }
161
162    protected static String JavaDoc getJoinPointGeneratorFieldName(String JavaDoc className, int index)
163    {
164       return GENERATOR_PREFIX + className + "_" + index;
165    }
166
167
168    private static class BaseClassGenerator
169    {
170       GeneratedAdvisorInstrumentor instrumentor;
171       CtClass advisedClass;
172       CtConstructor advisedCtor;
173       String JavaDoc ciname;
174       int index;
175
176       CtClass jp;
177       CtMethod invokeJoinpointMethod;
178       CtConstructor publicConstructor;
179       CtConstructor protectedConstructor;
180       CtField targetField;
181       CtClass[] originalParams;
182       CtClass[] params;
183       CtClass constructionInfoClass;
184
185       BaseClassGenerator(
186             GeneratedAdvisorInstrumentor instrumentor,
187             CtClass advisedClass,
188             CtConstructor advisedCtor,
189             String JavaDoc ciname,
190             int index) throws NotFoundException
191       {
192          this.instrumentor = instrumentor;
193          this.advisedClass = advisedClass;
194          this.advisedCtor = advisedCtor;
195          this.ciname = ciname;
196          this.index = index;
197          this.originalParams = advisedCtor.getParameterTypes();
198          this.params = new CtClass[originalParams.length + 1];
199          this.params[0] = advisedClass;
200          System.arraycopy(originalParams, 0, params, 1, originalParams.length);
201
202          constructionInfoClass = instrumentor.forName(ConstructionTransformer.CONSTRUCTION_INFO_CLASS_NAME);
203       }
204
205       protected CtClass generate() throws CannotCompileException, NotFoundException
206       {
207          jp = setupClass();
208          addArgumentsFieldsAndAccessors();
209          addTypedTargetField();
210          addInvokeJoinpointMethod();
211          addConstructionInfoField();
212          addPublicConstructor();
213          addProtectedConstructor();
214          addDispatchMethods();
215
216          TransformerCommon.compileOrLoadClass(advisedClass, jp);
217          return jp;
218       }
219
220
221       private CtClass setupClass()throws NotFoundException, CannotCompileException
222       {
223          String JavaDoc className = getInfoClassName(advisedClass.getSimpleName(), index);
224
225          //Create inner joinpoint class in advised class, super class is jp
226
jp = TransformerCommon.makeNestedClass(advisedClass, className, true, Modifier.PUBLIC | Modifier.STATIC, INVOCATION_CT_TYPE);
227          addUntransformableInterface(instrumentor, jp);
228          return jp;
229       }
230
231       private void addTypedTargetField()throws CannotCompileException
232       {
233          targetField = new CtField(advisedClass, TARGET_FIELD, jp);
234          jp.addField(targetField);
235          targetField.setModifiers(Modifier.PROTECTED);
236       }
237
238
239       private void addArgumentsFieldsAndAccessors() throws NotFoundException, CannotCompileException
240       {
241          OptimizedBehaviourInvocations.addArgumentFieldsToInvocation(jp, originalParams);
242          OptimizedBehaviourInvocations.addSetArguments(instrumentor.getClassPool(), jp, originalParams);
243          OptimizedBehaviourInvocations.addGetArguments(instrumentor.getClassPool(), jp, originalParams);
244       }
245
246       /**
247        * This constructor is used by the advisor when we have regenerated the joinpoint.
248        * This just creates a generic JoinPoint instance with no data specific to the
249        * method call
250        */

251       private void addPublicConstructor() throws CannotCompileException
252       {
253          publicConstructor = CtNewConstructor.make(
254                new CtClass[] {constructionInfoClass},
255                new CtClass[0],
256                "{super($1, $1.getInterceptors()); this." + INFO_FIELD + " = $1;}",
257                jp);
258
259          jp.addConstructor(publicConstructor);
260       }
261
262       /**
263        * This constructor will be called by invokeJoinpoint in the generated subclass when we need to
264        * instantiate a joinpoint containing target and args
265        */

266       protected void addProtectedConstructor() throws CannotCompileException
267       {
268          CtClass[] ctorParams = new CtClass[params.length + 1];
269          ctorParams[0] = jp;
270          System.arraycopy(params, 0, ctorParams, 1, params.length);
271
272          StringBuffer JavaDoc body = new StringBuffer JavaDoc();
273          body.append("{");
274          body.append(" this($1." + INFO_FIELD + ");");
275
276          int offset = 2;
277          body.append(" this." + targetField.getName() + " = $2;");
278          body.append(" super.setTargetObject($2);");
279
280          for (int i = offset ; i < ctorParams.length ; i++)
281          {
282             body.append(" arg" + (i - offset) + " = $" + (i + 1) + ";");
283          }
284
285          body.append("}");
286          protectedConstructor = CtNewConstructor.make(
287                ctorParams,
288                new CtClass[0],
289                body.toString(),
290                jp);
291          protectedConstructor.setModifiers(Modifier.PROTECTED);
292
293          jp.addConstructor(protectedConstructor);
294       }
295
296       /**
297        * Add an empty invokeJoinpoint() method. This method will be overridden by generated subclasses,
298        * when the interceptors are rebuilt
299        */

300       private CtMethod addInvokeJoinpointMethod() throws CannotCompileException, NotFoundException
301       {
302          invokeJoinpointMethod = CtNewMethod.make(
303                CtClass.voidType,
304                INVOKE_JOINPOINT,
305                params,
306                advisedCtor.getExceptionTypes(),
307                null,
308                jp);
309          invokeJoinpointMethod.setModifiers(Modifier.PROTECTED);
310          jp.addMethod(invokeJoinpointMethod);
311          return invokeJoinpointMethod;
312        }
313
314       private void addConstructionInfoField()throws CannotCompileException
315       {
316          CtField infoField = new CtField(constructionInfoClass, INFO_FIELD, jp);
317          infoField.setModifiers(javassist.Modifier.PROTECTED);//Make visible to classes in child classloaders
318
jp.addField(infoField);
319       }
320
321       private void addDispatchMethods() throws CannotCompileException, NotFoundException
322       {
323          addInvokeNextDispatchMethod();
324          addInvokeJoinPointDispatchMethod();
325       }
326
327       private void addInvokeNextDispatchMethod() throws CannotCompileException, NotFoundException
328       {
329          //This dispatch method will be called by the invokeNext() methods for around advice
330

331          String JavaDoc body =
332                "{ return null;}";
333          try
334          {
335             CtMethod dispatch = CtNewMethod.make(
336                   CtClass.voidType,
337                   JoinPointGenerator.DISPATCH,
338                   EMPTY_CTCLASS_ARRAY,
339                   advisedCtor.getExceptionTypes(),
340                   body,
341                   jp);
342             dispatch.setModifiers(Modifier.PROTECTED);
343             jp.addMethod(dispatch);
344          }
345          catch (CannotCompileException e)
346          {
347             throw new RuntimeException JavaDoc("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, EMPTY_CTCLASS_ARRAY), e);
348          }
349       }
350
351       private void addInvokeJoinPointDispatchMethod() throws CannotCompileException, NotFoundException
352       {
353          //This dispatch method will be called by the invokeJoinPoint() method if the joinpoint has no around advices
354
String JavaDoc body =
355                "{ return null;}";
356
357          try
358          {
359             CtMethod dispatch = CtNewMethod.make(
360                   CtClass.voidType,
361                   JoinPointGenerator.DISPATCH,
362                   params,
363                   advisedCtor.getExceptionTypes(),
364                   body,
365                   jp);
366             dispatch.setModifiers(Modifier.PROTECTED);
367             jp.addMethod(dispatch);
368          }
369          catch (CannotCompileException e)
370          {
371             throw new RuntimeException JavaDoc("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, params), e);
372          }
373       }
374    }
375 }
376
Popular Tags