/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