Переглянути джерело

big refactoring

refactoring
aclement 16 роки тому
джерело
коміт
08ee3d1bca

+ 145
- 1
weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java Переглянути файл

@@ -21,11 +21,14 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.aspectj.apache.bcel.classfile.AnnotationDefault;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.LocalVariable;
import org.aspectj.apache.bcel.classfile.LocalVariableTable;
import org.aspectj.apache.bcel.util.NonCachingClassLoaderRepository;
import org.aspectj.apache.bcel.util.Repository;
import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
@@ -96,6 +99,74 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder {
return null;
}
public AnnotationX getAnnotationOfType(UnresolvedType ofType,Member onMember) {
if (!(onMember instanceof AccessibleObject)) return null;
// here we really want both the runtime visible AND the class visible annotations
// so we bail out to Bcel and then chuck away the JavaClass so that we don't hog
// memory.
try {
JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass());
org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0];
if (onMember instanceof Method) {
org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method)onMember);
if (bcelMethod == null) {
// pr220430
//System.err.println("Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '"+onMember.getName()+"' in class '"+jc.getClassName()+"'");
} else {
anns = bcelMethod.getAnnotations();
}
} else if (onMember instanceof Constructor) {
org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor)onMember);
anns = bcelCons.getAnnotations();
} else if (onMember instanceof Field) {
org.aspectj.apache.bcel.classfile.Field bcelField = jc.getField((Field)onMember);
anns = bcelField.getAnnotations();
}
// the answer is cached and we don't want to hold on to memory
bcelRepository.clear();
if (anns == null) anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0];
// convert to our Annotation type
for (int i=0;i<anns.length;i++) {
if (anns[i].getTypeSignature().equals(ofType.getSignature())) {
return new AnnotationX(anns[i],world);
}
}
return null;
} catch (ClassNotFoundException cnfEx) {
// just use reflection then
}
return null;
}
public String getAnnotationDefaultValue(Member onMember) {
try {
JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass());
if (onMember instanceof Method) {
org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method)onMember);

if (bcelMethod == null) {
// pr220430
// System.err.println("Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '"+onMember.getName()+"' in class '"+jc.getClassName()+"'");
} else {
Attribute[] attrs = bcelMethod.getAttributes();
for (int i = 0; i < attrs.length; i++) {
Attribute attribute = attrs[i];
if (attribute.getName().equals("AnnotationDefault")) {
AnnotationDefault def = (AnnotationDefault)attribute;
return def.getElementValue().stringifyValue();
}
}
return null;
}
}
} catch (ClassNotFoundException cnfEx) {
// just use reflection then
}
return null;
}
public Set getAnnotations(Member onMember) {
if (!(onMember instanceof AccessibleObject)) return Collections.EMPTY_SET;
// here we really want both the runtime visible AND the class visible annotations
@@ -106,7 +177,12 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder {
org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0];
if (onMember instanceof Method) {
org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method)onMember);
anns = bcelMethod.getAnnotations();
if (bcelMethod == null) {
// fallback on reflection - see pr220430
// System.err.println("Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '"+onMember.getName()+"' in class '"+jc.getClassName()+"'");
} else {
anns = bcelMethod.getAnnotations();
}
} else if (onMember instanceof Constructor) {
org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor)onMember);
anns = bcelCons.getAnnotations();
@@ -189,6 +265,8 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder {
}
private String[] getParameterNamesFromLVT(LocalVariableTable lvt, int numVars) {
if (lvt == null)
return null;// pr222987 - prevent NPE
LocalVariable[] vars = lvt.getLocalVariableTable();
if (vars.length < numVars) {
// basic error, we can't get the names...
@@ -200,4 +278,70 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder {
}
return ret;
}
public static final ResolvedType[][] NO_PARAMETER_ANNOTATIONS = new ResolvedType[][]{};
public ResolvedType[][] getParameterAnnotationTypes(Member onMember) {
if (!(onMember instanceof AccessibleObject)) return NO_PARAMETER_ANNOTATIONS;
// here we really want both the runtime visible AND the class visible annotations
// so we bail out to Bcel and then chuck away the JavaClass so that we don't hog
// memory.
try {
JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass());
org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[][] anns = null;
if (onMember instanceof Method) {
org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method)onMember);
if (bcelMethod == null) {
// pr220430
//System.err.println("Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '"+onMember.getName()+"' in class '"+jc.getClassName()+"'");
} else {
anns = bcelMethod.getParameterAnnotations();
}
} else if (onMember instanceof Constructor) {
org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor)onMember);
anns = bcelCons.getParameterAnnotations();
} else if (onMember instanceof Field) {
anns = null;
}
// the answer is cached and we don't want to hold on to memory
bcelRepository.clear();
if (anns == null) return NO_PARAMETER_ANNOTATIONS;
ResolvedType[][] result = new ResolvedType[anns.length][];
// CACHING??
for (int i=0;i<anns.length;i++) {
if (anns[i]!=null) {
result[i] = new ResolvedType[anns[i].length];
for (int j=0;j<anns[i].length;j++) {
result[i][j] = world.resolve(UnresolvedType.forSignature(anns[i][j].getTypeSignature()));
}
}
}
return result;
} catch (ClassNotFoundException cnfEx) {
// just use reflection then
}
// reflection...
AccessibleObject ao = (AccessibleObject) onMember;
Annotation[][] anns = null;
if (onMember instanceof Method) {
anns = ((Method)ao).getParameterAnnotations();
} else if (onMember instanceof Constructor) {
anns = ((Constructor)ao).getParameterAnnotations();
} else if (onMember instanceof Field) {
anns = null;
}
if (anns == null) return NO_PARAMETER_ANNOTATIONS;
ResolvedType[][] result = new ResolvedType[anns.length][];
// CACHING??
for (int i=0;i<anns.length;i++) {
if (anns[i]!=null) {
result[i] = new ResolvedType[anns[i].length];
for (int j=0;j<anns[i].length;j++) {
result[i][j] = UnresolvedType.forName(anns[i][j].annotationType().getName()).resolve(world);
}
}
}
return result;
}
}

+ 26
- 14
weaver5/java5-src/org/aspectj/weaver/reflect/Java15ReflectionBasedReferenceTypeDelegate.java Переглянути файл

@@ -17,6 +17,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.Set;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.AjType;
@@ -31,6 +33,7 @@ import org.aspectj.weaver.TypeVariable;
import org.aspectj.weaver.TypeVariableReferenceType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.tools.PointcutDesignatorHandler;
import org.aspectj.weaver.tools.PointcutParameter;

/**
@@ -64,6 +67,7 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
annotationFinder = new Java15AnnotationFinder();
argNameFinder = annotationFinder;
annotationFinder.setClassLoader(this.classLoader);
annotationFinder.setWorld(aWorld);
this.typeConverter = new JavaLangTypeToResolvedTypeConverter(aWorld);
}
@@ -101,10 +105,11 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
public ResolvedMember[] getDeclaredFields() {
if (fields == null) {
Field[] reflectFields = this.myType.getDeclaredFields();
this.fields = new ResolvedMember[reflectFields.length];
ResolvedMember[] rFields = new ResolvedMember[reflectFields.length];
for (int i = 0; i < reflectFields.length; i++) {
this.fields[i] = createGenericFieldMember(reflectFields[i]);
rFields[i] = createGenericFieldMember(reflectFields[i]);
}
this.fields = rFields;
}
return fields;
}
@@ -141,24 +146,25 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
}
if (this.typeVariables == null) {
java.lang.reflect.TypeVariable[] tVars = this.getBaseClass().getTypeParameters();
this.typeVariables = new TypeVariable[tVars.length];
TypeVariable[] rTypeVariables = new TypeVariable[tVars.length];
// basic initialization
for (int i = 0; i < tVars.length; i++) {
typeVariables[i] = new TypeVariable(tVars[i].getName());
rTypeVariables[i] = new TypeVariable(tVars[i].getName());
}
// stash it
this.getResolvedTypeX().getWorld().recordTypeVariablesCurrentlyBeingProcessed(getBaseClass(),typeVariables);
this.getResolvedTypeX().getWorld().recordTypeVariablesCurrentlyBeingProcessed(getBaseClass(), rTypeVariables);
// now fill in the details...
for (int i = 0; i < tVars.length; i++) {
TypeVariableReferenceType tvrt = ((TypeVariableReferenceType) typeConverter.fromType(tVars[i]));
TypeVariable tv = tvrt.getTypeVariable();
typeVariables[i].setUpperBound(tv.getUpperBound());
typeVariables[i].setAdditionalInterfaceBounds(tv.getAdditionalInterfaceBounds());
typeVariables[i].setDeclaringElement(tv.getDeclaringElement());
typeVariables[i].setDeclaringElementKind(tv.getDeclaringElementKind());
typeVariables[i].setRank(tv.getRank());
typeVariables[i].setLowerBound(tv.getLowerBound());
rTypeVariables[i].setUpperBound(tv.getUpperBound());
rTypeVariables[i].setAdditionalInterfaceBounds(tv.getAdditionalInterfaceBounds());
rTypeVariables[i].setDeclaringElement(tv.getDeclaringElement());
rTypeVariables[i].setDeclaringElementKind(tv.getDeclaringElementKind());
rTypeVariables[i].setRank(tv.getRank());
rTypeVariables[i].setLowerBound(tv.getLowerBound());
}
this.typeVariables = rTypeVariables;
this.getResolvedTypeX().getWorld().forgetTypeVariablesCurrentlyBeingProcessed(getBaseClass());
}
return this.typeVariables;
@@ -170,14 +176,15 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
if (methods == null) {
Method[] reflectMethods = this.myType.getDeclaredMethods();
Constructor[] reflectCons = this.myType.getDeclaredConstructors();
this.methods = new ResolvedMember[reflectMethods.length + reflectCons.length];
ResolvedMember[] rMethods = new ResolvedMember[reflectMethods.length + reflectCons.length];
for (int i = 0; i < reflectMethods.length; i++) {
this.methods[i] = createGenericMethodMember(reflectMethods[i]);
rMethods[i] = createGenericMethodMember(reflectMethods[i]);
}
for (int i = 0; i < reflectCons.length; i++) {
this.methods[i + reflectMethods.length] =
rMethods[i + reflectMethods.length] =
createGenericConstructorMember(reflectCons[i]);
}
this.methods = rMethods;
}
return methods;
}
@@ -250,6 +257,11 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
} else {
parser = new InternalUseOnlyPointcutParser(classLoader);
}
Set additionalPointcutHandlers = world.getRegisteredPointcutHandlers();
for (Iterator handlerIterator = additionalPointcutHandlers.iterator(); handlerIterator.hasNext();) {
PointcutDesignatorHandler handler = (PointcutDesignatorHandler) handlerIterator.next();
parser.registerPointcutDesignatorHandler(handler);
}
// phase 1, create legitimate entries in pointcuts[] before we attempt to resolve *any* of the pointcuts
// resolution can sometimes cause us to recurse, and this two stage process allows us to cope with that

+ 1
- 0
weaver5/java5-src/org/aspectj/weaver/tools/Jdk14Trace.java Переглянути файл

@@ -14,6 +14,7 @@ import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

// OPTIMIZE move out for now? check what doc says about using these variants on trace (commons/14)
public class Jdk14Trace extends AbstractTrace {

private Logger logger;

+ 52
- 0
weaver5/java5-testsrc/CounterAspect.java Переглянути файл

@@ -0,0 +1,52 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andy Clement initial implementation
* ******************************************************************/
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
* Created to enable PointcutDesignatorHandlerTests.testParsingBeanInReferencePointcut01 and 02 to run
*
* @author Andy Clement
*/
@Aspect
public class CounterAspect {

int count;

@Before("execution(* set*(..)) && bean(testBean1)")
public void increment1ForAnonymousPointcut() {
count++;
}

@Pointcut("execution(* toString(..)) && bean(testBean1)")
public void testBean1toString() {
}
@Pointcut("execution(* setAge(..)) && bean(testBean1)")
public void testBean1SetAge() {
}

@Pointcut("execution(* setAge(..)) && bean(testBean2)")
public void testBean2SetAge() {
}

@Before("testBean1SetAge()")
public void increment1() {
count++;
}

@Before("testBean2SetAge()")
public void increment2() {
count++;
}
}

+ 15
- 0
weaver5/java5-testsrc/MA.java Переглянути файл

@@ -0,0 +1,15 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/

public @interface MA {

}

+ 15
- 0
weaver5/java5-testsrc/MB.java Переглянути файл

@@ -0,0 +1,15 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/

public @interface MB {

}

+ 15
- 0
weaver5/java5-testsrc/MC.java Переглянути файл

@@ -0,0 +1,15 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/

public @interface MC {

}

+ 15
- 0
weaver5/java5-testsrc/MD.java Переглянути файл

@@ -0,0 +1,15 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/

public @interface MD {

}

+ 295
- 1
weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java Переглянути файл

@@ -14,17 +14,40 @@ package org.aspectj.weaver.tools;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.internal.tools.PointcutExpressionImpl;
import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor;
import org.aspectj.weaver.patterns.AndAnnotationTypePattern;
import org.aspectj.weaver.patterns.AnnotationPatternList;
import org.aspectj.weaver.patterns.AnyAnnotationTypePattern;
import org.aspectj.weaver.patterns.BindingAnnotationTypePattern;
import org.aspectj.weaver.patterns.ExactAnnotationTypePattern;
import org.aspectj.weaver.patterns.KindedPointcut;
import org.aspectj.weaver.patterns.NotAnnotationTypePattern;
import org.aspectj.weaver.patterns.OrAnnotationTypePattern;
import org.aspectj.weaver.patterns.SignaturePattern;
import org.aspectj.weaver.patterns.TypePattern;
import org.aspectj.weaver.patterns.TypePatternList;
import org.aspectj.weaver.patterns.WildAnnotationTypePattern;

import test.A1AnnotatedType;
import test.A2AnnotatedType;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
* @author colyer
* Test parameter pointcut parsing. Extended by Andy Clement to cover parameter annotation matching.
*
*/
public class Java15PointcutExpressionTest extends TestCase {
@@ -41,6 +64,277 @@ public class Java15PointcutExpressionTest extends TestCase {
private Method c;
private Method d;
/**
* Parse some expressions and ensure we capture the parameter annotations and parameter type annotations correctly.
* Buckle up, this will get complicated ;)
*/
public void testParseParameterAnnotationExpressions() {
PointcutParser p = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
PointcutExpression pexpr = null;

pexpr = p.parsePointcutExpression("execution(public void foo(@MA *))");
checkParameterAnnotations(pexpr,0,null,"@MA","exact[@MA:t]");

pexpr = p.parsePointcutExpression("execution(public void foo(@MA (*)))");
checkParameterAnnotations(pexpr,0,"@MA",null,"exact[@MA:p]");

pexpr = p.parsePointcutExpression("execution(public void foo(@MA @MB *))");
checkParameterAnnotations(pexpr,0,null,"@MA @MB","(exact[@MA:t] and exact[@MB:t])");
pexpr = p.parsePointcutExpression("execution(public void foo(@MA (@MB *)))");
checkParameterAnnotations(pexpr,0,"@MA","@MB","(exact[@MA:p] and exact[@MB:t])");
pexpr = p.parsePointcutExpression("execution(public void foo(@MA @MB (@MC *)))");
checkParameterAnnotations(pexpr,0,"@MA @MB","@MC","((exact[@MA:p] and exact[@MB:p]) and exact[@MC:t])");

pexpr = p.parsePointcutExpression("execution(public void foo(@MA (@MB @MC @MD *)))");
checkParameterAnnotations(pexpr,0,"@MA","@MB @MC @MD","(exact[@MA:p] and ((exact[@MB:t] and exact[@MC:t]) and exact[@MD:t]))");
pexpr = p.parsePointcutExpression("execution(public void foo(@(MA || MB) (@MC @MD *)))");
checkParameterAnnotations(pexpr,0,null/*Should be MA MB */,"@MC @MD","(wild[(MA || MB)] and (exact[@MC:t] and exact[@MD:t]))"); // I dont think WildAnnotationTypePatterns work properly...

pexpr = p.parsePointcutExpression("execution(public void foo(@MA (@MB *),(@MC *),@MD (*)))");
checkParameterAnnotations(pexpr,0,"@MA","@MB","(exact[@MA:p] and exact[@MB:t])");
checkParameterAnnotations(pexpr,1,null,"@MC","exact[@MC:t]");
checkParameterAnnotations(pexpr,2,"@MD",null,"exact[@MD:p]");
}
public void testMatchingAnnotationValueExpressions() throws SecurityException, NoSuchMethodException {
PointcutParser p = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
PointcutExpression pexpr = null;
ShadowMatch match = null;

Method n = test.AnnoValues.class.getMethod("none",null);
Method r = test.AnnoValues.class.getMethod("redMethod",null);
Method g = test.AnnoValues.class.getMethod("greenMethod",null);
Method b = test.AnnoValues.class.getMethod("blueMethod",null);
Method d = test.AnnoValues.class.getMethod("defaultMethod",null);

pexpr = p.parsePointcutExpression("execution(@test.A3(test.Color.RED) public void *(..))");
assertTrue("Should match", pexpr.matchesMethodExecution(n).neverMatches()); // default value RED
assertTrue("Should match", pexpr.matchesMethodExecution(r).alwaysMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(g).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(b).neverMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(d).alwaysMatches());
pexpr = p.parsePointcutExpression("execution(@test.A3(test.Color.GREEN) public void *(..))");
assertTrue("Should not match", pexpr.matchesMethodExecution(n).neverMatches()); // default value RED
assertTrue("Should not match", pexpr.matchesMethodExecution(r).neverMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(g).alwaysMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(b).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(d).neverMatches());
pexpr = p.parsePointcutExpression("execution(@test.A3(test.Color.BLUE) public void *(..))");
assertTrue("Should not match", pexpr.matchesMethodExecution(n).neverMatches()); // default value RED
assertTrue("Should not match", pexpr.matchesMethodExecution(r).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(g).neverMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(b).alwaysMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(d).neverMatches());

pexpr = p.parsePointcutExpression("execution(@test.A3 public void *(..))");
assertTrue("Should match", pexpr.matchesMethodExecution(n).neverMatches()); // default value RED
assertTrue("Should match", pexpr.matchesMethodExecution(r).alwaysMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(g).alwaysMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(b).alwaysMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(d).alwaysMatches());

}

/**
* Test matching of pointcuts against expressions. A reflection world is being used on the backend here (not a Bcel one).
*/
public void testMatchingParameterAnnotationExpressions() throws SecurityException, NoSuchMethodException {
PointcutParser p = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
PointcutExpression pexpr = null;
ShadowMatch match = null;

Method a = test.A.class.getMethod("a",new Class[] {String.class}); // public void a(String s) {}
Method b = test.A.class.getMethod("b",new Class[] {String.class}); // public void b(@A1 String s) {}
Method c = test.A.class.getMethod("c",new Class[] {String.class}); // public void c(@A1 @A2 String s) {}
Method d = test.A.class.getMethod("d",new Class[] {String.class,String.class});// public void d(@A1 String s,@A2 String t) {}

Method e = test.A.class.getMethod("e",new Class[] {A1AnnotatedType.class}); // public void e(A1AnnotatedType s) {}
Method f = test.A.class.getMethod("f",new Class[] {A2AnnotatedType.class}); // public void f(A2AnnotatedType s) {}
Method g = test.A.class.getMethod("g",new Class[] {A1AnnotatedType.class}); // public void g(@A2 A1AnnotatedType s) {}
Method h = test.A.class.getMethod("h",new Class[] {A1AnnotatedType.class}); // public void h(@A1 A1AnnotatedType s) {}
Method i = test.A.class.getMethod("i",new Class[] {A1AnnotatedType.class,String.class}); // public void i(A1AnnotatedType s,@A2 String t) {}
Method j = test.A.class.getMethod("j",new Class[] {String.class}); // public void j(@A1 @A2 String s) {}

pexpr = p.parsePointcutExpression("execution(public void *(@test.A1 *))");
assertTrue("Should not match", pexpr.matchesMethodExecution(a).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(b).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(c).neverMatches());
pexpr = p.parsePointcutExpression("execution(public void *(@test.A1 (*)))");
assertTrue("Should not match", pexpr.matchesMethodExecution(a).neverMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(b).alwaysMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(c).alwaysMatches());

pexpr = p.parsePointcutExpression("execution(public void *(@test.A1 *))");
assertTrue("Should match", pexpr.matchesMethodExecution(e).alwaysMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(f).neverMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(g).alwaysMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(h).alwaysMatches());

pexpr = p.parsePointcutExpression("execution(public void *(@test.A1 (*)))");
assertTrue("Should not match", pexpr.matchesMethodExecution(e).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(f).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(g).neverMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(h).alwaysMatches());

pexpr = p.parsePointcutExpression("execution(public void *(@(test.A1 || test.A2) (*)))");
assertTrue("Should not match", pexpr.matchesMethodExecution(a).neverMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(b).alwaysMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(c).alwaysMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(g).alwaysMatches());
assertTrue("Should match", pexpr.matchesMethodExecution(h).alwaysMatches());

pexpr = p.parsePointcutExpression("execution(public void *(@(test.A1 && test.A2) (*),..))");
assertTrue("Should not match", pexpr.matchesMethodExecution(a).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(b).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(c).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(g).neverMatches());
assertTrue("Should not match", pexpr.matchesMethodExecution(h).neverMatches());
// assertTrue("Should match", pexpr.matchesMethodExecution(j).alwaysMatches()); // should match but does not, broken implementation, old bug - see WildAnnotationTypePattern.match

}

private void checkParameterAnnotations(PointcutExpression pe,int parameterNumber,String expectedParameterAnnotations,String expectedParameterTypeAnnotations,String expectedNodeStructure) {
org.aspectj.weaver.patterns.Pointcut p = ((PointcutExpressionImpl)pe).getUnderlyingPointcut();
KindedPointcut kindedP = (KindedPointcut)p;
SignaturePattern sp = kindedP.getSignature();
TypePatternList tpl = sp.getParameterTypes();
TypePattern[] tps = tpl.getTypePatterns();
// A visitor over the annotation pattern for the parameter will break it down into parameter vs parameter type annotations
MyPatternNodeVisitor mpnv = new MyPatternNodeVisitor();
tps[parameterNumber].getAnnotationPattern().accept(mpnv,null);
if (expectedNodeStructure==null) {
// The caller hasn't worked it out yet!!
System.out.println(mpnv.getStringRepresentation());
} else if (!mpnv.getStringRepresentation().equals(expectedNodeStructure)) {
System.out.println(mpnv.getStringRepresentation());
fail("Expected annotation pattern node structure for expression "+pe.getPointcutExpression()+
" was '"+expectedNodeStructure+"' but it turned out to be '"+mpnv.getStringRepresentation()+"'");
}
String annotationTypePattern = tps[parameterNumber].getAnnotationPattern().toString();
// parameter type annotation checking
Set<String> expected = new HashSet<String>();
expected.addAll(mpnv.getParameterTypeAnnotations());
StringTokenizer st = new StringTokenizer(expectedParameterTypeAnnotations==null?"":expectedParameterTypeAnnotations);
while (st.hasMoreTokens()) {
String nextToken = st.nextToken();
if (!expected.contains(nextToken))
fail("In pointcut expression "+pe.getPointcutExpression()+" parameter "+parameterNumber+". The annotation type pattern did not include parameter type annotation "+nextToken+". It's full set was "+mpnv.getParameterTypeAnnotations());
expected.remove(nextToken);
}
if (expected.size()>0) { // we have excess ones!
StringBuffer excessTokens = new StringBuffer();
for (Iterator iterator = expected.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
excessTokens.append(string).append(" ");
}
fail("In pointcut expression "+pe.getPointcutExpression()+" parameter "+parameterNumber+". The annotation type pattern has these unexpected parameter type annotations "+excessTokens.toString());
}
// parameter annotation checking
expected = new HashSet<String>();
expected.addAll(mpnv.getParameterAnnotations());
st = new StringTokenizer(expectedParameterAnnotations==null?"":expectedParameterAnnotations);
while (st.hasMoreTokens()) {
String nextToken = st.nextToken();
if (!expected.contains(nextToken))
fail("In pointcut expression "+pe.getPointcutExpression()+" parameter "+parameterNumber+". The annotation type pattern did not include parameter annotation "+nextToken+". It's full set was "+mpnv.getParameterAnnotations());
expected.remove(nextToken);
}
if (expected.size()>0) { // we have excess ones!
StringBuffer excessTokens = new StringBuffer();
for (Iterator iterator = expected.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
excessTokens.append(string).append(" ");
}
fail("In pointcut expression "+pe.getPointcutExpression()+" parameter "+parameterNumber+". The annotation type pattern has these unexpected parameter annotations "+excessTokens.toString());
}
}
static class MyPatternNodeVisitor extends AbstractPatternNodeVisitor {
private StringBuffer stringRep = new StringBuffer();
private List<String> parameterAnnotations = new ArrayList<String>();
private List<String> parameterTypeAnnotations = new ArrayList<String>();
public String getStringRepresentation() { return stringRep.toString(); }
public List<String> getParameterAnnotations() { return parameterAnnotations; }
public List<String> getParameterTypeAnnotations() { return parameterTypeAnnotations; }
public Object visit(AndAnnotationTypePattern node, Object data) {
stringRep.append("(");
node.getLeft().accept(this, data);
stringRep.append(" and ");
node.getRight().accept(this, data);
stringRep.append(")");
return node;
}
public Object visit(AnyAnnotationTypePattern node, Object data) {
stringRep.append("any");
return node;
}
public Object visit(ExactAnnotationTypePattern node, Object data) {
stringRep.append("exact["+stringify(node.getResolvedAnnotationType())+":"+(node.isForParameterAnnotationMatch()?"p":"t")+"]");
if (node.isForParameterAnnotationMatch()) {
parameterAnnotations.add(stringify(node.getResolvedAnnotationType()));
} else {
parameterTypeAnnotations.add(stringify(node.getResolvedAnnotationType()));
}
return node;
}
private String stringify(ResolvedType resolvedAnnotationType) {
return "@"+resolvedAnnotationType.getSimpleName();
}

public Object visit(BindingAnnotationTypePattern node, Object data) {
stringRep.append("binding");
return node;
}
public Object visit(NotAnnotationTypePattern node, Object data) {
stringRep.append("not");
return node;
}
public Object visit(OrAnnotationTypePattern node, Object data) {
stringRep.append("(");
node.getLeft().accept(this, data);
stringRep.append(" or ");
node.getRight().accept(this, data);
stringRep.append(")");
return node;
}
public Object visit(WildAnnotationTypePattern node, Object data) {
stringRep.append("wild[");
stringRep.append(node.getTypePattern().toString());
stringRep.append("]");
return node;
}
public Object visit(AnnotationPatternList node, Object data) {
stringRep.append("list");
return node;
}
}
public void testAtThis() {
PointcutExpression atThis = parser.parsePointcutExpression("@this(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
ShadowMatch sMatch1 = atThis.matchesMethodExecution(a);

+ 27
- 0
weaver5/java5-testsrc/test/A.java Переглянути файл

@@ -0,0 +1,27 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/
package test;

public class A {
public void a(String s) {}
public void b(@A1 String s) {}
public void c(@A1 @A2 String s) {}
public void d(@A1 String s,@A2 String t) {}
public void e(A1AnnotatedType s) {}
public void f(A2AnnotatedType s) {}
public void g(@A2 A1AnnotatedType s) {}
public void h(@A1 A1AnnotatedType s) {}
public void i(A1AnnotatedType s,@A2 String t) {}
public void j(@A1 @A2 String s) {}

}

+ 20
- 0
weaver5/java5-testsrc/test/A1.java Переглянути файл

@@ -0,0 +1,20 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/
package test;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface A1 {

}

+ 17
- 0
weaver5/java5-testsrc/test/A1AnnotatedType.java Переглянути файл

@@ -0,0 +1,17 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/
package test;

@A1
public class A1AnnotatedType {

}

+ 20
- 0
weaver5/java5-testsrc/test/A2.java Переглянути файл

@@ -0,0 +1,20 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/
package test;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface A2 {

}

+ 17
- 0
weaver5/java5-testsrc/test/A2AnnotatedType.java Переглянути файл

@@ -0,0 +1,17 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/
package test;

@A2
public class A2AnnotatedType {

}

+ 19
- 0
weaver5/java5-testsrc/test/A3.java Переглянути файл

@@ -0,0 +1,19 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/
package test;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface A3 {
Color value() default Color.RED;
}

+ 20
- 0
weaver5/java5-testsrc/test/AnnoValues.java Переглянути файл

@@ -0,0 +1,20 @@
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/
package test;

public class AnnoValues {
public void none() {}
@A3 public void defaultMethod() {}
@A3(Color.GREEN) public void greenMethod() {}
@A3(Color.RED) public void redMethod() {}
@A3(Color.BLUE) public void blueMethod() {}
}

+ 14
- 0
weaver5/java5-testsrc/test/Color.java Переглянути файл

@@ -0,0 +1,14 @@
package test;
/* *******************************************************************
* Copyright (c) 2008 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors
* Andy Clement
* ******************************************************************/

public enum Color { RED, GREEN, BLUE }

Завантаження…
Відмінити
Зберегти