public inbox for java-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* FYI: Merge java.net.URLClassLoader
@ 2007-01-15 10:33 Gary Benson
  2007-01-15 18:45 ` Tom Tromey
  0 siblings, 1 reply; 2+ messages in thread
From: Gary Benson @ 2007-01-15 10:33 UTC (permalink / raw)
  To: java-patches

[-- Attachment #1: Type: text/plain, Size: 92 bytes --]

Hi all,

This commit replaces GCJ's java.net.URLClassLoader with Classpath's.

Cheers,
Gary

[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 50478 bytes --]

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 120790)
+++ ChangeLog	(working copy)
@@ -1,3 +1,11 @@
+2007-01-15  Gary Benson  <gbenson@redhat.com>
+
+	* java/net/URLClassLoader.java: Removed.
+	* gnu/java/net/loader/Load_gcjlib.java: New file.
+	* gnu/gcj/runtime/BootClassLoader.java: Ensure core
+	URL handler is present in static executables.
+	* sources.am, Makefile.in: Rebuilt.
+
 2007-01-14  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* Makefile.am (libgcj_la_LDFLAGS): Add
Index: java/net/URLClassLoader.java
===================================================================
--- java/net/URLClassLoader.java	(revision 120790)
+++ java/net/URLClassLoader.java	(working copy)
@@ -1,1448 +0,0 @@
-/* URLClassLoader.java --  ClassLoader that loads classes from one or more URLs
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.net;
-
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FilePermission;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.PermissionCollection;
-import java.security.PrivilegedAction;
-import java.security.SecureClassLoader;
-import java.security.cert.Certificate;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.jar.Attributes;
-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
- * multiple locations.  Given an array of <code>URL</code>s this class
- * loader will retrieve classes and resources by fetching them from
- * possible remote locations.  Each <code>URL</code> is searched in
- * order in which it was added.  If the file portion of the
- * <code>URL</code> ends with a '/' character then it is interpreted
- * as a base directory, otherwise it is interpreted as a jar file from
- * which the classes/resources are resolved.
- *
- * <p>New instances can be created by two static
- * <code>newInstance()</code> methods or by three public
- * contructors. Both ways give the option to supply an initial array
- * of <code>URL</code>s and (optionally) a parent classloader (that is
- * different from the standard system class loader).</p>
- *
- * <p>Normally creating a <code>URLClassLoader</code> throws a
- * <code>SecurityException</code> if a <code>SecurityManager</code> is
- * installed and the <code>checkCreateClassLoader()</code> method does
- * not return true.  But the <code>newInstance()</code> methods may be
- * used by any code as long as it has permission to acces the given
- * <code>URL</code>s.  <code>URLClassLoaders</code> created by the
- * <code>newInstance()</code> methods also explicitly call the
- * <code>checkPackageAccess()</code> method of
- * <code>SecurityManager</code> if one is installed before trying to
- * load a class.  Note that only subclasses of
- * <code>URLClassLoader</code> can add new URLs after the
- * URLClassLoader had been created. But it is always possible to get
- * an array of all URLs that the class loader uses to resolve classes
- * and resources by way of the <code>getURLs()</code> method.</p>
- *
- * <p>Open issues:
- * <ul>
- *
- * <li>Should the URLClassLoader actually add the locations found in
- * the manifest or is this the responsibility of some other
- * loader/(sub)class?  (see <a
- * href="http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html">
- * Extension Mechanism Architecture - Bundles Extensions</a>)</li>
- *
- * <li>How does <code>definePackage()</code> and sealing work
- * precisely?</li>
- *
- * <li>We save and use the security context (when a created by
- * <code>newInstance()</code> but do we have to use it in more
- * places?</li>
- *
- * <li>The use of <code>URLStreamHandler</code>s has not been tested.</li>
- *
- * </ul>
- * </p>
- *
- * @since 1.2
- *
- * @author Mark Wielaard (mark@klomp.org)
- * @author Wu Gansha (gansha.wu@intel.com)
- */
-public class URLClassLoader extends SecureClassLoader
-{
-  // Class Variables
-
-  /**
-   * A global cache to store mappings between URLLoader and URL,
-   * so we can avoid do all the homework each time the same URL
-   * comes.
-   * XXX - Keeps these loaders forever which prevents garbage collection.
-   */
-  private static HashMap urlloaders = new HashMap();
-
-  /**
-   * A cache to store mappings between handler factory and its
-   * private protocol handler cache (also a HashMap), so we can avoid
-   * create handlers each time the same protocol comes.
-   */
-  private static HashMap factoryCache = new HashMap(5);
-
-  // Instance variables
-
-  /** Locations to load classes from */
-  private final Vector urls = new Vector();
-
-  /**
-   * Store pre-parsed information for each url into this vector: each
-   * element is a URL loader.  A jar file has its own class-path
-   * attribute which adds to the URLs that will be searched, but this
-   * does not add to the list of urls.
-   */
-  private final Vector urlinfos = new Vector();
-
-  /** Factory used to get the protocol handlers of the URLs */
-  private final URLStreamHandlerFactory factory;
-
-  /**
-   * The security context when created from <code>newInstance()</code>
-   * or null when created through a normal constructor or when no
-   * <code>SecurityManager</code> was installed.
-   */
-  private final AccessControlContext securityContext;
-
-  // Helper classes
-
-  /**
-   * A <code>URLLoader</code> contains all logic to load resources from a
-   * given base <code>URL</code>.
-   */
-  abstract static class URLLoader
-  {
-    /**
-     * Our classloader to get info from if needed.
-     */
-    final URLClassLoader classloader;
-
-    /**
-     * The base URL from which all resources are loaded.
-     */
-    final URL baseURL;
-
-    /**
-     * A <code>CodeSource</code> without any associated certificates.
-     * It is common for classes to not have certificates associated
-     * with them.  If they come from the same <code>URLLoader</code>
-     * then it is safe to share the associated <code>CodeSource</code>
-     * between them since <code>CodeSource</code> is immutable.
-     */
-    final CodeSource noCertCodeSource;
-
-    URLLoader(URLClassLoader classloader, URL baseURL)
-    {
-      this(classloader, baseURL, baseURL);
-    }
-
-    URLLoader(URLClassLoader classloader, URL baseURL, URL overrideURL)
-    {
-      this.classloader = classloader;
-      this.baseURL = baseURL;
-      this.noCertCodeSource = new CodeSource(overrideURL, null);
-    }
-
-    /**
-     * 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.
-     */
-    abstract Resource getResource(String s);
-
-    /**
-     * Returns the <code>Manifest</code> associated with the
-     * <code>Resource</code>s loaded by this <code>URLLoader</code> or
-     * <code>null</code> there is no such <code>Manifest</code>.
-     */
-    Manifest getManifest()
-    {
-      return null;
-    }
-
-    Vector getClassPath()
-    {
-      return null;
-    }
-  }
-
-  /**
-   * A <code>Resource</code> represents a resource in some
-   * <code>URLLoader</code>. It also contains all information (e.g.,
-   * <code>URL</code>, <code>CodeSource</code>, <code>Manifest</code> and
-   * <code>InputStream</code>) that is necessary for loading resources
-   * and creating classes from a <code>URL</code>.
-   */
-  abstract static class Resource
-  {
-    final URLLoader loader;
-
-    Resource(URLLoader loader)
-    {
-      this.loader = loader;
-    }
-
-    /**
-     * Returns the non-null <code>CodeSource</code> associated with
-     * this resource.
-     */
-    CodeSource getCodeSource()
-    {
-      Certificate[] certs = getCertificates();
-      if (certs == null)
-        return loader.noCertCodeSource;
-      else
-        return new CodeSource(loader.baseURL, certs);
-    }
-
-    /**
-     * Returns <code>Certificates</code> associated with this
-     * resource, or null when there are none.
-     */
-    Certificate[] getCertificates()
-    {
-      return null;
-    }
-
-    /**
-     * Return a <code>URL</code> that can be used to access this resource.
-     */
-    abstract URL getURL();
-
-    /**
-     * Returns the size of this <code>Resource</code> in bytes or
-     * <code>-1</code> when unknown.
-     */
-    abstract int getLength();
-
-    /**
-     * Returns the non-null <code>InputStream</code> through which
-     * this resource can be loaded.
-     */
-    abstract InputStream getInputStream() throws IOException;
-  }
-
-  /**
-   * A <code>JarURLLoader</code> is a type of <code>URLLoader</code>
-   * only loading from jar url.
-   */
-  static final class JarURLLoader extends URLLoader
-  {
-    final JarFile jarfile; // The jar file for this url
-    final URL baseJarURL; // Base jar: url for all resources loaded from jar
-
-    Vector classPath;	// The "Class-Path" attribute of this Jar's manifest
-
-    public JarURLLoader(URLClassLoader classloader, URL baseURL,
-			URL absoluteUrl)
-    {
-      super(classloader, baseURL, absoluteUrl);
-
-      // Cache url prefix for all resources in this jar url.
-      String external = baseURL.toExternalForm();
-      StringBuffer sb = new StringBuffer(external.length() + 6);
-      sb.append("jar:");
-      sb.append(external);
-      sb.append("!/");
-      String jarURL = sb.toString();
-
-      this.classPath = null;
-      URL baseJarURL = null;
-      JarFile jarfile = null;
-      try
-	{
-	  baseJarURL =
-	    new URL(null, jarURL, classloader.getURLStreamHandler("jar"));
-	  
-	  jarfile =
-	    ((JarURLConnection) baseJarURL.openConnection()).getJarFile();
-	  
-	  Manifest manifest;
-	  Attributes attributes;
-	  String classPathString;
-
-	  if ((manifest = jarfile.getManifest()) != null
-	      && (attributes = manifest.getMainAttributes()) != null
-	      && ((classPathString 
-		   = attributes.getValue(Attributes.Name.CLASS_PATH)) 
-		  != null))
-	    {
-	      this.classPath = new Vector();
-	      
-	      StringTokenizer st = new StringTokenizer(classPathString, " ");
-	      while (st.hasMoreElements ()) 
-		{  
-		  String e = st.nextToken ();
-		  try
-		    {
-		      URL url = new URL(baseURL, e);
-		      this.classPath.add(url);
-		    } 
-		  catch (java.net.MalformedURLException xx)
-		    {
-		      // Give up
-		    }
-		}
-	    }
-	}
-      catch (IOException ioe)
-        {
-	  /* ignored */
-        }
-
-      this.baseJarURL = baseJarURL;
-      this.jarfile = jarfile;
-    }
-
-    /** get resource with the name "name" in the jar url */
-    Resource getResource(String name)
-    {
-      if (jarfile == null)
-        return null;
-
-      if (name.startsWith("/"))
-        name = name.substring(1);
-
-      JarEntry je = jarfile.getJarEntry(name);
-      if (je != null)
-        return new JarURLResource(this, name, je);
-      else
-        return null;
-    }
-
-    Manifest getManifest()
-    {
-      try
-        {
-          return (jarfile == null) ? null : jarfile.getManifest();
-        }
-      catch (IOException ioe)
-        {
-          return null;
-        }
-    }
-
-    Vector getClassPath()
-    {
-      return classPath;
-    }
-  }
-
-  static final class JarURLResource extends Resource
-  {
-    private final JarEntry entry;
-    private final String name;
-
-    JarURLResource(JarURLLoader loader, String name, JarEntry entry)
-    {
-      super(loader);
-      this.entry = entry;
-      this.name = name;
-    }
-
-    InputStream getInputStream() throws IOException
-    {
-      return ((JarURLLoader) loader).jarfile.getInputStream(entry);
-    }
-
-    int getLength()
-    {
-      return (int) entry.getSize();
-    }
-
-    Certificate[] getCertificates()
-    {
-      // We have to get the entry from the jar file again, because the
-      // certificates will not be available until the entire entry has
-      // been read.
-      return ((JarEntry) ((JarURLLoader) loader).jarfile.getEntry(name))
-        .getCertificates();
-    }
-
-    URL getURL()
-    {
-      try
-        {
-          return new URL(((JarURLLoader) loader).baseJarURL, name,
-                         loader.classloader.getURLStreamHandler("jar"));
-        }
-      catch (MalformedURLException e)
-        {
-          InternalError ie = new InternalError();
-          ie.initCause(e);
-          throw ie;
-        }
-    }
-  }
-
-  /**
-   * Loader for remote directories.
-   */
-  static final class RemoteURLLoader extends URLLoader
-  {
-    private final String protocol;
-
-    RemoteURLLoader(URLClassLoader classloader, URL url)
-    {
-      super(classloader, url);
-      protocol = url.getProtocol();
-    }
-
-    /**
-     * Get a remote resource.
-     * Returns null if no such resource exists.
-     */
-    Resource getResource(String name)
-    {
-      try
-        {
-          URL url =
-            new URL(baseURL, name, classloader.getURLStreamHandler(protocol));
-          URLConnection connection = url.openConnection();
-
-          // Open the connection and check the stream
-          // just to be sure it exists.
-          int length = connection.getContentLength();
-          InputStream stream = connection.getInputStream();
-
-          // We can do some extra checking if it is a http request
-          if (connection instanceof HttpURLConnection)
-            {
-              int response =
-                ((HttpURLConnection) connection).getResponseCode();
-              if (response / 100 != 2)
-                return null;
-            }
-
-          if (stream != null)
-            return new RemoteResource(this, name, url, stream, length);
-          else
-            return null;
-        }
-      catch (IOException ioe)
-        {
-          return null;
-        }
-    }
-  }
-
-  /**
-   * A resource from some remote location.
-   */
-  static final class RemoteResource extends Resource
-  {
-    private final URL url;
-    private final InputStream stream;
-    private final int length;
-
-    RemoteResource(RemoteURLLoader loader, String name, URL url,
-                   InputStream stream, int length)
-    {
-      super(loader);
-      this.url = url;
-      this.stream = stream;
-      this.length = length;
-    }
-
-    InputStream getInputStream() throws IOException
-    {
-      return stream;
-    }
-
-    public int getLength()
-    {
-      return length;
-    }
-
-    public URL getURL()
-    {
-      return url;
-    }
-  }
-
-  /**
-   * 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, url);
-    }
-  }
-
-  final static class SoResource extends Resource
-  {
-    SoResource(SoURLLoader loader, URL url)
-    {
-      super(loader);
-      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.
-   */
-  static final class FileURLLoader extends URLLoader
-  {
-    File dir; //the file for this file url
-
-    FileURLLoader(URLClassLoader classloader, URL url, URL absoluteUrl)
-    {
-      super(classloader, url, absoluteUrl);
-      dir = new File(absoluteUrl.getFile());
-    }
-
-    /** get resource with the name "name" in the file url */
-    Resource getResource(String name)
-    {
-      try 
- 	{
- 	  File file = new File(dir, name).getCanonicalFile();
- 	  if (file.exists() && !file.isDirectory())
- 	    return new FileResource(this, file);
- 	}
-      catch (IOException e)
- 	{
- 	  // Fall through...
- 	}
-      return null;
-    }
-  }
-
-  static final class FileResource extends Resource
-  {
-    final File file;
-
-    FileResource(FileURLLoader loader, File file)
-    {
-      super(loader);
-      this.file = file;
-    }
-
-    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();
-    }
-
-    public URL getURL()
-    {
-      try
-        {
-          return file.toURL();
-        }
-      catch (MalformedURLException e)
-        {
-          InternalError ie = new InternalError();
-          ie.initCause(e);
-          throw ie;
-        }
-    }
-  }
-
-  /**
-   * 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
-  {
-    private final Core core;
-    private final String name;
-
-    CoreResource(CoreURLLoader loader, String name, Core core)
-    {
-      super(loader);
-      this.core = core;
-      this.name = name;
-    }
-
-    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
-
-  /**
-   * Creates a URLClassLoader that gets classes from the supplied URLs.
-   * To determine if this classloader may be created the constructor of
-   * the super class (<code>SecureClassLoader</code>) is called first, which
-   * can throw a SecurityException. Then the supplied URLs are added
-   * in the order given to the URLClassLoader which uses these URLs to
-   * load classes and resources (after using the default parent ClassLoader).
-   *
-   * @param urls Locations that should be searched by this ClassLoader when
-   * resolving Classes or Resources.
-   * @exception SecurityException if the SecurityManager disallows the
-   * creation of a ClassLoader.
-   * @see SecureClassLoader
-   */
-  public URLClassLoader(URL[] urls) throws SecurityException
-  {
-    super();
-    this.factory = null;
-    this.securityContext = null;
-    addURLs(urls);
-  }
-
-  /**
-   * 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
-   * the super class (<code>SecureClassLoader</code>) is called first, which
-   * can throw a SecurityException. Then the supplied URLs are added
-   * in the order given to the URLClassLoader which uses these URLs to
-   * load classes and resources (after using the supplied parent ClassLoader).
-   * @param urls Locations that should be searched by this ClassLoader when
-   * resolving Classes or Resources.
-   * @param parent The parent class loader used before trying this class
-   * loader.
-   * @exception SecurityException if the SecurityManager disallows the
-   * creation of a ClassLoader.
-   * @exception SecurityException
-   * @see SecureClassLoader
-   */
-  public URLClassLoader(URL[] urls, ClassLoader parent)
-    throws SecurityException
-  {
-    super(parent);
-    this.factory = null;
-    this.securityContext = null;
-    addURLs(urls);
-  }
-
-  // Package-private to avoid a trampoline constructor.
-  /**
-   * Package-private constructor used by the static
-   * <code>newInstance(URL[])</code> method.  Creates an
-   * <code>URLClassLoader</code> with the given parent but 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.
-   */
-  URLClassLoader(ClassLoader parent, AccessControlContext securityContext)
-  {
-    super(parent);
-    this.factory = null;
-    this.securityContext = securityContext;
-  }
-
-  /**
-   * Creates a URLClassLoader that gets classes from the supplied URLs.
-   * To determine if this classloader may be created the constructor of
-   * the super class (<CODE>SecureClassLoader</CODE>) is called first, which
-   * can throw a SecurityException. Then the supplied URLs are added
-   * in the order given to the URLClassLoader which uses these URLs to
-   * load classes and resources (after using the supplied parent ClassLoader).
-   * It will use the supplied <CODE>URLStreamHandlerFactory</CODE> to get the
-   * protocol handlers of the supplied URLs.
-   * @param urls Locations that should be searched by this ClassLoader when
-   * resolving Classes or Resources.
-   * @param parent The parent class loader used before trying this class
-   * loader.
-   * @param factory Used to get the protocol handler for the URLs.
-   * @exception SecurityException if the SecurityManager disallows the
-   * creation of a ClassLoader.
-   * @exception SecurityException
-   * @see SecureClassLoader
-   */
-  public URLClassLoader(URL[] urls, ClassLoader parent,
-                        URLStreamHandlerFactory factory)
-    throws SecurityException
-  {
-    super(parent);
-    this.securityContext = null;
-    this.factory = factory;
-    addURLs(urls);
-
-    // If this factory is still not in factoryCache, add it,
-    //   since we only support three protocols so far, 5 is enough
-    //   for cache initial size
-    synchronized (factoryCache)
-      {
-        if (factory != null && factoryCache.get(factory) == null)
-          factoryCache.put(factory, new HashMap(5));
-      }
-  }
-
-  // Methods
-
-  /**
-   * Adds a new location to the end of the internal URL store.
-   * @param newUrl the location to add
-   */
-  protected void addURL(URL newUrl)
-  {
-    urls.add(newUrl);
-    addURLImpl(newUrl);
-  }
-
-  private void addURLImpl(URL newUrl)
-  {
-    synchronized (this)
-      {
-        if (newUrl == null)
-          return; // Silently ignore...
-
-	// Reset the toString() value.
-	thisString = null;
-
-        // Check global cache to see if there're already url loader
-        // for this url.
-        URLLoader loader = (URLLoader) urlloaders.get(newUrl);
-        if (loader == null)
-          {
-            String file = newUrl.getFile();
-            String protocol = newUrl.getProtocol();
-
-	    // If we have a file: URL, we want to make it absolute
-	    // here, before we decide whether it is really a jar.
-	    URL absoluteURL;
-	    if ("file".equals (protocol))
-	      {
-		File dir = new File(file);
-		URL absUrl;
-		try
-		  {
-		    absoluteURL = dir.getCanonicalFile().toURL();
-		  }
-		catch (IOException ignore)
-		  {
-		    try
-		      {
-			absoluteURL = dir.getAbsoluteFile().toURL();
-		      }
-		    catch (MalformedURLException _)
-		      {
-			// This really should not happen.
-			absoluteURL = newUrl;
-		      }
-		  }
-	      }
-	    else
-	      {
-		// This doesn't hurt, and it simplifies the logic a
-		// little.
-		absoluteURL = newUrl;
-	      }
-
-            // Check that it is not a directory
-	    if ("gcjlib".equals(protocol))
-	      loader = new SoURLLoader(this, newUrl);
-	    else if (! (file.endsWith("/") || file.endsWith(File.separator)))
-              loader = new JarURLLoader(this, newUrl, absoluteURL);
-            else if ("file".equals(protocol))
-	      loader = new FileURLLoader(this, newUrl, absoluteURL);
-	    else if ("core".equals(protocol))
-	      loader = new CoreURLLoader(this, newUrl);
-            else
-              loader = new RemoteURLLoader(this, newUrl);
-
-            // Cache it.
-            urlloaders.put(newUrl, loader);
-          }
-
-	urlinfos.add(loader);
-
-	Vector extraUrls = loader.getClassPath();
-	if (extraUrls != null)
-	  {
-	    Iterator it = extraUrls.iterator();
-	    while (it.hasNext())
-	      {
-		URL url = (URL)it.next();
-		URLLoader extraLoader = (URLLoader) urlloaders.get(url);
-		if (! urlinfos.contains (extraLoader))
-		  addURLImpl(url);
-	      }
-	  }
-
-      }
-  }
-
-  /**
-   * Adds an array of new locations to the end of the internal URL
-   * store.  Called from the the constructors. Should not call to the
-   * protected addURL() method since that can be overridden and
-   * subclasses are not yet in a good state at this point.
-   * jboss 4.0.3 for example depends on this.
-   *
-   * @param newUrls the locations to add
-   */
-  private void addURLs(URL[] newUrls)
-  {
-    for (int i = 0; i < newUrls.length; i++)
-      {
-	urls.add(newUrls[i]);
-	addURLImpl(newUrls[i]);
-      }
-  }
-
-  /**
-   * Look in both Attributes for a given value.  The first Attributes
-   * object, if not null, has precedence.
-   */
-  private String getAttributeValue(Attributes.Name name, Attributes first,
-				   Attributes second)
-  {
-    String result = null;
-    if (first != null)
-      result = first.getValue(name);
-    if (result == null)
-      result = second.getValue(name);
-    return result;
-  }
-
-  /**
-   * Defines a Package based on the given name and the supplied manifest
-   * information. The manifest indicates the title, version and
-   * vendor information of the specification and implementation and whether the
-   * package is sealed. If the Manifest indicates that the package is sealed
-   * then the Package will be sealed with respect to the supplied URL.
-   *
-   * @param name The name of the package
-   * @param manifest The manifest describing the specification,
-   * implementation and sealing details of the package
-   * @param url the code source url to seal the package
-   * @return the defined Package
-   * @throws IllegalArgumentException If this package name already exists
-   * in this class loader
-   */
-  protected Package definePackage(String name, Manifest manifest, URL url)
-    throws IllegalArgumentException
-  {
-    // Compute the name of the package as it may appear in the
-    // Manifest.
-    StringBuffer xform = new StringBuffer(name);
-    for (int i = xform.length () - 1; i >= 0; --i)
-      if (xform.charAt(i) == '.')
-	xform.setCharAt(i, '/');
-    xform.append('/');
-    String xformName = xform.toString();
-
-    Attributes entryAttr = manifest.getAttributes(xformName);
-    Attributes attr = manifest.getMainAttributes();
-
-    String specTitle
-      = getAttributeValue(Attributes.Name.SPECIFICATION_TITLE,
-			  entryAttr, attr);
-    String specVersion
-      = getAttributeValue(Attributes.Name.SPECIFICATION_VERSION,
-			  entryAttr, attr);
-    String specVendor
-      = getAttributeValue(Attributes.Name.SPECIFICATION_VENDOR,
-			  entryAttr, attr);
-    String implTitle
-      = getAttributeValue(Attributes.Name.IMPLEMENTATION_TITLE,
-			  entryAttr, attr);
-    String implVersion
-      = getAttributeValue(Attributes.Name.IMPLEMENTATION_VERSION,
-			  entryAttr, attr);
-    String implVendor
-      = getAttributeValue(Attributes.Name.IMPLEMENTATION_VENDOR,
-			  entryAttr, attr);
-
-    // Look if the Manifest indicates that this package is sealed
-    // XXX - most likely not completely correct!
-    // Shouldn't we also check the sealed attribute of the complete jar?
-    // http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html#bundled
-    // But how do we get that jar manifest here?
-    String sealed = attr.getValue(Attributes.Name.SEALED);
-    if ("false".equals(sealed))
-      // make sure that the URL is null so the package is not sealed
-      url = null;
-
-    return definePackage(name,
-			 specTitle, specVendor, specVersion,
-			 implTitle, implVendor, implVersion,
-			 url);
-  }
-
-  /**
-   * Finds (the first) class by name from one of the locations. The locations
-   * are searched in the order they were added to the URLClassLoader.
-   *
-   * @param className the classname to find
-   * @exception ClassNotFoundException when the class could not be found or
-   * loaded
-   * @return a Class object representing the found class
-   */
-  protected Class findClass(final String className)
-    throws ClassNotFoundException
-  {
-    // Just try to find the resource by the (almost) same name
-    String resourceName = className.replace('.', '/') + ".class";
-    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)
-      {
-	String message = className + " not found";
-	// Calling this.toString() during VM startup when a
-	// security manager is in force causes the stack to
-	// be unwound before it can properly be decoded.
-	if (Thread.currentThread() != null)
-	  message += " in " + this;
-	throw new ClassNotFoundException(message);
-      }
-
-    // Try to read the class data, create the CodeSource, Package and
-    // construct the class (and watch out for those nasty IOExceptions)
-    try
-      {
-	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();
-	  }
-	final byte[] classData = data;
-
-        // Now get the CodeSource
-        final CodeSource source = resource.getCodeSource();
-
-        // Find out package name
-        String packageName = null;
-        int lastDot = className.lastIndexOf('.');
-        if (lastDot != -1)
-          packageName = className.substring(0, lastDot);
-
-        if (packageName != null && getPackage(packageName) == null)
-          {
-            // define the package
-            Manifest manifest = resource.loader.getManifest();
-            if (manifest == null)
-              definePackage(packageName, null, null, null, null, null, null,
-                            null);
-            else
-              definePackage(packageName, manifest, resource.loader.baseURL);
-          }
-
-        // And finally construct the class!
-        SecurityManager sm = System.getSecurityManager();
-        Class result = null;
-        if (sm != null && securityContext != null)
-          {
-            result = (Class)AccessController.doPrivileged
-              (new PrivilegedAction()
-                {
-                  public Object run()
-                  {
-                    return defineClass(className, classData,
-                                       0, classData.length,
-                                       source);
-                  }
-                }, securityContext);
-          }
-        else
-          result = defineClass(className, classData, 0, classData.length, source);
-
-        // Avoid NullPointerExceptions.
-        Certificate[] resourceCertificates = resource.getCertificates();
-        if(resourceCertificates != null)
-          super.setSigners(result, resourceCertificates);
-        
-        return result;
-      }
-    catch (IOException ioe)
-      {
-	ClassNotFoundException cnfe;
-	cnfe = new ClassNotFoundException(className + " not found in " + this);
-	cnfe.initCause(ioe);
-	throw cnfe;
-      }
-  }
-  
-  // Cached String representation of this URLClassLoader
-  private String thisString;
-  
-  /**
-   * Returns a String representation of this URLClassLoader giving the
-   * actual Class name, the URLs that are searched and the parent
-   * ClassLoader.
-   */
-  public String toString()
-  {
-    synchronized (this)
-      {
-	if (thisString == null)
-	  {
-	    StringBuffer sb = new StringBuffer();
-	    sb.append(this.getClass().getName());
-	    sb.append("{urls=[" );
-	    URL[] thisURLs = getURLs();
-	    for (int i = 0; i < thisURLs.length; i++)
-	      {
-		sb.append(thisURLs[i]);
-		if (i < thisURLs.length - 1)
-		  sb.append(',');
-	      }
-	    sb.append(']');
-	    sb.append(", parent=");
-	    sb.append(getParent());
-	    sb.append('}');
-	    thisString = sb.toString();
-	  }
-	return thisString;
-      }
-  }
-
-  /**
-   * Finds the first occurrence of a resource that can be found. The locations
-   * are searched in the order they were added to the URLClassLoader.
-   *
-   * @param resourceName the resource name to look for
-   * @return the URLResource for the resource if found, null otherwise
-   */
-  private Resource findURLResource(String resourceName)
-  {
-    int max = urlinfos.size();
-    for (int i = 0; i < max; i++)
-      {
-        URLLoader loader = (URLLoader) urlinfos.elementAt(i);
-        if (loader == null)
-          continue;
-
-        Resource resource = loader.getResource(resourceName);
-        if (resource != null)
-          return resource;
-      }
-    return null;
-  }
-
-  /**
-   * Finds the first occurrence of a resource that can be found.
-   *
-   * @param resourceName the resource name to look for
-   * @return the URL if found, null otherwise
-   */
-  public URL findResource(String resourceName)
-  {
-    Resource resource = findURLResource(resourceName);
-    if (resource != null)
-      return resource.getURL();
-
-    // Resource not found
-    return null;
-  }
-
-  /**
-   * If the URLStreamHandlerFactory has been set this return the appropriate
-   * URLStreamHandler for the given protocol, if not set returns null.
-   *
-   * @param protocol the protocol for which we need a URLStreamHandler
-   * @return the appropriate URLStreamHandler or null
-   */
-  URLStreamHandler getURLStreamHandler(String protocol)
-  {
-    if (factory == null)
-      return null;
-
-    URLStreamHandler handler;
-    synchronized (factoryCache)
-      {
-        // Check if there're handler for the same protocol in cache.
-        HashMap cache = (HashMap) factoryCache.get(factory);
-        handler = (URLStreamHandler) cache.get(protocol);
-        if (handler == null)
-          {
-            // Add it to cache.
-            handler = factory.createURLStreamHandler(protocol);
-            cache.put(protocol, handler);
-          }
-      }
-    return handler;
-  }
-
-  /**
-   * Finds all the resources with a particular name from all the locations.
-   *
-   * @param resourceName the name of the resource to lookup
-   * @return a (possible empty) enumeration of URLs where the resource can be
-   * found
-   * @exception IOException when an error occurs accessing one of the
-   * locations
-   */
-  public Enumeration findResources(String resourceName)
-    throws IOException
-  {
-    Vector resources = new Vector();
-    int max = urlinfos.size();
-    for (int i = 0; i < max; i++)
-      {
-        URLLoader loader = (URLLoader) urlinfos.elementAt(i);
-        Resource resource = loader.getResource(resourceName);
-        if (resource != null)
-          resources.add(resource.getURL());
-      }
-    return resources.elements();
-  }
-
-  /**
-   * Returns the permissions needed to access a particular code
-   * source.  These permissions includes those returned by
-   * <code>SecureClassLoader.getPermissions()</code> and the actual
-   * permissions to access the objects referenced by the URL of the
-   * code source.  The extra permissions added depend on the protocol
-   * and file portion of the URL in the code source. If the URL has
-   * the "file" protocol ends with a '/' character then it must be a
-   * directory and a file Permission to read everything in that
-   * directory and all subdirectories is added. If the URL had the
-   * "file" protocol and doesn't end with a '/' character then it must
-   * be a normal file and a file permission to read that file is
-   * added. If the <code>URL</code> has any other protocol then a
-   * socket permission to connect and accept connections from the host
-   * portion of the URL is added.
-   *
-   * @param source The codesource that needs the permissions to be accessed
-   * @return the collection of permissions needed to access the code resource
-   * @see java.security.SecureClassLoader#getPermissions(CodeSource)
-   */
-  protected PermissionCollection getPermissions(CodeSource source)
-  {
-    // XXX - This implementation does exactly as the Javadoc describes.
-    // But maybe we should/could use URLConnection.getPermissions()?
-    // First get the permissions that would normally be granted
-    PermissionCollection permissions = super.getPermissions(source);
-
-    // Now add any extra permissions depending on the URL location.
-    URL url = source.getLocation();
-    String protocol = url.getProtocol();
-    if (protocol.equals("file"))
-      {
-        String file = url.getFile();
-
-        // If the file end in / it must be an directory.
-        if (file.endsWith("/") || file.endsWith(File.separator))
-          {
-            // Grant permission to read everything in that directory and
-            // all subdirectories.
-            permissions.add(new FilePermission(file + "-", "read"));
-          }
-        else
-          {
-            // It is a 'normal' file.
-            // Grant permission to access that file.
-            permissions.add(new FilePermission(file, "read"));
-          }
-      }
-    else
-      {
-        // Grant permission to connect to and accept connections from host
-        String host = url.getHost();
-        if (host != null)
-          permissions.add(new SocketPermission(host, "connect,accept"));
-      }
-
-    return permissions;
-  }
-
-  /**
-   * Returns all the locations that this class loader currently uses the
-   * resolve classes and resource. This includes both the initially supplied
-   * URLs as any URLs added later by the loader.
-   * @return All the currently used URLs
-   */
-  public URL[] getURLs()
-  {
-    return (URL[]) urls.toArray(new URL[urls.size()]);
-  }
-
-  /**
-   * Creates a new instance of a <code>URLClassLoader</code> that gets
-   * classes from the supplied <code>URL</code>s. This class loader
-   * will have as parent the standard system class loader.
-   *
-   * @param urls the initial URLs used to resolve classes and
-   * resources
-   *
-   * @return the class loader
-   *
-   * @exception SecurityException when the calling code does not have
-   * permission to access the given <code>URL</code>s
-   */
-  public static URLClassLoader newInstance(URL[] urls)
-    throws SecurityException
-  {
-    return newInstance(urls, null);
-  }
-
-  /**
-   * Creates a new instance of a <code>URLClassLoader</code> that gets
-   * classes from the supplied <code>URL</code>s and with the supplied
-   * loader as parent class loader.
-   *
-   * @param urls the initial URLs used to resolve classes and
-   * resources
-   * @param parent the parent class loader
-   *
-   * @return the class loader
-   *
-   * @exception SecurityException when the calling code does not have
-   * permission to access the given <code>URL</code>s
-   */
-  public static URLClassLoader newInstance(URL[] urls, final ClassLoader parent)
-    throws SecurityException
-  {
-    SecurityManager sm = System.getSecurityManager();
-    if (sm == null)
-      return new URLClassLoader(urls, parent);
-    else
-      {
-        final Object securityContext = sm.getSecurityContext();
-
-        // XXX - What to do with anything else then an AccessControlContext?
-        if (! (securityContext instanceof AccessControlContext))
-          throw new SecurityException("securityContext must be AccessControlContext: "
-                                      + securityContext);
-
-        URLClassLoader loader =
-          (URLClassLoader) AccessController.doPrivileged(new PrivilegedAction()
-              {
-                public Object run()
-                {
-                  return new URLClassLoader(parent,
-                                            (AccessControlContext) securityContext);
-                }
-              });
-        loader.addURLs(urls);
-        return loader;
-      }
-  }
-}
Index: gnu/java/net/loader/Load_gcjlib.java
===================================================================
--- gnu/java/net/loader/Load_gcjlib.java	(revision 0)
+++ gnu/java/net/loader/Load_gcjlib.java	(revision 0)
@@ -0,0 +1,77 @@
+/* Copyright (C) 2007  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+package gnu.java.net.loader;
+
+import gnu.gcj.runtime.SharedLibHelper;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.net.URLStreamHandlerFactory;
+
+/**
+ * A <code>Load_gcjlib</code> is a type of <code>URLLoader</code>
+ * that loads classes and resources from a shared library.
+ */
+public final class Load_gcjlib extends URLLoader
+{
+  private SharedLibHelper helper;
+
+  public Load_gcjlib(URLClassLoader classloader,
+		     URLStreamHandlerCache cache,
+		     URLStreamHandlerFactory factory,
+		     URL url, URL absoluteUrl)
+  {
+    super(classloader, cache, factory, url, absoluteUrl);
+    helper = SharedLibHelper.findHelper(classloader, url.getFile(),
+					noCertCodeSource, true);
+  }
+
+  public Class getClass(String className)
+  {
+    return helper.findClass(className);
+  }
+
+  public Resource getResource(String name)
+  {
+    URL url = helper.findResource(name);
+    if (url == null)
+      return null;
+    return new SoResource(this, url);
+  }
+
+  final static class SoResource extends Resource
+  {
+    private final URL url;
+
+    SoResource(Load_gcjlib loader, URL url)
+    {
+      super(loader);
+      this.url = url;
+    }
+
+    public 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;
+    }
+  }
+}
Index: gnu/gcj/runtime/BootClassLoader.java
===================================================================
--- gnu/gcj/runtime/BootClassLoader.java	(revision 120790)
+++ gnu/gcj/runtime/BootClassLoader.java	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005  Free Software Foundation
+/* Copyright (C) 2005, 2007  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -8,6 +8,7 @@
 
 package gnu.gcj.runtime;
 
+import gnu.java.net.protocol.core.Handler;
 import java.io.IOException;
 import java.net.URL;
 import java.util.Enumeration;
@@ -21,6 +22,11 @@
  */
 public final class BootClassLoader extends HelperClassLoader
 {
+  // This forces the core URL handler to be included in statically
+  // linked executables.  The line that adds core:/ to the search
+  // path fails otherwise.
+  static Class coreHandler = gnu.java.net.protocol.core.Handler.class;
+
   BootClassLoader(String libdir)
   {
     // The BootClassLoader is the top of the delegation chain. It does not
Index: sources.am
===================================================================
--- sources.am	(revision 120790)
+++ sources.am	(working copy)
@@ -1338,6 +1338,7 @@
 classpath/gnu/java/net/loader/FileURLLoader.java \
 classpath/gnu/java/net/loader/JarURLLoader.java \
 classpath/gnu/java/net/loader/JarURLResource.java \
+gnu/java/net/loader/Load_gcjlib.java \
 classpath/gnu/java/net/loader/RemoteResource.java \
 classpath/gnu/java/net/loader/RemoteURLLoader.java \
 classpath/gnu/java/net/loader/Resource.java \
@@ -4846,7 +4847,7 @@
 classpath/java/net/URI.java \
 classpath/java/net/URISyntaxException.java \
 classpath/java/net/URL.java \
-java/net/URLClassLoader.java \
+classpath/java/net/URLClassLoader.java \
 classpath/java/net/URLConnection.java \
 classpath/java/net/URLDecoder.java \
 classpath/java/net/URLEncoder.java \
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 120790)
+++ Makefile.in	(working copy)
@@ -1922,6 +1922,7 @@
 classpath/gnu/java/net/loader/FileURLLoader.java \
 classpath/gnu/java/net/loader/JarURLLoader.java \
 classpath/gnu/java/net/loader/JarURLResource.java \
+gnu/java/net/loader/Load_gcjlib.java \
 classpath/gnu/java/net/loader/RemoteResource.java \
 classpath/gnu/java/net/loader/RemoteURLLoader.java \
 classpath/gnu/java/net/loader/Resource.java \
@@ -4402,7 +4403,7 @@
 classpath/java/net/URI.java \
 classpath/java/net/URISyntaxException.java \
 classpath/java/net/URL.java \
-java/net/URLClassLoader.java \
+classpath/java/net/URLClassLoader.java \
 classpath/java/net/URLConnection.java \
 classpath/java/net/URLDecoder.java \
 classpath/java/net/URLEncoder.java \

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: FYI: Merge java.net.URLClassLoader
  2007-01-15 10:33 FYI: Merge java.net.URLClassLoader Gary Benson
@ 2007-01-15 18:45 ` Tom Tromey
  0 siblings, 0 replies; 2+ messages in thread
From: Tom Tromey @ 2007-01-15 18:45 UTC (permalink / raw)
  To: Gary Benson; +Cc: java-patches

>>>>> "Gary" == Gary Benson <gbenson@redhat.com> writes:

Gary> This commit replaces GCJ's java.net.URLClassLoader with Classpath's.

Nice.  Thank you.

Tom

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-01-15 18:45 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-15 10:33 FYI: Merge java.net.URLClassLoader Gary Benson
2007-01-15 18:45 ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).