[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [cp-patches] FYI: Implemented missing RMI method
From: |
Thomas Fitzsimmons |
Subject: |
Re: [cp-patches] FYI: Implemented missing RMI method |
Date: |
Thu, 29 Sep 2005 13:27:56 -0400 |
On Thu, 2005-09-29 at 09:19 +0200, Meskauskas Audrius wrote:
> Oh, this is great! In future that thing will also load classes for
> javax.rmi that I am finishing in days.
Finishing to the 1.4 level or to the 1.5 level? In general, I think we
should be aiming for full 1.5 API coverage now, even if we can't
genericize things yet.
Tom
>
> Roman Kennke wrote:
>
> >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 <address@hidden>
> >
> > * 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 address@hidden
> >java.rmi.server.RMIClassLoaderSpi}.
> >+ *
> >+ * @author Roman Kennke (address@hidden)
> >+ */
> >+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 address@hidden #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
> >address@hidden
> >http://lists.gnu.org/mailman/listinfo/classpath-patches
> >
> >
>
>
>
> _______________________________________________
> Classpath-patches mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/classpath-patches