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.annotation.AnnotationInfo;
11 import org.codehaus.aspectwerkz.expression.ast.ASTAnd;
12 import org.codehaus.aspectwerkz.expression.ast.ASTAttribute;
13 import org.codehaus.aspectwerkz.expression.ast.ASTCall;
14 import org.codehaus.aspectwerkz.expression.ast.ASTCflow;
15 import org.codehaus.aspectwerkz.expression.ast.ASTCflowBelow;
16 import org.codehaus.aspectwerkz.expression.ast.ASTClassPattern;
17 import org.codehaus.aspectwerkz.expression.ast.ASTConstructorPattern;
18 import org.codehaus.aspectwerkz.expression.ast.ASTExecution;
19 import org.codehaus.aspectwerkz.expression.ast.ASTExpression;
20 import org.codehaus.aspectwerkz.expression.ast.ASTFieldPattern;
21 import org.codehaus.aspectwerkz.expression.ast.ASTGet;
22 import org.codehaus.aspectwerkz.expression.ast.ASTHandler;
23 import org.codehaus.aspectwerkz.expression.ast.ASTMethodPattern;
24 import org.codehaus.aspectwerkz.expression.ast.ASTModifier;
25 import org.codehaus.aspectwerkz.expression.ast.ASTNot;
26 import org.codehaus.aspectwerkz.expression.ast.ASTOr;
27 import org.codehaus.aspectwerkz.expression.ast.ASTParameter;
28 import org.codehaus.aspectwerkz.expression.ast.ASTPointcutReference;
29 import org.codehaus.aspectwerkz.expression.ast.ASTRoot;
30 import org.codehaus.aspectwerkz.expression.ast.ASTSet;
31 import org.codehaus.aspectwerkz.expression.ast.ASTStaticInitialization;
32 import org.codehaus.aspectwerkz.expression.ast.ASTWithin;
33 import org.codehaus.aspectwerkz.expression.ast.ASTWithinCode;
34 import org.codehaus.aspectwerkz.expression.ast.ExpressionParserVisitor;
35 import org.codehaus.aspectwerkz.expression.ast.Node;
36 import org.codehaus.aspectwerkz.expression.ast.SimpleNode;
37 import org.codehaus.aspectwerkz.expression.ast.ASTArgs;
38 import org.codehaus.aspectwerkz.expression.ast.ASTArgParameter;
39 import org.codehaus.aspectwerkz.expression.regexp.TypePattern;
40 import org.codehaus.aspectwerkz.reflect.ClassInfo;
41 import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
42 import org.codehaus.aspectwerkz.reflect.FieldInfo;
43 import org.codehaus.aspectwerkz.reflect.MemberInfo;
44 import org.codehaus.aspectwerkz.reflect.MethodInfo;
45 import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
46 import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
47 import org.codehaus.aspectwerkz.reflect.StaticInitializationInfo;
48
49 import java.lang.reflect.Modifier;
50 import java.util.ArrayList;
51 import java.util.Iterator;
52 import java.util.List;
53
54 import org.codehaus.aspectwerkz.expression.ast.ASTHasField;
55 import org.codehaus.aspectwerkz.expression.ast.ASTHasMethod;
56 import org.codehaus.aspectwerkz.expression.ast.ASTTarget;
57 import org.codehaus.aspectwerkz.expression.ast.ASTThis;
58 import org.codehaus.aspectwerkz.util.Util;
59
60 /***
61 * The expression visitor.
62 * If a runtime residual is required (target => instance of check sometimes), Undeterministic matching is used.
63 *
64 * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
65 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
66 * @author Michael Nascimento
67 * @author <a href="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
68 */
69 public class ExpressionVisitor implements ExpressionParserVisitor {
70
71 protected Node m_root;
72 protected String m_expression;
73 protected String m_namespace;
74
75 /***
76 * The expressionInfo this visitor is built on
77 */
78 protected ExpressionInfo m_expressionInfo;
79
80 /***
81 * Creates a new expression.
82 *
83 * @param expressionInfo the expressionInfo this visitor is built on for expression with signature
84 * @param expression the expression as a string
85 * @param namespace the namespace
86 * @param root the AST root
87 */
88 public ExpressionVisitor(final ExpressionInfo expressionInfo,
89 final String expression,
90 final String namespace,
91 final Node root) {
92 m_expressionInfo = expressionInfo;
93 m_expression = expression;
94 m_namespace = namespace;
95 m_root = root;
96 }
97
98 /***
99 * Matches the expression context.
100 * If undetermined, assume true.
101 * Do not use for poincut reference - see matchUndeterministic
102 *
103 * @param context
104 * @return
105 */
106 public boolean match(final ExpressionContext context) {
107 Boolean match = ((Boolean) visit(m_root, context));
108
109
110
111 return (match != null) ? match.booleanValue() : true;
112 }
113
114 protected Boolean matchUndeterministic(final ExpressionContext context) {
115 Boolean match = ((Boolean) visit(m_root, context));
116 return match;
117 }
118
119
120 public Object visit(Node node, Object data) {
121 return node.jjtGetChild(0).jjtAccept(this, data);
122 }
123
124 public Object visit(SimpleNode node, Object data) {
125 return node.jjtGetChild(0).jjtAccept(this, data);
126 }
127
128 public Object visit(ASTRoot node, Object data) {
129 return node.jjtGetChild(0).jjtAccept(this, data);
130 }
131
132 public Object visit(ASTExpression node, Object data) {
133 return node.jjtGetChild(0).jjtAccept(this, data);
134 }
135
136
137 public Object visit(ASTOr node, Object data) {
138
139 Boolean matchL = (Boolean) node.jjtGetChild(0).jjtAccept(this, data);
140 Boolean matchR = (Boolean) node.jjtGetChild(1).jjtAccept(this, data);
141 Boolean intermediate = Undeterministic.or(matchL, matchR);
142 for (int i = 2; i < node.jjtGetNumChildren(); i++) {
143 Boolean matchNext = (Boolean) node.jjtGetChild(i).jjtAccept(this, data);
144 intermediate = Undeterministic.or(intermediate, matchNext);
145 }
146 return intermediate;
147 }
148
149 public Object visit(ASTAnd node, Object data) {
150
151 Boolean matchL = (Boolean) node.jjtGetChild(0).jjtAccept(this, data);
152 Boolean matchR = (Boolean) node.jjtGetChild(1).jjtAccept(this, data);
153 Boolean intermediate = Undeterministic.and(matchL, matchR);
154 for (int i = 2; i < node.jjtGetNumChildren(); i++) {
155 Boolean matchNext = (Boolean) node.jjtGetChild(i).jjtAccept(this, data);
156 intermediate = Undeterministic.and(intermediate, matchNext);
157 }
158 return intermediate;
159 }
160
161 public Object visit(ASTNot node, Object data) {
162 Boolean match = (Boolean) node.jjtGetChild(0).jjtAccept(this, data);
163 return Undeterministic.not(match);
164 }
165
166
167 public Object visit(ASTPointcutReference node, Object data) {
168 ExpressionContext context = (ExpressionContext) data;
169 ExpressionNamespace namespace = ExpressionNamespace.getNamespace(m_namespace);
170 ExpressionVisitor expression = namespace.getExpression(node.getName());
171 return expression.matchUndeterministic(context);
172 }
173
174 public Object visit(ASTExecution node, Object data) {
175 ExpressionContext context = (ExpressionContext) data;
176 if (context.hasExecutionPointcut() && (context.hasMethodInfo() || context.hasConstructorInfo())) {
177 return visitAnnotatedNode(node, context.getReflectionInfo());
178 } else {
179 return Boolean.FALSE;
180 }
181 }
182
183 public Object visit(ASTCall node, Object data) {
184 ExpressionContext context = (ExpressionContext) data;
185 if (context.hasCallPointcut() && (context.hasMethodInfo() || context.hasConstructorInfo())) {
186 return visitAnnotatedNode(node, context.getReflectionInfo());
187 } else {
188 return Boolean.FALSE;
189 }
190 }
191
192 public Object visit(ASTSet node, Object data) {
193 ExpressionContext context = (ExpressionContext) data;
194 if (context.hasSetPointcut() && context.hasFieldInfo()) {
195 return visitAnnotatedNode(node, context.getReflectionInfo());
196 } else {
197 return Boolean.FALSE;
198 }
199 }
200
201 public Object visit(ASTGet node, Object data) {
202 ExpressionContext context = (ExpressionContext) data;
203 if (context.hasGetPointcut() && context.hasFieldInfo()) {
204 return visitAnnotatedNode(node, context.getReflectionInfo());
205 } else {
206 return Boolean.FALSE;
207 }
208 }
209
210 public Object visit(ASTHandler node, Object data) {
211 ExpressionContext context = (ExpressionContext) data;
212 if (context.hasHandlerPointcut() && context.hasClassInfo()) {
213 return node.jjtGetChild(0).jjtAccept(this, context.getReflectionInfo());
214 } else {
215 return Boolean.FALSE;
216 }
217 }
218
219 public Object visit(ASTStaticInitialization node, Object data) {
220 ExpressionContext context = (ExpressionContext) data;
221
222 if (context.hasStaticInitializationPointcut() && context.hasReflectionInfo()) {
223 ReflectionInfo reflectInfo = context.getReflectionInfo();
224
225 if(reflectInfo instanceof StaticInitializationInfo) {
226 ClassInfo declaringClassInfo = ((StaticInitializationInfo) reflectInfo).getDeclaringType();
227
228
229 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
230 if (!(patternNode instanceof ASTAttribute)) {
231 Boolean matchPattern = (Boolean) patternNode.jjtAccept(this, reflectInfo);
232 if (Boolean.FALSE.equals(matchPattern)) {
233 return Boolean.FALSE;
234 }
235 }
236
237
238 boolean matchedAnnotations = visitAttributes(node, declaringClassInfo);
239 if (!matchedAnnotations) {
240 return Boolean.FALSE;
241 } else {
242 return Boolean.TRUE;
243 }
244 } else {
245 return Boolean.FALSE;
246 }
247 } else {
248 return Boolean.FALSE;
249 }
250 }
251
252 public Object visit(ASTWithin node, Object data) {
253 ExpressionContext context = (ExpressionContext) data;
254 if (context.hasWithinReflectionInfo()) {
255 ReflectionInfo reflectInfo = context.getWithinReflectionInfo();
256 ReflectionInfo withinInfo = null;
257
258 if(reflectInfo instanceof MemberInfo) {
259 withinInfo = ((MemberInfo) reflectInfo).getDeclaringType();
260 } else if(reflectInfo instanceof ClassInfo) {
261 withinInfo = reflectInfo;
262 } else {
263 return Boolean.FALSE;
264 }
265 return visitAnnotatedNode(
266 node,
267 withinInfo);
268 } else {
269 return null;
270 }
271 }
272
273 public Object visit(ASTWithinCode node, Object data) {
274 ExpressionContext context = (ExpressionContext) data;
275
276 if(!context.hasWithinReflectionInfo()) {
277 return null;
278 }
279
280 ReflectionInfo reflectInfo = context.getWithinReflectionInfo();
281
282 if(node.isStaticInitializer()) {
283 if(reflectInfo instanceof StaticInitializationInfo) {
284
285 SimpleNode staticClinitNode = (SimpleNode) node.jjtGetChild(0);
286 ClassInfo declaringClassInfo = ((StaticInitializationInfo) reflectInfo).getDeclaringType();
287
288 boolean matchedAnnotations = visitAttributes(staticClinitNode, declaringClassInfo);
289 if(!matchedAnnotations) {
290 return Boolean.FALSE;
291 }
292
293
294 Node lastNode = staticClinitNode.jjtGetChild(staticClinitNode.jjtGetNumChildren() - 1);
295 if(lastNode instanceof ASTAttribute) {
296 return Boolean.TRUE;
297 } else {
298 return lastNode.jjtAccept(this, reflectInfo);
299 }
300 } else {
301 return Boolean.FALSE;
302 }
303 } else {
304 return visitAnnotatedNode(
305 node,
306 reflectInfo
307 );
308 }
309 }
310
311
312 public Object visit(ASTHasMethod node, Object data) {
313 ExpressionContext context = (ExpressionContext) data;
314
315
316
317 ReflectionInfo info = context.getWithinReflectionInfo();
318 ClassInfo classInfo = info instanceof MemberInfo
319 ? ((MemberInfo) info).getDeclaringType()
320 : (ClassInfo) info;
321
322 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
323 boolean hasPatternNode = !(patternNode instanceof ASTAttribute);
324
325 MethodInfo[] methodInfos = classInfo.getMethods();
326 for (int i = 0; i < methodInfos.length; i++) {
327 if (hasPatternNode) {
328 if(Boolean.FALSE.equals(patternNode.jjtAccept(this, methodInfos[i]))) {
329 continue;
330 }
331 }
332
333 boolean matchAnnotations = visitAttributes(node, methodInfos[i]);
334 if (matchAnnotations) {
335 return Boolean.TRUE;
336 }
337 }
338
339 ConstructorInfo[] constructorInfos = classInfo.getConstructors();
340 for (int i = 0; i < constructorInfos.length; i++) {
341 if (hasPatternNode) {
342 if(Boolean.FALSE.equals(patternNode.jjtAccept(this, constructorInfos[i]))) {
343 continue;
344 }
345 }
346
347 boolean matchAnnotations = visitAttributes(node, constructorInfos[i]);
348 if (matchAnnotations) {
349 return Boolean.TRUE;
350 }
351 }
352
353 return Boolean.FALSE;
354 }
355
356 public Object visit(ASTHasField node, Object data) {
357 ExpressionContext context = (ExpressionContext) data;
358
359
360
361 ReflectionInfo info = context.getWithinReflectionInfo();
362 ClassInfo classInfo = (info instanceof MemberInfo) ?
363 ((MemberInfo) info).getDeclaringType() : (ClassInfo) info;
364
365 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
366 boolean hasPatternNode = !(patternNode instanceof ASTAttribute);
367
368 FieldInfo[] fieldInfos = classInfo.getFields();
369 for (int i = 0; i < fieldInfos.length; i++) {
370 if (hasPatternNode) {
371 if (Boolean.FALSE.equals(patternNode.jjtAccept(this, fieldInfos[i]))) {
372 continue;
373 }
374 }
375
376 boolean matchAnnotations = visitAttributes(node, fieldInfos[i]);
377 if (matchAnnotations) {
378 return Boolean.TRUE;
379 }
380 }
381
382 return Boolean.FALSE;
383 }
384
385 public Object visit(ASTTarget node, Object data) {
386 ExpressionContext context = (ExpressionContext) data;
387 ReflectionInfo info = context.getReflectionInfo();
388
389
390
391
392
393
394 ClassInfo declaringType = null;
395 if (info instanceof MemberInfo) {
396
397 if (Modifier.isStatic(((MemberInfo) info).getModifiers())) {
398 return Boolean.FALSE;
399 }
400
401 declaringType = ((MemberInfo) info).getDeclaringType();
402 } else if (info instanceof ClassInfo) {
403 declaringType = (ClassInfo) info;
404 } else {
405 return Boolean.FALSE;
406 }
407
408 String boundedTypeName = node.getBoundedType(m_expressionInfo);
409
410
411 if (declaringType.isInterface()) {
412
413 if (ClassInfoHelper.instanceOf(declaringType, boundedTypeName)) {
414 return Boolean.TRUE;
415 } else {
416
417
418 return null;
419 }
420 } else {
421 return Util.booleanValueOf(ClassInfoHelper.instanceOf(declaringType, boundedTypeName));
422 }
423 }
424
425 public Object visit(ASTThis node, Object data) {
426 ExpressionContext context = (ExpressionContext) data;
427
428
429 if (context.hasWithinReflectionInfo()) {
430 ReflectionInfo withinInfo = context.getWithinReflectionInfo();
431 if (withinInfo instanceof MemberInfo) {
432
433 if (Modifier.isStatic(((MemberInfo) withinInfo).getModifiers())) {
434 return Boolean.FALSE;
435 }
436 return Util.booleanValueOf(
437 ClassInfoHelper.instanceOf(
438 ((MemberInfo) withinInfo).getDeclaringType(),
439 node.getBoundedType(m_expressionInfo)
440 )
441 );
442 } else if (withinInfo instanceof ClassInfo) {
443 return Util.booleanValueOf(
444 ClassInfoHelper.instanceOf((ClassInfo) withinInfo, node.getBoundedType(m_expressionInfo))
445 );
446 }
447 }
448 return Boolean.FALSE;
449 }
450
451 public Object visit(ASTCflow node, Object data) {
452 return null;
453 }
454
455 public Object visit(ASTCflowBelow node, Object data) {
456 return null;
457 }
458
459
460 public Object visit(ASTClassPattern node, Object data) {
461 if (data instanceof ClassInfo) {
462 ClassInfo classInfo = (ClassInfo) data;
463 TypePattern typePattern = node.getTypePattern();
464
465 if (typePattern.matchType(classInfo)
466 && visitModifiers(node, classInfo)) {
467 return Boolean.TRUE;
468 } else {
469 return Boolean.FALSE;
470 }
471 } else if (data instanceof StaticInitializationInfo) {
472 ClassInfo classInfo = ((StaticInitializationInfo) data).getDeclaringType();
473
474 if(node.getTypePattern().matchType(classInfo)) {
475 return Boolean.TRUE;
476 } else {
477 return Boolean.FALSE;
478 }
479
480
481 }
482
483 return Boolean.FALSE;
484 }
485
486 public Object visit(ASTMethodPattern node, Object data) {
487 if (data instanceof MethodInfo) {
488 MethodInfo methodInfo = (MethodInfo) data;
489 if (node.getMethodNamePattern().matches(methodInfo.getName())
490 && node.getDeclaringTypePattern().matchType(methodInfo.getDeclaringType())
491 && node.getReturnTypePattern().matchType(methodInfo.getReturnType())
492 && visitModifiers(node, methodInfo)
493 && visitParameters(node, methodInfo.getParameterTypes())) {
494 return Boolean.TRUE;
495 }
496 }
497
498 return Boolean.FALSE;
499 }
500
501 public Object visit(ASTConstructorPattern node, Object data) {
502 if (data instanceof ConstructorInfo) {
503 ConstructorInfo constructorMetaData = (ConstructorInfo) data;
504 if (node.getDeclaringTypePattern().matchType(constructorMetaData.getDeclaringType())
505 && visitModifiers(node, constructorMetaData)
506 && visitParameters(node, constructorMetaData.getParameterTypes())) {
507 return Boolean.TRUE;
508 }
509 }
510 return Boolean.FALSE;
511 }
512
513 public Object visit(ASTFieldPattern node, Object data) {
514 if (data instanceof FieldInfo) {
515 FieldInfo fieldInfo = (FieldInfo) data;
516 if (node.getFieldNamePattern().matches(fieldInfo.getName())
517 && node.getDeclaringTypePattern().matchType(fieldInfo.getDeclaringType())
518 && node.getFieldTypePattern().matchType(fieldInfo.getType())
519 && visitModifiers(node, fieldInfo)) {
520 return Boolean.TRUE;
521 }
522 }
523 return Boolean.FALSE;
524 }
525
526 public Object visit(ASTParameter node, Object data) {
527 ClassInfo parameterType = (ClassInfo) data;
528 if (node.getDeclaringClassPattern().matchType(parameterType)) {
529 return Boolean.TRUE;
530 } else {
531 return Boolean.FALSE;
532 }
533 }
534
535 public Object visit(ASTArgs node, Object data) {
536 ExpressionContext ctx = (ExpressionContext) data;
537 if (node.jjtGetNumChildren() <= 0) {
538
539 return (getParametersCount(ctx) == 0) ? Boolean.TRUE : Boolean.FALSE;
540 } else {
541
542 int expressionParameterCount = node.jjtGetNumChildren();
543 boolean isFirstArgEager = ((ASTArgParameter) node.jjtGetChild(0)).getTypePattern().isEagerWildCard();
544 boolean isLastArgEager = ((ASTArgParameter) node.jjtGetChild(node.jjtGetNumChildren() - 1))
545 .getTypePattern().isEagerWildCard();
546
547 if (isFirstArgEager && expressionParameterCount == 1) {
548 return Boolean.TRUE;
549 }
550 int contextParametersCount = getParametersCount(ctx);
551 if (isFirstArgEager && isLastArgEager) {
552 expressionParameterCount -= 2;
553 if (expressionParameterCount == 0) {
554
555 return Boolean.TRUE;
556 }
557
558
559
560
561 int matchCount = 0;
562 int ictx = 0;
563 for (int iexp = 0; iexp < expressionParameterCount; iexp++) {
564 if (ictx >= contextParametersCount) {
565
566 matchCount = -1;
567 break;
568 }
569 ctx.setCurrentTargetArgsIndex(ictx);
570
571 boolean isEager = ((ASTArgParameter) node.jjtGetChild(iexp + 1)).getTypePattern().isEagerWildCard();
572 if (isEager) {
573
574 }
575 if (Boolean.TRUE.equals((Boolean) node.jjtGetChild(iexp + 1).jjtAccept(this, ctx))) {
576 matchCount += 1;
577 ictx++;
578 } else {
579
580 matchCount = 0;
581 ictx++;
582 iexp = -1;
583 }
584 }
585 if (matchCount == expressionParameterCount) {
586 return Boolean.TRUE;
587 } else {
588 return Boolean.FALSE;
589 }
590 } else if (isFirstArgEager) {
591 expressionParameterCount--;
592 if (contextParametersCount >= expressionParameterCount) {
593
594 for (int i = 0; (i < contextParametersCount) && (expressionParameterCount - i >= 0); i++) {
595 ctx.setCurrentTargetArgsIndex(contextParametersCount - 1 - i);
596 if (Boolean.TRUE.equals(
597 (Boolean) node.jjtGetChild(expressionParameterCount - i).jjtAccept(
598 this,
599 ctx
600 )
601 )) {
602 ;
603 } else {
604 return Boolean.FALSE;
605 }
606 }
607 return Boolean.TRUE;
608 } else {
609
610 return Boolean.FALSE;
611 }
612 } else if (isLastArgEager) {
613 expressionParameterCount--;
614 if (contextParametersCount >= expressionParameterCount) {
615
616 for (int i = 0; (i < contextParametersCount) && (i < expressionParameterCount); i++) {
617 ctx.setCurrentTargetArgsIndex(i);
618 if (Boolean.TRUE.equals((Boolean) node.jjtGetChild(i).jjtAccept(this, ctx))) {
619 ;
620 } else {
621 return Boolean.FALSE;
622 }
623 }
624 return Boolean.TRUE;
625 } else {
626 return Boolean.FALSE;
627 }
628 } else {
629
630
631 if (expressionParameterCount == contextParametersCount) {
632 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
633 ctx.setCurrentTargetArgsIndex(i);
634 if (Boolean.TRUE.equals((Boolean) node.jjtGetChild(i).jjtAccept(this, ctx))) {
635 ;
636 } else {
637 return Boolean.FALSE;
638 }
639 }
640 return Boolean.TRUE;
641 } else {
642 return Boolean.FALSE;
643 }
644 }
645 }
646 }
647
648 public Object visit(ASTArgParameter node, Object data) {
649
650
651
652
653 TypePattern typePattern = node.getTypePattern();
654 TypePattern realPattern = typePattern;
655
656
657
658
659
660
661
662 int pointcutArgIndex = -1;
663 if (typePattern.getPattern().indexOf(".") < 0) {
664 String boundedType = m_expressionInfo.getArgumentType(typePattern.getPattern());
665 if (boundedType != null) {
666 pointcutArgIndex = m_expressionInfo.getArgumentIndex(typePattern.getPattern());
667 realPattern = TypePattern.compileTypePattern(boundedType, SubtypePatternType.NOT_HIERARCHICAL);
668 }
669 }
670
671 ExpressionContext ctx = (ExpressionContext) data;
672 ClassInfo argInfo = null;
673 try {
674 if (ctx.getReflectionInfo() instanceof MethodInfo) {
675 argInfo = ((MethodInfo) ctx.getReflectionInfo()).getParameterTypes()[ctx.getCurrentTargetArgsIndex()];
676 } else if (ctx.getReflectionInfo() instanceof ConstructorInfo) {
677 argInfo = ((ConstructorInfo) ctx.getReflectionInfo()).getParameterTypes()[ctx
678 .getCurrentTargetArgsIndex()];
679 } else if (ctx.getReflectionInfo() instanceof FieldInfo) {
680 argInfo = ((FieldInfo) ctx.getReflectionInfo()).getType();
681 } else if (ctx.getPointcutType().equals(PointcutType.HANDLER) && ctx.getReflectionInfo() instanceof ClassInfo) {
682 argInfo = (ClassInfo) ctx.getReflectionInfo();
683 }
684 } catch (ArrayIndexOutOfBoundsException e) {
685
686 return Boolean.FALSE;
687 }
688 if (realPattern.matchType(argInfo)) {
689 return Boolean.TRUE;
690 } else {
691 return Boolean.FALSE;
692 }
693 }
694
695 public Object visit(ASTAttribute node, Object data) {
696 boolean matchAnnotation = false;
697 List annotations = (List) data;
698 for (Iterator it = annotations.iterator(); it.hasNext();) {
699 AnnotationInfo annotation = (AnnotationInfo) it.next();
700 if (annotation.getName().equals(node.getName())) {
701 matchAnnotation = true;
702 }
703 }
704 if (node.isNot()) {
705 return Util.booleanValueOf(!matchAnnotation);
706 } else {
707 return Util.booleanValueOf(matchAnnotation);
708 }
709 }
710
711 public Object visit(ASTModifier node, Object data) {
712 ReflectionInfo refInfo = (ReflectionInfo) data;
713 int modifiersToMatch = refInfo.getModifiers();
714 int modifierPattern = node.getModifier();
715 if (node.isNot()) {
716 if ((modifierPattern & Modifier.PUBLIC) != 0) {
717 if (((modifiersToMatch & Modifier.PUBLIC) == 0)) {
718 return Boolean.TRUE;
719 } else {
720 return Boolean.FALSE;
721 }
722 } else if ((modifierPattern & Modifier.PROTECTED) != 0) {
723 if ((modifiersToMatch & Modifier.PROTECTED) == 0) {
724 return Boolean.TRUE;
725 } else {
726 return Boolean.FALSE;
727 }
728 } else if ((modifierPattern & Modifier.PRIVATE) != 0) {
729 if ((modifiersToMatch & Modifier.PRIVATE) == 0) {
730 return Boolean.TRUE;
731 } else {
732 return Boolean.FALSE;
733 }
734 } else if ((modifierPattern & Modifier.STATIC) != 0) {
735 if ((modifiersToMatch & Modifier.STATIC) == 0) {
736 return Boolean.TRUE;
737 } else {
738 return Boolean.FALSE;
739 }
740 } else if ((modifierPattern & Modifier.SYNCHRONIZED) != 0) {
741 if ((modifiersToMatch & Modifier.SYNCHRONIZED) == 0) {
742 return Boolean.TRUE;
743 } else {
744 return Boolean.FALSE;
745 }
746 } else if ((modifierPattern & Modifier.FINAL) != 0) {
747 if ((modifiersToMatch & Modifier.FINAL) == 0) {
748 return Boolean.TRUE;
749 } else {
750 return Boolean.FALSE;
751 }
752 } else if ((modifierPattern & Modifier.TRANSIENT) != 0) {
753 if ((modifiersToMatch & Modifier.TRANSIENT) == 0) {
754 return Boolean.TRUE;
755 } else {
756 return Boolean.FALSE;
757 }
758 } else if ((modifierPattern & Modifier.VOLATILE) != 0) {
759 if ((modifiersToMatch & Modifier.VOLATILE) == 0) {
760 return Boolean.TRUE;
761 } else {
762 return Boolean.FALSE;
763 }
764 } else if ((modifierPattern & Modifier.STRICT) != 0) {
765 if ((modifiersToMatch & Modifier.STRICT) == 0) {
766 return Boolean.TRUE;
767 } else {
768 return Boolean.FALSE;
769 }
770 } else {
771 return Boolean.FALSE;
772 }
773 } else {
774 if ((modifierPattern & Modifier.PUBLIC) != 0) {
775 if (((modifiersToMatch & Modifier.PUBLIC) == 0)) {
776 return Boolean.FALSE;
777 } else {
778 return Boolean.TRUE;
779 }
780 } else if ((modifierPattern & Modifier.PROTECTED) != 0) {
781 if ((modifiersToMatch & Modifier.PROTECTED) == 0) {
782 return Boolean.FALSE;
783 } else {
784 return Boolean.TRUE;
785 }
786 } else if ((modifierPattern & Modifier.PRIVATE) != 0) {
787 if ((modifiersToMatch & Modifier.PRIVATE) == 0) {
788 return Boolean.FALSE;
789 } else {
790 return Boolean.TRUE;
791 }
792 } else if ((modifierPattern & Modifier.STATIC) != 0) {
793 if ((modifiersToMatch & Modifier.STATIC) == 0) {
794 return Boolean.FALSE;
795 } else {
796 return Boolean.TRUE;
797 }
798 } else if ((modifierPattern & Modifier.SYNCHRONIZED) != 0) {
799 if ((modifiersToMatch & Modifier.SYNCHRONIZED) == 0) {
800 return Boolean.FALSE;
801 } else {
802 return Boolean.TRUE;
803 }
804 } else if ((modifierPattern & Modifier.FINAL) != 0) {
805 if ((modifiersToMatch & Modifier.FINAL) == 0) {
806 return Boolean.FALSE;
807 } else {
808 return Boolean.TRUE;
809 }
810 } else if ((modifierPattern & Modifier.TRANSIENT) != 0) {
811 if ((modifiersToMatch & Modifier.TRANSIENT) == 0) {
812 return Boolean.FALSE;
813 } else {
814 return Boolean.TRUE;
815 }
816 } else if ((modifierPattern & Modifier.VOLATILE) != 0) {
817 if ((modifiersToMatch & Modifier.VOLATILE) == 0) {
818 return Boolean.FALSE;
819 } else {
820 return Boolean.TRUE;
821 }
822 } else if ((modifierPattern & Modifier.STRICT) != 0) {
823 if ((modifiersToMatch & Modifier.STRICT) == 0) {
824 return Boolean.FALSE;
825 } else {
826 return Boolean.TRUE;
827 }
828 } else {
829 return Boolean.TRUE;
830 }
831 }
832 }
833
834 protected boolean visitAttributes(SimpleNode node, ReflectionInfo refInfo) {
835 int nrChildren = node.jjtGetNumChildren();
836 if (nrChildren != 0) {
837 for (int i = 0; i < nrChildren; i++) {
838 Node child = node.jjtGetChild(i);
839 if (child instanceof ASTAttribute) {
840 List annotations = refInfo.getAnnotations();
841 if (Boolean.TRUE.equals(child.jjtAccept(this, annotations))) {
842 continue;
843 } else {
844 return false;
845 }
846 }
847 }
848 }
849 return true;
850 }
851
852 protected boolean visitModifiers(SimpleNode node, ReflectionInfo refInfo) {
853 int nrChildren = node.jjtGetNumChildren();
854 if (nrChildren != 0) {
855 for (int i = 0; i < nrChildren; i++) {
856 Node child = node.jjtGetChild(i);
857 if (child instanceof ASTModifier) {
858 if (Boolean.TRUE.equals(child.jjtAccept(this, refInfo))) {
859 continue;
860 } else {
861 return false;
862 }
863 }
864 }
865 }
866 return true;
867 }
868
869 protected boolean visitParameters(SimpleNode node, ClassInfo[] parameterTypes) {
870 int nrChildren = node.jjtGetNumChildren();
871 if (nrChildren <= 0) {
872 return (parameterTypes.length == 0);
873 }
874
875
876 List parameterNodes = new ArrayList();
877 for (int i = 0; i < nrChildren; i++) {
878 Node child = node.jjtGetChild(i);
879 if (child instanceof ASTParameter) {
880 parameterNodes.add(child);
881 }
882 }
883
884 if (parameterNodes.size() <= 0) {
885 return (parameterTypes.length == 0);
886 }
887
888
889
890
891
892 int expressionParameterCount = parameterNodes.size();
893 boolean isFirstArgEager = ((ASTParameter) parameterNodes.get(0)).getDeclaringClassPattern().isEagerWildCard();
894 boolean isLastArgEager = ((ASTParameter) parameterNodes.get(expressionParameterCount - 1)).getDeclaringClassPattern()
895 .isEagerWildCard();
896
897 if (isFirstArgEager && expressionParameterCount == 1) {
898 return true;
899 }
900 int contextParametersCount = parameterTypes.length;
901 if (isFirstArgEager && isLastArgEager) {
902 expressionParameterCount -= 2;
903 if (expressionParameterCount == 0) {
904
905 return true;
906 }
907
908
909
910
911 int matchCount = 0;
912 int ictx = 0;
913 for (int iexp = 0; iexp < expressionParameterCount; iexp++) {
914 if (ictx >= contextParametersCount) {
915
916 matchCount = -1;
917 break;
918 }
919
920 ASTParameter parameterNode = (ASTParameter) parameterNodes.get(iexp + 1);
921 boolean isEager = parameterNode.getDeclaringClassPattern().isEagerWildCard();
922 if (isEager) {
923
924 }
925 if (Boolean.TRUE.equals((Boolean) parameterNode.jjtAccept(this, parameterTypes[ictx]))) {
926 matchCount += 1;
927 ictx++;
928 } else {
929
930 matchCount = 0;
931 ictx++;
932 iexp = -1;
933 }
934 }
935 if (matchCount == expressionParameterCount) {
936 return true;
937 } else {
938 return false;
939 }
940 } else if (isFirstArgEager) {
941 expressionParameterCount--;
942 if (contextParametersCount >= expressionParameterCount) {
943
944 for (int i = 0; (i < contextParametersCount) && (expressionParameterCount - i >= 0); i++) {
945 ASTParameter parameterNode = (ASTParameter) parameterNodes.get(expressionParameterCount - i);
946 if (Boolean.TRUE.equals(
947 (Boolean) parameterNode.jjtAccept(
948 this,
949 parameterTypes[contextParametersCount - 1 - i]
950 )
951 )) {
952 ;
953 } else {
954 return false;
955 }
956 }
957 return true;
958 } else {
959
960 return false;
961 }
962 } else if (isLastArgEager) {
963 expressionParameterCount--;
964 if (contextParametersCount >= expressionParameterCount) {
965
966 for (int i = 0; (i < contextParametersCount) && (i < expressionParameterCount); i++) {
967 ASTParameter parameterNode = (ASTParameter) parameterNodes.get(i);
968 if (Boolean.TRUE.equals((Boolean) parameterNode.jjtAccept(this, parameterTypes[i]))) {
969 ;
970 } else {
971 return false;
972 }
973 }
974 return true;
975 } else {
976 return false;
977 }
978 } else {
979
980
981 if (expressionParameterCount == contextParametersCount) {
982 for (int i = 0; i < parameterNodes.size(); i++) {
983 ASTParameter parameterNode = (ASTParameter) parameterNodes.get(i);
984 if (Boolean.TRUE.equals((Boolean) parameterNode.jjtAccept(this, parameterTypes[i]))) {
985 ;
986 } else {
987 return false;
988 }
989 }
990 return true;
991 } else {
992 return false;
993 }
994 }
995 }
996
997 /***
998 * Returns the string representation of the expression.
999 *
1000 * @return
1001 */
1002 public String toString() {
1003 return m_expression;
1004 }
1005
1006 /***
1007 * Returns the number of parameters to the target method/constructor else -1.
1008 *
1009 * @param ctx
1010 * @return
1011 */
1012 private int getParametersCount(final ExpressionContext ctx) {
1013 ReflectionInfo reflectionInfo = ctx.getReflectionInfo();
1014 if (reflectionInfo instanceof MethodInfo) {
1015 return ((MethodInfo) reflectionInfo).getParameterTypes().length;
1016 } else if (reflectionInfo instanceof ConstructorInfo) {
1017 return ((ConstructorInfo) reflectionInfo).getParameterTypes().length;
1018 } else if (reflectionInfo instanceof FieldInfo) {
1019 return 1;
1020 } else if (ctx.getPointcutType().equals(PointcutType.HANDLER) && reflectionInfo instanceof ClassInfo) {
1021
1022 return 1;
1023 } else {
1024 return -1;
1025 }
1026 }
1027
1028 /***
1029 * Test the context upon the expression tree, under a node that can
1030 * contain annotations.
1031 *
1032 * @param node root node of the annotation expression
1033 * @param reflectInfo context reflection info
1034 *
1035 * @return <CODE>Boolean.TRUE</CODE> in case the <tt>reflectInfo</tt> match
1036 * the expression subtree, <CODE>Boolean.FALSE</CODE> otherwise.
1037 */
1038 protected Object visitAnnotatedNode(SimpleNode node,
1039 ReflectionInfo reflectInfo) {
1040
1041 Node patternNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
1042 if (!(patternNode instanceof ASTAttribute)) {
1043 if (Boolean.FALSE.equals((Boolean)patternNode.jjtAccept(this, reflectInfo))) {
1044 return Boolean.FALSE;
1045 }
1046 }
1047
1048 boolean matchedAnnotations = visitAttributes(node, reflectInfo);
1049 if (!matchedAnnotations) {
1050 return Boolean.FALSE;
1051 } else {
1052 return Boolean.TRUE;
1053 }
1054 }
1055
1056 /***
1057 * Access the ASTRoot we visit
1058 *
1059 * @return
1060 */
1061 public Node getASTRoot() {
1062 return m_root;
1063 }
1064
1065 /***
1066 * Access the ExpressionInfo we are build on
1067 *
1068 * @return
1069 */
1070 public ExpressionInfo getExpressionInfo() {
1071 return m_expressionInfo;
1072 }
1073 }