package hep.io.root.core;
import hep.io.root.RootClassNotFound;
import hep.io.root.RootFileReader;
import hep.io.root.test.JasminVisitor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.bcel.classfile.JavaClass;
/**
* A classloader which can dynamically create classes based on the streamer info
* objects in a root file.
* @author tonyj
*/
public class RootClassLoader extends ClassLoader
{
private final static boolean debugRoot = System.getProperty("debugRoot") != null;
private Map<Class,GenericRootClass> classMap = new HashMap<Class,GenericRootClass>();
private Map<String,ClassBuilder> stemMap = new HashMap<String,ClassBuilder>();
private RootFileReader rfr;
private final static Object bcelLock = new Object();
private NameMangler nameMangler = NameMangler.instance();
RootClassLoader(RootFileReader rfr)
{
super(RootClassLoader.class.getClassLoader());
this.rfr = rfr;
register(new InterfaceBuilder());
register(new ProxyBuilder());
register(new Proxy2Builder());
register(new ClonesBuilder());
register(new CloneBuilder());
register(new Clone2Builder());
}
@Override
public Class findClass(String name) throws ClassNotFoundException
{
try
{
if (debugRoot)
System.out.println("RootClassLoader: loading " + name);
String stem = nameMangler.getStemForJavaClass(name);
String rootClassName = nameMangler.getClassForJavaClass(name);
ClassBuilder builder = stemMap.get(stem);
GenericRootClass gc = (GenericRootClass) rfr.getFactory().create(rootClassName);
JavaClass jc;
// BCEL is not thread safe, so class building must be synchronized
synchronized (bcelLock)
{
jc = builder.build(gc);
}
if (debugRoot)
{
try
{
FileOutputStream out = new FileOutputStream(name + ".j");
new JasminVisitor(jc, out).disassemble();
out.close();
}
catch (IOException x) {}
}
byte[] data = jc.getBytes();
Class result = defineClass(name, data, 0, data.length);
classMap.put(result, gc);
return result;
}
catch (RootClassNotFound x)
{
throw new ClassNotFoundException(name);
}
}
public Class loadSpecial(ClassBuilder builder, String name, GenericRootClass rc)
{
if (debugRoot)
System.out.println("RootClassLoader: loading special " + name);
JavaClass jc = builder.build(rc);
if (debugRoot)
{
try
{
FileOutputStream out = new FileOutputStream(name + ".j");
new JasminVisitor(jc, out).disassemble();
out.close();
}
catch (IOException x) {}
}
byte[] data = jc.getBytes();
Class result = defineClass(name, data, 0, data.length);
classMap.put(result, rc);
return result;
}
GenericRootClass getRootClass(Class klass)
{
return classMap.get(klass);
}
private void register(ClassBuilder builder)
{
stemMap.put(builder.getStem(), builder);
}
}