I reworked java.rmi.server.RMIClassLoader a little, so that it now uses
the java.rmi.server.RMIClassLoaderSpi interface. I moved the actual
implementation code to gnu.java.rmi.server.RMIClassLoaderImpl. And yes, I
added the last missing method for JDK1.1 binary compatibility to
java.rmi.server.RMIClassLoader.

2005-09-28  Roman Kennke  <[EMAIL PROTECTED]>

        * java/rmi/server/RMIClassLoader.java:
        Moved all implementation code to
        gnu.java.rmi.server.RMIClassLoaderImpl.
        (getProviderInstance): New helper method to find a provider.
        (getDefaultProviderInstance): New helper method to find a provider.
        (loadClass(String, String, Class)): New method.
        * gnu/java/rmi/server/RMIClassLoaderImpl.java:
        New class. The implementation is moved from
        java.rmi.server.RMIClassLoader.


/Roman
Index: java/rmi/server/RMIClassLoader.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/rmi/server/RMIClassLoader.java,v
retrieving revision 1.17
diff -u -r1.17 RMIClassLoader.java
--- java/rmi/server/RMIClassLoader.java	25 Jul 2005 16:31:52 -0000	1.17
+++ java/rmi/server/RMIClassLoader.java	28 Sep 2005 19:11:44 -0000
@@ -38,14 +38,9 @@
 
 package java.rmi.server;
 
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.StringTokenizer;
+import gnu.java.rmi.server.RMIClassLoaderImpl;
 
+import java.net.MalformedURLException;
 
 /**
  * This class provides a set of public static utility methods for supporting
@@ -60,221 +55,51 @@
    */
   private RMIClassLoader() {}
 
-  private static class MyClassLoader extends URLClassLoader
-  {
-    // Package-private to avoid a trampoline constructor.
-    MyClassLoader (URL[] urls, ClassLoader parent, String annotation)
-    {
-      super (urls, parent);
-      this.annotation = annotation;
-    }
-
-    private MyClassLoader (URL[] urls, ClassLoader parent)
-    {
-      super (urls, parent);
-      this.annotation = urlToAnnotation (urls);
-    }
-
-    public static String urlToAnnotation (URL[] urls)
-    {
-      if (urls.length == 0)
-        return null;
-
-      StringBuffer annotation = new StringBuffer (64 * urls.length);
-
-      for (int i = 0; i < urls.length; i++)
-      {
-        annotation.append (urls [i].toExternalForm());
-        annotation.append (' ');
-      }
-
-      return annotation.toString();
-    }
-
-    public final String getClassAnnotation()
-    {
-      return annotation;
-    }
-
-    private final String annotation;
-  }
-  
-  /** 
-   * This class is used to identify a cached classloader by its codebase and 
-   * the context classloader that is its parent.
-   */  
-  private static class CacheKey
-  {
-     private String mCodeBase;
-     private ClassLoader mContextClassLoader;
-  	
-     public CacheKey (String theCodebase, ClassLoader theContextClassLoader)
-     {
-       mCodeBase = theCodebase;
-       mContextClassLoader = theContextClassLoader;
-     }
-  	
-    /**
-     * @return true if the codebase and the context classloader are equal
-     */
-    public boolean equals (Object theOther)
-    {
-      if (theOther instanceof CacheKey)
-      {
-      	CacheKey key = (CacheKey) theOther;
-	
-      	return (equals (this.mCodeBase,key.mCodeBase)
-                && equals (this.mContextClassLoader, key.mContextClassLoader));
-        }
-      return false;
-    }
-    
-    /**
-     * Test if the two objects are equal or both null.
-     * @param theOne
-     * @param theOther
-     * @return
-     */
-    private boolean equals (Object theOne, Object theOther)
-    {
-      return theOne != null ? theOne.equals (theOther) : theOther == null;
-    }
-
-    /**
-     * @return hashCode  
-     */
-    public int hashCode()
-    {
-      return ((mCodeBase != null           ? mCodeBase.hashCode()           :  0) 
-              ^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1));
-    }
-
-    public String toString()
-    {
-      return "[" + mCodeBase + "," + mContextClassLoader + "]"; 
-    }
-
-  }
-
-  private static Map cacheLoaders; //map annotations to loaders
-  private static Map cacheAnnotations; //map loaders to annotations
-
-  //defaultAnnotation is got from system property
-  // "java.rmi.server.defaultAnnotation"
-  private static String defaultAnnotation;
-
-  //URL object for defaultAnnotation
-  private static URL defaultCodebase;
-
-  //class loader for defaultAnnotation
-  private static MyClassLoader defaultLoader;
-
-  static
-  {
-    // 89 is a nice prime number for Hashtable initial capacity
-    cacheLoaders = new Hashtable (89);
-    cacheAnnotations = new Hashtable (89);
-
-    defaultAnnotation = System.getProperty ("java.rmi.server.defaultAnnotation");
-
-    try
-      {
-        if (defaultAnnotation != null)
-          defaultCodebase = new URL (defaultAnnotation);
-      }
-    catch (Exception _)
-      {
-        defaultCodebase = null;
-      }
-
-    if (defaultCodebase != null)
-      {
-        defaultLoader = new MyClassLoader (new URL[] { defaultCodebase }, null,
-                                           defaultAnnotation);
-        cacheLoaders.put (new CacheKey (defaultAnnotation,
-                                        Thread.currentThread().getContextClassLoader()),
-                                        defaultLoader);
-      }
-    }
-
   /**
    * @deprecated
    */
-  public static Class loadClass (String name)
+  public static Class loadClass(String name)
     throws MalformedURLException, ClassNotFoundException
   {
-    return loadClass ("", name);
+    return loadClass("", name);
   }
 
-  public static Class loadClass (String codebases, String name)
+  public static Class loadClass(String codebase, String name)
     throws MalformedURLException, ClassNotFoundException
   {
-    ClassLoader loader = Thread.currentThread().getContextClassLoader();
-
-    //try context class loader first
-    try 
-      {
-        return Class.forName(name, false, loader);
-      }
-    catch (ClassNotFoundException e)
-      {
-        // class not found in the local classpath
-      }
-
-    if (codebases.length() == 0) //==""
-      {
-        loader = defaultLoader;
-      }
-    else
-      {
-        loader = getClassLoader(codebases);
-      }
+    RMIClassLoaderSpi spi = getProviderInstance();
+    if (spi == null)
+      spi = getDefaultProviderInstance(); 
+    return spi.loadClass(codebase, name, null);
+  }
 
-    if (loader == null)
-      {
-        //do not throw NullPointerException
-        throw new ClassNotFoundException ("Could not find class (" + name +
-                                          ") at codebase (" + codebases + ")");
-      }
-      
-    return Class.forName(name, false, loader);
+  public static Class loadClass(String codebase, String name,
+                                ClassLoader defaultLoader)
+    throws MalformedURLException, ClassNotFoundException
+  {
+    RMIClassLoaderSpi spi = getProviderInstance();
+    if (spi == null)
+      spi = getDefaultProviderInstance(); 
+    return spi.loadClass(codebase, name, defaultLoader);
   }
 
   /**
    * Gets a classloader for the given codebase and with the current
    * context classloader as parent.
    * 
-   * @param codebases
+   * @param codebase
    * 
    * @return a classloader for the given codebase
    * 
    * @throws MalformedURLException if the codebase contains a malformed URL
    */
-  public static ClassLoader getClassLoader (String codebases) 
+  public static ClassLoader getClassLoader(String codebase) 
     throws MalformedURLException
   {
-    ClassLoader loader;
-    CacheKey loaderKey = new CacheKey
-      (codebases, Thread.currentThread().getContextClassLoader());
-    loader = (ClassLoader) cacheLoaders.get (loaderKey);
-      
-    if (loader == null)
-      {
-        //create an entry in cacheLoaders mapping a loader to codebases.
-        // codebases are separated by " "
-        StringTokenizer tok = new StringTokenizer (codebases, " ");
-        ArrayList urls = new ArrayList();
-      
-        while (tok.hasMoreTokens())
-          urls.add (new URL (tok.nextToken()));
-      
-        loader = new MyClassLoader ((URL[]) urls.toArray (new URL [urls.size()]),
-                                    Thread.currentThread().getContextClassLoader(),
-                                    codebases);
-        cacheLoaders.put (loaderKey, loader);
-      }
-           
-    return loader;
+    RMIClassLoaderSpi spi = getProviderInstance();
+    if (spi == null)
+      spi = getDefaultProviderInstance(); 
+    return spi.getClassLoader(codebase);
   }
  
   /**
@@ -286,47 +111,12 @@
    * @return a space seperated list of URLs where the class-definition
    * of cl may be found
    */
-  public static String getClassAnnotation (Class cl)
+  public static String getClassAnnotation(Class cl)
   {
-    ClassLoader loader = cl.getClassLoader();
-    
-    if (loader == null
-        || loader == ClassLoader.getSystemClassLoader())
-      {
-        return System.getProperty ("java.rmi.server.codebase");
-      }
-
-    if (loader instanceof MyClassLoader)
-      {
-        return ((MyClassLoader) loader).getClassAnnotation();
-      }
-
-    String s = (String) cacheAnnotations.get (loader);
-
-    if (s != null)
-      return s;
-
-    if (loader instanceof URLClassLoader)
-      {
-        URL[] urls = ((URLClassLoader) loader).getURLs();
-
-        if (urls.length == 0)
-          return null;
-
-        StringBuffer annotation = new StringBuffer (64 * urls.length);
-
-        for (int i = 0; i < urls.length; i++)
-          {
-            annotation.append (urls [i].toExternalForm());
-            annotation.append (' ');
-          }
-
-        s = annotation.toString();
-        cacheAnnotations.put (loader, s);
-        return s;
-      }
-
-    return System.getProperty ("java.rmi.server.codebase");
+    RMIClassLoaderSpi spi = getProviderInstance();
+    if (spi == null)
+      spi = getDefaultProviderInstance(); 
+    return spi.getClassAnnotation(cl);
   }
 
   /**
@@ -335,5 +125,26 @@
   public static Object getSecurityContext (ClassLoader loader)
   {
     throw new Error ("Not implemented");
+  }
+
+  /**
+   * Returns the default service provider for <code>RMIClassLoader</code>.
+   *
+   * @return the default provider for <code>RMIClassLoader</code>
+   */
+  public static RMIClassLoaderSpi getDefaultProviderInstance()
+  {
+    return RMIClassLoaderImpl.getInstance();
+  }
+
+  /**
+   * Chooses, instantiates and returns a service provider.
+   *
+   * @return a service provider
+   */
+  private static RMIClassLoaderSpi getProviderInstance()
+  {
+    // TODO: Do something more useful here.
+    return null;
   }
 }
Index: gnu/java/rmi/server/RMIClassLoaderImpl.java
===================================================================
RCS file: gnu/java/rmi/server/RMIClassLoaderImpl.java
diff -N gnu/java/rmi/server/RMIClassLoaderImpl.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/rmi/server/RMIClassLoaderImpl.java	28 Sep 2005 19:11:44 -0000
@@ -0,0 +1,350 @@
+/* RMIClassLoaderImpl.java -- FIXME: briefly describe file purpose
+   Copyright (C) 2005 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 gnu.java.rmi.server;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.rmi.server.RMIClassLoaderSpi;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * The default implementation of [EMAIL PROTECTED] java.rmi.server.RMIClassLoaderSpi}.
+ *
+ * @author Roman Kennke ([EMAIL PROTECTED])
+ */
+public class RMIClassLoaderImpl extends RMIClassLoaderSpi
+{
+  private static class MyClassLoader extends URLClassLoader
+  {
+    // Package-private to avoid a trampoline constructor.
+    MyClassLoader (URL[] urls, ClassLoader parent, String annotation)
+    {
+      super (urls, parent);
+      this.annotation = annotation;
+    }
+
+    private MyClassLoader (URL[] urls, ClassLoader parent)
+    {
+      super (urls, parent);
+      this.annotation = urlToAnnotation (urls);
+    }
+
+    public static String urlToAnnotation (URL[] urls)
+    {
+      if (urls.length == 0)
+        return null;
+
+      StringBuffer annotation = new StringBuffer (64 * urls.length);
+
+      for (int i = 0; i < urls.length; i++)
+      {
+        annotation.append (urls [i].toExternalForm());
+        annotation.append (' ');
+      }
+
+      return annotation.toString();
+    }
+
+    public final String getClassAnnotation()
+    {
+      return annotation;
+    }
+
+    private final String annotation;
+  }
+
+  /** 
+   * This class is used to identify a cached classloader by its codebase and 
+   * the context classloader that is its parent.
+   */  
+  private static class CacheKey
+  {
+     private String mCodeBase;
+     private ClassLoader mContextClassLoader;
+    
+     public CacheKey (String theCodebase, ClassLoader theContextClassLoader)
+     {
+       mCodeBase = theCodebase;
+       mContextClassLoader = theContextClassLoader;
+     }
+    
+    /**
+     * @return true if the codebase and the context classloader are equal
+     */
+    public boolean equals (Object theOther)
+    {
+      if (theOther instanceof CacheKey)
+      {
+        CacheKey key = (CacheKey) theOther;
+    
+        return (equals (this.mCodeBase,key.mCodeBase)
+                && equals (this.mContextClassLoader, key.mContextClassLoader));
+        }
+      return false;
+    }
+    
+    /**
+     * Test if the two objects are equal or both null.
+     * @param theOne
+     * @param theOther
+     * @return
+     */
+    private boolean equals (Object theOne, Object theOther)
+    {
+      return theOne != null ? theOne.equals (theOther) : theOther == null;
+    }
+
+    /**
+     * @return hashCode  
+     */
+    public int hashCode()
+    {
+      return ((mCodeBase != null           ? mCodeBase.hashCode()           :  0) 
+              ^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1));
+    }
+
+    public String toString()
+    {
+      return "[" + mCodeBase + "," + mContextClassLoader + "]"; 
+    }
+
+  }
+
+  private static RMIClassLoaderImpl instance = null;
+
+  private static Map cacheLoaders; //map annotations to loaders
+  private static Map cacheAnnotations; //map loaders to annotations
+  //class loader for defaultAnnotation
+  private static MyClassLoader defaultClassLoader;
+
+  //defaultAnnotation is got from system property
+  // "java.rmi.server.defaultAnnotation"
+  private static String defaultAnnotation;
+
+  //URL object for defaultAnnotation
+  private static URL defaultCodebase;
+
+  static
+  {
+    // 89 is a nice prime number for Hashtable initial capacity
+    cacheLoaders = new Hashtable (89);
+    cacheAnnotations = new Hashtable (89);
+
+    defaultAnnotation = System.getProperty ("java.rmi.server.defaultAnnotation");
+
+    try
+      {
+        if (defaultAnnotation != null)
+          defaultCodebase = new URL (defaultAnnotation);
+      }
+    catch (Exception _)
+      {
+        defaultCodebase = null;
+      }
+
+    if (defaultCodebase != null)
+      {
+        defaultClassLoader = new MyClassLoader (new URL[] { defaultCodebase }, null,
+                                               defaultAnnotation);
+        cacheLoaders.put (new CacheKey (defaultAnnotation,
+                                        Thread.currentThread().getContextClassLoader()),
+                                        defaultClassLoader);
+      }
+    }
+
+  /**
+   * This is a singleton class and may only be instantiated once from within
+   * the [EMAIL PROTECTED] #getInstance} method.
+   */
+  private RMIClassLoaderImpl()
+  {
+  }
+
+  /**
+   * Returns an instance of RMIClassLoaderImpl.
+   *
+   * @return an instance of RMIClassLoaderImpl
+   */
+  public static RMIClassLoaderSpi getInstance()
+  {
+    if (instance == null)
+      instance = new RMIClassLoaderImpl();
+    return instance;
+  }
+
+  public Class loadClass(String codeBase, String name,
+                         ClassLoader defaultLoader)
+    throws MalformedURLException, ClassNotFoundException
+  {
+    ClassLoader loader;
+    if (defaultLoader == null)
+      loader = Thread.currentThread().getContextClassLoader();
+    else
+      loader = defaultLoader;
+
+    //try context class loader first
+    try 
+      {
+        return Class.forName(name, false, loader);
+      }
+    catch (ClassNotFoundException e)
+      {
+        // class not found in the local classpath
+      }
+    
+    if (codeBase.length() == 0) //==""
+      {
+        loader = defaultClassLoader;
+      }
+    else
+      {
+        loader = getClassLoader(codeBase);
+      }
+
+    if (loader == null)
+      {
+        //do not throw NullPointerException
+        throw new ClassNotFoundException ("Could not find class (" + name +
+                                          ") at codebase (" + codeBase + ")");
+      }
+
+    return Class.forName(name, false, loader);
+  }
+
+  public Class loadProxyClass(String codeBase, String[] interfaces,
+                              ClassLoader defaultLoader)
+      throws MalformedURLException, ClassNotFoundException
+  {
+    // FIXME: Implement this.
+    return null;
+  }
+
+  /**
+   * Gets a classloader for the given codebase and with the current
+   * context classloader as parent.
+   * 
+   * @param codebase
+   * 
+   * @return a classloader for the given codebase
+   * 
+   * @throws MalformedURLException if the codebase contains a malformed URL
+   */
+  public ClassLoader getClassLoader(String codebase)
+    throws MalformedURLException
+  {
+    ClassLoader loader;
+    CacheKey loaderKey = new CacheKey
+    (codebase, Thread.currentThread().getContextClassLoader());
+    loader = (ClassLoader) cacheLoaders.get (loaderKey);
+    
+    if (loader == null)
+      {
+        //create an entry in cacheLoaders mapping a loader to codebases.
+        // codebases are separated by " "
+        StringTokenizer tok = new StringTokenizer (codebase, " ");
+        ArrayList urls = new ArrayList();
+        
+        while (tok.hasMoreTokens())
+          urls.add (new URL(tok.nextToken()));
+        
+        loader = new MyClassLoader((URL[]) urls.toArray(new URL [urls.size()]),
+                                 Thread.currentThread().getContextClassLoader(),
+                                 codebase);
+        cacheLoaders.put (loaderKey, loader);
+      }
+    
+    return loader;
+  }
+
+  /**
+   * Returns a string representation of the network location where a remote
+   * endpoint can get the class-definition of the given class.
+   *
+   * @param cl
+   *
+   * @return a space seperated list of URLs where the class-definition
+   * of cl may be found
+   */
+  public String getClassAnnotation(Class cl)
+  {
+    ClassLoader loader = cl.getClassLoader();
+    
+    if (loader == null
+        || loader == ClassLoader.getSystemClassLoader())
+      {
+        return System.getProperty ("java.rmi.server.codebase");
+      }
+    
+    if (loader instanceof MyClassLoader)
+      {
+        return ((MyClassLoader) loader).getClassAnnotation();
+      }
+    
+    String s = (String) cacheAnnotations.get (loader);
+    
+    if (s != null)
+      return s;
+    
+    if (loader instanceof URLClassLoader)
+      {
+        URL[] urls = ((URLClassLoader) loader).getURLs();
+        
+        if (urls.length == 0)
+          return null;
+        
+        StringBuffer annotation = new StringBuffer (64 * urls.length);
+        
+        for (int i = 0; i < urls.length; i++)
+          {
+            annotation.append (urls [i].toExternalForm());
+            annotation.append (' ');
+          }
+        
+        s = annotation.toString();
+        cacheAnnotations.put (loader, s);
+        return s;
+      }
+
+    return System.getProperty ("java.rmi.server.codebase");
+  }
+}
_______________________________________________
Classpath-patches mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/classpath-patches

Reply via email to