package it.unina.seclab.jafimon;
import it.unina.seclab.jafimon.util.SystemEnvironmentVariables;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.loader.WebappClassLoader;
import org.xml.sax.SAXException;
public class TomcatWebappClassLoader extends WebappClassLoader{
private ClassPool thePool = null;
private CustomTranslator theTranslator = null;
private SAXParser parser = null;
private ConfigurationSAXParser ch = null;
private boolean updated = false;
private boolean initialized = false;
private void initPool() {
if (thePool == null) {
thePool = new ClassPool();
updated = false;
}
}
private void initTranslator() throws CannotCompileException {
if (initialized) return;
log.info("Initializing Translator");
theTranslator = new CustomTranslator();
log.info("Initializing Translator - 2");
String cfgFile = "NYS";
try {
cfgFile = SystemEnvironmentVariables.getEnvironmentVariable("CATALINA_HOME");
if (cfgFile == null)
cfgFile = "webapps/axis/META-INF/custom";
else
cfgFile += "/webapps/axis/META-INF/custom";
Vector v = new Vector();
listaFiles(cfgFile,".xml",v);
String[] s = new String[v.size()];
v.copyInto(s);
cfgFile = s[0];
log.info("Sto per caricare " + cfgFile);
} catch (IOException e1) {
log.error(e1.getLocalizedMessage());
e1.printStackTrace();
}
log.info("Initializing Translator - 3");
ch = new ConfigurationSAXParser(theTranslator,thePool);
log.info("Initializing Translator - 4");
try {
parser = SAXParserFactory.newInstance().newSAXParser();
log.info("Initializing Translator - 5");
parser.parse(cfgFile, ch);
log.info("Initializing Translator - 6");
} catch (IOException e) {
log.fatal("IO");
e.printStackTrace();
throw new CannotCompileException(cfgFile,e);
} catch (SAXException e) {
log.fatal("SAX");
e.printStackTrace();
throw new CannotCompileException(cfgFile,e);
} catch (ParserConfigurationException e) {
log.fatal("PCE");
e.printStackTrace();
throw new CannotCompileException(cfgFile,e);
} catch (FactoryConfigurationError e) {
log.fatal("FCE");
e.printStackTrace();
throw new CannotCompileException(cfgFile,e);
}
try {
theTranslator.start(thePool);
} catch (NotFoundException e) {
log.fatal("NFE");
e.printStackTrace();
throw new CannotCompileException(cfgFile,e);
}
initialized = true;
log.info("Translator initialized successfully");
}
private void updatePool() {
if (updated) return;
updated = true;
try {
for (int i = 0; i < repositories.length; i++) {
log.info("Appending \"" + repositories[i] + "\" to ClassPool");
thePool.appendClassPath(repositories[i]);
}
for (int i = 0; i < jarRealFiles.length; i++) {
log.info("Appending \"" + jarRealFiles[i].getCanonicalPath() + "\" to ClassPool");
thePool.appendClassPath(jarRealFiles[i].getCanonicalPath());
}
} catch (NotFoundException e) {
log.error("Unable to append to ClassPool: \"" + e.getLocalizedMessage() + "\"");
} catch (IOException e) {
log.error("Unable to append to ClassPool: \"" + e.getLocalizedMessage() + "\"");
}
thePool.appendSystemPath();
}
public TomcatWebappClassLoader() {
super();
log.info("Creato TomcatWebappClassLoader$C0");
}
public TomcatWebappClassLoader(ClassLoader parent) {
super(parent);
log.info("Creato TomcatWebappClassLoader$C1");
}
public Class findClass(String className) throws ClassNotFoundException {
try {
log.info("Looking for " + className + " in ClassPool");
CtClass ctc = thePool.get(className);
//
// Do the real instrumentation before delivering
// to the JVM
//
if (initialized) {
if (theTranslator.existConverterForClass(className)) {
log.info("Instrumenting " + className + " with Converter");
ctc.instrument(theTranslator.getConverterForClass(className));
}
if (theTranslator.existEditorForClass(className)) {
log.info("Instrumenting " + className + " with Editor");
ctc.instrument(theTranslator.getEditorForClass(className));
}
}
byte[] b = ctc.toBytecode();
Class c = defineClass(className, b, 0, b.length);
log.info("Class " + className + " found and loaded from ClassPool");
return c;
} catch (NotFoundException e) {
log.error("ClassNotFound in ClassPool: " + e.getLocalizedMessage());
return super.findClass(className);
} catch (IOException e) {
log.error("IOException in ClassPool: " + e.getLocalizedMessage());
throw new ClassNotFoundException(className,e);
} catch (CannotCompileException e) {
log.error("CannotCompileException in ClassPool: " + e.getLocalizedMessage());
throw new ClassNotFoundException(className,e);
}
}
public void start() throws LifecycleException {
super.start();
/*
* Non so quando e chi aggiunge i repositories. Quindi chiamo
* updatePool e lo eseguo alla prima invocazione di findClass.
* Sono ragionevolmente certo che a questo punto i repositories
* ci sono tutti, quindi li aggiungo al ClassPool e carico da l�.
*/
try {
initPool();
updatePool();
initTranslator();
} catch (CannotCompileException e) {
throw new LifecycleException("Translator error", e);
}
}
/**
* Scorre il percorso indicato da basePath alla ricerca di files, restituendone
* la lista.
*
* @param basePath il percorso dal quale avviare la ricerca
* @param v il vettore che conterra' la lista dei file
*/
private void listaFiles(String basePath, String filter, Vector v) {
//logger.trace("basePath = \"" + basePath + "\"");
//logger.trace("filter = \"" + filter + "\"");
String[] basePathList = new File(basePath).list();
//logger.trace("basePathList = \"" + basePathList + "\"");
for (int i = 0; i < basePathList.length; i++) {
File f = new File(basePath + File.separator + basePathList[i]);
if (f.isFile()) {
if (f.getName().endsWith(filter)) {
String n = new String(basePath + File.separator + basePathList[i]);
v.addElement(n);
}
}
else {
listaFiles(basePath + File.separator + basePathList[i],filter,v);
}
}
}
}