diff options
36 files changed, 1261 insertions, 6 deletions
diff --git a/docs/build.xml b/docs/build.xml index d0b8248d0..107da3834 100644 --- a/docs/build.xml +++ b/docs/build.xml @@ -166,14 +166,15 @@ </target> <target name="api" depends="init" - description="javadoc for AspectJ lang and lang.reflect"> + description="javadoc for AspectJ lang, lang.reflect and org.aspectj.weaver.tools"> <delete dir="${docs.dist.dir}/doc/api"/> <mkdir dir="${docs.dist.dir}/doc/api"/> - <javadoc sourcepath="${aspectj.modules.dir}/runtime/src" + <javadoc sourcepath="${aspectj.modules.dir}/runtime/src;${aspectj.modules.dir}/weaver/src" destdir="${docs.dist.dir}/doc/api" windowtitle="AspectJ(tm) runtime API" link="http://java.sun.com/j2se/1.4.2/docs/api" - packagenames="org.aspectj.lang,org.aspectj.lang.reflect" /> + classpath="${aspectj.modules.dir}/asm/bin;${aspectj.modules.dir}/bridge/bin;${aspectj.modules.dir}/util/bin;${aspectj.modules.dir}/lib/bcel/bcel.jar" + packagenames="org.aspectj.lang,org.aspectj.lang.reflect,org.aspectj.weaver.tools" /> <!-- note: link ineffective at avoiding see tag warning --> </target> diff --git a/docs/dist/doc/examples/build.xml b/docs/dist/doc/examples/build.xml index 8fd48dbc7..ba2931fba 100644 --- a/docs/dist/doc/examples/build.xml +++ b/docs/dist/doc/examples/build.xml @@ -394,4 +394,62 @@ </target> + <!-- ============================================================= --> + <!-- do tracing example with 1.2 load-time weaving --> + <!-- (and use fork/forkclasspath to avoid Eclipse 2.x bug) --> + <!-- ============================================================= --> + <target name="tracing-lt" depends="init" + description="tracing example with load-time aspect weaving"> + <antcall target="clean" /> + + <!-- build application classes --> + <iajc outjar="${jar.dir}/tracingApp.jar" + classpath="${aspectjrt.jar}" + fork="true" + forkclasspath="${aspectjtools.jar}" + verbose="off"> + <src path="${example.dir}"/> + <include name="tracing/*.java" /> + </iajc> + + <!-- Build a read-only tracing library --> + <iajc outjar="${jar.dir}/tracingLib.jar" + classpath="${aspectjrt.jar}:${jar.dir}/tracingApp.jar" + fork="true" + forkclasspath="${aspectjtools.jar}" + verbose="off"> + <src path="${example.dir}"/> + <include name="tracing/version2/Trace.java" /> + <include name="tracing/version2/TraceMyClasses.java" /> + </iajc> + + <!-- test standalone application by running without tracing --> + <echo message="---------- running without tracing - START"/> + <java classname="tracing.ExampleMain"> + <classpath> + <pathelement path="${aspectjrt.jar}"/> + <pathelement path="${jar.dir}/tracingApp.jar"/> + </classpath> + </java> + <echo message="---------- running without tracing - FINISH "/> + + <!-- run appliaction with LTW to add tracing --> + <echo message="---------- running with tracing - START"/> + <java classname="tracing.ExampleMain" + fork="true"> + <classpath> + <pathelement path="${aspectjrt.jar}"/> + <pathelement path="${aspectjtools.jar}"/> + <pathelement path="d:/eclipse_aspectj/workspace/weaver/bin"/> + </classpath> + <jvmarg line="-showversion"/> + <sysproperty key="java.system.class.loader" value="org.aspectj.weaver.WeavingURLClassLoader"/> + <sysproperty key="aj.weaving.verbose" value="True"/> + <sysproperty key="aj.class.path" path="${jar.dir}/tracingLib.jar:${jar.dir}/tracingApp.jar"/> + <sysproperty key="aj.aspect.path" path="${jar.dir}/tracingLib.jar"/> + </java> + <echo message="---------- running with tracing - FINISH"/> + + </target> + </project> diff --git a/docs/dist/doc/examples/ltw/README b/docs/dist/doc/examples/ltw/README new file mode 100644 index 000000000..bbeb56290 --- /dev/null +++ b/docs/dist/doc/examples/ltw/README @@ -0,0 +1,22 @@ +
+This directory contains a script "aj" to demonstrate load-time weaving. Java
+classes on the CLASSPATH are loaded and woven with aspects on the ASPECTPATH.
+This feature is only supported on JDK 1.4 and later.
+
+--To compile the tracing example--
+
+ ant -f ../build.xml tracing-lt
+
+--To run the example--
+
+ set CLASSPATH to include "../jars/tracingApp.jar"
+
+ aj tracing.ExampleMain
+
+--To run the example with tracing--
+
+ set ASPECTPATH=../jars/tracingLib.jar
+
+ aj tracing.ExampleMain
+
+
diff --git a/docs/dist/doc/examples/ltw/aj b/docs/dist/doc/examples/ltw/aj new file mode 100644 index 000000000..8e7a250bb --- /dev/null +++ b/docs/dist/doc/examples/ltw/aj @@ -0,0 +1,16 @@ +# *******************************************************************
+# 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
+# ******************************************************************/
+
+if [ "$ASPECTJ_HOME" = "" ] ; then ASPECTJ_HOME=../../../
+fi
+
+"$JAVA_HOME/bin/java" -classpath "$ASPECTJ_HOME/lib/aspectjtools.jar" "-Djava.system.class.loader=org.aspectj.weaver.WeavingURLClassLoader" "-Daj.class.path=$ASPECTPATH:$CLASSPATH" "-Daj.aspect.path=$ASPECTPATH" "$@"
diff --git a/docs/dist/doc/examples/ltw/aj.bat b/docs/dist/doc/examples/ltw/aj.bat new file mode 100644 index 000000000..c004598bb --- /dev/null +++ b/docs/dist/doc/examples/ltw/aj.bat @@ -0,0 +1,22 @@ +@echo off
+rem *******************************************************************
+rem Copyright (c) 2004 IBM Corporation
+rem All rights reserved.
+rem This program and the accompanying materials are made available
+rem under the terms of the Common Public License v1.0
+rem which accompanies this distribution and is available at
+rem http://www.eclipse.org/legal/cpl-v10.html
+rem
+rem Contributors:
+rem Matthew Webster initial implementation
+rem ******************************************************************/
+
+if "%ASPECTJ_HOME%" == "" set ASPECTJ_HOME=..\..\..\
+
+if exist "%JAVA_HOME%\bin\java.exe" goto haveJava
+if exist "%JAVA_HOME%\bin\java.bat" goto haveJava
+if exist "%JAVA_HOME%\bin\java" goto haveJava
+echo java does not exist as %JAVA_HOME%\bin\java
+echo please fix the JAVA_HOME environment variable
+:haveJava
+"%JAVA_HOME%\bin\java" -classpath "%ASPECTJ_HOME%\lib\aspectjtools.jar" "-Djava.system.class.loader=org.aspectj.weaver.WeavingURLClassLoader" "-Daj.class.path=%ASPECTPATH%;%CLASSPATH%" "-Daj.aspect.path=%ASPECTPATH%" %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/org.aspectj.ajdt.core/testdata/src1/LTWAroundClosure.aj b/org.aspectj.ajdt.core/testdata/src1/LTWAroundClosure.aj new file mode 100644 index 000000000..80af46fd7 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/LTWAroundClosure.aj @@ -0,0 +1,20 @@ +import java.util.List;
+
+public aspect LTWAroundClosure {
+
+ pointcut println (List list) :
+ execution(* println()) && this(list);
+
+ void around (final List list) : println (list) {
+
+ Runnable runnable = new Runnable() {
+ public void run () {
+ System.err.println("LTWAroundClosure.run(" + thisJoinPointStaticPart + ")");
+ proceed(list);
+ }
+ };
+ runnable.run();
+ list.add("LTWAroundClosure");
+ }
+
+}
diff --git a/org.aspectj.ajdt.core/testdata/src1/LTWAspect.aj b/org.aspectj.ajdt.core/testdata/src1/LTWAspect.aj new file mode 100644 index 000000000..1721b4ef7 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/LTWAspect.aj @@ -0,0 +1,12 @@ +import java.util.List;
+
+public privileged aspect LTWAspect {
+
+ pointcut method (List list) :
+ execution(* LTWHelloWorld.*(..)) && this(list);
+
+ before (List list) : method (list) {
+ System.err.println("LTWAspect.method(" + thisJoinPointStaticPart + ")");
+ list.add("LTWAspect");
+ }
+}
diff --git a/org.aspectj.ajdt.core/testdata/src1/LTWFieldITD.aj b/org.aspectj.ajdt.core/testdata/src1/LTWFieldITD.aj new file mode 100644 index 000000000..87f441544 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/LTWFieldITD.aj @@ -0,0 +1,16 @@ +import java.util.List;
+
+public aspect LTWFieldITD {
+
+ private int LTWHelloWorld.intField = 999;
+
+ pointcut init (LTWHelloWorld hw) :
+ execution(LTWHelloWorld.new()) && this(hw);
+
+ after (LTWHelloWorld hw) : init (hw) {
+ System.err.println("LTWFieldITD.init(" + thisJoinPointStaticPart + ")");
+ hw.intField = 999999;
+ hw.add(getClass().getName());
+ }
+
+}
diff --git a/org.aspectj.ajdt.core/testdata/src1/LTWHelloWorld.java b/org.aspectj.ajdt.core/testdata/src1/LTWHelloWorld.java new file mode 100644 index 000000000..ec533506d --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/LTWHelloWorld.java @@ -0,0 +1,24 @@ +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Properties; + +public class LTWHelloWorld extends ArrayList { + + private String message = "Hello World!"; + + public void println () { + System.out.println(message); + } + + public static void main(String[] args) { + LTWHelloWorld hw = new LTWHelloWorld(); + hw.println(); + for (int i = 0; i < args.length; i++) { + String jp = args[i]; + if (!hw.contains(jp)) { + throw new RuntimeException(jp + " missing"); + } + } + } + +} diff --git a/org.aspectj.ajdt.core/testdata/src1/LTWInterfaceITD.aj b/org.aspectj.ajdt.core/testdata/src1/LTWInterfaceITD.aj new file mode 100644 index 000000000..e7fa6a46a --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/LTWInterfaceITD.aj @@ -0,0 +1,18 @@ +import java.util.List;
+
+public privileged aspect LTWInterfaceITD {
+
+ declare parents : LTWHelloWorld implements Runnable;
+
+ public void LTWHelloWorld.run () {
+ add("LTWInterfaceITD");
+ }
+
+ pointcut init (LTWHelloWorld hw) :
+ execution(LTWHelloWorld.new()) && this(hw);
+
+ after (LTWHelloWorld hw) : init (hw) {
+ System.err.println("LTWInterfaceITD.init(" + thisJoinPointStaticPart + ")");
+ hw.run();
+ }
+}
diff --git a/org.aspectj.ajdt.core/testdata/src1/LTWMethodITD.aj b/org.aspectj.ajdt.core/testdata/src1/LTWMethodITD.aj new file mode 100644 index 000000000..35049f04f --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/LTWMethodITD.aj @@ -0,0 +1,22 @@ +import java.util.List;
+
+public privileged aspect LTWMethodITD {
+
+ public String LTWHelloWorld.getMessage () {
+ return message;
+ }
+
+ public void LTWHelloWorld.setMessage (String newMessage) {
+ message = newMessage;
+ }
+
+ pointcut init (LTWHelloWorld hw) :
+ execution(LTWHelloWorld.new()) && this(hw);
+
+ after (LTWHelloWorld hw) : init (hw) {
+ System.err.println("LTWMethodITD.init(" + thisJoinPointStaticPart + ")");
+ hw.getMessage();
+ hw.setMessage("Hello LTWMethodITD");
+ hw.add(getClass().getName());
+ }
+}
\ No newline at end of file diff --git a/org.aspectj.ajdt.core/testdata/src1/LTWPerthis.aj b/org.aspectj.ajdt.core/testdata/src1/LTWPerthis.aj new file mode 100644 index 000000000..955d72096 --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/LTWPerthis.aj @@ -0,0 +1,13 @@ +import java.util.List;
+
+public aspect LTWPerthis perthis(this(LTWHelloWorld)) {
+
+ pointcut println (List list) :
+ execution(* println()) && this(list);
+
+ before (List list) : println (list) {
+ System.err.println("LTWPerthis.println(" + thisJoinPointStaticPart + ")");
+ list.add(getClass().getName());
+ }
+
+}
diff --git a/org.aspectj.ajdt.core/testdata/src1/ltw/LTWPackageTest.java b/org.aspectj.ajdt.core/testdata/src1/ltw/LTWPackageTest.java new file mode 100644 index 000000000..e749db20c --- /dev/null +++ b/org.aspectj.ajdt.core/testdata/src1/ltw/LTWPackageTest.java @@ -0,0 +1,8 @@ +package ltw; + +public class LTWPackageTest { + + public static void main(String[] args) { + } + +} diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java index 25e621ca1..b6dfb5184 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/ajdt/internal/compiler/batch/BcweaverJarMaker.java @@ -36,6 +36,8 @@ public class BcweaverJarMaker { makeTestJars(); + + makeURLWeavingClassLoaderJars(); } public static void makeJar0() throws IOException { @@ -179,5 +181,85 @@ public class BcweaverJarMaker { CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); } + public static void makeURLWeavingClassLoaderJars() throws IOException { + List args = new ArrayList(); + + /* + * Vanilla classes + */ + args.add("-classpath"); + args.add("../lib/test/aspectjrt.jar;../lib/test/testing-client.jar" + + File.pathSeparator + System.getProperty("aspectjrt.path")); + args.add("-outjar"); + args.add("../weaver/testdata/ltw-classes.jar"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWHelloWorld.java"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/ltw/LTWPackageTest.java"); + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + + /* + * Woven classes + */ + args = new ArrayList(); + args.add("-classpath"); + args.add("../lib/test/aspectjrt.jar;../lib/test/testing-client.jar;../weaver/testdata/ltw-classes.jar" + + File.pathSeparator + System.getProperty("aspectjrt.path")); + args.add("-outjar"); + args.add("../weaver/testdata/ltw-woven.jar"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWHelloWorld.java"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWAspect.aj"); + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + + /* + * Advice + */ + args = new ArrayList(); + args.add("-classpath"); + args.add("../lib/test/aspectjrt.jar;../lib/test/testing-client.jar;../weaver/testdata/ltw-classes.jar" + + File.pathSeparator + System.getProperty("aspectjrt.path")); + args.add("-outjar"); + args.add("../weaver/testdata/ltw-aspects.jar"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWAspect.aj"); + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + + /* + * Around closure advice + */ + args = new ArrayList(); + args.add("-classpath"); + args.add("../lib/test/aspectjrt.jar;../lib/test/testing-client.jar;../weaver/testdata/ltw-classes.jar" + + File.pathSeparator + System.getProperty("aspectjrt.path")); + args.add("-outjar"); + args.add("../weaver/testdata/ltw-acaspects.jar"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWAroundClosure.aj"); + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + + /* + * ITD + */ + args = new ArrayList(); + args.add("-Xlint:ignore"); + args.add("-classpath"); + args.add("../lib/test/aspectjrt.jar;../lib/test/testing-client.jar;../weaver/testdata/ltw-classes.jar" + + File.pathSeparator + System.getProperty("aspectjrt.path")); + args.add("-outjar"); + args.add("../weaver/testdata/ltw-itdaspects.jar"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWInterfaceITD.aj"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWFieldITD.aj"); + /* Uncomment when bug #55341 fixed */ +// args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWMethodITD.aj"); + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + + /* + * perXXX() + */ + args = new ArrayList(); + args.add("-classpath"); + args.add("../lib/test/aspectjrt.jar;../lib/test/testing-client.jar;../weaver/testdata/ltw-classes.jar" + + File.pathSeparator + System.getProperty("aspectjrt.path")); + args.add("-outjar"); + args.add("../weaver/testdata/ltw-peraspects.jar"); + args.add(AjdtAjcTests.TESTDATA_PATH + "/src1/LTWPerthis.aj"); + CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS); + } } diff --git a/util/src/org/aspectj/util/FileUtil.java b/util/src/org/aspectj/util/FileUtil.java index 34bf103a9..ccf54831f 100644 --- a/util/src/org/aspectj/util/FileUtil.java +++ b/util/src/org/aspectj/util/FileUtil.java @@ -1262,7 +1262,16 @@ public class FileUtil { } private FileUtil() { throw new Error("utility class"); } - + + public static List makeClasspath(URL[] urls) { + List ret = new LinkedList(); + if (urls != null) { + for (int i = 0; i < urls.length; i++) { + ret.add(urls[i].getPath()); + } + } + return ret; + } /** * A pipe when run reads from an input stream to an output stream, 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()); + } + } + +} |