/[classpath]/classpath/java/rmi/server/RMIClassLoader.java
ViewVC logotype

Diff of /classpath/java/rmi/server/RMIClassLoader.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.6 by mark, Thu Oct 31 18:35:23 2002 UTC revision 1.7 by iproetel, Tue Aug 12 12:01:36 2003 UTC
# Line 34  or based on this library.  If you modify Line 34  or based on this library.  If you modify
34  this exception to your version of the library, but you are not  this exception to your version of the library, but you are not
35  obligated to do so.  If you do not wish to do so, delete this  obligated to do so.  If you do not wish to do so, delete this
36  exception statement from your version. */  exception statement from your version. */
   
37  package java.rmi.server;  package java.rmi.server;
38    
39    import java.net.MalformedURLException;
40  import java.net.URL;  import java.net.URL;
 import java.net.URLConnection;  
41  import java.net.URLClassLoader;  import java.net.URLClassLoader;
 import java.io.IOException;  
 import java.io.DataInputStream;  
 import java.net.MalformedURLException;  
42  import java.util.ArrayList;  import java.util.ArrayList;
 import java.util.Collection;  
 import java.util.Collections;  
43  import java.util.Hashtable;  import java.util.Hashtable;
44  import java.util.Map;  import java.util.Map;
45  import java.util.StringTokenizer;  import java.util.StringTokenizer;
 import java.util.WeakHashMap;  
46    
 public class RMIClassLoader  
 {  
47    
48    static private class MyClassLoader extends URLClassLoader  /**
49     * This class provides a set of public static utility methods for supporting
50     * network-based class loading in RMI. These methods are called by RMI's
51     * internal marshal streams to implement the dynamic class loading of types for
52     * RMI parameters and return values.
53     */
54    public class RMIClassLoader
55    {    {
56      static private class MyClassLoader extends URLClassLoader
     private MyClassLoader(URL[] urls, ClassLoader parent, String annotation)  
57      {      {
58        private MyClassLoader(URL[] urls, ClassLoader parent, String annotation)
59          {
60        super(urls, parent);        super(urls, parent);
61        this.annotation = annotation;        this.annotation = annotation;
62      }        }
63    
64      private MyClassLoader(URL[] urls, ClassLoader parent)      private MyClassLoader(URL[] urls, ClassLoader parent)
65      {        {
66        super (urls, parent);        super(urls, parent);
67        this.annotation = urlToAnnotation(urls);        this.annotation = urlToAnnotation(urls);
68      }        }
69    
70      public static String urlToAnnotation(URL[] urls)      public static String urlToAnnotation(URL[] urls)
71      {        {
72        if (urls.length == 0)        if (urls.length == 0)
73          return null;        {
74            return null;
75            }
76    
77        StringBuffer annotation = new StringBuffer(64*urls.length);        StringBuffer annotation = new StringBuffer(64 * urls.length);
78        for(int i = 0; i < urls.length; i++)  
79          {        for (int i = 0; i < urls.length; i++)
80            annotation.append(urls[i].toExternalForm());          {
81            annotation.append(' ');          annotation.append(urls[i].toExternalForm());
82          }          annotation.append(' ');
83            }
84    
85        return annotation.toString();        return annotation.toString();
86      }        }
87    
88      public final String getClassAnnotation(){      public final String getClassAnnotation()
89          {
90        return annotation;        return annotation;
91      }        }
92    
93      private final String annotation;      private final String annotation;
94        
95        }
96      
97      /**
98       * This class is used to identify a cached classloader by its codebase and
99       * the context classloader that is its parent.
100       */  
101      private static class CacheKey
102      {
103            
104            private String mCodeBase;
105            private ClassLoader mContextClassLoader;
106            
107            public CacheKey(String theCodebase, ClassLoader theContextClassLoader)
108            {
109          mCodeBase = theCodebase;
110              mContextClassLoader = theContextClassLoader;
111        }
112              
113            
114            
115        /**
116         * @return true if the codebase and the context classloader are equal
117         */
118        public boolean equals(Object theOther)
119        {
120          if(theOther != null && theOther instanceof CacheKey)
121            {
122            CacheKey key = (CacheKey) theOther;
123            return (  equals(this.mCodeBase,key.mCodeBase)
124                   && equals(this.mContextClassLoader,key.mContextClassLoader) );          
125            }
126          return false;
127        }
128        
129        /**
130         * Test if the two objects are equal or both null.
131         * @param theOne
132         * @param theOther
133         * @return
134         */
135        private boolean equals(Object theOne, Object theOther)
136        {
137            return (theOne != null ? theOne.equals(theOther): theOther == null);    
138        }
139    
140        /**
141         * @return hashCode  
142         */
143        public int hashCode()
144        {
145          return ((mCodeBase != null           ? mCodeBase.hashCode()           :  0)
146                 ^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1));
147        }
148    
149        
150        public String toString()
151        {
152          return "["+mCodeBase+","+mContextClassLoader+"]";
153        }
154    
155    }    }
156    
157    private static Map cacheLoaders; //map annotations to loaders    private static Map cacheLoaders; //map annotations to loaders
158    private static Map cacheAnnotations; //map loaders to annotations    private static Map cacheAnnotations; //map loaders to annotations
   
   //defaultAnnotation is got from system property  
   // "java.rmi.server.defaultAnnotation"  
159    private static String defaultAnnotation;    private static String defaultAnnotation;
160    
161    //URL object for defaultAnnotation    //URL object for defaultAnnotation
162    private static URL defaultCodebase;    private static URL defaultCodebase;
163    
164    //class loader for defaultAnnotation    //class loader for defaultAnnotation
165    private static MyClassLoader defaultLoader;    private static MyClassLoader defaultLoader;
166      
167    static    static
168    {      {
169      // 89 is a nice prime number for Hashtable initial capacity      // 89 is a nice prime number for Hashtable initial capacity
170      cacheLoaders = new Hashtable(89);      cacheLoaders = new Hashtable(89);
171      cacheAnnotations = new Hashtable(89);      cacheAnnotations = new Hashtable(89);
172        
173      defaultAnnotation = System.getProperty("java.rmi.server.defaultAnnotation");      defaultAnnotation = System.getProperty("java.rmi.server.defaultAnnotation");
174      try  
175        try
176          {
177          if (defaultAnnotation != null)
178        {        {
179          if (defaultAnnotation != null)          defaultCodebase = new URL(defaultAnnotation);
180            defaultCodebase = new URL(defaultAnnotation);          }
181        }        }
182      catch(Exception _)      catch (Exception _)
183        {        {
184          defaultCodebase = null;        defaultCodebase = null;
185        }        }
186    
187      if (defaultCodebase != null)      if (defaultCodebase != null)
188        {        {
189          defaultLoader = new MyClassLoader(new URL[]{ defaultCodebase },        defaultLoader = new MyClassLoader(new URL[] { defaultCodebase }, null,
190                                            null, defaultAnnotation);                                          defaultAnnotation);
191          cacheLoaders.put(defaultAnnotation, defaultLoader);        cacheLoaders.put(new CacheKey(defaultAnnotation,Thread.currentThread().getContextClassLoader()), defaultLoader);
192        }        }
193    }      }
194      
195    /**    /**
196     * @deprecated     * @deprecated
197     */     */
198    public static Class loadClass(String name)    public static Class loadClass(String name)
199      throws MalformedURLException, ClassNotFoundException    throws MalformedURLException, ClassNotFoundException
200    {      {
201      return (loadClass("", name));      return (loadClass("", name));
202    }      }
203    
204    public static Class loadClass(String codebases, String name)    public static Class loadClass(String codebases, String name)
205      throws MalformedURLException, ClassNotFoundException    throws MalformedURLException, ClassNotFoundException
206    {      {
207      Class c = null;      Class c = null;
208      ClassLoader loader = Thread.currentThread().getContextClassLoader();      ClassLoader loader = Thread.currentThread().getContextClassLoader();
209    
210      //try context class loader first      //try context class loader first
211      try      try
212        {        {
213              c = loader.loadClass(name);              c = loader.loadClass(name);
       }  
     catch(ClassNotFoundException e) {}  
214    
     if (c != null)  
215        return c;        return c;
216          }
217        catch (ClassNotFoundException e)
218          {
219          // class not found in the local classpath
220          }
221    
222      if (codebases.length() == 0) //==""      if (codebases.length() == 0) //==""
223          {
224        loader = defaultLoader;        loader = defaultLoader;
225      else        }
226        else
227        {        {
228          loader = (ClassLoader)cacheLoaders.get(codebases);        loader = getClassLoader(codebases);
         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()]),  
                                         null, codebases);  
             cacheLoaders.put(codebases, loader);  
           }  
229        }        }
230    
231        if (loader == null)
232          {
233          //do not throw NullPointerException
234          throw new ClassNotFoundException("Could not find class (" + name +
235                                           ") at codebase (" + codebases + ")");
236          }
237          
238      return loader.loadClass(name);      return loader.loadClass(name);
239    }      }
240      
241        /**
242         * Gets a classloader for the given codebase and with the current context classloader
243         * as parent.
244         * @param codebases
245         * @return a classloader for the given codebase
246         * @throws MalformedURLException if the codebase contains a malformed URL
247         */
248        private static ClassLoader getClassLoader(String codebases) throws MalformedURLException
249        {
250          ClassLoader loader;
251          CacheKey loaderKey = new CacheKey(codebases, Thread.currentThread().getContextClassLoader());
252          loader = (ClassLoader) cacheLoaders.get(loaderKey);
253          
254          if (loader == null)
255            {
256            //create an entry in cacheLoaders mapping a loader to codebases.
257            // codebases are separated by " "
258            StringTokenizer tok = new StringTokenizer(codebases, " ");
259            ArrayList urls = new ArrayList();
260          
261            while (tok.hasMoreTokens())
262              urls.add(new URL(tok.nextToken()));
263          
264            loader = new MyClassLoader( (URL[]) urls.toArray(new URL[urls.size()]),
265                                        Thread.currentThread().getContextClassLoader(),
266                                        codebases);
267            cacheLoaders.put(loaderKey, loader);
268            }
269              
270          return loader;
271        }
272    
273      /**
274       * Returns a string representation of the network location where a remote
275       * endpoint can get the class-definition of the given class.
276       * @param cl
277       * @return a space seperated list of URLs where the class-definition of cl may be found
278       */
279    public static String getClassAnnotation(Class cl)    public static String getClassAnnotation(Class cl)
280    {      {
281      ClassLoader loader = cl.getClassLoader();      ClassLoader loader = cl.getClassLoader();
282      if (loader == null || loader == ClassLoader.getSystemClassLoader())  
283        if ((loader == null) || (loader == ClassLoader.getSystemClassLoader()))
284        {        {
285          return null; //??        return System.getProperty("java.rmi.server.codebase");
286        }        }
287            
288      if (loader instanceof MyClassLoader)      if (loader instanceof MyClassLoader)
289        {        {
290          return ((MyClassLoader)loader).getClassAnnotation();        return ((MyClassLoader) loader).getClassAnnotation();
291        }        }
292            
293      String s = (String)cacheAnnotations.get(loader);      String s = (String) cacheAnnotations.get(loader);
294    
295      if (s != null)      if (s != null)
296        {
297        return s;        return s;
298                      }
299    
300      if (loader instanceof URLClassLoader)      if (loader instanceof URLClassLoader)
301        {        {
302          URL[] urls = ((URLClassLoader)loader).getURLs();        URL[] urls = ((URLClassLoader) loader).getURLs();
303          if(urls.length == 0)  
304            return null;        if (urls.length == 0)
305          {
306          StringBuffer annotation = new StringBuffer(64*urls.length);          return null;
307          for(int i = 0; i < urls.length; i++)          }
308            {  
309              annotation.append(urls[i].toExternalForm());        StringBuffer annotation = new StringBuffer(64 * urls.length);
310              annotation.append(' ');  
311            }        for (int i = 0; i < urls.length; i++)
312          s = annotation.toString();          {
313          cacheAnnotations.put(loader, s);          annotation.append(urls[i].toExternalForm());
314            annotation.append(' ');
315            }
316    
317          s = annotation.toString();
318          cacheAnnotations.put(loader, s);
319    
320          return s;
321        }        }
322      return null;  
323    }      return System.getProperty("java.rmi.server.codebase");
324          }
325    
326    /**    /**
327     * @deprecated     * @deprecated
328     */     */
329    public static Object getSecurityContext(ClassLoader loader)    public static Object getSecurityContext(ClassLoader loader)
330    {      {
331      throw new Error("Not implemented");      throw new Error("Not implemented");
332        }
333    }    }
   
 }  

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26