KickJava   Java API By Example, From Geeks To Geeks.

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


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.exception.DefinitionException;
11 import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
12 import org.codehaus.aspectwerkz.expression.ast.ASTRoot;
13 import org.codehaus.aspectwerkz.expression.ast.ExpressionParser;
14 import org.codehaus.aspectwerkz.expression.ast.SimpleNode;
15 import org.codehaus.aspectwerkz.expression.ast.Node;
16 import org.codehaus.aspectwerkz.expression.regexp.Pattern;
17 import org.codehaus.aspectwerkz.util.SequencedHashMap;
18 import org.codehaus.aspectwerkz.util.ContextClassLoader;
19 import org.codehaus.aspectwerkz.joinpoint.JoinPoint;
20 import org.codehaus.aspectwerkz.joinpoint.StaticJoinPoint;
21 import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
22 import org.codehaus.aspectwerkz.reflect.ClassInfo;
23 import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo;
24 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
25 import org.codehaus.aspectwerkz.cflow.CflowAspectExpressionVisitor;
26
27 import java.util.Map JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.ArrayList JavaDoc;
31
32 /**
33  * Abstraction that holds info about the expression and the different visitors.
34  * <br/>
35  * We are using a lazy initialization for m_hasCflowPointcut field to allow to fully resolve each expression (that is f.e. on IBM
36  * compiler, fields are in the reverse order, thus pointcut reference in aspect defined with annotations
37  * may not be resolved until the whole class has been parsed.
38  *
39  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
40  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
41  */

42 public class ExpressionInfo {
43
44     public final static String JavaDoc JOINPOINT_CLASS_NAME = JoinPoint.class.getName();
45     public final static String JavaDoc STATIC_JOINPOINT_CLASS_NAME = StaticJoinPoint.class.getName();
46     public final static String JavaDoc JOINPOINT_ABBREVIATION = "JoinPoint";
47     public final static String JavaDoc STATIC_JOINPOINT_ABBREVIATION = "StaticJoinPoint";
48     public final static String JavaDoc RTTI_ABBREVIATION = "Rtti";
49
50     /**
51      * The sole instance of the parser.
52      */

53     private static final ExpressionParser s_parser = new ExpressionParser(System.in);
54
55     private final ExpressionVisitor m_expression;
56
57     private final AdvisedClassFilterExpressionVisitor m_advisedClassFilterExpression;
58
59     private final CflowAspectExpressionVisitor m_cflowAspectExpression;
60
61     /**
62      * Ordered map of the pointcut arguments type, indexed by their name.
63      */

64     private Map m_argsTypeByName = new SequencedHashMap();
65
66     /**
67      * List<String> of possible arguments names/references that appear in the expression.
68      * Note that afterReturning/Throwing binding will not appear here (not composable).
69      * This list is lasily populated once using the ExpressionValidateVisitor.
70      * Note that "types" are part of the populated list:
71      * <br/>pointcutRef(x) ==> "x"
72      * <br/>execution(...) && args(x, int) ==> "x", "int"
73      * <br/>this(..), target(..)
74      */

75     private List JavaDoc m_possibleArguments = null;
76
77     /**
78      * Name of the special argument for an afterReturning/Throwing when this one is bounded.
79      */

80     private String JavaDoc m_specialArgumentName = null;
81
82     /**
83      * Creates a new expression info instance from its string representation
84      *
85      * @param expression the expression
86      * @param namespace the namespace
87      */

88     public ExpressionInfo(final String JavaDoc expression, final String JavaDoc namespace) {
89         try {
90             Node root = s_parser.parse(expression);
91             m_expression = new ExpressionVisitor(this, expression, namespace, root);
92             m_advisedClassFilterExpression =
93                 new AdvisedClassFilterExpressionVisitor(this, expression, namespace, root);
94             m_cflowAspectExpression = new CflowAspectExpressionVisitor(this, root, namespace);
95         } catch (Throwable JavaDoc e) {
96             throw new DefinitionException("expression is not well-formed [" + expression + "]: " + e.getMessage(), e);
97         }
98     }
99
100     /**
101      * Creates a new expression info from an already parsed node
102      * This is usefull when extracting cflow sub expressions.
103      *
104      * Some attached visitor will be wrong since the string representation
105      * of the expression is not available.
106      *
107      * @param subExpression the sub expression node
108      * @param namespace the namespace
109      */

110     public ExpressionInfo(final Node subExpression, final String JavaDoc namespace) {
111         try {
112             m_expression = new ExpressionVisitor(this, "N/A", namespace, subExpression);
113             m_advisedClassFilterExpression =
114                 new AdvisedClassFilterExpressionVisitor(this, "N/A", namespace, subExpression);
115             m_cflowAspectExpression = new CflowAspectExpressionVisitor(this, subExpression, namespace);
116         } catch (Throwable JavaDoc e) {
117             throw new DefinitionException("sub expression is not well-formed from [" + subExpression+ "]: " + e.getMessage(), e);
118         }
119     }
120
121     /**
122      * Returns the regular expression.
123      *
124      * @return the regular expression
125      */

126     public ExpressionVisitor getExpression() {
127         return m_expression;
128     }
129
130     /**
131      * Returns the namespace
132      *
133      * @return
134      */

135     public String JavaDoc getNamespace() {
136         return m_expression.m_namespace;
137     }
138
139     /**
140      * Returns the cflow aspect expression.
141      *
142      * @return the cflow aspect expression
143      */

144     public CflowAspectExpressionVisitor getCflowAspectExpression() {
145         return m_cflowAspectExpression;
146     }
147
148     /**
149      * Returns the advised class filter expression.
150      *
151      * @return the advised class filter expression
152      */

153     public AdvisedClassFilterExpressionVisitor getAdvisedClassFilterExpression() {
154         return m_advisedClassFilterExpression;
155     }
156
157     /**
158      * Returns the parser.
159      *
160      * @return the parser
161      */

162     public static ExpressionParser getParser() {
163         return s_parser;
164     }
165
166     /**
167      * Returns the expression as string.
168      *
169      * @return the expression as string
170      */

171     public String JavaDoc toString() {
172         return m_expression.toString();
173     }
174
175     /**
176      * Add an argument extracted from the call signature of the expression info.
177      * Check is made to ensure that the argument is part of an args(..) or pointcutReference(..) subexpression.
178      * Note that specialArgument for afterReturning/Throwing is handled in a different way.
179      *
180      * @param name
181      * @param className
182      * @param loader
183      */

184     public void addArgument(final String JavaDoc name, final String JavaDoc className, final ClassLoader JavaDoc loader) {
185         //AW-241
186
// Note: we do not check the signature and we ignore JoinPoint parameters types
187
String JavaDoc expression = toString();
188         // fast check if we have a parenthesis
189
if (expression.indexOf('(') > 0) {
190             // fast check if the given argument (that appears in the advice signature) is part of the pointcut expression
191
if (!isJoinPointOrRtti(className, loader)) {
192                 if (toString().indexOf(name) < 0) {
193                     throw new DefinitionException(
194                             "pointcut expression is missing a parameter that has been encountered in the advice: '"
195                             + toString() + "' - '" + name + "' of type '" + className +
196                             "' missing in '" +
197                             getExpression().m_namespace +
198                             "'"
199                     );
200                 } else {
201                     // lazily populate the possible argument list
202
if (m_possibleArguments == null) {
203                         m_possibleArguments = new ArrayList JavaDoc();
204                         new ExpressionValidateVisitor(toString(), getNamespace(), getExpression().m_root)
205                                 .populate(m_possibleArguments);
206                     }
207                     if (!m_possibleArguments.contains(name)) {
208                         throw new DefinitionException(
209                                 "pointcut expression is missing a parameter that has been encountered in the advice: '"
210                                 + toString() + "' - '" + name + "' of type '" +
211                                 className +
212                                 "' missing in '" +
213                                 getExpression().m_namespace +
214                                 "'"
215                         );
216                     }
217                 }
218             }
219         }
220         m_argsTypeByName.put(name, className);
221     }
222
223     /**
224      * Set the bounded name of the special argument for afterReturning/Throwing binding
225      *
226      * @param specialArgumentName
227      */

228     public void setSpecialArgumentName(String JavaDoc specialArgumentName) {
229         m_specialArgumentName = specialArgumentName;
230     }
231
232     /**
233      * Get the bounded name of the special argument for afterReturning/Throwing binding
234      *
235      * @return
236      */

237     public String JavaDoc getSpecialArgumentName() {
238         return m_specialArgumentName;
239     }
240
241     /**
242      * Returns the argumen type.
243      *
244      * @param parameterName
245      * @return
246      */

247     public String JavaDoc getArgumentType(final String JavaDoc parameterName) {
248         return (String JavaDoc) m_argsTypeByName.get(parameterName);
249     }
250
251     /**
252      * Returns the argument index.
253      *
254      * @param parameterName
255      * @return
256      */

257     public int getArgumentIndex(final String JavaDoc parameterName) {
258         if (m_argsTypeByName.containsKey(parameterName)) {
259             return ((SequencedHashMap) m_argsTypeByName).indexOf(parameterName);
260         } else {
261             return -1;
262         }
263     }
264
265     /**
266      * Returns the argument at the given index.
267      *
268      * @param index
269      * @return paramName
270      */

271     public String JavaDoc getArgumentNameAtIndex(final int index) {
272         if (index >= m_argsTypeByName.size()) {
273             throw new ArrayIndexOutOfBoundsException JavaDoc(
274                     "cannot get argument at index " +
275                     index + " in " + m_expression.toString()
276             );
277         }
278         return (String JavaDoc) m_argsTypeByName.keySet().toArray()[index];
279     }
280
281     /**
282      * Returns all argument names.
283      *
284      * @return
285      */

286     public Set JavaDoc getArgumentNames() {
287         return m_argsTypeByName.keySet();
288     }
289
290     /**
291      * Check if the given className is one of the know argument: JoinPoint, StaticJoinPoint, Rtti
292      * <p/>
293      * className can be not qualified (for XML def simplification)
294      *
295      * @param className
296      * @param loader
297      * @return true if so
298      */

299     private boolean isJoinPointOrRtti(String JavaDoc className, final ClassLoader JavaDoc loader) {
300         if (JOINPOINT_CLASS_NAME.equals(className)
301             || STATIC_JOINPOINT_CLASS_NAME.equals(className)
302             || JOINPOINT_ABBREVIATION.equals(className)
303             || STATIC_JOINPOINT_ABBREVIATION.equals(className)
304             || RTTI_ABBREVIATION.equals(className)) {
305             return true;
306         }
307         if (className.equals("int") ||
308             className.equals("long") ||
309             className.equals("short") ||
310             className.equals("float") ||
311             className.equals("double") ||
312             className.equals("boolean") ||
313             className.equals("byte") ||
314             className.equals("char") ||
315             className.endsWith("]") ||
316             className.startsWith("java.")) {
317             return false;
318         }
319         try {
320             String JavaDoc fullClassName = (String JavaDoc) Pattern.ABBREVIATIONS.get(className);
321             if (fullClassName != null) {
322                 className = fullClassName;
323             }
324             if (className.startsWith("java.")) {
325                 return false;
326             }
327             ClassInfo classInfo = AsmClassInfo.getClassInfo(className, loader);
328             if (ClassInfoHelper.implementsInterface(classInfo, JOINPOINT_CLASS_NAME) ||
329                 ClassInfoHelper.implementsInterface(classInfo, STATIC_JOINPOINT_CLASS_NAME)) {
330                 return true;
331             }
332         } catch (Throwable JavaDoc e) {
333             throw new WrappedRuntimeException(e);
334         }
335         return false;
336     }
337
338     public void inheritPossibleArgumentFrom(ExpressionInfo expressionInfo) {
339         m_specialArgumentName = expressionInfo.m_specialArgumentName;
340         m_possibleArguments = expressionInfo.m_possibleArguments;
341         m_argsTypeByName = expressionInfo.m_argsTypeByName;
342     }
343 }
344
345
Popular Tags