--- /home/cpdev/src/classpath/java/net/URLClassLoader.java	2005-07-10 05:32:36.000000000 +0000
+++ java/net/URLClassLoader.java	2005-06-30 05:34:40.000000000 +0000
@@ -62,7 +62,9 @@
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
-
+import gnu.gcj.runtime.SharedLibHelper;
+import gnu.gcj.Core;
+import gnu.java.net.protocol.core.CoreInputStream;
 
 /**
  * A secure class loader that can load classes and resources from
@@ -203,6 +205,17 @@
     }
 
     /**
+     * Returns a <code>Class</code> loaded by this
+     * <code>URLLoader</code>, or <code>null</code> when this loader
+     * either can't load the class or doesn't know how to load classes
+     * at all.
+     */
+    Class getClass(String className)
+    {
+      return null;
+    }
+
+    /**
      * Returns a <code>Resource</code> loaded by this
      * <code>URLLoader</code>, or <code>null</code> when no
      * <code>Resource</code> with the given name exists.
@@ -519,6 +532,68 @@
   }
 
   /**
+   * A <code>SoURLLoader</code> is a type of <code>URLLoader</code>
+   * that loads classes and resources from a shared library.
+   */
+  final static class SoURLLoader extends URLLoader
+  {
+    SharedLibHelper helper;
+
+    SoURLLoader(URLClassLoader classloader, URL url)
+    {
+      this(classloader, url, url);
+    }
+
+    SoURLLoader(URLClassLoader classloader, URL url, URL overrideURL)
+    {
+      super(classloader, url, overrideURL);
+      helper = SharedLibHelper.findHelper(classloader, url.getFile(),
+					  noCertCodeSource, true);
+    }
+
+    Class getClass(String className)
+    {
+      return helper.findClass(className);
+    }
+
+    Resource getResource(String name)
+    {
+      URL url = helper.findResource(name);
+      if (url == null)
+	return null;
+      return new SoResource(this, name, url);
+    }
+  }
+
+  final static class SoResource extends Resource
+  {
+    SoResource(SoURLLoader loader, String name, URL url)
+    {
+      super(loader, name);
+      this.url = url;
+    }
+
+    InputStream getInputStream() throws IOException
+    {
+      URLConnection conn = url.openConnection();
+      return conn.getInputStream();
+    }
+
+    public int getLength()
+    {
+      // FIXME we could find this by asking the core object.
+      return -1;
+    }
+
+    public URL getURL ()
+    {
+      return url;
+    }
+
+    final URL url;
+  }
+
+  /**
    * A <code>FileURLLoader</code> is a type of <code>URLLoader</code>
    * only loading from file url.
    */
@@ -536,7 +611,7 @@
     Resource getResource(String name)
     {
       File file = new File(dir, name);
-      if (file.exists() && !file.isDirectory())
+      if (file.exists())
         return new FileResource(this, name, file);
       return null;
     }
@@ -554,11 +629,36 @@
 
     InputStream getInputStream() throws IOException
     {
+      // Delegate to the URL content handler mechanism to retrieve an
+      // HTML representation of the directory listing if a directory
+      if (file.isDirectory())
+        {
+          URL url = getURL();
+          return url.openStream();
+        }
+      // Otherwise simply return a FileInputStream
       return new FileInputStream(file);
     }
 
     public int getLength()
     {
+      // Delegate to the URL content handler mechanism to retrieve the
+      // length of the HTML representation of the directory listing if
+      // a directory, or -1 if an exception occurs opening the directory.
+      if (file.isDirectory())
+        {
+          URL url = getURL();
+          try
+            {
+              URLConnection connection = url.openConnection();
+              return connection.getContentLength();
+            }
+          catch (IOException e)
+            {
+              return -1;
+            }
+        }
+      // Otherwise simply return the file length
       return (int) file.length();
     }
 
@@ -578,6 +678,66 @@
     }
   }
 
+  /**
+   * A <code>CoreURLLoader</code> is a type of <code>URLLoader</code>
+   * only loading from core url.
+   */
+  static final class CoreURLLoader extends URLLoader
+  {
+    private String dir;
+
+    CoreURLLoader(URLClassLoader classloader, URL url)
+    {
+      super(classloader, url);
+      dir = baseURL.getFile();
+    }
+
+    /** get resource with the name "name" in the core url */
+    Resource getResource(String name)
+    {
+      Core core = Core.find (dir + name);
+      if (core != null)
+        return new CoreResource(this, name, core);
+      return null;
+    }
+  }
+
+  static final class CoreResource extends Resource
+  {
+    final Core core;
+
+    CoreResource(CoreURLLoader loader, String name, Core core)
+    {
+      super(loader, name);
+      this.core = core;
+    }
+
+    InputStream getInputStream() throws IOException
+    {
+      return new CoreInputStream(core);
+    }
+
+    public int getLength()
+    {
+      return core.length;
+    }
+
+    public URL getURL()
+    {
+      try
+        {
+          return new URL(loader.baseURL, name,
+                         loader.classloader.getURLStreamHandler("core"));
+        }
+      catch (MalformedURLException e)
+        {
+          InternalError ie = new InternalError();
+          ie.initCause(e);
+          throw ie;
+        }
+    }
+  }
+
   // Constructors
 
   /**
@@ -603,6 +763,25 @@
   }
 
   /**
+   * Private constructor used by the static
+   * <code>newInstance(URL[])</code> method.  Creates an
+   * <code>URLClassLoader</code> without any <code>URL</code>s
+   * yet. This is used to bypass the normal security check for
+   * creating classloaders, but remembers the security context which
+   * will be used when defining classes.  The <code>URL</code>s to
+   * load from must be added by the <code>newInstance()</code> method
+   * in the security context of the caller.
+   *
+   * @param securityContext the security context of the unprivileged code.
+   */
+  private URLClassLoader(AccessControlContext securityContext)
+  {
+    super();
+    this.factory = null;
+    this.securityContext = securityContext;
+  }
+
+  /**
    * Creates a <code>URLClassLoader</code> that gets classes from the supplied
    * <code>URL</code>s.
    * To determine if this classloader may be created the constructor of
@@ -718,10 +897,14 @@
             String protocol = newUrl.getProtocol();
 
             // Check that it is not a directory
-            if (! (file.endsWith("/") || file.endsWith(File.separator)))
+	    if ("gcjlib".equals(protocol))
+	      loader = new SoURLLoader(this, newUrl);
+	    else if (! (file.endsWith("/") || file.endsWith(File.separator)))
               loader = new JarURLLoader(this, newUrl);
             else if ("file".equals(protocol))
               loader = new FileURLLoader(this, newUrl);
+	    else if ("core".equals(protocol))
+	      loader = new CoreURLLoader(this, newUrl);
             else
               loader = new RemoteURLLoader(this, newUrl);
 
@@ -811,7 +994,20 @@
   {
     // Just try to find the resource by the (almost) same name
     String resourceName = className.replace('.', '/') + ".class";
-    Resource resource = findURLResource(resourceName);
+    int max = urlinfos.size();
+    Resource resource = null;
+    for (int i = 0; i < max && resource == null; i++)
+      {
+	URLLoader loader = (URLLoader)urlinfos.elementAt(i);
+	if (loader == null)
+	  continue;
+
+	Class k = loader.getClass(className);
+	if (k != null)
+	  return k;
+
+	resource = loader.getResource(resourceName);
+      }
     if (resource == null)
       throw new ClassNotFoundException(className + " not found in " + this);
 
@@ -821,43 +1017,36 @@
       {
         byte[] data;
         InputStream in = resource.getInputStream();
-        try
-          {
-            int length = resource.getLength();
-            if (length != -1)
-              {
-                // We know the length of the data.
-                // Just try to read it in all at once
-                data = new byte[length];
-                int pos = 0;
-                while (length - pos > 0)
-                  {
-                    int len = in.read(data, pos, length - pos);
-                    if (len == -1)
-                      throw new EOFException("Not enough data reading from: "
-                                             + in);
-                    pos += len;
-                  }
-              }
-            else
-              {
-                // We don't know the data length.
-                // Have to read it in chunks.
-                ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
-                byte[] b = new byte[4096];
-                int l = 0;
-                while (l != -1)
-                  {
-                    l = in.read(b);
-                    if (l != -1)
-                      out.write(b, 0, l);
-                  }
-                data = out.toByteArray();
-              }
-          }
-        finally
-          {
-            in.close();
+	int length = resource.getLength();
+	if (length != -1)
+	  {
+	    // We know the length of the data.
+	    // Just try to read it in all at once
+	    data = new byte[length];
+	    int pos = 0;
+	    while (length - pos > 0)
+	      {
+		int len = in.read(data, pos, length - pos);
+		if (len == -1)
+		  throw new EOFException("Not enough data reading from: "
+					 + in);
+		pos += len;
+	      }
+	  }
+	else
+	  {
+	    // We don't know the data length.
+	    // Have to read it in chunks.
+	    ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
+	    byte[] b = new byte[4096];
+	    int l = 0;
+	    while (l != -1)
+	      {
+		l = in.read(b);
+		if (l != -1)
+		  out.write(b, 0, l);
+	      }
+	    data = out.toByteArray();
           }
         final byte[] classData = data;
 
