private IWeavingContext weavingContext;
public ClassLoaderWeavingAdaptor(final ClassLoader loader, IWeavingContext wContext) {
- super(null);
+ this.weavingContext = wContext;
}
void initialize(final ClassLoader loader, IWeavingContext wContext) {
*/
private void registerDefinitions(final BcelWeaver weaver, final ClassLoader loader) {
try {
- MessageUtil.info(messageHandler, "register classloader " + ((loader!=null)?loader.getClass().getName()+"@"+loader.hashCode():"null"));
+ MessageUtil.info(messageHandler, "register classloader " + getClassLoaderName(loader));
//TODO av underoptimized: we will parse each XML once per CL that see it
List definitions = new ArrayList();
registerDump(weaver, loader, definitions);
} else {
enabled = false;// will allow very fast skip in shouldWeave()
+ info("no configuration found. Disabling weaver for class loader " + getClassLoaderName(loader));
}
} catch (Exception e) {
weaver.getWorld().getMessageHandler().handleMessage(
}
}
+ private String getClassLoaderName (ClassLoader loader) {
+ return weavingContext.getClassLoaderName();
+ }
+
/**
* Configure the weaver according to the option directives
* TODO av - don't know if it is that good to reuse, since we only allow a small subset of options in LTW
allOptions.append(definition.getWeaverOptions()).append(' ');
}
- Options.WeaverOption weaverOption = Options.parse(allOptions.toString(), loader);
+ Options.WeaverOption weaverOption = Options.parse(allOptions.toString(), loader, messageHandler);
// configure the weaver and world
// AV - code duplicates AspectJBuilder.initWorldAndWeaver()
for (Iterator aspects = definition.getAspectClassNames().iterator(); aspects.hasNext();) {
String aspectClassName = (String) aspects.next();
if (acceptAspect(aspectClassName)) {
+ info("register aspect " + aspectClassName);
ResolvedType aspect = weaver.addLibraryAspect(aspectClassName);
- if (aspect.isAbstract()) {
- // this is a warning
- weaver.getWorld().getMessageHandler().handleMessage(
- new Message("Abstract aspect registered in aop.xml, use a <concrete-aspect> element instead", IMessage.WARNING, null, null)
- );
- }
+
//generate key for SC
if(namespace==null){
namespace=new StringBuffer(aspectClassName);
if (acceptAspect(concreteAspect.name)) {
ConcreteAspectCodeGen gen = new ConcreteAspectCodeGen(concreteAspect, weaver.getWorld());
if (!gen.validate()) {
- weaver.getWorld().getMessageHandler().handleMessage(
- new Message("Concrete-aspect '"+concreteAspect.name+"' could not be registered", IMessage.ERROR, null, null)
- );
+ error("Concrete-aspect '"+concreteAspect.name+"' could not be registered");
break;
}
this.generatedClassHandler.acceptClass(
*/
public class DefaultWeavingContext implements IWeavingContext {
- private ClassLoader loader;
+ protected ClassLoader loader;
public DefaultWeavingContext(){
loader = getClass().getClassLoader();
return null;
}
+ /**
+ * @return classname@hashcode
+ */
+ public String getClassLoaderName() {
+ return ((loader!=null)?loader.getClass().getName()+"@"+loader.hashCode():"null");
+ }
+
}
* @return
*/
public String getBundleIdFromURL(URL url);
+
+ /**
+ * In an environment with multiple class loaders allows each to be
+ * identified using something safer and than toString
+ * @return name of the associated class loader
+ */
+ public String getClassLoaderName ();
}
private static final String OPTIONVALUED_Xlint = "-Xlint:";
- public static WeaverOption parse(String options, ClassLoader laoder) {
+ public static WeaverOption parse(String options, ClassLoader laoder, IMessageHandler imh) {
+ WeaverOption weaverOption = new WeaverOption(imh);
+
if (LangUtil.isEmpty(options)) {
- return new WeaverOption();
+ return weaverOption;
}
// the first option wins
List flags = LangUtil.anySplit(options, " ");
Collections.reverse(flags);
- WeaverOption weaverOption = new WeaverOption();
-
// do a first round on the message handler since it will report the options themselves
for (Iterator iterator = flags.iterator(); iterator.hasNext();) {
String arg = (String) iterator.next();
String lint;
String lintFile;
- public WeaverOption() {
- messageHandler = new DefaultMessageHandler();//default
+ public WeaverOption(IMessageHandler imh) {
+// messageHandler = new DefaultMessageHandler();//default
+ this.messageHandler = imh;
}
}
}
public static final String WEAVING_ASPECT_PATH = "aj.aspect.path";
private URL[] aspectURLs;
- private WeavingAdaptor adaptor;
+ private WeavingAdaptor adaptor;
+ private boolean initializingAdaptor;
private Map generatedClasses = new HashMap(); /* String -> byte[] */
/*
*/
protected Class defineClass(String name, byte[] b, CodeSource cs) throws IOException {
// System.err.println("? WeavingURLClassLoader.defineClass(" + name + ", [" + b.length + "])");
-
- /* Need to defer creation because of possible recursion during constructor execution */
- if (adaptor == null) {
- ClassLoaderWeavingAdaptor clwAdaptor = new ClassLoaderWeavingAdaptor(this,null);
- clwAdaptor.initialize(this,null);
- adaptor = clwAdaptor;
+
+ /* Avoid recursion during adaptor initialization */
+ if (!initializingAdaptor) {
+
+ /* Need to defer creation because of possible recursion during constructor execution */
+ if (adaptor == null && !initializingAdaptor) {
+ DefaultWeavingContext weavingContext = new DefaultWeavingContext (this) {
+
+ /* Ensures consistent LTW messages for testing */
+ public String getClassLoaderName() {
+ return loader.getClass().getName();
+ }
+
+ };
+
+ ClassLoaderWeavingAdaptor clwAdaptor = new ClassLoaderWeavingAdaptor(this,weavingContext);
+ initializingAdaptor = true;
+ clwAdaptor.initialize(this,weavingContext);
+ initializingAdaptor = false;
+ adaptor = clwAdaptor;
+ }
+
+ b = adaptor.weaveClass(name,b);
}
-
- b = adaptor.weaveClass(name,b);
return super.defineClass(name, b, cs);
}
}
}
+ /*
+ * We won't get an exception because the aspect path is empty and there is
+ * no aop.xml file so the weaver will be disabled and no reweaving will
+ * take place
+ */
public void testLoadWovenClass () {
setSystemProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,"");
setSystemProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,WOVEN_JAR);
}
}
+ /*
+ * We get an exception because the class was not built reweavable
+ */
public void testWeaveWovenClass () {
setSystemProperty(WeavingURLClassLoader.WEAVING_ASPECT_PATH,ADVICE_ASPECTS);
setSystemProperty(WeavingURLClassLoader.WEAVING_CLASS_PATH,ADVICE_ASPECTS + File.pathSeparator + WOVEN_JAR);
fail("Expecting java.lang.NoClassDefFoundError");
}
catch (Exception ex) {
+ assertTrue("Expecting java.lang.NoClassDefFoundError but caught " + ex,ex.getMessage().contains("java.lang.NoClassDefFoundError"));
}
}
method.invoke(null,params);
}
catch (InvocationTargetException ex) {
- throw new RuntimeException(ex.getTargetException().toString());
+ Throwable targetException = ex.getTargetException();
+ if (targetException instanceof RuntimeException) throw (RuntimeException)ex.getTargetException();
+ else throw new RuntimeException(ex.getTargetException().toString());
}
catch (Exception ex) {
throw new RuntimeException(ex.toString());
URLClassLoader cLoader;
if (useLTW) {
- cLoader = new WeavingURLClassLoader(urls,null);
+ ClassLoader parent = getClass().getClassLoader();
+ cLoader = new WeavingURLClassLoader(urls,parent);
}
else {
cLoader = new URLClassLoader(urls,null);
} catch (Exception ex) {
fail ("Unable to prepare org.aspectj.testing.Tester for test run: " + ex);
}
- Class toRun = cLoader.loadClass(className);
- Method mainMethod = toRun.getMethod("main",new Class[] {String[].class});
System.setOut(new PrintStream(baosOut));
System.setErr(new PrintStream(baosErr));
+ Class toRun = cLoader.loadClass(className);
+ Method mainMethod = toRun.getMethod("main",new Class[] {String[].class});
mainMethod.invoke(null,new Object[] {args});
lastRunResult = new RunResult(command.toString(),new String(baosOut.toByteArray()),new String(baosErr.toByteArray()));
} catch(ClassNotFoundException cnf) {
useLtw = true;
}
catch (IOException ex) {
- ex.printStackTrace();
+ AjcTestCase.fail(ex.toString());
}
}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Matthew Webster initial implementation
+ *******************************************************************************/
+import java.lang.reflect.*;
+
+public abstract aspect AbstractAspect {
+
+ /*
+ * These should not take effect unless a concrete sub-aspect is defined
+ */
+ declare parents : TestITDMethod implements Runnable;
+
+ declare soft : InvocationTargetException : execution(public void TestITDMethod.*());
+
+ declare warning : execution(public void main(..)) :
+ "AbstractAspect_main";
+
+ /*
+ * This should always take effect
+ */
+ public void TestITDMethod.test () {
+ System.err.println("AbstractAspect_TestITDMethod.test");
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Matthew Webster initial implementation
+ *******************************************************************************/
+
+public abstract aspect AbstractSuperAspect {
+
+ protected abstract pointcut scope ();
+
+ before () : execution(void test1()) && scope() {
+ System.err.println("AbstractSuperAspect.before_" + thisJoinPoint.getSignature().getName());
+ }
+}
* Contributors:
* Matthew Webster initial implementation
*******************************************************************************/
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
public class Main {
System.out.println("Main.test2");
}
- public static void main (String[] args) {
+ public void invokeDeclaredMethods () throws Exception {
+ Method[] methods = getClass().getDeclaredMethods();
+ for (int i = 0; i < methods.length; i++) {
+ Method method = methods[i];
+ int modifiers = method.getModifiers();
+ if (!Modifier.isStatic(modifiers) && !method.getName().equals("invokeDeclaredMethods")) {
+ method.invoke(this,new Object[] {});
+ }
+ }
+ }
+
+ public static void main (String[] args) throws Exception {
System.out.println("Main.main");
new Main().test1();
new Main().test2();
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Matthew Webster initial implementation
+ *******************************************************************************/
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class TestITDMethod {
+
+ public void invokeDeclaredMethods (String[] names) throws Exception {
+ for (int i = 0; i < names.length; i++) {
+ Method method = getClass().getDeclaredMethod(names[i],new Class[] {});
+ method.invoke(this,new Object[] {});
+ }
+ }
+
+ public static void main (String[] args) throws Exception {
+ System.out.println("TestITDMethod.main");
+ new TestITDMethod().invokeDeclaredMethods(args);
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Matthew Webster initial implementation
+ *******************************************************************************/
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class TestMain {
+
+ public static void main (String[] args) throws Exception {
+ Main.main(args);
+ }
+}
--- /dev/null
+<aspectj>
+ <aspects>
+ <aspect name="AbstractAspect"/>
+ </aspects>
+
+ <weaver options="-showWeaveInfo -verbose"/>
+</aspectj>
+
--- /dev/null
+<aspectj>
+ <aspects>
+ <concrete-aspect name="ConcreteAspect" extends="AbstractSuperAspect">
+ <pointcut name="scope" expression="within(Main)"/>
+ </concrete-aspect>
+ </aspects>
+</aspectj>
+
package org.aspectj.systemtest.ajc150.ltw;
import java.io.File;
+import java.util.Enumeration;
+import java.util.Properties;
import junit.framework.Test;
import org.aspectj.testing.XMLBasedAjcTestCase;
+import org.aspectj.weaver.tools.WeavingAdaptor;
public class LTWTests extends org.aspectj.testing.XMLBasedAjcTestCase {
public void testOutxmlJar (){
runTest("Ensure valid aop.xml is generated for -outjar");
}
+
+ public void testNoAopxml(){
+ setSystemProperty(WeavingAdaptor.WEAVING_ADAPTOR_VERBOSE,"true");
+ runTest("Ensure no weaving without visible aop.xml");
+ }
+
+ public void testDefineConcreteAspect(){
+ runTest("Define concrete sub-aspect using aop.xml");
+ }
+
+ public void testDeclareAbstractAspect(){
+// setSystemProperty(WeavingAdaptor.WEAVING_ADAPTOR_VERBOSE,"true");
+// setSystemProperty(WeavingAdaptor.SHOW_WEAVE_INFO_PROPERTY,"true");
+ runTest("Use abstract aspect for ITD using aop.xml");
+ }
+
+ /*
+ * Allow system properties to be set and restored
+ * TODO maw move to XMLBasedAjcTestCase or RunSpec
+ */
+ private final static String NULL = "null";
+
+ private Properties savedProperties;
+
+ protected void setSystemProperty (String key, String value) {
+ Properties systemProperties = System.getProperties();
+ copyProperty(key,systemProperties,savedProperties);
+ systemProperties.setProperty(key,value);
+ }
+
+ private static void copyProperty (String key, Properties from, Properties to) {
+ String value = from.getProperty(key,NULL);
+ to.setProperty(key,value);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ savedProperties = new Properties();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ /* Restore system properties */
+ Properties systemProperties = System.getProperties();
+ for (Enumeration enu = savedProperties.keys(); enu.hasMoreElements(); ) {
+ String key = (String)enu.nextElement();
+ String value = savedProperties.getProperty(key);
+ if (value == NULL) systemProperties.remove(key);
+ else systemProperties.setProperty(key,value);
+ }
+ }
}
outjar="main1.jar"
options="-showWeaveInfo"
>
- <message kind="weave" text="method-execution(void Main.test1())' in Type 'Main' (Main.java:15) advised by before advice from 'Aspect1' (Aspect1.aj:16)"/>
+ <message kind="weave" text="method-execution(void Main.test1())' in Type 'Main' (Main.java:17) advised by before advice from 'Aspect1' (Aspect1.aj:16)"/>
</compile>
<compile
classpath="main1.jar"
<line text="Main.test2"/>
</stdout>
<stderr>
+ <line text="weaveinfo Join point 'method-execution(void Main.test1())' in Type 'Main' (Main.java:17) advised by before advice from 'Aspect1' (Aspect1.aj:16)"/>
+ <line text="weaveinfo Join point 'method-execution(void Main.test2())' in Type 'Main' (Main.java:21) advised by before advice from 'Aspect2' (Aspect2.aj:16)"/>
<line text="Aspect1.before_test1"/>
<line text="Aspect2.before_test2"/>
</stderr>
</run>
</ajc-test>
+ <ajc-test dir="ltw"
+ title="Ensure no weaving without visible aop.xml"
+ keywords="reweavable">
+ <compile
+ files="TestMain.java, Main.java"
+ >
+ </compile>
+ <run class="TestMain" ltw="">
+ <stdout>
+ <line text="Main.main"/>
+ <line text="Main.test1"/>
+ <line text="Main.test2"/>
+ </stdout>
+ <stderr>
+ <line text="info register classloader org.aspectj.weaver.loadtime.WeavingURLClassLoader"/>
+ <line text="info no configuration found. Disabling weaver for class loader org.aspectj.weaver.loadtime.WeavingURLClassLoader"/>
+ </stderr>
+ </run>
+ </ajc-test>
+
+
+ <ajc-test dir="ltw"
+ title="Define concrete sub-aspect using aop.xml"
+ keywords="aop.xml">
+ <compile
+ files="Main.java"
+ outjar="main.jar"
+ >
+ </compile>
+ <compile
+ classpath="main1.jar"
+ files="AbstractSuperAspect.aj"
+ outjar="aspect.jar"
+ >
+ </compile>
+ <run class="Main" ltw="aop-defineaspect.xml">
+ <stdout>
+ <line text="Main.main"/>
+ <line text="Main.test1"/>
+ <line text="Main.test2"/>
+ </stdout>
+ <stderr>
+ <line text="AbstractSuperAspect.before_test1"/>
+ </stderr>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="ltw"
+ title="Use abstract aspect for ITD using aop.xml"
+ keywords="abstract aspect, ITD">
+ <compile
+ files="TestITDMethod.java"
+ >
+ </compile>
+ <compile
+ files="AbstractAspect.aj"
+ >
+ <message kind="warning" text="this affected type is not exposed to the weaver: TestITDMethod"/>
+ </compile>
+ <run class="TestITDMethod" options="test" ltw="aop-abstractaspect.xml">
+ <stdout>
+ <line text="TestITDMethod.main"/>
+ </stdout>
+ <stderr>
+ <line text="weaveinfo Type 'TestITDMethod' (TestITDMethod.java) has intertyped method from 'AbstractAspect' (AbstractAspect.aj:'void TestITDMethod.test()')"/>
+ <line text="AbstractAspect_TestITDMethod.test"/>
+ </stderr>
+ </run>
+ </ajc-test>
protected GeneratedClassHandler generatedClassHandler;
protected Map generatedClasses = new HashMap(); /* String -> UnwovenClassFile */
+ protected WeavingAdaptor () {
+ createMessageHandler();
+ }
+
+
/**
* Construct a WeavingAdaptor with a reference to a weaving class loader. The
* adaptor will automatically search the class loader hierarchy to resolve
}
private void init(List classPath, List aspectPath) {
- messageHandler = new WeavingAdaptorMessageHandler(new PrintWriter(System.err));
- if (verbose) messageHandler.dontIgnore(IMessage.INFO);
- if (Boolean.getBoolean(SHOW_WEAVE_INFO_PROPERTY)) messageHandler.dontIgnore(IMessage.WEAVEINFO);
+ createMessageHandler();
info("using classpath: " + classPath);
info("using aspectpath: " + aspectPath);
weaver = new BcelWeaver(bcelWorld);
registerAspectLibraries(aspectPath);
}
+
+
+ private void createMessageHandler() {
+ messageHandler = new WeavingAdaptorMessageHandler(new PrintWriter(System.err));
+ if (verbose) messageHandler.dontIgnore(IMessage.INFO);
+ if (Boolean.getBoolean(SHOW_WEAVE_INFO_PROPERTY)) messageHandler.dontIgnore(IMessage.WEAVEINFO);
+ }
/**
* Appends URL to path used by the WeavingAdptor to resolve classes
return ret;
}
- private boolean info (String message) {
+ protected boolean info (String message) {
return MessageUtil.info(messageHandler,message);
}
- private boolean warn (String message) {
+ protected boolean warn (String message) {
return MessageUtil.warn(messageHandler,message);
}
- private boolean error (String message) {
+ protected boolean error (String message) {
return MessageUtil.error(messageHandler,message);
}