Browse Source

added LTW: modules loadtime and loadtime5

fix some build issues - some more left in deps handling
refactored IMessageHandler to support dontIgnore()
AspectJ5_Development
avasseur 19 years ago
parent
commit
7bd3548306
43 changed files with 1483 additions and 53 deletions
  1. 3
    3
      aspectj5rt/build.xml
  2. 8
    0
      bridge/src/org/aspectj/bridge/CountingMessageHandler.java
  3. 10
    0
      bridge/src/org/aspectj/bridge/IMessageHandler.java
  4. 7
    0
      bridge/src/org/aspectj/bridge/MessageUtil.java
  5. 9
    1
      bridge/src/org/aspectj/bridge/MessageWriter.java
  6. 3
    3
      build-common.xml
  7. 6
    2
      build.xml
  8. 52
    0
      loadtime/build.xml
  9. 127
    0
      loadtime/src/aspectj_1_5_0.dtd
  10. 292
    0
      loadtime/src/org/aspectj/weaver/loadtime/Aj.java
  11. 32
    0
      loadtime/src/org/aspectj/weaver/loadtime/ClassPreProcessor.java
  12. 161
    0
      loadtime/src/org/aspectj/weaver/loadtime/Options.java
  13. 93
    0
      loadtime/src/org/aspectj/weaver/loadtime/definition/Definition.java
  14. 196
    0
      loadtime/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java
  15. 84
    0
      loadtime5/build.xml
  16. 2
    0
      loadtime5/loadtime5.mf.txt
  17. 52
    0
      loadtime5/src/org/aspectj/weaver/loadtime/Agent.java
  18. 59
    0
      loadtime5/src/org/aspectj/weaver/loadtime/ClassPreProcessorAgentAdapter.java
  19. 11
    0
      loadtime5/testsrc/aop.xml
  20. 46
    0
      loadtime5/testsrc/org/aspectj/weaver/loadtime5/test/AllTests.java
  21. 129
    0
      loadtime5/testsrc/test/loadtime5/AtAspectJTest.java
  22. 5
    1
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java
  23. 1
    22
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
  24. 28
    1
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java
  25. 5
    1
      org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java
  26. 5
    1
      org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java
  27. 5
    1
      testing-client/testsrc/org/aspectj/testing/TesterTest.java
  28. 10
    2
      testing-util/build.xml
  29. BIN
      testing-util/testdata/testCompareClassFiles/org/aspectj/testingutil/TestCompareClassFile$1.class
  30. BIN
      testing-util/testdata/testCompareClassFiles/org/aspectj/testingutil/TestCompareClassFile.class
  31. 1
    0
      testing-util/testdata/testCompareClassFiles/org/aspectj/testingutil/readme.txt
  32. 2
    2
      testing-util/testsrc/org/aspectj/testingutil/TestUtilTest.java
  33. 5
    1
      testing/src/org/aspectj/testing/run/RunStatus.java
  34. 4
    0
      testing/testsrc/org/aspectj/testing/taskdefs/AjcTaskCompileCommandTest.java
  35. 1
    0
      tests/build.xml
  36. 4
    2
      tests/java5/ataspectj/ataspectj/IfPointcutTest.java
  37. 1
    1
      tests/java5/ataspectj/ataspectj/PrecedenceTest.java
  38. 1
    1
      tests/src/org/aspectj/systemtest/AllTests15.java
  39. 2
    1
      tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150_NeedJava15.java
  40. 8
    6
      weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java
  41. 4
    1
      weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
  42. 5
    0
      weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
  43. 4
    0
      weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java

+ 3
- 3
aspectj5rt/build.xml View File

@@ -18,9 +18,9 @@
<target name="compile" if="jdk15" depends="init,
runtime.compile">
<!-- FIXME: we override compile due to use of java5-src instead of src.. and source/target attrs -->
<mkdir dir="${basedir}/bin"/>
<javac debug="on" destdir="${basedir}/bin" source="1.5" target="1.5">
<src path="${basedir}/java5-src"/>
<mkdir dir="../aspectj5rt/bin"/>
<javac debug="on" destdir="../aspectj5rt/bin" source="1.5" target="1.5">
<src path="../aspectj5rt/java5-src"/>
<classpath refid="aspectj5rt.src.path"/>
</javac>
</target>

+ 8
- 0
bridge/src/org/aspectj/bridge/CountingMessageHandler.java View File

@@ -140,4 +140,12 @@ public class CountingMessageHandler implements IMessageHandler {
if (proxy != null) proxy.reset();
counters.clear();
}

/**
* Not supported
* @param kind
*/
public void dontIgnore(IMessage.Kind kind) {
;
}
}

+ 10
- 0
bridge/src/org/aspectj/bridge/IMessageHandler.java View File

@@ -49,6 +49,9 @@ public interface IMessageHandler {
public boolean isIgnoring(IMessage.Kind kind) {
return false;
}
public void dontIgnore(IMessage.Kind kind) {
;
}
};

/**
@@ -66,4 +69,11 @@ public interface IMessageHandler {
* @return true if this handler is ignoring all messages of this type
*/
boolean isIgnoring(IMessage.Kind kind);

/**
* Allow fine grained configuration. This implementation does not ignore anything.
* @param kind
*/
void dontIgnore(IMessage.Kind kind);

}

+ 7
- 0
bridge/src/org/aspectj/bridge/MessageUtil.java View File

@@ -358,6 +358,9 @@ public class MessageUtil {
public boolean isIgnoring(Kind kind) {
return false;
}
public void dontIgnore(IMessage.Kind kind) {
;
}
};
return visitMessages(holder, selector, true, false);
}
@@ -584,6 +587,10 @@ public class MessageUtil {
String text = message.getMessage();
return ((null != message) && (-1 != text.indexOf(infix)));
}

public void dontIgnore(IMessage.Kind kind) {
;
}
}

// ------------------ components to render messages

+ 9
- 1
bridge/src/org/aspectj/bridge/MessageWriter.java View File

@@ -52,7 +52,7 @@ public class MessageWriter implements IMessageHandler {
}
/**
* @see org.aspectj.bridge.IMessageHandler#isIgnoring(Kind)
* @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind)
*/
public boolean isIgnoring(IMessage.Kind kind) {
// XXX share MessageHandler implementation in superclass
@@ -64,4 +64,12 @@ public class MessageWriter implements IMessageHandler {
return message.toString();
}

/**
* Override to allow fine grained configuration. This implementation does not ignore anything.
* @param kind
*/
public void dontIgnore(IMessage.Kind kind) {
;
}

}

+ 3
- 3
build-common.xml View File

@@ -72,7 +72,7 @@
<sequential>
<echo message="compile ... @{project}"/>
<mkdir dir="../@{project}/${build.dir}"/>
<javac debug="on" destdir="../@{project}/${build.dir}" source="1.2" target="1.1">
<javac debug="on" destdir="../@{project}/${build.dir}" source="1.3" target="1.3">
<src path="../@{project}/${src.dir}"/>
<classpath refid="@{path}"/>
</javac>
@@ -85,7 +85,7 @@
<sequential>
<echo message="test:compile ... @{project}"/>
<mkdir dir="../@{project}/${test.build.dir}"/>
<javac debug="on" destdir="../@{project}/${test.build.dir}" source="1.2" target="1.1">
<javac debug="on" destdir="../@{project}/${test.build.dir}" source="1.3" target="1.3">
<src path="../@{project}/${test.src.dir}"/>
<classpath refid="@{path}"/>
<classpath path="../@{project}/${build.dir}"/>
@@ -99,7 +99,7 @@
<attribute name="suite"/>
<sequential>
<!-- showoutput="on" -->
<junit showoutput="on" fork="on" haltonfailure="on" haltonerror="on" printsummary="on">
<junit showoutput="on" fork="on" haltonfailure="on" haltonerror="on" printsummary="on" dir="../@{project}">
<classpath>
<pathelement path="../@{project}/${build.dir}"/>
<pathelement path="../@{project}/${test.build.dir}"/>

+ 6
- 2
build.xml View File

@@ -23,7 +23,9 @@
testing-drivers/build.xml,
ajdoc/build.xml,
ajbrowser/build.xml,
tests/build.xml"/>
tests/build.xml,
loadtime/build.xml,
loadtime5/build.xml"/>
</subant>
</sequential>
</macrodef>
@@ -62,7 +64,9 @@
ajde/build.xml,
taskdefs/build.xml,
ajdoc/build.xml,
ajbrowser/build.xml"/>
ajbrowser/build.xml,
loadtime/build.xml,
loadtime5/build.xml"/>
<!-- TODO av org.aspectj.lib -->
</subant>
<!-- FIXME av bcel-builder -->

+ 52
- 0
loadtime/build.xml View File

@@ -0,0 +1,52 @@
<?xml version="1.0"?>
<project name="loadtime" default="all" basedir=".">

<import file="../build-common.xml"/>
<import file="../asm/build.xml"/>
<import file="../bridge/build.xml"/>
<import file="../util/build.xml"/>
<import file="../weaver/build.xml"/>


<path id="loadtime.test.src.path">
<fileset dir="${basedir}/../lib">
<include name="junit/*.jar"/>
</fileset>
<path refid="loadtime.src.path"/>
</path>

<path id="loadtime.src.path">
<pathelement path="../asm/bin"/>
<pathelement path="../bridge/bin"/>
<pathelement path="../util/bin"/>
<pathelement path="../weaver/bin"/>
<fileset dir="${basedir}/../lib">
<include name="bcel/*.jar"/>
</fileset>
</path>

<target name="compile" depends="init,
asm.compile,
bridge.compile,
util.compile,
weaver.compile">
<srccompile project="loadtime" path="loadtime.src.path"/>
</target>

<target name="test:compile" depends="compile">
</target>

<target name="test" depends="test:compile">
</target>

<target name="jar" depends="compile">
<delete file="${build.ajdir}/jars/loadtime.jar"/>
<jar destfile="${build.ajdir}/jars/loadtime.jar">
<fileset dir="bin">
<include name="**/*"/>
</fileset>
</jar>
</target>

</project>


+ 127
- 0
loadtime/src/aspectj_1_5_0.dtd View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--*****************************************************************************************************************************
AspectJ 5 DTD

To use this DTD, start your defintion file with
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD 1.5.0//EN"
"http://.../dtd/aspectj_1_5_0.dtd">

You can also use the "aliasing DTD" that matchs always the latest release of AspectJ
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN"
"http://.../dtd/aspectj.dtd">

To not use this DTD, start your definition file with
<?xml version="1.0"?>

******************************************************************************************************************************-->


<!--*****************************************************************************************************************************
aspectj
*********************************************************************************************************************************
[aspectj] defines the root element
******************************************************************************************************************************-->
<!ELEMENT aspectj (
weaver?,
aspects?
)>
<!--*****************************************************************************************************************************
weaver
*********************************************************************************************************************************
[weaver] defines the weaver configuration
@options defines a command like line of option
When multiple aspectj DD are found, the options are simply toggled
TODO: Note: the scope of the options can be ClassLoader aware but should be assumed JVM wide
******************************************************************************************************************************-->
<!ELEMENT weaver (
(include | exclude)*
)>
<!ATTLIST weaver
options CDATA #IMPLIED
>
<!--*****************************************************************************************************************************
include
*********************************************************************************************************************************
[include] narrows the scope of the weaver
A class must be matched by ALL the include elements to be exposed to the weaver
@within defines a type pattern
(it is not a startWith)
******************************************************************************************************************************-->
<!ELEMENT include EMPTY>
<!ATTLIST include
within CDATA #REQUIRED
>
<!--*****************************************************************************************************************************
exclude
*********************************************************************************************************************************
[exclude] narrows the scope of the weaver
A class must be matched by NONE of the exclude elements to be exposed to the weaver
@within defines a type pattern
(it is not a startWith)
TODO should it be called @from: "<exclude from=..> instead of <exclude within=..>
TODO: AND must be written that way and not with the "&&" symbol. Thus NOT and OR exists as well.
******************************************************************************************************************************-->
<!ELEMENT exclude EMPTY>
<!ATTLIST exclude
within CDATA #REQUIRED
>
<!--*****************************************************************************************************************************
aspects
*********************************************************************************************************************************
[aspects] defines a set of aspects
TODO we were about to use include but it is already used for weaver scope with "within" which is not relevant
for aspects. I (AV) decided to use only aspect and provide include= thru name, and exclude= as exclude.
see sample.
******************************************************************************************************************************-->
<!ELEMENT aspects (
(aspect | exclude | concrete-aspect)*
)>
<!--*****************************************************************************************************************************
aspect
TODO: did not used include since already used in weaver/include@within and @within does not makes sense
*********************************************************************************************************************************
[aspect] defines an aspect to include
@name FQN of the aspect, nested class must use $
******************************************************************************************************************************-->
<!ELEMENT aspect EMPTY>
<!ATTLIST aspect
name CDATA #REQUIRED
>
<!--*****************************************************************************************************************************
exclude
*********************************************************************************************************************************
[exclude] defines a set of aspect to exclude
@within within pattern (even from other systems / parent classloader)
SAME AS FOR weaver/exclude
******************************************************************************************************************************-->
<!--*****************************************************************************************************************************
concrete-aspect
*********************************************************************************************************************************
[concrete-aspect] defines a concrete aspect from an abstract one
@name FQN of the concrete aspect (use $ for nested class) [will be jit generated]
@extends FQN of the abstract aspect (use $ for nested class)
******************************************************************************************************************************-->
<!ELEMENT concrete-aspect (
pointcut+
)>
<!ATTLIST concrete-aspect
name CDATA #REQUIRED
extends CDATA #REQUIRED
>
<!--*****************************************************************************************************************************
pointcut
*********************************************************************************************************************************
[pointcut] defines a concrete pointcut within a concrete aspect from an abstract one
@name name of the abstract pointcut (method name, unique in aspect class hierarchy)
@expression pointcut expression
Note: for argument binding, the bounded arguments must be present and bounded:
<pointcut name="myAdvice(int i)" expression="... AND args(i)"/>
TODO: AND must be written that way and not with the "&&" symbol. Thus NOT and OR exists as well.
******************************************************************************************************************************-->
<!ELEMENT pointcut EMPTY>
<!ATTLIST pointcut
name CDATA #REQUIRED
expression CDATA #REQUIRED
>

+ 292
- 0
loadtime/src/org/aspectj/weaver/loadtime/Aj.java View File

@@ -0,0 +1,292 @@
/*******************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur
* 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
*******************************************************************************/
package org.aspectj.weaver.loadtime;

import org.aspectj.asm.IRelationship;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.weaver.ICrossReferenceHandler;
import org.aspectj.weaver.World;
import org.aspectj.weaver.bcel.BcelWeaver;
import org.aspectj.weaver.bcel.BcelWorld;
import org.aspectj.weaver.loadtime.definition.Definition;
import org.aspectj.weaver.loadtime.definition.DocumentParser;
import org.aspectj.weaver.tools.GeneratedClassHandler;
import org.aspectj.weaver.tools.WeavingAdaptor;

import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

/**
* Adapter between the generic class pre processor interface and the AspectJ weaver
* Load time weaving consistency relies on Bcel.setRepository
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class Aj implements ClassPreProcessor {

/**
* Initialization
*/
public void initialize() {
;
}

/**
* Weave
*
* @param className
* @param bytes
* @param loader
* @return
*/
public byte[] preProcess(String className, byte[] bytes, ClassLoader loader) {
//System.out.println("Aj.preProcess " + className + " @ " + loader + " " + Thread.currentThread());
//TODO av needs to spec and doc that
//TODO av should skip org.aspectj as well unless done somewhere else
if (loader == null
|| className == null) {
// skip boot loader or null classes (hibernate)
return bytes;
}

try {
byte[] weaved = WeaverContainer.getWeaver(loader).weaveClass(className, bytes);
//TODO av make dump optionnal and configurable
__dump(className, weaved);
return weaved;
} catch (Throwable t) {
t.printStackTrace();
return bytes;
}
}

/**
* Cache of weaver
* There is one weaver per classloader
*/
static class WeaverContainer {

private static Map weavingAdaptors = new WeakHashMap();

static WeavingAdaptor getWeaver(ClassLoader loader) {
synchronized (weavingAdaptors) {
WeavingAdaptor weavingAdaptor = (WeavingAdaptor) weavingAdaptors.get(loader);
if (weavingAdaptor == null) {
weavingAdaptor = new ClassLoaderWeavingAdaptor(loader);
weavingAdaptors.put(loader, weavingAdaptor);
}
return weavingAdaptor;
}
}
}

/**
* Adaptor with the AspectJ WeavingAdaptor
*/
static class ClassLoaderWeavingAdaptor extends WeavingAdaptor {

public ClassLoaderWeavingAdaptor(final ClassLoader loader) {
super(null);// at this stage we don't have yet a generatedClassHandler to define to the VM the closures
this.generatedClassHandler = new GeneratedClassHandler() {
/**
* Callback when we need to define a Closure in the JVM
*
* @param name
* @param bytes
*/
public void acceptClass(String name, byte[] bytes) {
//TODO av make dump configurable
try {
__dump(name, bytes);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
defineClass(loader, name, bytes);// could be done lazily using the hook
}
};

bcelWorld = new BcelWorld(
loader, messageHandler, new ICrossReferenceHandler() {
public void addCrossReference(ISourceLocation from, ISourceLocation to, IRelationship.Kind kind, boolean runtimeTest) {
;// for tools only
}
}
);

// //TODO this AJ code will call
// //org.aspectj.apache.bcel.Repository.setRepository(this);
// //ie set some static things
// //==> bogus as Bcel is expected to be
// org.aspectj.apache.bcel.Repository.setRepository(new ClassLoaderRepository(loader));

weaver = new BcelWeaver(bcelWorld);

// register the definitions
registerDefinitions(weaver, loader);

// after adding aspects
weaver.prepareForWeave();
}
}

private static void defineClass(ClassLoader loader, String name, byte[] bytes) {
try {
//TODO av protection domain, and optimize
Method defineClass = ClassLoader.class.getDeclaredMethod(
"defineClass", new Class[]{
String.class, bytes.getClass(), int.class, int.class
}
);
defineClass.setAccessible(true);
defineClass.invoke(
loader, new Object[]{
name,
bytes,
new Integer(0),
new Integer(bytes.length)
}
);
} catch (Throwable t) {
t.printStackTrace();
}
}

/**
* Dump the given bytcode in _dump/...
*
* @param name
* @param b
* @throws Throwable
*/
private static void __dump(String name, byte[] b) throws Throwable {
String className = name.replace('.', '/');
final File dir;
if (className.indexOf('/') > 0) {
dir = new File("_dump" + File.separator + className.substring(0, className.lastIndexOf('/')));
} else {
dir = new File("_dump");
}
dir.mkdirs();
String fileName = "_dump" + File.separator + className + ".class";
FileOutputStream os = new FileOutputStream(fileName);
os.write(b);
os.close();
}

/**
* Load and cache the aop.xml/properties according to the classloader visibility rules
*
* @param weaver
* @param loader
*/
private static void registerDefinitions(final BcelWeaver weaver, final ClassLoader loader) {
try {
//TODO av underoptimized: we will parse each XML once per CL that see it
Enumeration xmls = loader.getResources("/META-INF/aop.xml");
List definitions = new ArrayList();

//TODO av dev mode needed ? TBD -Daj5.def=...
if (loader != null && loader != ClassLoader.getSystemClassLoader().getParent()) {
String file = System.getProperty("aj5.def", null);
if (file != null) {
definitions.add(DocumentParser.parse((new File(file)).toURL()));
}
}

while (xmls.hasMoreElements()) {
URL xml = (URL) xmls.nextElement();
definitions.add(DocumentParser.parse(xml));
}
registerOptions(weaver, loader, definitions);
registerAspects(weaver, loader, definitions);
registerFilters(weaver, loader, definitions);
} catch (Exception e) {
weaver.getWorld().getMessageHandler().handleMessage(
new Message("Register definition failed", IMessage.FAIL, e, null)
);
}
}

/**
* 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
*
* @param weaver
* @param loader
* @param definitions
*/
private static void registerOptions(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
StringBuffer allOptions = new StringBuffer();
for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
Definition definition = (Definition) iterator.next();
allOptions.append(definition.getWeaverOptions()).append(' ');
}

Options.WeaverOption weaverOption = Options.parse(allOptions.toString(), loader);

// configure the weaver and world
// AV - code duplicates AspectJBuilder.initWorldAndWeaver()
World world = weaver.getWorld();
world.setMessageHandler(weaverOption.messageHandler);
world.setXlazyTjp(weaverOption.lazyTjp);
weaver.setReweavableMode(weaverOption.reWeavable, false);
world.setXnoInline(weaverOption.noInline);
world.setBehaveInJava5Way(weaverOption.java5);
//TODO proceedOnError option
}

/**
* Register the aspect, following include / exclude rules
*
* @param weaver
* @param loader
* @param definitions
*/
private static void registerAspects(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
//TODO: the exclude aspect allow to exclude aspect defined upper in the CL hierarchy - is it what we want ??
// if not, review the getResource so that we track which resource is defined by which CL

//it aspectClassNames
//exclude if in any of the exclude list
for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
Definition definition = (Definition) iterator.next();
for (Iterator aspects = definition.getAspectClassNames().iterator(); aspects.hasNext();) {
String aspectClassName = (String) aspects.next();
if (!Definition.isAspectExcluded(aspectClassName, definitions)) {
weaver.addLibraryAspect(aspectClassName);
}
}
}

//it concreteAspects
//exclude if in any of the exclude list
//TODO
}

/**
* Register the include / exclude filters
*
* @param weaver
* @param loader
* @param definitions
*/
private static void registerFilters(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
//TODO
;
}
}

+ 32
- 0
loadtime/src/org/aspectj/weaver/loadtime/ClassPreProcessor.java View File

@@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur
* 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
*******************************************************************************/
package org.aspectj.weaver.loadtime;

/**
* Generic class pre processor interface that allows to separate the AspectJ 5 load time weaving
* from Java 5 JVMTI interfaces for further use on Java 1.3 / 1.4
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public interface ClassPreProcessor {

/**
* Post constructor initialization, usually empty
*/
void initialize();

/**
* Weave
*
* @param className
* @param bytes
* @param classLoader
* @return
*/
byte[] preProcess(String className, byte[] bytes, ClassLoader classLoader);
}

+ 161
- 0
loadtime/src/org/aspectj/weaver/loadtime/Options.java View File

@@ -0,0 +1,161 @@
/**************************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
* http://aspectwerkz.codehaus.org *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package org.aspectj.weaver.loadtime;

import org.aspectj.bridge.AbortException;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.Message;
import org.aspectj.util.LangUtil;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
* A class that hanldes LTW options.
* Note: AV - I choosed to not reuse AjCompilerOptions and alike since those implies too many dependancies on
* jdt and ajdt modules.
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class Options {

private static class DefaultMessageHandler implements IMessageHandler {

boolean isVerbose = false;
boolean showWeaveInfo = false;
boolean showWarn = true;

public boolean handleMessage(IMessage message) throws AbortException {
return SYSTEM_OUT.handleMessage(message);
}

public boolean isIgnoring(IMessage.Kind kind) {
if (kind.equals(IMessage.WEAVEINFO)) {
return !showWeaveInfo;
}
if (kind.isSameOrLessThan(IMessage.INFO)) {
return !isVerbose;
}
return !showWarn;
}

public void dontIgnore(IMessage.Kind kind) {
if (kind.equals(IMessage.WEAVEINFO)) {
showWeaveInfo = true;
} else if (kind.equals(IMessage.DEBUG)) {
isVerbose = true;
} else if (kind.equals(IMessage.WARNING)) {
showWarn = false;
}
}
}

private final static String OPTION_15 = "-1.5";
private final static String OPTION_lazyTjp = "-XlazyTjp";
private final static String OPTION_noWarn = "-nowarn";
private final static String OPTION_noWarnNone = "-warn:none";
private final static String OPTION_proceedOnError = "-proceedOnError";
private final static String OPTION_verbose = "-verbose";
private final static String OPTION_reweavable = "-Xreweavable";
private final static String OPTION_noinline = "-Xnoinline";
private final static String OPTION_showWeaveInfo = "-showWeaveInfo";
private final static String OPTIONVALUED_messageHolder = "-XmessageHolderClass:";//TODO rename to Handler

//FIXME dump option - dump what - dump before/after ?

public static WeaverOption parse(String options, ClassLoader laoder) {
// the first option wins
List flags = LangUtil.anySplit(options, " ");
Collections.reverse(flags);

WeaverOption weaverOption = new WeaverOption();
weaverOption.messageHandler = new DefaultMessageHandler();//default


// 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();
if (arg.startsWith(OPTIONVALUED_messageHolder)) {
if (arg.length() > OPTIONVALUED_messageHolder.length()) {
String handlerClass = arg.substring(OPTIONVALUED_messageHolder.length()).trim();
try {
Class handler = Class.forName(handlerClass, false, laoder);
weaverOption.messageHandler = ((IMessageHandler) handler.newInstance());
} catch (Throwable t) {
weaverOption.messageHandler.handleMessage(
new Message(
"Cannot instantiate message handler " + handlerClass,
IMessage.ERROR,
t,
null
)
);
}
}
}
}

// configure the other options
for (Iterator iterator = flags.iterator(); iterator.hasNext();) {
String arg = (String) iterator.next();
if (arg.equals(OPTION_15)) {
weaverOption.java5 = true;
} else if (arg.equalsIgnoreCase(OPTION_lazyTjp)) {
weaverOption.lazyTjp = true;
} else if (arg.equalsIgnoreCase(OPTION_noinline)) {
weaverOption.noInline = true;
} else if (arg.equalsIgnoreCase(OPTION_noWarn) || arg.equalsIgnoreCase(OPTION_noWarnNone)) {
weaverOption.noWarn = true;
} else if (arg.equalsIgnoreCase(OPTION_proceedOnError)) {
weaverOption.proceedOnError = true;
} else if (arg.equalsIgnoreCase(OPTION_reweavable)) {
weaverOption.reWeavable = true;
} else if (arg.equalsIgnoreCase(OPTION_showWeaveInfo)) {
weaverOption.showWeaveInfo = true;
} else if (arg.equalsIgnoreCase(OPTION_verbose)) {
weaverOption.verbose = true;
} else {
weaverOption.messageHandler.handleMessage(
new Message(
"Cannot configure weaver with option " + arg + ": unknown option",
IMessage.WARNING,
null,
null
)
);
}
}

// refine message handler configuration
if (weaverOption.noWarn) {
weaverOption.messageHandler.dontIgnore(IMessage.WARNING);
}
if (weaverOption.verbose) {
weaverOption.messageHandler.dontIgnore(IMessage.DEBUG);
}
if (weaverOption.showWeaveInfo) {
weaverOption.messageHandler.dontIgnore(IMessage.WEAVEINFO);
}

return weaverOption;
}

public static class WeaverOption {
boolean java5;
boolean lazyTjp;
boolean noWarn;
boolean proceedOnError;
boolean verbose;
boolean reWeavable;
boolean noInline;
boolean showWeaveInfo;
IMessageHandler messageHandler;
}
}

+ 93
- 0
loadtime/src/org/aspectj/weaver/loadtime/definition/Definition.java View File

@@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur
* 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
*******************************************************************************/
package org.aspectj.weaver.loadtime.definition;

import java.util.List;
import java.util.ArrayList;

/**
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class Definition {

private StringBuffer m_weaverOptions;

private List m_includePatterns;

private List m_excludePatterns;

private List m_aspectClassNames;

private List m_aspectExcludePatterns;

private List m_concreteAspects;

public Definition() {
m_weaverOptions = new StringBuffer();
m_includePatterns = new ArrayList(0);
m_excludePatterns = new ArrayList(0);
m_aspectClassNames = new ArrayList();
m_aspectExcludePatterns = new ArrayList(0);
m_concreteAspects = new ArrayList(0);
}

public String getWeaverOptions() {
return m_weaverOptions.toString();
}

public List getIncludePatterns() {
return m_includePatterns;
}

public List getExcludePatterns() {
return m_excludePatterns;
}

public List getAspectClassNames() {
return m_aspectClassNames;
}

public List getAspectExcludePatterns() {
return m_aspectExcludePatterns;
}

public List getConcreteAspects() {
return m_concreteAspects;
}

public static class ConcreteAspect {
String name;
String extend;
List pointcuts;

public ConcreteAspect(String name, String extend) {
this.name = name;
this.extend = extend;
this.pointcuts = new ArrayList();
}
}

public static class Pointcut {
String name;
String expression;
public Pointcut(String name, String expression) {
this.name = name;
this.expression = expression;
}
}

public static boolean isAspectExcluded(String aspectClassName, List definitions) {
//TODO
return false;
}

public void appendWeaverOptions(String option) {
m_weaverOptions.append(option.trim()).append(' ');
}

}

+ 196
- 0
loadtime/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java View File

@@ -0,0 +1,196 @@
/*******************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur
* 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
*******************************************************************************/
package org.aspectj.weaver.loadtime.definition;

import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;
import org.xml.sax.Attributes;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import org.aspectj.weaver.loadtime.definition.Definition;

import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.net.URL;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;

/**
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class DocumentParser extends DefaultHandler {

/**
* The current DTD public id. The matching dtd will be searched as a resource.
*/
private final static String DTD_PUBLIC_ID = "-//AspectJ//DTD 1.5.0//EN";

/**
* The DTD alias, for better user experience.
*/
private final static String DTD_PUBLIC_ID_ALIAS = "-//AspectJ//DTD//EN";

/**
* A handler to the DTD stream so that we are only using one file descriptor
*/
private final static InputStream DTD_STREAM = DocumentParser.class.getResourceAsStream("/aspectj_1_5_0.dtd");

private final static String ASPECTJ_ELEMENT = "aspectj";
private final static String WEAVER_ELEMENT = "weaver";
private final static String OPTIONS_ATTRIBUTE = "options";
private final static String ASPECTS_ELEMENT = "aspects";
private final static String ASPECT_ELEMENT = "aspect";
private final static String CONCRETE_ASPECT_ELEMENT = "concrete-aspect";
private final static String NAME_ATTRIBUTE = "name";
private final static String EXTEND_ATTRIBUTE = "extends";
private final static String POINTCUT_ELEMENT = "pointcut";
private final static String EXPRESSION_ATTRIBUTE = "expression";


private final Definition m_definition;

private boolean m_inAspectJ;

private Definition.ConcreteAspect m_lastConcreteAspect;

private DocumentParser() {
m_definition = new Definition();
}

public static Definition parse(final URL url) throws Exception {
InputStream in = null;
try {
DocumentParser parser = new DocumentParser();

XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setEntityResolver(parser);
xmlReader.setContentHandler(parser);
//TODO use a locator for error location reporting ?

try {
if (xmlReader.getFeature("http://xml.org/sax/features/validation")) {
xmlReader.setFeature("http://xml.org/sax/features/validation", false);
}
// xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
// xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
}
catch (SAXNotRecognizedException e) {
;//fine, the parser don't do validation
}

in = url.openStream();
xmlReader.parse(new InputSource(in));
return parser.m_definition;
} finally {
try {in.close();} catch (Throwable t) {;}
}
}

public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
if (publicId.equals(DTD_PUBLIC_ID) || publicId.equals(DTD_PUBLIC_ID_ALIAS)) {
InputStream in = DTD_STREAM;
if (in == null) {
// System.err.println("AspectJ - WARN - could not open DTD");
return null;
} else {
return new InputSource(in);
}
} else {
// System.err.println(
// "AspectJ - WARN - deprecated DTD "
// + publicId
// + " - consider upgrading to "
// + DTD_PUBLIC_ID
// );
return null;//new InputSource();
}
}

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (ASPECT_ELEMENT.equals(qName)) {
String name = attributes.getValue(NAME_ATTRIBUTE);
if (!isNull(name)) {
m_definition.getAspectClassNames().add(name);
}
} else if (WEAVER_ELEMENT.equals(qName)) {
String options = attributes.getValue(OPTIONS_ATTRIBUTE);
if (!isNull(options)) {
m_definition.appendWeaverOptions(options);
}
} else if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
String name = attributes.getValue(NAME_ATTRIBUTE);
String extend = attributes.getValue(EXTEND_ATTRIBUTE);
if (!isNull(name) && !isNull(extend)) {
m_lastConcreteAspect = new Definition.ConcreteAspect(name, extend);
m_definition.getConcreteAspects().add(m_lastConcreteAspect);
}
} else if (POINTCUT_ELEMENT.equals(qName) && m_lastConcreteAspect != null) {
String name = attributes.getValue(NAME_ATTRIBUTE);
String expression = attributes.getValue(EXPRESSION_ATTRIBUTE);
if (!isNull(name) && !isNull(expression)) {
m_lastConcreteAspect.pointcuts.add(new Definition.Pointcut(name, replaceXmlAnd(expression)));
}
} else if (ASPECTJ_ELEMENT.equals(qName)) {
if (m_inAspectJ) {
throw new SAXException("Found nested <aspectj> element");
}
m_inAspectJ = true;
} else if (ASPECTS_ELEMENT.equals(qName)) {
;//nothing to do
} else {
throw new SAXException("Unknown element while parsing <aspectj> element: " + qName);
}
//TODO include / exclude
super.startElement(uri, localName, qName, attributes);
}

public void endElement(String uri, String localName, String qName) throws SAXException {
if (CONCRETE_ASPECT_ELEMENT.equals(qName)) {
m_lastConcreteAspect = null;
} else if (ASPECTJ_ELEMENT.equals(qName)) {
m_inAspectJ = false;
}
super.endElement(uri, localName, qName);
}

public void warning(SAXParseException e) throws SAXException {
super.warning(e);
}

public void error(SAXParseException e) throws SAXException {
super.error(e);
}

public void fatalError(SAXParseException e) throws SAXException {
super.fatalError(e);
}



private static String replaceXmlAnd(String expression) {
//TODO av do we need to handle "..)AND" or "AND(.." ?
//FIXME av Java 1.4 code - if KO, use some Strings util
return expression.replaceAll(" AND ", " && ");
}

public static void main(String args[]) throws Throwable {
Definition def = parse(new File(args[0]).toURL());
System.out.println(def);
}

private boolean isNull(String s) {
return (s == null || s.length() <= 0);
}

}

+ 84
- 0
loadtime5/build.xml View File

@@ -0,0 +1,84 @@
<?xml version="1.0"?>
<project name="loadtime5" default="all" basedir=".">

<import file="../build-common.xml"/>
<import file="../asm/build.xml"/>
<import file="../bridge/build.xml"/>
<import file="../loadtime/build.xml"/>
<import file="../weaver/build.xml"/>
<import file="../util/build.xml"/>
<import file="../runtime/build.xml/"/>
<import file="../aspectj5rt/build.xml"/>



<path id="loadtime5.test.src.path">
<fileset dir="${basedir}/../lib">
<include name="junit/*.jar"/>
</fileset>
<path refid="loadtime5.src.path"/>
<pathelement path="../runtime/bin"/>
<pathelement path="../aspectj5rt/bin"/>
<pathelement path="../util/bin"/>
</path>

<path id="loadtime5.src.path">
<pathelement path="../asm/bin"/>
<pathelement path="../bridge/bin"/>
<pathelement path="../loadtime/bin"/>
<pathelement path="../weaver/bin"/>
<fileset dir="${basedir}/../lib">
<include name="bcel/*.jar"/>
</fileset>
</path>

<target name="compile" depends="init,
asm.compile,
bridge.compile,
loadtime.compile,
weaver.compile" if="jdk15">
<!-- FIXME: we override compile due to use of 1.5 -->
<mkdir dir="${basedir}/bin"/>
<javac debug="on" destdir="${basedir}/bin" source="1.5" target="1.5">
<src path="${basedir}/src"/>
<classpath refid="loadtime5.src.path"/>
</javac>
</target>

<target name="test:compile" depends="compile" if="jdk15">
<!-- FIXME sucky deps -->
<antcall target="runtime.compile"/>
<antcall target="aspectj5rt.compile"/>
<!-- FIXME: we override compile due to use of 1.5 -->
<mkdir dir="${basedir}/bintest"/>
<javac debug="on" destdir="${basedir}/bintest" source="1.5" target="1.5">
<src path="${basedir}/testsrc"/>
<classpath refid="loadtime5.test.src.path"/>
</javac>
</target>

<target name="test" depends="test:compile, jar" if="jdk15">
<!-- FIXME sucky deps -->
<antcall target="util.compile"/>

<java fork="true" classname="org.aspectj.weaver.loadtime5.test.AllTests">
<jvmarg line="-javaagent:${build.ajdir}/jars/loadtime5.jar -Daj5.def=../loadtime5/testsrc/aop.xml"/>
<classpath refid="loadtime5.test.src.path"/>
<classpath>
<pathelement path="${basedir}/bintest"/>
</classpath>
</java>
</target>

<target name="jar" depends="compile">
<delete file="${build.ajdir}/jars/loadtime5.jar"/>
<copy file="loadtime5.mf.txt" todir="${build.ajdir}/temp" filtering="yes"/>
<jar destfile="${build.ajdir}/jars/loadtime5.jar" manifest="${build.ajdir}/temp/loadtime5.mf.txt">
<fileset dir="bin">
<include name="**/*"/>
</fileset>
</jar>
</target>

</project>


+ 2
- 0
loadtime5/loadtime5.mf.txt View File

@@ -0,0 +1,2 @@
Premain-Class: org.aspectj.weaver.loadtime.Agent
Can-Redefine-Classes: true

+ 52
- 0
loadtime5/src/org/aspectj/weaver/loadtime/Agent.java View File

@@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur
* 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
*******************************************************************************/
package org.aspectj.weaver.loadtime;

import java.lang.instrument.Instrumentation;
import java.lang.instrument.ClassFileTransformer;

/**
* Java 1.5 preMain agent to hook in the class pre processor
* Can be used with -javaagent:aspectjweaver.jar
*
* @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur</a>
*/
public class Agent {

/**
* The instrumentation instance
*/
private static Instrumentation s_instrumentation;

/**
* The ClassFileTransformer wrapping the weaver
*/
private static ClassFileTransformer s_transformer = new ClassPreProcessorAgentAdapter();

/**
* JSR-163 preMain Agent entry method
*
* @param options
* @param instrumentation
*/
public static void premain(String options, Instrumentation instrumentation) {
s_instrumentation = instrumentation;
s_instrumentation.addTransformer(s_transformer);
}

/**
* Returns the Instrumentation system level instance
*/
public static Instrumentation getInstrumentation() {
if (s_instrumentation == null) {
throw new UnsupportedOperationException("Java 5 was not started with preMain -javaagent for AspectJ");
}
return s_instrumentation;
}

}

+ 59
- 0
loadtime5/src/org/aspectj/weaver/loadtime/ClassPreProcessorAgentAdapter.java View File

@@ -0,0 +1,59 @@
/*******************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur
* 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
*******************************************************************************/
package org.aspectj.weaver.loadtime;

import org.aspectj.weaver.loadtime.Aj;
import org.aspectj.weaver.loadtime.ClassPreProcessor;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

/**
* Java 1.5 adapter for class pre processor
*
* @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur</a>
*/
public class ClassPreProcessorAgentAdapter implements ClassFileTransformer {

/**
* Concrete preprocessor.
*/
private static ClassPreProcessor s_preProcessor;

static {
try {
s_preProcessor = new Aj();
s_preProcessor.initialize();
} catch (Exception e) {
throw new ExceptionInInitializerError("could not initialize JSR163 preprocessor due to: " + e.toString());
}
}

/**
* Weaving delegation
*
* @param loader the defining class loader
* @param className the name of class beeing loaded
* @param classBeingRedefined when hotswap is called
* @param protectionDomain
* @param bytes the bytecode before weaving
* @return the weaved bytecode
*/
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
if (classBeingRedefined == null) {
return s_preProcessor.preProcess(className, bytes, loader);
} else {
//FIXME av for now we skip hotswap. We should think more about that
new Exception("AspectJ5 does not weave hotswapped class (" + className + ")").printStackTrace();
return bytes;
}
}

}

+ 11
- 0
loadtime5/testsrc/aop.xml View File

@@ -0,0 +1,11 @@
<!-- FIXME fails when DTD here and call from Ant-->
<!--<!DOCTYPE aspectj PUBLIC-->
<!-- "-//AspectJ//DTD//EN"-->
<!-- "http://www.aspectj.org/dtd/aspectj_1_5_0.dtd">-->
<aspectj>
<weaver options="-showWeaveInfo"/>
<aspects>
<!-- see here nested class with ".", "$" is accepted as well -->
<aspect name="test.loadtime5.AtAspectJTest.TestAspect"/>
</aspects>
</aspectj>

+ 46
- 0
loadtime5/testsrc/org/aspectj/weaver/loadtime5/test/AllTests.java View File

@@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur
* 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
*******************************************************************************/
package org.aspectj.weaver.loadtime5.test;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import test.loadtime5.AtAspectJTest;

/**
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class AllTests extends TestCase {
public static Test suite() {
TestSuite suite = new TestSuite("All tests");

suite.addTestSuite(AtAspectJTest.class);

// suite.addTestSuite(SingletonAspectBindingsTest.class);
// suite.addTestSuite(CflowTest.class);
// suite.addTestSuite(PointcutReferenceTest.class);
// suite.addTestSuite(AfterXTest.class);
//
// //FIXME AV - fix the pc grammar to support if for @AJ aspects
// System.err.println("(AllTests: IfPointcutTest fails)");
// //suite.addTestSuite(IfPointcutTest.class);
//
// suite.addTestSuite(XXJoinPointTest.class);
// suite.addTestSuite(PrecedenceTest.class);
// suite.addTestSuite(BindingTest.class);
//
// suite.addTestSuite(PerClauseTest.class);

return suite;
}

public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}

}

+ 129
- 0
loadtime5/testsrc/test/loadtime5/AtAspectJTest.java View File

@@ -0,0 +1,129 @@
/*******************************************************************************
* Copyright (c) Jonas Bonér, Alexandre Vasseur
* 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
*******************************************************************************/
package test.loadtime5;

import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import junit.framework.TestCase;
import junit.textui.TestRunner;

/**
* Test various advice and JoinPoint + binding, without pc ref
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class AtAspectJTest extends TestCase {

static StringBuffer s_log = new StringBuffer();
static void log(String s) {
s_log.append(s).append(" ");
}

public static void main(String[] args) {
TestRunner.run(AtAspectJTest.class);
}

public static junit.framework.Test suite() {
return new junit.framework.TestSuite(AtAspectJTest.class);
}

public void hello() {
log("hello");
}

public void hello(String s) {
log("hello-");
log(s);
}

public void testExecutionWithThisBinding() {
s_log = new StringBuffer();
AtAspectJTest me = new AtAspectJTest();
me.hello();
// see here advice precedence as in source code order
//TODO check around relative order
// see fix in BcelWeaver sorting shadowMungerList
//assertEquals("around2_ around_ before hello after _around _around2 ", s_log.toString());
assertEquals("around_ around2_ before hello _around2 _around after ", s_log.toString());
}

public void testExecutionWithArgBinding() {
s_log = new StringBuffer();
AtAspectJTest me = new AtAspectJTest();
me.hello("x");
assertEquals("before- x hello- x ", s_log.toString());
}


@Aspect
public static class TestAspect {

static int s = 0;

static {
s++;
}

public TestAspect() {
// assert clinit has run when singleton aspectOf reaches that
assertTrue(s>0);
}

//public static TestAspect aspectOf() {return null;}

@Around("execution(* test.loadtime5.AtAspectJTest.hello())")
public void aaround(ProceedingJoinPoint jp) {
log("around_");
try {
jp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
log("_around");
}

@Around("execution(* test.loadtime5.AtAspectJTest.hello()) && this(t)")
public void around2(ProceedingJoinPoint jp, Object t) {
log("around2_");
assertEquals(AtAspectJTest.class.getName(), t.getClass().getName());
try {
jp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
log("_around2");
}

@Before("execution(* test.loadtime5.AtAspectJTest.hello())")
public void before(JoinPoint.StaticPart sjp) {
log("before");
assertEquals("hello", sjp.getSignature().getName());
}

@After("execution(* test.loadtime5.AtAspectJTest.hello())")
public void after(JoinPoint.StaticPart sjp) {
log("after");
assertEquals("execution(public void test.loadtime5.AtAspectJTest.hello())", sjp.toLongString());
}

//TODO see String alias, see before advice name clash - all that works
// 1/ String is in java.lang.* - see SimpleScope.javalangPrefix array
// 2/ the advice is register thru its Bcel Method mirror
@Before("execution(* test.loadtime5.AtAspectJTest.hello(String)) && args(s)")
public void before(String s, JoinPoint.StaticPart sjp) {
log("before-");
log(s);
assertEquals("hello", sjp.getSignature().getName());
}

}
}

+ 5
- 1
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java View File

@@ -120,7 +120,11 @@ public class WeaverMessageHandler implements IMessageHandler {
public boolean isIgnoring(Kind kind) {
return sink.isIgnoring(kind);
}

public void dontIgnore(IMessage.Kind kind) {
;
}

private int getStartPos(ISourceLocation sLoc,CompilationResult result) {
int pos = 0;
if (sLoc == null) return 0;

+ 1
- 22
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java View File

@@ -411,28 +411,7 @@ public class AjBuildConfig {

public void setLintMode(String lintMode) {
this.lintMode = lintMode;
String lintValue = null;
if (AJLINT_IGNORE.equals(lintMode)) {
lintValue = AjCompilerOptions.IGNORE;
} else if (AJLINT_WARN.equals(lintMode)) {
lintValue = AjCompilerOptions.WARNING;
} else if (AJLINT_ERROR.equals(lintMode)) {
lintValue = AjCompilerOptions.ERROR;
}
if (lintValue != null) {
Map lintOptions = new HashMap();
lintOptions.put(AjCompilerOptions.OPTION_ReportInvalidAbsoluteTypeName,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportInvalidWildcardTypeName,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportUnresolvableMember,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportTypeNotExposedToWeaver,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportShadowNotInStructure,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportUnmatchedSuperTypeInCall,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportCannotImplementLazyTJP,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportNeedSerialVersionUIDField,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportIncompatibleSerialVersion,lintValue);
options.set(lintOptions);
}
options.setLintMode(lintMode);
}
public boolean isNoWeave() {

+ 28
- 1
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java View File

@@ -14,6 +14,7 @@
package org.aspectj.ajdt.internal.core.builder;

import java.util.Map;
import java.util.HashMap;

import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;

@@ -122,7 +123,33 @@ public class AjCompilerOptions extends CompilerOptions {
return map;
}

public void setLintMode(String lintMode) {
String lintValue = null;
if (AjBuildConfig.AJLINT_IGNORE.equals(lintMode)) {
lintValue = AjCompilerOptions.IGNORE;
} else if (AjBuildConfig.AJLINT_WARN.equals(lintMode)) {
lintValue = AjCompilerOptions.WARNING;
} else if (AjBuildConfig.AJLINT_ERROR.equals(lintMode)) {
lintValue = AjCompilerOptions.ERROR;
}

if (lintValue != null) {
Map lintOptions = new HashMap();
lintOptions.put(AjCompilerOptions.OPTION_ReportInvalidAbsoluteTypeName,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportInvalidWildcardTypeName,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportUnresolvableMember,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportTypeNotExposedToWeaver,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportShadowNotInStructure,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportUnmatchedSuperTypeInCall,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportCannotImplementLazyTJP,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportNeedSerialVersionUIDField,lintValue);
lintOptions.put(AjCompilerOptions.OPTION_ReportIncompatibleSerialVersion,lintValue);
set(lintOptions);
}
}


/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.impl.CompilerOptions#set(java.util.Map)
*/

+ 5
- 1
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java View File

@@ -228,7 +228,11 @@ public class AspectJBuilder extends JavaBuilder implements ICompilerAdapterFacto
if (kind == IMessage.DEBUG || kind == IMessage.INFO) return true;
return false;
}

public void dontIgnore(IMessage.Kind kind) {
;
}

}

+ 5
- 1
org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java View File

@@ -455,7 +455,11 @@ public class Main {
}
return false;
}

public void dontIgnore(IMessage.Kind kind) {
;
}

/**
* Render message differently.
* If abort, then prefix stack trace with feedback request.

+ 5
- 1
testing-client/testsrc/org/aspectj/testing/TesterTest.java View File

@@ -202,7 +202,11 @@ public class TesterTest extends TestCase {
public boolean isIgnoring(IMessage.Kind kind) {
return false;
}

public void dontIgnore(IMessage.Kind kind) {
;
}

public boolean handleMessage(IMessage message) {
(message.isFailed() ? failures : passes).add(message);
return true;

+ 10
- 2
testing-util/build.xml View File

@@ -4,11 +4,17 @@
<import file="../build-common.xml"/>
<import file="../bridge/build.xml"/>
<import file="../util/build.xml"/>
<import file="../runtime/build.xml"/>


<path id="testing-util.test.src.path">
<fileset dir="${basedir}/../lib">
<include name="junit/*.jar"/>
<include name="bcel/*.jar"/>
</fileset>
<!-- depends on weaver to use Dissasemble feature on LazyClassGen to test comparison of .class file -->
<pathelement path="../weaver/bin"/>
<pathelement path="../runtime/bin"/>
<path refid="testing-util.src.path"/>
</path>

@@ -30,8 +36,10 @@
<testcompile project="testing-util" path="testing-util.test.src.path"/>
</target>

<!-- FIXME: seems to depend on weaver, seems to emit warnings -->
<target name="test" depends="test:compile">
<target name="test" depends="test:compile,
runtime.compile">
<!-- depends on weaver to access .class dissassemble utility hence circular -->
<subant antfile="build.xml" target="test:compile" buildpath="../weaver" />
<testrun project="testing-util" path="testing-util.test.src.path" suite="TestingUtilModuleTests"/>
</target>


BIN
testing-util/testdata/testCompareClassFiles/org/aspectj/testingutil/TestCompareClassFile$1.class View File


BIN
testing-util/testdata/testCompareClassFiles/org/aspectj/testingutil/TestCompareClassFile.class View File


+ 1
- 0
testing-util/testdata/testCompareClassFiles/org/aspectj/testingutil/readme.txt View File

@@ -0,0 +1 @@
AV - should be added to CVS since I have renamed old files

+ 2
- 2
testing-util/testsrc/org/aspectj/testingutil/TestUtilTest.java View File

@@ -34,7 +34,7 @@ public class TestUtilTest extends TestCase {
public void testFileCompareNonClass() throws IOException {
MessageHandler holder = new MessageHandler();
File thisFile = new File(UtilTests.TESTING_UTIL_PATH + "/testsrc/org/aspectj/testing/util/TestUtilTest.java");
File thisFile = new File(UtilTests.TESTING_UTIL_PATH + "/testsrc/org/aspectj/testingutil/TestUtilTest.java");
//File thisFile = new File("src/testing-util.lst");
assertTrue(TestUtil.sameFiles(holder, thisFile, thisFile));
@@ -100,7 +100,7 @@ public class TestUtilTest extends TestCase {
}
MessageHandler holder = new MessageHandler();
File classBase = new File(UtilTests.TESTING_UTIL_PATH + "/testdata/testCompareClassFiles");
String path = "org/aspectj/testing/util/TestCompareClassFile.class";
String path = "org/aspectj/testingutil/TestCompareClassFile.class";
File classFile = new File(classBase, path);
try {

+ 5
- 1
testing/src/org/aspectj/testing/run/RunStatus.java View File

@@ -277,7 +277,11 @@ public class RunStatus implements IRunStatus {
public boolean isIgnoring(IMessage.Kind kind) {
return messageHolder.isIgnoring(kind);
}

public void dontIgnore(IMessage.Kind kind) {
;
}

/**
* @see org.aspectj.bridge.IMessageHolder#hasAnyMessage(Kind, boolean)
*/

+ 4
- 0
testing/testsrc/org/aspectj/testing/taskdefs/AjcTaskCompileCommandTest.java View File

@@ -134,6 +134,10 @@ public class AjcTaskCompileCommandTest extends TestCase {
public boolean isIgnoring(IMessage.Kind kind) {
return false;
}

public void dontIgnore(IMessage.Kind kind) {
;
}
});
String[] parms = (String[]) args.toArray(new String[0]);
boolean result = command.runCommand(parms, handler);

+ 1
- 0
tests/build.xml View File

@@ -79,6 +79,7 @@
<testrun project="tests" path="tests.test.src.path" suite="org.aspectj.systemtest.AllTests"/>
</target>

<!-- run a single test with "ant -Dtest=org.aspectj.systemtest.AllTests15 atest" -->
<target name="atest" depends="test:compile,
runtime.compile,
weaver.compile">

+ 4
- 2
tests/java5/ataspectj/ataspectj/IfPointcutTest.java View File

@@ -52,10 +52,12 @@ public class IfPointcutTest extends TestCase {
return (i>=0);
}

@Pointcut("args(i) && if(i>0)")
//FIXME av if pcd support
//@Pointcut("args(i) && if(i>0)")
void ifPc(int i) {}

@Before("execution(* ataspectj.IfPointcutTest.hello(int)) && ifPc(i)")
//FIXME av if pcd support
//@Before("execution(* ataspectj.IfPointcutTest.hello(int)) && ifPc(i)")
void before(int i) {
System.out.println("IfPointcutTest$TestAspect.before");
}

+ 1
- 1
tests/java5/ataspectj/ataspectj/PrecedenceTest.java View File

@@ -39,7 +39,7 @@ public class PrecedenceTest extends TestCase {
public void testPrecedence() {
s_log = new StringBuffer();
hello();
assertEquals("TestAspect_3 TestAspect_2 TestAspect_1 hello", s_log.toString());
assertEquals("TestAspect_3 TestAspect_2 TestAspect_1 hello ", s_log.toString());
}



+ 1
- 1
tests/src/org/aspectj/systemtest/AllTests15.java View File

@@ -14,7 +14,7 @@ public class AllTests15 {
TestSuite suite = new TestSuite("AspectJ System Test Suite - JDK 1.5");
//$JUnit-BEGIN$
suite.addTest(AllTests14.suite());
suite.addTestSuite(AllTestsAspectJ150_NeedJava15.class);
suite.addTest(AllTestsAspectJ150_NeedJava15.suite());
//$JUnit-END$
return suite;
}

+ 2
- 1
tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150_NeedJava15.java View File

@@ -12,6 +12,7 @@ package org.aspectj.systemtest.ajc150;

import junit.framework.Test;
import junit.framework.TestSuite;
import junit.framework.TestCase;
import org.aspectj.systemtest.ajc150.ataspectj.AtAjc150Tests;

/**
@@ -27,7 +28,7 @@ public class AllTestsAspectJ150_NeedJava15 {
suite.addTestSuite(Annotations.class);
suite.addTestSuite(AnnotationBinding.class);
//ATAJ tests
//ATAeJ tests
suite.addTest(AtAjc150Tests.suite());

//$JUnit-END$

+ 8
- 6
weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java View File

@@ -87,8 +87,9 @@ public class Aj5Attributes {
ISourceContext context;
IMessageHandler handler;

public AjAttributeStruct(ResolvedTypeX type) {
public AjAttributeStruct(ResolvedTypeX type, ISourceContext sourceContext) {
enclosingType = type;
context = sourceContext;
}
}

@@ -107,8 +108,8 @@ public class Aj5Attributes {

Method method;

public AjAttributeMethodStruct(Method method, ResolvedTypeX type) {
super(type);
public AjAttributeMethodStruct(Method method, ResolvedTypeX type, ISourceContext sourceContext) {
super(type, sourceContext);
this.method = method;
}

@@ -140,7 +141,7 @@ public class Aj5Attributes {
* @return list of AjAttributes
*/
public static List readAj5ClassAttributes(JavaClass javaClass, ResolvedTypeX type, ISourceContext context,IMessageHandler msgHandler) {
AjAttributeStruct struct = new AjAttributeStruct(type);
AjAttributeStruct struct = new AjAttributeStruct(type, context);
Attribute[] attributes = javaClass.getAttributes();
for (int i = 0; i < attributes.length; i++) {
Attribute attribute = attributes[i];
@@ -158,7 +159,8 @@ public class Aj5Attributes {
//TODO can that be too slow ?
for (int m = 0; m < javaClass.getMethods().length; m++) {
Method method = javaClass.getMethods()[m];
AjAttributeMethodStruct mstruct = new AjAttributeMethodStruct(method, type);
//TODO optimize, this method struct will gets recreated for advice extraction
AjAttributeMethodStruct mstruct = new AjAttributeMethodStruct(method, type, context);
Attribute[] mattributes = method.getAttributes();

for (int i = 0; i < mattributes.length; i++) {
@@ -184,7 +186,7 @@ public class Aj5Attributes {
* @return list of AjAttributes
*/
public static List readAj5MethodAttributes(Method method, ResolvedTypeX type, ISourceContext context,IMessageHandler msgHandler) {
AjAttributeMethodStruct struct = new AjAttributeMethodStruct(method, type);
AjAttributeMethodStruct struct = new AjAttributeMethodStruct(method, type, context);
Attribute[] attributes = method.getAttributes();

for (int i = 0; i < attributes.length; i++) {

+ 4
- 1
weaver/src/org/aspectj/weaver/bcel/BcelMethod.java View File

@@ -36,7 +36,10 @@ import org.aspectj.weaver.ataspectj.Aj5Attributes;

final class BcelMethod extends ResolvedMember {

private Method method;
Method method;
public int foo() {
return method.getLineNumberTable().getLineNumberTable()[0].getLineNumber();//getSourceLine(0);
}
private boolean isAjSynthetic;
private ShadowMunger associatedShadowMunger;
private AjAttribute.EffectiveSignatureAttribute effectiveSignature;

+ 5
- 0
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java View File

@@ -66,6 +66,7 @@ import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.WeaverMetrics;
import org.aspectj.weaver.WeaverStateInfo;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.AndPointcut;
import org.aspectj.weaver.patterns.BindingAnnotationTypePattern;
import org.aspectj.weaver.patterns.BindingTypePattern;
@@ -1282,4 +1283,8 @@ public class BcelWeaver implements IWeaver {
public boolean isReweavable() {
return inReweavableMode;
}

public World getWorld() {
return world;
}
}

+ 4
- 0
weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java View File

@@ -99,6 +99,10 @@ public class AnnotationPatternMatchingTestCase extends TestCase {
return false;
}
public boolean isIgnoring(Kind kind) {return false;}

public void dontIgnore(IMessage.Kind kind) {
;
}
}
public void testReferenceToNonAnnotationType() {

Loading…
Cancel
Save