diff options
author | aclement <aclement> | 2006-08-14 14:21:38 +0000 |
---|---|---|
committer | aclement <aclement> | 2006-08-14 14:21:38 +0000 |
commit | 2d33e8d998fde7f5d695e8be56b2d197622e7cfc (patch) | |
tree | 4906fe65937d62647d3f3b18c89c8d45df4c207d /weaver | |
parent | 67bbaac0301bf2007c16ab5b6ad0e62664a99fbd (diff) | |
download | aspectj-2d33e8d998fde7f5d695e8be56b2d197622e7cfc.tar.gz aspectj-2d33e8d998fde7f5d695e8be56b2d197622e7cfc.zip |
133770 'call and ltw': now able to complete ITD binding for binary types in LTW world
Diffstat (limited to 'weaver')
-rw-r--r-- | weaver/src/org/aspectj/weaver/World.java | 66 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelWorld.java | 128 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/ltw/LTWWorld.java | 19 |
3 files changed, 210 insertions, 3 deletions
diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index fb17ab9d3..2112f3525 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -109,6 +109,7 @@ public abstract class World implements Dump.INode { private boolean fastDelegateSupportEnabled = isASMAround; private boolean runMinimalMemory = false; private boolean shouldPipelineCompilation = true; + private boolean completeBinaryTypes = true; public boolean forDEBUG_structuralChangesCode = false; public boolean forDEBUG_bridgingCode = false; @@ -267,6 +268,24 @@ public abstract class World implements Dump.INode { if (!allowMissing && ret.isMissing()) { ret = handleRequiredMissingTypeDuringResolution(ty); } + + if (completeBinaryTypes && needsCompletion() && isLocallyDefined(ret.getName())) { + if (typeCompletionInProgress) { + typesForCompletion.add(ret); + } else { + try { + typeCompletionInProgress=true; + completeType(ret); + } finally { + typeCompletionInProgress=false; + } + while (typesForCompletion.size()!=0) { + ResolvedType rt = (ResolvedType)typesForCompletion.get(0); + completeType(rt); + typesForCompletion.remove(0); + } + } + } } // Pulling in the type may have already put the right entry in the map @@ -275,7 +294,42 @@ public abstract class World implements Dump.INode { } return ret; } + + // --- these methods are for supporting loadtime weaving with inter type declarations + // the idea is that when types are resolved, we give the world a chance to say whether + // it needs to 'finish them off' - ie. attach type mungers for ITDs. These types won't + // actually get woven at this time, they will merely have type mungers attached to them + // for the purposes of answering questions like 'what is your supertype?' correctly. + + /** + * return true if types need completing when getting resolved - overridden by subtypes. + */ + protected boolean needsCompletion() { + return false; + } + + /** + * Called when a type is resolved - enables its type hierarchy to be finished off before we + * proceed + */ + protected void completeType(ResolvedType ret) {} + + + /** + * Return true if the classloader relating to this world is definetly the one that will + * define the specified class. Return false otherwise or we don't know for certain. + */ + public boolean isLocallyDefined(String classname) { + return false; + } + // One type is completed at a time, if multiple need doing then they + // are queued up + private boolean typeCompletionInProgress = false; + private List/*ResolvedType*/typesForCompletion = new ArrayList(); + + // --- + /** * We tried to resolve a type and couldn't find it... */ @@ -765,8 +819,10 @@ public abstract class World implements Dump.INode { public final static String xsetRUN_MINIMAL_MEMORY ="runMinimalMemory"; // default true public final static String xsetDEBUG_STRUCTURAL_CHANGES_CODE = "debugStructuralChangesCode"; // default false public final static String xsetDEBUG_BRIDGING = "debugBridging"; // default false - public final static String xsetPIPELINE_COMPILATION = "pipelineCompilation"; // default true + public final static String xsetPIPELINE_COMPILATION = "pipelineCompilation"; public final static String xsetPIPELINE_COMPILATION_DEFAULT = "true"; + public final static String xsetCOMPLETE_BINARY_TYPES = "completeBinaryTypes"; + public final static String xsetCOMPLETE_BINARY_TYPES_DEFAULT = "true"; public boolean isInJava5Mode() { return behaveInJava5Way; @@ -1153,6 +1209,12 @@ public abstract class World implements Dump.INode { String s = p.getProperty(xsetPIPELINE_COMPILATION,xsetPIPELINE_COMPILATION_DEFAULT); shouldPipelineCompilation = s.equalsIgnoreCase("true"); + + s = p.getProperty(xsetCOMPLETE_BINARY_TYPES,xsetCOMPLETE_BINARY_TYPES_DEFAULT); + completeBinaryTypes = s.equalsIgnoreCase("true"); + if (!completeBinaryTypes) { + getMessageHandler().handleMessage(MessageUtil.info("[completeBinaryTypes=false] Completion of binary types deactivated")); + } s = p.getProperty(xsetRUN_MINIMAL_MEMORY,"false"); runMinimalMemory = s.equalsIgnoreCase("true"); @@ -1206,4 +1268,4 @@ public abstract class World implements Dump.INode { public boolean isASMAround() { return isASMAround; } -} +}
\ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java index f7bd4d5f1..b0d5ce96a 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java @@ -53,11 +53,14 @@ import org.aspectj.bridge.IMessageHandler; import org.aspectj.weaver.Advice; import org.aspectj.weaver.AdviceKind; import org.aspectj.weaver.AjAttribute; +import org.aspectj.weaver.AnnotationOnTypeMunger; +import org.aspectj.weaver.AnnotationX; import org.aspectj.weaver.BCException; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.ICrossReferenceHandler; import org.aspectj.weaver.Member; import org.aspectj.weaver.MemberImpl; +import org.aspectj.weaver.NewParentTypeMunger; import org.aspectj.weaver.ReferenceType; import org.aspectj.weaver.ReferenceTypeDelegate; import org.aspectj.weaver.ResolvedMember; @@ -68,6 +71,8 @@ import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.World; import org.aspectj.weaver.AjAttribute.Aspect; import org.aspectj.weaver.asm.AsmDelegate; +import org.aspectj.weaver.patterns.DeclareAnnotation; +import org.aspectj.weaver.patterns.DeclareParents; import org.aspectj.weaver.patterns.FormalBinding; import org.aspectj.weaver.patterns.PerClause; import org.aspectj.weaver.patterns.Pointcut; @@ -719,4 +724,127 @@ public class BcelWorld extends World implements Repository { return true; } } + + /** + * Apply a single declare parents - return true if we change the type + */ + private boolean applyDeclareParents(DeclareParents p, ResolvedType onType) { + boolean didSomething = false; + List newParents = p.findMatchingNewParents(onType,true); + if (!newParents.isEmpty()) { + didSomething=true; + BcelObjectType classType = BcelWorld.getBcelObjectType(onType); + //System.err.println("need to do declare parents for: " + onType); + for (Iterator j = newParents.iterator(); j.hasNext(); ) { + ResolvedType newParent = (ResolvedType)j.next(); + + // We set it here so that the imminent matching for ITDs can succeed - we + // still haven't done the necessary changes to the class file itself + // (like transform super calls) - that is done in BcelTypeMunger.mungeNewParent() + classType.addParent(newParent); + ResolvedTypeMunger newParentMunger = new NewParentTypeMunger(newParent); + newParentMunger.setSourceLocation(p.getSourceLocation()); + onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, getCrosscuttingMembersSet().findAspectDeclaringParents(p))); + } + } + return didSomething; + } + + /** + * Apply a declare @type - return true if we change the type + */ + private boolean applyDeclareAtType(DeclareAnnotation decA, ResolvedType onType,boolean reportProblems) { + boolean didSomething = false; + if (decA.matches(onType)) { + + if (onType.hasAnnotation(decA.getAnnotationX().getSignature())) { + // already has it + return false; + } + + AnnotationX annoX = decA.getAnnotationX(); + + // check the annotation is suitable for the target + boolean isOK = checkTargetOK(decA,onType,annoX); + + if (isOK) { + didSomething = true; + ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger(annoX); + newAnnotationTM.setSourceLocation(decA.getSourceLocation()); + onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM,decA.getAspect().resolve(this))); + decA.copyAnnotationTo(onType); + } + } + return didSomething; + } + + /** + * Checks for an @target() on the annotation and if found ensures it allows the annotation + * to be attached to the target type that matched. + */ + private boolean checkTargetOK(DeclareAnnotation decA, ResolvedType onType, AnnotationX annoX) { + if (annoX.specifiesTarget()) { + if ( (onType.isAnnotation() && !annoX.allowedOnAnnotationType()) || + (!annoX.allowedOnRegularType())) { + return false; + } + } + return true; + } + + // Hmmm - very similar to the code in BcelWeaver.weaveParentTypeMungers - this code + // doesn't need to produce errors/warnings though as it won't really be weaving. + protected void weaveInterTypeDeclarations(ResolvedType onType) { + + List declareParentsList = getCrosscuttingMembersSet().getDeclareParents(); + if (onType.isRawType()) onType = onType.getGenericType(); + onType.clearInterTypeMungers(); + + List decpToRepeat = new ArrayList(); + + boolean aParentChangeOccurred = false; + boolean anAnnotationChangeOccurred = false; + // First pass - apply all decp mungers + for (Iterator i = declareParentsList.iterator(); i.hasNext(); ) { + DeclareParents decp = (DeclareParents)i.next(); + boolean typeChanged = applyDeclareParents(decp,onType); + if (typeChanged) { + aParentChangeOccurred = true; + } else { // Perhaps it would have matched if a 'dec @type' had modified the type + if (!decp.getChild().isStarAnnotation()) decpToRepeat.add(decp); + } + } + + // Still first pass - apply all dec @type mungers + for (Iterator i = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator();i.hasNext();) { + DeclareAnnotation decA = (DeclareAnnotation)i.next(); + boolean typeChanged = applyDeclareAtType(decA,onType,true); + if (typeChanged) { + anAnnotationChangeOccurred = true; + } + } + + while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) { + anAnnotationChangeOccurred = aParentChangeOccurred = false; + List decpToRepeatNextTime = new ArrayList(); + for (Iterator iter = decpToRepeat.iterator(); iter.hasNext();) { + DeclareParents decp = (DeclareParents) iter.next(); + boolean typeChanged = applyDeclareParents(decp,onType); + if (typeChanged) { + aParentChangeOccurred = true; + } else { + decpToRepeatNextTime.add(decp); + } + } + + for (Iterator iter = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator(); iter.hasNext();) { + DeclareAnnotation decA = (DeclareAnnotation) iter.next(); + boolean typeChanged = applyDeclareAtType(decA,onType,false); + if (typeChanged) { + anAnnotationChangeOccurred = true; + } + } + decpToRepeat = decpToRepeatNextTime; + } + } }
\ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java b/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java index 2a9db1024..49596ca51 100644 --- a/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java +++ b/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java @@ -24,6 +24,7 @@ import org.aspectj.weaver.ReferenceType; import org.aspectj.weaver.ReferenceTypeDelegate; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.bcel.BcelWorld; +import org.aspectj.weaver.loadtime.IWeavingContext; import org.aspectj.weaver.reflect.AnnotationFinder; import org.aspectj.weaver.reflect.IReflectionWorld; import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegateFactory; @@ -47,6 +48,7 @@ public class LTWWorld extends BcelWorld implements IReflectionWorld { private AnnotationFinder annotationFinder; private ClassLoader loader; // weavingContext? + private IWeavingContext weavingContext; protected final static Class concurrentMapClass = makeConcurrentMapClass(); protected static Map/*<String, WeakReference<ReflectionBasedReferenceTypeDelegate>>*/ bootstrapTypes = makeConcurrentMap(); @@ -54,9 +56,10 @@ public class LTWWorld extends BcelWorld implements IReflectionWorld { /** * Build a World from a ClassLoader, for LTW support */ - public LTWWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) { + public LTWWorld(ClassLoader loader, IWeavingContext weavingContext, IMessageHandler handler, ICrossReferenceHandler xrefHandler) { super(loader, handler, xrefHandler); this.loader = loader; + this.weavingContext = weavingContext; setBehaveInJava5Way(LangUtil.is15VMOrGreater()); annotationFinder = ReflectionWorld.makeAnnotationFinderIfAny(loader, this); @@ -184,4 +187,18 @@ public class LTWWorld extends BcelWorld implements IReflectionWorld { return true; } + protected void completeType(ResolvedType ret) { + getLint().typeNotExposedToWeaver.setSuppressed(true); + weaveInterTypeDeclarations(ret); + getLint().typeNotExposedToWeaver.setSuppressed(false); + } + + protected boolean needsCompletion() { + return true; + } + + public boolean isLocallyDefined(String classname) { + return weavingContext.isLocallyDefined(classname); + } + } |