KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > transform > inlining > compiler > JoinPointFactory


1 /**************************************************************************************
2  * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.transform.inlining.compiler;
9
10 import java.util.Map JavaDoc;
11 import java.util.Iterator JavaDoc;
12 import java.util.WeakHashMap JavaDoc;
13 import java.util.HashSet JavaDoc;
14 import java.util.Set JavaDoc;
15
16 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType;
17 import org.codehaus.aspectwerkz.expression.ExpressionContext;
18 import org.codehaus.aspectwerkz.expression.PointcutType;
19 import org.codehaus.aspectwerkz.expression.ExpressionInfo;
20 import org.codehaus.aspectwerkz.reflect.MethodInfo;
21 import org.codehaus.aspectwerkz.reflect.ClassInfo;
22 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
23 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
24 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint;
25
26 /**
27  * TODO is factory a good name, now that it does so much more?
28  * <p/>
29  * Factory for the different join point implementations.
30  * Compiles a new join point on the fly and loads the class.
31  *
32  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
33  */

34 public class JoinPointFactory {
35
36     /**
37      * Stores the compilation infos - mapped to the last compiled join point class based on this compilation info.
38      */

39     private static final Map JavaDoc COMPILATION_INFO_REPOSITORY = new WeakHashMap JavaDoc();
40
41     /**
42      * Compiles and loades a join point class, one specific class for each distinct join point.
43      *
44      * @param model the model for the compilation
45      * @param loader the class loader that the compiled join point should live in
46      * @return the compiled join point class
47      */

48     public static Class JavaDoc compileJoinPointAndAttachToClassLoader(final CompilationInfo.Model model,
49                                                                final ClassLoader JavaDoc loader) {
50         return attachToClassLoader(model.getJoinPointClassName(), loader, compileJoinPoint(model));
51     }
52
53     /**
54      * Loads a join point class, one specific class for each distinct join point.
55      *
56      * @param joinpointClassName
57      * @param loader the class loader that the compiled join point should live in
58      * @param bytecode of the joinpoint
59      * @return the compiled join point class
60      */

61     public static Class JavaDoc attachToClassLoader(final String JavaDoc joinpointClassName,
62                                             final ClassLoader JavaDoc loader,
63                                             final byte[] bytecode) {
64         return AsmHelper.defineClass(loader, bytecode, joinpointClassName);
65     }
66
67     /**
68      * Adds or updates a compilation info. The class key is always the first compiled join point class.
69      *
70      * @param clazz
71      * @param compilationInfo
72      */

73     public static void addCompilationInfo(final Class JavaDoc clazz, final CompilationInfo compilationInfo) {
74         COMPILATION_INFO_REPOSITORY.put(clazz, compilationInfo);
75     }
76
77     /**
78      * Compiles a join point class, one specific class for each distinct join point.
79      *
80      * @param model the model for the compilation
81      * @return the compiled join point bytecode
82      */

83     public static byte[] compileJoinPoint(final CompilationInfo.Model model) {
84         switch (model.getEmittedJoinPoint().getJoinPointType()) {
85             case JoinPointType.METHOD_EXECUTION_INT:
86                 return new MethodExecutionJoinPointCompiler(model).compile();
87             case JoinPointType.METHOD_CALL_INT:
88                 return new MethodCallJoinPointCompiler(model).compile();
89             case JoinPointType.CONSTRUCTOR_EXECUTION_INT:
90                 return new ConstructorExecutionJoinPointCompiler(model).compile();
91             case JoinPointType.CONSTRUCTOR_CALL_INT:
92                 return new ConstructorCallJoinPointCompiler(model).compile();
93             case JoinPointType.FIELD_SET_INT:
94                 return new FieldSetJoinPointCompiler(model).compile();
95             case JoinPointType.FIELD_GET_INT:
96                 return new FieldGetJoinPointCompiler(model).compile();
97             case JoinPointType.HANDLER_INT:
98                 return new HandlerJoinPointCompiler(model).compile();
99             case JoinPointType.STATIC_INITIALIZATION_INT:
100                 return new StaticInitializationJoinPointCompiler(model).compile();
101             default:
102                 throw new UnsupportedOperationException JavaDoc(
103                         "join point type is not supported: " + model.getEmittedJoinPoint().getJoinPointType()
104                 );
105         }
106     }
107
108     /**
109      * Redefines the originally compiled join point.
110      *
111      * @param compilationInfo the model for the compilation
112      * @return the compiled join point bytecode
113      */

114     public static byte[] redefineJoinPoint(final CompilationInfo compilationInfo) {
115         switch (compilationInfo.getInitialModel().getEmittedJoinPoint().getJoinPointType()) {
116             case JoinPointType.METHOD_EXECUTION_INT:
117                 return new MethodExecutionJoinPointRedefiner(compilationInfo).compile();
118             case JoinPointType.METHOD_CALL_INT:
119                 return new MethodCallJoinPointRedefiner(compilationInfo).compile();
120             case JoinPointType.CONSTRUCTOR_EXECUTION_INT:
121                 return new ConstructorExecutionJoinPointRedefiner(compilationInfo).compile();
122             case JoinPointType.CONSTRUCTOR_CALL_INT:
123                 return new ConstructorCallJoinPointRedefiner(compilationInfo).compile();
124             case JoinPointType.FIELD_SET_INT:
125                 return new FieldSetJoinPointRedefiner(compilationInfo).compile();
126             case JoinPointType.FIELD_GET_INT:
127                 return new FieldGetJoinPointRedefiner(compilationInfo).compile();
128             case JoinPointType.HANDLER_INT:
129                 return new HandlerJoinPointRedefiner(compilationInfo).compile();
130             default:
131                 throw new UnsupportedOperationException JavaDoc(
132                         "join point type is not supported: " +
133                         compilationInfo.getInitialModel().getEmittedJoinPoint().getJoinPointType()
134                 );
135         }
136     }
137
138     /**
139      * Returns a list with all the join point compilers that matches a specific pointcut expression.
140      * <p/>
141      * To be used for redefinition of the join point compilers only. This since the compilers must have been created
142      * in advance to exist in the repository (which is done when the target class is loaded).
143      *
144      * @param expression the pointcut expression
145      * @return a set with the matching emitted join point
146      */

147     public static Set JavaDoc getJoinPointsMatching(final ExpressionInfo expression) {
148         final Set JavaDoc matchingJoinPointInfos = new HashSet JavaDoc();
149         for (Iterator JavaDoc it = COMPILATION_INFO_REPOSITORY.entrySet().iterator(); it.hasNext();) {
150             final Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
151
152             final Class JavaDoc clazz = (Class JavaDoc) entry.getKey();
153             final CompilationInfo compilationInfo = (CompilationInfo) entry.getValue();
154             final EmittedJoinPoint joinPoint = (EmittedJoinPoint) compilationInfo.
155                     getInitialModel().getEmittedJoinPoint();
156             final ClassLoader JavaDoc loader = clazz.getClassLoader();
157
158             final ClassInfo calleeClassInfo = AsmClassInfo.getClassInfo(joinPoint.getCalleeClassName(), loader);
159             final ClassInfo callerClassInfo = AsmClassInfo.getClassInfo(joinPoint.getCallerClassName(), loader);
160             final MethodInfo callerMethodInfo = getCallerMethodInfo(callerClassInfo, joinPoint);
161
162             ExpressionContext ctx = null;
163             switch (joinPoint.getJoinPointType()) {
164                 case JoinPointType.METHOD_EXECUTION_INT:
165                     ctx = new ExpressionContext(
166                             PointcutType.EXECUTION,
167                             calleeClassInfo.getMethod(joinPoint.getJoinPointHash()),
168                             callerMethodInfo
169                     );
170                     break;
171                 case JoinPointType.METHOD_CALL_INT:
172                     ctx = new ExpressionContext(
173                             PointcutType.CALL,
174                             calleeClassInfo.getMethod(joinPoint.getJoinPointHash()),
175                             callerMethodInfo
176                     );
177                     break;
178                 case JoinPointType.CONSTRUCTOR_EXECUTION_INT:
179                     ctx = new ExpressionContext(
180                             PointcutType.EXECUTION,
181                             calleeClassInfo.getConstructor(joinPoint.getJoinPointHash()),
182                             callerMethodInfo
183                     );
184                     break;
185                 case JoinPointType.CONSTRUCTOR_CALL_INT:
186                     ctx = new ExpressionContext(
187                             PointcutType.CALL,
188                             calleeClassInfo.getConstructor(joinPoint.getJoinPointHash()),
189                             callerMethodInfo
190                     );
191                     break;
192                 case JoinPointType.FIELD_SET_INT:
193                     ctx = new ExpressionContext(
194                             PointcutType.SET,
195                             calleeClassInfo.getField(joinPoint.getJoinPointHash()),
196                             callerMethodInfo
197                     );
198                     break;
199                 case JoinPointType.FIELD_GET_INT:
200                     ctx = new ExpressionContext(
201                             PointcutType.GET,
202                             calleeClassInfo.getField(joinPoint.getJoinPointHash()),
203                             callerMethodInfo
204                     );
205                     break;
206                 case JoinPointType.HANDLER_INT:
207                     ctx = new ExpressionContext(
208                             PointcutType.HANDLER,
209                             AsmClassInfo.getClassInfo(joinPoint.getCalleeClassName(), loader),
210                             callerMethodInfo
211                     );
212                     break;
213                 case JoinPointType.STATIC_INITIALIZATION_INT:
214                     ctx = new ExpressionContext(
215                             PointcutType.STATIC_INITIALIZATION,
216                             calleeClassInfo.staticInitializer(),
217                             calleeClassInfo
218                     );
219             }
220             if (expression.getExpression().match(ctx)) {
221                 matchingJoinPointInfos.add(new MatchingJoinPointInfo(clazz, compilationInfo, ctx));
222             }
223         }
224         return matchingJoinPointInfos;
225     }
226
227     /**
228      * Returns the emitted join point structure for a specific JIT generated join point class.
229      *
230      * @param clazz the join point class
231      * @return the emitted join point structure
232      */

233     public static EmittedJoinPoint getEmittedJoinPoint(final Class JavaDoc clazz) {
234         return (EmittedJoinPoint) COMPILATION_INFO_REPOSITORY.get(clazz);
235     }
236
237     /**
238      * Grabs the caller method info.
239      *
240      * @param callerClassInfo
241      * @param emittedJoinPoint
242      * @return
243      */

244     private static MethodInfo getCallerMethodInfo(final ClassInfo callerClassInfo,
245                                                   final EmittedJoinPoint emittedJoinPoint) {
246         MethodInfo callerMethodInfo = null;
247         MethodInfo[] callerMethods = callerClassInfo.getMethods();
248         for (int i = 0; i < callerMethods.length; i++) {
249             MethodInfo method = callerMethods[i];
250             if (method.getName().equals(emittedJoinPoint.getCallerMethodName()) &&
251                 method.getSignature().equals(emittedJoinPoint.getCallerMethodDesc())) {
252                 callerMethodInfo = method;
253                 break;
254             }
255         }
256         return callerMethodInfo;
257     }
258 }
259
Popular Tags