1   /*
2    *  GateClassLoader.java
3    *
4    *  Copyright (c) 1998-2005, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   * 
11   *  Kalina Bontcheva, 1998
12   *
13   *  Revised by Hamish for 1.2 style and URL/Jar loading, June 2000
14   *
15   *  $Id: GateClassLoader.java,v 1.14 2005/10/10 17:41:36 nirajaswani Exp $
16   */
17  
18  package gate.util;
19  
20  import java.net.URL;
21  import java.net.URLClassLoader;
22  
23  /** GATE's class loader, which allows loading of classes over the net.
24    * A list of URLs is searched, which should point at .jar files or
25    * to directories containing class file hierarchies.
26    * The class loader is unusual in supporting reloading of classes, which
27    * is useful for CREOLE developers who want to recompile modules without
28    * relaunching GATE.
29    * The loader is also used for creating JAPE RHS action classes.
30    */
31  public class GateClassLoader extends URLClassLoader {
32  
33    /** Debug flag */
34    private static final boolean DEBUG = false;
35  
36    /** Default construction - use an empty URL list. */
37    public GateClassLoader() { super(new URL[0]); }
38  
39    /** Chaining constructor. */
40    public GateClassLoader(ClassLoader parent) { super(new URL[0], parent); }
41  
42    /** Default construction with URLs list. */
43    public GateClassLoader(URL[] urls) { super(urls); }
44  
45    /** Chaining constructor with URLs list. */
46    public GateClassLoader(URL[] urls, ClassLoader parent) {
47      super(urls, parent);
48    } // Chaining constructor with URLs list.
49  
50    /** Appends the specified URL to the list of URLs to search for classes
51      * and resources.
52      */
53    public void addURL(URL url) { super.addURL(url); }
54  
55    /** Delegate loading to the super class (loadClass has protected
56      * access there).
57      */
58    public synchronized Class loadClass(String name, boolean resolve)
59    throws ClassNotFoundException {
60      return super.loadClass(name, resolve);
61    } // loadClass(name, resolve)
62  
63    /** Forward a call to super.defineClass, which is protected and final
64      * in super. This is used by JAPE and the Jdk compiler class.
65      */
66    public Class defineGateClass(String name, byte[] bytes, int offset, int len)
67    {
68      return super.defineClass(name, bytes, offset, len);
69    } // defineGateClass(name, bytes, offset, len);
70  
71    /** Forward a call to super.resolveClass, which is protected and final
72      * in super. This is used by JAPE and the Jdk compiler class
73      */
74    public void resolveGateClass(Class c) { super.resolveClass(c); }
75  
76    /**
77     * Given a fully qualified class name, this method returns the instance of Class if it is already loaded using the ClassLoader
78     * or it returns null.
79     * @param name
80     * @return
81     */
82    public Class findExistingClass(String name) {
83      return findLoadedClass(name);
84    }
85    
86    /** Reload a class. This works on the assumption that all classes that
87      * we are asked to reload will have been loaded by a GateClassLoader
88      * and not the system class loader. If this is not the case, this
89      * method will simply return the previously loaded class (because of
90      * the delegation chaining model of class loaders in JDK1.2 and above).
91      * <P>
92      * The method works by avoiding the normal chaining behaviour of
93      * class loaders by creating a star-shaped group of parallel loaders.
94      * Each of these chains of the system class loader, but as long as
95      * the class that we wish to reload wan't loaded by the system loader,
96      * it will not be present in a new loader of this type.
97      * <P>
98      * An implication is that reloaded classes must always be instantiated
99      * via the class returned from this method.
100     */
101   public Class reloadClass(String name) throws ClassNotFoundException {
102     Class theClass = null;
103 
104     // if the class isn't already present in this class loader
105     // we can just load it
106     theClass = findLoadedClass(name);
107     if(theClass == null)
108       return loadClass(name);
109 
110     // if there's a cached loader, try that
111     if(cachedReloader != null) {
112 
113       // if the cached loader hasn't already loaded this file, then ask it to
114       theClass = cachedReloader.findLoadedClass(name);
115       if(theClass == null)
116         return cachedReloader.loadClass(name);
117     }
118 
119     // create a new reloader and cache it
120     cachedReloader = new GateClassLoader(getURLs());
121 
122     // ask the new reloader to load the class
123     return cachedReloader.loadClass(name, true);
124 
125   } // reloadClass(String name)
126 
127   /** A cache used by the reloadClass method to store the last new
128     * loader that we created.
129     */
130   private static GateClassLoader cachedReloader = null;
131 
132 } // GateClassLoader
133