diff options
author | acolyer <acolyer> | 2004-04-02 12:03:40 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2004-04-02 12:03:40 +0000 |
commit | 33d8ee9eededcd1219a6cbd1d063af005d40a3f7 (patch) | |
tree | d30f882cbab26f54b62dc1cddfab666d97d6bd3d /weaver | |
parent | fc1c15110e8a9cfafabad0dcc4c10445725c9fb2 (diff) | |
download | aspectj-33d8ee9eededcd1219a6cbd1d063af005d40a3f7.tar.gz aspectj-33d8ee9eededcd1219a6cbd1d063af005d40a3f7.zip |
fix for Bugzilla Bug 31460
Weaving class loader
Diffstat (limited to 'weaver')
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 Binary files differindex 321efc4e4..6bc31ed85 100644 --- a/weaver/testdata/dummyAspect.jar +++ b/weaver/testdata/dummyAspect.jar diff --git a/weaver/testdata/ltw-acaspects.jar b/weaver/testdata/ltw-acaspects.jar Binary files differnew file mode 100644 index 000000000..c49320821 --- /dev/null +++ b/weaver/testdata/ltw-acaspects.jar diff --git a/weaver/testdata/ltw-aspects.jar b/weaver/testdata/ltw-aspects.jar Binary files differnew file mode 100644 index 000000000..428c2b156 --- /dev/null +++ b/weaver/testdata/ltw-aspects.jar diff --git a/weaver/testdata/ltw-classes.jar b/weaver/testdata/ltw-classes.jar Binary files differnew file mode 100644 index 000000000..f74d613b7 --- /dev/null +++ b/weaver/testdata/ltw-classes.jar diff --git a/weaver/testdata/ltw-itdaspects.jar b/weaver/testdata/ltw-itdaspects.jar Binary files differnew file mode 100644 index 000000000..0870a4a73 --- /dev/null +++ b/weaver/testdata/ltw-itdaspects.jar diff --git a/weaver/testdata/ltw-peraspects.jar b/weaver/testdata/ltw-peraspects.jar Binary files differnew file mode 100644 index 000000000..071d2bbfa --- /dev/null +++ b/weaver/testdata/ltw-peraspects.jar diff --git a/weaver/testdata/ltw-woven.jar b/weaver/testdata/ltw-woven.jar Binary files differnew file mode 100644 index 000000000..b0b6368f4 --- /dev/null +++ b/weaver/testdata/ltw-woven.jar diff --git a/weaver/testdata/megatrace.jar b/weaver/testdata/megatrace.jar Binary files differindex 31c8d0dc2..aff5ffe96 100644 --- a/weaver/testdata/megatrace.jar +++ b/weaver/testdata/megatrace.jar diff --git a/weaver/testdata/megatrace0easy.jar b/weaver/testdata/megatrace0easy.jar Binary files differindex a7499e84d..97c8081aa 100644 --- a/weaver/testdata/megatrace0easy.jar +++ b/weaver/testdata/megatrace0easy.jar diff --git a/weaver/testdata/megatrace0hard.jar b/weaver/testdata/megatrace0hard.jar Binary files differindex 114217106..583926b3f 100644 --- a/weaver/testdata/megatrace0hard.jar +++ b/weaver/testdata/megatrace0hard.jar diff --git a/weaver/testdata/megatraceNoweave.jar b/weaver/testdata/megatraceNoweave.jar Binary files differindex f51ebb94f..8d454e6a2 100644 --- a/weaver/testdata/megatraceNoweave.jar +++ b/weaver/testdata/megatraceNoweave.jar diff --git a/weaver/testdata/tracing.jar b/weaver/testdata/tracing.jar Binary files differindex 93f0d578a..2c8cafbcc 100644 --- a/weaver/testdata/tracing.jar +++ b/weaver/testdata/tracing.jar 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()); + } + } + +} |