diff options
author | aclement <aclement> | 2005-08-08 09:54:54 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-08-08 09:54:54 +0000 |
commit | 211806608a60557fb6180d55f9c9802a79ab490d (patch) | |
tree | fd0f1d15a449dca5dfafb667554ec1202e54dfcc /weaver | |
parent | 64f0a5bd91915a3c626a49841c9e4eb64d7f6de9 (diff) | |
download | aspectj-211806608a60557fb6180d55f9c9802a79ab490d.tar.gz aspectj-211806608a60557fb6180d55f9c9802a79ab490d.zip |
Fix for pr98901: copying annotations to new members created via ITD !!
Diffstat (limited to 'weaver')
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java | 178 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelShadow.java | 114 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java | 174 |
3 files changed, 314 insertions, 152 deletions
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index c10b2f16d..f9c2eabcb 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -27,9 +27,12 @@ import java.util.Set; import org.aspectj.apache.bcel.Constants; import org.aspectj.apache.bcel.classfile.Field; +import org.aspectj.apache.bcel.classfile.Method; +import org.aspectj.apache.bcel.classfile.annotation.Annotation; import org.aspectj.apache.bcel.generic.BranchInstruction; import org.aspectj.apache.bcel.generic.CPInstruction; import org.aspectj.apache.bcel.generic.ConstantPoolGen; +import org.aspectj.apache.bcel.generic.FieldGen; import org.aspectj.apache.bcel.generic.FieldInstruction; import org.aspectj.apache.bcel.generic.INVOKESPECIAL; import org.aspectj.apache.bcel.generic.IndexedInstruction; @@ -41,6 +44,7 @@ import org.aspectj.apache.bcel.generic.InstructionList; import org.aspectj.apache.bcel.generic.InstructionTargeter; import org.aspectj.apache.bcel.generic.InvokeInstruction; import org.aspectj.apache.bcel.generic.LocalVariableInstruction; +import org.aspectj.apache.bcel.generic.MethodGen; import org.aspectj.apache.bcel.generic.NEW; import org.aspectj.apache.bcel.generic.ObjectType; import org.aspectj.apache.bcel.generic.PUTFIELD; @@ -49,6 +53,7 @@ import org.aspectj.apache.bcel.generic.RET; import org.aspectj.apache.bcel.generic.ReturnInstruction; import org.aspectj.apache.bcel.generic.Select; import org.aspectj.apache.bcel.generic.Type; +import org.aspectj.apache.bcel.generic.annotation.AnnotationGen; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.WeaveMessage; @@ -66,8 +71,8 @@ import org.aspectj.weaver.NewConstructorTypeMunger; import org.aspectj.weaver.NewFieldTypeMunger; import org.aspectj.weaver.NewMethodTypeMunger; import org.aspectj.weaver.ResolvedMember; -import org.aspectj.weaver.ResolvedTypeMunger; import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.ResolvedTypeMunger; import org.aspectj.weaver.Shadow; import org.aspectj.weaver.ShadowMunger; import org.aspectj.weaver.UnresolvedType; @@ -463,46 +468,55 @@ class BcelClassWeaver implements IClassWeaver { for (int memberCounter = 0;memberCounter<members.size();memberCounter++) { LazyMethodGen mg = (LazyMethodGen)members.get(memberCounter); if (!mg.getName().startsWith(NameMangler.PREFIX)) { - - // Single first pass - List worthRetrying = new ArrayList(); - boolean modificationOccured = false; - - for (Iterator iter = decaMs.iterator(); iter.hasNext();) { - DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); - - if (decaM.matches(mg.getMemberView(),world)) { - if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... - mg.addAnnotation(decaM.getAnnotationX()); - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod()); - - reportMethodCtorWeavingMessage(clazz, mg, decaM); - isChanged = true; - modificationOccured = true; - } else { - if (!decaM.isStarredAnnotationPattern()) - worthRetrying.add(decaM); // an annotation is specified that might be put on by a subsequent decaf - } - } - - // Multiple secondary passes - while (!worthRetrying.isEmpty() && modificationOccured) { - modificationOccured = false; - // lets have another go - List forRemoval = new ArrayList(); - for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) { - DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); - if (decaM.matches(mg.getMemberView(),world)) { - if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... - mg.addAnnotation(decaM.getAnnotationX()); - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod()); - isChanged = true; - modificationOccured = true; - forRemoval.add(decaM); - } - } - worthRetrying.removeAll(forRemoval); - } + + // Single first pass + List worthRetrying = new ArrayList(); + boolean modificationOccured = false; + + for (Iterator iter = decaMs.iterator(); iter.hasNext();) { + DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); + + if (decaM.matches(mg.getMemberView(),world)) { + if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... + + Annotation a = decaM.getAnnotationX().getBcelAnnotation(); + AnnotationGen ag = new AnnotationGen(a,clazz.getConstantPoolGen(),true); + Method oldMethod = mg.getMethod(); + MethodGen myGen = new MethodGen(oldMethod,clazz.getClassName(),clazz.getConstantPoolGen()); + myGen.addAnnotation(ag); + Method newMethod = myGen.getMethod(); + mg.addAnnotation(decaM.getAnnotationX()); + members.set(memberCounter,new LazyMethodGen(newMethod,clazz)); + + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod()); + + reportMethodCtorWeavingMessage(clazz, mg, decaM); + isChanged = true; + modificationOccured = true; + } else { + if (!decaM.isStarredAnnotationPattern()) + worthRetrying.add(decaM); // an annotation is specified that might be put on by a subsequent decaf + } + } + + // Multiple secondary passes + while (!worthRetrying.isEmpty() && modificationOccured) { + modificationOccured = false; + // lets have another go + List forRemoval = new ArrayList(); + for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) { + DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); + if (decaM.matches(mg.getMemberView(),world)) { + if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... + mg.addAnnotation(decaM.getAnnotationX()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod()); + isChanged = true; + modificationOccured = true; + forRemoval.add(decaM); + } + } + worthRetrying.removeAll(forRemoval); + } } } } @@ -599,14 +613,16 @@ class BcelClassWeaver implements IClassWeaver { // FIXME asc refactor this to neaten it up public LazyMethodGen locateAnnotationHolderForMethodCtorMunger(LazyClassGen clazz,BcelTypeMunger methodCtorMunger) { if (methodCtorMunger.getMunger() instanceof NewMethodTypeMunger) { - NewMethodTypeMunger nftm = (NewMethodTypeMunger)methodCtorMunger.getMunger(); - ResolvedMember lookingFor =AjcMemberMaker.interMethodBody(nftm.getSignature(),methodCtorMunger.getAspectType()); - List meths = clazz.getMethodGens(); - for (Iterator iter = meths.iterator(); iter.hasNext();) { - LazyMethodGen element = (LazyMethodGen) iter.next(); - if (element.getName().equals(lookingFor.getName()) && element.getParameterSignature().equals(lookingFor.getParameterSignature())) return element; - } - return null; + NewMethodTypeMunger nftm = (NewMethodTypeMunger)methodCtorMunger.getMunger(); + + ResolvedMember lookingFor = AjcMemberMaker.interMethodDispatcher(nftm.getSignature(),methodCtorMunger.getAspectType()); + + List meths = clazz.getMethodGens(); + for (Iterator iter = meths.iterator(); iter.hasNext();) { + LazyMethodGen element = (LazyMethodGen) iter.next(); + if (element.getName().equals(lookingFor.getName()) && element.getParameterSignature().equals(lookingFor.getParameterSignature())) return element; + } + return null; } else if (methodCtorMunger.getMunger() instanceof NewConstructorTypeMunger) { NewConstructorTypeMunger nftm = (NewConstructorTypeMunger)methodCtorMunger.getMunger(); ResolvedMember lookingFor =AjcMemberMaker.postIntroducedConstructor(methodCtorMunger.getAspectType(),nftm.getSignature().getDeclaringType(),nftm.getSignature().getParameterTypes()); @@ -683,20 +699,20 @@ class BcelClassWeaver implements IClassWeaver { boolean isChanged = false; for (Iterator iter = itdMethodsCtors.iterator(); iter.hasNext();) { BcelTypeMunger methodctorMunger = (BcelTypeMunger) iter.next(); - ResolvedMember itdIsActually = methodctorMunger.getSignature(); + ResolvedMember unMangledInterMethod = methodctorMunger.getSignature(); List worthRetrying = new ArrayList(); boolean modificationOccured = false; for (Iterator iter2 = decaMCs.iterator(); iter2.hasNext();) { DeclareAnnotation decaMC = (DeclareAnnotation) iter2.next(); - - if (decaMC.matches(itdIsActually,world)) { + if (decaMC.matches(unMangledInterMethod,world)) { LazyMethodGen annotationHolder = locateAnnotationHolderForMethodCtorMunger(clazz,methodctorMunger); - if (doesAlreadyHaveAnnotation(annotationHolder,itdIsActually,decaMC,reportedErrors)) continue; // skip this one... + if (annotationHolder == null || doesAlreadyHaveAnnotation(annotationHolder,unMangledInterMethod,decaMC,reportedErrors)){ + continue; // skip this one... + } annotationHolder.addAnnotation(decaMC.getAnnotationX()); - itdIsActually.addAnnotation(decaMC.getAnnotationX()); isChanged=true; - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(),itdIsActually.getSourceLocation()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(),unMangledInterMethod.getSourceLocation()); modificationOccured = true; } else { if (!decaMC.isStarredAnnotationPattern()) @@ -709,12 +725,12 @@ class BcelClassWeaver implements IClassWeaver { List forRemoval = new ArrayList(); for (Iterator iter2 = worthRetrying.iterator(); iter.hasNext();) { DeclareAnnotation decaMC = (DeclareAnnotation) iter2.next(); - if (decaMC.matches(itdIsActually,world)) { + if (decaMC.matches(unMangledInterMethod,world)) { LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz,methodctorMunger); - if (doesAlreadyHaveAnnotation(annotationHolder,itdIsActually,decaMC,reportedErrors)) continue; // skip this one... + if (doesAlreadyHaveAnnotation(annotationHolder,unMangledInterMethod,decaMC,reportedErrors)) continue; // skip this one... annotationHolder.addAnnotation(decaMC.getAnnotationX()); - itdIsActually.addAnnotation(decaMC.getAnnotationX()); - AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(),itdIsActually.getSourceLocation()); + unMangledInterMethod.addAnnotation(decaMC.getAnnotationX()); + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(),unMangledInterMethod.getSourceLocation()); isChanged = true; modificationOccured = true; forRemoval.add(decaMC); @@ -726,6 +742,16 @@ class BcelClassWeaver implements IClassWeaver { return isChanged; } + private boolean dontAddTwice(DeclareAnnotation decaF, Annotation [] dontAddMeTwice){ + for (int i = 0; i < dontAddMeTwice.length; i++){ + Annotation ann = dontAddMeTwice[i]; + if (ann != null && decaF.getAnnotationX().getTypeName().equals(ann.getTypeName())){ + dontAddMeTwice[i] = null; // incase it really has been added twice! + return true; + } + } + return false; + } /** * Weave any declare @field statements into the fields of the supplied class @@ -769,12 +795,37 @@ class BcelClassWeaver implements IClassWeaver { // Single first pass List worthRetrying = new ArrayList(); boolean modificationOccured = false; + + Annotation [] dontAddMeTwice = fields[fieldCounter].getAnnotations(); + // go through all the declare @field statements for (Iterator iter = decaFs.iterator(); iter.hasNext();) { DeclareAnnotation decaF = (DeclareAnnotation) iter.next(); if (decaF.matches(aBcelField,world)) { - if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) continue; // skip this one... - aBcelField.addAnnotation(decaF.getAnnotationX()); + + if (!dontAddTwice(decaF,dontAddMeTwice)){ + if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)){ + continue; + } + + if(decaF.getAnnotationX().isRuntimeVisible()){ // isAnnotationWithRuntimeRetention(clazz.getJavaClass(world))){ + //if(decaF.getAnnotationTypeX().isAnnotationWithRuntimeRetention(world)){ + // it should be runtime visible, so put it on the Field + Annotation a = decaF.getAnnotationX().getBcelAnnotation(); + AnnotationGen ag = new AnnotationGen(a,clazz.getConstantPoolGen(),true); + FieldGen myGen = new FieldGen(fields[fieldCounter],clazz.getConstantPoolGen()); + myGen.addAnnotation(ag); + Field newField = myGen.getField(); + + aBcelField.addAnnotation(decaF.getAnnotationX()); + clazz.replaceField(fields[fieldCounter],newField); + fields[fieldCounter]=newField; + + } else{ + aBcelField.addAnnotation(decaF.getAnnotationX()); + } + } + AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]); reportFieldAnnotationWeavingMessage(clazz, fields, fieldCounter, decaF); isChanged = true; @@ -793,6 +844,7 @@ class BcelClassWeaver implements IClassWeaver { for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) { DeclareAnnotation decaF = (DeclareAnnotation) iter.next(); if (decaF.matches(aBcelField,world)) { + // below code is for recursive things if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) continue; // skip this one... aBcelField.addAnnotation(decaF.getAnnotationX()); AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]); @@ -846,7 +898,7 @@ class BcelClassWeaver implements IClassWeaver { } private boolean doesAlreadyHaveAnnotation(LazyMethodGen rm,ResolvedMember itdfieldsig,DeclareAnnotation deca,List reportedProblems) { - if (rm.hasAnnotation(deca.getAnnotationTypeX())) { + if (rm != null && rm.hasAnnotation(deca.getAnnotationTypeX())) { if (world.getLint().elementAlreadyAnnotated.isEnabled()) { Integer uniqueID = new Integer(rm.hashCode()*deca.hashCode()); if (!reportedProblems.contains(uniqueID)) { @@ -1592,7 +1644,7 @@ class BcelClassWeaver implements IClassWeaver { ResolvedMember resolvedDooberry = world.resolve(declaredSig); annotations = resolvedDooberry.getAnnotationTypes(); } else { - ResolvedMember realthing = AjcMemberMaker.interMethodBody(rm,memberHostType); + ResolvedMember realthing = AjcMemberMaker.interMethodDispatcher(rm,memberHostType); ResolvedMember resolvedDooberry = world.resolve(realthing); annotations = resolvedDooberry.getAnnotationTypes(); } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index afafc943a..495656bba 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -1336,6 +1336,68 @@ public class BcelShadow extends Shadow { // what the full set of annotations could be (due to static/dynamic type differences...) } } + + protected Member getRelevantMember(Member relevantMember, ResolvedType relevantType){ + if (relevantMember != null){ + return relevantMember; + } + + relevantMember = getSignature().resolve(world); + + // check the ITD'd dooberries + List mungers = relevantType.resolve(world).getInterTypeMungers(); + for (Iterator iter = mungers.iterator(); iter.hasNext();) { + BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next(); + if (typeMunger.getMunger() instanceof NewMethodTypeMunger || + typeMunger.getMunger() instanceof NewConstructorTypeMunger) { + ResolvedMember fakerm = typeMunger.getSignature(); + if (fakerm.getName().equals(getSignature().getName()) && + fakerm.getParameterSignature().equals(getSignature().getParameterSignature())){ + if (relevantMember.getKind()==ResolvedMember.CONSTRUCTOR){ + relevantMember = AjcMemberMaker.interConstructor( + relevantType, + (ResolvedMember)relevantMember, + typeMunger.getAspectType()); + } else { + relevantMember = AjcMemberMaker.interMethod((ResolvedMember)relevantMember, + typeMunger.getAspectType(), false); + } + // in the above.. what about if it's on an Interface? Can that happen? + // then the last arg of the above should be true + return relevantMember; + } + } + } + return null; + } + + protected ResolvedType [] getAnnotations(Member relevantMember, ResolvedType relevantType){ + if (relevantMember == null){ + // check the ITD'd dooberries + List mungers = relevantType.resolve(world).getInterTypeMungers(); + for (Iterator iter = mungers.iterator(); iter.hasNext();) { + BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next(); + if (typeMunger.getMunger() instanceof NewMethodTypeMunger || + typeMunger.getMunger() instanceof NewConstructorTypeMunger) { + ResolvedMember fakerm = typeMunger.getSignature(); + //if (fakerm.hasAnnotations()) + + ResolvedMember ajcMethod = (getSignature().getKind()==ResolvedMember.CONSTRUCTOR? + AjcMemberMaker.postIntroducedConstructor(typeMunger.getAspectType(),fakerm.getDeclaringType(),fakerm.getParameterTypes()): + AjcMemberMaker.interMethodDispatcher(fakerm,typeMunger.getAspectType())); + //AjcMemberMaker.interMethodBody(fakerm,typeMunger.getAspectType())); + ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod); + if (fakerm.getName().equals(getSignature().getName()) && + fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) { + relevantType = typeMunger.getAspectType(); + relevantMember = rmm; + return relevantMember.getAnnotationTypes(); + } + } + } + } + return relevantMember.getAnnotationTypes(); + } public void initializeKindedAnnotationVars() { if (kindedAnnotationVars != null) return; @@ -1355,30 +1417,9 @@ public class BcelShadow extends Shadow { } else if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) { relevantMember = findMethod2(relevantType.resolve(world).getDeclaredMethods(),getSignature()); - - if (relevantMember == null) { - // check the ITD'd dooberries - List mungers = relevantType.resolve(world).getInterTypeMungers(); - for (Iterator iter = mungers.iterator(); iter.hasNext();) { - BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next(); - if (typeMunger.getMunger() instanceof NewMethodTypeMunger || - typeMunger.getMunger() instanceof NewConstructorTypeMunger) { - ResolvedMember fakerm = typeMunger.getSignature(); - //if (fakerm.hasAnnotations()) - - ResolvedMember ajcMethod = (getSignature().getKind()==ResolvedMember.CONSTRUCTOR? - AjcMemberMaker.postIntroducedConstructor(typeMunger.getAspectType(),fakerm.getDeclaringType(),fakerm.getParameterTypes()): - AjcMemberMaker.interMethodBody(fakerm,typeMunger.getAspectType())); - ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod); - if (fakerm.getName().equals(getSignature().getName()) && - fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) { - relevantType = typeMunger.getAspectType(); - relevantMember = rmm; - } - } - } - } - annotations = relevantMember.getAnnotationTypes(); + + annotations = getAnnotations(relevantMember,relevantType); + relevantMember = getRelevantMember(relevantMember,relevantType); } else if (getKind() == Shadow.FieldSet || getKind() == Shadow.FieldGet) { relevantMember = findField(relevantType.getDeclaredFields(),getSignature()); @@ -1407,29 +1448,8 @@ public class BcelShadow extends Shadow { ResolvedMember rm[] = relevantType.getDeclaredMethods(); relevantMember = findMethod2(relevantType.getDeclaredMethods(),getSignature()); - if (relevantMember == null) { - // check the ITD'd dooberries - List mungers = relevantType.resolve(world).getInterTypeMungers(); - for (Iterator iter = mungers.iterator(); iter.hasNext();) { - BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next(); - if (typeMunger.getMunger() instanceof NewMethodTypeMunger || - typeMunger.getMunger() instanceof NewConstructorTypeMunger) { - ResolvedMember fakerm = typeMunger.getSignature(); - //if (fakerm.hasAnnotations()) - - ResolvedMember ajcMethod = (getSignature().getKind()==ResolvedMember.CONSTRUCTOR? - AjcMemberMaker.postIntroducedConstructor(typeMunger.getAspectType(),fakerm.getDeclaringType(),fakerm.getParameterTypes()): - AjcMemberMaker.interMethodBody(fakerm,typeMunger.getAspectType())); - ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod); - if (fakerm.getName().equals(getSignature().getName()) && - fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) { - relevantType = typeMunger.getAspectType(); - relevantMember = rmm; - } - } - } - } - annotations = relevantMember.getAnnotationTypes(); + annotations = getAnnotations(relevantMember,relevantType); + relevantMember = getRelevantMember(relevantMember,relevantType); } else if (getKind() == Shadow.ExceptionHandler) { relevantType = getSignature().getParameterTypes()[0].resolve(world); diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 8ea410091..5de5b1065 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -55,6 +55,7 @@ import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverStateInfo; +import org.aspectj.weaver.patterns.DeclareAnnotation; import org.aspectj.weaver.patterns.Pointcut; @@ -708,13 +709,14 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } private boolean mungeNewMethod(BcelClassWeaver weaver, NewMethodTypeMunger munger) { - ResolvedMember signature = munger.getSignature(); - // TODO asc I'm confused? Why do we treat the 'real method' (the inter method body) as the dispatch method? - ResolvedMember dispatchMethod = munger.getInterMethodBody(aspectType); - + ResolvedMember unMangledInterMethod = munger.getSignature(); + // do matching on the unMangled one, but actually add them to the mangled method + ResolvedMember interMethodBody = munger.getInterMethodBody(aspectType); + ResolvedMember interMethodDispatcher = munger.getInterMethodDispatcher(aspectType); + LazyClassGen gen = weaver.getLazyClassGen(); - ResolvedType onType = weaver.getWorld().resolve(signature.getDeclaringType(),munger.getSourceLocation()); + ResolvedType onType = weaver.getWorld().resolve(unMangledInterMethod.getDeclaringType(),munger.getSourceLocation()); if (onType.isRawType()) onType = onType.getGenericType(); boolean onInterface = onType.isInterface(); @@ -730,50 +732,62 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } if (onType.equals(gen.getType())) { - ResolvedMember introMethod = - AjcMemberMaker.interMethod(signature, aspectType, onInterface); + ResolvedMember mangledInterMethod = + AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, onInterface); - AnnotationX annotationsOnRealMember[] = null; + + LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod); + // pr98901 // For copying the annotations across, we have to discover the real member in the aspect // which is holding them. - if (weaver.getWorld().isInJava5Mode() && !onInterface && munger.getSignature().isPublic() && !munger.getSignature().isAbstract()) { - ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,dispatchMethod); + if (weaver.getWorld().isInJava5Mode()){ + AnnotationX annotationsOnRealMember[] = null; + ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodDispatcher); if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+ - dispatchMethod+"' on aspect "+aspectType); + interMethodDispatcher+"' on aspect "+aspectType); annotationsOnRealMember = realMember.getAnnotations(); - } - - LazyMethodGen mg = makeMethodGen(gen, introMethod); - - if (annotationsOnRealMember!=null) { - for (int i = 0; i < annotationsOnRealMember.length; i++) { - AnnotationX annotationX = annotationsOnRealMember[i]; - Annotation a = annotationX.getBcelAnnotation(); - AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); - mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld())); + + if (annotationsOnRealMember!=null) { + for (int i = 0; i < annotationsOnRealMember.length; i++) { + AnnotationX annotationX = annotationsOnRealMember[i]; + Annotation a = annotationX.getBcelAnnotation(); + AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); + mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld())); + } + } + // the below loop fixes the very special (and very stupid) + // case where an aspect declares an annotation + // on an ITD it declared on itself. + List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods(); + for (Iterator i = allDecams.iterator(); i.hasNext();){ + DeclareAnnotation decaMC = (DeclareAnnotation) i.next(); + if (decaMC.matches(unMangledInterMethod,weaver.getWorld()) + && mg.getEnclosingClass().getType() == aspectType) { + mg.addAnnotation(decaMC.getAnnotationX()); + } } } - if (!onInterface && !Modifier.isAbstract(introMethod.getModifiers())) { + if (!onInterface && !Modifier.isAbstract(mangledInterMethod.getModifiers())) { InstructionList body = mg.getBody(); InstructionFactory fact = gen.getFactory(); int pos = 0; - if (!signature.isStatic()) { + if (!unMangledInterMethod.isStatic()) { body.append(InstructionFactory.createThis()); pos++; } - Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes()); + Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes()); for (int i = 0, len = paramTypes.length; i < len; i++) { Type paramType = paramTypes[i]; body.append(InstructionFactory.createLoad(paramType, pos)); pos+=paramType.getSize(); } - body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod)); + body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody)); body.append( InstructionFactory.createReturn( - BcelWorld.makeBcelType(introMethod.getReturnType()))); + BcelWorld.makeBcelType(mangledInterMethod.getReturnType()))); } else { //??? this is okay //if (!(mg.getBody() == null)) throw new RuntimeException("bas"); @@ -788,7 +802,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { return true; - } else if (onInterface && !Modifier.isAbstract(signature.getModifiers())) { + } else if (onInterface && !Modifier.isAbstract(unMangledInterMethod.getModifiers())) { // This means the 'gen' should be the top most implementor // - if it is *not* then something went wrong after we worked @@ -808,19 +822,19 @@ public class BcelTypeMunger extends ConcreteTypeMunger { return false; } else { - ResolvedMember introMethod = - AjcMemberMaker.interMethod(signature, aspectType, false); + ResolvedMember mangledInterMethod = + AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, false); - LazyMethodGen mg = makeMethodGen(gen, introMethod); + LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod); - Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes()); - Type returnType = BcelWorld.makeBcelType(introMethod.getReturnType()); + Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes()); + Type returnType = BcelWorld.makeBcelType(mangledInterMethod.getReturnType()); InstructionList body = mg.getBody(); InstructionFactory fact = gen.getFactory(); int pos = 0; - if (!introMethod.isStatic()) { + if (!mangledInterMethod.isStatic()) { body.append(InstructionFactory.createThis()); pos++; } @@ -829,7 +843,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { body.append(InstructionFactory.createLoad(paramType, pos)); pos+=paramType.getSize(); } - body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod)); + body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody)); body.append(InstructionFactory.createReturn(returnType)); mg.definingType = onType; @@ -844,12 +858,28 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } } - private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember dispatchMethod) { + private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor) { ResolvedMember aspectMethods[] = aspectType.getDeclaredMethods(); + UnresolvedType [] lookingForParams = lookingFor.getParameterTypes(); + ResolvedMember realMember = null; for (int i = 0; realMember==null && i < aspectMethods.length; i++) { ResolvedMember member = aspectMethods[i]; - if (member.getName().equals(dispatchMethod.getName())) realMember = member; + if (member.getName().equals(lookingFor.getName())){ + UnresolvedType [] memberParams = member.getParameterTypes(); + if (memberParams.length == lookingForParams.length){ + boolean matchOK = true; + for (int j = 0; j < memberParams.length && matchOK; j++){ + UnresolvedType memberParam = memberParams[j]; + UnresolvedType lookingForParam = lookingForParams[j].resolve(aspectType.getWorld()); + if (lookingForParam.isTypeVariableReference()) lookingForParam = lookingForParam.getUpperBound(); + if (!memberParam.equals(lookingForParam)){ + matchOK=false; + } + } + if (matchOK) realMember = member; + } + } } return realMember; } @@ -898,6 +928,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { BcelClassWeaver weaver, NewConstructorTypeMunger newConstructorTypeMunger) { + final LazyClassGen currentClass = weaver.getLazyClassGen(); final InstructionFactory fact = currentClass.getFactory(); @@ -919,17 +950,50 @@ public class BcelTypeMunger extends ConcreteTypeMunger { ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor(); //int declaredParameterCount = newConstructorTypeMunger.getDeclaredParameterCount(); - LazyMethodGen freshConstructor = + LazyMethodGen mg = makeMethodGen(currentClass, newConstructorMember); - currentClass.addMethodGen(freshConstructor); + +// pr98901 + // For copying the annotations across, we have to discover the real member in the aspect + // which is holding them. + if (weaver.getWorld().isInJava5Mode()){ + + ResolvedMember interMethodDispatcher =AjcMemberMaker.postIntroducedConstructor(aspectType,onType,newConstructorTypeMunger.getSignature().getParameterTypes()); + AnnotationX annotationsOnRealMember[] = null; + ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodDispatcher); + if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+ + interMethodDispatcher+"' on aspect "+aspectType); + annotationsOnRealMember = realMember.getAnnotations(); + if (annotationsOnRealMember!=null) { + for (int i = 0; i < annotationsOnRealMember.length; i++) { + AnnotationX annotationX = annotationsOnRealMember[i]; + Annotation a = annotationX.getBcelAnnotation(); + AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); + mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld())); + } + } + // the below loop fixes the very special (and very stupid) + // case where an aspect declares an annotation + // on an ITD it declared on itself. + List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods(); + for (Iterator i = allDecams.iterator(); i.hasNext();){ + DeclareAnnotation decaMC = (DeclareAnnotation) i.next(); + if (decaMC.matches(explicitConstructor,weaver.getWorld()) + && mg.getEnclosingClass().getType() == aspectType) { + mg.addAnnotation(decaMC.getAnnotationX()); + } + } + } + + currentClass.addMethodGen(mg); //weaver.addLazyMethodGen(freshConstructor); - InstructionList body = freshConstructor.getBody(); + InstructionList body = mg.getBody(); // add to body: push arts for call to pre, from actual args starting at 1 (skipping this), going to // declared argcount + 1 UnresolvedType[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes(); - Type[] paramTypes = freshConstructor.getArgumentTypes(); + Type[] paramTypes = mg.getArgumentTypes(); int frameIndex = 1; for (int i = 0, len = declaredParams.length; i < len; i++) { body.append(InstructionFactory.createLoad(paramTypes[i], frameIndex)); @@ -941,7 +1005,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { body.append(Utility.createInvoke(fact, null, preMethod)); // create a local, and store return pre stuff into it. - int arraySlot = freshConstructor.allocateLocal(1); + int arraySlot = mg.allocateLocal(1); body.append(InstructionFactory.createStore(Type.OBJECT, arraySlot)); // put this on the stack @@ -1063,6 +1127,21 @@ public class BcelTypeMunger extends ConcreteTypeMunger { return false; } + + ResolvedMember interMethodBody = munger.getInitMethod(aspectType); + + AnnotationX annotationsOnRealMember[] = null; + // pr98901 + // For copying the annotations across, we have to discover the real member in the aspect + // which is holding them. + if (weaver.getWorld().isInJava5Mode()){ + // the below line just gets the method with the same name in aspectType.getDeclaredMethods(); + ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodBody); + if (realMember==null) throw new BCException("Couldn't find ITD init member '"+ + interMethodBody+"' on aspect "+aspectType); + annotationsOnRealMember = realMember.getAnnotations(); + } + if (onType.equals(gen.getType())) { if (onInterface) { LazyMethodGen mg = makeMethodGen(gen, @@ -1076,7 +1155,18 @@ public class BcelTypeMunger extends ConcreteTypeMunger { weaver.addInitializer(this); FieldGen fg = makeFieldGen(gen, AjcMemberMaker.interFieldClassField(field, aspectType)); - gen.addField(fg.getField(),getSourceLocation()); + + if (annotationsOnRealMember!=null) { + for (int i = 0; i < annotationsOnRealMember.length; i++) { + AnnotationX annotationX = annotationsOnRealMember[i]; + Annotation a = annotationX.getBcelAnnotation(); + AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); + fg.addAnnotation(ag); + } + } + + gen.addField(fg.getField(),getSourceLocation()); + } return true; } else if (onInterface && gen.getType().isTopmostImplementor(onType)) { |