|
|
@@ -26,48 +26,48 @@ import org.aspectj.weaver.UnresolvedType; |
|
|
|
import org.aspectj.weaver.Shadow.Kind; |
|
|
|
|
|
|
|
/** |
|
|
|
* Represents access to an annotation on an element, relating to some kinded pointcut. |
|
|
|
* Depending on the kind of pointcut the element might be a field or a method and the code |
|
|
|
* generators in here can retrieve the annotation from the element. |
|
|
|
* Represents access to an annotation on an element, relating to some kinded pointcut. Depending on the kind of pointcut the element |
|
|
|
* might be a field or a method and the code generators in here can retrieve the annotation from the element. |
|
|
|
*/ |
|
|
|
public class AnnotationAccessVar extends BcelVar { |
|
|
|
|
|
|
|
private Kind kind; // What kind of shadow are we at? |
|
|
|
private UnresolvedType containingType; // The type upon which we want to ask for 'member' |
|
|
|
private Member member; // Holds the member that has the annotations (for method/field join points) |
|
|
|
|
|
|
|
private Kind kind; // What kind of shadow are we at? |
|
|
|
private UnresolvedType containingType; // The type upon which we want to ask for 'member' |
|
|
|
private Member member; // Holds the member that has the annotations (for method/field join points) |
|
|
|
|
|
|
|
public AnnotationAccessVar(Kind kind, ResolvedType annotationType, UnresolvedType theTargetIsStoredHere, Member sig) { |
|
|
|
super(annotationType,0); |
|
|
|
super(annotationType, 0); |
|
|
|
this.kind = kind; |
|
|
|
this.containingType = theTargetIsStoredHere; |
|
|
|
this.containingType = theTargetIsStoredHere; |
|
|
|
this.member = sig; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Kind getKind() { |
|
|
|
return kind; |
|
|
|
} |
|
|
|
return kind; |
|
|
|
} |
|
|
|
|
|
|
|
public String toString() { |
|
|
|
return "AnnotationAccessVar(" + getType() +")"; |
|
|
|
return "AnnotationAccessVar(" + getType() + ")"; |
|
|
|
} |
|
|
|
|
|
|
|
public Instruction createLoad(InstructionFactory fact) { |
|
|
|
throw new IllegalStateException("unimplemented"); |
|
|
|
} |
|
|
|
|
|
|
|
public Instruction createStore(InstructionFactory fact) { |
|
|
|
throw new IllegalStateException("unimplemented"); |
|
|
|
} |
|
|
|
|
|
|
|
public Instruction createLoad(InstructionFactory fact) { |
|
|
|
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) { |
|
|
|
throw new IllegalStateException("unimplemented"); |
|
|
|
} |
|
|
|
public Instruction createStore(InstructionFactory fact) { |
|
|
|
throw new IllegalStateException("unimplemented"); |
|
|
|
} |
|
|
|
|
|
|
|
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) { |
|
|
|
throw new IllegalStateException("unimplemented"); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public void appendLoad(InstructionList il, InstructionFactory fact) { |
|
|
|
il.append(createLoadInstructions(getType(), fact)); |
|
|
|
} |
|
|
|
|
|
|
|
public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) { |
|
|
|
il.append(createLoadInstructions(toType, fact)); |
|
|
|
il.append(createLoadInstructions(toType, fact)); |
|
|
|
} |
|
|
|
|
|
|
|
public void insertLoad(InstructionList il, InstructionFactory fact) { |
|
|
@@ -75,94 +75,122 @@ public class AnnotationAccessVar extends BcelVar { |
|
|
|
} |
|
|
|
|
|
|
|
private InstructionList createLoadInstructions(ResolvedType toType, InstructionFactory fact) { |
|
|
|
|
|
|
|
|
|
|
|
InstructionList il = new InstructionList(); |
|
|
|
|
|
|
|
|
|
|
|
Type jlClass = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_CLASS); |
|
|
|
Type jlString = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.String;")); |
|
|
|
Type jlClassArray = BcelWorld.makeBcelType(UnresolvedType.forSignature("[Ljava.lang.Class;")); |
|
|
|
Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.annotation.Annotation;")); |
|
|
|
|
|
|
|
Instruction pushConstant = fact.createConstant(new ObjectType(toType.getName())); |
|
|
|
|
|
|
|
if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution || |
|
|
|
kind==Shadow.PreInitialization || kind==Shadow.Initialization || |
|
|
|
kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution || |
|
|
|
kind==Shadow.AdviceExecution || |
|
|
|
// annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD |
|
|
|
((kind==Shadow.FieldGet || kind==Shadow.FieldSet) && member.getKind()==Member.METHOD)) { |
|
|
|
|
|
|
|
Type jlString = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_STRING); |
|
|
|
Type jlClassArray = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_CLASS_ARRAY); |
|
|
|
Type jlaAnnotation = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_ANNOTATION); |
|
|
|
|
|
|
|
Instruction pushConstant = fact.createConstant(new ObjectType(toType.getName())); |
|
|
|
|
|
|
|
if (kind == Shadow.MethodCall || kind == Shadow.MethodExecution || kind == Shadow.PreInitialization |
|
|
|
|| kind == Shadow.Initialization || kind == Shadow.ConstructorCall || kind == Shadow.ConstructorExecution |
|
|
|
|| kind == Shadow.AdviceExecution || |
|
|
|
// annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD |
|
|
|
((kind == Shadow.FieldGet || kind == Shadow.FieldSet) && member.getKind() == Member.METHOD)) { |
|
|
|
|
|
|
|
Type jlrMethod = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Method;")); |
|
|
|
Type[] paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes()); |
|
|
|
|
|
|
|
il.append(fact.createConstant(BcelWorld.makeBcelType(containingType))); |
|
|
|
|
|
|
|
if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution || kind==Shadow.AdviceExecution || |
|
|
|
// annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD |
|
|
|
((kind==Shadow.FieldGet || kind==Shadow.FieldSet) && member.getKind()==Member.METHOD) || |
|
|
|
((kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution) && member.getKind()==Member.METHOD)) { |
|
|
|
|
|
|
|
if (kind == Shadow.MethodCall |
|
|
|
|| kind == Shadow.MethodExecution |
|
|
|
|| kind == Shadow.AdviceExecution |
|
|
|
|| |
|
|
|
// annotations for fieldset/fieldget when an ITD is involved are stored against a METHOD |
|
|
|
((kind == Shadow.FieldGet || kind == Shadow.FieldSet) && member.getKind() == Member.METHOD) |
|
|
|
|| ((kind == Shadow.ConstructorCall || kind == Shadow.ConstructorExecution) && member.getKind() == Member.METHOD)) { |
|
|
|
|
|
|
|
il.append(fact.createConstant(member.getName())); |
|
|
|
buildArray(il,fact,jlClass,paramTypes,1); |
|
|
|
// OPTIMIZE cache result of getDeclaredMethod and getAnnotation? Might be able to use it again if someone else needs the same annotations? |
|
|
|
il.append(fact.createInvoke("java/lang/Class","getDeclaredMethod",jlrMethod,new Type[]{jlString,jlClassArray},Constants.INVOKEVIRTUAL)); |
|
|
|
il.append(pushConstant);//fact.createConstant(new ObjectType(toType.getName()))); |
|
|
|
il.append(fact.createInvoke("java/lang/reflect/Method","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); |
|
|
|
} else { // init/preinit/ctor-call/ctor-exec |
|
|
|
buildArray(il,fact,jlClass,paramTypes,1); |
|
|
|
buildArray(il, fact, jlClass, paramTypes, 1); |
|
|
|
// OPTIMIZE cache result of getDeclaredMethod and getAnnotation? Might be able to use it again if someone else needs |
|
|
|
// the same annotations? |
|
|
|
il.append(fact.createInvoke("java/lang/Class", "getDeclaredMethod", jlrMethod, |
|
|
|
new Type[] { jlString, jlClassArray }, Constants.INVOKEVIRTUAL)); |
|
|
|
il.append(pushConstant);// fact.createConstant(new ObjectType(toType.getName()))); |
|
|
|
il.append(fact.createInvoke("java/lang/reflect/Method", "getAnnotation", jlaAnnotation, new Type[] { jlClass }, |
|
|
|
Constants.INVOKEVIRTUAL)); |
|
|
|
} else { // init/preinit/ctor-call/ctor-exec |
|
|
|
buildArray(il, fact, jlClass, paramTypes, 1); |
|
|
|
Type jlrCtor = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Constructor;")); |
|
|
|
// OPTIMIZE cache result of getDeclaredConstructor and getAnnotation? Might be able to use it again if someone else needs the same annotations? |
|
|
|
il.append(fact.createInvoke("java/lang/Class","getDeclaredConstructor",jlrCtor,new Type[]{jlClassArray},Constants.INVOKEVIRTUAL)); |
|
|
|
il.append(pushConstant); |
|
|
|
il.append(fact.createInvoke("java/lang/reflect/Constructor","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); |
|
|
|
} |
|
|
|
} else if (kind == Shadow.FieldSet || kind == Shadow.FieldGet) { |
|
|
|
// OPTIMIZE cache result of getDeclaredConstructor and getAnnotation? Might be able to use it again if someone else |
|
|
|
// needs the same annotations? |
|
|
|
il.append(fact.createInvoke("java/lang/Class", "getDeclaredConstructor", jlrCtor, new Type[] { jlClassArray }, |
|
|
|
Constants.INVOKEVIRTUAL)); |
|
|
|
il.append(pushConstant); |
|
|
|
il.append(fact.createInvoke("java/lang/reflect/Constructor", "getAnnotation", jlaAnnotation, |
|
|
|
new Type[] { jlClass }, Constants.INVOKEVIRTUAL)); |
|
|
|
} |
|
|
|
} else if (kind == Shadow.FieldSet || kind == Shadow.FieldGet) { |
|
|
|
Type jlrField = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava.lang.reflect.Field;")); |
|
|
|
il.append(fact.createConstant(BcelWorld.makeBcelType(containingType))); // Stick the target on the stack |
|
|
|
il.append(fact.createConstant(member.getName())); // Stick what we are after on the stack |
|
|
|
il.append(fact.createInvoke("java/lang/Class","getDeclaredField",jlrField,new Type[]{jlString},Constants.INVOKEVIRTUAL)); |
|
|
|
il.append(pushConstant); |
|
|
|
il.append(fact.createInvoke("java/lang/reflect/Field","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); |
|
|
|
} else if (kind == Shadow.StaticInitialization || kind==Shadow.ExceptionHandler) { |
|
|
|
il.append(fact.createInvoke("java/lang/Class", "getDeclaredField", jlrField, new Type[] { jlString }, |
|
|
|
Constants.INVOKEVIRTUAL)); |
|
|
|
il.append(pushConstant); |
|
|
|
il.append(fact.createInvoke("java/lang/reflect/Field", "getAnnotation", jlaAnnotation, new Type[] { jlClass }, |
|
|
|
Constants.INVOKEVIRTUAL)); |
|
|
|
} else if (kind == Shadow.StaticInitialization || kind == Shadow.ExceptionHandler) { |
|
|
|
il.append(fact.createConstant(BcelWorld.makeBcelType(containingType))); |
|
|
|
il.append(pushConstant); |
|
|
|
il.append(fact.createInvoke("java/lang/Class","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); |
|
|
|
il.append(pushConstant); |
|
|
|
il.append(fact.createInvoke("java/lang/Class", "getAnnotation", jlaAnnotation, new Type[] { jlClass }, |
|
|
|
Constants.INVOKEVIRTUAL)); |
|
|
|
} else { |
|
|
|
throw new RuntimeException("Don't understand this kind "+kind); |
|
|
|
throw new RuntimeException("Don't understand this kind " + kind); |
|
|
|
} |
|
|
|
il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType))); |
|
|
|
il.append(Utility.createConversion(fact, jlaAnnotation, BcelWorld.makeBcelType(toType))); |
|
|
|
return il; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void buildArray(InstructionList il, InstructionFactory fact, Type arrayElementType, Type[] arrayEntries,int dim) { |
|
|
|
il.append(fact.createConstant(Integer.valueOf(arrayEntries==null?0:arrayEntries.length))); |
|
|
|
il.append(fact.createNewArray(arrayElementType,(short)dim)); |
|
|
|
if (arrayEntries == null) return; |
|
|
|
for (int i = 0; i < arrayEntries.length; i++) { |
|
|
|
private void buildArray(InstructionList il, InstructionFactory fact, Type arrayElementType, Type[] arrayEntries, int dim) { |
|
|
|
il.append(fact.createConstant(Integer.valueOf(arrayEntries == null ? 0 : arrayEntries.length))); |
|
|
|
il.append(fact.createNewArray(arrayElementType, (short) dim)); |
|
|
|
if (arrayEntries == null) |
|
|
|
return; |
|
|
|
for (int i = 0; i < arrayEntries.length; i++) { |
|
|
|
il.append(InstructionFactory.createDup(1)); |
|
|
|
il.append(fact.createConstant(Integer.valueOf(i))); |
|
|
|
switch (arrayEntries[i].getType()) { |
|
|
|
case Constants.T_ARRAY: |
|
|
|
il.append(fact.createConstant(new ObjectType(arrayEntries[i].getSignature()))); // FIXME should be getName() and not getSignature()? |
|
|
|
break; |
|
|
|
case Constants.T_BOOLEAN: il.append(fact.createGetStatic("java/lang/Boolean","TYPE",arrayElementType)); break; |
|
|
|
case Constants.T_BYTE:il.append(fact.createGetStatic("java/lang/Byte","TYPE",arrayElementType)); break; |
|
|
|
case Constants.T_CHAR:il.append(fact.createGetStatic("java/lang/Character","TYPE",arrayElementType)); break; |
|
|
|
case Constants.T_INT:il.append(fact.createGetStatic("java/lang/Integer","TYPE",arrayElementType)); break; |
|
|
|
case Constants.T_LONG:il.append(fact.createGetStatic("java/lang/Long","TYPE",arrayElementType)); break; |
|
|
|
case Constants.T_DOUBLE:il.append(fact.createGetStatic("java/lang/Double","TYPE",arrayElementType)); break; |
|
|
|
case Constants.T_FLOAT:il.append(fact.createGetStatic("java/lang/Float","TYPE",arrayElementType)); break; |
|
|
|
case Constants.T_SHORT:il.append(fact.createGetStatic("java/lang/Short","TYPE",arrayElementType)); break; |
|
|
|
default: |
|
|
|
il.append(fact.createConstant(arrayEntries[i])); |
|
|
|
} |
|
|
|
switch (arrayEntries[i].getType()) { |
|
|
|
case Constants.T_ARRAY: |
|
|
|
il.append(fact.createConstant(new ObjectType(arrayEntries[i].getSignature()))); // FIXME should be getName() and not |
|
|
|
// getSignature()? |
|
|
|
break; |
|
|
|
case Constants.T_BOOLEAN: |
|
|
|
il.append(fact.createGetStatic("java/lang/Boolean", "TYPE", arrayElementType)); |
|
|
|
break; |
|
|
|
case Constants.T_BYTE: |
|
|
|
il.append(fact.createGetStatic("java/lang/Byte", "TYPE", arrayElementType)); |
|
|
|
break; |
|
|
|
case Constants.T_CHAR: |
|
|
|
il.append(fact.createGetStatic("java/lang/Character", "TYPE", arrayElementType)); |
|
|
|
break; |
|
|
|
case Constants.T_INT: |
|
|
|
il.append(fact.createGetStatic("java/lang/Integer", "TYPE", arrayElementType)); |
|
|
|
break; |
|
|
|
case Constants.T_LONG: |
|
|
|
il.append(fact.createGetStatic("java/lang/Long", "TYPE", arrayElementType)); |
|
|
|
break; |
|
|
|
case Constants.T_DOUBLE: |
|
|
|
il.append(fact.createGetStatic("java/lang/Double", "TYPE", arrayElementType)); |
|
|
|
break; |
|
|
|
case Constants.T_FLOAT: |
|
|
|
il.append(fact.createGetStatic("java/lang/Float", "TYPE", arrayElementType)); |
|
|
|
break; |
|
|
|
case Constants.T_SHORT: |
|
|
|
il.append(fact.createGetStatic("java/lang/Short", "TYPE", arrayElementType)); |
|
|
|
break; |
|
|
|
default: |
|
|
|
il.append(fact.createConstant(arrayEntries[i])); |
|
|
|
} |
|
|
|
il.append(InstructionConstants.AASTORE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public Member getMember() { |
|
|
|
return member; |
|
|
|
} |
|
|
|
public Member getMember() { |
|
|
|
return member; |
|
|
|
} |
|
|
|
|
|
|
|
} |