package abbot.util;
import abbot.Log;
/** Provides support for loading a class <i>before</i> checking the parent
* class loader for it. If the shouldDelegate method returns false for a
* given class name, it will defer to its parent class loader only if the
* class is not found in this loader's path. This provides a means for
* reloading classes that would otherwise be permanently cached by the app
* or boot class loaders.<p>
* The name for this class is not quite correct; it <i>will</i> delegate to
* its parent if it doesn't find a given class.
*/
public class NonDelegatingClassLoader extends PathClassLoader {
public NonDelegatingClassLoader(String path, ClassLoader parent) {
super(path, parent);
}
/** Returns whether the given class should be given to the parent class
* loader to try before this one does. The default implementation always
* returns false. Making this method return true will revert to the
* standard class loader behavior.
*/
protected boolean shouldDelegate(String name) {
return false;
}
/** Find the given class in the search path. */
public Class findClass(String name) throws ClassNotFoundException {
Log.debug("Looking up " + name + " with " + this);
return super.findClass(name);
}
/** Load the given class, but attempt to load <i>before</i> the parent if
shouldDelegate returns false for the given class.
*/
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
if (shouldDelegate(name)) {
Log.debug("Delegating lookup for " + name);
return super.loadClass(name, resolve);
}
else {
Log.debug("Non-delegating lookup for " + name);
Class c = findLoadedClass(name);
if (c == null) {
try {
c = findClass(name);
}
catch(SecurityException se) {
Log.debug(se);
// We're not allowed to find it, so give it to the parent
return super.loadClass(name, resolve);
}
catch(ClassNotFoundException cnf) {
// If we can't find it, maybe the parent can
return super.loadClass(name, resolve);
}
if (resolve) {
resolveClass(c);
}
}
else {
Log.debug("Class already loaded " + name);
}
return c;
}
}
}