GateClassLoader.java
001 /*
002  *  GateClassLoader.java
003  *
004  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006  *
007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
008  *  software, licenced under the GNU Library General Public License,
009  *  Version 2, June 1991 (in the distribution as file licence.html,
010  *  and also available at http://gate.ac.uk/gate/licence.html).
011  
012  *  Kalina Bontcheva, 1998
013  *
014  *  Revised by Hamish for 1.2 style and URL/Jar loading, June 2000
015  *
016  *  $Id: GateClassLoader.java 12006 2009-12-01 17:24:28Z thomas_heitz $
017  */
018 
019 package gate.util;
020 
021 import java.net.URL;
022 import java.net.URLClassLoader;
023 
024 /** GATE's class loader, which allows loading of classes over the net.
025   * A list of URLs is searched, which should point at .jar files or
026   * to directories containing class file hierarchies.
027   * The class loader is unusual in supporting reloading of classes, which
028   * is useful for CREOLE developers who want to recompile modules without
029   * relaunching GATE.
030   * The loader is also used for creating JAPE RHS action classes.
031   */
032 public class GateClassLoader extends URLClassLoader {
033 
034   /** Debug flag */
035   private static final boolean DEBUG = false;
036 
037   /** Default construction - use an empty URL list. */
038   public GateClassLoader() { super(new URL[0])}
039 
040   /** Chaining constructor. */
041   public GateClassLoader(ClassLoader parent) { super(new URL[0], parent)}
042 
043   /** Default construction with URLs list. */
044   public GateClassLoader(URL[] urls) { super(urls)}
045 
046   /** Chaining constructor with URLs list. */
047   public GateClassLoader(URL[] urls, ClassLoader parent) {
048     super(urls, parent);
049   // Chaining constructor with URLs list.
050 
051   /** Appends the specified URL to the list of URLs to search for classes
052     * and resources.
053     */
054   @Override
055   public void addURL(URL url) { super.addURL(url)}
056 
057   /** Delegate loading to the super class (loadClass has protected
058     * access there).
059     */
060   @Override
061   public synchronized Class<?> loadClass(String name, boolean resolve)
062   throws ClassNotFoundException {
063     return super.loadClass(name, resolve);
064   // loadClass(name, resolve)
065 
066   /** Forward a call to super.defineClass, which is protected and final
067     * in super. This is used by JAPE and the Jdk compiler class.
068     */
069   public synchronized Class<?> defineGateClass(String name, byte[] bytes, int offset, int len)
070   {
071     return super.defineClass(name, bytes, offset, len);
072   // defineGateClass(name, bytes, offset, len);
073 
074   /** Forward a call to super.resolveClass, which is protected and final
075     * in super. This is used by JAPE and the Jdk compiler class
076     */
077   public synchronized void resolveGateClass(Class<?> c) { super.resolveClass(c)}
078 
079   /**
080    * Given a fully qualified class name, this method returns the instance of Class if it is already loaded using the ClassLoader
081    * or it returns null.
082    @param name
083    @return
084    */
085   public synchronized Class<?> findExistingClass(String name) {
086     return findLoadedClass(name);
087   }
088   
089   /** Reload a class. This works on the assumption that all classes that
090     * we are asked to reload will have been loaded by a GateClassLoader
091     * and not the system class loader. If this is not the case, this
092     * method will simply return the previously loaded class (because of
093     * the delegation chaining model of class loaders in JDK1.2 and above).
094     <P>
095     * The method works by avoiding the normal chaining behaviour of
096     * class loaders by creating a star-shaped group of parallel loaders.
097     * Each of these chains of the system class loader, but as long as
098     * the class that we wish to reload wan't loaded by the system loader,
099     * it will not be present in a new loader of this type.
100     <P>
101     * An implication is that reloaded classes must always be instantiated
102     * via the class returned from this method.
103     */
104   public synchronized Class<?> reloadClass(String namethrows ClassNotFoundException {
105     Class<?> theClass = null;
106 
107     // if the class isn't already present in this class loader
108     // we can just load it
109     theClass = findLoadedClass(name);
110     if(theClass == null)
111       return loadClass(name);
112 
113     // if there's a cached loader, try that
114     if(cachedReloader != null) {
115 
116       // if the cached loader hasn't already loaded this file, then ask it to
117       theClass = cachedReloader.findLoadedClass(name);
118       if(theClass == null)
119         return cachedReloader.loadClass(name);
120     }
121 
122     // create a new reloader and cache it
123     cachedReloader = new GateClassLoader(getURLs());
124 
125     // ask the new reloader to load the class
126     return cachedReloader.loadClass(name, true);
127 
128   // reloadClass(String name)
129 
130   /** A cache used by the reloadClass method to store the last new
131     * loader that we created.
132     */
133   private static GateClassLoader cachedReloader = null;
134 
135 // GateClassLoader