View Javadoc

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.ASTCall;
11  import org.codehaus.aspectwerkz.expression.ast.ASTCflow;
12  import org.codehaus.aspectwerkz.expression.ast.ASTCflowBelow;
13  import org.codehaus.aspectwerkz.expression.ast.ASTExecution;
14  import org.codehaus.aspectwerkz.expression.ast.ASTGet;
15  import org.codehaus.aspectwerkz.expression.ast.ASTHandler;
16  import org.codehaus.aspectwerkz.expression.ast.ASTNot;
17  import org.codehaus.aspectwerkz.expression.ast.ASTPointcutReference;
18  import org.codehaus.aspectwerkz.expression.ast.ASTRoot;
19  import org.codehaus.aspectwerkz.expression.ast.ASTSet;
20  import org.codehaus.aspectwerkz.expression.ast.ASTStaticInitialization;
21  import org.codehaus.aspectwerkz.expression.ast.ASTWithin;
22  import org.codehaus.aspectwerkz.expression.ast.ASTWithinCode;
23  import org.codehaus.aspectwerkz.expression.ast.ASTArgs;
24  import org.codehaus.aspectwerkz.expression.ast.ASTArgParameter;
25  import org.codehaus.aspectwerkz.expression.ast.ASTHasField;
26  import org.codehaus.aspectwerkz.expression.ast.ASTHasMethod;
27  
28  /***
29   * The Cflow expression visitor used at runtime. <p/>This visitor does a parse on a compsosite context, based on the
30   * gathered cflow related context AND the joinpoint context. <p/>This allow to parse complex cflow expression like "(pc1
31   * AND cf1 AND cf3) OR (pc2 AND cf2)".
32   * 
33   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
34   * @author Michael Nascimento
35   */
36  public class CflowExpressionVisitorRuntime extends ExpressionVisitor {
37      /***
38       * Creates a new cflow runtime visitor.
39       * 
40       * @param expression the expression as a string
41       * @param namespace the namespace
42       * @param root the AST root
43       */
44      public CflowExpressionVisitorRuntime(final ExpressionInfo expressionInfo,
45                                           final String expression,
46                                           final String namespace,
47                                           final ASTRoot root) {
48          super(expressionInfo, expression, namespace, root);
49      }
50  
51      /***
52       * Matches the cflow information stack.
53       * 
54       * @param contexts the cflow gathered contexts
55       * @param jpContext the joinpoint context
56       * @return true if parse
57       */
58      public boolean matchCflowStack(final Object[] contexts, final ExpressionContext jpContext) {
59          CompositeContext compositeContext = new CompositeContext();
60          ExpressionContext[] ctxs = new ExpressionContext[contexts.length];
61          for (int i = 0; i < ctxs.length; i++) {
62              ctxs[i] = (ExpressionContext) contexts[i];
63          }
64          compositeContext.cflowContexts = ctxs;
65          compositeContext.expressionContext = jpContext;
66          return matchCflowStack(compositeContext);
67      }
68  
69      public Object visit(ASTNot node, Object data) {
70          Boolean match = (Boolean) node.jjtGetChild(0).jjtAccept(this, data);
71          if (match.equals(Boolean.TRUE)) {
72              return Boolean.FALSE;
73          } else {
74              return Boolean.TRUE;
75          }
76      }
77  
78      public Object visit(ASTPointcutReference node, Object data) {
79          CompositeContext context = (CompositeContext) data;
80          ExpressionNamespace namespace = ExpressionNamespace.getNamespace(m_namespace);
81          CflowExpressionVisitorRuntime expression = namespace.getCflowExpressionRuntime(node.getName());
82          return new Boolean(expression.matchCflowStack(context));
83      }
84  
85      public Object visit(ASTExecution node, Object data) {
86          return super.visit(node, ((CompositeContext) data).getLocalContext());
87      }
88  
89      public Object visit(ASTCall node, Object data) {
90          return super.visit(node, ((CompositeContext) data).getLocalContext());
91      }
92  
93      public Object visit(ASTSet node, Object data) {
94          return super.visit(node, ((CompositeContext) data).getLocalContext());
95      }
96  
97      public Object visit(ASTGet node, Object data) {
98          return super.visit(node, ((CompositeContext) data).getLocalContext());
99      }
100 
101     public Object visit(ASTHandler node, Object data) {
102         return super.visit(node, ((CompositeContext) data).getLocalContext());
103     }
104 
105     public Object visit(ASTWithin node, Object data) {
106         return super.visit(node, ((CompositeContext) data).getLocalContext());
107     }
108 
109     public Object visit(ASTWithinCode node, Object data) {
110         return super.visit(node, ((CompositeContext) data).getLocalContext());
111     }
112 
113     public Object visit(ASTStaticInitialization node, Object data) {
114         return super.visit(node, ((CompositeContext) data).getLocalContext());
115     }
116 
117     public Object visit(ASTArgs node, Object data) {
118         return super.visit(node, ((CompositeContext) data).getLocalContext());
119     }
120 
121     public Object visit(ASTHasMethod node, Object data) {
122         return super.visit(node, ((CompositeContext) data).getLocalContext());
123     }
124 
125     public Object visit(ASTHasField node, Object data) {
126         return super.visit(node, ((CompositeContext) data).getLocalContext());
127     }
128 
129     public Object visit(ASTCflow node, Object data) {
130         CompositeContext compositeContext = (CompositeContext) data;
131         try {
132             for (int i = 0; i < compositeContext.cflowContexts.length; i++) {
133                 compositeContext.localContext = compositeContext.cflowContexts[i];
134                 Boolean match = (Boolean) node.jjtGetChild(0).jjtAccept(this, data);
135                 if (match.booleanValue()) {
136                     return Boolean.TRUE;
137                 }
138             }
139             return Boolean.FALSE;
140         } finally {
141             compositeContext.localContext = null;
142         }
143     }
144 
145     public Object visit(ASTCflowBelow node, Object data) {
146         CompositeContext compositeContext = (CompositeContext) data;
147         try {
148             for (int i = 0; i < compositeContext.cflowContexts.length; i++) {
149                 compositeContext.localContext = compositeContext.cflowContexts[i];
150                 Boolean match = (Boolean) node.jjtGetChild(0).jjtAccept(this, data);
151                 if (match.booleanValue()) {
152                     return Boolean.TRUE;
153                 }
154             }
155             return Boolean.FALSE;
156         } finally {
157             compositeContext.localContext = null;
158         }
159     }
160 
161     /***
162      * Matches the cflow information stack.
163      * 
164      * @param compositeContext the composite context
165      * @return true if parse
166      */
167     private boolean matchCflowStack(final CompositeContext compositeContext) {
168         return ((Boolean) visit(m_root, compositeContext)).booleanValue();
169     }
170 
171     // --- Pattern matching is delegated to regular ExpressionVisitor thru the
172     // compositeContext.localContext
173 
174     /***
175      * A composite context for use in cflow evaluation at runtime.
176      * 
177      * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
178      */
179     static class CompositeContext {
180         public ExpressionContext expressionContext;
181 
182         public ExpressionContext[] cflowContexts;
183 
184         public ExpressionContext localContext;
185 
186         /***
187          * The actual local context is the dependent on where we are in the tree. <p/>Local context is the join point
188          * context - when outside of cflow subtree. - else it is one of the cflow contexts that we iterate over.
189          * 
190          * @return the expression
191          */
192         public ExpressionContext getLocalContext() {
193             return (localContext == null) ? expressionContext : localContext;
194         }
195     }
196 }