KickJava   Java API By Example, From Geeks To Geeks.

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


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

35 public class ExpressionInfo {
36
37   public final static String JavaDoc JOINPOINT_CLASS_NAME = JoinPoint.class.getName();
38   public final static String JavaDoc STATIC_JOINPOINT_CLASS_NAME = StaticJoinPoint.class.getName();
39   public final static String JavaDoc JOINPOINT_ABBREVIATION = "JoinPoint";
40   public final static String JavaDoc STATIC_JOINPOINT_ABBREVIATION = "StaticJoinPoint";
41   public final static String JavaDoc RTTI_ABBREVIATION = "Rtti";
42
43   /**
44    * The sole instance of the parser.
45    */

46   private static final ExpressionParser s_parser = new ExpressionParser(System.in);
47
48   private final ExpressionVisitor m_expression;
49
50   private final AdvisedClassFilterExpressionVisitor m_advisedClassFilterExpression;
51
52   private final CflowAspectExpressionVisitor m_cflowAspectExpression;
53
54   /**
55    * Ordered map of the pointcut arguments type, indexed by their name.
56    */

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

68   private List JavaDoc m_possibleArguments = null;
69
70   /**
71    * Name of the special argument for an afterReturning/Throwing when this one is bounded.
72    */

73   private String JavaDoc m_specialArgumentName = null;
74
75   /**
76    * Creates a new expression info instance from its string representation
77    *
78    * @param expression the expression
79    * @param namespace the namespace
80    */

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

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

122   public ExpressionVisitor getExpression() {
123     return m_expression;
124   }
125
126   /**
127    * Returns the namespace
128    *
129    * @return
130    */

131   public String JavaDoc getNamespace() {
132     return m_expression.m_namespace;
133   }
134
135   /**
136    * Returns the cflow aspect expression.
137    *
138    * @return the cflow aspect expression
139    */

140   public CflowAspectExpressionVisitor getCflowAspectExpression() {
141     return m_cflowAspectExpression;
142   }
143
144   /**
145    * Returns the advised class filter expression.
146    *
147    * @return the advised class filter expression
148    */

149   public AdvisedClassFilterExpressionVisitor getAdvisedClassFilterExpression() {
150     return m_advisedClassFilterExpression;
151   }
152
153   /**
154    * Returns the expression as string.
155    *
156    * @return the expression as string
157    */

158   public String JavaDoc toString() {
159     return m_expression.toString();
160   }
161
162   /**
163    * Add an argument extracted from the call signature of the expression info.
164    * Check is made to ensure that the argument is part of an args(..) or pointcutReference(..) subexpression.
165    * Note that specialArgument for afterReturning/Throwing is handled in a different way.
166    *
167    * @param name
168    * @param className
169    * @param loader
170    */

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

215   public void setSpecialArgumentName(String JavaDoc specialArgumentName) {
216     m_specialArgumentName = specialArgumentName;
217   }
218
219   /**
220    * Get the bounded name of the special argument for afterReturning/Throwing binding
221    *
222    * @return
223    */

224   public String JavaDoc getSpecialArgumentName() {
225     return m_specialArgumentName;
226   }
227
228   /**
229    * Returns the argumen type.
230    *
231    * @param parameterName
232    * @return
233    */

234   public String JavaDoc getArgumentType(final String JavaDoc parameterName) {
235     return (String JavaDoc) m_argsTypeByName.get(parameterName);
236   }
237
238   /**
239    * Returns the argument index.
240    *
241    * @param parameterName
242    * @return
243    */

244   public int getArgumentIndex(final String JavaDoc parameterName) {
245     if (m_argsTypeByName.containsKey(parameterName)) {
246       return ((SequencedHashMap) m_argsTypeByName).indexOf(parameterName);
247     } else {
248       return -1;
249     }
250   }
251
252   /**
253    * Returns the argument at the given index.
254    *
255    * @param index
256    * @return paramName
257    */

258   public String JavaDoc getArgumentNameAtIndex(final int index) {
259     if (index >= m_argsTypeByName.size()) {
260       throw new ArrayIndexOutOfBoundsException JavaDoc(
261               "cannot getDefault argument at index " +
262                       index + " in " + m_expression.toString()
263       );
264     }
265     return (String JavaDoc) m_argsTypeByName.keySet().toArray()[index];
266   }
267
268   /**
269    * Returns all argument names.
270    *
271    * @return
272    */

273   public Set JavaDoc getArgumentNames() {
274     return m_argsTypeByName.keySet();
275   }
276
277   /**
278    * Check if the given className is one of the know argument: JoinPoint, StaticJoinPoint, Rtti
279    * <p/>
280    * className can be not qualified (for XML def simplification)
281    *
282    * @param className
283    * @param loader
284    * @return true if so
285    */

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