package org.jboss.seam.wicket.ioc;
import static org.jboss.seam.deployment.ClassDescriptor.filenameToClassname;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.Loader;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
public class WicketClassLoader extends Loader
{
private static LogProvider log = Logging.getLogProvider(WicketClassLoader.class);
private Set<String> classes;
private File wicketComponentDirectory;
private ClassPool classPool;
private ClassLoader parentLoader;
private JavassistInstrumentor instrumentor;
public WicketClassLoader(ClassLoader parent, ClassPool classPool, File wicketComponentDirectory)
{
super(parent, classPool);
this.classes = new HashSet<String>();
this.wicketComponentDirectory = wicketComponentDirectory;
this.classPool = classPool;
this.parentLoader = parent;
this.instrumentor = new JavassistInstrumentor(classPool);
}
public WicketClassLoader instrument() throws NotFoundException, CannotCompileException, ClassNotFoundException
{
classPool.insertClassPath(wicketComponentDirectory.getAbsolutePath());
classPool.insertClassPath(new LoaderClassPath(parentLoader));
// Scan for classes
if (wicketComponentDirectory.exists())
{
handleDirectory(wicketComponentDirectory, null, classes);
instrumentor.instrumentClassSet(classes,null);
}
// Ensure classes' static initializers have run, to register the classes
// with WicketComponent
for (String className : classes)
{
loadClass(className);
}
return this;
}
/**
* Recursively collect all class names for class files found in this directory.
* @param file which directory
* @param path parent path
* @param collectedClasses where to store the classes
* @throws NotFoundException
* @throws CannotCompileException
*/
private void handleDirectory(File file, String path, Set<String> collectedClasses) throws NotFoundException, CannotCompileException
{
log.trace("directory: " + file);
for (File child : file.listFiles())
{
String newPath = path == null ? child.getName() : path + '/' + child.getName();
if (child.isDirectory())
{
handleDirectory(child, newPath, collectedClasses);
}
else
{
if (newPath.endsWith(".class"))
{
collectedClasses.add(filenameToClassname(newPath));
}
}
}
}
@Override
protected Class loadClassByDelegation(String name) throws ClassNotFoundException
{
Class clazz = super.loadClassByDelegation(name);
if (clazz == null)
{
if (!classes.contains(name))
{
clazz = delegateToParent(name);
}
}
return clazz;
}
@Override
public URL getResource(String name)
{
File file = new File(wicketComponentDirectory, name);
if (file.exists())
{
try
{
return file.toURL();
}
catch (MalformedURLException e)
{
throw new RuntimeException(e);
}
}
else
{
if (getParent() != null)
{
return getParent().getResource(name);
}
else
{
return null;
}
}
}
}