KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > expression > AdvisedClassFilterExpressionVisitor


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.aspectwerkz.expression;
5
6 import com.tc.backport175.bytecode.AnnotationElement;
7
8 import com.tc.aspectwerkz.expression.ast.ASTArgParameter;
9 import com.tc.aspectwerkz.expression.ast.ASTArgs;
10 import com.tc.aspectwerkz.expression.ast.ASTAttribute;
11 import com.tc.aspectwerkz.expression.ast.ASTCall;
12 import com.tc.aspectwerkz.expression.ast.ASTCflow;
13 import com.tc.aspectwerkz.expression.ast.ASTCflowBelow;
14 import com.tc.aspectwerkz.expression.ast.ASTConstructorPattern;
15 import com.tc.aspectwerkz.expression.ast.ASTExecution;
16 import com.tc.aspectwerkz.expression.ast.ASTExpression;
17 import com.tc.aspectwerkz.expression.ast.ASTFieldPattern;
18 import com.tc.aspectwerkz.expression.ast.ASTGet;
19 import com.tc.aspectwerkz.expression.ast.ASTHandler;
20 import com.tc.aspectwerkz.expression.ast.ASTMethodPattern;
21 import com.tc.aspectwerkz.expression.ast.ASTModifier;
22 import com.tc.aspectwerkz.expression.ast.ASTNot;
23 import com.tc.aspectwerkz.expression.ast.ASTParameter;
24 import com.tc.aspectwerkz.expression.ast.ASTPointcutReference;
25 import com.tc.aspectwerkz.expression.ast.ASTRoot;
26 import com.tc.aspectwerkz.expression.ast.ASTSet;
27 import com.tc.aspectwerkz.expression.ast.ASTStaticInitialization;
28 import com.tc.aspectwerkz.expression.ast.ASTTarget;
29 import com.tc.aspectwerkz.expression.ast.ASTThis;
30 import com.tc.aspectwerkz.expression.ast.ASTWithin;
31 import com.tc.aspectwerkz.expression.ast.ASTWithinCode;
32 import com.tc.aspectwerkz.expression.ast.ExpressionParserVisitor;
33 import com.tc.aspectwerkz.expression.ast.Node;
34 import com.tc.aspectwerkz.expression.ast.SimpleNode;
35 import com.tc.aspectwerkz.util.Util;
36 import com.tc.aspectwerkz.reflect.StaticInitializationInfo;
37 import com.tc.aspectwerkz.reflect.ReflectionInfo;
38 import com.tc.aspectwerkz.reflect.ClassInfo;
39 import com.tc.aspectwerkz.reflect.MemberInfo;
40 import com.tc.aspectwerkz.reflect.ClassInfoHelper;
41 import com.tc.aspectwerkz.reflect.MethodInfo;
42 import com.tc.aspectwerkz.reflect.FieldInfo;
43 import com.tc.aspectwerkz.reflect.ConstructorInfo;
44
45 /**
46  * The advised class filter visitor.
47  * <p/>
48  * Visit() methods are returning Boolean.TRUE/FALSE or null when decision cannot be taken.
49  * Using null allow composition of OR/AND with NOT in the best way.
50  *
51  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
52  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
53  * @author Michael Nascimento
54  * @author <a HREF="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
55  */

56 public class AdvisedClassFilterExpressionVisitor extends ExpressionVisitor implements ExpressionParserVisitor {
57
58   /**
59    * Creates a new expression.
60    *
61    * @param expression the expression as a string
62    * @param namespace the namespace
63    * @param root the AST root
64    */

65   public AdvisedClassFilterExpressionVisitor(final ExpressionInfo expressionInfo, final String JavaDoc expression,
66                                              final String JavaDoc namespace, final Node root) {
67     super(expressionInfo, expression, namespace, root);
68   }
69
70   // ============ Boot strap =============
71
public Object JavaDoc visit(SimpleNode node, Object JavaDoc data) {
72     return node.jjtGetChild(0).jjtAccept(this, data);
73   }
74
75   public Object JavaDoc visit(ASTRoot node, Object JavaDoc data) {
76     Node child = node.jjtGetChild(0);
77     Boolean JavaDoc match = (Boolean JavaDoc) child.jjtAccept(this, data);
78     return match;
79   }
80
81   public Object JavaDoc visit(ASTExpression node, Object JavaDoc data) {
82     Node child = node.jjtGetChild(0);
83     Boolean JavaDoc match = (Boolean JavaDoc) child.jjtAccept(this, data);
84     return match;
85   }
86
87   public Object JavaDoc visit(ASTNot node, Object JavaDoc data) {
88     return super.visit(node, data);
89   }
90
91   // ============ Pointcut types =============
92
public Object JavaDoc visit(ASTPointcutReference node, Object JavaDoc data) {
93     ExpressionContext context = (ExpressionContext) data;
94     ExpressionNamespace namespace = ExpressionNamespace.getNamespace(m_namespace);
95     AdvisedClassFilterExpressionVisitor expression = namespace.getAdvisedClassExpression(node.getName());
96     return expression.matchUndeterministic(context);
97   }
98
99   public Object JavaDoc visit(ASTExecution node, Object JavaDoc data) {
100     ExpressionContext context = (ExpressionContext) data;
101
102     // only the last node might be the pattern, others are annotations
103
Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
104     boolean checkPattern = !(patternNode instanceof ASTAttribute);
105
106     if (checkPattern) {
107       if (context.hasWithinPointcut() || context.hasExecutionPointcut()) {
108         if (context.hasExecutionPointcut()) {
109           // reflectionInfo was given
110
return patternNode.jjtAccept(this, context.getReflectionInfo());
111         } else {
112           // only withinInfo was given
113
return patternNode.jjtAccept(this, context.getWithinReflectionInfo());
114         }
115       } else {
116         return Boolean.FALSE;
117       }
118     } else {
119       return null;
120     }
121   }
122
123   public Object JavaDoc visit(ASTCall node, Object JavaDoc data) {
124     ExpressionContext context = (ExpressionContext) data;
125
126     // only the last node might be the pattern, others are annotations
127
Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
128     boolean checkPattern = !(patternNode instanceof ASTAttribute);
129
130     if (checkPattern) {
131       if (context.hasWithinPointcut() || context.hasCallPointcut()) {
132         if (context.hasReflectionInfo()) {
133           return patternNode.jjtAccept(this, context.getReflectionInfo());
134         } else {
135           return null;
136         }
137       } else {
138         return Boolean.FALSE;
139       }
140     } else {
141       return null;
142     }
143   }
144
145   public Object JavaDoc visit(ASTSet node, Object JavaDoc data) {
146     ExpressionContext context = (ExpressionContext) data;
147
148     // only the last node might be the pattern, others are annotations
149
Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
150     boolean checkPattern = !(patternNode instanceof ASTAttribute);
151
152     // for set evaluation, the reflection info may be null at the early matching phase
153
// when we will allow for field interception within non declaring class
154
if (checkPattern) {
155       if (context.hasWithinPointcut() || context.hasSetPointcut()) {
156         if (context.hasReflectionInfo()) {
157           return patternNode.jjtAccept(this, context.getReflectionInfo());
158         } else {
159           return null;
160         }
161       } else {
162         return Boolean.FALSE;
163       }
164     } else {
165       return null;
166     }
167   }
168
169   public Object JavaDoc visit(ASTGet node, Object JavaDoc data) {
170     ExpressionContext context = (ExpressionContext) data;
171
172     // only the last node might be the pattern, others are annotations
173
Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
174     boolean checkPattern = !(patternNode instanceof ASTAttribute);
175
176     // for getDefault evaluation, the reflection info may be null at the early matching phase
177
// since we allow for field interception within non declaring class
178
if (checkPattern) {
179       if (context.hasWithinPointcut() || context.hasGetPointcut()) {
180         if (context.hasReflectionInfo()) {
181           return patternNode.jjtAccept(this, context.getReflectionInfo());
182         } else {
183           return null;
184         }
185       } else {
186         return Boolean.FALSE;
187       }
188     } else {
189       return null;
190     }
191   }
192
193   public Object JavaDoc visit(ASTHandler node, Object JavaDoc data) {
194     return null;
195   }
196
197   public Object JavaDoc visit(ASTStaticInitialization node, Object JavaDoc data) {
198     ExpressionContext context = (ExpressionContext) data;
199
200     if (context.hasStaticInitializationPointcut() && context.hasWithinReflectionInfo()) {
201       ReflectionInfo reflectInfo = context.getWithinReflectionInfo();
202       if (reflectInfo instanceof StaticInitializationInfo) {
203         reflectInfo = ((StaticInitializationInfo) reflectInfo).getDeclaringType();
204       }
205       if (reflectInfo instanceof ClassInfo) {
206         // In an annotated subtree, the last child node represents the pattern
207
Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
208         if (!(patternNode instanceof ASTAttribute)) {
209           Boolean JavaDoc matchPattern = (Boolean JavaDoc) patternNode.jjtAccept(this, reflectInfo);
210           if (Boolean.FALSE.equals(matchPattern)) {
211             return Boolean.FALSE;
212           }
213         }
214
215         // match on the annotations since the pattern was not there or matched
216
boolean matchedAnnotations = visitAttributes(node, reflectInfo);
217         if (!matchedAnnotations) {
218           return Boolean.FALSE;
219         } else {
220           return null;//match but early phase
221
}
222       } else {
223         return Boolean.FALSE;
224       }
225     } else {
226       return Boolean.FALSE;
227     }
228   }
229
230   public Object JavaDoc visit(ASTWithinCode node, Object JavaDoc data) {
231     ExpressionContext context = (ExpressionContext) data;
232     ReflectionInfo withinInfo = context.getWithinReflectionInfo();
233
234     if (node.isStaticInitializer()) {
235       // transform the node in a within node to do an exact match on the within info
236
//TODO would be worth to do the fastNode creation only once somewhere
237
ASTWithin fastNode = new ASTWithin(0);
238       for (int i = 0; i < node.jjtGetChild(0).jjtGetNumChildren(); i++) {
239         fastNode.jjtAddChild(node.jjtGetChild(0).jjtGetChild(i), i);
240       }
241       return super.visit(fastNode, data);
242     } else {
243       Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
244       boolean checkPattern = !(patternNode instanceof ASTAttribute);
245
246       if (checkPattern) {
247         if (withinInfo instanceof MemberInfo) {
248           return patternNode.jjtAccept(this, withinInfo);
249         } else if (withinInfo instanceof ClassInfo) {
250           Boolean JavaDoc matchDeclaringType = (Boolean JavaDoc) patternNode.jjtAccept(this, withinInfo);
251           if (Boolean.FALSE.equals(matchDeclaringType)) {
252             return Boolean.FALSE;
253           } else {
254             // may be we match now but not later?
255
return null;
256           }
257         } else {
258           return null;
259         }
260       } else {
261         return null;
262       }
263     }
264   }
265
266   public Object JavaDoc visit(ASTCflow node, Object JavaDoc data) {
267     return null;
268   }
269
270   public Object JavaDoc visit(ASTCflowBelow node, Object JavaDoc data) {
271     return null;
272   }
273
274   public Object JavaDoc visit(ASTArgs node, Object JavaDoc data) {
275     return null;
276   }
277
278   public Object JavaDoc visit(ASTTarget node, Object JavaDoc data) {
279     return null;// is that good enough ? For execution PC we would optimize some
280
}
281
282   public Object JavaDoc visit(ASTThis node, Object JavaDoc data) {
283     ExpressionContext context = (ExpressionContext) data;
284     if (context.hasWithinReflectionInfo()) {
285       ReflectionInfo withinInfo = context.getWithinReflectionInfo();
286       if (withinInfo instanceof MemberInfo) {
287         return Util.booleanValueOf(
288                 ClassInfoHelper.instanceOf(
289                         ((MemberInfo) withinInfo).getDeclaringType(),
290                         node.getBoundedType(m_expressionInfo)
291                 )
292         );
293       } else if (withinInfo instanceof ClassInfo) {
294         return Util.booleanValueOf(
295                 ClassInfoHelper.instanceOf((ClassInfo) withinInfo, node.getBoundedType(m_expressionInfo))
296         );
297       }
298     }
299     return Boolean.FALSE;
300   }
301
302   // ============ Patterns =============
303
// public Object visit(ASTClassPattern node, Object data) {
304
// if(null == data) {
305
// return null;
306
// } else if( !(data instanceof ClassInfo) ) {
307
// return Boolean.FALSE;
308
// }
309
//
310
// ClassInfo classInfo = (ClassInfo) data;
311
// if (node.getTypePattern().matchType(classInfo) && visitAttributes(node, classInfo)) {
312
// return Boolean.TRUE;
313
// } else {
314
// return Boolean.FALSE;
315
// }
316
// }
317

318   public Object JavaDoc visit(ASTMethodPattern node, Object JavaDoc data) {
319     if (data instanceof ClassInfo) {
320       ClassInfo classInfo = (ClassInfo) data;
321       if (node.getDeclaringTypePattern().matchType(classInfo)) {
322         return Boolean.TRUE;
323       }
324       return Boolean.FALSE;
325     } else if (data instanceof MethodInfo) {
326       MethodInfo methodInfo = (MethodInfo) data;
327       if (node.getDeclaringTypePattern().matchType(methodInfo.getDeclaringType())) {
328         return null;// it might not match further because of modifiers etc
329
}
330       return Boolean.FALSE;
331     }
332     return Boolean.FALSE;
333   }
334
335   public Object JavaDoc visit(ASTConstructorPattern node, Object JavaDoc data) {
336     if (data instanceof ClassInfo) {
337       ClassInfo classInfo = (ClassInfo) data;
338       if (node.getDeclaringTypePattern().matchType(classInfo)) {
339         // we matched but the actual match result may be false
340
return Boolean.TRUE;
341       }
342     } else if (data instanceof ConstructorInfo) {
343       ConstructorInfo constructorInfo = (ConstructorInfo) data;
344       if (node.getDeclaringTypePattern().matchType(constructorInfo.getDeclaringType())) {
345         return null;// it might not match further because of modifiers etc
346
}
347       return Boolean.FALSE;
348     }
349     return Boolean.FALSE;
350   }
351
352   public Object JavaDoc visit(ASTFieldPattern node, Object JavaDoc data) {
353     if (data instanceof ClassInfo) {
354       ClassInfo classInfo = (ClassInfo) data;
355       if (node.getDeclaringTypePattern().matchType(classInfo)) {
356         // we matched but the actual match result may be false
357
return Boolean.TRUE;
358       }
359     } else if (data instanceof FieldInfo) {
360       FieldInfo fieldInfo = (FieldInfo) data;
361       if (node.getDeclaringTypePattern().matchType(fieldInfo.getDeclaringType())) {
362         return null;// it might not match further because of modifiers etc
363
}
364       return Boolean.FALSE;
365     }
366     return Boolean.FALSE;
367   }
368
369   public Object JavaDoc visit(ASTParameter node, Object JavaDoc data) {
370     ClassInfo parameterType = (ClassInfo) data;
371     if (node.getDeclaringClassPattern().matchType(parameterType)) {
372       // we matched but the actual match result may be false
373
return Boolean.TRUE;
374     } else {
375       return Boolean.FALSE;
376     }
377   }
378
379   public Object JavaDoc visit(ASTArgParameter node, Object JavaDoc data) {
380     // never called
381
return Boolean.TRUE;
382   }
383
384   public Object JavaDoc visit(ASTAttribute node, Object JavaDoc data) {
385     // called for class level annotation matching f.e. in a within context
386
boolean matchAnnotation = false;
387     AnnotationElement.Annotation[] annotations = (AnnotationElement.Annotation[]) data;
388     for (int i = 0; i < annotations.length; i++) {
389       AnnotationElement.Annotation annotation = annotations[i];
390       if (annotation.getInterfaceName().equals(node.getName())) {
391         matchAnnotation = true;
392       }
393     }
394     if (node.isNot()) {
395       return Util.booleanValueOf(!matchAnnotation);
396     } else {
397       return Util.booleanValueOf(matchAnnotation);
398     }
399   }
400
401   public Object JavaDoc visit(ASTModifier node, Object JavaDoc data) {
402     // TODO
403
return null;
404   }
405
406   /**
407    * Returns the string representation of the AST.
408    *
409    * @return
410    */

411   public String JavaDoc toString() {
412     return m_expression;
413   }
414 }
415
Popular Tags