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.expression;
9
10 import org.codehaus.aspectwerkz.expression.ast.ASTAnd;
11 import org.codehaus.aspectwerkz.expression.ast.ASTAttribute;
12 import org.codehaus.aspectwerkz.expression.ast.ASTCall;
13 import org.codehaus.aspectwerkz.expression.ast.ASTCflow;
14 import org.codehaus.aspectwerkz.expression.ast.ASTCflowBelow;
15 import org.codehaus.aspectwerkz.expression.ast.ASTClassPattern;
16 import org.codehaus.aspectwerkz.expression.ast.ASTConstructorPattern;
17 import org.codehaus.aspectwerkz.expression.ast.ASTExecution;
18 import org.codehaus.aspectwerkz.expression.ast.ASTExpression;
19 import org.codehaus.aspectwerkz.expression.ast.ASTFieldPattern;
20 import org.codehaus.aspectwerkz.expression.ast.ASTGet;
21 import org.codehaus.aspectwerkz.expression.ast.ASTHandler;
22 import org.codehaus.aspectwerkz.expression.ast.ASTMethodPattern;
23 import org.codehaus.aspectwerkz.expression.ast.ASTModifier;
24 import org.codehaus.aspectwerkz.expression.ast.ASTParameter;
25 import org.codehaus.aspectwerkz.expression.ast.ASTPointcutReference;
26 import org.codehaus.aspectwerkz.expression.ast.ASTRoot;
27 import org.codehaus.aspectwerkz.expression.ast.ASTSet;
28 import org.codehaus.aspectwerkz.expression.ast.ASTStaticInitialization;
29 import org.codehaus.aspectwerkz.expression.ast.ASTWithin;
30 import org.codehaus.aspectwerkz.expression.ast.ASTWithinCode;
31 import org.codehaus.aspectwerkz.expression.ast.ExpressionParserVisitor;
32 import org.codehaus.aspectwerkz.expression.ast.Node;
33 import org.codehaus.aspectwerkz.expression.ast.SimpleNode;
34 import org.codehaus.aspectwerkz.expression.ast.ASTArgs;
35 import org.codehaus.aspectwerkz.expression.ast.ASTArgParameter;
36 import org.codehaus.aspectwerkz.expression.ast.ASTHasField;
37 import org.codehaus.aspectwerkz.expression.ast.ASTHasMethod;
38 import org.codehaus.aspectwerkz.expression.ast.ASTTarget;
39 import org.codehaus.aspectwerkz.expression.ast.ASTThis;
40 import org.codehaus.aspectwerkz.expression.ast.ASTNot;
41 import org.codehaus.aspectwerkz.expression.regexp.TypePattern;
42 import org.codehaus.aspectwerkz.reflect.ClassInfo;
43 import org.codehaus.aspectwerkz.reflect.MemberInfo;
44 import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
45 import org.codehaus.aspectwerkz.reflect.MethodInfo;
46 import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
47 import org.codehaus.aspectwerkz.reflect.FieldInfo;
48 import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
49 import org.codehaus.aspectwerkz.reflect.StaticInitializationInfo;
50 import org.codehaus.aspectwerkz.annotation.AnnotationInfo;
51 import org.codehaus.aspectwerkz.util.Util;
52
53 import java.util.List;
54 import java.util.Iterator;
55
56 /***
57 * The advised class filter visitor.
58 * <p/>
59 * Visit() methods are returning Boolean.TRUE/FALSE or null when decision cannot be taken.
60 * Using null allow composition of OR/AND with NOT in the best way.
61 *
62 * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
63 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
64 * @author Michael Nascimento
65 * @author <a href="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
66 */
67 public class AdvisedClassFilterExpressionVisitor extends ExpressionVisitor implements ExpressionParserVisitor {
68
69 /***
70 * Creates a new expression.
71 *
72 * @param expression the expression as a string
73 * @param namespace the namespace
74 * @param root the AST root
75 */
76 public AdvisedClassFilterExpressionVisitor(final ExpressionInfo expressionInfo, final String expression,
77 final String namespace, final Node root) {
78 super(expressionInfo, expression, namespace, root);
79 }
80
81
82 public Object visit(SimpleNode node, Object data) {
83 return node.jjtGetChild(0).jjtAccept(this, data);
84 }
85
86 public Object visit(ASTRoot node, Object data) {
87 Node child = node.jjtGetChild(0);
88 Boolean match = (Boolean) child.jjtAccept(this, data);
89 return match;
90 }
91
92 public Object visit(ASTExpression node, Object data) {
93 Node child = node.jjtGetChild(0);
94 Boolean match = (Boolean) child.jjtAccept(this, data);
95 return match;
96 }
97
98 public Object visit(ASTNot node, Object data) {
99 return super.visit(node,data);
100 }
101
102
103 public Object visit(ASTPointcutReference node, Object data) {
104 ExpressionContext context = (ExpressionContext) data;
105 ExpressionNamespace namespace = ExpressionNamespace.getNamespace(m_namespace);
106 AdvisedClassFilterExpressionVisitor expression = namespace.getAdvisedClassExpression(node.getName());
107 return expression.matchUndeterministic(context);
108 }
109
110 public Object visit(ASTExecution node, Object data) {
111 ExpressionContext context = (ExpressionContext) data;
112
113
114 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
115 boolean checkPattern = !(patternNode instanceof ASTAttribute);
116
117 if(checkPattern) {
118 if (context.hasWithinPointcut() || context.hasExecutionPointcut()) {
119 if (context.hasExecutionPointcut()) {
120
121 return patternNode.jjtAccept(this, context.getReflectionInfo());
122 } else {
123
124 return patternNode.jjtAccept(this, context.getWithinReflectionInfo());
125 }
126 } else {
127 return Boolean.FALSE;
128 }
129 } else {
130 return null;
131 }
132 }
133
134 public Object visit(ASTCall node, Object data) {
135 ExpressionContext context = (ExpressionContext) data;
136
137
138 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
139 boolean checkPattern = !(patternNode instanceof ASTAttribute);
140
141 if(checkPattern) {
142 if (context.hasWithinPointcut() || context.hasCallPointcut()) {
143 if (context.hasReflectionInfo()) {
144 return patternNode.jjtAccept(this, context.getReflectionInfo());
145 } else {
146 return null;
147 }
148 } else {
149 return Boolean.FALSE;
150 }
151 } else {
152 return null;
153 }
154 }
155
156 public Object visit(ASTSet node, Object data) {
157 ExpressionContext context = (ExpressionContext) data;
158
159
160 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
161 boolean checkPattern = !(patternNode instanceof ASTAttribute);
162
163
164
165 if(checkPattern) {
166 if (context.hasWithinPointcut() || context.hasSetPointcut()) {
167 if (context.hasReflectionInfo()) {
168 return patternNode.jjtAccept(this, context.getReflectionInfo());
169 } else {
170 return null;
171 }
172 } else {
173 return Boolean.FALSE;
174 }
175 } else {
176 return null;
177 }
178 }
179
180 public Object visit(ASTGet node, Object data) {
181 ExpressionContext context = (ExpressionContext) data;
182
183
184 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
185 boolean checkPattern = !(patternNode instanceof ASTAttribute);
186
187
188
189 if(checkPattern) {
190 if (context.hasWithinPointcut() || context.hasGetPointcut()) {
191 if (context.hasReflectionInfo()) {
192 return patternNode.jjtAccept(this, context.getReflectionInfo());
193 } else {
194 return null;
195 }
196 } else {
197 return Boolean.FALSE;
198 }
199 } else {
200 return null;
201 }
202 }
203
204 public Object visit(ASTHandler node, Object data) {
205 return null;
206 }
207
208 public Object visit(ASTStaticInitialization node, Object data) {
209 ExpressionContext context = (ExpressionContext) data;
210
211 if (context.hasStaticInitializationPointcut() && context.hasWithinReflectionInfo()) {
212 ReflectionInfo reflectInfo = context.getWithinReflectionInfo();
213 if (reflectInfo instanceof StaticInitializationInfo) {
214 reflectInfo = ((StaticInitializationInfo) reflectInfo).getDeclaringType();
215 }
216 if (reflectInfo instanceof ClassInfo) {
217
218 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
219 if (!(patternNode instanceof ASTAttribute)) {
220 Boolean matchPattern = (Boolean) patternNode.jjtAccept(this, reflectInfo);
221 if (Boolean.FALSE.equals(matchPattern)) {
222 return Boolean.FALSE;
223 }
224 }
225
226
227 boolean matchedAnnotations = visitAttributes(node, reflectInfo);
228 if (!matchedAnnotations) {
229 return Boolean.FALSE;
230 } else {
231 return null;
232 }
233 } else {
234 return Boolean.FALSE;
235 }
236 } else {
237 return Boolean.FALSE;
238 }
239 }
240
241 public Object visit(ASTWithinCode node, Object data) {
242 ExpressionContext context = (ExpressionContext) data;
243 ReflectionInfo withinInfo = context.getWithinReflectionInfo();
244
245 if (node.isStaticInitializer()) {
246
247
248 ASTWithin fastNode = new ASTWithin(0);
249 for (int i = 0; i < node.jjtGetChild(0).jjtGetNumChildren(); i++) {
250 fastNode.jjtAddChild(node.jjtGetChild(0).jjtGetChild(i), i);
251 }
252 return super.visit(fastNode, data);
253 } else {
254 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
255 boolean checkPattern = !(patternNode instanceof ASTAttribute);
256
257 if (checkPattern) {
258 if (withinInfo instanceof MemberInfo) {
259 return patternNode.jjtAccept(this, withinInfo);
260 } else if (withinInfo instanceof ClassInfo) {
261 Boolean matchDeclaringType = (Boolean) patternNode.jjtAccept(this, withinInfo);
262 if (Boolean.FALSE.equals(matchDeclaringType)) {
263 return Boolean.FALSE;
264 } else {
265
266 return null;
267 }
268 } else {
269 return null;
270 }
271 } else {
272 return null;
273 }
274 }
275 }
276
277 public Object visit(ASTCflow node, Object data) {
278 return null;
279 }
280
281 public Object visit(ASTCflowBelow node, Object data) {
282 return null;
283 }
284
285 public Object visit(ASTArgs node, Object data) {
286 return null;
287 }
288
289 public Object visit(ASTTarget node, Object data) {
290 return null;
291 }
292
293 public Object visit(ASTThis node, Object data) {
294 ExpressionContext context = (ExpressionContext) data;
295 if (context.hasWithinReflectionInfo()) {
296 ReflectionInfo withinInfo = context.getWithinReflectionInfo();
297 if (withinInfo instanceof MemberInfo) {
298 return Util.booleanValueOf(
299 ClassInfoHelper.instanceOf(
300 ((MemberInfo) withinInfo).getDeclaringType(),
301 node.getBoundedType(m_expressionInfo)
302 )
303 );
304 } else if (withinInfo instanceof ClassInfo) {
305 return Util.booleanValueOf(
306 ClassInfoHelper.instanceOf((ClassInfo) withinInfo, node.getBoundedType(m_expressionInfo))
307 );
308 }
309 }
310 return Boolean.FALSE;
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 public Object visit(ASTMethodPattern node, Object data) {
330 if (data instanceof ClassInfo) {
331 ClassInfo classInfo = (ClassInfo) data;
332 if (node.getDeclaringTypePattern().matchType(classInfo)) {
333 return Boolean.TRUE;
334 }
335 return Boolean.FALSE;
336 } else if (data instanceof MethodInfo) {
337 MethodInfo methodInfo = (MethodInfo) data;
338 if (node.getDeclaringTypePattern().matchType(methodInfo.getDeclaringType())) {
339 return null;
340 }
341 return Boolean.FALSE;
342 }
343 return Boolean.FALSE;
344 }
345
346 public Object visit(ASTConstructorPattern node, Object data) {
347 if (data instanceof ClassInfo) {
348 ClassInfo classInfo = (ClassInfo) data;
349 if (node.getDeclaringTypePattern().matchType(classInfo)) {
350
351 return Boolean.TRUE;
352 }
353 } else if (data instanceof ConstructorInfo) {
354 ConstructorInfo constructorInfo = (ConstructorInfo) data;
355 if (node.getDeclaringTypePattern().matchType(constructorInfo.getDeclaringType())) {
356 return null;
357 }
358 return Boolean.FALSE;
359 }
360 return Boolean.FALSE;
361 }
362
363 public Object visit(ASTFieldPattern node, Object data) {
364 if (data instanceof ClassInfo) {
365 ClassInfo classInfo = (ClassInfo) data;
366 if (node.getDeclaringTypePattern().matchType(classInfo)) {
367
368 return Boolean.TRUE;
369 }
370 } else if (data instanceof FieldInfo) {
371 FieldInfo fieldInfo = (FieldInfo) data;
372 if (node.getDeclaringTypePattern().matchType(fieldInfo.getDeclaringType())) {
373 return null;
374 }
375 return Boolean.FALSE;
376 }
377 return Boolean.FALSE;
378 }
379
380 public Object visit(ASTParameter node, Object data) {
381 ClassInfo parameterType = (ClassInfo) data;
382 if (node.getDeclaringClassPattern().matchType(parameterType)) {
383
384 return Boolean.TRUE;
385 } else {
386 return Boolean.FALSE;
387 }
388 }
389
390 public Object visit(ASTArgParameter node, Object data) {
391
392 return Boolean.TRUE;
393 }
394
395 public Object visit(ASTAttribute node, Object data) {
396
397 boolean matchAnnotation = false;
398 List annotations = (List) data;
399 for (Iterator it = annotations.iterator(); it.hasNext();) {
400 AnnotationInfo annotation = (AnnotationInfo) it.next();
401 if (annotation.getName().equals(node.getName())) {
402 matchAnnotation = true;
403 }
404 }
405 if (node.isNot()) {
406 return Util.booleanValueOf(!matchAnnotation);
407 } else {
408 return Util.booleanValueOf(matchAnnotation);
409 }
410 }
411
412 public Object visit(ASTModifier node, Object data) {
413
414 return null;
415 }
416
417 /***
418 * Returns the string representation of the AST.
419 *
420 * @return
421 */
422 public String toString() {
423 return m_expression;
424 }
425 }