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.definition;
9   
10  import org.codehaus.aspectwerkz.expression.ExpressionInfo;
11  import org.codehaus.aspectwerkz.aspect.AdviceType;
12  import org.codehaus.aspectwerkz.reflect.MethodInfo;
13  import org.codehaus.aspectwerkz.util.Strings;
14  import org.codehaus.aspectwerkz.DeploymentModel;
15  import org.codehaus.aspectwerkz.cflow.CflowBinding;
16  
17  import java.util.List;
18  
19  /***
20   * Holds the meta-data for the advices.
21   *
22   * @author <a href="mailto:jboner@codehaus.org">Jonas Boner </a>
23   */
24  public class AdviceDefinition {
25  
26      /***
27       * The name of the advice.
28       * It is the advice method name and optionnaly the call signature.
29       * e.g. advice or advice() or advice(JoinPoint jp) or myadvice(JoinPoint myJp , java.lang.String foo) ...
30       */
31      private String m_name;
32  
33      /***
34       * The type of the advice.
35       */
36      private AdviceType m_type;
37  
38      /***
39       * The aspect class name.
40       */
41      private final String m_aspectClassName;
42  
43      /***
44       * The aspect name.
45       */
46      private final String m_aspectName;
47  
48      /***
49       * The pointcut expression.
50       */
51      private ExpressionInfo m_expressionInfo;
52  
53      /***
54       * The method for the advice.
55       */
56      private final MethodInfo m_method;
57  
58      /***
59       * The attribute for the advice.
60       */
61      private String m_attribute = "";
62  
63      /***
64       * The aspect definition holding this advice definition.
65       */
66      private AspectDefinition m_aspectDefinition;
67  
68      /***
69       * The special arg type, such as returning(TYPE) or throwing(TYPE).
70       */
71      private String m_specialArgumentType;
72  
73      /***
74       * Indicates if this advice will need a cflow or cflowbelow runtime check
75       */
76      private boolean m_hasCflowOrCflowBelow = false;
77  
78      /***
79       * TODO only use this method and make ctor private?
80       * <p/>
81       * Creates a new advice definition.
82       *
83       * @param adviceName          the advice name
84       * @param adviceType          the advice type
85       * @param expression          the advice expression
86       * @param specialArgumentType the arg
87       * @param aspectName          the aspect name
88       * @param aspectClassName     the aspect class name
89       * @param method              the advice method
90       * @param aspectDef           the aspect definition
91       * @return the new advice definition
92       */
93      public static AdviceDefinition newInstance(final String adviceName,
94                                                 final AdviceType adviceType,
95                                                 final String expression,
96                                                 final String specialArgumentType,
97                                                 final String aspectName,
98                                                 final String aspectClassName,
99                                                 final MethodInfo method,
100                                                final AspectDefinition aspectDef) {
101         ExpressionInfo expressionInfo = new ExpressionInfo(
102                 expression,
103                 aspectDef.getQualifiedName()
104         );
105 
106         // support for pointcut signature
107         String adviceCallSignature = null;
108         String resolvedSpecialArgumentType = specialArgumentType;
109         if (adviceName.indexOf('(') > 0) {
110             adviceCallSignature = adviceName.substring(adviceName.indexOf('(') + 1, adviceName.lastIndexOf(')'));
111             String[] parameters = Strings.splitString(adviceCallSignature, ",");
112             for (int i = 0; i < parameters.length; i++) {
113                 String[] parameterInfo = Strings.splitString(
114                         Strings.replaceSubString(parameters[i].trim(), "  ", " "),
115                         " "
116                 );
117                 // skip the parameter if this ones is a after returning / throwing binding
118                 if (parameterInfo[1].equals(specialArgumentType)) {
119                     resolvedSpecialArgumentType = parameterInfo[0];
120                     expressionInfo.setSpecialArgumentName(parameterInfo[1]);
121                 } else {
122                     expressionInfo.addArgument(
123                             parameterInfo[1],
124                             parameterInfo[0],
125                             aspectDef.getClassInfo().getClassLoader()
126                     );
127                 }
128             }
129         }
130 
131         return new AdviceDefinition(
132                 adviceName,
133                 adviceType,
134                 resolvedSpecialArgumentType,
135                 aspectName,
136                 aspectClassName,
137                 expressionInfo,
138                 method,
139                 aspectDef
140         );
141     }
142 
143     /***
144      * Creates a new advice meta-data instance.
145      *
146      * @param name                the name of the expressionInfo
147      * @param type                the type of the advice
148      * @param specialArgumentType the special arg type, such as returning(TYPE) or throwing(TYPE)
149      * @param aspectName          the name of the aspect
150      * @param aspectClassName     the class name of the aspect
151      * @param expressionInfo      the expressionInfo
152      * @param methodInfo          the methodInfo
153      */
154     public AdviceDefinition(final String name,
155                             final AdviceType type,
156                             final String specialArgumentType,
157                             final String aspectName,
158                             final String aspectClassName,
159                             final ExpressionInfo expressionInfo,
160                             final MethodInfo methodInfo,
161                             final AspectDefinition aspectDef) {
162         if (name == null) {
163             throw new IllegalArgumentException("name can not be null");
164         }
165         if (type == null) {
166             throw new IllegalArgumentException("illegal advice type");
167         }
168         if (aspectName == null) {
169             throw new IllegalArgumentException("aspect name can not be null");
170         }
171         if (aspectClassName == null) {
172             throw new IllegalArgumentException("class name can not be null");
173         }
174         if (methodInfo == null) {
175             throw new IllegalArgumentException("methodInfo can not be null");
176         }
177         if (aspectDef == null) {
178             throw new IllegalArgumentException("aspect definition can not be null");
179         }
180         m_name = name;
181         m_type = type;
182         m_specialArgumentType = specialArgumentType;
183         m_aspectName = aspectName;
184         m_aspectClassName = aspectClassName;
185         m_expressionInfo = expressionInfo;
186         m_method = methodInfo;
187         m_aspectDefinition = aspectDef;
188 
189         // get the cflow Advice bindings to know if this advice binding is using cflow or cflowbelow
190         List cflowBindings = CflowBinding.getCflowBindingsForCflowOf(m_expressionInfo);
191         m_hasCflowOrCflowBelow = (cflowBindings.size() > 0);
192     }
193 
194     /***
195      * Returns the advice type.
196      *
197      * @return the advice type
198      */
199     public AdviceType getType() {
200         return m_type;
201     }
202 
203     /***
204      * Returns the name of the advice.
205      *
206      * @return the name
207      */
208     public String getName() {
209         return m_name;
210     }
211 
212     /***
213      * Returns the fully qualified name for the advice
214      *
215      * @return the fully qualified name
216      */
217     public String getQualifiedName() {
218         return m_aspectDefinition.getQualifiedName() + '.' + m_name;
219     }
220 
221     /***
222      * Sets the name of the advice.
223      *
224      * @param name the name
225      */
226     public void setName(final String name) {
227         m_name = name.trim();
228     }
229 
230     /***
231      * Returns the expression.
232      * <p/>
233      * TODO should return NULL object if null
234      *
235      * @return the expression
236      */
237     public ExpressionInfo getExpressionInfo() {
238         return m_expressionInfo;
239     }
240 
241     /***
242      * Sets the expression info.
243      *
244      * @param newExpression the new expression info
245      */
246     public void setExpressionInfo(final ExpressionInfo newExpression) {
247         m_expressionInfo = newExpression;
248         // update the hasCflow caracteristic
249         List cflowBindings = CflowBinding.getCflowBindingsForCflowOf(m_expressionInfo);
250         m_hasCflowOrCflowBelow = (cflowBindings.size() > 0);
251     }
252 
253     /***
254      * Returns the class name.
255      *
256      * @return the class name
257      */
258     public String getAspectClassName() {
259         return m_aspectClassName;
260     }
261 
262     /***
263      * Returns the aspect name.
264      *
265      * @return the aspect name
266      */
267     public String getAspectName() {
268         return m_aspectName;
269     }
270 
271     /***
272      * Returns the special arg type, such as returning(TYPE) or throwing(TYPE).
273      *
274      * @return
275      */
276     public String getSpecialArgumentType() {
277         return m_specialArgumentType;
278     }
279 
280     /***
281      * Returns the method.
282      *
283      * @return the method
284      */
285     public MethodInfo getMethodInfo() {
286         return m_method;
287     }
288 
289     /***
290      * Returns the the deployment model for the advice
291      *
292      * @return the deployment model
293      */
294     public DeploymentModel getDeploymentModel() {
295         return m_aspectDefinition.getDeploymentModel();
296     }
297 
298     /***
299      * Returns the attribute.
300      *
301      * @return the attribute
302      */
303     public String getAttribute() {
304         return m_attribute;
305     }
306 
307     /***
308      * Sets the attribute.
309      *
310      * @param attribute the attribute
311      */
312     public void setAttribute(final String attribute) {
313         m_attribute = attribute;
314     }
315 
316     /***
317      * Returns the definition for the aspect that defines this advice.
318      *
319      * @return the aspect definition
320      */
321     public AspectDefinition getAspectDefinition() {
322         return m_aspectDefinition;
323     }
324 
325     /***
326      * Check if the advice is bound to a pointcut with cflow or cflowbelow
327      *
328      * @return
329      */
330     public boolean hasCflowOrCflowBelow() {
331         return m_hasCflowOrCflowBelow;
332     }
333 
334     /***
335      * Deep copy of the definition.
336      *
337      * @param expressionInfo
338      * @return
339      */
340     public AdviceDefinition copyAt(final ExpressionInfo expressionInfo) {
341         return new AdviceDefinition(
342                 getName(),
343                 getType(),
344                 getSpecialArgumentType(),
345                 getAspectName(),
346                 getAspectClassName(),
347                 expressionInfo,
348                 getMethodInfo(),
349                 m_aspectDefinition
350         );
351     }
352 
353     /***
354      * Equals and hashcode means we have the same advice if the aspect qualified name (not classname) and
355      * advice name (may include signature) are the same. [AW-439 fix]
356      *
357      * @param o
358      * @return
359      */
360     public boolean equals(Object o) {
361         if (this == o) return true;
362         if (!(o instanceof AdviceDefinition)) return false;
363 
364         final AdviceDefinition adviceDefinition = (AdviceDefinition) o;
365 
366         if (!m_aspectName.equals(adviceDefinition.m_aspectName)) return false;
367         if (!m_name.equals(adviceDefinition.m_name)) return false;
368 
369         return true;
370     }
371 
372     public int hashCode() {
373         int result;
374         result = m_name.hashCode();
375         result = 29 * result + m_aspectName.hashCode();
376         return result;
377     }
378 }