aboutsummaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authoracolyer <acolyer>2004-04-02 12:03:40 +0000
committeracolyer <acolyer>2004-04-02 12:03:40 +0000
commit33d8ee9eededcd1219a6cbd1d063af005d40a3f7 (patch)
treed30f882cbab26f54b62dc1cddfab666d97d6bd3d /weaver
parentfc1c15110e8a9cfafabad0dcc4c10445725c9fb2 (diff)
downloadaspectj-33d8ee9eededcd1219a6cbd1d063af005d40a3f7.tar.gz
aspectj-33d8ee9eededcd1219a6cbd1d063af005d40a3f7.zip
fix for Bugzilla Bug 31460
Weaving class loader
Diffstat (limited to 'weaver')
-rw-r--r--weaver/src/org/aspectj/weaver/ExtensibleURLClassLoader.java87
-rw-r--r--weaver/src/org/aspectj/weaver/WeavingURLClassLoader.java123
-rw-r--r--weaver/src/org/aspectj/weaver/tools/GeneratedClassHandler.java29
-rw-r--r--weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java332
-rw-r--r--weaver/src/org/aspectj/weaver/tools/WeavingClassLoader.java31
-rw-r--r--weaver/src/org/aspectj/weaver/tools/package.html7
-rw-r--r--weaver/testdata/dummyAspect.jarbin613 -> 819 bytes
-rw-r--r--weaver/testdata/ltw-acaspects.jarbin0 -> 2412 bytes
-rw-r--r--weaver/testdata/ltw-aspects.jarbin0 -> 1474 bytes
-rw-r--r--weaver/testdata/ltw-classes.jarbin0 -> 1410 bytes
-rw-r--r--weaver/testdata/ltw-itdaspects.jarbin0 -> 3214 bytes
-rw-r--r--weaver/testdata/ltw-peraspects.jarbin0 -> 1874 bytes
-rw-r--r--weaver/testdata/ltw-woven.jarbin0 -> 2653 bytes
-rw-r--r--weaver/testdata/megatrace.jarbin3777 -> 5285 bytes
-rw-r--r--weaver/testdata/megatrace0easy.jarbin3039 -> 3256 bytes
-rw-r--r--weaver/testdata/megatrace0hard.jarbin2940 -> 3152 bytes
-rw-r--r--weaver/testdata/megatraceNoweave.jarbin2832 -> 3043 bytes
-rw-r--r--weaver/testdata/tracing.jarbin2406 -> 2616 bytes
-rw-r--r--weaver/testsrc/BcweaverModuleTests.java2
-rw-r--r--weaver/testsrc/org/aspectj/weaver/BcweaverTests.java4
-rw-r--r--weaver/testsrc/org/aspectj/weaver/WeavingURLClassLoaderTest.java301
21 files changed, 914 insertions, 2 deletions
diff --git a/weaver/src/org/aspectj/weaver/ExtensibleURLClassLoader.java b/weaver/src/org/aspectj/weaver/ExtensibleURLClassLoader.java
new file mode 100644
index 000000000..1117c6b96
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/ExtensibleURLClassLoader.java
@@ -0,0 +1,87 @@
+/* *******************************************************************
+ * 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;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.CodeSource;
+
+import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.bcel.ClassPathManager;
+import org.aspectj.weaver.tools.*;
+
+public abstract class ExtensibleURLClassLoader extends URLClassLoader {
+
+ private ClassPathManager classPath;
+
+ public ExtensibleURLClassLoader (URL[] urls, ClassLoader parent) {
+ super(urls,parent);
+
+// System.err.println("? ExtensibleURLClassLoader.<init>() path=" + WeavingAdaptor.makeClasspath(urls));
+ classPath = new ClassPathManager(FileUtil.makeClasspath(urls),null);
+ }
+
+ protected void addURL(URL url) {
+ classPath.addPath(url.getPath(),null);
+ }
+
+ protected Class findClass(String name) throws ClassNotFoundException {
+// System.err.println("? ExtensibleURLClassLoader.findClass(" + name + ")");
+ try {
+ byte[] bytes = getBytes(name);
+ if (bytes != null) {
+ return defineClass(name,bytes);
+ }
+ else {
+ throw new ClassNotFoundException(name);
+ }
+ }
+ catch (IOException ex) {
+ throw new ClassNotFoundException(name);
+ }
+ }
+
+ protected Class defineClass(String name, byte[] b, CodeSource cs) throws IOException {
+// System.err.println("? ExtensibleURLClassLoader.defineClass(" + name + ",[" + b.length + "])");
+ return defineClass(name, b, 0, b.length, cs);
+ }
+
+ protected byte[] getBytes (String name) throws IOException {
+ byte[] b = null;
+ ClassPathManager.ClassFile classFile = classPath.find(TypeX.forName(name));
+ if (classFile != null) {
+ b = FileUtil.readAsByteArray(classFile.getInputStream());
+ }
+ return b;
+ }
+
+ private Class defineClass(String name, byte[] bytes /*ClassPathManager.ClassFile classFile*/) throws IOException {
+ String packageName = getPackageName(name);
+ if (packageName != null) {
+ Package pakkage = getPackage(packageName);
+ if (pakkage == null) {
+ definePackage(packageName,null,null,null,null,null,null,null);
+ }
+ }
+
+ return defineClass(name, bytes, null);
+ }
+
+ private String getPackageName (String className) {
+ int offset = className.lastIndexOf('.');
+ return (offset == -1)? null : className.substring(0,offset);
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/WeavingURLClassLoader.java b/weaver/src/org/aspectj/weaver/WeavingURLClassLoader.java
new file mode 100644
index 000000000..c01f18812
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/WeavingURLClassLoader.java
@@ -0,0 +1,123 @@
+/* *******************************************************************
+ * 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;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.net.URLStreamHandlerFactory;
+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.util.UtilClassLoader;
+import org.aspectj.weaver.tools.*;
+
+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 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>(" + parent + ")");
+ }
+
+ public WeavingURLClassLoader (URL[] classURLs, URL[] aspectURLs, ClassLoader parent) {
+ super(classURLs,parent);
+// System.err.println("? WeavingURLClassLoader.<init>()");
+ this.aspectURLs = aspectURLs;
+ 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 + "])");
+ 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);
+ }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/tools/GeneratedClassHandler.java b/weaver/src/org/aspectj/weaver/tools/GeneratedClassHandler.java
new file mode 100644
index 000000000..0a782452c
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/tools/GeneratedClassHandler.java
@@ -0,0 +1,29 @@
+/* *******************************************************************
+ * 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.tools;
+
+/**
+ * Interface implemented by weaving class loaders to allow classes generated by
+ * the weaving process to be defined.
+ */
+public interface GeneratedClassHandler {
+
+ /**
+ * Accept class generated by WeavingAdaptor. The class loader should store
+ * the class definition in its local cache until called upon to load it.
+ * @param name class name
+ * @param bytes class definition
+ */
+ public void acceptClass (String name, byte[] bytes);
+
+}
diff --git a/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java b/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java
new file mode 100644
index 000000000..a7cd1ed74
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java
@@ -0,0 +1,332 @@
+/* *******************************************************************
+ * 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.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.aspectj.bridge.AbortException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.MessageHandler;
+import org.aspectj.bridge.IMessage.Kind;
+import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.IClassFileProvider;
+import org.aspectj.weaver.IWeaveRequestor;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.bcel.BcelObjectType;
+import org.aspectj.weaver.bcel.BcelWeaver;
+import org.aspectj.weaver.bcel.BcelWorld;
+import org.aspectj.weaver.bcel.LazyClassGen;
+import org.aspectj.weaver.bcel.UnwovenClassFile;
+
+/**
+ * This adaptor allows the AspectJ compiler to be embedded in an existing
+ * system to facilitate load-time weaving. It provides an interface for a
+ * weaving class loader to provide a classpath to be woven by a set of
+ * aspects. A callback is supplied to allow a class loader to define classes
+ * generated by the compiler during the weaving process.
+ * <p>
+ * A weaving class loader should create a <code>WeavingAdaptor</code> before
+ * any classes are defined, typically during construction. The set of aspects
+ * passed to the adaptor is fixed for the lifetime of the adaptor although the
+ * classpath can be augmented. A system property can be set to allow verbose
+ * weaving messages to be written to the console.
+ *
+ */
+public class WeavingAdaptor {
+
+ /**
+ * System property used to turn on verbose weaving messages
+ */
+ public static final String WEAVING_ADAPTOR_VERBOSE = "aj.weaving.verbose";
+
+ private boolean enabled = true;
+ private boolean verbose = getVerbose();
+ private BcelWorld bcelWorld = null;
+ private BcelWeaver weaver = null;
+ private IMessageHandler messageHandler = null;
+ private GeneratedClassHandler generatedClassHandler;
+ private Map generatedClasses = new HashMap(); /* String -> UnwovenClassFile */
+
+ /**
+ * Construct a WeavingAdaptor with a reference to a weaving class loader. The
+ * adaptor will automatically search the class loader hierarchy to resolve
+ * classes. The adaptor will also search the hierarchy for WeavingClassLoader
+ * instances to determine the set of aspects to be used ofr weaving.
+ * @param loader instance of <code>ClassLoader</code>
+ */
+ public WeavingAdaptor (WeavingClassLoader loader) {
+// System.err.println("? WeavingAdaptor.<init>(" + loader +"," + aspectURLs.length + ")");
+ generatedClassHandler = loader;
+ init(getFullClassPath((ClassLoader)loader),getFullAspectPath((ClassLoader)loader/*,aspectURLs*/));
+ }
+
+ /**
+ * Construct a WeavingAdator with a reference to a
+ * <code>GeneratedClassHandler</code>, a full search path for resolving
+ * classes and a complete set of aspects. The search path must include
+ * classes loaded by the class loader constructing the WeavingAdaptor and
+ * all its parents in the hierarchy.
+ * @param handler <code>GeneratedClassHandler</code>
+ * @param classURLs the URLs from which to resolve classes
+ * @param aspectURLs the aspects used to weave classes defined by this class loader
+ */
+ public WeavingAdaptor (GeneratedClassHandler handler, URL[] classURLs, URL[] aspectURLs) {
+// System.err.println("? WeavingAdaptor.<init>()");
+ generatedClassHandler = handler;
+ init(FileUtil.makeClasspath(classURLs),FileUtil.makeClasspath(aspectURLs));
+ }
+
+ private List getFullClassPath (ClassLoader loader) {
+ List list = new LinkedList();
+ for (; loader != null; loader = loader.getParent()) {
+ if (loader instanceof URLClassLoader) {
+ URL[] urls = ((URLClassLoader)loader).getURLs();
+ list.addAll(0,FileUtil.makeClasspath(urls));
+ }
+ else {
+ if (verbose) System.err.println("WeavingAdaptor: Warning - could not determine classpath for " + loader);
+ }
+ }
+
+ list.addAll(0,makeClasspath(System.getProperty("sun.boot.class.path")));
+
+ return list;
+ }
+
+ private List getFullAspectPath (ClassLoader loader) {
+ List list = new LinkedList();
+ for (; loader != null; loader = loader.getParent()) {
+ if (loader instanceof WeavingClassLoader) {
+ URL[] urls = ((WeavingClassLoader)loader).getAspectURLs();
+ list.addAll(0,FileUtil.makeClasspath(urls));
+ }
+ }
+
+ return list;
+ }
+
+ private static boolean getVerbose () {
+ return Boolean.getBoolean(WEAVING_ADAPTOR_VERBOSE);
+ }
+
+ private void init(List classPath, List aspectPath) {
+ if (verbose) System.out.println("WeavingAdaptor: classPath='" + classPath + "'");
+
+ // make sure the weaver can find all types...
+ messageHandler = new MessageHandler();
+ bcelWorld = new BcelWorld(classPath,messageHandler,null);
+ bcelWorld.setXnoInline(false);
+ bcelWorld.getLint().loadDefaultProperties();
+
+ weaver = new BcelWeaver(bcelWorld);
+ registerAspectLibraries(aspectPath);
+ }
+
+ /**
+ * Appends URL to path used by the WeavingAdptor to resolve classes
+ * @param url to be appended to search path
+ */
+ public void addURL(URL url) {
+ try {
+ weaver.addLibraryJarFile(new File(url.getPath()));
+ }
+ catch (IOException ex) {
+ }
+ }
+
+ /**
+ * Weave a class using aspects previously supplied to the adaptor.
+ * @param name the name of the class
+ * @param bytes the class bytes
+ * @return the woven bytes
+ * @exception IOException weave failed
+ */
+ public byte[] weaveClass (String name, byte[] bytes) throws IOException {
+ if (shouldWeave(name)) {
+ bytes = getWovenBytes(name, bytes);
+ }
+ return bytes;
+ }
+
+ private boolean shouldWeave (String name) {
+ name = name.replace('/','.');
+ boolean b = (enabled && !generatedClasses.containsKey(name) && shouldWeaveName(name) && shouldWeaveAspect(name));
+ if (verbose) System.out.println("WeavingAdaptor: shouldWeave('" + name + "') " + b);
+ return b;
+ }
+
+ private boolean shouldWeaveName (String name) {
+ return !((name.startsWith("org.apache.bcel.") || name.startsWith("org.aspectj.") || name.startsWith("java.") || name.startsWith("javax.")));
+ }
+
+ private boolean shouldWeaveAspect (String name) {
+ ResolvedTypeX type = bcelWorld.resolve(name);
+ return (type == null || !type.isAspect());
+ }
+
+ /**
+ * Weave a set of bytes defining a class.
+ * @param name the name of the class being woven
+ * @param bytes the bytes that define the class
+ * @return byte[] the woven bytes for the class
+ * @throws IOException
+ * @throws FileNotFoundException
+ */
+ private byte[] getWovenBytes(String name, byte[] bytes) throws IOException {
+ WeavingClassFileProvider wcp = new WeavingClassFileProvider(name,bytes);
+ weaver.weave(wcp);
+ return wcp.getBytes();
+
+// UnwovenClassFile unwoven = new UnwovenClassFile(name,bytes);
+//
+// // weave
+// BcelObjectType bcelType = bcelWorld.addSourceObjectType(unwoven.getJavaClass());
+// LazyClassGen woven = weaver.weaveWithoutDump(unwoven,bcelType);
+//
+// byte[] wovenBytes = woven != null ? woven.getJavaClass(bcelWorld).getBytes() : bytes;
+// return wovenBytes;
+ }
+
+ private void registerAspectLibraries(List aspectPath) {
+// System.err.println("? WeavingAdaptor.registerAspectLibraries(" + aspectPath + ")");
+ for (Iterator i = aspectPath.iterator(); i.hasNext();) {
+ String lib = (String)i.next();
+ File libFile = new File(lib);
+ if (libFile.isFile() && lib.endsWith(".jar")) {
+ try {
+ if (verbose) System.out.println("WeavingAdaptor: adding aspect '" + lib + "' to weaver");
+ addAspectLibrary(new File(lib));
+ } catch (IOException ioEx) {
+ if (verbose) System.err.println(
+ "WeavingAdaptor: Warning - could not load aspect path entry "
+ + lib + " : " + ioEx);
+ }
+ } else {
+ if (verbose) System.err.println(
+ "WeavingAdaptor: Warning - ignoring aspect path entry: " + lib);
+ }
+ }
+
+ weaver.prepareForWeave();
+ }
+
+ /*
+ * Register an aspect library with this classloader for use during
+ * weaving. This class loader will also return (unmodified) any of the
+ * classes in the library in response to a <code>findClass()</code> request.
+ * The library is not required to be on the weavingClasspath given when this
+ * classloader was constructed.
+ * @param aspectLibraryJarFile a jar file representing an aspect library
+ * @throws IOException
+ */
+ private void addAspectLibrary(File aspectLibraryJarFile) throws IOException {
+ weaver.addLibraryJarFile(aspectLibraryJarFile);
+// weaver.prepareForWeave();
+ }
+
+ private static List makeClasspath(String cp) {
+ List ret = new ArrayList();
+ if (cp != null) {
+ StringTokenizer tok = new StringTokenizer(cp,File.pathSeparator);
+ while (tok.hasMoreTokens()) {
+ ret.add(tok.nextToken());
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Processes messages arising from weaver operations.
+ * Tell weaver to abort on any non-informational error.
+ */
+ private class MessageHandler implements IMessageHandler {
+
+ public boolean handleMessage(IMessage message) throws AbortException {
+ if (!isIgnoring(message.getKind())) {
+ if (verbose) System.err.println(message.getMessage());
+ throw new AbortException(message);
+ }
+ return true;
+ }
+
+ public boolean isIgnoring(Kind kind) {
+ return ((kind == IMessage.INFO) || (kind == IMessage.DEBUG));
+ }
+ }
+
+ private class WeavingClassFileProvider implements IClassFileProvider {
+
+ private List unwovenClasses = new ArrayList(); /* List<UnovenClassFile> */
+ private UnwovenClassFile wovenClass;
+
+ public WeavingClassFileProvider (String name, byte[] bytes) {
+ UnwovenClassFile unwoven = new UnwovenClassFile(name,bytes);
+ unwovenClasses.add(unwoven);
+ bcelWorld.addSourceObjectType(unwoven.getJavaClass());
+ }
+
+ public byte[] getBytes () {
+ return wovenClass.getBytes();
+ }
+
+ public Iterator getClassFileIterator() {
+ return unwovenClasses.iterator();
+ }
+
+ public IWeaveRequestor getRequestor() {
+ return new IWeaveRequestor() {
+
+ public void acceptResult(UnwovenClassFile result) {
+ if (wovenClass == null) {
+ wovenClass = result;
+ }
+
+ /* Classes generated by weaver e.g. around closure advice */
+ else {
+ String className = result.getClassName();
+ generatedClasses.put(className,result);
+ generatedClassHandler.acceptClass(className,result.getBytes());
+ }
+ }
+
+ public void processingReweavableState() { }
+
+ public void addingTypeMungers() {}
+
+ public void weavingAspects() {}
+
+ public void weavingClasses() {}
+
+ public void weaveCompleted() {}
+ };
+ }
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/tools/WeavingClassLoader.java b/weaver/src/org/aspectj/weaver/tools/WeavingClassLoader.java
new file mode 100644
index 000000000..045cd6c8b
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/tools/WeavingClassLoader.java
@@ -0,0 +1,31 @@
+/* *******************************************************************
+ * 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.tools;
+
+import java.net.URL;
+
+/**
+ * An interface for weaving class loaders to provide callbacks for a
+ * WeavingAdaptor.
+ */
+public interface WeavingClassLoader extends GeneratedClassHandler {
+
+ /**
+ * Returns the aspects to be used by a WeavingAdaptor to weave classes
+ * defined by the class loader.
+ * @return the aspects used for weaving classes.
+ */
+ public URL[] getAspectURLs ();
+
+}
diff --git a/weaver/src/org/aspectj/weaver/tools/package.html b/weaver/src/org/aspectj/weaver/tools/package.html
new file mode 100644
index 000000000..b996ebb69
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/tools/package.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+Provides a set of interfaces to allow a class loader to perform
+load-time weaving.
+
+</body>
+</html>
diff --git a/weaver/testdata/dummyAspect.jar b/weaver/testdata/dummyAspect.jar
index 321efc4e4..6bc31ed85 100644
--- a/weaver/testdata/dummyAspect.jar
+++ b/weaver/testdata/dummyAspect.jar
Binary files differ
diff --git a/weaver/testdata/ltw-acaspects.jar b/weaver/testdata/ltw-acaspects.jar
new file mode 100644
index 000000000..c49320821
--- /dev/null
+++ b/weaver/testdata/ltw-acaspects.jar
Binary files differ
diff --git a/weaver/testdata/ltw-aspects.jar b/weaver/testdata/ltw-aspects.jar
new file mode 100644
index 000000000..428c2b156
--- /dev/null
+++ b/weaver/testdata/ltw-aspects.jar
Binary files differ
diff --git a/weaver/testdata/ltw-classes.jar b/weaver/testdata/ltw-classes.jar
new file mode 100644
index 000000000..f74d613b7
--- /dev/null
+++ b/weaver/testdata/ltw-classes.jar
Binary files differ
diff --git a/weaver/testdata/ltw-itdaspects.jar b/weaver/testdata/ltw-itdaspects.jar
new file mode 100644
index 000000000..0870a4a73
--- /dev/null
+++ b/weaver/testdata/ltw-itdaspects.jar
Binary files differ
diff --git a/weaver/testdata/ltw-peraspects.jar b/weaver/testdata/ltw-peraspects.jar
new file mode 100644
index 000000000..071d2bbfa
--- /dev/null
+++ b/weaver/testdata/ltw-peraspects.jar
Binary files differ
diff --git a/weaver/testdata/ltw-woven.jar b/weaver/testdata/ltw-woven.jar
new file mode 100644
index 000000000..b0b6368f4
--- /dev/null
+++ b/weaver/testdata/ltw-woven.jar
Binary files differ
diff --git a/weaver/testdata/megatrace.jar b/weaver/testdata/megatrace.jar
index 31c8d0dc2..aff5ffe96 100644
--- a/weaver/testdata/megatrace.jar
+++ b/weaver/testdata/megatrace.jar
Binary files differ
diff --git a/weaver/testdata/megatrace0easy.jar b/weaver/testdata/megatrace0easy.jar
index a7499e84d..97c8081aa 100644
--- a/weaver/testdata/megatrace0easy.jar
+++ b/weaver/testdata/megatrace0easy.jar
Binary files differ
diff --git a/weaver/testdata/megatrace0hard.jar b/weaver/testdata/megatrace0hard.jar
index 114217106..583926b3f 100644
--- a/weaver/testdata/megatrace0hard.jar
+++ b/weaver/testdata/megatrace0hard.jar
Binary files differ
diff --git a/weaver/testdata/megatraceNoweave.jar b/weaver/testdata/megatraceNoweave.jar
index f51ebb94f..8d454e6a2 100644
--- a/weaver/testdata/megatraceNoweave.jar
+++ b/weaver/testdata/megatraceNoweave.jar
Binary files differ
diff --git a/weaver/testdata/tracing.jar b/weaver/testdata/tracing.jar
index 93f0d578a..2c8cafbcc 100644
--- a/weaver/testdata/tracing.jar
+++ b/weaver/testdata/tracing.jar
Binary files differ
diff --git a/weaver/testsrc/BcweaverModuleTests.java b/weaver/testsrc/BcweaverModuleTests.java
index 82ea4979f..4e8ff7a79 100644
--- a/weaver/testsrc/BcweaverModuleTests.java
+++ b/weaver/testsrc/BcweaverModuleTests.java
@@ -21,7 +21,7 @@ public class BcweaverModuleTests extends TestCase {
TestSuite suite = new TestSuite(BcweaverModuleTests.class.getName());
suite.addTest(org.aspectj.weaver.bcel.BcelTests.suite());
suite.addTest(org.aspectj.weaver.BcweaverTests.suite());
- suite.addTest(org.aspectj.weaver.patterns.PatternsTests.suite());
+ suite.addTest(org.aspectj.weaver.patterns.PatternsTests.suite());
suite.addTestSuite(LocaleTest.class);
return suite;
}
diff --git a/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java b/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java
index 35e7c5473..e2e58a36c 100644
--- a/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java
+++ b/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java
@@ -16,6 +16,7 @@ package org.aspectj.weaver;
import java.io.File;
import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.tools.*;
import junit.framework.*;
@@ -49,7 +50,8 @@ public class BcweaverTests extends TestCase {
//suite.addTestSuite(AbstractWorldTestCase.class);
//$JUnit-BEGIN$
suite.addTestSuite(MemberTestCase.class);
- suite.addTestSuite(TypeXTestCase.class);
+ suite.addTestSuite(TypeXTestCase.class);
+ suite.addTestSuite(WeavingURLClassLoaderTest.class);
//$JUnit-END$
return suite;
}
diff --git a/weaver/testsrc/org/aspectj/weaver/WeavingURLClassLoaderTest.java b/weaver/testsrc/org/aspectj/weaver/WeavingURLClassLoaderTest.java
new file mode 100644
index 000000000..41f9b56ab
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/WeavingURLClassLoaderTest.java
@@ -0,0 +1,301 @@
+/* *******************************************************************
+ * 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 initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.aspectj.bridge.AbortException;
+import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.tools.WeavingAdaptor;
+
+/**
+ * @author websterm
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class WeavingURLClassLoaderTest extends TestCase {
+
+ private final static String CLASSES_JAR = BcweaverTests.TESTDATA_PATH + "/ltw-classes.jar";
+ private final static String WOVEN_JAR = BcweaverTests.TESTDATA_PATH + "/ltw-woven.jar";
+ private final static String JUNK_JAR = BcweaverTests.TESTDATA_PATH + "/ltw-junk.jar";
+ private final static String ADVICE_ASPECTS = BcweaverTests.TESTDATA_PATH + "/ltw-aspects.jar";
+ private final static String AROUNDCLOSURE_ASPECTS = BcweaverTests.TESTDATA_PATH + "/ltw-acaspects.jar";
+ private final static String ITD_ASPECTS = BcweaverTests.TESTDATA_PATH + "/ltw-itdaspects.jar";
+ private final static String PER_ASPECTS = BcweaverTests.TESTDATA_PATH + "/ltw-peraspects.jar";
+
+
+ public WeavingURLClassLoaderTest(String name) {
+ super(name);
+ System.setProperty(WeavingAdaptor.WEAVING_ADAPTOR_VERBOSE,"true");
+ }
+
+ public void testLoadClass () {
+ System.setProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,"");
+ System.setProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,CLASSES_JAR);
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] {});
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testLoadWovenClass () {
+ System.setProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,"");
+ System.setProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,WOVEN_JAR);
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] { "LTWAspect" });
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testWeaveWovenClass () {
+ System.setProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,ADVICE_ASPECTS);
+ System.setProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,ADVICE_ASPECTS + File.pathSeparator + WOVEN_JAR);
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ fail("Expecting org.aspectj.bridge.AbortException");
+ }
+ catch (Exception ex) {
+ assertTrue("Expecting org.aspectj.bridge.AbortException caught " + ex,(ex instanceof AbortException));
+ }
+ }
+
+ public void testWeavingURLClassLoader () {
+ URL classes = FileUtil.getFileURL(new File(CLASSES_JAR));
+ URL aspects = FileUtil.getFileURL(new File(ADVICE_ASPECTS));
+ URL[] classURLs = new URL[] { aspects, classes };
+ URL[] aspectURLs = new URL[] { aspects };
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(classURLs,aspectURLs,getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] { "LTWAspect" });
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testWeaveAdvice () {
+ System.setProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,ADVICE_ASPECTS);
+ System.setProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,ADVICE_ASPECTS + File.pathSeparator + CLASSES_JAR);
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] { "LTWAspect" });
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testWeaveAroundClosure () {
+ System.setProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,AROUNDCLOSURE_ASPECTS);
+ System.setProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,AROUNDCLOSURE_ASPECTS + File.pathSeparator + CLASSES_JAR);
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] { "LTWAroundClosure" });
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testWeavingITD () {
+ URL classes = FileUtil.getFileURL(new File(CLASSES_JAR));
+ URL aspects = FileUtil.getFileURL(new File(ITD_ASPECTS));
+ URL[] classURLs = new URL[] { aspects, classes };
+ URL[] aspectURLs = new URL[] { aspects };
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(classURLs,aspectURLs,getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ /* Uncomment when bug #55341 fixed */
+// invokeMain(clazz,new String[] { "LTWInterfaceITD", "LTWFieldITD", "LTWMethodITD" });
+ invokeMain(clazz,new String[] { "LTWInterfaceITD", "LTWFieldITD" });
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testWeavingPer () {
+ URL classes = FileUtil.getFileURL(new File(CLASSES_JAR));
+ URL aspects = FileUtil.getFileURL(new File(PER_ASPECTS));
+ URL[] classURLs = new URL[] { aspects, classes };
+ URL[] aspectURLs = new URL[] { aspects };
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(classURLs,aspectURLs,getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] { "LTWPerthis" });
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testWeavingAspects () {
+ URL classes = FileUtil.getFileURL(new File(CLASSES_JAR));
+ URL aspects1 = FileUtil.getFileURL(new File(ADVICE_ASPECTS));
+ URL aspects2 = FileUtil.getFileURL(new File(AROUNDCLOSURE_ASPECTS));
+ URL aspects3 = FileUtil.getFileURL(new File(ITD_ASPECTS));
+ URL aspects4 = FileUtil.getFileURL(new File(PER_ASPECTS));
+ URL[] classURLs = new URL[] { aspects1, aspects2, aspects3, aspects4, classes };
+ URL[] aspectURLs = new URL[] { aspects1, aspects2, aspects3, aspects4 };
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(classURLs,aspectURLs,getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ /* Uncomment when bug #55341 fixed */
+// invokeMain(clazz,new String[] { "LTWAspect", "LTWAroundClosure", "LTWPerthis", "LTWInterfaceITD", "LTWFieldITD", "LTWMethodITD", "LTWPerthis"});
+ invokeMain(clazz,new String[] { "LTWAspect", "LTWAroundClosure", "LTWPerthis", "LTWInterfaceITD", "LTWFieldITD", "LTWPerthis"});
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testJunkJar () {
+ File junkJar = new File(JUNK_JAR);
+ assertFalse(junkJar + " should not exist",junkJar.exists());
+
+ URL classes = FileUtil.getFileURL(junkJar);
+ URL[] classURLs = new URL[] { classes };
+ URL[] aspectURLs = new URL[] { };
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(classURLs,aspectURLs,getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ fail("Expecting java.lang.ClassNotFoundException");
+ }
+ catch (Exception ex) {
+ assertTrue("Expecting java.lang.ClassNotFoundException caught " + ex,(ex instanceof ClassNotFoundException));
+ }
+ }
+
+ public void testAddURL () {
+ URL classes = FileUtil.getFileURL(new File(CLASSES_JAR));
+ URL aspects = FileUtil.getFileURL(new File(ADVICE_ASPECTS));
+ URL[] classURLs = new URL[] { aspects };
+ URL[] aspectURLs = new URL[] { aspects };
+
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(classURLs,aspectURLs,getClass().getClassLoader());
+ loader.addURL(classes);
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] { "LTWAspect" });
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public void testParentChild() {
+ URL classes = FileUtil.getFileURL(new File(CLASSES_JAR));
+ URL aspects = FileUtil.getFileURL(new File(ADVICE_ASPECTS));
+
+ URL[] classURLs = new URL[] { aspects };
+ URL[] aspectURLs = new URL[] { aspects };
+ WeavingURLClassLoader parent = new WeavingURLClassLoader(classURLs,aspectURLs,getClass().getClassLoader());
+
+ classURLs = new URL[] { classes };
+ aspectURLs = new URL[] { };
+ WeavingURLClassLoader child = new WeavingURLClassLoader(classURLs,aspectURLs,parent);
+
+ try {
+ Class clazz = child.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] { "LTWAspect" });
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ /*
+ * Aspects on ASPECTPATH but missing from CLASSPATH
+ */
+ public void testIncompletePath () {
+ System.setProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,ADVICE_ASPECTS);
+ System.setProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,CLASSES_JAR);
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("LTWHelloWorld");
+ invokeMain(clazz,new String[] { "LTWAspect" });
+ fail("Expecting java.lang.NoClassDefFoundError");
+ }
+ catch (Exception ex) {
+ }
+ }
+
+ /*
+ * Ensure package object is correct
+ */
+ public void testPackage () {
+ System.setProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,"");
+ System.setProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,CLASSES_JAR);
+ WeavingURLClassLoader loader = new WeavingURLClassLoader(getClass().getClassLoader());
+
+ try {
+ Class clazz = loader.loadClass("ltw.LTWPackageTest");
+ invokeMain(clazz,new String[] { });
+ Package pakkage = clazz.getPackage();
+ assertTrue("Expected 'ltw' got " + pakkage,(pakkage != null));
+ }
+ catch (Exception ex) {
+ fail(ex.toString());
+ }
+ }
+
+ public static void invokeMain (Class clazz, String[] args)
+ {
+ Class[] paramTypes = new Class[1];
+ paramTypes[0] = args.getClass();
+
+ try {
+ Method method = clazz.getDeclaredMethod("main",paramTypes);
+ Object[] params = new Object[1];
+ params[0] = args;
+ method.invoke(null,params);
+ }
+ catch (InvocationTargetException ex) {
+ throw new RuntimeException(ex.getTargetException().toString());
+ }
+ catch (Exception ex) {
+ throw new RuntimeException(ex.toString());
+ }
+ }
+
+}