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.definition;
9
10 import org.codehaus.aspectwerkz.expression.ExpressionInfo;
11 import org.codehaus.aspectwerkz.expression.ExpressionNamespace;
12 import org.codehaus.aspectwerkz.expression.regexp.Pattern;
13 import org.codehaus.aspectwerkz.util.Strings;
14 import org.codehaus.aspectwerkz.aspect.AdviceType;
15 import org.codehaus.aspectwerkz.DeploymentModel;
16 import org.codehaus.aspectwerkz.reflect.MethodInfo;
17 import org.codehaus.aspectwerkz.reflect.ClassInfo;
18 import org.codehaus.aspectwerkz.exception.DefinitionException;
19
20 import java.util.Iterator;
21 import java.util.Collection;
22
23 /***
24 * Helper class for the attribute and the XML definition parsers.
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 DefinitionParserHelper {
30 public static final String EXPRESSION_PREFIX = "AW_";
31
32 /***
33 * Creates and adds pointcut definition to aspect definition.
34 *
35 * @param name
36 * @param expression
37 * @param aspectDef
38 */
39 public static void createAndAddPointcutDefToAspectDef(final String name,
40 final String expression,
41 final AspectDefinition aspectDef) {
42 PointcutDefinition pointcutDef = new PointcutDefinition(expression);
43 aspectDef.addPointcutDefinition(pointcutDef);
44
45
46
47
48
49 String pointcutName = name;
50 String pointcutCallSignature = null;
51 if (name.indexOf("(") > 0) {
52 pointcutName = name.substring(0, name.indexOf("("));
53 pointcutCallSignature = name.substring(name.indexOf("(") + 1, name.lastIndexOf(")"));
54 }
55
56
57
58
59 ExpressionNamespace namespace = ExpressionNamespace.getNamespace(aspectDef.getQualifiedName());
60 ExpressionInfo info = namespace.getExpressionInfoOrNull(pointcutName);
61 if (info == null) {
62 info = new ExpressionInfo(expression, aspectDef.getQualifiedName());
63
64 if (pointcutCallSignature != null) {
65 String[] parameters = Strings.splitString(pointcutCallSignature, ",");
66 for (int i = 0; i < parameters.length; i++) {
67 String[] parameterInfo = Strings.splitString(
68 Strings.replaceSubString(parameters[i].trim(), " ", " "),
69 " "
70 );
71 info.addArgument(parameterInfo[1], parameterInfo[0], aspectDef.getClassInfo().getClassLoader());
72 }
73 }
74 }
75 ExpressionNamespace.getNamespace(aspectDef.getQualifiedName()).addExpressionInfo(pointcutName, info);
76 }
77
78 /***
79 * Creates and adds a prepared pointcut definition to virtual aspect definition.
80 *
81 * @param name
82 * @param expression
83 * @param systemDef
84 */
85 public static void createAndAddDeploymentScopeDef(final String name,
86 final String expression,
87 final SystemDefinition systemDef) {
88 AspectDefinition aspectDef = systemDef.getAspectDefinition(Virtual.class.getName());
89 aspectDef.addPointcutDefinition(new PointcutDefinition(expression));
90 systemDef.addDeploymentScope(new DeploymentScope(name, expression));
91 }
92
93 /***
94 * Creates and adds an advisable definition to virtual aspect definition.
95 *
96 * @param expression
97 * @param systemDef
98 */
99 public static void createAndAddAdvisableDef(final String expression, final SystemDefinition systemDef) {
100 AspectDefinition virtualAspectDef = systemDef.getAspectDefinition(Virtual.class.getName());
101 virtualAspectDef.addPointcutDefinition(new PointcutDefinition(expression));
102
103 AdviceDefinition virtualAdviceDef = (AdviceDefinition) virtualAspectDef.getBeforeAdviceDefinitions().get(0);
104 ExpressionInfo oldExpressionInfo = virtualAdviceDef.getExpressionInfo();
105 String newExpression;
106 if (oldExpressionInfo != null) {
107 String oldExpression = oldExpressionInfo.toString();
108 newExpression = oldExpression + " || " + expression;
109 } else {
110 newExpression = expression;
111 }
112
113 virtualAdviceDef.setExpressionInfo(
114 new ExpressionInfo(
115 newExpression,
116 virtualAspectDef.getQualifiedName()
117 )
118 );
119 }
120
121 /***
122 * Attaches all deployment scopes in a system to the virtual advice.
123 *
124 * @param systemDef the system definition
125 */
126 public static void attachDeploymentScopeDefsToVirtualAdvice(final SystemDefinition systemDef) {
127 final AspectDefinition virtualAspectDef = systemDef.getAspectDefinition(Virtual.class.getName());
128 final AdviceDefinition virtualAdviceDef = (AdviceDefinition) virtualAspectDef.getBeforeAdviceDefinitions().get(
129 0
130 );
131
132 final StringBuffer newExpression = new StringBuffer();
133 final ExpressionInfo oldExpressionInfo = virtualAdviceDef.getExpressionInfo();
134 if (oldExpressionInfo != null) {
135 String oldExpression = oldExpressionInfo.toString();
136 newExpression.append(oldExpression);
137 }
138 final Collection deploymentScopes = systemDef.getDeploymentScopes();
139 if (deploymentScopes.size() != 0 && oldExpressionInfo != null) {
140 newExpression.append(" || ");
141 }
142 for (Iterator it = deploymentScopes.iterator(); it.hasNext();) {
143 DeploymentScope deploymentScope = (DeploymentScope) it.next();
144 newExpression.append(deploymentScope.getExpression());
145 if (it.hasNext()) {
146 newExpression.append(" || ");
147 }
148 }
149 if (newExpression.length() != 0) {
150 virtualAdviceDef.setExpressionInfo(
151 new ExpressionInfo(
152 newExpression.toString(),
153 virtualAspectDef.getQualifiedName()
154 )
155 );
156 }
157 }
158
159 /***
160 * Creates and add mixin definition to system definition.
161 *
162 * @param mixinClassInfo
163 * @param expression
164 * @param deploymentModel
165 * @param isTransient
166 * @param systemDef
167 * @return the mixin definition
168 */
169 public static MixinDefinition createAndAddMixinDefToSystemDef(final ClassInfo mixinClassInfo,
170 final String expression,
171 final DeploymentModel deploymentModel,
172 final boolean isTransient,
173 final SystemDefinition systemDef) {
174 final MixinDefinition mixinDef = createMixinDefinition(
175 mixinClassInfo,
176 expression,
177 deploymentModel,
178 isTransient,
179 systemDef
180 );
181
182
183 MixinDefinition doublon = null;
184 for (Iterator intros = systemDef.getMixinDefinitions().iterator(); intros.hasNext();) {
185 MixinDefinition intro = (MixinDefinition) intros.next();
186 if (intro.getMixinImpl().getName().equals(mixinDef.getMixinImpl().getName())) {
187 doublon = intro;
188 intro.addExpressionInfos(mixinDef.getExpressionInfos());
189 break;
190 }
191 }
192 if (doublon == null) {
193 systemDef.addMixinDefinition(mixinDef);
194 }
195 return mixinDef;
196 }
197
198 /***
199 * Creates and add interface introduction definition to aspect definition.
200 *
201 * @param expression
202 * @param introductionName
203 * @param interfaceClassName
204 * @param aspectDef
205 */
206 public static void createAndAddInterfaceIntroductionDefToAspectDef(final String expression,
207 final String introductionName,
208 final String interfaceClassName,
209 final AspectDefinition aspectDef) {
210
211 InterfaceIntroductionDefinition introDef = createInterfaceIntroductionDefinition(
212 introductionName,
213 expression,
214 interfaceClassName,
215 aspectDef
216 );
217 aspectDef.addInterfaceIntroductionDefinition(introDef);
218 }
219
220 /***
221 * Creates a new advice definition.
222 *
223 * @param adviceName the advice name
224 * @param adviceType the advice type
225 * @param expression the advice expression
226 * @param specialArgumentType the arg
227 * @param aspectName the aspect name
228 * @param aspectClassName the aspect class name
229 * @param methodInfo the advice methodInfo
230 * @param aspectDef the aspect definition
231 * @return the new advice definition
232 */
233 public static AdviceDefinition createAdviceDefinition(final String adviceName,
234 final AdviceType adviceType,
235 final String expression,
236 final String specialArgumentType,
237 final String aspectName,
238 final String aspectClassName,
239 final MethodInfo methodInfo,
240 final AspectDefinition aspectDef) {
241 ExpressionInfo expressionInfo = new ExpressionInfo(
242 expression,
243 aspectDef.getQualifiedName()
244 );
245
246
247 String adviceCallSignature = null;
248 String resolvedSpecialArgumentType = specialArgumentType;
249 if (adviceName.indexOf('(') > 0) {
250 adviceCallSignature = adviceName.substring(adviceName.indexOf('(') + 1, adviceName.lastIndexOf(')'));
251 String[] parameters = Strings.splitString(adviceCallSignature, ",");
252 for (int i = 0; i < parameters.length; i++) {
253 String[] parameterInfo = Strings.splitString(
254 Strings.replaceSubString(parameters[i].trim(), " ", " "),
255 " "
256 );
257
258
259
260 String paramName, paramType = null;
261 if (parameterInfo.length == 2) {
262 paramName = parameterInfo[1];
263 paramType = parameterInfo[0];
264 } else {
265 paramName = "anonymous_" + i;
266 paramType = (String) Pattern.ABBREVIATIONS.get(parameterInfo[0]);
267 }
268
269 if (paramName.equals(specialArgumentType)) {
270 resolvedSpecialArgumentType = paramType;
271 expressionInfo.setSpecialArgumentName(paramName);
272 } else {
273 expressionInfo.addArgument(paramName, paramType, aspectDef.getClassInfo().getClassLoader());
274 }
275 }
276 }
277
278
279 if (adviceType.equals(AdviceType.AROUND)) {
280 if (!"java.lang.Object".equals(methodInfo.getReturnType().getName())) {
281 throw new DefinitionException(
282 "around advice must return java.lang.Object : " + aspectClassName + "." + methodInfo.getName()
283 );
284 }
285 }
286
287 final AdviceDefinition adviceDef = new AdviceDefinition(
288 adviceName,
289 adviceType,
290 resolvedSpecialArgumentType,
291 aspectName,
292 aspectClassName,
293 expressionInfo,
294 methodInfo,
295 aspectDef
296 );
297 return adviceDef;
298 }
299
300 /***
301 * Creates an introduction definition.
302 *
303 * @param mixinClassInfo
304 * @param expression
305 * @param deploymentModel
306 * @param isTransient
307 * @param systemDef
308 * @return
309 */
310 public static MixinDefinition createMixinDefinition(final ClassInfo mixinClassInfo,
311 final String expression,
312 final DeploymentModel deploymentModel,
313 final boolean isTransient,
314 final SystemDefinition systemDef) {
315 final MixinDefinition mixinDef = new MixinDefinition(mixinClassInfo, deploymentModel, isTransient, systemDef);
316 if (expression != null) {
317 ExpressionInfo expressionInfo = new ExpressionInfo(expression, systemDef.getUuid());
318
319
320 ExpressionNamespace.getNamespace(systemDef.getUuid()).addExpressionInfo(
321 EXPRESSION_PREFIX + expression.hashCode(),
322 expressionInfo
323 );
324 mixinDef.addExpressionInfo(expressionInfo);
325 }
326 return mixinDef;
327 }
328
329 /***
330 * Creates a new interface introduction definition.
331 *
332 * @param introductionName the introduction name
333 * @param expression the pointcut expression
334 * @param interfaceClassName the class name of the interface
335 * @param aspectDef the aspect definition
336 * @return the new introduction definition
337 */
338 public static InterfaceIntroductionDefinition createInterfaceIntroductionDefinition(final String introductionName,
339 final String expression,
340 final String interfaceClassName,
341 final AspectDefinition aspectDef) {
342 final InterfaceIntroductionDefinition introDef = new InterfaceIntroductionDefinition(
343 introductionName, interfaceClassName
344 );
345 if (expression != null) {
346 ExpressionInfo expressionInfo = new ExpressionInfo(expression, aspectDef.getQualifiedName());
347
348
349 ExpressionNamespace.getNamespace(aspectDef.getQualifiedName()).addExpressionInfo(
350 EXPRESSION_PREFIX + expression.hashCode(),
351 expressionInfo
352 );
353 introDef.addExpressionInfo(expressionInfo);
354 }
355 return introDef;
356 }
357
358 }