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
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
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
100 if (activate) {
101
102
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
111
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 }