Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/simscomputing/testbed/FileSystemClassLoader.java


1   package com.simscomputing.testbed;
2   
3   import java.io.*;
4   import java.net.*;
5   import java.util.*;
6   import java.util.jar.JarEntry;
7   import java.util.jar.JarFile;
8   import java.util.jar.JarInputStream;
9   import java.util.zip.*;
10  
11  import java.io.File;
12  import java.io.FileNotFoundException;
13  import java.io.FileInputStream;
14  import java.io.IOException;
15  import java.security.AllPermission;
16  import java.security.ProtectionDomain;
17  import java.security.Permissions;
18  import java.security.*;
19  
20  /**
21  This class is almost a trivial subclass of URLClassLoader.
22  
23  The one thing that I'm baffled by is that if I overload loadClass(),
24  then newly loaded classes have their class loader set to this class.
25  If I don't, then new classes have their class loader set to the
26  primordial class loader.
27  
28  I've no idea why this behaves this way. I've tested it under Linux JDK 1.2
29  and Windows JDK 1.3 beta.
30  
31  I need newly loaded classes to have their class loader set to
32  FileSystemClassLoader so that can be reloaded when the user clicks
33  "Re-Exercise".
34  
35  Why not just find the class file in the file system and call
36  defineClass() like almost all other custom class loaders do? Because
37  it gets real tricky when you're trying to load classes from signed jar
38  files and the like. I figured that since URLClassLoader has already
39  gone to all the trouble to do these things for me, why not use it?
40  
41  The only downside so far is that classes loaded from the CLASSPATH,
42  and not the TestClassPath, have their class loader set to the
43  primordial one, which means they can't be re-exercised properly. This
44  is why we have the concept of the TestClassPath.
45  
46  But even with this problem, the benefits outweigh the drawbacks. I get
47  to reuse a lot of JDK code which works properly even under tricky
48  security situations.
49  
50  Please let me know if you have some insight into this
51  situation. david@simscomputing.com
52  
53  @author David Sims
54  @version $Revision: 1.1.1.1 $ $Date: 2000/02/21 21:22:33 $ */
55  public class FileSystemClassLoader extends URLClassLoader {
56    private String classPath;
57    private ArrayList storageUnits;
58    private boolean debug = true;
59    private ClassLoader exemptClassLoader;
60    private ArrayList exemptPackagePrefixList = new ArrayList();
61    private boolean second = false;
62  
63    public FileSystemClassLoader(URL[] urls, ClassLoader exemptClassLoader) {
64      super(urls, exemptClassLoader);
65      this.exemptClassLoader = exemptClassLoader;
66  //      System.out.println("FSCL's excempt CL = " + exemptClassLoader.getClass().getName());
67      String classPath = System.getProperty("java.class.path", ".");
68  //      if (debug) System.out.println("*** CP is " + classPath);
69  //      setClassPath(classPath);
70    } // constructor
71  
72  //    public FileSystemClassLoader(URL[] urls) {
73  //      super(urls);
74  //      second = true;
75  //    } // constructor
76  
77  
78  //    public void exemptPackagePrefix(String prefix) {
79  //      exemptPackagePrefixList.add(prefix + ".");
80  //    }
81  
82    public Class loadClass(File file) throws ClassNotFoundException {
83      try {
84        final FileInputStream inputStream = new FileInputStream(file);
85        final long length = file.length();
86  
87        if (length > Integer.MAX_VALUE) {
88          throw new ClassNotFoundException();
89        } // if
90  
91        // a safe cast
92        final int size = (int) length;
93  
94        final byte[] bytes = new byte[ (int) size];
95  
96        if (inputStream.read(bytes) != size) {
97          throw new ClassNotFoundException();
98        } // if
99        
100       Class result = defineClass(null, bytes, 0, size);
101       resolveClass(result);
102       return result;
103     } // try
104     catch (FileNotFoundException e) {
105       throw new ClassNotFoundException(e.getMessage());
106     } // catch
107     catch (IOException e) {
108       throw new ClassNotFoundException(e.getMessage());
109     } // catch
110   } // loadClass()
111 
112 //      public Class loadClass(String name) throws ClassNotFoundException {
113 //  //        System.out.println("$$$ loadClass(" + name + ")");
114 //        return super.loadClass(name, true);
115 //      } // loadClass()
116 
117 //      public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
118 //        System.out.println("loadClass(" + name + ", " + resolve + ")");
119 //        return super.loadClass(name, resolve);
120 //      } // loadClass()
121 
122 
123   public String toString() { return "FileSystemClassLoader"; }
124 
125 //    public void setClassPath(String classPath) {
126 //      if (!classPath.equals(this.classPath)) {
127 //        this.classPath = classPath;
128 //        storageUnits = new ArrayList();
129                       
130 //        // turn the class paths, separated by File.pathSeparator, into an ArrayList of .jar files.
131 //        StringTokenizer tokens = new StringTokenizer(classPath, File.pathSeparator);
132 //        while (tokens.hasMoreTokens()) {
133 //          StorageUnit unit;
134 //          String nextToken = tokens.nextToken();
135 //          File f = new File(nextToken);
136 //          if (f.isDirectory()) {
137 //            String newurl = "file:" + nextToken;
138 //            if (nextToken.length() > 0 && nextToken.charAt(nextToken.length() - 1) != File.separatorChar) {
139 //              newurl = newurl + File.separatorChar;
140 //            } // if
141 
142 //  //            System.out.println("adding directory url: " + newurl);
143 //  //            try {
144 //  //            addURL(new URL(newurl));
145 //  //            } // try
146 //  //            catch (Exception e) {
147 //  //              e.printStackTrace();
148 //  //            } // catch
149 
150 //  //            System.out.println("CP directory: " + nextToken);
151 //            unit = new DirectoryStorageUnit(f);
152 //          } // if
153 //          else {
154 //            String newurl = "file:" + nextToken;
155 //  //            System.out.println("adding file url: " + newurl);
156 //  //            try {
157 //  //              addURL(new URL(newurl));
158 //  //            } // try
159 //  //            catch (Exception e) {
160 //  //              e.printStackTrace();
161 //  //            } // catch
162 
163 //  //            System.out.println("CP jar file: " + nextToken);
164 //            unit = new JarStorageUnit(nextToken);
165 //          } // else
166 //          storageUnits.add(unit);
167 //        } // while
168 //      } // if
169 //    } // setClassPath()
170   
171 //    /**
172 //    Enumerates all known storage units, searching for the named file, and returns
173 //    a non-null stream if it can be found.
174 //    */
175 //    private byte[] /*InputStream*/ getStream(String path, CodeSourceHolder csh) {
176 //      final int size = storageUnits.size();
177 
178 //      for (int index = 0; index < size; ++index) {
179 //        StorageUnit unit = (StorageUnit) storageUnits.get(index);
180 //  //        InputStream stream = unit.getStream(path, oi);
181 //        byte[] stream =  unit.getStream(path, csh);
182 
183 //        if (stream != null) {
184 //  //          System.out.println("getStream() success on " + 
185 //  //                             ((StorageUnit) storageUnits.get(index)).getName());
186 //          return stream;
187 //        } // if
188 //      } // for index
189 
190 //      return null;
191 //    } // getStream()
192               
193 //    private byte[] loadClassData(String name, CodeSourceHolder csh) {
194 //      System.out.println("*** loadClassData(" + name + ")");
195 //      // load the class data from the class path.
196 //      InputStream stream = null;
197 
198 //      try {
199 //        String entryName = name.replace('.', '/') + ".class";
200 //  //        OutInteger oi = new OutInteger();
201 //  //        stream = getStream(entryName, oi);
202 //        return getStream(entryName, csh);//, oi);
203 
204 //          if (stream != null) {
205 //            if (name.startsWith("BigDummy")) System.out.println("@@@@ trying to read from jar");
206 //            long size = oi.getSize();
207 //            if (name.startsWith("BigDummy")) System.out.println("@@@@ size = " + size);
208 //            byte[] data = new byte[ (int) size];
209 //            int dataread = stream.read(data);
210 //            if (name.startsWith("BigDummy")) System.out.println("@@@@ dataread = " + dataread);
211 //            return data;
212 //  //            DataInputStream input = new DataInputStream(stream);
213 //  //            input.readFully(data);
214 //  //            input.close();
215 //  //            return data;
216 //          } // if
217 //          else System.out.println("*** failed to load " + entryName);
218 
219 
220 
221 
222 
223 //        } // if
224 //        else {
225 
226 //        System.out.println("*** trying to load: " + entryName);
227 
228 //          totalBytes = read(byte[] b,
229 //                  int off,
230 //                  int len)
231 //           throws IOException
232 
233 //          final File f = new File(entryName);
234 //          if (f.exists()) {
235 //            final int size = (int) f.length();
236 //            if (size > 0) {
237 //              byte[] data = new byte[size];
238 //              DataInputStream input = new DataInputStream(new FileInputStream(f));
239 //              input.readFully(data);
240 //              input.close();
241 //              return data;
242 //            } // if
243 //          } // if
244 //  //        } // else
245 //      } // try
246 //  //      catch (IOException ioe) {
247 //  //        ioe.printStackTrace();
248 //  //        // return null below
249 //  //      } // catch
250 //      finally {
251 //        if (stream != null) {
252 //          try {
253 //            stream.close();
254 //          } // try
255 //          catch (IOException e) {
256 //            // ignore. do nothing.
257 //          } // catch
258 //        } // if
259 //      }
260     
261 //  //      return null;
262 //    } // loadClassData()
263 
264 //    public Class findClass(String name) throws ClassNotFoundException {
265 //      System.out.println("************ findClass(" + name + ") ************");
266 //      return Integer.class;
267 //    }
268 
269   /**
270   According the JDK source, loadClass is supposed to be declared as synchronzied.
271   For reasons unknown, if this method is commented out, all classes loaded by
272   this class loader will have their class loader set to primordial class loader,
273   NOT this class (FileSystemClassLoader).
274   */
275   public synchronized Class loadClass(String name, boolean resolve)
276     throws ClassNotFoundException {
277     return super.loadClass(name, resolve);
278   } // loadClass()
279 
280 
281 //        System.out.println("$$$$ loadClass(" + name + ", " + resolve + ")");
282 //        return super.loadClass(name, resolve);
283 
284     // first, check if class name's package matches one of the exempt package prefixes
285 //      final int size = exemptPackagePrefixList.size();
286 //      for (int index = 0; index < size; ++index) {
287 //        if (name.startsWith( (String) exemptPackagePrefixList.get(index)) ) {
288 //          // name is exempt from special class loading. Use the stock class loader.
289 //          if (debug) System.out.println("*** exempt: " + name);
290 //          Class result = exemptClassLoader.loadClass(name);
291 //          System.out.println("exempt: " + result.getName() + ", CL = " + result.getClassLoader().getClass().getName());
292 //          return result;
293 //  //          return super.findClass(name);
294 //        } // if
295 //      } // for index
296 
297 //      System.out.println("loading " + name);
298 
299 //      /*
300 
301 //      Class c = findLoadedClass(name);
302 //      if (c == null) {
303 //        // don't look load system classes in our class loader, because this can mess up Java.
304 //        boolean direct = true;
305 //        if ((!name.startsWith("java.")) && (!name.startsWith("javax."))) {
306 //          direct = false;
307 //          CodeSourceHolder csh = new CodeSourceHolder();
308 //          byte[] data = loadClassData(name, csh);
309 //          if (data == null) System.out.println("*********** loadClassData failed on " + name);
310 //          if (debug && name.equals("BigDummy")) System.out.println("###(loadClassData(), got back: " + data);
311 //          if (data != null) {
312 //            System.out.println("defineClass on data length " + data.length);
313 //  //            try {
314 //  //            FileOutputStream fos = new FileOutputStream("testme");
315 //  //            fos.write(data);
316 //  //            fos.close();
317 //  //            } catch (IOException e) {e.printStackTrace();}
318 //  //            URL u = null;
319 //  //            try {
320 //  //            u = new URL("file:.");
321 //  //            }
322 //  //            catch (MalformedURLException e) {
323 //  //              // do nothing
324 //  //            }
325 //  //            CodeSource codeSource = new CodeSource(u,
326 
327 //            Permissions permissions = new Permissions();
328 //            permissions.add(new AllPermission());
329 //            ProtectionDomain pd = new ProtectionDomain(csh.codeSource, permissions);
330 
331 //  //            SecureClassLoader scl = new SecureClassLoader(this);
332 //  //            c = scl.defineClass(name, data, 0, data.length, 0);
333 //            CodeSource cs = null;
334 
335 //            c = defineClass(name, data, 0, data.length, null); // null was cs
336 
337 //  //            Class superc = super.loadClass(name, resolve);
338 //  //            if (c == superc) System.out.println("c == superc");
339 //  //            try {
340 //  //              Object o = c.newInstance();
341 //  //              System.out.println("c.newInstance() = " + o);
342 //  //            }
343 //  //            catch (Exception e) {e.printStackTrace();}
344 //  //            System.out.println("c = " + c + ", superc = " + superc);
345 
346 //            if (c == null) System.out.println("******* defineClass() returned null");
347 //            if (debug && name.equals("BigDummy")) System.out.println("#### after defineClass(), got back c: " + c);
348 //          } // if
349 //        } // if
350 //        if (c == null) {
351 //  //          System.out.println("*** using stock class loader on " + name);// + ", direct = " + direct);
352 
353 
354 
355 //  //          System.out.println("*** using stock class loader (" + FileSystemClassLoader.class.getClassLoader() + ") on " + name);// + ", direct = " + direct);
356 //          return super.loadClass(name, resolve);
357 //  //          ClassLoader loader = FileSystemClassLoader.class.getClassLoader();
358 //  //          if (loader != null) {
359 //  //            return loader.loadClass(name);
360 //  //          } // if
361 //        } // if
362 //        if (c == null) {
363 //          System.out.println("*** findSystemClass on " + name);
364 //          c = findSystemClass(name);
365 //        } // if
366 //        if (c == null) {
367 //          System.out.println("*** throwing ClassNotFoundException");
368 //          throw new ClassNotFoundException(name);
369 //        } // if
370 //      } // if
371 //      else {
372 //        System.out.println("*** found loaded class: " + name);
373 //      } // else
374            
375 //      if (resolve) {
376 //        resolveClass(c);
377 //      } // if
378                       
379 //      if (c == null) {
380 //        System.out.println("*** loadClass() returns null on: " + name);
381 //      }
382 
383 //      return c;
384 
385 //        */
386 
387 //    } // loadClass()
388 
389 
390   ///////////////////
391   // inner classes //
392   ///////////////////
393 
394 //    private abstract class StorageUnit {
395 //      abstract byte[] /*InputStream*/ getStream(String path, CodeSourceHolder csh);
396 //      abstract String getName();
397 //    } // class StorageUnit
398 
399 //    /**
400 //              Retrieves class files from a directory.
401 //              */
402 //    private class DirectoryStorageUnit extends StorageUnit {
403 //      private File directory;
404 
405 //      public String getName() { return "dir storage: " + directory; }
406 
407 //      DirectoryStorageUnit(File directory) {
408 //        this.directory = directory;
409 //      } // constructor
410 
411 //      byte[] /*InputStream*/ getStream(String path, CodeSourceHolder csh) {
412 //        try {
413 //        File f = new File(directory, path);
414 //        if (f.exists()) {
415 //  //          oi.setSize(f.length());
416 //          FileInputStream fis = new FileInputStream(f);
417 //          if (fis != null) {
418 //            byte[] result = new byte[ (int) f.length()];
419 //            fis.read(result);
420 //            fis.close();
421 //            return result;
422 //          } // if
423 //        } // if
424 //        }
425 //        catch (IOException e) {
426 //          // return null below
427 //        }
428 
429 //        return null;
430 
431 //  //        return (f.exists() ? new FileInputStream(f) : null);
432 //      } // getStream()
433 //    } // class DirectoryStorageUnit
434 
435 //    /**
436 //              Retrieves class files from a jar file.
437 //              */
438 //    private class JarStorageUnit extends StorageUnit {
439 //  //      private File archivePath;
440 //  //      private ZipFile archive;
441 //      String jarFile;
442 
443 //      public String getName() { return "jar storage: " + jarFile; }
444 
445 //      JarStorageUnit(String jarFile) {
446 //        this.jarFile = jarFile;
447 //  //        archive = null;
448 //      } // constructor
449 
450 //      byte[] /*InputStream*/ getStream(String path, CodeSourceHolder csh) {
451 //  //        System.out.println("#### jar " + jarFile + " getStream: " + path);
452 //        try {
453 
454 //        // extracts just sizes only. 
455 //        final HashMap htSizes = new HashMap();
456 //        final ZipFile zf = new ZipFile(jarFile);
457 //        final Enumeration e = zf.entries();
458 //        while (e.hasMoreElements()) {
459 //          ZipEntry ze=(ZipEntry)e.nextElement();
460 //          htSizes.put(ze.getName(), new Integer((int)ze.getSize()));
461 //        } // while
462 //        zf.close();
463 //        // end
464 
465 
466 
467 //        // have to reload the archive from disk every time in case it changes
468 //  //csh        ZipFile archive = new ZipFile(jarFile);
469 //        JarFile archive = new JarFile(jarFile);
470 
471 //        FileInputStream fis = new FileInputStream(jarFile);
472 //  //csh        ZipInputStream zis = new ZipInputStream(fis);
473 //  //csh        ZipEntry ze;
474 //        JarInputStream zis = new JarInputStream(fis);
475 //        JarEntry ze;
476 
477 //  //csh        while ((ze = zis.getNextEntry()) != null) {
478 //        while ((ze = zis.getNextJarEntry()) != null) {
479 //          if (ze.isDirectory()) continue;
480 
481 //          if (ze.getName().equals(path)) {
482 //            // found our boy
483 //  //            System.out.println("!!!! ze name: " + ze.getName());
484 //  //            System.out.println("!!!! archive size = " + new File(jarFile).length());
485 //  //            System.out.println("!!!! entry size = " + ze.getSize());
486 //  //            System.out.println("!!!! entry compressed size = " + ze.getCompressedSize());
487 
488 //  //            oi.setSize(ze.getSize());
489 
490 //  //            java.security.cert.Certificate[] certs = ze.getCertificates();
491 //  //            int len = certs == null ? 0 : certs.length;
492 //  //            if (len != 0)
493 //  //              System.out.println("got " + len + " certs on " + ze.getName());
494 //  //            csh.codeSource = new CodeSource(null, certs);
495 
496 //            int size = (int) ze.getSize();
497 //            if (size == -1) {
498 //              size = ((Integer) htSizes.get(ze.getName())).intValue();
499 //  //              oi.setSize(size);
500 //  //              System.out.println("!!!! remapped size to " + size);
501 //            } // if
502 //            byte[] result = new byte[size];
503 
504 //            int rb=0;
505 //            int chunk=0;
506           
507 //            // fixme: why on earth do we have to loop like this?
508 //            while ( ((int)size - rb) > 0) {
509 //              chunk = zis.read(result, rb,(int)size - rb);
510 //              if (chunk==-1) {
511 //                break;
512 //              }
513 //              rb += chunk;
514 //            } // while
515 
516 //  //            int got = zis.read(result);
517 //  //            System.out.println("!!!! read " + rb + " bytes from " + path);
518 //            zis.close();
519 //            fis.close();
520 //            archive.close();
521 
522 //            return result;
523 //          } // if
524 
525 //        } // while
526 //        } // try
527 //        catch (IOException e) {
528 //          // return null below
529 //        }
530 
531 //        /*
532 //        ZipEntry entry = archive.getEntry(path);
533 
534 //        if (entry != null) {
535 //          if (debug) System.out.println("!!!! archive size = " + new File(jarFile).length());
536 //          if (debug) System.out.println("!!!! entry size = " + entry.getSize());
537 //          oi.setSize(entry.getSize());
538 //          InputStream input = archive.getInputStream(entry);
539 //          ZipInputStream zis = new ZipInputStream(input);
540 
541 //          final int size = (int) entry.getSize();
542 //          byte[] result = new byte[size];
543 
544 //            int rb=0;
545 //            int chunk=0;
546           
547 //            // fixme: why on earth do we have to loop like this?
548 //            while ( ((int)size - rb) > 0) {
549 //              chunk = zis.read(result, rb,(int)size - rb);
550 //              if (chunk==-1) {
551 //                break;
552 //              }
553 //              rb += chunk;
554 //            } // while
555 
556 
557 //  //          int got = input.read(result);
558 //          if (debug) System.out.println("read " + rb + " bytes from " + path);
559 //          input.close();
560 //          zis.close();
561 //          archive.close();
562 //          return result;
563 //        } // if
564 //        else {
565 //          if (debug) System.out.println("!!!! ZipEntry is null");
566 //        } // else
567 
568 //        archive.close();
569 //        */
570 
571 //        return null;
572 //      } // getStream()
573 //    } // class JarStorageUnit
574 
575 //    class OutInteger {
576 //      long size;
577 
578 //      void setSize(long newsize) { size = newsize; }
579 //      long getSize() { return size; }
580 //    } // class OutInteger
581 
582   //////////////////////////
583 
584 //    public java.net.URL findResource(String name) {
585 //      System.out.println("#### findResource(" + name + ") called");
586 //      return super.findResource(name);
587 //    }
588 
589 //    public Enumeration findResources(String name) throws IOException {
590 //      System.out.println("#### findResources(" + name + ") called");
591 //      return super.findResources(name);
592 //    }
593 
594 //    public java.net.URL getResource(String name) {
595 //      System.out.println("#### getResource(" + name + ") called");
596 //      return super.getResource(name);
597 //    }
598 
599 //    public Enumeration getResources(String name) throws IOException {
600 //      System.out.println("#### getResources(" + name + ") called");
601 //      return super.getResources(name);
602 //    }
603 
604 //    public InputStream getResourceAsStrream(String name) {
605 //      System.out.println("#### getResourceAsStream(" + name + ") called");
606 //      return super.getResourceAsStream(name);
607 //    }
608 
609 //    public String findLibrary(String library) {
610 //      System.out.println("#### findLibrary(" + library + ") called");
611 //      return super.findLibrary(library);
612 //    }
613 
614 
615 //    public Class findClass(String name) throws ClassNotFoundException {
616 //  //      try {
617 //      System.out.println("************* findClass() called: " + name);
618 //      if (true || second) {
619 //        System.out.println("************* calling super.findClass()");
620 //        Class c = super.findClass(name);
621 //        System.out.println("************* super.findClass() returned: " + c.getName());
622 //        return c;
623 //      }
624 //        throw new ClassNotFoundException();
625 //      }
626 
627 
628 //      final String testClassPath = System.getProperty("TestClassPath");
629 //      System.out.println("*** TestClassPath = " + testClassPath);
630 //      FileSystemClassLoader fileSystemClassLoader;
631 //      if (testClassPath != null) {
632 //        final StringTokenizer tokenizer = new StringTokenizer(testClassPath, File.pathSeparator);
633 //        String token;
634 //        final URL[] urls = new URL[tokenizer.countTokens()];
635 //        int index = 0;
636 //        while (tokenizer.hasMoreTokens()) {
637 //          token = tokenizer.nextToken();
638           
639 //          String fileUrl = "file:" + token;
640 //          if (token.length() > 0 && token.charAt(token.length() - 1) != File.separatorChar) {
641 //            File fileToken = new File(token);
642 //            if (fileToken.isDirectory()) {
643 //              fileUrl = fileUrl + File.separatorChar;
644 //            } // if
645 //          } // if
646 
647 //          urls[index] = new URL(fileUrl);
648 //          System.out.println(urls[index]);
649 //          ++index;
650 //        } // while
651 //        fileSystemClassLoader = new FileSystemClassLoader(urls);
652 //      } // if
653 //      else {
654 //        fileSystemClassLoader = new FileSystemClassLoader(new URL[0]);
655 //      } // else
656 //      System.out.println("*** calling loadClass() on " + name);
657 //      return fileSystemClassLoader.loadClass(name);
658 //      }
659 //      catch (Exception e) {
660 //        e.printStackTrace();
661 //        throw new ClassNotFoundException(e.getMessage());
662 //      } // catch
663 //    } // findClass()
664 
665 //    public Class findClass(String name) throws ClassNotFoundException {
666 //      System.out.println("#### findClass(" + name + ") called");
667 //      return super.findClass(name);
668 //    }
669 
670 //    class CodeSourceHolder {
671 //      public CodeSource codeSource = null;
672 //    }
673 
674 } // class FileSystemClassLoader