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;
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
}
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...
*/
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;
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");
public boolean isASMAround() {
return isASMAround;
}
-}
+}
\ No newline at end of file
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;
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;
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
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;
private AnnotationFinder annotationFinder;
private ClassLoader loader; // weavingContext?
+ private IWeavingContext weavingContext;
protected final static Class concurrentMapClass = makeConcurrentMapClass();
protected static Map/*<String, WeakReference<ReflectionBasedReferenceTypeDelegate>>*/ bootstrapTypes = makeConcurrentMap();
/**
* 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);
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);
+ }
+
}