KickJava   Java API By Example, From Geeks To Geeks.

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


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.ConstructorInfo;
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.ConstructorInvocation;
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 ConstructorJoinPointGenerator extends JoinPointGenerator
50 {
51    public static final String JavaDoc GENERATOR_PREFIX = JoinPointGenerator.GENERATOR_PREFIX + "constructor_";
52    public static final String JavaDoc JOINPOINT_CLASS_PREFIX = JoinPointGenerator.JOINPOINT_CLASS_PREFIX + "constructor_";
53    public static final String JavaDoc JOINPOINT_FIELD_PREFIX = JoinPointGenerator.JOINPOINT_FIELD_PREFIX + "constructor_";
54    private static final Class JavaDoc INVOCATION_TYPE = ConstructorInvocation.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
69    public ConstructorJoinPointGenerator(GeneratedClassAdvisor advisor, JoinPointInfo info)
70    {
71       super(advisor, info);
72    }
73
74
75    protected void initialiseJoinPointNames()
76    {
77       joinpointClassName = getInfoClassName(
78                classSimpleName(),
79                index());
80
81       joinpointFieldName = getInfoFieldName(
82                classSimpleName(),
83                index());
84    }
85
86    private String JavaDoc classSimpleName()
87    {
88       Constructor JavaDoc ctor = ((ConstructorInfo)info).getConstructor();
89       return Advisor.getSimpleName(ctor.getDeclaringClass());
90    }
91
92    private int index()
93    {
94       return ((ConstructorInfo)info).getIndex();
95    }
96
97    protected boolean isVoid()
98    {
99       return false;
100    }
101
102    protected Class JavaDoc getReturnType()
103    {
104       return ((ConstructorInfo)super.info).getConstructor().getDeclaringClass();
105    }
106
107    protected AdviceMethodProperties getAdviceMethodProperties(AdviceSetup setup)
108    {
109       Constructor JavaDoc ctor = ((ConstructorInfo)info).getConstructor();
110       return new AdviceMethodProperties(
111             setup.getAspectClass(),
112             setup.getAdviceName(),
113             info.getClass(),
114             INVOCATION_TYPE,
115             ctor.getDeclaringClass(),
116             ctor.getParameterTypes(),
117             ctor.getExceptionTypes());
118    }
119
120    protected boolean hasTargetObject()
121    {
122       return false;
123    }
124
125    protected static CtClass createJoinpointBaseClass(
126          GeneratedAdvisorInstrumentor instrumentor,
127          CtClass advisedClass,
128          CtConstructor advisedCtor,
129          String JavaDoc ciname,
130          int index)throws NotFoundException, CannotCompileException
131    {
132       instrumentor.addJoinPointGeneratorFieldToGenAdvisor(
133             getJoinPointGeneratorFieldName(advisedClass.getSimpleName(), index));
134
135       BaseClassGenerator generator = new BaseClassGenerator(instrumentor, advisedClass, advisedCtor, ciname, index);
136       return generator.generate();
137    }
138
139    protected String JavaDoc getJoinPointGeneratorFieldName()
140    {
141       return getJoinPointGeneratorFieldName(classSimpleName(), index());
142    }
143
144    protected static String JavaDoc getInfoFieldName(String JavaDoc className, int index)
145    {
146       return JOINPOINT_FIELD_PREFIX + className + "_" + index;
147    }
148
149    private static String JavaDoc getInfoClassName(String JavaDoc className, int index)
150    {
151       return JOINPOINT_CLASS_PREFIX + className + "_" + index;
152    }
153
154    protected static String JavaDoc getJoinPointGeneratorFieldName(String JavaDoc className, int index)
155    {
156       return GENERATOR_PREFIX + className + "_" + index;
157    }
158
159    private static class BaseClassGenerator
160    {
161       GeneratedAdvisorInstrumentor instrumentor;
162       CtClass advisedClass;
163       CtConstructor advisedCtor;
164       String JavaDoc ciname;
165       int index;
166
167       CtClass jp;
168       CtMethod invokeJoinpointMethod;
169       CtConstructor publicConstructor;
170       CtConstructor protectedConstructor;
171       CtField targetField;
172       CtClass[] params;
173       CtClass constructorInfoClass;
174
175       BaseClassGenerator(
176             GeneratedAdvisorInstrumentor instrumentor,
177             CtClass advisedClass,
178             CtConstructor advisedCtor,
179             String JavaDoc ciname,
180             int index) throws NotFoundException
181       {
182          this.instrumentor = instrumentor;
183          this.advisedClass = advisedClass;
184          this.advisedCtor = advisedCtor;
185          this.ciname = ciname;
186          this.index = index;
187          this.params = advisedCtor.getParameterTypes();
188          constructorInfoClass = instrumentor.forName(ConstructorExecutionTransformer.CONSTRUCTOR_INFO_CLASS_NAME);
189       }
190
191       protected CtClass generate() throws CannotCompileException, NotFoundException
192       {
193          jp = setupClass();
194          addArgumentsFieldsAndAccessors();
195          addInvokeJoinpointMethod();
196          addMethodInfoField();
197          addPublicConstructor();
198          addProtectedConstructor();
199          addDispatchMethods();
200
201          TransformerCommon.compileOrLoadClass(advisedClass, jp);
202          return jp;
203       }
204
205
206       private CtClass setupClass()throws NotFoundException, CannotCompileException
207       {
208          String JavaDoc className = getInfoClassName(advisedClass.getSimpleName(), index);
209
210          //Create inner joinpoint class in advised class, super class is ConstructorInvocation
211
jp = TransformerCommon.makeNestedClass(advisedClass, className, true, Modifier.PUBLIC | Modifier.STATIC, INVOCATION_CT_TYPE);
212          addUntransformableInterface(instrumentor, jp);
213          return jp;
214       }
215
216       private void addArgumentsFieldsAndAccessors() throws NotFoundException, CannotCompileException
217       {
218          OptimizedBehaviourInvocations.addArgumentFieldsToInvocation(jp, params);
219          OptimizedBehaviourInvocations.addSetArguments(instrumentor.getClassPool(), jp, params);
220          OptimizedBehaviourInvocations.addGetArguments(instrumentor.getClassPool(), jp, params);
221       }
222
223       /**
224        * This constructor is used by the advisor when we have regenerated the joinpoint.
225        * This just creates a generic JoinPoint instance with no data specific to the
226        * method call
227        */

228       private void addPublicConstructor() throws CannotCompileException
229       {
230          publicConstructor = CtNewConstructor.make(
231                new CtClass[] {constructorInfoClass},
232                new CtClass[0],
233                "{super($1, $1.getInterceptors()); this." + INFO_FIELD + " = $1;}",
234                jp);
235
236          jp.addConstructor(publicConstructor);
237       }
238
239       /**
240        * This constructor will be called by invokeJoinpoint in the generated subclass when we need to
241        * instantiate a joinpoint containing target and args
242        */

243       protected void addProtectedConstructor() throws CannotCompileException
244       {
245          CtClass[] ctorParams = new CtClass[params.length + 1];
246          ctorParams[0] = jp;
247          System.arraycopy(params, 0, ctorParams, 1, params.length);
248
249          StringBuffer JavaDoc body = new StringBuffer JavaDoc();
250          body.append("{");
251          body.append(" this($1." + INFO_FIELD + ");");
252
253          int offset = 1;
254          for (int i = offset ; i < ctorParams.length ; i++)
255          {
256             body.append(" arg" + (i - offset) + " = $" + (i + 1) + ";");
257          }
258
259          body.append("}");
260          protectedConstructor = CtNewConstructor.make(
261                ctorParams,
262                new CtClass[0],
263                body.toString(),
264                jp);
265          protectedConstructor.setModifiers(Modifier.PROTECTED);
266          jp.addConstructor(protectedConstructor);
267
268       }
269
270       /**
271        * Add an empty invokeJoinpoint() method. This method will be overridden by generated subclasses,
272        * when the interceptors are rebuilt
273        */

274       private CtMethod addInvokeJoinpointMethod() throws CannotCompileException, NotFoundException
275       {
276          invokeJoinpointMethod = CtNewMethod.make(
277                advisedClass,
278                INVOKE_JOINPOINT,
279                params,
280                advisedCtor.getExceptionTypes(),
281                null,
282                jp);
283          invokeJoinpointMethod.setModifiers(Modifier.PROTECTED);
284          jp.addMethod(invokeJoinpointMethod);
285          return invokeJoinpointMethod;
286        }
287
288       private void addMethodInfoField()throws CannotCompileException
289       {
290          CtField infoField = new CtField(constructorInfoClass, INFO_FIELD, jp);
291          infoField.setModifiers(javassist.Modifier.PROTECTED);//Make visible to classes in child classloaders
292
jp.addField(infoField);
293       }
294
295       private void addDispatchMethods() throws CannotCompileException, NotFoundException
296       {
297          addInvokeNextDispatchMethod();
298
299          if (params.length > 0)
300          {
301             addInvokeJoinPointDispatchMethod();
302          }
303          
304          addInvokeTargetMethod();
305       }
306
307       private void addInvokeNextDispatchMethod() throws CannotCompileException, NotFoundException
308       {
309          //This dispatch method will be called by the invokeNext() methods for around advice
310
StringBuffer JavaDoc parameters = new StringBuffer JavaDoc("(");
311          for (int i = 0 ; i < params.length ; i++)
312          {
313             if (i > 0)parameters.append(", ");
314             parameters.append("arg" + i);
315          }
316          parameters.append(")");
317
318          String JavaDoc body =
319             "{" +
320             " " + advisedClass.getName() + " obj = new " + advisedClass.getName() + parameters + ";" +
321             " setTargetObject(obj);" +
322             " return obj;" +
323             "}";
324
325          try
326          {
327             CtMethod dispatch = CtNewMethod.make(
328                   advisedClass,
329                   JoinPointGenerator.DISPATCH,
330                   new CtClass[0],
331                   advisedCtor.getExceptionTypes(),
332                   body,
333                   jp);
334             dispatch.setModifiers(Modifier.PROTECTED);
335             jp.addMethod(dispatch);
336          }
337          catch (CannotCompileException e)
338          {
339             throw new RuntimeException JavaDoc("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, params), e);
340          }
341       }
342
343       private void addInvokeJoinPointDispatchMethod() throws CannotCompileException, NotFoundException
344       {
345          //This dispatch method will be called by the invokeJoinPoint() method if the joinpoint has no around advices
346

347          String JavaDoc body =
348             "{" +
349             " " + advisedClass.getName() + " obj = new " + advisedClass.getName() + "($$);" +
350             " setTargetObject(obj);" +
351             " return obj;" +
352             "}";
353
354          try
355          {
356             CtMethod dispatch = CtNewMethod.make(
357                   advisedClass,
358                   JoinPointGenerator.DISPATCH,
359                   params,
360                   advisedCtor.getExceptionTypes(),
361                   body,
362                   jp);
363             dispatch.setModifiers(Modifier.PROTECTED);
364             jp.addMethod(dispatch);
365          }
366          catch (CannotCompileException e)
367          {
368             throw new RuntimeException JavaDoc("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, params), e);
369          }
370       }
371       
372       private void addInvokeTargetMethod() throws CannotCompileException, NotFoundException
373       {
374          CtMethod template = INVOCATION_CT_TYPE.getDeclaredMethod(INVOKE_TARGET);
375          
376          String JavaDoc body = "{return dispatch();}";
377          
378          CtMethod invokeTarget = CtNewMethod.make(
379                template.getReturnType(),
380                template.getName(),
381                template.getParameterTypes(),
382                template.getExceptionTypes(),
383                body,
384                jp);
385          jp.addMethod(invokeTarget);
386       }
387       
388    }
389 }
390
Popular Tags