/* *******************************************************************
* Copyright (c) 2004 IBM Corporation
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Matthew Webster, Adrian Colyer,
* Martin Lippert initial implementation
* ******************************************************************/
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.weaver.ExtensibleURLClassLoader;
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(); /* String -> byte[] */
/*
* This constructor is needed when using "-Djava.system.class.loader".
*/
public WeavingURLClassLoader (ClassLoader parent) {
this(getURLs(getClassPath()),getURLs(getAspectPath()),parent);
// System.err.println("? WeavingURLClassLoader.<init>(" + m_parent + ")");
}
public WeavingURLClassLoader (URL[] urls, ClassLoader parent) {
super(urls,parent);
// System.out.println("WeavingURLClassLoader.WeavingURLClassLoader()");
}
public WeavingURLClassLoader (URL[] classURLs, URL[] aspectURLs, ClassLoader parent) {
super(classURLs,parent);
// System.err.println("? WeavingURLClassLoader.<init>() classURLs=" + classURLs.length + ", aspectURLs=" + aspectURLs.length);
this.aspectURLs = aspectURLs;
/* If either we nor our m_parent is using an ASPECT_PATH use a new-style
* adaptor
*/
if (this.aspectURLs.length > 0 || parent instanceof WeavingClassLoader) {
adaptor = new WeavingAdaptor(this);
}
}
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) {
adaptor.addURL(url);
super.addURL(url);
}
/**
* Override to weave class using WeavingAdaptor
*/
protected Class defineClass(String name, byte[] b, CodeSource cs) throws IOException {
// System.err.println("? WeavingURLClassLoader.defineClass(" + name + ", [" + b.length + "])");
/* Avoid recursion during adaptor initialization */
if (!initializingAdaptor) {
/* Need to defer creation because of possible recursion during constructor execution */
if (adaptor == null && !initializingAdaptor) {
DefaultWeavingContext weavingContext = new DefaultWeavingContext (this) {
/* Ensures consistent LTW messages for testing */
public String getClassLoaderName() {
return loader.getClass().getName();
}
};
ClassLoaderWeavingAdaptor clwAdaptor = new ClassLoaderWeavingAdaptor(this,weavingContext);
initializingAdaptor = true;
clwAdaptor.initialize(this,weavingContext);
initializingAdaptor = false;
adaptor = clwAdaptor;
}
b = adaptor.weaveClass(name,b);
}
return super.defineClass(name, b, cs);
}
/**
* Override to find classes generated by WeavingAdaptor
*/
protected byte[] getBytes (String name) throws IOException {
byte[] bytes = super.getBytes(name);
if (bytes == null) {
// return adaptor.findClass(name);
return (byte[])generatedClasses.remove(name);
}
return bytes;
}
/**
* Implement method from WeavingClassLoader
*/
public URL[] getAspectURLs() {
return aspectURLs;
}
public void acceptClass (String name, byte[] bytes) {
generatedClasses.put(name,bytes);
}
// private interface ClassPreProcessorAdaptor extends ClassPreProcessor {
// public void addURL(URL url);
// }
//
// private class WeavingAdaptorPreProcessor implements ClassPreProcessorAdaptor {
//
// private WeavingAdaptor adaptor;
//
// public WeavingAdaptorPreProcessor (WeavingClassLoader wcl) {
// adaptor = new WeavingAdaptor(wcl);
// }
//
// public void initialize() {
// }
//
// public byte[] preProcess(String className, byte[] bytes, ClassLoader classLoader) {
// return adaptor.weaveClass(className,bytes);
// }
//
// public void addURL(URL url) {
//
// }
// }
}