aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Clement <andrew.clement@gmail.com>2012-04-02 14:15:08 -0700
committerAndy Clement <andrew.clement@gmail.com>2012-04-02 14:15:08 -0700
commit096b004fda4d21cca0e1ee4c776e5824715d0ecd (patch)
tree1b56bf3e3ba31d909df8822f9ef7093166916c19
parentf85631fd2fb2e0f3213abb9c5a7cd86eec2c9ab5 (diff)
downloadaspectj-096b004fda4d21cca0e1ee4c776e5824715d0ecd.tar.gz
aspectj-096b004fda4d21cca0e1ee4c776e5824715d0ecd.zip
375881
-rw-r--r--loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java291
-rw-r--r--org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicTokenSource.java2
-rw-r--r--tests/bugs170/xmldefs/Anno.classbin0 -> 128 bytes
-rw-r--r--tests/bugs170/xmldefs/Anno.java5
-rw-r--r--tests/bugs170/xmldefs/Anno2.java5
-rw-r--r--tests/bugs170/xmldefs/Anno4.java25
-rw-r--r--tests/bugs170/xmldefs/Anno5.java37
-rw-r--r--tests/bugs170/xmldefs/Anno6.java9
-rw-r--r--tests/bugs170/xmldefs/AnnoBoolean.classbin0 -> 220 bytes
-rw-r--r--tests/bugs170/xmldefs/AnnoClass.classbin0 -> 267 bytes
-rw-r--r--tests/bugs170/xmldefs/AnnoLong.classbin0 -> 225 bytes
-rw-r--r--tests/bugs170/xmldefs/AnnoString.classbin0 -> 238 bytes
-rw-r--r--tests/bugs170/xmldefs/Foo.classbin0 -> 2300 bytes
-rw-r--r--tests/bugs170/xmldefs/Foo.java3
-rw-r--r--tests/bugs170/xmldefs/Hello.java36
-rw-r--r--tests/bugs170/xmldefs/Hello2.java27
-rw-r--r--tests/bugs170/xmldefs/Hello4.java42
-rw-r--r--tests/bugs170/xmldefs/Hello5.java42
-rw-r--r--tests/bugs170/xmldefs/Hello6.java41
-rw-r--r--tests/bugs170/xmldefs/aop.xml13
-rw-r--r--tests/bugs170/xmldefs/aop2.xml13
-rw-r--r--tests/bugs170/xmldefs/aop3.xml13
-rw-r--r--tests/bugs170/xmldefs/aop4.xml17
-rw-r--r--tests/bugs170/xmldefs/aop5.xml18
-rw-r--r--tests/bugs170/xmldefs/aop6.xml13
-rw-r--r--tests/bugs170/xmldefs/aop6a.xml13
-rw-r--r--tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java38
-rw-r--r--tests/src/org/aspectj/systemtest/ajc170/ajc170.xml100
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java4
-rw-r--r--weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java18
-rw-r--r--weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java27
31 files changed, 843 insertions, 9 deletions
diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java b/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java
index bab276699..bc6695e3e 100644
--- a/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java
+++ b/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java
@@ -21,8 +21,10 @@ import java.util.List;
import java.util.Map;
import org.aspectj.apache.bcel.Constants;
+import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
+import org.aspectj.apache.bcel.classfile.annotation.ClassElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
@@ -36,6 +38,7 @@ import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.Message;
+import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.GeneratedReferenceTypeDelegate;
import org.aspectj.weaver.ReferenceType;
@@ -50,7 +53,14 @@ import org.aspectj.weaver.bcel.LazyClassGen;
import org.aspectj.weaver.bcel.LazyMethodGen;
import org.aspectj.weaver.loadtime.definition.Definition;
import org.aspectj.weaver.loadtime.definition.Definition.AdviceKind;
+import org.aspectj.weaver.loadtime.definition.Definition.DeclareAnnotationKind;
import org.aspectj.weaver.loadtime.definition.Definition.PointcutAndAdvice;
+import org.aspectj.weaver.patterns.BasicTokenSource;
+import org.aspectj.weaver.patterns.DeclareAnnotation;
+import org.aspectj.weaver.patterns.ISignaturePattern;
+import org.aspectj.weaver.patterns.ITokenSource;
+import org.aspectj.weaver.patterns.NamePattern;
+import org.aspectj.weaver.patterns.PatternParser;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.PerSingleton;
@@ -134,6 +144,11 @@ public class ConcreteAspectCodeGen {
isValid = true;
return true;
}
+
+ if (concreteAspect.declareAnnotations.size()!=0) {
+ isValid = true;
+ return true;
+ }
// it can happen that extends is null, for precedence only declaration
if (concreteAspect.extend == null && concreteAspect.precedence != null) {
@@ -471,6 +486,13 @@ public class ConcreteAspectCodeGen {
adviceCounter++;
}
}
+
+ if (concreteAspect.declareAnnotations.size()>0) {
+ int decCounter = 1;
+ for (Definition.DeclareAnnotation da: concreteAspect.declareAnnotations) {
+ generateDeclareAnnotation(da,decCounter++,cg);
+ }
+ }
// handle the perClause
ReferenceType rt = new ReferenceType(ResolvedType.forName(concreteAspect.name).getSignature(), world);
@@ -492,6 +514,275 @@ public class ConcreteAspectCodeGen {
}
/**
+ * The DeclareAnnotation object encapsulates an method/field/type descriptor and an annotation. This uses a DeclareAnnotation object
+ * captured from the XML (something like '<declare-annotation field="* field1(..)" annotation="@Annot(a='a',fred=false,'abc')"/>')
+ * and builds the same construct that would have existed if the code style variant was used. This involves creating a member upon
+ * which to hang the real annotation and then creating a classfile level attribute indicating a declare annotation is present
+ * (that includes the signature pattern and a pointer to the real member holding the annotation).
+ *
+ */
+ private void generateDeclareAnnotation(Definition.DeclareAnnotation da, int decCounter, LazyClassGen cg) {
+
+ // Here is an example member from a code style declare annotation:
+ //void ajc$declare_at_method_1();
+ // RuntimeInvisibleAnnotations: length = 0x6
+ // 00 01 00 1B 00 00
+ // RuntimeVisibleAnnotations: length = 0x15
+ // 00 01 00 1D 00 03 00 1E 73 00 1F 00 20 73 00 21
+ // 00 22 73 00 23
+ // org.aspectj.weaver.MethodDeclarationLineNumber: length = 0x8
+ // 00 00 00 02 00 00 00 16
+ // org.aspectj.weaver.AjSynthetic: length = 0x
+ //
+ // Code:
+ // Stack=0, Locals=1, Args_size=1
+ // 0: return
+
+ // and at the class level a Declare attribute:
+ // org.aspectj.weaver.Declare: length = 0x51
+ // 05 00 00 00 03 01 00 05 40 41 6E 6E 6F 01 00 17
+ // 61 6A 63 24 64 65 63 6C 61 72 65 5F 61 74 5F 6D
+ // 65 74 68 6F 64 5F 31 01 01 00 00 00 00 05 05 00
+ // 08 73 61 79 48 65 6C 6C 6F 00 01 04 00 00 00 00
+ // 07 00 00 00 27 00 00 00 34 00 00 00 16 00 00 00
+ // 3C
+
+ AnnotationAJ constructedAnnotation = buildDeclareAnnotation_actualAnnotation(cg, da);
+ if (constructedAnnotation==null) {
+ return; // error occurred (and was reported), do not continue
+ }
+ if (da.declareAnnotationKind==DeclareAnnotationKind.Method || da.declareAnnotationKind==DeclareAnnotationKind.Field) {
+ String declareName = new StringBuilder("ajc$declare_at_").append(da.declareAnnotationKind==DeclareAnnotationKind.Method?"method":"field").append("_").append(decCounter).toString();
+ LazyMethodGen declareMethod = new LazyMethodGen(Modifier.PUBLIC, Type.VOID, declareName, Type.NO_ARGS, EMPTY_STRINGS, cg);
+ InstructionList declareMethodBody = declareMethod.getBody();
+ declareMethodBody.append(InstructionFactory.RETURN);
+ declareMethod.addAnnotation(constructedAnnotation);
+
+ ITokenSource tokenSource = BasicTokenSource.makeTokenSource(da.pattern,null);
+ PatternParser pp = new PatternParser(tokenSource);
+ ISignaturePattern isp = (da.declareAnnotationKind==DeclareAnnotationKind.Method?pp.parseCompoundMethodOrConstructorSignaturePattern(true):pp.parseCompoundFieldSignaturePattern());
+ DeclareAnnotation deca = new DeclareAnnotation(da.declareAnnotationKind==DeclareAnnotationKind.Method?DeclareAnnotation.AT_METHOD:DeclareAnnotation.AT_FIELD, isp);
+ deca.setAnnotationMethod(declareName);
+ deca.setAnnotationString(da.annotation);
+ AjAttribute attribute = new AjAttribute.DeclareAttribute(deca);
+ cg.addAttribute(attribute);
+ cg.addMethodGen(declareMethod);
+ }
+ }
+
+ /**
+ * Construct the annotation that the declare wants to add to the target.
+ */
+ private AnnotationAJ buildDeclareAnnotation_actualAnnotation(LazyClassGen cg, Definition.DeclareAnnotation da) {
+ AnnotationGen anno = buildAnnotationFromString(cg.getConstantPool(),cg.getWorld(),da.annotation);
+ if (anno==null) {
+ return null;
+ } else {
+ AnnotationAJ bcelAnnotation = new BcelAnnotation(anno, world);
+ return bcelAnnotation;
+ }
+ }
+
+ // TODO support array values
+ // TODO support annotation values
+ /**
+ * Build an AnnotationGen object based on a string, for example "@Foo(35,message='string')". Notice single quotes are fine for
+ * strings as they don't need special handling in the XML.
+ */
+ private AnnotationGen buildAnnotationFromString(ConstantPool cp, World w, String annotationString) {
+ int paren = annotationString.indexOf('(');
+ if (paren==-1) {
+ // the easy case, no values
+ AnnotationGen aaj = buildBaseAnnotationType(cp,world,annotationString);
+ return aaj;
+ } else {
+ // Discover the name and name/value pairs
+ String name = annotationString.substring(0,paren);
+ // break the rest into pieces based on the commas
+ List<String> values = new ArrayList<String>();
+ int pos = paren+1;
+ int depth = 0;
+ int len = annotationString.length();
+ int start = pos;
+ while (pos<len) {
+ char ch = annotationString.charAt(pos);
+ if (ch==')' && depth==0) {
+ break; // reached the end
+ }
+ if (ch=='(' || ch=='[') {
+ depth++;
+ } else if (ch==')' || ch==']') {
+ depth--;
+ }
+ if (ch==',' && depth==0) {
+ // found a comma at the right level to end a name/value pair
+ values.add(annotationString.substring(start,pos).trim());
+ start=pos+1;
+ }
+ pos++;
+ }
+ if (start != pos) {
+ // there is a last bit to add
+ values.add(annotationString.substring(start,pos).trim());
+ }
+ AnnotationGen aaj = buildBaseAnnotationType(cp,world,name);
+ if (aaj==null) {
+ return null; // a check failed
+ }
+ String typename = aaj.getTypeName();
+ ResolvedType type = UnresolvedType.forName(typename).resolve(world); // shame it isn't retrievable from the anno
+ ResolvedMember[] rms = type.getDeclaredMethods();
+ // Add the values
+ for (String value: values) {
+ int equalsIndex = value.indexOf("=");
+ String key = "value";
+ if (value.charAt(0)!='\"' && equalsIndex!=-1) {
+ key = value.substring(0,equalsIndex).trim();
+ value = value.substring(equalsIndex+1).trim();
+ }
+ boolean keyIsOk = false;
+ for (int m=0;m<rms.length;m++) {
+ NameValuePair nvp = null;
+ if (rms[m].getName().equals(key)) {
+ // found it!
+ keyIsOk=true;
+ UnresolvedType rt = rms[m].getReturnType();
+ if (rt.isPrimitiveType()) {
+ switch (rt.getSignature().charAt(0)) {
+ case 'J': // long
+ try {
+ long longValue = Long.parseLong(value);
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.PRIMITIVE_LONG,cp,longValue),cp);
+ } catch (NumberFormatException nfe) {
+ reportError("unable to interpret annotation value '"+value+"' as a long");
+ return null;
+ }
+ break;
+ case 'S': // short
+ try {
+ short shortValue = Short.parseShort(value);
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.PRIMITIVE_SHORT,cp,shortValue),cp);
+ } catch (NumberFormatException nfe) {
+ reportError("unable to interpret annotation value '"+value+"' as a short");
+ return null;
+ }
+ break;
+ case 'F': // float
+ try {
+ float floatValue = Float.parseFloat(value);
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.PRIMITIVE_FLOAT,cp,floatValue),cp);
+ } catch (NumberFormatException nfe) {
+ reportError("unable to interpret annotation value '"+value+"' as a float");
+ return null;
+ }
+ break;
+ case 'D': // double
+ try {
+ double doubleValue = Double.parseDouble(value);
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.PRIMITIVE_DOUBLE,cp,doubleValue),cp);
+ } catch (NumberFormatException nfe) {
+ reportError("unable to interpret annotation value '"+value+"' as a double");
+ return null;
+ }
+ break;
+ case 'I': // integer
+ try {
+ int intValue = Integer.parseInt(value);
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.PRIMITIVE_INT,cp,intValue),cp);
+ } catch (NumberFormatException nfe) {
+ reportError("unable to interpret annotation value '"+value+"' as an integer");
+ return null;
+ }
+ break;
+ case 'B': // byte
+ try {
+ byte byteValue = Byte.parseByte(value);
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.PRIMITIVE_BYTE,cp,byteValue),cp);
+ } catch (NumberFormatException nfe) {
+ reportError("unable to interpret annotation value '"+value+"' as a byte");
+ return null;
+ }
+ break;
+ case 'C': // char
+ if (value.length()<2) {
+ reportError("unable to interpret annotation value '"+value+"' as a char");
+ return null;
+ }
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.PRIMITIVE_CHAR,cp,value.charAt(1)),cp);
+ break;
+ case 'Z': // boolean
+ try {
+ boolean booleanValue = Boolean.parseBoolean(value);
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.PRIMITIVE_BOOLEAN,cp,booleanValue),cp);
+ } catch (NumberFormatException nfe) {
+ reportError("unable to interpret annotation value '"+value+"' as a boolean");
+ return null;
+ }
+ break;
+ default:
+ reportError("not yet supporting XML setting of annotation values of type "+rt.getName());
+ return null;
+ }
+ } else if (UnresolvedType.JL_STRING.equals(rt)) {
+ if (value.length()<2) {
+ reportError("Invalid string value specified in annotation string: "+annotationString);
+ return null;
+ }
+ value = value.substring(1,value.length()-1); // trim the quotes off
+ nvp = new NameValuePair(key,new SimpleElementValue(ElementValue.STRING,cp,value),cp);
+ } else if (UnresolvedType.JL_CLASS.equals(rt)) {
+ // format of class string:
+ // Foo.class
+ // java.lang.Foo.class
+ if (value.length()<6) {
+ reportError("Not a well formed class value for an annotation '"+value+"'");
+ return null;
+ }
+ String clazz = value.substring(0,value.length()-6);
+ boolean qualified = clazz.indexOf(".")!=-1;
+ if (!qualified) {
+ // if not qualified, have to assume java.lang
+ clazz = "java.lang."+clazz;
+ }
+ nvp = new NameValuePair(key,new ClassElementValue(new ObjectType(clazz),cp),cp);
+ }
+ }
+ if (nvp!=null) {
+ aaj.addElementNameValuePair(nvp);
+ }
+ }
+ if (!keyIsOk) {
+ reportError("annotation @"+typename+" does not have a value named "+key);
+ return null;
+ }
+ }
+ return aaj;
+ }
+ }
+
+ private AnnotationGen buildBaseAnnotationType(ConstantPool cp,World world, String typename) {
+ String annoname = typename;
+ if (annoname.startsWith("@")) {
+ annoname= annoname.substring(1);
+ }
+ ResolvedType annotationType = UnresolvedType.forName(annoname).resolve(world);
+ if (!annotationType.isAnnotation()) {
+ reportError("declare is not specifying an annotation type :"+typename);
+ return null;
+ }
+ if (!annotationType.isAnnotationWithRuntimeRetention()) {
+ reportError("declare is using an annotation type that does not have runtime retention: "+typename);
+ return null;
+ }
+ List<NameValuePair> elems = new ArrayList<NameValuePair>();
+ return new AnnotationGen(new ObjectType(annoname), elems, true, cp);
+ }
+
+ /**
+ * Construct the annotation that indicates this is a declare
+ */
+
+ /**
* The PointcutAndAdvice object encapsulates an advice kind, a pointcut and names a Java method in a particular class. Generate
* an annotation style advice that has that pointcut whose implementation delegates to the Java method.
*/
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicTokenSource.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicTokenSource.java
index 37bc7eda1..9e2a62618 100644
--- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicTokenSource.java
+++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/BasicTokenSource.java
@@ -80,7 +80,7 @@ public class BasicTokenSource implements ITokenSource {
//////////////////////////////////////////////////////
// Convenience, maybe just for testing
- static ITokenSource makeTokenSource(String input, ISourceContext context) {
+ public static ITokenSource makeTokenSource(String input, ISourceContext context) {
char[] chars = input.toCharArray();
int i = 0;
diff --git a/tests/bugs170/xmldefs/Anno.class b/tests/bugs170/xmldefs/Anno.class
new file mode 100644
index 000000000..6e378d760
--- /dev/null
+++ b/tests/bugs170/xmldefs/Anno.class
Binary files differ
diff --git a/tests/bugs170/xmldefs/Anno.java b/tests/bugs170/xmldefs/Anno.java
new file mode 100644
index 000000000..7bb1cb2aa
--- /dev/null
+++ b/tests/bugs170/xmldefs/Anno.java
@@ -0,0 +1,5 @@
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Anno {
+}
diff --git a/tests/bugs170/xmldefs/Anno2.java b/tests/bugs170/xmldefs/Anno2.java
new file mode 100644
index 000000000..f5dfcb99f
--- /dev/null
+++ b/tests/bugs170/xmldefs/Anno2.java
@@ -0,0 +1,5 @@
+import java.lang.annotation.*;
+
+// deliberately wrong retention
+public @interface Anno2 {
+}
diff --git a/tests/bugs170/xmldefs/Anno4.java b/tests/bugs170/xmldefs/Anno4.java
new file mode 100644
index 000000000..ebff22092
--- /dev/null
+++ b/tests/bugs170/xmldefs/Anno4.java
@@ -0,0 +1,25 @@
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoString {
+ String value() default "xyz";
+ String sss() default "xyz";
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoLong {
+ long value() default 111L;
+ long jjj() default 111L;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoBoolean {
+ boolean value() default false;
+ boolean zzz() default false;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoClass {
+ Class value() default String.class;
+ Class ccc() default String.class;
+}
diff --git a/tests/bugs170/xmldefs/Anno5.java b/tests/bugs170/xmldefs/Anno5.java
new file mode 100644
index 000000000..5906bcaa1
--- /dev/null
+++ b/tests/bugs170/xmldefs/Anno5.java
@@ -0,0 +1,37 @@
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoShort {
+ short value() default 3;
+ short sss() default 3;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoDouble {
+ double value() default 3.0d;
+ double ddd() default 3.0d;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoFloat {
+ float value() default 4.0f;
+ float fff() default 4.0f;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoChar {
+ char value() default 'a';
+ char ccc() default 'a';
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoByte {
+ byte value() default 66;
+ byte bbb() default 66;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface AnnoInt {
+ int value() default 111;
+ int iii() default 111;
+}
diff --git a/tests/bugs170/xmldefs/Anno6.java b/tests/bugs170/xmldefs/Anno6.java
new file mode 100644
index 000000000..18d8f544b
--- /dev/null
+++ b/tests/bugs170/xmldefs/Anno6.java
@@ -0,0 +1,9 @@
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Annot {
+ char a();
+ boolean fred();
+ String value();
+}
+
diff --git a/tests/bugs170/xmldefs/AnnoBoolean.class b/tests/bugs170/xmldefs/AnnoBoolean.class
new file mode 100644
index 000000000..33b76156a
--- /dev/null
+++ b/tests/bugs170/xmldefs/AnnoBoolean.class
Binary files differ
diff --git a/tests/bugs170/xmldefs/AnnoClass.class b/tests/bugs170/xmldefs/AnnoClass.class
new file mode 100644
index 000000000..4071d56d6
--- /dev/null
+++ b/tests/bugs170/xmldefs/AnnoClass.class
Binary files differ
diff --git a/tests/bugs170/xmldefs/AnnoLong.class b/tests/bugs170/xmldefs/AnnoLong.class
new file mode 100644
index 000000000..a7990fbad
--- /dev/null
+++ b/tests/bugs170/xmldefs/AnnoLong.class
Binary files differ
diff --git a/tests/bugs170/xmldefs/AnnoString.class b/tests/bugs170/xmldefs/AnnoString.class
new file mode 100644
index 000000000..ba0e8eaf7
--- /dev/null
+++ b/tests/bugs170/xmldefs/AnnoString.class
Binary files differ
diff --git a/tests/bugs170/xmldefs/Foo.class b/tests/bugs170/xmldefs/Foo.class
new file mode 100644
index 000000000..eaa12c965
--- /dev/null
+++ b/tests/bugs170/xmldefs/Foo.class
Binary files differ
diff --git a/tests/bugs170/xmldefs/Foo.java b/tests/bugs170/xmldefs/Foo.java
new file mode 100644
index 000000000..2edbdabfd
--- /dev/null
+++ b/tests/bugs170/xmldefs/Foo.java
@@ -0,0 +1,3 @@
+public aspect Foo {
+ declare @method: * sayHello(..): @Anno;
+}
diff --git a/tests/bugs170/xmldefs/Hello.java b/tests/bugs170/xmldefs/Hello.java
new file mode 100644
index 000000000..fdf29eab3
--- /dev/null
+++ b/tests/bugs170/xmldefs/Hello.java
@@ -0,0 +1,36 @@
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+public class Hello {
+
+ public static void main(String[] args) {
+ sayHello();
+ printAnnos("sayHello");
+ }
+
+ public static void sayHello() {
+ System.out.println("Hello");
+ sayWorld();
+ }
+
+ public static int sayWorld() {
+ System.out.println("World");
+ return 0;
+ }
+
+ public static void printAnnos(String methodname) {
+ try {
+ Method m = Hello.class.getDeclaredMethod(methodname);
+ Annotation[] annos = m.getAnnotations();
+ System.out.println("Annotations on "+methodname+"? "+(annos!=null && annos.length!=0));
+ if (annos!=null && annos.length>0) {
+ System.out.println("Annotation count is "+annos.length);
+ for (Annotation anno: annos) {
+ System.out.println(anno);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/tests/bugs170/xmldefs/Hello2.java b/tests/bugs170/xmldefs/Hello2.java
new file mode 100644
index 000000000..9fa6a4a9a
--- /dev/null
+++ b/tests/bugs170/xmldefs/Hello2.java
@@ -0,0 +1,27 @@
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+public class Hello2 {
+
+ public static int i;
+
+ public static void main(String[] args) {
+ printAnnos("i");
+ }
+
+ public static void printAnnos(String fieldname) {
+ try {
+ Field m = Hello2.class.getDeclaredField(fieldname);
+ Annotation[] annos = m.getAnnotations();
+ System.out.println("Annotations on "+fieldname+"? "+(annos!=null && annos.length!=0));
+ if (annos!=null && annos.length>0) {
+ System.out.println("Annotation count is "+annos.length);
+ for (Annotation anno: annos) {
+ System.out.println(anno);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/tests/bugs170/xmldefs/Hello4.java b/tests/bugs170/xmldefs/Hello4.java
new file mode 100644
index 000000000..7f7c6183b
--- /dev/null
+++ b/tests/bugs170/xmldefs/Hello4.java
@@ -0,0 +1,42 @@
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.*;
+public class Hello4 {
+
+ public static int field1;
+ public static int field2;
+
+ public static void main(String[] args) {
+ printAnnos("field1");
+ printAnnos("field2");
+ }
+
+ public static void printAnnos(String fieldname) {
+ try {
+ Field m = Hello4.class.getDeclaredField(fieldname);
+ Annotation[] annos = m.getAnnotations();
+ System.out.println("Annotations on "+fieldname+"? "+(annos!=null && annos.length!=0));
+ if (annos!=null && annos.length>0) {
+ List<Annotation> la = new ArrayList<Annotation>();
+ for (Annotation anno: annos) {
+ la.add(anno);
+ }
+ Collections.<Annotation>sort(la,new AnnoComparator());
+
+ System.out.println("Annotation count is "+annos.length);
+ for (Annotation anno: la) {
+ System.out.println(anno);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ static class AnnoComparator implements Comparator<Annotation> {
+ public int compare(Annotation a, Annotation b) {
+ return a.toString().compareTo(b.toString());
+ }
+ }
+}
diff --git a/tests/bugs170/xmldefs/Hello5.java b/tests/bugs170/xmldefs/Hello5.java
new file mode 100644
index 000000000..361415a3e
--- /dev/null
+++ b/tests/bugs170/xmldefs/Hello5.java
@@ -0,0 +1,42 @@
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.*;
+public class Hello5 {
+
+ public static int field1;
+ public static int field2;
+
+ public static void main(String[] args) {
+ printAnnos("field1");
+ printAnnos("field2");
+ }
+
+ public static void printAnnos(String fieldname) {
+ try {
+ Field m = Hello5.class.getDeclaredField(fieldname);
+ Annotation[] annos = m.getAnnotations();
+ System.out.println("Annotations on "+fieldname+"? "+(annos!=null && annos.length!=0));
+ if (annos!=null && annos.length>0) {
+ List<Annotation> la = new ArrayList<Annotation>();
+ for (Annotation anno: annos) {
+ la.add(anno);
+ }
+ Collections.<Annotation>sort(la,new AnnoComparator());
+
+ System.out.println("Annotation count is "+annos.length);
+ for (Annotation anno: la) {
+ System.out.println(anno);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ static class AnnoComparator implements Comparator<Annotation> {
+ public int compare(Annotation a, Annotation b) {
+ return a.toString().compareTo(b.toString());
+ }
+ }
+}
diff --git a/tests/bugs170/xmldefs/Hello6.java b/tests/bugs170/xmldefs/Hello6.java
new file mode 100644
index 000000000..568a5b46e
--- /dev/null
+++ b/tests/bugs170/xmldefs/Hello6.java
@@ -0,0 +1,41 @@
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.*;
+
+public class Hello6 {
+
+ public static int field1;
+
+ public static void main(String[] args) {
+ printAnnos("field1");
+ }
+
+ public static void printAnnos(String fieldname) {
+ try {
+ Field m = Hello6.class.getDeclaredField(fieldname);
+ Annotation[] annos = m.getAnnotations();
+ System.out.println("Annotations on "+fieldname+"? "+(annos!=null && annos.length!=0));
+ if (annos!=null && annos.length>0) {
+ List<Annotation> la = new ArrayList<Annotation>();
+ for (Annotation anno: annos) {
+ la.add(anno);
+ }
+ Collections.<Annotation>sort(la,new AnnoComparator());
+
+ System.out.println("Annotation count is "+annos.length);
+ for (Annotation anno: la) {
+ System.out.println(anno);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ static class AnnoComparator implements Comparator<Annotation> {
+ public int compare(Annotation a, Annotation b) {
+ return a.toString().compareTo(b.toString());
+ }
+ }
+}
diff --git a/tests/bugs170/xmldefs/aop.xml b/tests/bugs170/xmldefs/aop.xml
new file mode 100644
index 000000000..afa85168b
--- /dev/null
+++ b/tests/bugs170/xmldefs/aop.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aspectj>
+ <aspects>
+ <concrete-aspect name="ConjuredUp">
+ <declare-annotation method="* Hello.sayHello(..)" annotation="@Anno"/>
+ </concrete-aspect>
+ </aspects>
+
+ <weaver options="-Xreweavable -verbose -XlazyTjp -showWeaveInfo">
+ <include within="Hello"/>
+ </weaver>
+</aspectj>
+
diff --git a/tests/bugs170/xmldefs/aop2.xml b/tests/bugs170/xmldefs/aop2.xml
new file mode 100644
index 000000000..d5ebdf7af
--- /dev/null
+++ b/tests/bugs170/xmldefs/aop2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aspectj>
+ <aspects>
+ <concrete-aspect name="ConjuredUp">
+ <declare-annotation method="* Hello.sayHello(..)" annotation="@Anno2"/>
+ </concrete-aspect>
+ </aspects>
+
+ <weaver options="-Xreweavable -verbose -XlazyTjp -showWeaveInfo">
+ <include within="Hello"/>
+ </weaver>
+</aspectj>
+
diff --git a/tests/bugs170/xmldefs/aop3.xml b/tests/bugs170/xmldefs/aop3.xml
new file mode 100644
index 000000000..a65a552ed
--- /dev/null
+++ b/tests/bugs170/xmldefs/aop3.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aspectj>
+ <aspects>
+ <concrete-aspect name="ConjuredUp">
+ <declare-annotation field="* i" annotation="@Anno"/>
+ </concrete-aspect>
+ </aspects>
+
+ <weaver options="-Xreweavable -verbose -XlazyTjp -showWeaveInfo">
+ <include within="Hello2"/>
+ </weaver>
+</aspectj>
+
diff --git a/tests/bugs170/xmldefs/aop4.xml b/tests/bugs170/xmldefs/aop4.xml
new file mode 100644
index 000000000..1cf61807b
--- /dev/null
+++ b/tests/bugs170/xmldefs/aop4.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aspectj>
+ <aspects>
+ <concrete-aspect name="ConjuredUp">
+ <declare-annotation field="* field1(..)" annotation="@AnnoString(&quot;set from xml&quot;)"/>
+ <declare-annotation field="* field1(..)" annotation="@AnnoLong(999)"/>
+ <declare-annotation field="* field1(..)" annotation="@AnnoBoolean(true)"/>
+ <declare-annotation field="* field1(..)" annotation="@AnnoClass(Integer.class)"/>
+ <declare-annotation field="* field2(..)" annotation="@AnnoClass()"/> <!-- testing empty paren -->
+ </concrete-aspect>
+ </aspects>
+
+ <weaver options="-Xreweavable -verbose -XlazyTjp -showWeaveInfo">
+ <include within="Hello4"/>
+ </weaver>
+</aspectj>
+
diff --git a/tests/bugs170/xmldefs/aop5.xml b/tests/bugs170/xmldefs/aop5.xml
new file mode 100644
index 000000000..31a5f7d48
--- /dev/null
+++ b/tests/bugs170/xmldefs/aop5.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aspectj>
+ <aspects>
+ <concrete-aspect name="ConjuredUp">
+ <declare-annotation field="* field1(..)" annotation="@AnnoShort(8)"/>
+ <declare-annotation field="* field1(..)" annotation="@AnnoChar('z')"/>
+ <declare-annotation field="* field1(..)" annotation="@AnnoDouble(99.0d)"/>
+ <declare-annotation field="* field1(..)" annotation="@AnnoFloat(6.0f)"/>
+ <declare-annotation field="* field2(..)" annotation="@AnnoByte(88)"/>
+ <declare-annotation field="* field2(..)" annotation="@AnnoInt(99)"/>
+ </concrete-aspect>
+ </aspects>
+
+ <weaver options="-Xreweavable -verbose -XlazyTjp -showWeaveInfo">
+ <include within="Hello5"/>
+ </weaver>
+</aspectj>
+
diff --git a/tests/bugs170/xmldefs/aop6.xml b/tests/bugs170/xmldefs/aop6.xml
new file mode 100644
index 000000000..06300b72f
--- /dev/null
+++ b/tests/bugs170/xmldefs/aop6.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aspectj>
+ <aspects>
+ <concrete-aspect name="ConjuredUp">
+ <declare-annotation field="* field1(..)" annotation="@Annot(a='a',fred=false,'abc')"/>
+ </concrete-aspect>
+ </aspects>
+
+ <weaver options="-Xreweavable -verbose -XlazyTjp -showWeaveInfo">
+ <include within="Hello6"/>
+ </weaver>
+</aspectj>
+
diff --git a/tests/bugs170/xmldefs/aop6a.xml b/tests/bugs170/xmldefs/aop6a.xml
new file mode 100644
index 000000000..2c6410a9b
--- /dev/null
+++ b/tests/bugs170/xmldefs/aop6a.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aspectj>
+ <aspects>
+ <concrete-aspect name="ConjuredUp">
+ <declare-annotation field="* field1(..)" annotation="@Annot( a= 'a' , fred = false, 'abc' )"/>
+ </concrete-aspect>
+ </aspects>
+
+ <weaver options="-Xreweavable -verbose -XlazyTjp -showWeaveInfo">
+ <include within="Hello6"/>
+ </weaver>
+</aspectj>
+
diff --git a/tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java b/tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java
index 9ce29a36f..907464990 100644
--- a/tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java
+++ b/tests/src/org/aspectj/systemtest/ajc170/Ajc170Tests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008 Contributors
+ * Copyright (c) 2008-2012 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
@@ -17,20 +17,13 @@ import junit.framework.Test;
import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.testing.XMLBasedAjcTestCase;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.TypeFactory;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.internal.tools.StandardPointcutExpressionImpl;
-import org.aspectj.weaver.patterns.BasicTokenSource;
-import org.aspectj.weaver.patterns.ITokenSource;
-import org.aspectj.weaver.patterns.PatternParser;
import org.aspectj.weaver.patterns.Pointcut;
-import org.aspectj.weaver.patterns.PointcutEvaluationExpenseComparator;
import org.aspectj.weaver.patterns.PointcutRewriter;
import org.aspectj.weaver.reflect.ReflectionWorld;
-import org.aspectj.weaver.tools.StandardPointcutExpression;
import org.aspectj.weaver.tools.StandardPointcutParser;
/**
@@ -38,6 +31,35 @@ import org.aspectj.weaver.tools.StandardPointcutParser;
*/
public class Ajc170Tests extends org.aspectj.testing.XMLBasedAjcTestCase {
+ public void testXmlDefsDeclareAnnoMethod() {
+ runTest("xml defined dec at method");
+ }
+
+ // anno not runtime vis
+ public void testXmlDefsDeclareAnnoMethod2() {
+ runTest("xml defined dec at method 2");
+ }
+
+ public void testXmlDefsDeclareAnnoField() {
+ runTest("xml defined dec at field");
+ }
+
+ public void testXmlDefsDeclareAnnoFieldVariants1() {
+ runTest("xml defined dec anno - variants 1");
+ }
+
+ public void testXmlDefsDeclareAnnoFieldVariants2() {
+ runTest("xml defined dec anno - variants 2");
+ }
+
+ public void testXmlDefsDeclareAnnoFieldMultipleValues() {
+ runTest("xml defined dec anno - multiple values");
+ }
+
+ public void testXmlDefsDeclareAnnoFieldMultipleValuesAndSpaces() {
+ runTest("xml defined dec anno - multiple values and spaces");
+ }
+
public void testPointcutExpense_374964() {
// check a declaring type being specified causes the call() to be considered cheaper than this()
diff --git a/tests/src/org/aspectj/systemtest/ajc170/ajc170.xml b/tests/src/org/aspectj/systemtest/ajc170/ajc170.xml
index 58c936905..daed3a8e7 100644
--- a/tests/src/org/aspectj/systemtest/ajc170/ajc170.xml
+++ b/tests/src/org/aspectj/systemtest/ajc170/ajc170.xml
@@ -2,6 +2,106 @@
<suite>
+
+ <ajc-test dir="bugs170/xmldefs" title="xml defined dec at method">
+ <compile files="Hello.java Anno.java" options="-1.5"/>
+ <run class="Hello" ltw="aop.xml">
+ <stdout>
+ <line text="Hello"/>
+ <line text="World"/>
+ <line text="Annotations on sayHello? true"/>
+ <line text="Annotation count is 1"/>
+ <line text="@Anno"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs170/xmldefs" title="xml defined dec at method 2">
+ <compile files="Hello.java Anno2.java" options="-1.5"/>
+ <run class="Hello" ltw="aop2.xml">
+ <stdout>
+ <line text="Hello"/>
+ <line text="World"/>
+ <line text="Annotations on sayHello? false"/>
+ </stdout>
+ <stderr>
+ <line text="info AspectJ Weaver"/>
+ <line text="info register"/>
+ <line text="info using configuration"/>
+ <line text="info define aspect ConjuredUp"/>
+ <line text="error declare is using an annotation type that does not have runtime retention: @Anno2"/>
+ <line text="info weaver"/>
+ </stderr>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs170/xmldefs" title="xml defined dec at field">
+ <compile files="Hello2.java Anno.java" options="-1.5"/>
+ <run class="Hello2" ltw="aop3.xml">
+ <stdout>
+ <line text="Annotations on i? true"/>
+ <line text="Annotation count is 1"/>
+ <line text="@Anno"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs170/xmldefs" title="xml defined dec anno - variants 1">
+ <compile files="Hello4.java Anno4.java" options="-1.5"/>
+ <run class="Hello4" ltw="aop4.xml">
+ <stdout>
+ <line text="Annotations on field1? true"/>
+ <line text="Annotation count is 4"/>
+ <line text="@AnnoBoolean(zzz=false, value=true)"/>
+ <line text="@AnnoClass(value=class java.lang.Integer, ccc=class java.lang.String)"/>
+ <line text="@AnnoLong(jjj=111, value=999)"/>
+ <line text="@AnnoString(sss=xyz, value=set from xml)"/>
+ <line text="Annotations on field2? true"/>
+ <line text="Annotation count is 1"/>
+ <line text="@AnnoClass(value=class java.lang.String, ccc=class java.lang.String)"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs170/xmldefs" title="xml defined dec anno - variants 2">
+ <compile files="Hello5.java Anno5.java" options="-1.5"/>
+ <run class="Hello5" ltw="aop5.xml">
+ <stdout>
+ <line text="Annotations on field1? true"/>
+ <line text="Annotation count is 4"/>
+ <line text="@AnnoChar(value=z, ccc=a)"/>
+ <line text="@AnnoDouble(ddd=3.0, value=99.0)"/>
+ <line text="@AnnoFloat(fff=4.0, value=6.0)"/>
+ <line text="@AnnoShort(sss=3, value=8)"/>
+ <line text="Annotations on field2? true"/>
+ <line text="Annotation count is 2"/>
+ <line text="@AnnoByte(value=88, bbb=66)"/>
+ <line text="@AnnoInt(value=99, iii=111)"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs170/xmldefs" title="xml defined dec anno - multiple values">
+ <compile files="Hello6.java Anno6.java" options="-1.5"/>
+ <run class="Hello6" ltw="aop6.xml">
+ <stdout>
+ <line text="Annotations on field1? true"/>
+ <line text="Annotation count is 1"/>
+ <line text="@Annot(a=a, fred=false, value=abc)"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs170/xmldefs" title="xml defined dec anno - multiple values and spaces">
+ <compile files="Hello6.java Anno6.java" options="-1.5"/>
+ <run class="Hello6" ltw="aop6a.xml">
+ <stdout>
+ <line text="Annotations on field1? true"/>
+ <line text="Annotation count is 1"/>
+ <line text="@Annot(a=a, fred=false, value=abc)"/>
+ </stdout>
+ </run>
+ </ajc-test>
<ajc-test dir="bugs170/pr73507" title="public ITDfs - 1">
<compile files="Case1.java" options="-1.5"/>
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
index d8a9c0e0e..62ebac92c 100644
--- a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
+++ b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
@@ -1578,6 +1578,10 @@ public final class LazyClassGen {
annotations.add(new AnnotationGen(a, getConstantPool(), true));
}
}
+
+ public void addAttribute(AjAttribute attribute) {
+ myGen.addAttribute(Utility.bcelAttribute(attribute, getConstantPool()));
+ }
// this test is like asking:
// if
diff --git a/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java b/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java
index 7f9ce729d..de780156e 100644
--- a/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java
+++ b/weaver/src/org/aspectj/weaver/loadtime/definition/Definition.java
@@ -112,6 +112,7 @@ public class Definition {
public final String extend;
public final String precedence;
public final List<Definition.Pointcut> pointcuts;
+ public final List<Definition.DeclareAnnotation> declareAnnotations;
public final List<Definition.PointcutAndAdvice> pointcutsAndAdvice;
public final String perclause;
public List<Definition.DeclareErrorOrWarning> deows;
@@ -135,6 +136,7 @@ public class Definition {
}
this.precedence = precedence;
this.pointcuts = new ArrayList<Definition.Pointcut>();
+ this.declareAnnotations = new ArrayList<Definition.DeclareAnnotation>();
this.pointcutsAndAdvice = new ArrayList<Definition.PointcutAndAdvice>();
this.deows = new ArrayList<Definition.DeclareErrorOrWarning>();
this.perclause = perclause;
@@ -154,6 +156,22 @@ public class Definition {
public enum AdviceKind {
Before, After, AfterReturning, AfterThrowing, Around;
}
+
+ public enum DeclareAnnotationKind {
+ Method, Field, Type;
+ }
+
+ public static class DeclareAnnotation {
+ public final DeclareAnnotationKind declareAnnotationKind;
+ public final String pattern;
+ public final String annotation;
+
+ public DeclareAnnotation(DeclareAnnotationKind kind, String pattern, String annotation) {
+ this.declareAnnotationKind = kind;
+ this.pattern = pattern;
+ this.annotation = annotation;
+ }
+ }
public static class PointcutAndAdvice {
public final AdviceKind adviceKind;
diff --git a/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java b/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java
index 13968a696..7ff275fd7 100644
--- a/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java
+++ b/weaver/src/org/aspectj/weaver/loadtime/definition/DocumentParser.java
@@ -22,6 +22,8 @@ import javax.xml.parsers.SAXParserFactory;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.loadtime.definition.Definition.AdviceKind;
+import org.aspectj.weaver.loadtime.definition.Definition.DeclareAnnotation;
+import org.aspectj.weaver.loadtime.definition.Definition.DeclareAnnotationKind;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -72,6 +74,7 @@ public class DocumentParser extends DefaultHandler {
private final static String AROUND_ELEMENT = "around";
private final static String WITHIN_ATTRIBUTE = "within";
private final static String EXPRESSION_ATTRIBUTE = "expression";
+ private final static String DECLARE_ANNOTATION_ELEMENT = "declare-annotation";
private final Definition definition;
@@ -226,6 +229,30 @@ public class DocumentParser extends DefaultHandler {
if (!isNull(name) && !isNull(expression)) {
activeConcreteAspectDefinition.pointcuts.add(new Definition.Pointcut(name, replaceXmlAnd(expression)));
}
+ } else if (DECLARE_ANNOTATION_ELEMENT.equals(qName) && activeConcreteAspectDefinition!=null) {
+ String methodSig = attributes.getValue("method");
+ String fieldSig = attributes.getValue("field");
+ String typePat = attributes.getValue("type");
+ String anno = attributes.getValue("annotation");
+ if (isNull(anno)) {
+ throw new SAXException("Badly formed <declare-annotation> element, 'annotation' value is missing");
+ }
+ if (isNull(methodSig) && isNull(fieldSig) && isNull(typePat)) {
+ throw new SAXException("Badly formed <declare-annotation> element, need one of 'method'/'field'/'type' specified");
+ }
+ if (!isNull(methodSig)) {
+ // declare @method
+ activeConcreteAspectDefinition.declareAnnotations.add(new Definition.DeclareAnnotation(DeclareAnnotationKind.Method,
+ methodSig, anno));
+ } else if (!isNull(fieldSig)) {
+ // declare @field
+ activeConcreteAspectDefinition.declareAnnotations.add(new Definition.DeclareAnnotation(DeclareAnnotationKind.Field,
+ fieldSig, anno));
+ } else if (!isNull(typePat)) {
+ // declare @type
+ activeConcreteAspectDefinition.declareAnnotations.add(new Definition.DeclareAnnotation(DeclareAnnotationKind.Type,
+ typePat, anno));
+ }
} else if (BEFORE_ELEMENT.equals(qName) && activeConcreteAspectDefinition != null) {
String pointcut = attributes.getValue(POINTCUT_ELEMENT);
String adviceClass = attributes.getValue("invokeClass");