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.exception.DefinitionException;
11  import org.codehaus.aspectwerkz.expression.ExpressionInfo;
12  import org.codehaus.aspectwerkz.expression.ExpressionNamespace;
13  import org.codehaus.aspectwerkz.util.Strings;
14  import org.codehaus.aspectwerkz.aspect.AdviceType;
15  
16  import java.lang.reflect.Method;
17  import java.util.Iterator;
18  import java.util.List;
19  import java.util.ArrayList;
20  
21  /***
22   * Helper class for the attribute and the XML definition parsers.
23   *
24   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
25   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
26   */
27  public class DefinitionParserHelper {
28      public static final String EXPR_PREFIX = "AW_";
29  
30      /***
31       * Creates and add pointcut definition to aspect definition.
32       *
33       * @param name
34       * @param expression
35       * @param aspectDef
36       */
37      public static void createAndAddPointcutDefToAspectDef(final String name,
38                                                            final String expression,
39                                                            final AspectDefinition aspectDef) {
40          PointcutDefinition pointcutDef = new PointcutDefinition(expression);
41          aspectDef.addPointcut(pointcutDef);
42  
43          // name can be the "pcName(paramType paramName)"
44          // extract the parameter name to type map
45          // and register the pointcut using its name
46          //TODO: support for same pc name and different signature
47          String pointcutName = name;
48          String pointcutCallSignature = null;
49          if (name.indexOf("(") > 0) {
50              pointcutName = name.substring(0, name.indexOf("("));
51              pointcutCallSignature = name.substring(name.indexOf("(") + 1, name.lastIndexOf(")"));
52          }
53  
54          // do a lookup first to avoid infinite recursion when:
55          // <pointcut name="pc" ...> [will be registered as pc]
56          // <advice bind-to="pc" ...> [will be registered as pc and should not override previous one !]
57          ExpressionNamespace namespace = ExpressionNamespace.getNamespace(aspectDef.getFullQualifiedName());
58          ExpressionInfo info = namespace.getExpressionInfo(pointcutName);
59          if (info == null) {
60              info = new ExpressionInfo(expression, aspectDef.getFullQualifiedName());
61              // extract the pointcut signature map
62              if (pointcutCallSignature != null) {
63                  String[] parameters = Strings.splitString(pointcutCallSignature, ",");
64                  for (int i = 0; i < parameters.length; i++) {
65                      String[] parameterInfo = Strings.splitString(
66                              Strings.replaceSubString(
67                                      parameters[i].trim(),
68                                      "  ",
69                                      " "
70                              ), " "
71                      );
72                      info.addArgument(parameterInfo[1], parameterInfo[0]);
73                  }
74              }
75          }
76          ExpressionNamespace.getNamespace(aspectDef.getFullQualifiedName()).addExpressionInfo(pointcutName, info);
77      }
78  
79      /***
80       * Creates and add introduction definition to aspect definition.
81       *
82       * @param mixinClass
83       * @param expression
84       * @param deploymentModel
85       * @param aspectDef
86       */
87      public static void createAndAddIntroductionDefToAspectDef(final Class mixinClass,
88                                                                final String expression,
89                                                                final String deploymentModel,
90                                                                final AspectDefinition aspectDef) {
91          IntroductionDefinition introDef = createIntroductionDefinition(
92                  mixinClass,
93                  expression,
94                  deploymentModel,
95                  aspectDef
96          );
97  
98          // check doublons - TODO change ArrayList to HashMap since NAME is a key
99          IntroductionDefinition doublon = null;
100         for (Iterator intros = aspectDef.getIntroductions().iterator(); intros.hasNext();) {
101             IntroductionDefinition intro = (IntroductionDefinition) intros.next();
102             if (intro.getName().equals(introDef.getName())) {
103                 doublon = intro;
104                 intro.addExpressionInfos(introDef.getExpressionInfos());
105                 break;
106             }
107         }
108         if (doublon == null) {
109             aspectDef.addIntroduction(introDef);
110         }
111     }
112 
113     /***
114      * Creates and add interface introduction definition to aspect definition.
115      *
116      * @param expression
117      * @param introductionName
118      * @param interfaceClassName
119      * @param aspectDef
120      */
121     public static void createAndAddInterfaceIntroductionDefToAspectDef(final String expression,
122                                                                        final String introductionName,
123                                                                        final String interfaceClassName,
124                                                                        final AspectDefinition aspectDef) {
125         InterfaceIntroductionDefinition introDef = createInterfaceIntroductionDefinition(
126                 introductionName,
127                 expression,
128                 interfaceClassName,
129                 aspectDef
130         );
131         aspectDef.addInterfaceIntroduction(introDef);
132     }
133 
134     /***
135      * Creates a new advice definition.
136      *
137      * @param adviceName          the advice name
138      * @param adviceType          the advice type
139      * @param expression          the advice expression
140      * @param specialArgumentType the arg
141      * @param aspectName          the aspect name
142      * @param aspectClassName     the aspect class name
143      * @param method              the advice method
144      * @param methodIndex         the advice method index
145      * @param aspectDef           the aspect definition
146      * @return the new advice definition
147      */
148     public static AdviceDefinition createAdviceDefinition(final String adviceName,
149                                                           final AdviceType adviceType,
150                                                           final String expression,
151                                                           final String specialArgumentType,
152                                                           final String aspectName,
153                                                           final String aspectClassName,
154                                                           final Method method,
155                                                           final int methodIndex,
156                                                           final AspectDefinition aspectDef) {
157         ExpressionInfo expressionInfo = new ExpressionInfo(
158                 expression,
159                 aspectDef.getFullQualifiedName()
160         );
161 
162         // support for pointcut signature
163         String adviceCallSignature = null;
164         if (adviceName.indexOf('(') > 0) {
165             adviceCallSignature = adviceName.substring(adviceName.indexOf('(') + 1, adviceName.lastIndexOf(')'));
166             String[] parameters = Strings.splitString(adviceCallSignature, ",");
167             for (int i = 0; i < parameters.length; i++) {
168                 String[] parameterInfo = Strings.splitString(
169                         Strings.replaceSubString(parameters[i].trim(), "  ", " "),
170                         " "
171                 );
172                 expressionInfo.addArgument(parameterInfo[1], parameterInfo[0]);
173             }
174         }
175 
176         final AdviceDefinition adviceDef = new AdviceDefinition(
177                 adviceName,
178                 adviceType,
179                 specialArgumentType,
180                 aspectName,
181                 aspectClassName,
182                 expressionInfo,
183                 method,
184                 methodIndex,
185                 aspectDef
186         );
187         return adviceDef;
188     }
189 
190     /***
191      * Creates an introduction definition.
192      *
193      * @param mixinClass
194      * @param expression
195      * @param deploymentModel
196      * @param aspectDef
197      * @return
198      */
199     public static IntroductionDefinition createIntroductionDefinition(final Class mixinClass,
200                                                                       final String expression,
201                                                                       final String deploymentModel,
202                                                                       final AspectDefinition aspectDef) {
203         ExpressionInfo expressionInfo = new ExpressionInfo(expression, aspectDef.getFullQualifiedName());
204 
205         // auto-name the pointcut which is anonymous for introduction
206         ExpressionNamespace.getNamespace(aspectDef.getFullQualifiedName()).addExpressionInfo(
207                 EXPR_PREFIX + expression.hashCode(),
208                 expressionInfo
209         );
210         final IntroductionDefinition introDef = new IntroductionDefinition(
211                 mixinClass, expressionInfo, deploymentModel
212         );
213         return introDef;
214     }
215 
216     /***
217      * Creates a new interface introduction definition.
218      *
219      * @param introductionName   the introduction name
220      * @param expression         the pointcut expression
221      * @param interfaceClassName the class name of the interface
222      * @param aspectDef          the aspect definition
223      * @return the new introduction definition
224      */
225     public static InterfaceIntroductionDefinition createInterfaceIntroductionDefinition(final String introductionName,
226                                                                                         final String expression,
227                                                                                         final String interfaceClassName,
228                                                                                         final AspectDefinition aspectDef) {
229         ExpressionInfo expressionInfo = new ExpressionInfo(expression, aspectDef.getFullQualifiedName());
230 
231         // auto-name the pointcut which is anonymous for introduction
232         ExpressionNamespace.getNamespace(aspectDef.getFullQualifiedName()).addExpressionInfo(
233                 EXPR_PREFIX + expression.hashCode(),
234                 expressionInfo
235         );
236         final InterfaceIntroductionDefinition introDef = new InterfaceIntroductionDefinition(
237                 introductionName,
238                 expressionInfo,
239                 interfaceClassName
240         );
241         return introDef;
242     }
243 
244 }