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 name) throws 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
|