KickJava   Java API By Example, From Geeks To Geeks.

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


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.ConByConInfo;
37 import org.jboss.aop.GeneratedClassAdvisor;
38 import org.jboss.aop.JoinPointInfo;
39 import org.jboss.aop.advice.AdviceMethodProperties;
40 import org.jboss.aop.joinpoint.ConstructorCalledByConstructorInvocation;
41 import org.jboss.aop.util.ReflectToJavassist;
42
43 /**
44  *
45  * @author <a HREF="kabir.khan@jboss.com">Kabir Khan</a>
46  * @version $Revision: 56807 $
47  */

48 public class ConByConJoinPointGenerator extends JoinPointGenerator
49 {
50    public static final String JavaDoc GENERATOR_PREFIX = JoinPointGenerator.GENERATOR_PREFIX + "CByC_";
51    public static final String JavaDoc JOINPOINT_CLASS_PREFIX = JoinPointGenerator.JOINPOINT_CLASS_PREFIX + "CByC_";
52    public static final String JavaDoc JOINPOINT_FIELD_PREFIX = JoinPointGenerator.JOINPOINT_FIELD_PREFIX + "CByC_";
53
54    private static final Class JavaDoc INVOCATION_TYPE = ConstructorCalledByConstructorInvocation.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 ConByConJoinPointGenerator(GeneratedClassAdvisor advisor, JoinPointInfo info)
69    {
70       super(advisor, info);
71    }
72
73    protected void initialiseJoinPointNames()
74    {
75       joinpointClassName = getInfoClassName(
76                callingIndex(),
77                calledClass(),
78                calledConHash());
79
80       joinpointFieldName = getInfoFieldName(
81             callingIndex(),
82             calledClass(),
83             calledConHash());
84
85    }
86
87    private int callingIndex()
88    {
89       return ((ConByConInfo)info).getCallingIndex();
90    }
91
92    private String JavaDoc calledClass()
93    {
94       return ((ConByConInfo)info).getCalledClass().getName();
95    }
96
97    private long calledConHash()
98    {
99       return ((ConByConInfo)info).getCalledConHash();
100    }
101
102
103    protected boolean isVoid()
104    {
105       return false;
106    }
107
108    protected Class JavaDoc getReturnType()
109    {
110       return ((ConByConInfo)info).getCalledClass();
111    }
112
113    protected AdviceMethodProperties getAdviceMethodProperties(AdviceSetup setup)
114    {
115       Constructor JavaDoc ctor = ((ConByConInfo)info).getConstructor();
116       return new AdviceMethodProperties(
117             setup.getAspectClass(),
118             setup.getAdviceName(),
119             info.getClass(),
120             INVOCATION_TYPE,
121             ctor.getDeclaringClass(),
122             ctor.getParameterTypes(),
123             ctor.getExceptionTypes());
124    }
125
126    protected boolean isCaller()
127    {
128       return true;
129    }
130
131    protected boolean hasCallingObject()
132    {
133       return false;
134    }
135
136    protected boolean hasTargetObject()
137    {
138       return false;
139    }
140
141
142    protected void overrideDispatchMethods(CtClass superClass, CtClass clazz, JoinPointInfo newInfo) throws CannotCompileException, NotFoundException
143    {
144       super.overrideDispatchMethods(superClass, clazz, (ConByConInfo)newInfo);
145    }
146
147    protected static CtClass createJoinpointBaseClass(
148             GeneratedAdvisorInstrumentor instrumentor,
149             int callingIndex,
150             CtClass callingClass,
151             CtConstructor targetCtor,
152             String JavaDoc classname,
153             long calledHash,
154             String JavaDoc ciname) throws NotFoundException, CannotCompileException
155    {
156       instrumentor.addJoinPointGeneratorFieldToGenAdvisor(
157             getJoinPointGeneratorFieldName(callingIndex, classname, calledHash));
158
159       BaseClassGenerator generator = new BaseClassGenerator(instrumentor, callingClass, callingIndex, classname, targetCtor, calledHash, ciname);
160       return generator.generate();
161    }
162
163    protected String JavaDoc getJoinPointGeneratorFieldName()
164    {
165       return getJoinPointGeneratorFieldName(
166             callingIndex(),
167             calledClass(),
168             calledConHash());
169    }
170
171    protected static String JavaDoc getInfoClassName(int callingIndex, String JavaDoc classname, long calledHash)
172    {
173       return JOINPOINT_CLASS_PREFIX + CallerTransformer.getUniqueInvocationFieldname(callingIndex, classname, calledHash);
174    }
175
176    protected static String JavaDoc getInfoFieldName(int callingIndex, String JavaDoc classname, long calledHash)
177    {
178       return JOINPOINT_FIELD_PREFIX + CallerTransformer.getUniqueInvocationFieldname(callingIndex, classname, calledHash);
179    }
180
181    protected static String JavaDoc getJoinPointGeneratorFieldName(int callingIndex, String JavaDoc classname, long calledHash)
182    {
183       return GENERATOR_PREFIX + CallerTransformer.getUniqueInvocationFieldname(callingIndex, classname, calledHash);
184    }
185
186    private static class BaseClassGenerator
187    {
188       GeneratedAdvisorInstrumentor instrumentor;
189       CtClass callingClass;
190       int callingIndex;
191       String JavaDoc classname;
192       CtClass targetClass;
193       CtConstructor targetCtor;
194       long calledHash;
195       String JavaDoc ciname;
196
197       CtClass jp;
198       CtMethod invokeJoinpointMethod;
199       CtConstructor publicConstructor;
200       CtConstructor protectedConstructor;
201       CtClass[] params;
202       CtClass constructorInfoClass;
203
204       BaseClassGenerator(
205             GeneratedAdvisorInstrumentor instrumentor,
206             CtClass callingClass,
207             int callingIndex,
208             String JavaDoc classname,
209             CtConstructor targetCtor,
210             long calledHash,
211             String JavaDoc ciname) throws NotFoundException
212       {
213          this.instrumentor = instrumentor;
214          this.callingClass = callingClass;
215          this.callingIndex = callingIndex;
216          this.classname = classname;
217          this.targetClass = instrumentor.forName(classname);
218          this.targetCtor = targetCtor;
219          this.calledHash = calledHash;
220          this.ciname = ciname;
221          this.params = targetCtor.getParameterTypes();
222          constructorInfoClass = instrumentor.forName(CallerTransformer.CON_BY_CON_INFO_CLASS_NAME);
223       }
224
225       protected CtClass generate() throws CannotCompileException, NotFoundException
226       {
227          jp = setupClass();
228          addArgumentsFieldsAndAccessors();
229          addInvokeJoinpointMethod();
230          addMethodInfoField();
231          addPublicConstructor();
232          addProtectedConstructor();
233          addDispatchMethods();
234
235          TransformerCommon.compileOrLoadClass(callingClass, jp);
236          return jp;
237       }
238
239
240       private CtClass setupClass()throws NotFoundException, CannotCompileException
241       {
242          String JavaDoc className = getInfoClassName(callingIndex, targetClass.getName(), calledHash);
243
244          //Create inner joinpoint class in advised class, super class is ConstructorInvocation
245
jp = TransformerCommon.makeNestedClass(callingClass, className, true, Modifier.PUBLIC | Modifier.STATIC, INVOCATION_CT_TYPE);
246          addUntransformableInterface(instrumentor, jp);
247          return jp;
248       }
249
250       private void addArgumentsFieldsAndAccessors() throws NotFoundException, CannotCompileException
251       {
252          OptimizedBehaviourInvocations.addArgumentFieldsToInvocation(jp, params);
253          OptimizedBehaviourInvocations.addSetArguments(instrumentor.getClassPool(), jp, params);
254          OptimizedBehaviourInvocations.addGetArguments(instrumentor.getClassPool(), jp, params);
255       }
256
257       /**
258        * This constructor is used by the advisor when we have regenerated the joinpoint.
259        * This just creates a generic JoinPoint instance with no data specific to the
260        * method call
261        */

262       private void addPublicConstructor() throws CannotCompileException
263       {
264          publicConstructor = CtNewConstructor.make(
265                new CtClass[] {constructorInfoClass},
266                new CtClass[0],
267                "{super($1, $1.getInterceptors()); this." + INFO_FIELD + " = $1;}",
268                jp);
269          jp.addConstructor(publicConstructor);
270       }
271
272       /**
273        * This constructor will be called by invokeJoinpoint in the generated subclass when we need to
274        * instantiate a joinpoint containing target and args
275        */

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

308       private CtMethod addInvokeJoinpointMethod() throws CannotCompileException, NotFoundException
309       {
310          invokeJoinpointMethod = CtNewMethod.make(
311                targetClass,
312                INVOKE_JOINPOINT,
313                params,
314                targetCtor.getExceptionTypes(),
315                null,
316                jp);
317          invokeJoinpointMethod.setModifiers(Modifier.PROTECTED);
318          jp.addMethod(invokeJoinpointMethod);
319          return invokeJoinpointMethod;
320        }
321
322       private void addMethodInfoField()throws CannotCompileException
323       {
324          CtField infoField = new CtField(constructorInfoClass, INFO_FIELD, jp);
325          infoField.setModifiers(javassist.Modifier.PROTECTED);//Make visible to classes in child classloaders
326
jp.addField(infoField);
327       }
328
329       private void addDispatchMethods() throws CannotCompileException, NotFoundException
330       {
331          addInvokeNextDispatchMethod();
332
333          if (params.length > 0)
334          {
335             addInvokeJoinpointDispatchMethod();
336          }
337          
338          addInvokeTargetMethod();
339       }
340
341       private void addInvokeNextDispatchMethod() throws CannotCompileException, NotFoundException
342       {
343          //This dispatch method will be called by the invokeNext() methods for around advice
344
StringBuffer JavaDoc parameters = new StringBuffer JavaDoc("(");
345          for (int i = 0 ; i < params.length ; i++)
346          {
347             if (i > 0)parameters.append(", ");
348             parameters.append("arg" + i);
349          }
350          parameters.append(")");
351
352          String JavaDoc body =
353             "{" +
354             " " + targetClass.getName() + " obj = new " + targetClass.getName() + parameters + ";" +
355             " setTargetObject(obj);" +
356             " return obj;" +
357             "}";
358
359          try
360          {
361             CtMethod dispatch = CtNewMethod.make(
362                   targetClass,
363                   JoinPointGenerator.DISPATCH,
364                   new CtClass[0],
365                   targetCtor.getExceptionTypes(),
366                   body,
367                   jp);
368             dispatch.setModifiers(Modifier.PROTECTED);
369             jp.addMethod(dispatch);
370          }
371          catch (CannotCompileException e)
372          {
373             throw new RuntimeException JavaDoc("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, params), e);
374          }
375       }
376
377       private void addInvokeJoinpointDispatchMethod() throws CannotCompileException, NotFoundException
378       {
379          //This dispatch method will be called by the invokeJoinPoint() method if the joinpoint has no around advices
380
String JavaDoc body =
381             "{" +
382             " " + targetClass.getName() + " obj = new " + targetClass.getName() + "($$);" +
383             " setTargetObject(obj);" +
384             " return obj;" +
385             "}";
386
387
388          try
389          {
390             CtMethod dispatch = CtNewMethod.make(
391                   targetClass,
392                   JoinPointGenerator.DISPATCH,
393                   params,
394                   targetCtor.getExceptionTypes(),
395                   body,
396                   jp);
397             dispatch.setModifiers(Modifier.PROTECTED);
398             jp.addMethod(dispatch);
399          }
400          catch (CannotCompileException e)
401          {
402             throw new RuntimeException JavaDoc("Could not compile code " + body + " for dispatch method " + getMethodString(jp, JoinPointGenerator.DISPATCH, params), e);
403          }
404       }
405
406       private void addInvokeTargetMethod() throws CannotCompileException, NotFoundException
407       {
408          CtMethod template = INVOCATION_CT_TYPE.getDeclaredMethod(INVOKE_TARGET);
409          
410          String JavaDoc body = "{return dispatch();}";
411          
412          CtMethod invokeTarget = CtNewMethod.make(
413                template.getReturnType(),
414                template.getName(),
415                template.getParameterTypes(),
416                template.getExceptionTypes(),
417                body,
418                jp);
419          jp.addMethod(invokeTarget);
420       }
421    }
422
423 }
424
Popular Tags