| ReloadingClassLoader.java |
1 package gate.util;
2
3 /**
4 * A ClassLoader that supports class reloading.
5 * It maintains a list of URLs which are searched for classes not found in the
6 * system classloader.
7 * URLs can be loaded and unloaded. Loading the same URL twice will cause the
8 * jar file or directory pointed by the URL to be reloaded.
9 */
10
11 import java.net.URL;
12 import java.net.URLClassLoader;
13 import java.util.*;
14
15 public class ReloadingClassLoader extends ClassLoader {
16
17 /**
18 * Constructs a ReloadingClassLoader using a custom class loader as parent.
19 *
20 * @param parent the parent class loader. The parent class loader should give
21 * access to the system classes at the least (in order to load a new class
22 * access to {@link java.lang.Object} is required).
23 */
24 public ReloadingClassLoader(ClassLoader parent){
25 this.parent = parent;
26 loaders = new HashMap();
27 }
28
29
30 /**
31 * Constructs a ReloadingClassLoader using the System Class Loader as a
32 * parent.
33 */
34 public ReloadingClassLoader() {
35 this(ClassLoader.getSystemClassLoader());
36 }
37
38 /**
39 * Registers an URL as a location where class files can be found.
40 * If the URL was already registered the the classes found at the location
41 * will be reloaded.
42 * @param url the URL pointing to a jar file or to a directory containing
43 * class files.
44 */
45 public void load(URL url){
46 LocationClassLoader loader = new LocationClassLoader(url);
47 loaders.put(url, loader);
48 }
49
50 /**
51 * Removes a registered URL.
52 * @param url the URl to be unloaded.
53 */
54 public void unload(URL url){
55 loaders.remove(url);
56 }
57
58 /**
59 * Loads the class with the specified name. It searches for classes in the
60 * following order:
61 * <ol>
62 * <li>the parent classloader</li>
63 * <li>all the locations registered with this class loader</li>
64 * </ol>
65 *
66 * @param name The name of the class
67 * @param resolve If <tt>true</tt> then resolve the class
68 * @return The resulting <tt>Class</tt> object
69 * @throws ClassNotFoundException If the class could not be found
70 */
71 protected synchronized Class loadClass(String name, boolean resolve)
72 throws ClassNotFoundException{
73 Class c = null;
74 //check with the parent (most classes are fixed)
75 if(parent != null){
76 try {
77 c = parent.loadClass(name);
78 }catch (ClassNotFoundException cnfe) {}
79 }
80
81 if(c == null){
82 //Check all the loaders for the class
83 Iterator loaderIter = loaders.values().iterator();
84 while (c == null && loaderIter.hasNext()) {
85 LocationClassLoader aLoader = (LocationClassLoader) loaderIter.next();
86 try {
87 c = aLoader.loadClass(name, false);
88 } catch (ClassNotFoundException e) {}
89 }
90 }
91 if(c == null) throw new ClassNotFoundException(name);
92 if (resolve) resolveClass(c);
93 return c;
94 }
95
96 /**
97 * A ClassLoader that loads classes from a location specified by an URL.
98 */
99 protected class LocationClassLoader extends URLClassLoader {
100
101 /**
102 * Constructs a LocationClassLoader for a specified URL.
103 * Uses the same parent classloader as the enclosing ReloadingClassLoader.
104 * @param location the URL to be searched for class files.
105 */
106 public LocationClassLoader(URL location) {
107 super(new URL[]{location}, null);
108 this.location = location;
109 classCache = new HashMap();
110 }
111
112 /**
113 * Loads the class with the specified name. It will search first the parent
114 * class loader, then an internal cache for classes already loaded and then
115 * the registered URL.
116 *
117 * @param name The name of the class
118 * @param resolve If <tt>true</tt> then resolve the class
119 * @return The resulting <tt>Class</tt> object
120 *
121 * @throws ClassNotFoundException If the class could not be found
122 */
123 protected synchronized Class loadClass(String name, boolean resolve)
124 throws ClassNotFoundException{
125 Class c = null;
126 //search the parent first
127 if(parent != null){
128 try {
129 c = parent.loadClass(name);
130 }catch (ClassNotFoundException cnfe) {}
131 }
132 //search the cache
133 if(c == null){
134 c = (Class) classCache.get(name);
135 }
136 //search the registered location
137 if (c == null) {
138 //this will trow ClassNotFoundException if necessary
139 c = findClass(name);
140 //save the class for future searches
141 classCache.put(name, c);
142 }
143 if (resolve) {
144 resolveClass(c);
145 }
146 return c;
147 }
148
149 /**
150 * A cache for classes already found and loaded.
151 */
152 protected Map classCache;
153 /**
154 * The location to be searched for new classes.
155 */
156 protected URL location;
157 }//protected class LocationClassLoader
158
159
160 /**
161 * Map that contains the {@link LocationClassLoader} for each registered URL.
162 */
163 protected Map loaders;
164
165 /**
166 * The parent class loader.
167 */
168 protected ClassLoader parent;
169 }