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.AspectSystem;
11  import org.codehaus.aspectwerkz.ContextClassLoader;
12  import org.codehaus.aspectwerkz.CrossCuttingInfo;
13  import org.codehaus.aspectwerkz.DeploymentModel;
14  import org.codehaus.aspectwerkz.SystemLoader;
15  import org.codehaus.aspectwerkz.aspect.AspectContainer;
16  import org.codehaus.aspectwerkz.aspect.CFlowSystemAspect;
17  import org.codehaus.aspectwerkz.aspect.AdviceType;
18  import org.codehaus.aspectwerkz.aspect.management.AspectManager;
19  import org.codehaus.aspectwerkz.aspect.management.Pointcut;
20  import org.codehaus.aspectwerkz.aspect.management.PointcutManager;
21  import org.codehaus.aspectwerkz.exception.DefinitionException;
22  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
23  import org.codehaus.aspectwerkz.expression.ExpressionInfo;
24  import org.codehaus.aspectwerkz.joinpoint.JoinPoint;
25  
26  import java.lang.reflect.Constructor;
27  import java.lang.reflect.InvocationTargetException;
28  import java.util.HashMap;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Map;
32  
33  /***
34   * Manages the startup procedure, walks through the definition and instantiates the
35   * aspects/advices/introduction/pointcuts. <p/>Reads the definition, either as a class of as an XML file. <p/>To use
36   * your XML definition file pass <code>-Daspectwerkz.definition.file=PathToFile</code> as parameter to the JVM. <p/>If
37   * the above given parameter is not specified, the <code>StartupManager</code> tries locate a file called
38   * <code>aspectwerkz.xml</code> in the classpath and if this fails the last attempt is to use the
39   * <code>ASPECTWERKZ_HOME/config/aspectwerkz.xml</code> file (if there is one).
40   * 
41   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
42   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
43   */
44  public class StartupManager {
45      /***
46       * The default aspect container class.
47       */
48      public static final String DEFAULT_ASPECT_CONTAINER = "org.codehaus.aspectwerkz.aspect.DefaultAspectContainerStrategy";
49  
50      /***
51       * Private constructor to prevent instantiability.
52       */
53      private StartupManager() {
54      }
55  
56      /***
57       * Loads the system definition.
58       * 
59       * @param aspectManager the aspectManager for the system
60       * @param definition the definition for the system
61       */
62      public static void initializeSystem(final AspectManager aspectManager, final SystemDefinition definition) {
63          // note: initialization check is maintained by AspectRegistry due to a lazy policy
64          registerAspects(aspectManager, definition);
65          registerPointcuts(aspectManager, definition);
66          registerCflowPointcuts(aspectManager, definition);
67      }
68  
69      /***
70       * ReLoads the system definition.
71       * 
72       * @param loader the class loader
73       * @param definition the definition for the system
74       */
75      public static void reinitializeSystem(final ClassLoader loader, final SystemDefinition definition) {
76          AspectSystem aspectSystem = SystemLoader.getSystem(loader);
77          AspectManager aspectManager = aspectSystem.getAspectManager(definition.getUuid());
78  
79          // TODO better runtime part sync with def part for RW/RuW/HotDeploy
80          // when altering existing pc, those needs to be updated manaually (see EWorldUtil)
81          registerPointcuts(aspectManager, definition);
82          registerCflowPointcuts(aspectManager, definition);
83          return;
84      }
85  
86      /***
87       * Creates a new aspect container.
88       * 
89       * @param crossCuttingInfo the cross-cutting info for the aspect
90       */
91      public static AspectContainer createAspectContainer(final CrossCuttingInfo crossCuttingInfo) {
92          String containerClassName = "";
93          try {
94              Class klass;
95              containerClassName = crossCuttingInfo.getAspectDefinition().getContainerClassName();
96              if ((containerClassName == null)
97                  || crossCuttingInfo.getAspectClass().getName().equals(CFlowSystemAspect.CLASS_NAME)) {
98                  klass = ContextClassLoader.loadClass(DEFAULT_ASPECT_CONTAINER);
99              } else {
100                 klass = ContextClassLoader.loadClass(containerClassName);
101             }
102             Constructor constructor = klass.getConstructor(new Class[] {
103                 CrossCuttingInfo.class
104             });
105             return (AspectContainer) constructor.newInstance(new Object[] {
106                 crossCuttingInfo
107             });
108         } catch (InvocationTargetException e) {
109             throw new DefinitionException(e.getTargetException().toString());
110         } catch (NoSuchMethodException e) {
111             throw new DefinitionException("aspect container does not have a valid constructor ["
112                 + containerClassName
113                 + "] (one that takes a CrossCuttingInfo instance as its only parameter): "
114                 + e.toString());
115         } catch (Throwable e) {
116             StringBuffer cause = new StringBuffer();
117             cause.append("could not create aspect container using the implementation specified [");
118             cause.append(containerClassName);
119             cause.append("] due to: ");
120             cause.append(e.toString());
121             e.printStackTrace();
122             throw new DefinitionException(cause.toString());
123         }
124     }
125 
126     /***
127      * Creates and registers the aspects defined.
128      * 
129      * @param aspectManager the aspectManager for the system
130      * @param definition the definition
131      */
132     private static void registerAspects(final AspectManager aspectManager, final SystemDefinition definition) {
133         try {
134             for (Iterator it = definition.getAspectDefinitions().iterator(); it.hasNext();) {
135                 AspectDefinition aspectDef = (AspectDefinition) it.next();
136                 registerAspect(aspectManager, aspectDef, definition.getParameters(aspectDef.getName()));
137             }
138         } catch (NullPointerException e) {
139             throw new DefinitionException("aspects not properly defined");
140         } catch (Exception e) {
141             throw new WrappedRuntimeException(e);
142         }
143     }
144 
145     /***
146      * Registers and creates a new aspect container for the aspect.
147      * 
148      * @param aspectManager the aspectManager for the system
149      * @param aspectDef the aspect definition
150      */
151     private static void registerAspect(
152         final AspectManager aspectManager,
153         final AspectDefinition aspectDef,
154         final Map parameters) {
155         try {
156             String aspectClassName = aspectDef.getClassName();
157 
158             // load the aspect class
159             final Class aspectClass;
160             try {
161                 aspectClass = aspectManager.m_system.getDefiningClassLoader().loadClass(aspectClassName);
162             } catch (ClassNotFoundException e) {
163                 throw new RuntimeException(aspectClassName + " could not be found on classpath: " + e.toString());
164             }
165             int deploymentModel;
166             if ((aspectDef.getDeploymentModel() == null) || aspectDef.getDeploymentModel().equals("")) {
167                 deploymentModel = DeploymentModel.PER_JVM;
168             } else {
169                 deploymentModel = DeploymentModel.getDeploymentModelAsInt(aspectDef.getDeploymentModel());
170             }
171 
172             //TODO: we could set the WHOLE AspectManager that defines the Aspect instead
173             final CrossCuttingInfo crossCuttingInfoPrototype = new CrossCuttingInfo(
174                 aspectManager.getUuid(),
175                 aspectClass,
176                 aspectDef.getName(),
177                 deploymentModel,
178                 aspectDef,
179                 parameters);
180             final AspectContainer container = createAspectContainer(crossCuttingInfoPrototype);
181             crossCuttingInfoPrototype.setContainer(container);
182             PointcutManager pointcutManager = new PointcutManager(aspectDef.getName(), deploymentModel);
183             aspectManager.register(container, pointcutManager);
184         } catch (Exception e) {
185             throw new WrappedRuntimeException(e);
186         }
187     }
188 
189     /***
190      * Creates and registers the aspects defined.
191      * 
192      * @param aspectManager the aspectManager for the system
193      * @param definition the AspectWerkz definition
194      */
195     private static void registerPointcuts(final AspectManager aspectManager, final SystemDefinition definition) {
196         for (Iterator it = definition.getAspectDefinitions().iterator(); it.hasNext();) {
197             AspectDefinition aspectDef = (AspectDefinition) it.next();
198             if (aspectDef.getName().equals(CFlowSystemAspect.CLASS_NAME)) {
199                 continue;
200             }
201             PointcutManager pointcutManager = aspectManager.getPointcutManager(aspectDef.getName());
202             for (Iterator it2 = aspectDef.getAroundAdvices().iterator(); it2.hasNext();) {
203                 AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
204                 Pointcut pointcut = pointcutManager.getPointcut(adviceDef.getExpressionInfo().getExpressionAsString());
205                 if (pointcut == null) {
206                     pointcut = new Pointcut(aspectManager, adviceDef.getExpressionInfo());
207                     pointcutManager.addPointcut(pointcut);
208                 }
209                 pointcut.addAroundAdvice(aspectDef.getName() + '/' + adviceDef.getName());
210             }
211             for (Iterator it2 = aspectDef.getBeforeAdvices().iterator(); it2.hasNext();) {
212                 AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
213                 Pointcut pointcut = pointcutManager.getPointcut(adviceDef.getExpressionInfo().getExpressionAsString());
214                 if (pointcut == null) {
215                     pointcut = new Pointcut(aspectManager, adviceDef.getExpressionInfo());
216                     pointcutManager.addPointcut(pointcut);
217                 }
218                 pointcut.addBeforeAdvice(aspectDef.getName() + '/' + adviceDef.getName());
219             }
220             for (Iterator it2 = aspectDef.getAfterAdvices().iterator(); it2.hasNext();) {
221                 AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
222                 Pointcut pointcut = pointcutManager.getPointcut(adviceDef.getExpressionInfo().getExpressionAsString());
223                 if (pointcut == null) {
224                     pointcut = new Pointcut(aspectManager, adviceDef.getExpressionInfo());
225                     pointcutManager.addPointcut(pointcut);
226                 }
227                 if (adviceDef.getType().equals(AdviceType.AFTER) ||
228                     adviceDef.getType().equals(AdviceType.AFTER_FINALLY)) {
229                     pointcut.addAfterFinallyAdvices(aspectDef.getName() + '/' + adviceDef.getName());
230                 }
231                 if (adviceDef.getType().equals(AdviceType.AFTER_RETURNING)) {
232                     pointcut.addAfterReturningAdvices(aspectDef.getName() + '/' + adviceDef.getName());
233                 }
234                 if (adviceDef.getType().equals(AdviceType.AFTER_THROWING)) {
235                     pointcut.addAfterThrowingAdvices(aspectDef.getName() + '/' + adviceDef.getName());
236                 }
237             }
238         }
239     }
240 
241     /***
242      * Registers the cflow pointcuts.
243      * 
244      * @param aspectManager the aspectManager for the system
245      * @param definition the AspectWerkz definition
246      */
247     private static void registerCflowPointcuts(final AspectManager aspectManager, final SystemDefinition definition) {
248         // get all aspects to be able to get all poincuts defined
249         for (Iterator it1 = definition.getAspectDefinitions().iterator(); it1.hasNext();) {
250             AspectDefinition aspectDef = (AspectDefinition) it1.next();
251             PointcutManager pointcutManager = aspectManager.getPointcutManager(aspectDef.getName());
252             List cflowPointcuts = pointcutManager.getCflowPointcuts();
253             for (Iterator it2 = cflowPointcuts.iterator(); it2.hasNext();) {
254                 Pointcut cflowPointcut = (Pointcut) it2.next();
255                 ExpressionInfo expressionInfo = cflowPointcut.getExpressionInfo();
256 
257                 // register the cflow advices in the system and create the cflow system
258                 // pointcutManager
259                 // (if it does not already exist)
260                 if (!aspectManager.hasAspect(CFlowSystemAspect.NAME)) {
261                     AspectDefinition cflowAspectDef = new AspectDefinition(
262                         CFlowSystemAspect.NAME,
263                         CFlowSystemAspect.CLASS_NAME,
264                         aspectManager.getUuid());
265                     PointcutDefinition pointcutDef = new PointcutDefinition(expressionInfo.getExpressionAsString());
266                     cflowAspectDef.setDeploymentModel(CFlowSystemAspect.DEPLOYMENT_MODEL);
267                     cflowAspectDef.addPointcut(pointcutDef);
268                     try {
269                         AdviceDefinition beforeAdviceDefinition = new AdviceDefinition(
270                             CFlowSystemAspect.PRE_ADVICE,
271                             AdviceType.BEFORE,
272                             null,
273                             cflowAspectDef.getName(),
274                             cflowAspectDef.getClassName(),
275                             expressionInfo,
276                             CFlowSystemAspect.class.getDeclaredMethod(CFlowSystemAspect.PRE_ADVICE, new Class[] {
277                                 JoinPoint.class
278                             }),
279                             CFlowSystemAspect.PRE_ADVICE_INDEX,
280                             cflowAspectDef);
281                         cflowAspectDef.addBeforeAdvice(beforeAdviceDefinition);
282                         AdviceDefinition afterAdviceDefinition = new AdviceDefinition(
283                             CFlowSystemAspect.POST_ADVICE,
284                             AdviceType.AFTER_FINALLY,
285                             null,
286                             cflowAspectDef.getName(),
287                             cflowAspectDef.getClassName(),
288                             expressionInfo,
289                             CFlowSystemAspect.class.getDeclaredMethod(CFlowSystemAspect.POST_ADVICE, new Class[] {
290                                 JoinPoint.class
291                             }),
292                             CFlowSystemAspect.POST_ADVICE_INDEX,
293                             cflowAspectDef);
294                         cflowAspectDef.addAfterAdvice(afterAdviceDefinition);
295                     } catch (NoSuchMethodException e) {
296                         ; // TODO: why ignore exception? ALEX??
297                     }
298                     definition.addAspect(cflowAspectDef);
299                     registerAspect(aspectManager, cflowAspectDef, new HashMap());
300                 }
301                 cflowPointcut.addBeforeAdvice(CFlowSystemAspect.NAME + '/' + CFlowSystemAspect.PRE_ADVICE);
302                 cflowPointcut.addAfterFinallyAdvices(CFlowSystemAspect.NAME + '/' + CFlowSystemAspect.POST_ADVICE);
303             }
304         }
305     }
306 }