home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / win95 / sieciowe / hotja32.lzh / hotjava / classsrc / net / www / html / wwwclassloader.java < prev   
Text File  |  1995-08-11  |  6KB  |  208 lines

  1. /*
  2.  * @(#)WWWClassLoader.java    1.39 95/05/21 Jonathan Payne
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package net.www.html;
  21.  
  22. import java.util.*;
  23. import java.io.*;
  24. import awt.*;
  25. import net.*;
  26. import net.www.http.*;
  27. import net.www.html.*;
  28.  
  29. public final
  30. class WWWClassLoader extends ClassLoader {
  31.     private static String urlpath[] = 
  32.     { /* "", */ "classes/", "/classes/" };
  33.     private URL source;
  34.     public URL ctx;            
  35.     Hashtable classes = new Hashtable();
  36.  
  37.     public WWWClassLoader(URL url) {
  38.     ctx = url;
  39.     source = new URL(new String(url.protocol),
  40.              new String(url.host),
  41.              new String(url.file));
  42.     }
  43.  
  44.     /**
  45.      * Load a class from an input stream
  46.      */
  47.     private Class loadClass(InputStream is) {
  48.     byte    bytes[] = new byte[4096];
  49.     byte    buffer[] = new byte[1024];
  50.     int    n;
  51.     int    totalBytes = 0;
  52.  
  53.     while ((n = is.read(buffer, 0, buffer.length)) >= 0) {
  54.         if (totalBytes + n >= bytes.length) {
  55.         byte    newbytes[] = new byte[((bytes.length + n) * 3) / 2];
  56.  
  57.         System.arraycopy(bytes, 0, newbytes, 0, totalBytes);
  58.         bytes = newbytes;
  59.         }
  60.         System.arraycopy(buffer, 0, bytes, totalBytes, n);
  61.         totalBytes += n;
  62.     }
  63.  
  64.     return defineClass(bytes, 0, totalBytes);
  65.     }
  66.  
  67.     private static Hashtable nonlocalPackages = new Hashtable();
  68.  
  69.     /**
  70.      * Check if a package is local. The package name is
  71.      * seperated by /'s.
  72.      */
  73.     public synchronized static boolean localPackage(String pkg) {
  74.  
  75.  
  76.     if (nonlocalPackages.get(pkg) != null) {
  77.         return false;
  78.     }
  79.  
  80.     // Check if the package occurs in the classpath
  81.     String str = System.getenv("CLASSPATH");
  82.     for (int i = str.indexOf(':') ; i >= 0 ; str = str.substring(i + 1), i = str.indexOf(':')) {
  83.         if (new File(str.substring(0, i) + "/" + pkg).isDirectory()) {
  84.         return true;
  85.         }
  86.     }
  87.     if ((str.length() > 0) && new File(str + "/" + pkg).isDirectory()) {
  88.         return true;
  89.     }
  90.     nonlocalPackages.put(pkg, pkg);
  91.     return false;
  92.     }
  93.  
  94.     /**
  95.      * Get the actual name of the class. We need to do
  96.      * some name mangling for backward compatibility.
  97.      */
  98.     String actualName(String name) {
  99.     if (name.startsWith("oak.")) {
  100.         return "java." + name.substring(4);
  101.     } else if (name.startsWith("webrunner.")) {
  102.         return "browser." + name.substring(10);
  103.     }
  104.     return name;
  105.     }
  106.  
  107.     /**
  108.      * Load a class from this class loader.
  109.      */
  110.     public Class loadClass(String name) {
  111.     return loadClass(name, true);
  112.     }
  113.  
  114.     /**
  115.      * Load and resolve a class.
  116.      */
  117.     protected Class loadClass(String name, boolean resolve) {
  118.     name = actualName(name);
  119.  
  120.     Class cl = (Class)classes.get(name);
  121.     if (cl == null) {
  122.         try {
  123.         return Class.forName(name);
  124.         } catch (Exception e) {}
  125.  
  126.         cl = findClass(name);
  127.     }
  128.  
  129.     if ((cl != null) && resolve) {
  130.         try {
  131.         resolveClass(cl);
  132.         } catch (Exception e) {
  133.         throw e;
  134.         }
  135.     }
  136.     return cl;
  137.     }
  138.  
  139.     /**
  140.      * This method finds a class. The returned class
  141.      * may be unresolved. This method has to be synchronized
  142.      * to avoid two threads loading the same class at the same time.
  143.      * Must be called with the actual class name.
  144.      */
  145.     private synchronized Class findClass(String name) {
  146.     Class cl = (Class)classes.get(name);
  147.     if (cl == null) {
  148.         System.out.println(Thread.currentThread().getName() + " find class " + name);
  149.  
  150.         int i = name.lastIndexOf('.');
  151.         if ((i >= 0) && localPackage(name.substring(0, i))) {
  152.         throw new NoClassDefFoundException(name);
  153.         }
  154.  
  155.         // skip the first entry if the context is "/" to avoid a
  156.         // duplicate probe
  157.         int start_index = ctx.file.equals("/") ? 1 : 0;
  158.  
  159.         for (i = start_index; i < urlpath.length; i++) {
  160.         String cpath = urlpath[i];
  161.         InputStream is = null;
  162.  
  163.         URL url = new URL(ctx, cpath + name.replace('.', '/') + ".class");
  164.  
  165.         if (!Firewall.verifyFileApplet(this) ||
  166.             (Firewall.getAppletRestriction() &&
  167.              !Firewall.verifyAppletLoading(this))) {
  168.             String msg = "Security restriction on " + url.toExternalForm();
  169.             throw new IOException(msg);
  170.         }
  171.  
  172.         System.out.println("Opening stream to: " + url.toExternalForm() + " to get " + name);
  173.         try {
  174.             is = url.openStream();
  175.             if (is != null) {
  176.             try {
  177.                 cl = loadClass(is);
  178.                 classes.put(name, cl);
  179.                 break;
  180.             } catch (FileFormatException e) {
  181.                 // There is very little we can do in this case
  182.                 // so we print a detailed message (with
  183.                 // corrective action) and rethrow the
  184.                 // exception.  
  185.                 System.err.println("File format exception when reading \"" + url.toExternalForm() + "\".");
  186.                 System.err.println("Try recompiling this class file from the source.");
  187.                 throw e;
  188.             } catch (Exception e) {
  189.                 throw e;
  190.             }
  191.             }
  192.         } catch (FileNotFoundException e) {
  193.             // It is not an error to not find the class file here, 
  194.             // just try another path.
  195.         } catch (IOException e) {
  196.  
  197.         } finally {
  198.             if (is != null) {
  199.             is.close();
  200.             }
  201.         }
  202.         }
  203.     } 
  204.     return cl;
  205.     }
  206.  
  207. }
  208.