@@ -28,44 +28,51 @@ 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.AnnotationAJ; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.WeakClassLoaderReference; | |||
import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.bcel.BcelAnnotation; | |||
/** | |||
* Find the given annotation (if present) on the given object | |||
* | |||
* | |||
*/ | |||
public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { | |||
private Repository bcelRepository; | |||
private WeakClassLoaderReference classLoaderRef; | |||
private World world; | |||
// must have no-arg constructor for reflective construction | |||
public Java15AnnotationFinder() { | |||
} | |||
public void setClassLoader(ClassLoader aLoader) { | |||
// TODO: No easy way to ask the world factory for the right kind of repository so | |||
// TODO: No easy way to ask the world factory for the right kind of | |||
// repository so | |||
// default to the safe one! (pr160674) | |||
this.classLoaderRef = new WeakClassLoaderReference(aLoader); | |||
this.bcelRepository = new NonCachingClassLoaderRepository(classLoaderRef); | |||
this.classLoaderRef = new WeakClassLoaderReference(aLoader); | |||
this.bcelRepository = new NonCachingClassLoaderRepository( | |||
classLoaderRef); | |||
} | |||
public void setWorld(World aWorld) { | |||
this.world = aWorld; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.reflect.AnnotationFinder#getAnnotation(org.aspectj.weaver.ResolvedType, java.lang.Object) | |||
/* | |||
* (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<? extends Annotation> annotationClass = (Class<? extends Annotation>) Class.forName(annotationType.getName(), false, | |||
getClassLoader()); | |||
Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) Class | |||
.forName(annotationType.getName(), false, getClassLoader()); | |||
if (onObject.getClass().isAnnotationPresent(annotationClass)) { | |||
return onObject.getClass().getAnnotation(annotationClass); | |||
} | |||
@@ -75,9 +82,11 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { | |||
return null; | |||
} | |||
public Object getAnnotationFromClass(ResolvedType annotationType, Class aClass) { | |||
public Object getAnnotationFromClass(ResolvedType annotationType, | |||
Class aClass) { | |||
try { | |||
Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) Class.forName(annotationType.getName(),false,getClassLoader()); | |||
Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) Class | |||
.forName(annotationType.getName(), false, getClassLoader()); | |||
if (aClass.isAnnotationPresent(annotationClass)) { | |||
return aClass.getAnnotation(annotationClass); | |||
} | |||
@@ -86,12 +95,15 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { | |||
} | |||
return null; | |||
} | |||
public Object getAnnotationFromMember(ResolvedType annotationType, Member aMember) { | |||
if (!(aMember instanceof AccessibleObject)) 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(),false,getClassLoader()); | |||
Class annotationClass = Class.forName(annotationType.getName(), | |||
false, getClassLoader()); | |||
if (ao.isAnnotationPresent(annotationClass)) { | |||
return ao.getAnnotation(annotationClass); | |||
} | |||
@@ -100,67 +112,84 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { | |||
} | |||
return null; | |||
} | |||
private ClassLoader getClassLoader() { | |||
return classLoaderRef.getClassLoader(); | |||
} | |||
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 | |||
public AnnotationAJ 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()); | |||
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); | |||
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()+"'"); | |||
// 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); | |||
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); | |||
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(); | |||
// OPTIMIZE make constant 0 size array for sharing | |||
if (anns == null) anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0]; | |||
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++) { | |||
for (int i = 0; i < anns.length; i++) { | |||
if (anns[i].getTypeSignature().equals(ofType.getSignature())) { | |||
return new AnnotationX(anns[i],world); | |||
return new BcelAnnotation(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()); | |||
JavaClass jc = bcelRepository.loadClass(onMember | |||
.getDeclaringClass()); | |||
if (onMember instanceof Method) { | |||
org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method)onMember); | |||
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()+"'"); | |||
// 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]; | |||
Attribute attribute = attrs[i]; | |||
if (attribute.getName().equals("AnnotationDefault")) { | |||
AnnotationDefault def = (AnnotationDefault)attribute; | |||
AnnotationDefault def = (AnnotationDefault) attribute; | |||
return def.getElementValue().stringifyValue(); | |||
} | |||
} | |||
@@ -170,156 +199,191 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { | |||
} 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 | |||
// so we bail out to Bcel and then chuck away the JavaClass so that we don't hog | |||
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()); | |||
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); | |||
org.aspectj.apache.bcel.classfile.Method bcelMethod = jc | |||
.getMethod((Method) onMember); | |||
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()+"'"); | |||
// 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); | |||
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); | |||
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(); | |||
// OPTIMIZE make this a constant 0 size array | |||
if (anns == null) anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0]; | |||
if (anns == null) | |||
anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0]; | |||
// convert to our Annotation type | |||
Set<ResolvedType> annSet = new HashSet<ResolvedType>(); | |||
for (int i = 0; i < anns.length; i++) { | |||
annSet.add(world.resolve(UnresolvedType.forSignature(anns[i].getTypeSignature()))); | |||
annSet.add(world.resolve(UnresolvedType.forSignature(anns[i] | |||
.getTypeSignature()))); | |||
} | |||
return annSet; | |||
} catch (ClassNotFoundException cnfEx) { | |||
// just use reflection then | |||
} | |||
AccessibleObject ao = (AccessibleObject) onMember; | |||
Annotation[] anns = ao.getDeclaredAnnotations(); | |||
Set<UnresolvedType> annSet = new HashSet<UnresolvedType>(); | |||
for (int i = 0; i < anns.length; i++) { | |||
annSet.add(UnresolvedType.forName(anns[i].annotationType().getName()).resolve(world)); | |||
annSet.add(UnresolvedType.forName( | |||
anns[i].annotationType().getName()).resolve(world)); | |||
} | |||
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 | |||
// 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.AnnotationGen[] anns =jc.getAnnotations(); | |||
org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = jc | |||
.getAnnotations(); | |||
bcelRepository.clear(); | |||
if (anns == null) return new ResolvedType[0]; | |||
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(UnresolvedType.forSignature(anns[i].getTypeSignature())); | |||
ret[i] = inWorld.resolve(UnresolvedType.forSignature(anns[i] | |||
.getTypeSignature())); | |||
} | |||
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()); | |||
ret[i] = inWorld.resolve(classAnnotations[i].annotationType() | |||
.getName()); | |||
} | |||
return ret; | |||
} | |||
public String[] getParameterNames(Member forMember) { | |||
if (!(forMember instanceof AccessibleObject)) return null; | |||
if (!(forMember instanceof AccessibleObject)) | |||
return null; | |||
try { | |||
JavaClass jc = bcelRepository.loadClass(forMember.getDeclaringClass()); | |||
JavaClass jc = bcelRepository.loadClass(forMember | |||
.getDeclaringClass()); | |||
LocalVariableTable lvt = null; | |||
int numVars = 0; | |||
if (forMember instanceof Method) { | |||
org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method)forMember); | |||
org.aspectj.apache.bcel.classfile.Method bcelMethod = jc | |||
.getMethod((Method) forMember); | |||
lvt = bcelMethod.getLocalVariableTable(); | |||
numVars = bcelMethod.getArgumentTypes().length; | |||
} else if (forMember instanceof Constructor) { | |||
org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor)forMember); | |||
org.aspectj.apache.bcel.classfile.Method bcelCons = jc | |||
.getMethod((Constructor) forMember); | |||
lvt = bcelCons.getLocalVariableTable(); | |||
numVars = bcelCons.getArgumentTypes().length; | |||
} | |||
return getParameterNamesFromLVT(lvt,numVars); | |||
return getParameterNamesFromLVT(lvt, numVars); | |||
} catch (ClassNotFoundException cnfEx) { | |||
; // no luck | |||
} | |||
return null; | |||
} | |||
private String[] getParameterNamesFromLVT(LocalVariableTable lvt, int numVars) { | |||
if (lvt == null) | |||
return null;// pr222987 - prevent NPE | |||
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... | |||
return null; | |||
} | |||
String[] ret = new String[numVars]; | |||
for(int i = 0; i < numVars; i++) { | |||
ret[i] = vars[i+1].getName(); | |||
for (int i = 0; i < numVars; i++) { | |||
ret[i] = vars[i + 1].getName(); | |||
} | |||
return ret; | |||
} | |||
public static final ResolvedType[][] NO_PARAMETER_ANNOTATIONS = new ResolvedType[][]{}; | |||
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 | |||
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()); | |||
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); | |||
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()+"'"); | |||
// 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); | |||
org.aspectj.apache.bcel.classfile.Method bcelCons = jc | |||
.getMethod((Constructor) onMember); | |||
anns = bcelCons.getParameterAnnotations(); | |||
} else if (onMember instanceof Field) { | |||
// anns = null; | |||
// 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; | |||
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) { | |||
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())); | |||
for (int j = 0; j < anns[i].length; j++) { | |||
result[i][j] = world.resolve(UnresolvedType | |||
.forSignature(anns[i][j].getTypeSignature())); | |||
} | |||
} | |||
} | |||
@@ -327,29 +391,32 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { | |||
} catch (ClassNotFoundException cnfEx) { | |||
// just use reflection then | |||
} | |||
// reflection... | |||
AccessibleObject ao = (AccessibleObject) onMember; | |||
Annotation[][] anns = null; | |||
if (onMember instanceof Method) { | |||
anns = ((Method)ao).getParameterAnnotations(); | |||
anns = ((Method) ao).getParameterAnnotations(); | |||
} else if (onMember instanceof Constructor) { | |||
anns = ((Constructor)ao).getParameterAnnotations(); | |||
anns = ((Constructor) ao).getParameterAnnotations(); | |||
} else if (onMember instanceof Field) { | |||
// anns = null; | |||
// anns = null; | |||
} | |||
if (anns == null) return NO_PARAMETER_ANNOTATIONS; | |||
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) { | |||
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); | |||
for (int j = 0; j < anns[i].length; j++) { | |||
result[i][j] = UnresolvedType.forName( | |||
anns[i][j].annotationType().getName()).resolve( | |||
world); | |||
} | |||
} | |||
} | |||
return result; | |||
} | |||
} |
@@ -24,7 +24,7 @@ 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.AnnotationAJ; | |||
import org.aspectj.weaver.ReferenceType; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedPointcutDefinition; | |||
@@ -37,13 +37,12 @@ import org.aspectj.weaver.tools.PointcutDesignatorHandler; | |||
import org.aspectj.weaver.tools.PointcutParameter; | |||
/** | |||
* @author colyer | |||
* Provides Java 5 behaviour in reflection based delegates (overriding | |||
* 1.4 behaviour from superclass where appropriate) | |||
* @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; | |||
@@ -56,38 +55,42 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends | |||
private JavaLangTypeToResolvedTypeConverter typeConverter; | |||
private Java15AnnotationFinder annotationFinder = null; | |||
private ArgNameFinder argNameFinder = null; | |||
public Java15ReflectionBasedReferenceTypeDelegate() {} | |||
public Java15ReflectionBasedReferenceTypeDelegate() { | |||
} | |||
@Override | |||
public void initialize(ReferenceType aType, Class aClass, ClassLoader classLoader, World aWorld) { | |||
public void initialize(ReferenceType aType, Class aClass, | |||
ClassLoader classLoader, World aWorld) { | |||
super.initialize(aType, aClass, classLoader, aWorld); | |||
myType = AjTypeSystem.getAjType(aClass); | |||
annotationFinder = new Java15AnnotationFinder(); | |||
argNameFinder = annotationFinder; | |||
annotationFinder.setClassLoader(this.classLoaderReference.getClassLoader()); | |||
annotationFinder.setClassLoader(this.classLoaderReference | |||
.getClassLoader()); | |||
annotationFinder.setWorld(aWorld); | |||
this.typeConverter = new JavaLangTypeToResolvedTypeConverter(aWorld); | |||
} | |||
public ReferenceType buildGenericType() { | |||
return (ReferenceType) UnresolvedType.forGenericTypeVariables( | |||
getResolvedTypeX().getSignature(), | |||
getTypeVariables()).resolve(getWorld()); | |||
return (ReferenceType) UnresolvedType.forGenericTypeVariables( | |||
getResolvedTypeX().getSignature(), getTypeVariables()).resolve( | |||
getWorld()); | |||
} | |||
public AnnotationX[] getAnnotations() { | |||
public AnnotationAJ[] getAnnotations() { | |||
// AMC - we seem not to need to implement this method... | |||
//throw new UnsupportedOperationException("getAnnotations on Java15ReflectionBasedReferenceTypeDelegate is not implemented yet"); | |||
// FIXME is this the right implementation in the reflective case? | |||
// throw new UnsupportedOperationException( | |||
// "getAnnotations on Java15ReflectionBasedReferenceTypeDelegate is not implemented yet" | |||
// ); | |||
// FIXME is this the right implementation in the reflective case? | |||
return super.getAnnotations(); | |||
} | |||
public ResolvedType[] getAnnotationTypes() { | |||
if (annotations == null) { | |||
annotations = annotationFinder.getAnnotations(getBaseClass(), getWorld()); | |||
annotations = annotationFinder.getAnnotations(getBaseClass(), | |||
getWorld()); | |||
} | |||
return annotations; | |||
} | |||
@@ -96,11 +99,12 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends | |||
ResolvedType[] myAnns = getAnnotationTypes(); | |||
ResolvedType toLookFor = ofType.resolve(getWorld()); | |||
for (int i = 0; i < myAnns.length; i++) { | |||
if (myAnns[i] == toLookFor) return true; | |||
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) { | |||
@@ -113,14 +117,14 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends | |||
} | |||
return fields; | |||
} | |||
public String getDeclaredGenericSignature() { | |||
if (this.genericSignature == null && isGeneric()) { | |||
} | |||
return genericSignature; | |||
} | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
if (superInterfaces == null) { | |||
Type[] genericInterfaces = getBaseClass().getGenericInterfaces(); | |||
@@ -128,45 +132,58 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends | |||
} | |||
return superInterfaces; | |||
} | |||
// If the superclass is null, return Object - same as bcel does | |||
public ResolvedType getSuperclass() { | |||
if (superclass == null && getBaseClass()!=Object.class) {// superclass of Object is null | |||
Type t = this.getBaseClass().getGenericSuperclass(); | |||
if (t!=null) superclass = typeConverter.fromType(t); | |||
if (t==null) superclass = getWorld().resolve(UnresolvedType.OBJECT); | |||
if (superclass == null && getBaseClass() != Object.class) {// superclass | |||
// of Object | |||
// is null | |||
Type t = this.getBaseClass().getGenericSuperclass(); | |||
if (t != null) | |||
superclass = typeConverter.fromType(t); | |||
if (t == null) | |||
superclass = getWorld().resolve(UnresolvedType.OBJECT); | |||
} | |||
return superclass; | |||
return superclass; | |||
} | |||
public TypeVariable[] getTypeVariables() { | |||
TypeVariable[] workInProgressSetOfVariables = (TypeVariable[])getResolvedTypeX().getWorld().getTypeVariablesCurrentlyBeingProcessed(getBaseClass()); | |||
if (workInProgressSetOfVariables!=null) { | |||
TypeVariable[] workInProgressSetOfVariables = (TypeVariable[]) getResolvedTypeX() | |||
.getWorld().getTypeVariablesCurrentlyBeingProcessed( | |||
getBaseClass()); | |||
if (workInProgressSetOfVariables != null) { | |||
return workInProgressSetOfVariables; | |||
} | |||
if (this.typeVariables == null) { | |||
java.lang.reflect.TypeVariable[] tVars = this.getBaseClass().getTypeParameters(); | |||
java.lang.reflect.TypeVariable[] tVars = this.getBaseClass() | |||
.getTypeParameters(); | |||
TypeVariable[] rTypeVariables = new TypeVariable[tVars.length]; | |||
// basic initialization | |||
for (int i = 0; i < tVars.length; i++) { | |||
rTypeVariables[i] = new TypeVariable(tVars[i].getName()); | |||
rTypeVariables[i] = new TypeVariable(tVars[i].getName()); | |||
} | |||
// stash it | |||
this.getResolvedTypeX().getWorld().recordTypeVariablesCurrentlyBeingProcessed(getBaseClass(), rTypeVariables); | |||
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])); | |||
TypeVariableReferenceType tvrt = ((TypeVariableReferenceType) typeConverter | |||
.fromType(tVars[i])); | |||
TypeVariable tv = tvrt.getTypeVariable(); | |||
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()); | |||
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()); | |||
} | |||
this.getResolvedTypeX().getWorld() | |||
.forgetTypeVariablesCurrentlyBeingProcessed(getBaseClass()); | |||
} | |||
return this.typeVariables; | |||
} | |||
@@ -176,73 +193,73 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends | |||
if (methods == null) { | |||
Method[] reflectMethods = this.myType.getDeclaredMethods(); | |||
Constructor[] reflectCons = this.myType.getDeclaredConstructors(); | |||
ResolvedMember[] rMethods = new ResolvedMember[reflectMethods.length + reflectCons.length]; | |||
ResolvedMember[] rMethods = new ResolvedMember[reflectMethods.length | |||
+ reflectCons.length]; | |||
for (int i = 0; i < reflectMethods.length; i++) { | |||
rMethods[i] = createGenericMethodMember(reflectMethods[i]); | |||
rMethods[i] = createGenericMethodMember(reflectMethods[i]); | |||
} | |||
for (int i = 0; i < reflectCons.length; i++) { | |||
rMethods[i + reflectMethods.length] = | |||
createGenericConstructorMember(reflectCons[i]); | |||
rMethods[i + reflectMethods.length] = createGenericConstructorMember(reflectCons[i]); | |||
} | |||
this.methods = rMethods; | |||
} | |||
return methods; | |||
} | |||
/** | |||
* Returns the generic type, regardless of the resolvedType we 'know about' | |||
*/ | |||
public ResolvedType getGenericResolvedType() { | |||
ResolvedType rt = getResolvedTypeX(); | |||
if (rt.isParameterizedType() || rt.isRawType()) return rt.getGenericType(); | |||
if (rt.isParameterizedType() || rt.isRawType()) | |||
return rt.getGenericType(); | |||
return rt; | |||
} | |||
private ResolvedMember createGenericMethodMember(Method forMethod) { | |||
ReflectionBasedResolvedMemberImpl ret = | |||
new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD, | |||
getGenericResolvedType(), | |||
forMethod.getModifiers(), | |||
typeConverter.fromType(forMethod.getReturnType()), | |||
forMethod.getName(), | |||
typeConverter.fromTypes(forMethod.getParameterTypes()), | |||
typeConverter.fromTypes(forMethod.getExceptionTypes()), | |||
forMethod | |||
); | |||
ReflectionBasedResolvedMemberImpl ret = new ReflectionBasedResolvedMemberImpl( | |||
org.aspectj.weaver.Member.METHOD, getGenericResolvedType(), | |||
forMethod.getModifiers(), typeConverter.fromType(forMethod | |||
.getReturnType()), forMethod.getName(), typeConverter | |||
.fromTypes(forMethod.getParameterTypes()), | |||
typeConverter.fromTypes(forMethod.getExceptionTypes()), | |||
forMethod); | |||
ret.setAnnotationFinder(this.annotationFinder); | |||
ret.setGenericSignatureInformationProvider(new Java15GenericSignatureInformationProvider(this.getWorld())); | |||
ret | |||
.setGenericSignatureInformationProvider(new Java15GenericSignatureInformationProvider( | |||
this.getWorld())); | |||
return ret; | |||
} | |||
private ResolvedMember createGenericConstructorMember(Constructor forConstructor) { | |||
ReflectionBasedResolvedMemberImpl ret = | |||
new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD, | |||
getGenericResolvedType(), | |||
forConstructor.getModifiers(), | |||
// to return what BCEL returns the return type is void | |||
ResolvedType.VOID,//getGenericResolvedType(), | |||
"<init>", | |||
typeConverter.fromTypes(forConstructor.getParameterTypes()), | |||
typeConverter.fromTypes(forConstructor.getExceptionTypes()), | |||
forConstructor | |||
); | |||
private ResolvedMember createGenericConstructorMember( | |||
Constructor forConstructor) { | |||
ReflectionBasedResolvedMemberImpl ret = new ReflectionBasedResolvedMemberImpl( | |||
org.aspectj.weaver.Member.METHOD, | |||
getGenericResolvedType(), | |||
forConstructor.getModifiers(), | |||
// to return what BCEL returns the return type is void | |||
ResolvedType.VOID,// getGenericResolvedType(), | |||
"<init>", typeConverter.fromTypes(forConstructor | |||
.getParameterTypes()), typeConverter | |||
.fromTypes(forConstructor.getExceptionTypes()), | |||
forConstructor); | |||
ret.setAnnotationFinder(this.annotationFinder); | |||
ret.setGenericSignatureInformationProvider(new Java15GenericSignatureInformationProvider(this.getWorld())); | |||
ret | |||
.setGenericSignatureInformationProvider(new Java15GenericSignatureInformationProvider( | |||
this.getWorld())); | |||
return ret; | |||
} | |||
private ResolvedMember createGenericFieldMember(Field forField) { | |||
ReflectionBasedResolvedMemberImpl ret = | |||
new ReflectionBasedResolvedMemberImpl( | |||
org.aspectj.weaver.Member.FIELD, | |||
getGenericResolvedType(), | |||
forField.getModifiers(), | |||
typeConverter.fromType(forField.getType()), | |||
forField.getName(), | |||
new UnresolvedType[0], | |||
ReflectionBasedResolvedMemberImpl ret = new ReflectionBasedResolvedMemberImpl( | |||
org.aspectj.weaver.Member.FIELD, getGenericResolvedType(), | |||
forField.getModifiers(), typeConverter.fromType(forField | |||
.getType()), forField.getName(), new UnresolvedType[0], | |||
forField); | |||
ret.setAnnotationFinder(this.annotationFinder); | |||
ret.setGenericSignatureInformationProvider(new Java15GenericSignatureInformationProvider(this.getWorld())); | |||
ret | |||
.setGenericSignatureInformationProvider(new Java15GenericSignatureInformationProvider( | |||
this.getWorld())); | |||
return ret; | |||
} | |||
@@ -253,27 +270,38 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends | |||
InternalUseOnlyPointcutParser parser = null; | |||
World world = getWorld(); | |||
if (world instanceof ReflectionWorld) { | |||
parser = new InternalUseOnlyPointcutParser(classLoaderReference.getClassLoader(), (ReflectionWorld) getWorld()); | |||
parser = new InternalUseOnlyPointcutParser(classLoaderReference | |||
.getClassLoader(), (ReflectionWorld) getWorld()); | |||
} else { | |||
parser = new InternalUseOnlyPointcutParser(classLoaderReference.getClassLoader()); | |||
parser = new InternalUseOnlyPointcutParser(classLoaderReference | |||
.getClassLoader()); | |||
} | |||
Set additionalPointcutHandlers = world | |||
.getRegisteredPointcutHandlers(); | |||
for (Iterator handlerIterator = additionalPointcutHandlers | |||
.iterator(); handlerIterator.hasNext();) { | |||
PointcutDesignatorHandler handler = (PointcutDesignatorHandler) handlerIterator | |||
.next(); | |||
parser.registerPointcutDesignatorHandler(handler); | |||
} | |||
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 | |||
// 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 | |||
for (int i = 0; i < pcs.length; i++) { | |||
AjType<?>[] ptypes = pcs[i].getParameterTypes(); | |||
UnresolvedType[] weaverPTypes = new UnresolvedType[ptypes.length]; | |||
for (int j = 0; j < weaverPTypes.length; j++) { | |||
weaverPTypes[j] = this.typeConverter.fromType(ptypes[j].getJavaClass()) ; | |||
weaverPTypes[j] = this.typeConverter.fromType(ptypes[j] | |||
.getJavaClass()); | |||
} | |||
pointcuts[i] = new DeferredResolvedPointcutDefinition(getResolvedTypeX(),pcs[i].getModifiers(),pcs[i].getName(),weaverPTypes); | |||
pointcuts[i] = new DeferredResolvedPointcutDefinition( | |||
getResolvedTypeX(), pcs[i].getModifiers(), pcs[i] | |||
.getName(), weaverPTypes); | |||
} | |||
// phase 2, now go back round and resolve in-place all of the pointcuts | |||
// phase 2, now go back round and resolve in-place all of the | |||
// pointcuts | |||
PointcutParameter[][] parameters = new PointcutParameter[pcs.length][]; | |||
for (int i = 0; i < pcs.length; i++) { | |||
AjType<?>[] ptypes = pcs[i].getParameterTypes(); | |||
@@ -281,73 +309,84 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends | |||
if (pnames.length != ptypes.length) { | |||
pnames = tryToDiscoverParameterNames(pcs[i]); | |||
if (pnames == null || (pnames.length != ptypes.length)) { | |||
throw new IllegalStateException("Required parameter names not available when parsing pointcut " + pcs[i].getName() + " in type " + getResolvedTypeX().getName()); | |||
throw new IllegalStateException( | |||
"Required parameter names not available when parsing pointcut " | |||
+ pcs[i].getName() + " in type " | |||
+ getResolvedTypeX().getName()); | |||
} | |||
} | |||
parameters[i] = new PointcutParameter[ptypes.length]; | |||
for (int j = 0; j < parameters[i].length; j++) { | |||
parameters[i][j] = parser.createPointcutParameter(pnames[j],ptypes[j].getJavaClass()); | |||
} String pcExpr = pcs[i].getPointcutExpression().toString(); | |||
org.aspectj.weaver.patterns.Pointcut pc = parser.resolvePointcutExpression(pcExpr,getBaseClass(),parameters[i]); | |||
((ResolvedPointcutDefinition)pointcuts[i]).setParameterNames(pnames); | |||
((ResolvedPointcutDefinition)pointcuts[i]).setPointcut(pc); | |||
parameters[i][j] = parser.createPointcutParameter( | |||
pnames[j], ptypes[j].getJavaClass()); | |||
} | |||
String pcExpr = pcs[i].getPointcutExpression().toString(); | |||
org.aspectj.weaver.patterns.Pointcut pc = parser | |||
.resolvePointcutExpression(pcExpr, getBaseClass(), | |||
parameters[i]); | |||
((ResolvedPointcutDefinition) pointcuts[i]) | |||
.setParameterNames(pnames); | |||
((ResolvedPointcutDefinition) pointcuts[i]).setPointcut(pc); | |||
} | |||
// phase 3, now concretize them all | |||
for (int i = 0; i < pointcuts.length; i++) { | |||
ResolvedPointcutDefinition rpd = (ResolvedPointcutDefinition) pointcuts[i]; | |||
rpd.setPointcut(parser.concretizePointcutExpression(rpd.getPointcut(), getBaseClass(), parameters[i])); | |||
rpd.setPointcut(parser.concretizePointcutExpression(rpd | |||
.getPointcut(), getBaseClass(), parameters[i])); | |||
} | |||
} | |||
return pointcuts; | |||
} | |||
// for @AspectJ pointcuts compiled by javac only... | |||
private String[] tryToDiscoverParameterNames(Pointcut pcut) { | |||
Method[] ms = pcut.getDeclaringType().getJavaClass().getDeclaredMethods(); | |||
for(Method m : ms) { | |||
Method[] ms = pcut.getDeclaringType().getJavaClass() | |||
.getDeclaredMethods(); | |||
for (Method m : ms) { | |||
if (m.getName().equals(pcut.getName())) { | |||
return argNameFinder.getParameterNames(m); | |||
} | |||
} | |||
return null; | |||
} | |||
public boolean isAnnotation() { | |||
return getBaseClass().isAnnotation(); | |||
} | |||
public boolean isAnnotationStyleAspect() { | |||
return getBaseClass().isAnnotationPresent(Aspect.class); | |||
} | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
if (!isAnnotation()) return false; | |||
if (!isAnnotation()) | |||
return false; | |||
if (getBaseClass().isAnnotationPresent(Retention.class)) { | |||
Retention retention = (Retention) getBaseClass().getAnnotation(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 false; // for now | |||
return getBaseClass().getTypeParameters().length > 0; | |||
} | |||
@Override | |||
public boolean isAnonymous() { | |||
public boolean isAnonymous() { | |||
return this.myClass.isAnonymousClass(); | |||
} | |||
} | |||