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;
9   
10  import org.codehaus.aspectwerkz.aspect.management.AspectManager;
11  import org.codehaus.aspectwerkz.definition.SystemDefinition;
12  import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer;
13  import org.codehaus.aspectwerkz.hook.impl.ClassPreProcessorHelper;
14  import org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor;
15  import org.codehaus.aspectwerkz.transform.ClassCacheTuple;
16  
17  import java.util.Collection;
18  import java.util.Iterator;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.WeakHashMap;
22  
23  /***
24   * Stores the AspectSystem on a per ClassLoader basis. <p/>The <code>getSystem</code> method checks for system
25   * initialization. <p/>
26   * 
27   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
28   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
29   */
30  public final class SystemLoader {
31      /***
32       * Holds references to all the systems defined. Maps the ClassLoader to a matching system instance.
33       */
34      private static final Map s_systems = new WeakHashMap();
35  
36      /***
37       * Returns the System for a specific ClassLoader. If the system is not initialized, register the ClassLoader
38       * hierarchy and all the definitions to initialize the system.
39       * 
40       * @param loader the ClassLoader
41       * @return the System instance for this ClassLoader
42       */
43      public synchronized static AspectSystem getSystem(ClassLoader loader) {
44          AspectSystem system = (AspectSystem) s_systems.get(loader);
45          if (system == null) {
46              List defs = SystemDefinitionContainer.getHierarchicalDefs(loader);
47              system = new AspectSystem(loader, defs);
48              s_systems.put(loader, system);
49          }
50          return system;
51      }
52  
53      /***
54       * Returns the System for a specific instance. The instance class ClassLoader is queried. TODO: avoid bootCL lookup
55       * 
56       * @param instance
57       * @return the System instance for the instance class ClassLoader
58       */
59      public static AspectSystem getSystem(Object instance) {
60          return getSystem(instance.getClass().getClassLoader());
61      }
62  
63      /***
64       * Returns the System for a specific class. The class ClassLoader is queried. TODO: avoid bootCL lookup
65       * 
66       * @param klass
67       * @return the System instance for the class ClassLoader
68       */
69      public static AspectSystem getSystem(Class klass) {
70          return getSystem(klass.getClassLoader());
71      }
72  
73      public static Collection getAllSystems() {
74          return s_systems.values();
75      }
76  
77      public static synchronized void deploySystemDefinitions(ClassLoader loader, List definitions, boolean activate) {
78          SystemDefinitionContainer.deploySystemDefinitions(loader, definitions);
79  
80          //TODO check uuid in the bottom hierarchy
81          AspectSystem system = getSystem(loader);
82          AspectManager[] currentAspectManagers = system.getAspectManagers();
83          AspectManager[] newAspectManagers = new AspectManager[currentAspectManagers.length + definitions.size()];
84          System.arraycopy(currentAspectManagers, 0, newAspectManagers, 0, currentAspectManagers.length);
85          int index = currentAspectManagers.length;
86          for (Iterator it = definitions.iterator(); it.hasNext();) {
87              newAspectManagers[index++] = new AspectManager(system, (SystemDefinition) it.next());
88          }
89  
90          // now we should grab all subclassloader' AspectSystem and rebuild em
91          Collection systems = SystemLoader.getAllSystems();
92          for (Iterator it = systems.iterator(); it.hasNext();) {
93              AspectSystem aspectSystem = (AspectSystem) it.next();
94              if (isChildOfOrEqual(aspectSystem.getDefiningClassLoader(), loader)) {
95                  system.propagateAspectManagers(newAspectManagers, currentAspectManagers.length);
96              }
97          }
98  
99          // hotswap if needed
100         if (activate) {
101             //TODO find a better way to trigger that
102             // the singleton idea of AWPP is boring
103             AspectWerkzPreProcessor awpp = (AspectWerkzPreProcessor) ClassPreProcessorHelper.getClassPreProcessor();
104             for (Iterator it = awpp.getClassCacheTuples().iterator(); it.hasNext();) {
105                 ClassCacheTuple tuple = (ClassCacheTuple) it.next();
106                 if (isChildOfOrEqual(tuple.getClassLoader(), loader)) {
107                     try {
108                         System.out.println("hotswapping " + tuple.getClassName());
109 
110                         // TODO - HotSwap is in extensions //
111                         // HotSwapClient.hotswap(tuple.getClassLoader().loadClass(tuple.getClassName()));
112                     } catch (Throwable t) {
113                         System.err.println("WARNING: " + t.getMessage());
114                     }
115                 }
116             }
117         }
118     }
119 
120     private static boolean isChildOfOrEqual(ClassLoader loader, ClassLoader parent) {
121         if (loader.equals(parent)) {
122             return true;
123         }
124         ClassLoader currentParent = loader.getParent();
125         while (currentParent != null) {
126             if (currentParent.equals(parent)) {
127                 return true;
128             }
129             currentParent = currentParent.getParent();
130         }
131         return false;
132     }
133 }