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 org.codehaus.aspectwerkz.AspectSystem;
11 import org.codehaus.aspectwerkz.AdviceInfo;
12 import org.codehaus.aspectwerkz.util.Strings;
13 import org.codehaus.aspectwerkz.aspect.management.AspectManager;
14 import org.codehaus.aspectwerkz.aspect.management.Pointcut;
15 import org.codehaus.aspectwerkz.expression.ExpressionContext;
16 import org.codehaus.aspectwerkz.expression.PointcutType;
17 import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
18
19 import java.util.ArrayList;
20 import java.util.Iterator;
21 import java.util.List;
22
23 /***
24 * Holds and creates meta data about a specific join point.
25 *
26 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
27 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
28 */
29 public class JoinPointMetaData {
30 /***
31 * The indexes for the advices.
32 */
33 public AdviceIndexInfo[] adviceIndexes;
34
35 /***
36 * The cflow expressions runtime.
37 */
38 public List cflowExpressions;
39
40 /***
41 * The cflow pointcut.
42 */
43 public Pointcut cflowPointcut;
44
45 /***
46 * The join point expression context
47 */
48 public ExpressionContext expressionContext;
49
50 /***
51 * Retrieves the join point metadata.
52 *
53 * @param type
54 * @param system
55 * @param reflectInfo
56 * @param withinInfo
57 */
58 public static JoinPointMetaData getJoinPointMetaData(final PointcutType type,
59 final AspectSystem system,
60 final ReflectionInfo reflectInfo,
61 final ReflectionInfo withinInfo) {
62
63 List adviceIndexInfoList = new ArrayList();
64 List cflowExpressionList = new ArrayList();
65 Pointcut cflowPointcut = null;
66
67 ExpressionContext ctx = new ExpressionContext(type, reflectInfo, withinInfo);
68 AspectManager[] aspectManagers = system.getAspectManagers();
69 for (int i = 0; i < aspectManagers.length; i++) {
70 AspectManager aspectManager = aspectManagers[i];
71
72
73 if (cflowPointcut == null) {
74 List cflowPointcuts = aspectManager.getCflowPointcuts(ctx);
75 if (!cflowPointcuts.isEmpty()) {
76 cflowPointcut = (Pointcut) cflowPointcuts.get(0);
77 }
78 }
79
80
81 for (Iterator it = aspectManager.getPointcuts(ctx).iterator(); it.hasNext();) {
82 Pointcut pointcut = (Pointcut) it.next();
83
84 AdviceInfo[] aroundAdviceIndexes = pointcut.getAroundAdviceIndexes();
85 AdviceInfo[] beforeAdviceIndexes = pointcut.getBeforeAdviceIndexes();
86 AdviceInfo[] afterFinallyAdviceIndexes = pointcut.getAfterFinallyAdviceIndexes();
87 AdviceInfo[] afterReturningAdviceIndexes = pointcut.getAfterReturningAdviceIndexes();
88 AdviceInfo[] afterThrowingAdviceIndexes = pointcut.getAfterThrowingAdviceIndexes();
89
90 AdviceIndexInfo adviceIndexInfo = new AdviceIndexInfo(
91 aroundAdviceIndexes,
92 beforeAdviceIndexes,
93 afterFinallyAdviceIndexes,
94 afterReturningAdviceIndexes,
95 afterThrowingAdviceIndexes
96 );
97
98
99
100
101 pointcut.getExpressionInfo().getArgsIndexMapper().match(ctx);
102
103
104
105
106 for (int j = 0; j < aroundAdviceIndexes.length; j++) {
107 setMethodArgumentIndexes(pointcut.getAroundAdviceName(j), pointcut, ctx, aroundAdviceIndexes[j]);
108 }
109
110 for (int j = 0; j < beforeAdviceIndexes.length; j++) {
111 setMethodArgumentIndexes(pointcut.getBeforeAdviceName(j), pointcut, ctx, beforeAdviceIndexes[j]);
112 }
113
114 for (int j = 0; j < afterFinallyAdviceIndexes.length; j++) {
115 setMethodArgumentIndexes(
116 pointcut.getAfterFinallyAdviceName(j), pointcut, ctx, afterFinallyAdviceIndexes[j]
117 );
118 }
119
120 for (int j = 0; j < afterReturningAdviceIndexes.length; j++) {
121 setMethodArgumentIndexes(
122 pointcut.getAfterReturningAdviceName(j), pointcut, ctx, afterReturningAdviceIndexes[j]
123 );
124 }
125
126 for (int j = 0; j < afterThrowingAdviceIndexes.length; j++) {
127 setMethodArgumentIndexes(
128 pointcut.getAfterThrowingAdviceName(j), pointcut, ctx, afterThrowingAdviceIndexes[j]
129 );
130
131 }
132
133 adviceIndexInfoList.add(adviceIndexInfo);
134
135
136 if (pointcut.getExpressionInfo().hasCflowPointcut()) {
137 cflowExpressionList.add(pointcut.getExpressionInfo().getCflowExpressionRuntime());
138 }
139 }
140 }
141
142
143 AdviceIndexInfo[] adviceIndexInfo = new AdviceIndexInfo[adviceIndexInfoList.size()];
144 int i = 0;
145 for (Iterator iterator = adviceIndexInfoList.iterator(); iterator.hasNext(); i++) {
146 adviceIndexInfo[i] = (AdviceIndexInfo) iterator.next();
147 }
148 JoinPointMetaData metaData = new JoinPointMetaData();
149 metaData.adviceIndexes = adviceIndexInfo;
150 metaData.cflowExpressions = cflowExpressionList;
151 metaData.cflowPointcut = cflowPointcut;
152 metaData.expressionContext = ctx;
153 return metaData;
154 }
155
156 /***
157 * Get the parameter names from a "method declaration" signature like pc(type a, type2 b) => 0:a, 1:b
158 *
159 * @param expression
160 * @return the parameter names
161 */
162 public static String[] getParameterNames(final String expression) {
163 int paren = expression.indexOf('(');
164 List paramNames = new ArrayList();
165 if (paren > 0) {
166 String params = expression.substring(paren + 1, expression.lastIndexOf(')')).trim();
167 String[] javaParameters = Strings.splitString(params, ",");
168 for (int i = 0; i < javaParameters.length; i++) {
169 String javaParameter = Strings.replaceSubString(javaParameters[i], " ", " ").trim();
170 String[] paramInfo = Strings.splitString(javaParameter, " ");
171 paramNames.add(paramInfo[1]);
172 }
173 }
174 String[] paramNamesArray = new String[paramNames.size()];
175 int index = 0;
176 for (Iterator it = paramNames.iterator(); it.hasNext(); index++) {
177 paramNamesArray[index] = (String) it.next();
178 }
179 return paramNamesArray;
180 }
181
182 /***
183 * Sets the method argument indexes.
184 *
185 * @param adviceName
186 * @param pointcut
187 * @param ctx
188 * @param indexTuple
189 */
190 private static void setMethodArgumentIndexes(final String adviceName,
191 final Pointcut pointcut,
192 final ExpressionContext ctx,
193 final AdviceInfo indexTuple) {
194
195 String[] adviceArgNames = JoinPointMetaData.getParameterNames(adviceName);
196
197
198 int[] adviceToTargetArgs = new int[adviceArgNames.length];
199 for (int k = 0; k < adviceArgNames.length; k++) {
200 String adviceArgName = adviceArgNames[k];
201 int exprArgIndex = pointcut.getExpressionInfo().getArgumentIndex(adviceArgName);
202 if (exprArgIndex >= 0 && ctx.m_exprIndexToTargetIndex.containsKey(exprArgIndex)) {
203 adviceToTargetArgs[k] = ctx.m_exprIndexToTargetIndex.get(exprArgIndex);
204 } else {
205 adviceToTargetArgs[k] = -1;
206 }
207 }
208 indexTuple.setMethodToArgIndexes(adviceToTargetArgs);
209 }
210
211 }