package org.aspectj.weaver.loadtime;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.aspectj.bridge.AbortException;
import org.aspectj.weaver.bcel.ExtensibleURLClassLoader;
import org.aspectj.weaver.tools.Trace;
import org.aspectj.weaver.tools.TraceFactory;
import org.aspectj.weaver.tools.WeavingAdaptor;
import org.aspectj.weaver.tools.WeavingClassLoader;
public class WeavingURLClassLoader extends ExtensibleURLClassLoader implements WeavingClassLoader {
public static final String WEAVING_CLASS_PATH = "aj.class.path";
public static final String WEAVING_ASPECT_PATH = "aj.aspect.path";
private URL[] aspectURLs;
private WeavingAdaptor adaptor;
private boolean initializingAdaptor;
private Map generatedClasses = new HashMap();
private static Trace trace = TraceFactory.getTraceFactory().getTrace(WeavingURLClassLoader.class);
public WeavingURLClassLoader(ClassLoader parent) {
this(getURLs(getClassPath()), getURLs(getAspectPath()), parent);
}
public WeavingURLClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
if (trace.isTraceEnabled())
trace.enter("<init>", this, new Object[] { urls, parent });
if (trace.isTraceEnabled())
trace.exit("<init>");
}
public WeavingURLClassLoader(URL[] classURLs, URL[] aspectURLs, ClassLoader parent) {
super(classURLs, parent);
this.aspectURLs = aspectURLs;
if (this.aspectURLs.length > 0 || getParent() instanceof WeavingClassLoader) {
try {
adaptor = new WeavingAdaptor(this);
} catch (ExceptionInInitializerError ex) {
ex.printStackTrace(System.out);
throw ex;
}
}
}
private static String getAspectPath() {
return System.getProperty(WEAVING_ASPECT_PATH, "");
}
private static String getClassPath() {
return System.getProperty(WEAVING_CLASS_PATH, "");
}
private static URL[] getURLs(String path) {
List urlList = new ArrayList();
for (StringTokenizer t = new StringTokenizer(path, File.pathSeparator); t.hasMoreTokens();) {
File f = new File(t.nextToken().trim());
try {
if (f.exists()) {
URL url = f.toURL();
if (url != null)
urlList.add(url);
}
} catch (MalformedURLException e) {
}
}
URL[] urls = new URL[urlList.size()];
urlList.toArray(urls);
return urls;
}
protected void addURL(URL url) {
if (adaptor == null) {
createAdaptor();
}
adaptor.addURL(url);
super.addURL(url);
}
protected Class defineClass(String name, byte[] b, CodeSource cs) throws IOException {
if (trace.isTraceEnabled())
trace.enter("defineClass", this, new Object[] { name, b, cs });
byte orig[] = b;
if (!initializingAdaptor) {
if (adaptor == null && !initializingAdaptor) {
createAdaptor();
}
try {
b = adaptor.weaveClass(name, b, false);
} catch (AbortException ex) {
trace.error("defineClass", ex);
throw ex;
} catch (Throwable th) {
trace.error("defineClass", th);
}
}
Class clazz;
try {
clazz= super.defineClass(name, b, cs);
} catch (Throwable th) {
trace.error("Weaving class problem. Original class has been returned. The error was caused because of: " + th, th);
clazz= super.defineClass(name, orig, cs);
}
if (trace.isTraceEnabled())
trace.exit("defineClass", clazz);
return clazz;
}
private void createAdaptor() {
DefaultWeavingContext weavingContext = new DefaultWeavingContext(this) {
public String getClassLoaderName() {
ClassLoader loader = getClassLoader();
return loader.getClass().getName();
}
};
ClassLoaderWeavingAdaptor clwAdaptor = new ClassLoaderWeavingAdaptor();
initializingAdaptor = true;
clwAdaptor.initialize(this, weavingContext);
initializingAdaptor = false;
adaptor = clwAdaptor;
}
protected byte[] getBytes(String name) throws IOException {
byte[] bytes = super.getBytes(name);
if (bytes == null) {
return (byte[]) generatedClasses.remove(name);
}
return bytes;
}
public URL[] getAspectURLs() {
return aspectURLs;
}
public void acceptClass (String name, byte[] classBytes, byte[] weavedBytes) {
generatedClasses.put(name, weavedBytes);
}
}