From 0ea99cad049a88bb2465472f8eba9800ae9d44f3 Mon Sep 17 00:00:00 2001 From: aclement Date: Mon, 26 Sep 2005 15:36:21 +0000 Subject: [PATCH] weaver5 split out so weaver can continue to be built with Java1.3 --- weaver5/.classpath | 15 + weaver5/.project | 17 + weaver5/.settings/org.eclipse.jdt.core.prefs | 12 + weaver5/.settings/org.eclipse.jdt.ui.prefs | 3 + weaver5/build.xml | 6 + .../reflect/Java15AnnotationFinder.java | 152 +++++++++ ...5ReflectionBasedReferenceTypeDelegate.java | 310 ++++++++++++++++++ weaver5/java5-testsrc/Weaver5ModuleTests.java | 40 +++ .../tools/Java15PointcutExpressionTest.java | 278 ++++++++++++++++ 9 files changed, 833 insertions(+) create mode 100644 weaver5/.classpath create mode 100644 weaver5/.project create mode 100644 weaver5/.settings/org.eclipse.jdt.core.prefs create mode 100644 weaver5/.settings/org.eclipse.jdt.ui.prefs create mode 100644 weaver5/build.xml create mode 100644 weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java create mode 100644 weaver5/java5-src/org/aspectj/weaver/reflect/Java15ReflectionBasedReferenceTypeDelegate.java create mode 100644 weaver5/java5-testsrc/Weaver5ModuleTests.java create mode 100644 weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java diff --git a/weaver5/.classpath b/weaver5/.classpath new file mode 100644 index 000000000..9ab8ac4c8 --- /dev/null +++ b/weaver5/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/weaver5/.project b/weaver5/.project new file mode 100644 index 000000000..3f4e4f364 --- /dev/null +++ b/weaver5/.project @@ -0,0 +1,17 @@ + + + weaver5 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/weaver5/.settings/org.eclipse.jdt.core.prefs b/weaver5/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..053aca2b3 --- /dev/null +++ b/weaver5/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Mon Sep 26 14:56:38 BST 2005 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/weaver5/.settings/org.eclipse.jdt.ui.prefs b/weaver5/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..60c05a46a --- /dev/null +++ b/weaver5/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,3 @@ +#Mon Sep 26 14:56:47 BST 2005 +eclipse.preferences.version=1 +internal.default.compliance=default diff --git a/weaver5/build.xml b/weaver5/build.xml new file mode 100644 index 000000000..5fc6b3443 --- /dev/null +++ b/weaver5/build.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java b/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java new file mode 100644 index 000000000..31abe3056 --- /dev/null +++ b/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java @@ -0,0 +1,152 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.weaver.reflect; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.util.Repository; +import org.aspectj.apache.bcel.util.ClassLoaderRepository; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.UnresolvedType; +import org.aspectj.weaver.World; + +/** + * Find the given annotation (if present) on the given object + * + */ +public class Java15AnnotationFinder implements AnnotationFinder { + + private Repository bcelRepository; + + public Java15AnnotationFinder() { + this.bcelRepository = new ClassLoaderRepository(getClass().getClassLoader()); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.reflect.AnnotationFinder#getAnnotation(org.aspectj.weaver.ResolvedType, java.lang.Object) + */ + public Object getAnnotation(ResolvedType annotationType, Object onObject) { + try { + Class annotationClass = Class.forName(annotationType.getName()); + if (onObject.getClass().isAnnotationPresent(annotationClass)) { + return onObject.getClass().getAnnotation(annotationClass); + } + } catch (ClassNotFoundException ex) { + // just return null + } + return null; + } + + public Object getAnnotationFromClass(ResolvedType annotationType, Class aClass) { + try { + Class annotationClass = Class.forName(annotationType.getName()); + if (aClass.isAnnotationPresent(annotationClass)) { + return aClass.getAnnotation(annotationClass); + } + } catch (ClassNotFoundException ex) { + // just return null + } + return null; + } + + public Object getAnnotationFromMember(ResolvedType annotationType, Member aMember) { + if (!(aMember instanceof AccessibleObject)) return null; + AccessibleObject ao = (AccessibleObject) aMember; + try { + Class annotationClass = Class.forName(annotationType.getName()); + if (ao.isAnnotationPresent(annotationClass)) { + return ao.getAnnotation(annotationClass); + } + } catch (ClassNotFoundException ex) { + // just return null + } + 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 + // 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.Annotation[] anns = new org.aspectj.apache.bcel.classfile.annotation.Annotation[0]; + if (onMember instanceof Method) { + org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method)onMember); + 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.Annotation[0]; + // convert to our Annotation type + Set annSet = new HashSet(); + for (int i = 0; i < anns.length; i++) { + annSet.add(UnresolvedType.forName(anns[i].getTypeName())); + } + return annSet; + } catch (ClassNotFoundException cnfEx) { + // just use reflection then + } + + + AccessibleObject ao = (AccessibleObject) onMember; + Annotation[] anns = ao.getDeclaredAnnotations(); + Set annSet = new HashSet(); + for (int i = 0; i < anns.length; i++) { + annSet.add(UnresolvedType.forName(anns[i].annotationType().getName())); + } + return annSet; + } + + public ResolvedType[] getAnnotations(Class forClass, World inWorld) { + // 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(forClass); + org.aspectj.apache.bcel.classfile.annotation.Annotation[] anns =jc.getAnnotations(); + bcelRepository.clear(); + if (anns == null) return new ResolvedType[0]; + ResolvedType[] ret = new ResolvedType[anns.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = inWorld.resolve(anns[i].getTypeName()); + } + return ret; + } catch (ClassNotFoundException cnfEx) { + // just use reflection then + } + + Annotation[] classAnnotations = forClass.getAnnotations(); + ResolvedType[] ret = new ResolvedType[classAnnotations.length]; + for (int i = 0; i < classAnnotations.length; i++) { + ret[i] = inWorld.resolve(classAnnotations[i].annotationType().getName()); + } + + return ret; + } + +} diff --git a/weaver5/java5-src/org/aspectj/weaver/reflect/Java15ReflectionBasedReferenceTypeDelegate.java b/weaver5/java5-src/org/aspectj/weaver/reflect/Java15ReflectionBasedReferenceTypeDelegate.java new file mode 100644 index 000000000..164fc9f80 --- /dev/null +++ b/weaver5/java5-src/org/aspectj/weaver/reflect/Java15ReflectionBasedReferenceTypeDelegate.java @@ -0,0 +1,310 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.weaver.reflect; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; + +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.AjType; +import org.aspectj.lang.reflect.AjTypeSystem; +import org.aspectj.lang.reflect.Pointcut; +import org.aspectj.weaver.AnnotationX; +import org.aspectj.weaver.BoundedReferenceType; +import org.aspectj.weaver.ReferenceType; +import org.aspectj.weaver.ResolvedMember; +import org.aspectj.weaver.ResolvedPointcutDefinition; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.TypeFactory; +import org.aspectj.weaver.TypeVariable; +import org.aspectj.weaver.TypeVariableReferenceType; +import org.aspectj.weaver.UnresolvedType; +import org.aspectj.weaver.World; +import org.aspectj.weaver.internal.tools.PointcutExpressionImpl; +import org.aspectj.weaver.tools.PointcutParameter; +import org.aspectj.weaver.tools.PointcutParser; + +/** + * @author colyer + * Provides Java 5 behaviour in reflection based delegates (overriding + * 1.4 behaviour from superclass where appropriate) + */ +public class Java15ReflectionBasedReferenceTypeDelegate extends + ReflectionBasedReferenceTypeDelegate { + + private AjType myType; + private ResolvedType[] annotations; + private ResolvedMember[] pointcuts; + private ResolvedMember[] methods; + private ResolvedMember[] fields; + private TypeVariable[] typeVariables; + private ResolvedType superclass; + private ResolvedType[] superInterfaces; + private String genericSignature = null; + private Java15AnnotationFinder annotationFinder = new Java15AnnotationFinder(); + + + public Java15ReflectionBasedReferenceTypeDelegate() {} + + public void initialize(ReferenceType aType, Class aClass, World aWorld) { + super.initialize(aType, aClass, aWorld); + myType = AjTypeSystem.getAjType(aClass); + } + + + public ReferenceType buildGenericType() { + return (ReferenceType) UnresolvedType.forGenericTypeVariables( + getResolvedTypeX().getSignature(), + getTypeVariables()).resolve(getWorld()); + } + + public AnnotationX[] getAnnotations() { + // AMC - we seem not to need to implement this method... + throw new UnsupportedOperationException("getAnnotations on Java15ReflectionBasedReferenceTypeDelegate is not implemented yet"); + //return super.getAnnotations(); + } + + public ResolvedType[] getAnnotationTypes() { + if (annotations == null) { + annotations = annotationFinder.getAnnotations(getBaseClass(), getWorld()); + } + return annotations; + } + + public boolean hasAnnotation(UnresolvedType ofType) { + ResolvedType[] myAnns = getAnnotationTypes(); + ResolvedType toLookFor = ofType.resolve(getWorld()); + for (int i = 0; i < myAnns.length; i++) { + if (myAnns[i] == toLookFor) return true; + } + return false; + } + + // use the MAP to ensure that any aj-synthetic fields are filtered out + public ResolvedMember[] getDeclaredFields() { + if (fields == null) { + Field[] reflectFields = this.myType.getDeclaredFields(); + this.fields = new ResolvedMember[reflectFields.length]; + for (int i = 0; i < reflectFields.length; i++) { + this.fields[i] = createGenericFieldMember(reflectFields[i]); + } + } + return fields; + } + + public String getDeclaredGenericSignature() { + if (this.genericSignature == null && isGeneric()) { + + } + return genericSignature; + } + + public ResolvedType[] getDeclaredInterfaces() { + if (superInterfaces == null) { + Type[] genericInterfaces = getBaseClass().getGenericInterfaces(); + this.superInterfaces = fromTypes(genericInterfaces); + } + return superInterfaces; + } + + public ResolvedType getSuperclass() { + if (superclass == null) + superclass = fromType(this.getBaseClass().getGenericSuperclass()); + return superclass; + } + + public TypeVariable[] getTypeVariables() { + if (this.typeVariables == null) { + java.lang.reflect.TypeVariable[] tVars = this.getBaseClass().getTypeParameters(); + this.typeVariables = new TypeVariable[tVars.length]; + for (int i = 0; i < tVars.length; i++) { + this.typeVariables[i] = ((TypeVariableReferenceType) fromType(tVars[i])).getTypeVariable(); + } + } + return this.typeVariables; + } + + // overrides super method since by using the MAP we can filter out advice + // methods that really shouldn't be seen in this list + public ResolvedMember[] getDeclaredMethods() { + if (methods == null) { + Method[] reflectMethods = this.myType.getDeclaredMethods(); + Constructor[] reflectCons = this.myType.getDeclaredConstructors(); + this.methods = new ResolvedMember[reflectMethods.length + reflectCons.length]; + for (int i = 0; i < reflectMethods.length; i++) { + this.methods[i] = createGenericMethodMember(reflectMethods[i]); + } + for (int i = 0; i < reflectCons.length; i++) { + this.methods[i + reflectMethods.length] = + createGenericConstructorMember(reflectCons[i]); + } + } + return methods; + } + + private ResolvedMember createGenericMethodMember(Method forMethod) { + ReflectionBasedResolvedMemberImpl ret = + new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD, + getResolvedTypeX(), + forMethod.getModifiers(), + fromType(forMethod.getGenericReturnType()), + forMethod.getName(), + fromTypes(forMethod.getGenericParameterTypes()), + fromTypes(forMethod.getGenericExceptionTypes()), + forMethod + ); + return ret; + } + + private ResolvedMember createGenericConstructorMember(Constructor forConstructor) { + ReflectionBasedResolvedMemberImpl ret = + new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD, + getResolvedTypeX(), + forConstructor.getModifiers(), + getResolvedTypeX(), + "init", + fromTypes(forConstructor.getGenericParameterTypes()), + fromTypes(forConstructor.getGenericExceptionTypes()), + forConstructor + ); + return ret; + } + + private ResolvedMember createGenericFieldMember(Field forField) { + return new ReflectionBasedResolvedMemberImpl( + org.aspectj.weaver.Member.FIELD, + getResolvedTypeX(), + forField.getModifiers(), + fromType(forField.getGenericType()), + forField.getName(), + new UnresolvedType[0], + forField); + } + + public ResolvedMember[] getDeclaredPointcuts() { + if (pointcuts == null) { + Pointcut[] pcs = this.myType.getDeclaredPointcuts(); + pointcuts = new ResolvedMember[pcs.length]; + PointcutParser parser = new PointcutParser(); + for (int i = 0; i < pcs.length; i++) { + Class[] ptypes = pcs[i].getParameterTypes(); + String[] pnames = pcs[i].getParameterNames(); + if (pnames.length != ptypes.length) { + throw new IllegalStateException("Required parameter names not available when parsing pointcut " + pcs[i].getName() + " in type " + getResolvedTypeX().getName()); + } + PointcutParameter[] parameters = new PointcutParameter[ptypes.length]; + for (int j = 0; j < parameters.length; j++) { + parameters[j] = parser.createPointcutParameter(pnames[j],ptypes[j]); + } + String pcExpr = pcs[i].getPointcutExpression().toString(); + PointcutExpressionImpl pEx = (PointcutExpressionImpl) parser.parsePointcutExpression(pcExpr,getBaseClass(),parameters); + org.aspectj.weaver.patterns.Pointcut pc = pEx.getUnderlyingPointcut(); + UnresolvedType[] weaverPTypes = new UnresolvedType[ptypes.length]; + for (int j = 0; j < weaverPTypes.length; j++) { + weaverPTypes[j] = UnresolvedType.forName(ptypes[j].getName()); + } + pointcuts[i] = new ResolvedPointcutDefinition(getResolvedTypeX(),pcs[i].getModifiers(),pcs[i].getName(),weaverPTypes,pc); + } + } + return pointcuts; + } + + public boolean isAnnotation() { + return getBaseClass().isAnnotation(); + } + + public boolean isAnnotationStyleAspect() { + return getBaseClass().isAnnotationPresent(Aspect.class); + } + + public boolean isAnnotationWithRuntimeRetention() { + if (!isAnnotation()) return false; + if (getBaseClass().isAnnotationPresent(Retention.class)) { + Retention retention = (Retention) getBaseClass().getAnnotation(Retention.class); + RetentionPolicy policy = retention.value(); + return policy == RetentionPolicy.RUNTIME; + } else { + return false; + } + } + + public boolean isAspect() { + return this.myType.isAspect(); + } + + public boolean isEnum() { + return getBaseClass().isEnum(); + } + + public boolean isGeneric() { + //return false; // for now + return getBaseClass().getTypeParameters().length > 0; + } + + private ResolvedType fromType(Type aType) { + if (aType instanceof Class) { + return getWorld().resolve(((Class)aType).getName()); + } else if (aType instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) aType; + ResolvedType baseType = fromType(pt.getRawType()); + Type[] args = pt.getActualTypeArguments(); + ResolvedType[] resolvedArgs = fromTypes(args); + return TypeFactory.createParameterizedType(baseType, resolvedArgs, getWorld()); + } else if (aType instanceof java.lang.reflect.TypeVariable) { + java.lang.reflect.TypeVariable tv = (java.lang.reflect.TypeVariable) aType; + Type[] bounds = tv.getBounds(); + ResolvedType[] resBounds = fromTypes(bounds); + ResolvedType upperBound = resBounds[0]; + ResolvedType[] additionalBounds = new ResolvedType[0]; + if (resBounds.length > 1) { + additionalBounds = new ResolvedType[resBounds.length - 1]; + System.arraycopy(resBounds,1,additionalBounds,0,additionalBounds.length); + } + TypeVariable rt_tv = new TypeVariable(tv.getName(),upperBound,additionalBounds); + return new TypeVariableReferenceType(rt_tv,getWorld()); + } else if (aType instanceof WildcardType) { + WildcardType wildType = (WildcardType) aType; + Type[] lowerBounds = wildType.getLowerBounds(); + Type[] upperBounds = wildType.getUpperBounds(); + ResolvedType bound = null; + boolean isExtends = lowerBounds.length == 0; + if (isExtends) { + bound = fromType(upperBounds[0]); + } else { + bound = fromType(lowerBounds[0]); + } + return new BoundedReferenceType((ReferenceType)bound,isExtends,getWorld()); + } else if (aType instanceof GenericArrayType) { + GenericArrayType gt = (GenericArrayType) aType; + Type componentType = gt.getGenericComponentType(); + UnresolvedType.makeArray(fromType(componentType),1); + } + return ResolvedType.MISSING; + } + + private ResolvedType[] fromTypes(Type[] types) { + ResolvedType[] ret = new ResolvedType[types.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = fromType(types[i]); + } + return ret; + } + +} + diff --git a/weaver5/java5-testsrc/Weaver5ModuleTests.java b/weaver5/java5-testsrc/Weaver5ModuleTests.java new file mode 100644 index 000000000..434f3022a --- /dev/null +++ b/weaver5/java5-testsrc/Weaver5ModuleTests.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: (See CVS logs) + * + *******************************************************************************/ + +import org.aspectj.testing.util.TestUtil; +import org.aspectj.util.LangUtil; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + */ +public class Weaver5ModuleTests extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite(Weaver5ModuleTests.class.getName()); + if (TestUtil.is15VMOrGreater()) { +// if (LangUtil.is15VMOrGreater()) { + TestUtil.loadTestsReflectively(suite, "org.aspectj.weaver.tools.Java15PointcutExpressionTest", false); +// } +// TestUtil.loadTestsReflectively(suite, "Weaver515ModuleTests", true); + } else { + suite.addTest(TestUtil.testNamed("all tests require 1.5")); + } + return suite; + } + public static void main(String[] args) { + junit.textui.TestRunner.main(new String[] {Weaver5ModuleTests.class.getName()}); + } + +} diff --git a/weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java b/weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java new file mode 100644 index 000000000..ceb549405 --- /dev/null +++ b/weaver5/java5-testsrc/org/aspectj/weaver/tools/Java15PointcutExpressionTest.java @@ -0,0 +1,278 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.weaver.tools; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; + +import org.aspectj.lang.annotation.Pointcut; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * @author colyer + * + */ +public class Java15PointcutExpressionTest extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite("Java15PointcutExpressionTest"); + suite.addTestSuite(Java15PointcutExpressionTest.class); + return suite; + } + + private PointcutParser parser; + private Method a; + private Method b; + private Method c; + + public void testAtThis() { + PointcutExpression atThis = parser.parsePointcutExpression("@this(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)"); + ShadowMatch sMatch1 = atThis.matchesMethodExecution(a); + ShadowMatch sMatch2 = atThis.matchesMethodExecution(b); + assertTrue("maybe matches A",sMatch1.maybeMatches()); + assertTrue("maybe matches B",sMatch2.maybeMatches()); + JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new A(), new A(), new Object[0]); + assertFalse("does not match",jp1.matches()); + JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[0]); + assertTrue("matches",jp2.matches()); + } + + public void testAtTarget() { + PointcutExpression atTarget = parser.parsePointcutExpression("@target(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)"); + ShadowMatch sMatch1 = atTarget.matchesMethodExecution(a); + ShadowMatch sMatch2 = atTarget.matchesMethodExecution(b); + assertTrue("maybe matches A",sMatch1.maybeMatches()); + assertTrue("maybe matches B",sMatch2.maybeMatches()); + JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new A(), new A(), new Object[0]); + assertFalse("does not match",jp1.matches()); + JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[0]); + assertTrue("matches",jp2.matches()); + } + + public void testAtThisWithBinding() { + PointcutParameter param = parser.createPointcutParameter("a",MyAnnotation.class); + B myB = new B(); + MyAnnotation bAnnotation = B.class.getAnnotation(MyAnnotation.class); + PointcutExpression atThis = parser.parsePointcutExpression("@this(a)",A.class,new PointcutParameter[] {param}); + ShadowMatch sMatch1 = atThis.matchesMethodExecution(a); + ShadowMatch sMatch2 = atThis.matchesMethodExecution(b); + assertTrue("maybe matches A",sMatch1.maybeMatches()); + assertTrue("maybe matches B",sMatch2.maybeMatches()); + JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new A(), new A(), new Object[0]); + assertFalse("does not match",jp1.matches()); + JoinPointMatch jp2 = sMatch2.matchesJoinPoint(myB, myB, new Object[0]); + assertTrue("matches",jp2.matches()); + assertEquals(1,jp2.getParameterBindings().length); + assertEquals("should be myB's annotation",bAnnotation,jp2.getParameterBindings()[0].getBinding()); + } + + public void testAtTargetWithBinding() { + PointcutParameter param = parser.createPointcutParameter("a",MyAnnotation.class); + B myB = new B(); + MyAnnotation bAnnotation = B.class.getAnnotation(MyAnnotation.class); + PointcutExpression atThis = parser.parsePointcutExpression("@target(a)",A.class,new PointcutParameter[] {param}); + ShadowMatch sMatch1 = atThis.matchesMethodExecution(a); + ShadowMatch sMatch2 = atThis.matchesMethodExecution(b); + assertTrue("maybe matches A",sMatch1.maybeMatches()); + assertTrue("maybe matches B",sMatch2.maybeMatches()); + JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new A(), new A(), new Object[0]); + assertFalse("does not match",jp1.matches()); + JoinPointMatch jp2 = sMatch2.matchesJoinPoint(myB, myB, new Object[0]); + assertTrue("matches",jp2.matches()); + assertEquals(1,jp2.getParameterBindings().length); + assertEquals("should be myB's annotation",bAnnotation,jp2.getParameterBindings()[0].getBinding()); + } + + public void testAtArgs() { + PointcutExpression atArgs = parser.parsePointcutExpression("@args(..,org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)"); + ShadowMatch sMatch1 = atArgs.matchesMethodExecution(a); + ShadowMatch sMatch2 = atArgs.matchesMethodExecution(c); + assertTrue("never matches A",sMatch1.neverMatches()); + assertTrue("maybe matches C",sMatch2.maybeMatches()); + JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[]{new A(),new B()}); + assertTrue("matches",jp2.matches()); + + atArgs = parser.parsePointcutExpression("@args(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation,org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)"); + sMatch1 = atArgs.matchesMethodExecution(a); + sMatch2 = atArgs.matchesMethodExecution(c); + assertTrue("never matches A",sMatch1.neverMatches()); + assertTrue("maybe matches C",sMatch2.maybeMatches()); + JoinPointMatch jp1 = sMatch2.matchesJoinPoint(new A(), new A(), new Object[] {new A(), new B()}); + assertFalse("does not match",jp1.matches()); + jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[] {new B(),new B()}); + assertTrue("matches",jp2.matches()); + } + + public void testAtArgsWithBinding() { + PointcutParameter p1 = parser.createPointcutParameter("a",MyAnnotation.class); + PointcutParameter p2 = parser.createPointcutParameter("b", MyAnnotation.class); + PointcutExpression atArgs = parser.parsePointcutExpression("@args(..,a)",A.class,new PointcutParameter[] {p1}); + ShadowMatch sMatch2 = atArgs.matchesMethodExecution(c); + assertTrue("maybe matches C",sMatch2.maybeMatches()); + JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[]{new A(),new B()}); + assertTrue("matches",jp2.matches()); + assertEquals(1,jp2.getParameterBindings().length); + MyAnnotation bAnnotation = B.class.getAnnotation(MyAnnotation.class); + assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[0].getBinding()); + + atArgs = parser.parsePointcutExpression("@args(a,b)",A.class,new PointcutParameter[] {p1,p2}); + sMatch2 = atArgs.matchesMethodExecution(c); + assertTrue("maybe matches C",sMatch2.maybeMatches()); + jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[] {new B(),new B()}); + assertTrue("matches",jp2.matches()); + assertEquals(2,jp2.getParameterBindings().length); + assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[0].getBinding()); + assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[1].getBinding()); + } + + public void testAtWithin() { + PointcutExpression atWithin = parser.parsePointcutExpression("@within(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)"); + ShadowMatch sMatch1 = atWithin.matchesMethodExecution(a); + ShadowMatch sMatch2 = atWithin.matchesMethodExecution(b); + assertTrue("does not match a",sMatch1.neverMatches()); + assertTrue("matches b",sMatch2.alwaysMatches()); + } + + public void testAtWithinWithBinding() { + PointcutParameter p1 = parser.createPointcutParameter("x",MyAnnotation.class); + PointcutExpression atWithin = parser.parsePointcutExpression("@within(x)",B.class,new PointcutParameter[] {p1}); + ShadowMatch sMatch1 = atWithin.matchesMethodExecution(a); + ShadowMatch sMatch2 = atWithin.matchesMethodExecution(b); + assertTrue("does not match a",sMatch1.neverMatches()); + assertTrue("matches b",sMatch2.alwaysMatches()); + JoinPointMatch jpm = sMatch2.matchesJoinPoint(new B(), new B(), new Object[0]); + assertTrue(jpm.matches()); + assertEquals(1,jpm.getParameterBindings().length); + MyAnnotation bAnnotation = B.class.getAnnotation(MyAnnotation.class); + assertEquals("annotation on B",bAnnotation,jpm.getParameterBindings()[0].getBinding()); + } + + public void testAtWithinCode() { + PointcutExpression atWithinCode = parser.parsePointcutExpression("@withincode(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)"); + ShadowMatch sMatch1 = atWithinCode.matchesMethodCall(a,b); + ShadowMatch sMatch2 = atWithinCode.matchesMethodCall(a,a); + assertTrue("does not match from b",sMatch1.neverMatches()); + assertTrue("matches from a",sMatch2.alwaysMatches()); + } + + public void testAtWithinCodeWithBinding() { + PointcutParameter p1 = parser.createPointcutParameter("x",MyAnnotation.class); + PointcutExpression atWithinCode = parser.parsePointcutExpression("@withincode(x)",A.class,new PointcutParameter[] {p1}); + ShadowMatch sMatch2 = atWithinCode.matchesMethodCall(a,a); + assertTrue("matches from a",sMatch2.alwaysMatches()); + JoinPointMatch jpm = sMatch2.matchesJoinPoint(new A(), new A(), new Object[0]); + assertEquals(1,jpm.getParameterBindings().length); + MyAnnotation annOna = a.getAnnotation(MyAnnotation.class); + assertEquals("MyAnnotation on a",annOna,jpm.getParameterBindings()[0].getBinding()); + } + + public void testAtAnnotation() { + PointcutExpression atAnnotation = parser.parsePointcutExpression("@annotation(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)"); + ShadowMatch sMatch1 = atAnnotation.matchesMethodCall(b,a); + ShadowMatch sMatch2 = atAnnotation.matchesMethodCall(a,a); + assertTrue("does not match call to b",sMatch1.neverMatches()); + assertTrue("matches call to a",sMatch2.alwaysMatches()); + } + + public void testAtAnnotationWithBinding() { + PointcutParameter p1 = parser.createPointcutParameter("x",MyAnnotation.class); + PointcutExpression atAnnotation = parser.parsePointcutExpression("@annotation(x)",A.class,new PointcutParameter[] {p1}); + ShadowMatch sMatch2 = atAnnotation.matchesMethodCall(a,a); + assertTrue("matches call to a",sMatch2.alwaysMatches()); + JoinPointMatch jpm = sMatch2.matchesJoinPoint(new A(), new A(), new Object[0]); + assertTrue(jpm.matches()); + assertEquals(1,jpm.getParameterBindings().length); + MyAnnotation annOna = a.getAnnotation(MyAnnotation.class); + assertEquals("MyAnnotation on a",annOna,jpm.getParameterBindings()[0].getBinding()); + } + + public void testReferencePointcutNoParams() { + PointcutExpression pc = parser.parsePointcutExpression("foo()",C.class,new PointcutParameter[0]); + ShadowMatch sMatch1 = pc.matchesMethodCall(a,b); + ShadowMatch sMatch2 = pc.matchesMethodExecution(a); + assertTrue("no match on call",sMatch1.neverMatches()); + assertTrue("match on execution",sMatch2.alwaysMatches()); + + pc = parser.parsePointcutExpression("org.aspectj.weaver.tools.Java15PointcutExpressionTest.C.foo()"); + sMatch1 = pc.matchesMethodCall(a,b); + sMatch2 = pc.matchesMethodExecution(a); + assertTrue("no match on call",sMatch1.neverMatches()); + assertTrue("match on execution",sMatch2.alwaysMatches()); + } + + public void testReferencePointcutParams() { + PointcutParameter p1 = parser.createPointcutParameter("x",A.class); + PointcutExpression pc = parser.parsePointcutExpression("goo(x)",C.class,new PointcutParameter[] {p1}); + + ShadowMatch sMatch1 = pc.matchesMethodCall(a,b); + ShadowMatch sMatch2 = pc.matchesMethodExecution(a); + assertTrue("no match on call",sMatch1.neverMatches()); + assertTrue("match on execution",sMatch2.maybeMatches()); + A anA = new A(); + JoinPointMatch jpm = sMatch2.matchesJoinPoint(anA, new A(), new Object[0]); + assertTrue(jpm.matches()); + assertEquals("should be bound to anA",anA,jpm.getParameterBindings()[0].getBinding()); + + } + + public void testExecutionWithClassFileRetentionAnnotation() { + PointcutExpression pc1 = parser.parsePointcutExpression("execution(@org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation * *(..))"); + PointcutExpression pc2 = parser.parsePointcutExpression("execution(@org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyClassFileRetentionAnnotation * *(..))"); + ShadowMatch sMatch = pc1.matchesMethodExecution(a); + assertTrue("matches",sMatch.alwaysMatches()); + sMatch = pc2.matchesMethodExecution(a); + assertTrue("no match",sMatch.neverMatches()); + sMatch = pc1.matchesMethodExecution(b); + assertTrue("no match",sMatch.neverMatches()); + sMatch = pc2.matchesMethodExecution(b); + assertTrue("matches",sMatch.alwaysMatches()); + } + + protected void setUp() throws Exception { + super.setUp(); + parser = new PointcutParser(); + a = A.class.getMethod("a"); + b = B.class.getMethod("b"); + c = B.class.getMethod("c",new Class[] {A.class,B.class}); + } + + @Retention(RetentionPolicy.RUNTIME) + private @interface MyAnnotation {} + + private @interface MyClassFileRetentionAnnotation {} + + private static class A { + @MyAnnotation public void a() {} + } + + @MyAnnotation + private static class B { + @MyClassFileRetentionAnnotation public void b() {} + public void c(A anA, B aB) {} + } + + private static class C { + + @Pointcut("execution(* *(..))") + public void foo() {} + + @Pointcut(value="execution(* *(..)) && this(x)", argNames="x") + public void goo(A x) {} + } + +} + + -- 2.39.5