Do not remove this method without running the WebIntegrationTestSuite */ public URL[] getAllURLs() { return repository.getURLs(); } /** * Black list a class * * @param name the name of the class */ public void addToClassBlackList(String name) { classBlackList.add(name); } /** * Remove class from black list * * @param name the name of the class */ public void removeFromClassBlackList(String name) { classBlackList.remove(name); } /** * Is the class black listed? * * @param name the name of the class * @return true when the class is black listed, false otherwise */ public boolean isClassBlackListed(String name) { return classBlackList.contains(name); } /** * Clear any class black list. */ public void clearClassBlackList() { classBlackList.clear(); } /** * Black list a resource * * @param name the name of the resource */ public void addToResourceBlackList(String name) { resourceBlackList.add(name); } /** * Remove resource from black list * * @param name the name of the resource */ public void removeFromResourceBlackList(String name) { resourceBlackList.remove(name); } /** * Is the resource black listed? * * @param name the name of the resource * @return true when the resource is black listed, false otherwise */ public boolean isResourceBlackListed(String name) { return resourceBlackList.contains(name); } /** * Clear any resource blacklist. */ public void clearResourceBlackList() { resourceBlackList.clear(); } /** * Clear all blacklists */ public void clearBlackLists() { clearClassBlackList(); clearResourceBlackList(); } // URLClassLoader overrides -------------------------------------- /** The only caller of this method should be the VM initiated * loadClassInternal() method. This method attempts to acquire the * UnifiedLoaderRepository2 lock and then asks the repository to * load the class. * *
Forwards request to {@link LoaderRepository}. */ public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { boolean trace = log.isTraceEnabled(); if (trace) log.trace("loadClass " + this + " name=" + name+", loadClassDepth="+loadClassDepth); Class clazz = null; try { if (repository != null) { clazz = repository.getCachedClass(name); if (clazz != null) { if( log.isTraceEnabled() ) { StringBuffer buffer = new StringBuffer("Loaded class from cache, "); ClassToStringAction.toString(clazz, buffer); log.trace(buffer.toString()); } return clazz; } } clazz = loadClassImpl(name, resolve, Integer.MAX_VALUE); return clazz; } finally { if (trace) { if (clazz != null) log.trace("loadClass " + this + " name=" + name + " class=" + clazz + " cl=" + clazz.getClassLoader()); else log.trace("loadClass " + this + " name=" + name + " not found"); } } } /** The only caller of this method should be the VM initiated * loadClassInternal() method. This method attempts to acquire the * UnifiedLoaderRepository2 lock and then asks the repository to * load the class. * *
Forwards request to {@link LoaderRepository}.
*/
public Class loadClassBefore(String name)
throws ClassNotFoundException
{
boolean trace = log.isTraceEnabled();
if (trace)
log.trace("loadClassBefore " + this + " name=" + name);
Class clazz = null;
try
{
clazz = loadClassImpl(name, false, addedOrder);
return clazz;
}
finally
{
if (trace)
{
if (clazz != null)
log.trace("loadClassBefore " + this + " name=" + name + " class=" + clazz + " cl=" + clazz.getClassLoader());
else
log.trace("loadClassBefore " + this + " name=" + name + " not found");
}
}
}
public synchronized Class loadClassImpl(String name, boolean resolve, int stopAt)
throws ClassNotFoundException
{
loadClassDepth ++;
boolean trace = log.isTraceEnabled();
if( trace )
log.trace("loadClassImpl, name="+name+", resolve="+resolve);
if( repository == null )
{
// If we have been undeployed we can still try locally
try
{
return super.loadClass(name, resolve);
}
catch (ClassNotFoundException ignored)
{
}
String msg = "Invalid use of destroyed classloader, UCL destroyed at:";
throw new ClassNotFoundException(msg, this.unregisterTrace);
}
/* Since loadClass can be called from loadClassInternal with the monitor
already held, we need to determine if there is a ClassLoadingTask
which requires this UCL. If there is, we release the UCL monitor
so that the ClassLoadingTask can use the UCL.
*/
boolean acquired = attempt(1);
while( acquired == false )
{
/* Another thread needs this UCL to load a class so release the
monitor acquired by the synchronized method. We loop until
we can acquire the class loading lock.
*/
try
{
if( trace )
log.trace("Waiting for loadClass lock");
this.wait();
}
catch(InterruptedException ignore)
{
}
acquired = attempt(1);
}
ClassLoadingTask task = null;
try
{
Thread t = Thread.currentThread();
// Register this thread as owning this UCL
if( loadLock.holds() == 1 )
LoadMgr3.registerLoaderThread(this, t);
// Create a class loading task and submit it to the repository
task = new ClassLoadingTask(name, this, t, stopAt);
/* Process class loading tasks needing this UCL until our task has
been completed by the thread owning the required UCL(s).
*/
UnifiedLoaderRepository3 ulr3 = (UnifiedLoaderRepository3) repository;
if( LoadMgr3.beginLoadTask(task, ulr3) == false )
{
while( task.threadTaskCount != 0 )
{
try
{
LoadMgr3.nextTask(t, task, ulr3);
}
catch(InterruptedException e)
{
// Abort the load or retry?
break;
}
}
}
}
finally
{
// Unregister as the UCL owner to reschedule any remaining load tasks
if( loadLock.holds() == 1 )
LoadMgr3.endLoadTask(task);
// Notify any threads waiting to use this UCL
this.release();
this.notifyAll();
loadClassDepth --;
}
if( task.loadedClass == null )
{
if( task.loadException instanceof ClassNotFoundException )
throw (ClassNotFoundException) task.loadException;
else if( task.loadException instanceof NoClassDefFoundError )
throw (NoClassDefFoundError) task.loadException;
else if( task.loadException != null )
{
if( log.isTraceEnabled() )
log.trace("Unexpected error during load of:"+name, task.loadException);
String msg = "Unexpected error during load of: "+name
+ ", msg="+task.loadException.getMessage();
ClassNotFoundException cnfe = new ClassNotFoundException(msg, task.loadException);
throw cnfe;
}
// Assert that loadedClass is not null
else
throw new IllegalStateException("ClassLoadingTask.loadedTask is null, name: "+name);
}
return task.loadedClass;
}
/**
* Attempts to load the resource from its URL and if not found
* forwards to the request to {@link LoaderRepository}.
*/
public URL getResource(String name)
{
if (repository != null)
return repository.getResource(name, this);
return null;
}
/** Find all resource URLs for the given name. This overrides the
* URLClassLoader version to look for resources in the repository.
*
* @param name the name of the resource
* @return Enumeration Do not remove this method without discussing it on the dev list.
*
* @return Empty URL[]
*/
public URL[] getURLs()
{
return EMPTY_URL_ARRAY;
}
public Package getPackage(String name)
{
return super.getPackage(name);
}
public Package[] getPackages()
{
return super.getPackages();
}
// Object overrides ----------------------------------------------
/**
* This is here to document that this must delegate to the
* super implementation to perform identity based equality. Using
* URL based equality caused conflicts with the Class.forName(String,
* boolean, ClassLoader).
*/
public final boolean equals(Object other)
{
return super.equals(other);
}
/**
* This is here to document that this must delegate to the
* super implementation to perform identity based hashing. Using
* URL based hashing caused conflicts with the Class.forName(String,
* boolean, ClassLoader).
*/
public final int hashCode()
{
return super.hashCode();
}
/**
* Returns a string representation.
*/
public String toString()
{
return super.toString() + "{ url=" + getURL() + " }";
}
// Protected -----------------------------------------------------
/** Attempt to acquire the class loading lock. This lock must be acquired
* before a thread enters the class loading task loop in loadClass. This
* method maintains any interrupted state of the calling thread.
*@see #loadClass(String, boolean)
*/
protected boolean attempt(long waitMS)
{
boolean acquired = false;
boolean trace = log.isTraceEnabled();
// Save and clear the interrupted state of the incoming thread
boolean threadWasInterrupted = Thread.interrupted();
try
{
acquired = loadLock.attempt(waitMS);
}
catch(InterruptedException e)
{
}
finally
{
// Restore the interrupted state of the thread
if( threadWasInterrupted )
Thread.currentThread().interrupt();
}
if( trace )
log.trace("attempt("+loadLock.holds()+") was: "+acquired+" for :"+this);
return acquired;
}
/** Acquire the class loading lock. This lock must be acquired
* before a thread enters the class loading task loop in loadClass.
*@see #loadClass(String, boolean)
*/
protected void acquire()
{
// Save and clear the interrupted state of the incoming thread
boolean threadWasInterrupted = Thread.interrupted();
try
{
loadLock.acquire();
}
catch(InterruptedException e)
{
}
finally
{
// Restore the interrupted state of the thread
if( threadWasInterrupted )
Thread.currentThread().interrupt();
}
if( log.isTraceEnabled() )
log.trace("acquired("+loadLock.holds()+") for :"+this);
}
/** Release the class loading lock previous acquired through the acquire
* method.
*/
protected void release()
{
if( log.isTraceEnabled() )
log.trace("release("+loadLock.holds()+") for :"+this);
loadLock.release();
if( log.isTraceEnabled() )
log.trace("released, holds: "+loadLock.holds());
}
/** Obtain the bytecode for the indicated class from this class loaders
* classpath.
*
* @param classname
* @return the bytecode array if found
* @exception ClassNotFoundException - if the class resource could not
* be found
*/
protected byte[] loadByteCode(String classname)
throws ClassNotFoundException, IOException
{
byte[] bytecode = null;
URL classURL = getClassURL(classname);
// Load the class bytecode
InputStream is = null;
try
{
is = classURL.openStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] tmp = new byte[1024];
int read = 0;
while( (read = is.read(tmp)) > 0 )
{
baos.write(tmp, 0, read);
}
bytecode = baos.toByteArray();
}
finally
{
if( is != null )
is.close();
}
return bytecode;
}
/** Obtain the bytecode for the indicated class from this class loaders
* classpath.
*
* @param classURL
* @return the bytecode array if found
* @exception ClassNotFoundException - if the class resource could not
* be found
*/
protected byte[] loadByteCode(URL classURL)
throws ClassNotFoundException, IOException
{
byte[] bytecode = null;
// Load the class bytecode
InputStream is = null;
try
{
is = classURL.openStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] tmp = new byte[1024];
int read = 0;
while( (read = is.read(tmp)) > 0 )
{
baos.write(tmp, 0, read);
}
bytecode = baos.toByteArray();
}
finally
{
if( is != null )
is.close();
}
return bytecode;
}
/**
* Determine the protection domain. If we are a copy of the original
* deployment, use the original url as the codebase.
* @return the protection domain
* @todo certificates and principles?
*/
protected ProtectionDomain getProtectionDomain(URL codesourceUrl)
{
Certificate certs[] = null;
CodeSource cs = new CodeSource(codesourceUrl, certs);
PermissionCollection permissions = Policy.getPolicy().getPermissions(cs);
if (log.isTraceEnabled())
log.trace("getProtectionDomain, url=" + codesourceUrl +
" codeSource=" + cs + " permissions=" + permissions);
return new ProtectionDomain(cs, permissions);
}
// Package Private -----------------------------------------------
// Private -------------------------------------------------------
private URL getCodeSourceURL(String classname, URL classURL) throws java.net.MalformedURLException
{
String classRsrcName = classname.replace('.', '/') + ".class";
String urlAsString = classURL.toString();
int idx = urlAsString.indexOf(classRsrcName);
if (idx == -1) return classURL;
urlAsString = urlAsString.substring(0, idx);
return new URL(urlAsString);
}
private URL getClassURL(String classname) throws ClassNotFoundException
{
String classRsrcName = classname.replace('.', '/') + ".class";
URL classURL = this.getResourceLocally(classRsrcName);
if( classURL == null )
{
String msg = "Failed to find: "+classname+" as resource: "+classRsrcName;
throw new ClassNotFoundException(msg);
}
return classURL;
}
// Inner classes -------------------------------------------------
}