diff options
author | aclement <aclement> | 2005-09-26 15:36:21 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-09-26 15:36:21 +0000 |
commit | 0ea99cad049a88bb2465472f8eba9800ae9d44f3 (patch) | |
tree | 86a87506b8a1d8311af3deaf65df77f4cf653598 /weaver5/java5-src | |
parent | d485f9bcc4df37aef60863fceb88654bbd32b680 (diff) | |
download | aspectj-0ea99cad049a88bb2465472f8eba9800ae9d44f3.tar.gz aspectj-0ea99cad049a88bb2465472f8eba9800ae9d44f3.zip |
weaver5 split out so weaver can continue to be built with Java1.3
Diffstat (limited to 'weaver5/java5-src')
-rw-r--r-- | weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java | 152 | ||||
-rw-r--r-- | weaver5/java5-src/org/aspectj/weaver/reflect/Java15ReflectionBasedReferenceTypeDelegate.java | 310 |
2 files changed, 462 insertions, 0 deletions
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<UnresolvedType> annSet = new HashSet<UnresolvedType>(); + 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<UnresolvedType> annSet = new HashSet<UnresolvedType>(); + 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; + } + +} + |