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.joinpoint.management;
9
10 import gnu.trove.TLongObjectHashMap;
11 import org.codehaus.aspectwerkz.AspectSystem;
12 import org.codehaus.aspectwerkz.AdviceInfo;
13 import org.codehaus.aspectwerkz.aspect.management.AspectManager;
14 import org.codehaus.aspectwerkz.aspect.management.AspectRegistry;
15 import org.codehaus.aspectwerkz.aspect.management.Pointcut;
16 import org.codehaus.aspectwerkz.expression.ExpressionContext;
17 import org.codehaus.aspectwerkz.expression.PointcutType;
18 import org.codehaus.aspectwerkz.reflect.ClassInfo;
19 import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
20 import org.codehaus.aspectwerkz.reflect.FieldInfo;
21 import org.codehaus.aspectwerkz.reflect.MethodInfo;
22 import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
23 import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo;
24 import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfoRepository;
25 import org.codehaus.aspectwerkz.reflect.impl.java.JavaConstructorInfo;
26 import org.codehaus.aspectwerkz.reflect.impl.java.JavaFieldInfo;
27 import org.codehaus.aspectwerkz.reflect.impl.java.JavaMethodInfo;
28
29 import java.lang.reflect.Constructor;
30 import java.lang.reflect.Method;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36
37 /***
38 * Manages the registration of join points and advices for these join points.
39 *
40 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
41 */
42 public class JoinPointRegistry {
43 /***
44 * Pre allocated empty array list.
45 */
46 private static final List EMTPY_ARRAY_LIST = new ArrayList();
47
48 /***
49 * The registry with all the classes and the index for the advices attatched to the join points in this class.
50 * <p/>Map of: the class hash => map of: join point hash => map of: join point type => array with advice indexes.
51 */
52 private static final TLongObjectHashMap m_joinPointMetaDataMap = new TLongObjectHashMap();
53
54 /***
55 * The registry with all the classes and the index for the cflow expressions attatched to the join points in this
56 * class. <p/>Map of: the class hash => map of: join point hash => map of: join point type => array cflow
57 * expressions.
58 */
59 private static final TLongObjectHashMap m_joinPointCflowExpressionMap = new TLongObjectHashMap();
60
61 /***
62 * Registers the advices for the method join point.
63 *
64 * @param joinPointType
65 * @param joinPointHash
66 * @param signature
67 * @param classHash
68 * @param declaringClass
69 * @param withinInfo
70 * @param system
71 * @TODO: cache the metadata created in the method - map it to the method hash (see pointcut for caching)
72 */
73 public void registerJoinPoint(final int joinPointType,
74 final int joinPointHash,
75 final String signature,
76 final int classHash,
77 final Class declaringClass,
78 final ReflectionInfo withinInfo,
79 final AspectSystem system) {
80 if (!m_joinPointMetaDataMap.containsKey(classHash)) {
81 m_joinPointMetaDataMap.put(classHash, new TLongObjectHashMap());
82 }
83 Map joinPointMetaDataMap = new HashMap();
84 joinPointMetaDataMap.put(PointcutType.EXECUTION, EMTPY_ARRAY_LIST);
85 joinPointMetaDataMap.put(PointcutType.CALL, EMTPY_ARRAY_LIST);
86 joinPointMetaDataMap.put(PointcutType.SET, EMTPY_ARRAY_LIST);
87 joinPointMetaDataMap.put(PointcutType.GET, EMTPY_ARRAY_LIST);
88 joinPointMetaDataMap.put(PointcutType.HANDLER, EMTPY_ARRAY_LIST);
89 joinPointMetaDataMap.put(PointcutType.STATIC_INITIALIZATION, EMTPY_ARRAY_LIST);
90
91 ((TLongObjectHashMap) m_joinPointMetaDataMap.get(classHash)).put(joinPointHash, joinPointMetaDataMap);
92 switch (joinPointType) {
93 case JoinPointType.METHOD_EXECUTION:
94 Method wrapperMethod = AspectRegistry.getMethodTuple(declaringClass, joinPointHash).getWrapperMethod();
95 MethodInfo methodInfo = JavaMethodInfo.getMethodInfo(wrapperMethod);
96 registerJoinPoint(
97 PointcutType.EXECUTION, system, methodInfo, methodInfo
98 );
99 break;
100 case JoinPointType.METHOD_CALL:
101 wrapperMethod = AspectRegistry.getMethodTuple(declaringClass, joinPointHash).getWrapperMethod();
102 methodInfo = JavaMethodInfo.getMethodInfo(wrapperMethod);
103 registerJoinPoint(PointcutType.CALL, system, methodInfo, withinInfo, joinPointMetaDataMap);
104 break;
105 case JoinPointType.CONSTRUCTOR_EXECUTION:
106 Constructor wrapperConstructor = AspectRegistry.getConstructorTuple(declaringClass, joinPointHash)
107 .getWrapperConstructor();
108 ConstructorInfo constructorInfo = JavaConstructorInfo.getConstructorInfo(wrapperConstructor);
109 registerJoinPoint(
110 PointcutType.EXECUTION, system, constructorInfo, constructorInfo
111 );
112 break;
113 case JoinPointType.CONSTRUCTOR_CALL:
114 wrapperConstructor = AspectRegistry.getConstructorTuple(declaringClass, joinPointHash)
115 .getWrapperConstructor();
116 constructorInfo = JavaConstructorInfo.getConstructorInfo(wrapperConstructor);
117 registerJoinPoint(PointcutType.CALL, system, constructorInfo, withinInfo, joinPointMetaDataMap);
118 break;
119 case JoinPointType.FIELD_SET:
120 FieldInfo fieldInfo = JavaFieldInfo
121 .getFieldInfo(AspectRegistry.getField(declaringClass, joinPointHash));
122 registerJoinPoint(PointcutType.SET, system, fieldInfo, withinInfo, joinPointMetaDataMap);
123 break;
124 case JoinPointType.FIELD_GET:
125 fieldInfo = JavaFieldInfo.getFieldInfo(AspectRegistry.getField(declaringClass, joinPointHash));
126 registerJoinPoint(PointcutType.GET, system, fieldInfo, withinInfo, joinPointMetaDataMap);
127 break;
128 case JoinPointType.HANDLER:
129 registerJoinPoint(
130 PointcutType.HANDLER,
131 system,
132 createClassInfo(declaringClass),
133 withinInfo,
134 joinPointMetaDataMap
135 );
136 break;
137 case JoinPointType.STATIC_INITALIZATION:
138 throw new UnsupportedOperationException("not implemented");
139 default:
140 throw new RuntimeException("join point type not valid");
141 }
142 }
143
144 /***
145 * Returns the keys to the advices for the join point.
146 *
147 * @param classHash
148 * @param joinPointHash
149 * @return the advices attached to the join point
150 */
151 public Map getJoinPointMetaData(final long classHash, final long joinPointHash) {
152 TLongObjectHashMap joinPoints = (TLongObjectHashMap) m_joinPointMetaDataMap.get(classHash);
153 return (Map) joinPoints.get(joinPointHash);
154 }
155
156 /***
157 * Returns the keys to the advices for the join point.
158 *
159 * @param classHash
160 * @param joinPointHash
161 * @return the advices attached to the join point
162 */
163 public Map getCflowPointcutsForJoinPoint(final long classHash, final long joinPointHash) {
164 TLongObjectHashMap joinPoints = (TLongObjectHashMap) m_joinPointCflowExpressionMap.get(classHash);
165 return (Map) joinPoints.get(joinPointHash);
166 }
167
168 /***
169 * Resets the registry.
170 *
171 * @param classHash
172 * @TODO do better RW/RuW/JPredef eWorld brute force reset Needed since JoinPointRegistry is somehow a singleton
173 * (static in JoinPointManager)
174 */
175 public void reset(final int classHash) {
176 m_joinPointMetaDataMap.remove(classHash);
177 m_joinPointCflowExpressionMap.remove(classHash);
178 }
179
180 /***
181 * Creates a class info instance out of a class instance.
182 *
183 * @param klass
184 * @return class info
185 */
186 private ClassInfo createClassInfo(final Class klass) {
187 ClassInfo classInfo = JavaClassInfoRepository.getRepository(klass.getClassLoader()).getClassInfo(
188 klass.getName()
189 );
190 if (classInfo == null) {
191 classInfo = JavaClassInfo.getClassInfo(klass);
192 }
193 return classInfo;
194 }
195
196 /***
197 * Register field get join points.
198 *
199 * @param type
200 * @param system
201 * @param reflectInfo
202 * @param withinInfo
203 * @param joinPointMetaDataMap
204 */
205 private void registerJoinPoint(final PointcutType type,
206 final AspectSystem system,
207 final ReflectionInfo reflectInfo,
208 final ReflectionInfo withinInfo,
209 final Map joinPointMetaDataMap) {
210 List adviceIndexInfoList = new ArrayList();
211 List cflowExpressionList = new ArrayList();
212 Pointcut cflowPointcut = null;
213 ExpressionContext ctx = new ExpressionContext(type, reflectInfo, withinInfo);
214 AspectManager[] aspectManagers = system.getAspectManagers();
215 for (int i = 0; i < aspectManagers.length; i++) {
216 AspectManager aspectManager = aspectManagers[i];
217
218
219 if (cflowPointcut == null) {
220 List cflowPointcuts = aspectManager.getCflowPointcuts(ctx);
221 if (!cflowPointcuts.isEmpty()) {
222 cflowPointcut = (Pointcut) cflowPointcuts.get(0);
223 }
224 }
225
226
227 for (Iterator it = aspectManager.getPointcuts(ctx).iterator(); it.hasNext();) {
228 Pointcut pointcut = (Pointcut) it.next();
229 AdviceInfo[] aroundAdviceIndexes = pointcut.getAroundAdviceIndexes();
230 AdviceInfo[] beforeAdviceIndexes = pointcut.getBeforeAdviceIndexes();
231 AdviceInfo[] afterAdviceIndexes = pointcut.getAfterFinallyAdviceIndexes();
232
233 AdviceIndexInfo adviceIndexInfo = new AdviceIndexInfo(
234 aroundAdviceIndexes,
235 pointcut.getBeforeAdviceIndexes(),
236 pointcut.getAfterFinallyAdviceIndexes(),
237 pointcut.getAfterReturningAdviceIndexes(),
238 pointcut.getAfterThrowingAdviceIndexes()
239 );
240
241
242
243
244
245
246 pointcut.getExpressionInfo().getArgsIndexMapper().match(ctx);
247
248
249
250 for (int j = 0; j < beforeAdviceIndexes.length; j++) {
251 AdviceInfo indexTuple = beforeAdviceIndexes[j];
252 String adviceName = pointcut.getBeforeAdviceName(j);
253
254
255 String[] adviceArgNames = JoinPointMetaData.getParameterNames(adviceName);
256
257
258 int[] adviceToTargetArgs = new int[adviceArgNames.length];
259 for (int k = 0; k < adviceArgNames.length; k++) {
260 String adviceArgName = adviceArgNames[k];
261 int exprArgIndex = pointcut.getExpressionInfo().getArgumentIndex(adviceArgName);
262 if (exprArgIndex >= 0 && ctx.m_exprIndexToTargetIndex.containsKey(exprArgIndex)) {
263 adviceToTargetArgs[k] = ctx.m_exprIndexToTargetIndex.get(exprArgIndex);
264 } else {
265 adviceToTargetArgs[k] = -1;
266 }
267 }
268
269
270
271
272
273 indexTuple.setMethodToArgIndexes(adviceToTargetArgs);
274 }
275 for (int j = 0; j < afterAdviceIndexes.length; j++) {
276 AdviceInfo indexTuple = afterAdviceIndexes[j];
277 String adviceName = pointcut.getAfterFinallyAdviceName(j);
278
279
280 String[] adviceArgNames = JoinPointMetaData.getParameterNames(adviceName);
281
282
283 int[] adviceToTargetArgs = new int[adviceArgNames.length];
284 for (int k = 0; k < adviceArgNames.length; k++) {
285 String adviceArgName = adviceArgNames[k];
286 int exprArgIndex = pointcut.getExpressionInfo().getArgumentIndex(adviceArgName);
287 if (exprArgIndex >= 0 && ctx.m_exprIndexToTargetIndex.containsKey(exprArgIndex)) {
288 adviceToTargetArgs[k] = ctx.m_exprIndexToTargetIndex.get(exprArgIndex);
289 } else {
290 adviceToTargetArgs[k] = -1;
291 }
292 }
293
294
295
296
297
298 indexTuple.setMethodToArgIndexes(adviceToTargetArgs);
299 }
300
301 for (int j = 0; j < aroundAdviceIndexes.length; j++) {
302 AdviceInfo indexTuple = aroundAdviceIndexes[j];
303 String adviceName = pointcut.getAroundAdviceName(j);
304
305
306 String[] adviceArgNames = JoinPointMetaData.getParameterNames(adviceName);
307
308
309 int[] adviceToTargetArgs = new int[adviceArgNames.length];
310 for (int k = 0; k < adviceArgNames.length; k++) {
311 String adviceArgName = adviceArgNames[k];
312 int exprArgIndex = pointcut.getExpressionInfo().getArgumentIndex(adviceArgName);
313 if (exprArgIndex >= 0 && ctx.m_exprIndexToTargetIndex.containsKey(exprArgIndex)) {
314 adviceToTargetArgs[k] = ctx.m_exprIndexToTargetIndex.get(exprArgIndex);
315 } else {
316 adviceToTargetArgs[k] = -1;
317 }
318 }
319
320
321
322
323
324 indexTuple.setMethodToArgIndexes(adviceToTargetArgs);
325 }
326
327 adviceIndexInfoList.add(adviceIndexInfo);
328
329
330 if (pointcut.getExpressionInfo().hasCflowPointcut()) {
331 cflowExpressionList.add(pointcut.getExpressionInfo().getCflowExpressionRuntime());
332 }
333 }
334 }
335
336
337 AdviceIndexInfo[] adviceIndexInfo = new AdviceIndexInfo[adviceIndexInfoList.size()];
338 int i = 0;
339 for (Iterator iterator = adviceIndexInfoList.iterator(); iterator.hasNext(); i++) {
340 adviceIndexInfo[i] = (AdviceIndexInfo) iterator.next();
341 }
342 JoinPointMetaData metaData = new JoinPointMetaData();
343 metaData.adviceIndexes = adviceIndexInfo;
344 metaData.cflowExpressions = cflowExpressionList;
345 metaData.cflowPointcut = cflowPointcut;
346 metaData.expressionContext = ctx;
347 joinPointMetaDataMap.put(type, metaData);
348 }
349 }