| Method from org.apache.tomcat.util.loader.ModuleClassLoader Detail: |
void addRepository(String repository) {
// Add this repository to our underlying class loader
try {
boolean mod=modified();
URL url = new URL(repository);
super.addURL(url);
if( ! mod ) {
// don't check if it is modified, so it works
updateStamp();
}
} catch (MalformedURLException e) {
IllegalArgumentException iae = new IllegalArgumentException
("Invalid repository: " + repository);
iae.initCause(e);
//jdkCompat.chainException(iae, e);
throw iae;
}
}
Add a new repository to the set of places this ClassLoader can look for
classes to be loaded. |
public Class findClass(String name) throws ClassNotFoundException {
return findClass2(name, true);
}
Find the specified class in our local repositories, if possible. If
not found, throw ClassNotFoundException. |
public Class findClass2(String name,
boolean del2repo) throws ClassNotFoundException {
if( del2repo ) {
return ((RepositoryClassLoader)repository.getClassLoader()).findClass(name);
} // else
Class clazz = null;
try {
clazz = super.findClass(name);
} catch (RuntimeException e) {
if (DEBUG)
log("findClass() -- >RuntimeException " + name, e);
throw e;
} catch( ClassNotFoundException ex ) {
URL cp[]=this.getURLs();
if (DEBUGNF)
log("findClass() NOTFOUND " + name + " " + (( cp.length > 0 ) ? cp[0].toString() : "") );
throw ex;
}
if (clazz == null) { // does it ever happen ?
if (DEBUGNF)
log("findClass() NOTFOUND throw CNFE " + name);
throw new ClassNotFoundException(name);
}
// Return the class we have located
if (DEBUG) {
if( clazz.getClassLoader() != this )
log("findClass() FOUND " + clazz + " Loaded by " + clazz.getClassLoader());
else
log("findClass() FOUND " + clazz );
}
return (clazz);
}
|
public Class findLocalClass(String name) throws ClassNotFoundException {
Class clazz = findLoadedClass(name);
if (clazz != null) {
if (DEBUG)
log("findLocalClass() - FOUND " + name);
return (clazz);
}
return findClass(name);
}
Same as findClass, but also checks if the class has been previously
loaded.
In most implementations, findClass() doesn't check with findLoadedClass().
In order to implement repository, we need to ask each loader in the group
to load only from it's local resources - however this will lead to errors
( duplicated definition ) if findClass() is used. |
public URL findResource(String name) {
return findResource2( name, true);
}
Find the specified resource in our local repository, and return a
URL refering to it, or null if this resource
cannot be found. |
public URL findResource2(String name,
boolean del2repo) {
if( del2repo ) {
return ((RepositoryClassLoader)repository.getClassLoader()).findResource(name);
} // else:
URL url = null;
url = super.findResource(name);
if(url==null) {
// try the repository
// TODO
}
if (url==null && DEBUG) {
if (DEBUGNF) log("findResource() NOTFOUND " + name );
return null;
}
if (DEBUG) log("findResource() found " + name + " " + url );
return (url);
}
|
public Enumeration findResources(String name) throws IOException {
return findResources2(name, true);
}
Return an enumeration of URLs representing all of the
resources with the given name. If no resources with this name are
found, return an empty enumeration. |
Enumeration findResources2(String name,
boolean del2repo) throws IOException {
if( del2repo ) {
return ((RepositoryClassLoader)repository.getClassLoader()).findResources(name);
} else {
return super.findResources(name);
}
}
|
Module getModule() {
return module;
}
Not public - his can only be called from package.
To get the module from a ClassLoader you need access to the Loader
instance. |
public URL getResource(String name) {
return getResource2( name, null, true);
}
getResource() - modified to implement the search alghoritm |
URL getResource2(String name,
ClassLoader originator,
boolean delegate2repo) {
URL url = null;
// (1) Delegate to parent if requested
if (delegate) {
url=getResourceParentDelegate(name);
if(url!=null ) return url;
}
// (2) Search local repositories
url = findResource(name);
if (url != null) {
// TODO: antijar locking - WebappClassLoader is making a copy ( is it ??)
if (DEBUG)
log("getResource() found locally " + delegate + " " + name + " " + url);
return (url);
}
// Finally, try the group loaders ( via super() in StandardClassLoader ).
// not found using normal loading mechanism. load from one of the classes in the group
if( delegate2repo && repository!=null ) {
url=repository.findResource(this, name);
if(url!=null ) {
if( DEBUG )
log("getResource() FOUND from group " + repository.getName() + " " + name + " " + url);
return url;
}
}
// (3) Delegate to parent unconditionally if not already attempted
if( !delegate ) {
url=getResourceParentDelegate(name);
if(url!=null ) return url;
}
// (4) Resource was not found
if (DEBUGNF)
log("getResource() NOTFOUND " + delegate + " " + name + " " + url);
return (null);
}
getResource() - same thing, but don't delegate to repo if called
from repo |
boolean isStarted() {
return started;
}
Support for "disabled" state. |
public Class loadClass(String name,
boolean resolve) throws ClassNotFoundException {
return loadClass2( name, resolve, true );
}
Load the class with the specified name, searching using the following
algorithm until it finds and returns the class. If the class cannot
be found, returns ClassNotFoundException.
- Call
findLoadedClass(String) to check if the
class has already been loaded. If it has, the same
Class object is returned.
- If the
delegate property is set to true,
call the loadClass() method of the parent class
loader, if any.
- Call
findClass() to find this class in our locally
defined repositories.
- Call the
loadClass() method of our parent
class loader, if any.
If the class was found using the above steps, and the
resolve flag is true, this method will then
call resolveClass(Class) on the resulting Class object. |
public Class loadClass2(String name,
boolean resolve,
boolean del2repo) throws ClassNotFoundException {
Class clazz = null;
// Don't load classes if class loader is stopped
if (!started) {
log("Not started " + this + " " + module);
//throw new ThreadDeath();
start();
}
// (0) Check our previously loaded local class cache
clazz = findLoadedClass(name);
if (clazz != null) {
if (DEBUG)
log("loadClass() FOUND findLoadedClass " + name + " , " + resolve);
if (resolve) resolveClass(clazz);
return (clazz);
}
// (0.2) Try loading the class with the system class loader, to prevent
// the webapp from overriding J2SE classes
try {
clazz = getSystemClassLoader().loadClass(name);
if (clazz != null) {
// enabling this can result in ClassCircularityException
// if (DEBUG)
// log("loadClass() FOUND system " + name + " , " + resolve);
if (resolve) resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
// Ignore
}
// TODO: delegate based on filter
boolean delegateLoad = delegate;// || filter(name);
// (1) Delegate to our parent if requested
if (delegateLoad) {
ClassLoader loader = getParent();
if( loader != null ) {
try {
clazz = loader.loadClass(name);
if (clazz != null) {
if (DEBUG)
log("loadClass() FOUND by parent " + delegate + " " + name + " , " + resolve);
if (resolve)
resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
}
// (2) Search local repositories
try {
clazz = findClass(name);
if (clazz != null) {
if (DEBUG)
log("loadClass - FOUND findClass " + delegate + " " + name + " , " + resolve);
if (resolve) resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
// Finally, try the group loaders ( via super() in StandardClassLoader ).
// not found using normal loading mechanism. load from one of the classes in the group
if( del2repo && repository!=null ) {
Class cls=repository.findClass(this, name);
if(cls!=null ) {
if( DEBUG )
log("loadClass(): FOUND from group " + repository.getName() + " " + name);
if (resolve) resolveClass(clazz);
return cls;
}
}
// (3) Delegate to parent unconditionally
if (!delegateLoad) {
ClassLoader loader = getParent();
if( loader != null ) {
try {
clazz = loader.loadClass(name);
if (clazz != null) {
if (DEBUG)
log("loadClass() FOUND parent " + delegate + " " + name + " , " + resolve);
if (resolve) resolveClass(clazz);
return (clazz);
}
} catch (ClassNotFoundException e) {
;
}
}
}
if( DEBUGNF ) log("loadClass(): NOTFOUND " + name + " xxx " + getParent() + " " + repository.getName() );
throw new ClassNotFoundException(name);
}
|
boolean modified() {
URL cp[]=super.getURLs();
if (cp != null ) {
for (int i = 0; i < cp.length; i++) {
File f=new File(cp[i].getFile());
long lm=f.lastModified();
if( lm > lastModified ) {
log( "Modified file: " + f + " " + lm + " " + lastModified);
return true;
}
// assume dirs are used only for debug and small
if( f.isDirectory() ) {
return dirCheck(f);
}
}
}
if (DEBUG)
log("modified() false");
// TODO - check at least the jars
return (false);
}
Have one or more classes or resources been modified so that a reload
is appropriate?
Not public - call it via Module |
void setDelegate(boolean delegate) {
// ------------------------------------------------------------- Properties
this.delegate = delegate;
}
Set the "delegate first" flag for this class loader. |
void setModule(Module webappLoader) {
this.module=webappLoader;
}
|
void setRepository(Repository lg) {
this.repository=lg;
}
|
void setWorkDir(File s) {
// TODO
}
|
void start() {
started = true;
}
|
void stop() {
started = false;
}
|
public String toString() {
StringBuffer sb = new StringBuffer("ModuleCL ");
sb.append(debugObj).append(" delegate: ");
sb.append(delegate);
//sb.append("\r\n");
sb.append(" cp: ");
URL cp[]=super.getURLs();
if (cp != null ) {
for (int i = 0; i < cp.length; i++) {
sb.append(" ");
sb.append(cp[i].getFile());
}
}
if (getParent() != null) {
sb.append("\r\n---------- > Parent: ");
sb.append(getParent().toString());
sb.append("\r\n");
}
return (sb.toString());
}
Render a String representation of this object. |
void updateStamp() {
URL cp[]=super.getURLs();
if (cp != null ) {
for (int i = 0; i < cp.length; i++) {
File f=new File(cp[i].getFile());
long lm=f.lastModified();
if( lm > lastModified ) lastModified=lm;
}
}
}
|
protected boolean validate(String name) {
if (name == null)
return false;
if (name.startsWith("java."))
return false;
return true;
}
Validate a classname. As per SRV.9.7.2, we must restict loading of
classes from J2SE (java.*) and classes of the servlet API
(javax.servlet.*). That should enhance robustness and prevent a number
of user error (where an older version of servlet.jar would be present
in /WEB-INF/lib). |