KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > expression > AdvisedClassFilterExpressionVisitor


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 JavaDoc;
54 import java.util.Iterator JavaDoc;
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 JavaDoc expression,
77                                                final String JavaDoc namespace, final Node root) {
78         super(expressionInfo, expression, namespace, root);
79     }
80
81     // ============ Boot strap =============
82
public Object JavaDoc visit(SimpleNode node, Object JavaDoc data) {
83         return node.jjtGetChild(0).jjtAccept(this, data);
84     }
85
86     public Object JavaDoc visit(ASTRoot node, Object JavaDoc data) {
87         Node child = node.jjtGetChild(0);
88         Boolean JavaDoc match = (Boolean JavaDoc) child.jjtAccept(this, data);
89         return match;
90     }
91
92     public Object JavaDoc visit(ASTExpression node, Object JavaDoc data) {
93         Node child = node.jjtGetChild(0);
94         Boolean JavaDoc match = (Boolean JavaDoc) child.jjtAccept(this, data);
95         return match;
96     }
97
98     public Object JavaDoc visit(ASTNot node, Object JavaDoc data) {
99         return super.visit(node,data);
100     }
101
102     // ============ Pointcut types =============
103
public Object JavaDoc visit(ASTPointcutReference node, Object JavaDoc 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 JavaDoc visit(ASTExecution node, Object JavaDoc data) {
111         ExpressionContext context = (ExpressionContext) data;
112
113         // only the last node might be the pattern, others are annotations
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                     // reflectionInfo was given
121
return patternNode.jjtAccept(this, context.getReflectionInfo());
122                 } else {
123                     // only withinInfo was given
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 JavaDoc visit(ASTCall node, Object JavaDoc data) {
135         ExpressionContext context = (ExpressionContext) data;
136         
137         // only the last node might be the pattern, others are annotations
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 JavaDoc visit(ASTSet node, Object JavaDoc data) {
157         ExpressionContext context = (ExpressionContext) data;
158         
159         // only the last node might be the pattern, others are annotations
160
Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
161         boolean checkPattern = !(patternNode instanceof ASTAttribute);
162         
163         // for set evaluation, the reflection info may be null at the early matching phase
164
// when we will allow for field interception within non declaring class
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 JavaDoc visit(ASTGet node, Object JavaDoc data) {
181         ExpressionContext context = (ExpressionContext) data;
182
183         // only the last node might be the pattern, others are annotations
184
Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
185         boolean checkPattern = !(patternNode instanceof ASTAttribute);
186         
187         // for get evaluation, the reflection info may be null at the early matching phase
188
// since we allow for field interception within non declaring class
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 JavaDoc visit(ASTHandler node, Object JavaDoc data) {
205         return null;
206     }
207
208     public Object JavaDoc visit(ASTStaticInitialization node, Object JavaDoc 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                 // In an annotated subtree, the last child node represents the pattern
218
Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
219                 if (!(patternNode instanceof ASTAttribute)) {
220                     Boolean JavaDoc matchPattern = (Boolean JavaDoc) patternNode.jjtAccept(this, reflectInfo);
221                     if (Boolean.FALSE.equals(matchPattern)) {
222                         return Boolean.FALSE;
223                     }
224                 }
225
226                 // match on the annotations since the pattern was not there or matched
227
boolean matchedAnnotations = visitAttributes(node, reflectInfo);
228                 if (!matchedAnnotations) {
229                     return Boolean.FALSE;
230                 } else {
231                     return null;//match but early phase
232
}
233             } else {
234                 return Boolean.FALSE;
235             }
236         } else {
237             return Boolean.FALSE;
238         }
239     }
240
241     public Object JavaDoc visit(ASTWithinCode node, Object JavaDoc data) {
242         ExpressionContext context = (ExpressionContext) data;
243         ReflectionInfo withinInfo = context.getWithinReflectionInfo();
244
245         if (node.isStaticInitializer()) {
246             // transform the node in a within node to do an exact match on the within info
247
//TODO would be worth to do the fastNode creation only once somewhere
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 JavaDoc matchDeclaringType = (Boolean JavaDoc) patternNode.jjtAccept(this, withinInfo);
262                     if (Boolean.FALSE.equals(matchDeclaringType)) {
263                         return Boolean.FALSE;
264                     } else {
265                         // may be we match now but not later?
266
return null;
267                     }
268                 } else {
269                     return null;
270                 }
271             } else {
272                 return null;
273             }
274         }
275     }
276
277     public Object JavaDoc visit(ASTCflow node, Object JavaDoc data) {
278         return null;
279     }
280
281     public Object JavaDoc visit(ASTCflowBelow node, Object JavaDoc data) {
282         return null;
283     }
284
285     public Object JavaDoc visit(ASTArgs node, Object JavaDoc data) {
286         return null;
287     }
288
289     public Object JavaDoc visit(ASTTarget node, Object JavaDoc data) {
290         return null;// is that good enough ? For execution PC we would optimize some
291
}
292
293     public Object JavaDoc visit(ASTThis node, Object JavaDoc 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     // ============ Patterns =============
314
// public Object visit(ASTClassPattern node, Object data) {
315
// if(null == data) {
316
// return null;
317
// } else if( !(data instanceof ClassInfo) ) {
318
// return Boolean.FALSE;
319
// }
320
//
321
// ClassInfo classInfo = (ClassInfo) data;
322
// if (node.getTypePattern().matchType(classInfo) && visitAttributes(node, classInfo)) {
323
// return Boolean.TRUE;
324
// } else {
325
// return Boolean.FALSE;
326
// }
327
// }
328

329     public Object JavaDoc visit(ASTMethodPattern node, Object JavaDoc 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;// it might not match further because of modifiers etc
340
}
341             return Boolean.FALSE;
342         }
343         return Boolean.FALSE;
344     }
345
346     public Object JavaDoc visit(ASTConstructorPattern node, Object JavaDoc data) {
347         if (data instanceof ClassInfo) {
348             ClassInfo classInfo = (ClassInfo) data;
349             if (node.getDeclaringTypePattern().matchType(classInfo)) {
350                 // we matched but the actual match result may be false
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;// it might not match further because of modifiers etc
357
}
358             return Boolean.FALSE;
359         }
360         return Boolean.FALSE;
361     }
362
363     public Object JavaDoc visit(ASTFieldPattern node, Object JavaDoc data) {
364         if (data instanceof ClassInfo) {
365             ClassInfo classInfo = (ClassInfo) data;
366             if (node.getDeclaringTypePattern().matchType(classInfo)) {
367                 // we matched but the actual match result may be false
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;// it might not match further because of modifiers etc
374
}
375             return Boolean.FALSE;
376         }
377         return Boolean.FALSE;
378     }
379
380     public Object JavaDoc visit(ASTParameter node, Object JavaDoc data) {
381         ClassInfo parameterType = (ClassInfo) data;
382         if (node.getDeclaringClassPattern().matchType(parameterType)) {
383             // we matched but the actual match result may be false
384
return Boolean.TRUE;
385         } else {
386             return Boolean.FALSE;
387         }
388     }
389
390     public Object JavaDoc visit(ASTArgParameter node, Object JavaDoc data) {
391         // never called
392
return Boolean.TRUE;
393     }
394
395     public Object JavaDoc visit(ASTAttribute node, Object JavaDoc data) {
396         // called for class level annotation matching f.e. in a within context
397
boolean matchAnnotation = false;
398         List JavaDoc annotations = (List JavaDoc) data;
399         for (Iterator JavaDoc 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 JavaDoc visit(ASTModifier node, Object JavaDoc data) {
413         // TODO
414
return null;
415     }
416
417     /**
418      * Returns the string representation of the AST.
419      *
420      * @return
421      */

422     public String JavaDoc toString() {
423         return m_expression;
424     }
425 }
426
Popular Tags