/Users/lyon/j4p/src/classUtils/pack/util/DynamicClassLoader.java
|
1 package classUtils.pack.util;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.net.MalformedURLException;
7 import java.net.URL;
8 import java.util.Enumeration;
9
10 import classUtils.pack.util.util.DynamicClassFileFinder;
11 import classUtils.pack.util.util.DynamicJDK12ClassFileFinder;
12 import classUtils.pack.util.util.DynamicResourceFileFinder;
13
14 /**
15 * A classloader whose classpath can be set dynamically.
16 * <p>
17 * Version 1.2 adds resource support capability, but for the
18 * {@link #findResources(java.lang.String) findResources()} which
19 * is not implemented.
20 * <p>
21 * By default, the classLoader attempts to use the parent class loader,
22 * if any, to find a class. By setting the {@link #setForceDynamicLoading(boolean)
23 * forceDynamicLoading} property, the classLoader will always find
24 * classes by using the embedded {@link classUtils.pack.util.util.DynamicClassFileFinder
25 * DynamicClassFileFinder}.
26 *
27 * $Revision$
28 *
29 * @version 1.3
30 * @author cris
31 */
32 public class DynamicClassLoader extends ClassLoader {
33
34 private DynamicClassFileFinder cff;
35 private DynamicResourceFileFinder rff;
36 private boolean forceDynamicLoading;
37
38 /**
39 * Constructor for DynamicClassLoader.
40 * @param arg0
41 */
42 public DynamicClassLoader(ClassLoader arg0, DynamicClassFileFinder cff, DynamicResourceFileFinder rff) {
43 super(arg0);
44 this.cff=cff;
45 this.rff=rff;
46 }
47
48 /**
49 * Constructor for DynamicClassLoader.
50 */
51 public DynamicClassLoader(DynamicClassFileFinder cff, DynamicResourceFileFinder rff) {
52 super();
53 this.cff=cff;
54 this.rff=rff;
55 }
56
57 private static DynamicJDK12ClassFileFinder dynamicJDK12ClassFileFinder = new DynamicJDK12ClassFileFinder();
58
59 public DynamicClassFileFinder getClassFileFinder() { return cff; }
60 public DynamicResourceFileFinder getResourceFileFinder() { return rff; }
61
62
63 public DynamicClassLoader(ClassLoader arg0) {
64 this(arg0, dynamicJDK12ClassFileFinder, dynamicJDK12ClassFileFinder);
65 }
66
67 /**
68 * Add a class path entry.
69 * @param entry
70 */
71 public void addClassPathEntry(String entry) {
72 synchronized(this) {
73 cff.addClassPathEntry(entry);
74 rff.addClassPathEntry(entry);
75 }
76 }
77
78 /**
79 * Set the class path.
80 * @param classPath
81 */
82 public void setClassPath(String classPath) {
83 synchronized(this) {
84 cff.setClassPath(classPath);
85 rff.setClassPath(classPath);
86 }
87 }
88
89 /**
90 * Constructor for DynamicClassLoader.
91 */
92 public DynamicClassLoader() {
93 this(dynamicJDK12ClassFileFinder, dynamicJDK12ClassFileFinder);
94 }
95
96
97 public static void main(String[] args) {
98 DynamicClassLoader dcl = new DynamicClassLoader();
99 dynamicJDK12ClassFileFinder.addClassPathEntry("C:/mc4j/lib/core.jar");
100 InputStream is = dcl.getResourceAsStream("org/netbeans/core/resources/action.gif");
101 System.out.println(is);
102 }
103
104 /**
105 * @see java.lang.ClassLoader#findClass(java.lang.String)
106 */
107 protected Class findClass(String arg0) throws ClassNotFoundException {
108 //System.out.println("Dynamic class loader finding class "+arg0);
109 try {
110 if (forceDynamicLoading) throw new ClassNotFoundException();
111 return super.findClass(arg0);
112 } catch(ClassNotFoundException e) {
113 try {
114 //System.out.println("Searching for class "+ arg0 + "; classpath is "+cff.getClassPath());
115 byte [] data = cff.getClassBytes(arg0);
116 return this.defineClass(arg0, data,0, data.length);
117 } catch(IOException e2) {
118 e2.printStackTrace();
119 throw new ClassNotFoundException("IOException while reading definition for class "+arg0, e2);
120 }
121 }
122 }
123
124
125
126 /**
127 * @see java.lang.ClassLoader#findResource(java.lang.String)
128 */
129 protected URL findResource(String name) {
130 try {
131 File f = rff.findResourceFile(name);
132 if (f==null) return null;
133 URL fileURL = new URL("file",
134 null,
135 rff.findResourceFile(name).getCanonicalPath()
136 );
137 if (f.equals(new File(name))) // It's the resource itself
138 return fileURL;
139 else return new URL("jar:"+fileURL+"!"+name);
140 } catch (MalformedURLException e) {
141 return null;
142 } catch (IOException e) {
143 return null;
144 }
145 }
146
147 /**
148 * @see java.lang.ClassLoader#findResources(java.lang.String)
149 */
150 protected Enumeration findResources(String name) throws IOException {
151 throw new RuntimeException("findResources is not implemented by this ClassLoader");
152 }
153
154 /**
155 * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
156 */
157 public InputStream getResourceAsStream(String name) {
158 InputStream is;
159 if ((is=super.getResourceAsStream(name))!=null) return is;
160 try {
161 return rff.openResource(name);
162 } catch (IOException e) {
163 return null;
164 }
165 }
166
167 /*
168 * @see java.lang.ClassLoader#getResource(java.lang.String)
169 *
170 public URL getResource(String name) {
171 URL url=null;
172 if (getParent() != null) {
173 url = getParent().getResource(name);
174 } else {
175 url = findResource(name);
176 }
177 return url;
178 }
179 */
180
181
182 /**
183 * Returns the forceDynamicLoading.
184 * @return boolean
185 */
186 public boolean isForceDynamicLoading() {
187 return forceDynamicLoading;
188 }
189
190 /**
191 * Sets the forceDynamicLoading.
192 * @param forceDynamicLoading The forceDynamicLoading to set
193 */
194 public void setForceDynamicLoading(boolean forceDynamicLoading) {
195 this.forceDynamicLoading = forceDynamicLoading;
196 }
197
198 /**
199 * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
200 */
201 protected synchronized Class loadClass(String name, boolean resolve)
202 throws ClassNotFoundException {
203 if (forceDynamicLoading && ! name.startsWith("java.")) {
204 Class c;
205 if ((c=super.findLoadedClass(name))!=null) {
206 //System.out.println(name+" already loaded");
207 return c;
208 }
209 //System.out.println(name+" not loaded yet");
210 return findClass(name);
211 } else return super.loadClass(name, resolve);
212 }
213
214
215 }
216