From 756f85938f3e573b55fba70ee8e3e6254a7edf99 Mon Sep 17 00:00:00 2001 From: aclement Date: Tue, 1 Feb 2005 09:20:21 +0000 Subject: [PATCH] Annotation Binding - now complete for @annotation (for *all* kinded PCDs) --- .../systemtest/ajc150/AnnotationBinding.java | 92 ++++++++++++-- .../org/aspectj/weaver/bcel/BcelShadow.java | 104 ++++++++++----- .../bcel/KindedAnnotationAccessVar.java | 119 ++++++++++++------ 3 files changed, 236 insertions(+), 79 deletions(-) diff --git a/tests/src/org/aspectj/systemtest/ajc150/AnnotationBinding.java b/tests/src/org/aspectj/systemtest/ajc150/AnnotationBinding.java index b1fd803bc..1aff11ace 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/AnnotationBinding.java +++ b/tests/src/org/aspectj/systemtest/ajc150/AnnotationBinding.java @@ -113,17 +113,90 @@ public class AnnotationBinding extends TestUtils { ///////////////////////////////////// @ANNOTATION and SET -// // 'set() && @annotation()' -// public void testFieldAnnotationBinding1() { -// CompilationResult cR = ajc(baseDir,new String[]{"FieldAnnBinding1.aj","-1.5"}); -// System.err.println(cR); -// assertMessages(cR,new EmptyMessageSpec()); -// RunResult rR = run("FieldAnnBinding1"); -// System.err.println(rR.getStdErr()); -// } + // 'set() && @annotation()' + public void testFieldAnnotationBinding1() { + CompilationResult cR = ajc(baseDir,new String[]{"FieldAnnBinding1.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("FieldAnnBinding1"); + } - + // 'get() && @annotation()' + public void testFieldAnnotationBinding2() { + CompilationResult cR = ajc(baseDir,new String[]{"FieldAnnBinding2.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("FieldAnnBinding2"); + } + + // 'get() && @annotation()' when using array fields + public void testFieldAnnotationBinding3() { + CompilationResult cR = ajc(baseDir,new String[]{"FieldAnnBinding3.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("FieldAnnBinding3"); + } + + ///////////////////////////////////// @ANNOTATION and CTOR-CALL + + // 'ctor-call(new) && @annotation()' + public void testCtorCallAnnotationBinding1() { + CompilationResult cR = ajc(baseDir,new String[]{"CtorAnnBinding1.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("CtorAnnBinding1"); + } + + ///////////////////////////////////// @ANNOTATION and CTOR-CALL + + // 'ctor-execution() && @annotation()' + public void testCtorExecAnnotationBinding1() { + CompilationResult cR = ajc(baseDir,new String[]{"CtorAnnBinding2.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("CtorAnnBinding2"); + } + + + ///////////////////////////////////// @ANNOTATION and STATICINITIALIZATION + // 'staticinitialization() && @annotation()' + public void testStaticInitAnnotationBinding1() { + CompilationResult cR = ajc(baseDir,new String[]{"StaticInitBinding.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("StaticInitBinding"); + } + + ///////////////////////////////////// @ANNOTATION and PREINITIALIZATION + + // 'preinitialization() && @annotation()' + public void testPreInitAnnotationBinding1() { + CompilationResult cR = ajc(baseDir,new String[]{"PreInitBinding.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("PreInitBinding"); + } + + ///////////////////////////////////// @ANNOTATION and INITIALIZATION + + // 'initialization() && @annotation()' + public void testInitAnnotationBinding1() { + CompilationResult cR = ajc(baseDir,new String[]{"InitBinding.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("InitBinding"); + } + + ///////////////////////////////////// @ANNOTATION and ADVICEEXECUTION + + // 'adviceexecution() && @annotation()' + public void testAdviceExecAnnotationBinding1() { + CompilationResult cR = ajc(baseDir,new String[]{"AdviceExecBinding.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("AdviceExecBinding"); + } + + ///////////////////////////////////// @ANNOTATION and HANDLER + + // 'handler() && @annotation()' + public void testHandlerAnnotationBinding1() { + CompilationResult cR = ajc(baseDir,new String[]{"HandlerBinding.aj","-1.5"}); + assertMessages(cR,new EmptyMessageSpec()); + RunResult rR = run("HandlerBinding"); + } ///////////////////////////////////// @ANNOTATION complex tests @@ -132,7 +205,6 @@ public class AnnotationBinding extends TestUtils { public void testPackageNamedTypesNoBinding() { CompilationResult cR = ajc(new File(baseDir,"complexExample"), new String[]{"A.java","B.java","Color.java","X.java","-1.5","-d","."}); - System.err.println(cR.getStandardError()); assertMessages(cR,new EmptyMessageSpec()); RunResult rR = run("a.b.c.A"); } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index bcc0fd05d..7e4b93135 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -1307,55 +1307,97 @@ public class BcelShadow extends Shadow { // Then create one BcelVar entry in the map for each annotation, keyed by // annotation type (TypeX). - // !!! Refactor these once all shadow kinds added - there is lots of commonality - if (getKind() == Shadow.MethodCall) { - ResolvedMember rm[] = getSignature().getDeclaringType().getDeclaredMethods(world); + // !!! PREAJ5FINAL Refactor these once all shadow kinds added - there is lots of commonality + ResolvedTypeX[] annotations = null; + TypeX relevantType = null; + + if (getKind() == Shadow.StaticInitialization) { + relevantType = getSignature().getDeclaringType(); + annotations = relevantType.resolve(world).getAnnotationTypes(); + } + if (getKind() == Shadow.ExceptionHandler) { + relevantType = getSignature().getParameterTypes()[0]; + annotations = relevantType.resolve(world).getAnnotationTypes(); + } + if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) { + relevantType = getSignature().getDeclaringType(); + ResolvedMember rm[] = relevantType.getDeclaredMethods(world); ResolvedMember found = null; String searchString = getSignature().getName()+getSignature().getParameterSignature(); - for (int i = 0; i < rm.length; i++) { + for (int i = 0; i < rm.length && found==null; i++) { ResolvedMember member = rm[i]; if ((member.getName()+member.getParameterSignature()).equals(searchString)) { found = member; } } - ResolvedTypeX[] anns = found.getAnnotationTypes(); - for (int i = 0; i < anns.length; i++) { - ResolvedTypeX typeX = anns[i]; - kindedAnnotationVars.put(typeX, - new KindedAnnotationAccessVar(typeX.resolve(world),getSignature().getDeclaringType(),getSignature())); + annotations = found.getAnnotationTypes(); + } + if (getKind() == Shadow.MethodExecution || getKind() == Shadow.ConstructorExecution || + getKind() == Shadow.AdviceExecution) { + relevantType = getSignature().getDeclaringType(); + ResolvedMember rm[] = relevantType.getDeclaredMethods(world); + ResolvedMember found = null; + String searchString = getSignature().getName()+getSignature().getParameterSignature(); + for (int i = 0; i < rm.length && found==null; i++) { + ResolvedMember member = rm[i]; + if ((member.getName()+member.getParameterSignature()).equals(searchString)) { + found = member; + } } + annotations = found.getAnnotationTypes(); } - if (getKind() == Shadow.MethodExecution) { - ResolvedMember rm[] = getSignature().getDeclaringType().getDeclaredMethods(world); + if (getKind() == Shadow.PreInitialization || getKind() == Shadow.Initialization) { + relevantType = getSignature().getDeclaringType(); + ResolvedMember rm[] = relevantType.getDeclaredMethods(world); ResolvedMember found = null; String searchString = getSignature().getName()+getSignature().getParameterSignature(); - for (int i = 0; i < rm.length; i++) { + for (int i = 0; i < rm.length && found==null; i++) { ResolvedMember member = rm[i]; if ((member.getName()+member.getParameterSignature()).equals(searchString)) { found = member; } } - ResolvedTypeX[] anns = found.getAnnotationTypes(); - for (int i = 0; i < anns.length; i++) { - ResolvedTypeX typeX = anns[i]; - kindedAnnotationVars.put(typeX,new KindedAnnotationAccessVar(typeX.resolve(world),getSignature().getDeclaringType(),getSignature())); + annotations = found.getAnnotationTypes(); + } + if (getKind() == Shadow.FieldSet) { + relevantType = getSignature().getDeclaringType(); + ResolvedMember rm[] = relevantType.getDeclaredFields(world); + ResolvedMember found = null; + for (int i = 0; i < rm.length && found==null; i++) { + ResolvedMember member = rm[i]; + if ( member.getName().equals(getSignature().getName()) && + member.getType().equals(getSignature().getType())) { + found = member; + } } + annotations = found.getAnnotationTypes(); } -// if (getKind() == Shadow.FieldSet) { -// ResolvedMember rm[] = this.getTargetType().getDeclaredFields(world); -// ResolvedMember found = null; -// for (int i = 0; i < rm.length; i++) { -// ResolvedMember member = rm[i]; -// if ((member.getName()+member.getParameterSignature()).equals(getSignature().getName()+getSignature().getParameterSignature())) { -// found = member; -// } -// } -// ResolvedTypeX[] anns = found.getAnnotationTypes(); -// for (int i = 0; i < anns.length; i++) { -// ResolvedTypeX typeX = anns[i]; -// kindedAnnotationVars.put(typeX,new KindedAnnotationAccessVar(typeX.resolve(world),(BcelVar)getTargetVar(),getSignature())); -// } -// } + if (getKind() == Shadow.FieldGet) { + relevantType = getSignature().getDeclaringType(); + ResolvedMember rm[] = relevantType.getDeclaredFields(world); + ResolvedMember found = null; + for (int i = 0; i < rm.length && found==null; i++) { + ResolvedMember member = rm[i]; + if ( member.getName().equals(getSignature().getName()) && + member.getType().equals(getSignature().getType())) { + found = member; + } + } + annotations = found.getAnnotationTypes(); + } + + if (annotations == null) { + // We can't have recognized the shadow - should blow up now to be on the safe side + throw new BCException("Didn't recognize shadow: "+getKind()); + } + + for (int i = 0; i < annotations.length; i++) { + ResolvedTypeX aTX = annotations[i]; + kindedAnnotationVars.put(aTX, + new KindedAnnotationAccessVar(getKind(),aTX.resolve(world),relevantType,getSignature())); + } + + } public void initializeWithinAnnotationVars() { diff --git a/weaver/src/org/aspectj/weaver/bcel/KindedAnnotationAccessVar.java b/weaver/src/org/aspectj/weaver/bcel/KindedAnnotationAccessVar.java index c86f7e328..27a2eacd9 100644 --- a/weaver/src/org/aspectj/weaver/bcel/KindedAnnotationAccessVar.java +++ b/weaver/src/org/aspectj/weaver/bcel/KindedAnnotationAccessVar.java @@ -22,34 +22,34 @@ import org.aspectj.apache.bcel.generic.ObjectType; import org.aspectj.apache.bcel.generic.Type; import org.aspectj.weaver.Member; import org.aspectj.weaver.ResolvedTypeX; +import org.aspectj.weaver.Shadow; import org.aspectj.weaver.TypeX; +import org.aspectj.weaver.Shadow.Kind; -/** - */ // Might need to create a mini hierarchy depending on how much can be shared // amongst kinded pointcut variants of this class. -public class KindedAnnotationAccessVar extends BcelVar { +/** + * 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 or a ... + * + */ +public class KindedAnnotationAccessVar extends BcelVar { - private Member stackField; - private int index; - TypeX target; - Member sig; + private Kind kind; // What kind of shadow are we at? + private TypeX target; // The type upon which we want to ask for 'member' + private Member member; // For method call/execution and field get/set contains the member that has the annotation -// public KindedAnnotationAccessVar(ResolvedTypeX type, Member stackField, int index) { -// super(type, 0); -// this.stackField = stackField; -// this.index = index; -// } - public KindedAnnotationAccessVar(ResolvedTypeX type,TypeX theTargetIsStoredHere,Member sig) { + public KindedAnnotationAccessVar(Kind kind, ResolvedTypeX type,TypeX theTargetIsStoredHere,Member sig) { super(type,0); - target = theTargetIsStoredHere; - this.sig = sig; + this.kind = kind; + target = theTargetIsStoredHere; + this.member = sig; } public String toString() { - return "KindedAnnotationAccessVar(" + getType() + " " + stackField + "." + index + ")"; + return "KindedAnnotationAccessVar(" + getType() +")"; } public Instruction createLoad(InstructionFactory fact) { @@ -67,6 +67,11 @@ public class KindedAnnotationAccessVar extends BcelVar { il.append(createLoadInstructions(getType(), fact)); } + // PREAJ5FINAL Refactor all this stuff - there is a lot of commonality + // PREAJ5FINAL Decide on inclusion of the exception handlers for getDeclaredXXX methods + // PREAJ5FINAL Optimization to share result of getDeclaredXXX if accessing multiple annos at a join point + + // ASC 31Jan05 Please don't look inside this method - it isnt finished yet. public InstructionList createLoadInstructions(ResolvedTypeX toType, InstructionFactory fact) { // We ought to build an exception handler for the NoSuchMethodException that can be thrown @@ -89,33 +94,71 @@ public class KindedAnnotationAccessVar extends BcelVar { Type jlClassArray = BcelWorld.makeBcelType(TypeX.forSignature("[Ljava.lang.Class;")); Type jlaAnnotation = BcelWorld.makeBcelType(TypeX.forSignature("Ljava.lang.annotation.Annotation;")); - Type jlrMethod = BcelWorld.makeBcelType(TypeX.forSignature("Ljava.lang.reflect.Method;")); + if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution || + kind==Shadow.PreInitialization || kind==Shadow.Initialization || + kind==Shadow.ConstructorCall || kind==Shadow.ConstructorExecution || + kind==Shadow.AdviceExecution) { + Type jlrMethod = BcelWorld.makeBcelType(TypeX.forSignature("Ljava.lang.reflect.Method;")); // Calls getClass - // System.err.println("What is the class of target? "+target.getType()); + + // Variant (1) Use the target directly il.append(fact.createConstant(BcelWorld.makeBcelType(target))); -// il.append(target.createLoad(fact)); -// il.append(fact.createInvoke("java/lang/Object","getClass",jlClass,new Type[]{},Constants.INVOKEVIRTUAL)); + + + // Variant (2) Ask the target for its class (could give a different answer at runtime) + // il.append(target.createLoad(fact)); + // il.append(fact.createInvoke("java/lang/Object","getClass",jlClass,new Type[]{},Constants.INVOKEVIRTUAL)); - // il.append(fact.createConstant(new ObjectType(toType.getClassName()))); - il.append(fact.createConstant(sig.getName())); - - - Type[] paramTypes = BcelWorld.makeBcelTypes(sig.getParameterTypes()); - - buildArray(il,fact,jlClass,paramTypes,1); - - // Calls getDeclaredMethod - il.append(fact.createInvoke("java/lang/Class","getDeclaredMethod",jlrMethod,new Type[]{jlString,jlClassArray},Constants.INVOKEVIRTUAL)); - - // !!! OPTIMIZATION: Cache the result of getDeclaredMethod() and use it - // again for other annotations on the same signature at this join point - // Calls getAnnotation - String ss = toType.getName(); - il.append(fact.createConstant(new ObjectType(toType.getName()))); - il.append(fact.createInvoke("java/lang/reflect/Method","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); - il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType))); + // il.append(fact.createConstant(new ObjectType(toType.getClassName()))); + + + if (kind==Shadow.MethodCall || kind==Shadow.MethodExecution || kind==Shadow.AdviceExecution) { + il.append(fact.createConstant(member.getName())); + Type[] paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes()); + buildArray(il,fact,jlClass,paramTypes,1); + // Calls getDeclaredMethod + il.append(fact.createInvoke("java/lang/Class","getDeclaredMethod",jlrMethod,new Type[]{jlString,jlClassArray},Constants.INVOKEVIRTUAL)); + // !!! OPTIMIZATION: Cache the result of getDeclaredMethod() and use it + // again for other annotations on the same signature at this join point + // Calls getAnnotation + String ss = toType.getName(); + il.append(fact.createConstant(new ObjectType(toType.getName()))); + il.append(fact.createInvoke("java/lang/reflect/Method","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); + il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType))); + } else { // init/preinit/ctor-call/ctor-exec + Type[] paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes()); + buildArray(il,fact,jlClass,paramTypes,1); + Type jlrCtor = BcelWorld.makeBcelType(TypeX.forSignature("Ljava.lang.reflect.Constructor;")); + il.append(fact.createInvoke("java/lang/Class","getDeclaredConstructor",jlrCtor,new Type[]{jlClassArray},Constants.INVOKEVIRTUAL)); + + // !!! OPTIMIZATION: Cache the result of getDeclaredMethod() and use it + // again for other annotations on the same signature at this join point + // Calls getAnnotation + String ss = toType.getName(); + il.append(fact.createConstant(new ObjectType(toType.getName()))); + il.append(fact.createInvoke("java/lang/reflect/Constructor","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); + il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType))); + } + } else if (kind == Shadow.FieldSet || kind == Shadow.FieldGet) { + Type jlrField = BcelWorld.makeBcelType(TypeX.forSignature("Ljava.lang.reflect.Field;")); + il.append(fact.createConstant(BcelWorld.makeBcelType(target))); // 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)); + String ss = toType.getName(); + il.append(fact.createConstant(new ObjectType(toType.getName()))); + il.append(fact.createInvoke("java/lang/reflect/Field","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); + il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType))); + } else if (kind == Shadow.StaticInitialization || kind==Shadow.ExceptionHandler) { + il.append(fact.createConstant(BcelWorld.makeBcelType(target))); + String ss = toType.getName(); + il.append(fact.createConstant(new ObjectType(toType.getName()))); + il.append(fact.createInvoke("java/lang/Class","getAnnotation",jlaAnnotation,new Type[]{jlClass},Constants.INVOKEVIRTUAL)); + il.append(Utility.createConversion(fact,jlaAnnotation,BcelWorld.makeBcelType(toType))); + } else { + throw new RuntimeException("Don't understand this kind "+kind); + } return il; } -- 2.39.5