* ******************************************************************/
package org.aspectj.weaver.bcel;
-import java.util.Iterator;
import java.util.List;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
+import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
private AnnotationAccessVar annoAccessor;
private ResolvedType annoFieldOfInterest;
+ private String name;
+ private int elementValueType;
- public AnnotationAccessFieldVar(AnnotationAccessVar aav, ResolvedType annoFieldOfInterest) {
+ public AnnotationAccessFieldVar(AnnotationAccessVar aav, ResolvedType annoFieldOfInterest, String name) {
super(annoFieldOfInterest, 0);
this.annoAccessor = aav;
+ this.name = name;
+ String sig = annoFieldOfInterest.getSignature();
+ if (sig.length() == 1) {
+ switch (sig.charAt(0)) {
+ case 'I':
+ elementValueType = ElementValue.PRIMITIVE_INT;
+ break;
+ default:
+ throw new IllegalStateException(sig);
+ }
+ } else if (sig.equals("Ljava/lang/String;")) {
+ elementValueType = ElementValue.STRING;
+ } else if (annoFieldOfInterest.isEnum()) {
+ elementValueType = ElementValue.ENUM_CONSTANT;
+ } else {
+ throw new IllegalStateException(sig);
+ }
this.annoFieldOfInterest = annoFieldOfInterest;
}
@Override
public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
- // Only possible to do annotation field value extraction at
- // MethodExecution
+ // Only possible to do annotation field value extraction at MethodExecution
if (annoAccessor.getKind() != Shadow.MethodExecution) {
return;
}
String annotationOfInterestSignature = annoAccessor.getType().getSignature();
- // So we have an entity that has an annotation on and within it is the
- // value we want
+ // So we have an entity that has an annotation on and within it is the value we want
Member holder = annoAccessor.getMember();
AnnotationAJ[] annos = holder.getAnnotations();
- for (int i = 0; i < annos.length; i++) {
- AnnotationGen annotation = ((BcelAnnotation) annos[i]).getBcelAnnotation();
+ for (AnnotationAJ anno : annos) {
+ AnnotationGen annotation = ((BcelAnnotation) anno).getBcelAnnotation();
+ boolean foundValueInAnnotationUsage = false;
if (annotation.getTypeSignature().equals(annotationOfInterestSignature)) {
- List<NameValuePair> vals = annotation.getValues();
- boolean doneAndDusted = false;
- for (Iterator<NameValuePair> iterator = vals.iterator(); iterator.hasNext();) {
- NameValuePair object = iterator.next();
- Object o = object.getValue();
+ ResolvedMember[] annotationFields = toType.getWorld()
+ .resolve(UnresolvedType.forSignature(annotation.getTypeSignature())).getDeclaredMethods();
+ // Check how many fields there are of the type we are looking for. If >1 then we'll need
+ // to use the name to choose the right one
+ int countOfType = 0;
+ for (ResolvedMember annotationField : annotationFields) {
+ if (annotationField.getType().equals(annoFieldOfInterest)) {
+ countOfType++;
+ }
+ }
+
+ // this block deals with an annotation that has actual values (i.e. not falling back to default values)
+ List<NameValuePair> nvps = annotation.getValues();
+ for (NameValuePair nvp : nvps) {
+ // If multiple of the same type, match by name
+ if (countOfType > 1) {
+ if (!nvp.getNameString().equals(name)) {
+ continue;
+ }
+ }
+ ElementValue o = nvp.getValue();
+ if (o.getElementValueType() != elementValueType) {
+ continue;
+ }
if (o instanceof EnumElementValue) {
- EnumElementValue v = (EnumElementValue) object.getValue();
+ EnumElementValue v = (EnumElementValue) o;
String s = v.getEnumTypeString();
ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(s));
if (rt.equals(toType)) {
il.append(fact.createGetStatic(rt.getName(), v.getEnumValueString(), Type.getType(rt.getSignature())));
- doneAndDusted = true;
+ foundValueInAnnotationUsage = true;
}
} else if (o instanceof SimpleElementValue) {
- // FIXASC types other than String will go bang bang at runtime
- SimpleElementValue v = (SimpleElementValue) object.getValue();
- il.append(fact.createConstant(v.getValueString()));
- doneAndDusted = true;
- // String s = v.getEnumTypeString();
- // ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(s));
- // if (rt.equals(toType)) {
- // il.append(fact.createGetStatic(rt.getName(), v.getEnumValueString(), Type.getType(rt.getSignature())));
- // doneAndDusted = true;
- // }
+ SimpleElementValue v = (SimpleElementValue) o;
+ switch (v.getElementValueType()) {
+ case ElementValue.PRIMITIVE_INT:
+ il.append(fact.createConstant(v.getValueInt()));
+ foundValueInAnnotationUsage = true;
+ break;
+ case ElementValue.STRING:
+ il.append(fact.createConstant(v.getValueString()));
+ foundValueInAnnotationUsage = true;
+ break;
+ default:
+ throw new IllegalStateException("NYI: Unsupported annotation value binding for " + o);
+ }
+ }
+ if (foundValueInAnnotationUsage) {
+ break;
}
}
- if (!doneAndDusted) {
- ResolvedMember[] annotationFields = toType.getWorld()
- .resolve(UnresolvedType.forSignature(annotation.getTypeSignature())).getDeclaredMethods();
-
- // ResolvedMember[] fs = rt.getDeclaredFields();
- for (int ii = 0; ii < annotationFields.length; ii++) {
- if (annotationFields[ii].getType().equals(annoFieldOfInterest)) {
- String dvalue = annotationFields[ii].getAnnotationDefaultValue();
- // form will be LBLAHBLAHBLAH;X where X is the field
- // within X
+ // this block deals with default values
+ if (!foundValueInAnnotationUsage) {
+ for (ResolvedMember annotationField : annotationFields) {
+ if (countOfType > 1) {
+ if (!annotationField.getName().equals(name)) {
+ continue;
+ }
+ }
+ if (!annotationField.getType().getSignature().equals(annoFieldOfInterest.getSignature())) {
+ continue;
+ }
+ if (annotationField.getType().getSignature().equals("I")) {
+ int ivalue = Integer.parseInt(annotationField.getAnnotationDefaultValue());
+ il.append(fact.createConstant(ivalue));
+ foundValueInAnnotationUsage = true;
+ break;
+ } else if (annotationField.getType().getSignature().equals("Ljava/lang/String;")) {
+ String svalue = annotationField.getAnnotationDefaultValue();
+ il.append(fact.createConstant(svalue));
+ foundValueInAnnotationUsage = true;
+ break;
+ } else {
+ String dvalue = annotationField.getAnnotationDefaultValue();
+ // form will be LBLAHBLAHBLAH;X where X is the field within X
String typename = dvalue.substring(0, dvalue.lastIndexOf(';') + 1);
String field = dvalue.substring(dvalue.lastIndexOf(';') + 1);
ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(typename));
il.append(fact.createGetStatic(rt.getName(), field, Type.getType(rt.getSignature())));
+ foundValueInAnnotationUsage = true;
+ break;
}
}
}
}
+ if (foundValueInAnnotationUsage) {
+ break;
+ }
}
}
import org.aspectj.weaver.Member;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.Shadow.Kind;
+import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.ast.Var;
/**
Field annotationCachingField = shadow.getEnclosingClass().getAnnotationCachingField(shadow, toType);
// Basic idea here is to check if the cached field is null, if it is then initialize it, otherwise use it
- il.append(fact
- .createGetStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
+ il.append(fact.createGetStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
il.append(InstructionConstants.DUP);
InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
il.append(ifNonNull);
il.append(fact.createInvoke("java/lang/reflect/Method", "getAnnotation", jlaAnnotation, new Type[] { jlClass },
Constants.INVOKEVIRTUAL));
il.append(InstructionConstants.DUP);
- il.append(fact
- .createPutStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
+ il.append(fact.createPutStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
InstructionHandle ifNullElse = il.append(InstructionConstants.NOP);
ifNonNull.setTarget(ifNullElse);
* Return an object that can access a particular value of this annotation.
*
* @param valueType The type from the annotation that is of interest
+ * @param the formal name expressed in the pointcut, can be used to disambiguate
* @return a variable that represents access to that annotation value
*/
@Override
- public Var getAccessorForValue(ResolvedType valueType) {
- return new AnnotationAccessFieldVar(this, valueType);
+ public Var getAccessorForValue(ResolvedType valueType, String formalName) {
+ return new AnnotationAccessFieldVar(this, valueType, formalName);
}
}