diff options
author | aclement <aclement> | 2005-01-18 11:39:16 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-01-18 11:39:16 +0000 |
commit | fe310a4e10cf69486f54d5cf4edd4893b0a0835c (patch) | |
tree | e5b015ba92184dce33b61a686b9d7dd420403570 /weaver | |
parent | 0e14ef28ab34628b3399cccb0118362fc22114a7 (diff) | |
download | aspectj-fe310a4e10cf69486f54d5cf4edd4893b0a0835c.tar.gz aspectj-fe310a4e10cf69486f54d5cf4edd4893b0a0835c.zip |
PerTypeWithin support.
Diffstat (limited to 'weaver')
13 files changed, 430 insertions, 5 deletions
diff --git a/weaver/src/org/aspectj/weaver/Advice.java b/weaver/src/org/aspectj/weaver/Advice.java index 11b8f69c7..a6cd8f412 100644 --- a/weaver/src/org/aspectj/weaver/Advice.java +++ b/weaver/src/org/aspectj/weaver/Advice.java @@ -67,6 +67,13 @@ public abstract class Advice extends ShadowMunger { return ret; } + // PTWIMPL per type within entry advice is what initializes the aspect instance in the matched type + public static Advice makePerTypeWithinEntry(World world, Pointcut p, ResolvedTypeX inAspect) { + Advice ret = world.concreteAdvice(AdviceKind.PerTypeWithinEntry,p,null,0,p); + ret.concreteAspect = inAspect; + return ret; + } + public static Advice makeSoftener(World world, Pointcut entry, TypePattern exceptionType,ResolvedTypeX inAspect,IHasSourceLocation loc) { Advice ret = world.concreteAdvice(AdviceKind.Softener, entry, null, 0, loc); diff --git a/weaver/src/org/aspectj/weaver/AdviceKind.java b/weaver/src/org/aspectj/weaver/AdviceKind.java index abc560386..57851fd64 100644 --- a/weaver/src/org/aspectj/weaver/AdviceKind.java +++ b/weaver/src/org/aspectj/weaver/AdviceKind.java @@ -53,6 +53,8 @@ public class AdviceKind extends TypeSafeEnum { case 12: return PerTargetEntry; case 13: return Softener; + + case 14: return PerTypeWithinEntry; } throw new RuntimeException("unimplemented kind: " + key); } @@ -75,6 +77,9 @@ public class AdviceKind extends TypeSafeEnum { public static final AdviceKind PerTargetEntry = new AdviceKind("perTargetEntry", 12, 1, false, false); public static final AdviceKind Softener = new AdviceKind("softener", 13, 1, false, false); + + // PTWIMPL Advice representing when aspect should be initialized + public static final AdviceKind PerTypeWithinEntry = new AdviceKind("perTypeWithinEntry",14,1,false,false); public static AdviceKind stringToKind(String s) { @@ -99,8 +104,10 @@ public class AdviceKind extends TypeSafeEnum { } public boolean isPerEntry() { - return this == PerCflowEntry || this == PerCflowBelowEntry || - this == PerThisEntry || this == PerTargetEntry; + return + this == PerCflowEntry || this == PerCflowBelowEntry || + this == PerThisEntry || this == PerTargetEntry || + this == PerTypeWithinEntry; // PTWIMPL Allow for PTW case } public boolean isPerObjectEntry() { diff --git a/weaver/src/org/aspectj/weaver/AjcMemberMaker.java b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java index f19776f05..d285a1574 100644 --- a/weaver/src/org/aspectj/weaver/AjcMemberMaker.java +++ b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java @@ -68,6 +68,15 @@ public class AjcMemberMaker { "<init>", "()V"); } + + public static Member noAspectBoundExceptionInit2() { + return new ResolvedMember( + Member.METHOD, + NO_ASPECT_BOUND_EXCEPTION, + Modifier.PUBLIC, + "<init>", + "(Ljava/lang/String;Ljava/lang/Throwable;)V"); + } public static Member noAspectBoundExceptionInitWithCause() { return new ResolvedMember( @@ -129,6 +138,27 @@ public class AjcMemberMaker { NameMangler.perObjectInterfaceField(aspectType), TypeX.NONE); } + + // PTWIMPL ResolvedMember for aspect instance field, declared in matched type + public static ResolvedMember perTypeWithinField(TypeX declaringType, ResolvedTypeX aspectType) { + int modifiers = Modifier.PRIVATE | Modifier.STATIC; + if (!TypeX.SERIALIZABLE.isAssignableFrom(aspectType, aspectType.getWorld())) { + modifiers |= Modifier.TRANSIENT; + } + return new ResolvedMember(Member.FIELD, declaringType, modifiers, + aspectType, NameMangler.perTypeWithinFieldForTarget(aspectType), TypeX.NONE); + } + + // PTWIMPL ResolvedMember for type instance field, declared in aspect + // (holds typename for which aspect instance exists) + public static ResolvedMember perTypeWithinWithinTypeField(TypeX declaringType, ResolvedTypeX aspectType) { + int modifiers = Modifier.PRIVATE; + if (!TypeX.SERIALIZABLE.isAssignableFrom(aspectType, aspectType.getWorld())) { + modifiers |= Modifier.TRANSIENT; + } + return new ResolvedMember(Member.FIELD, declaringType, modifiers, + TypeX.forSignature("Ljava/lang/String;"), NameMangler.PERTYPEWITHIN_WITHINTYPEFIELD, TypeX.NONE); + } public static ResolvedMember perObjectBind(TypeX declaringType) { @@ -139,6 +169,34 @@ public class AjcMemberMaker { NameMangler.PEROBJECT_BIND_METHOD, "(Ljava/lang/Object;)V"); } + + // PTWIMPL ResolvedMember for getInstance() method, declared in aspect + public static ResolvedMember perTypeWithinGetInstance(TypeX declaringType) { +// private static a.X ajc$getInstance(java.lang.Class) throws java/lang/Exception + ResolvedMember rm = new ResolvedMember( + Member.METHOD, + declaringType, + PRIVATE_STATIC, + declaringType, // return value + NameMangler.PERTYPEWITHIN_GETINSTANCE_METHOD, + new TypeX[]{TypeX.JAVA_LANG_CLASS}, + new TypeX[]{TypeX.JAVA_LANG_EXCEPTION} + ); + return rm; + } + + public static ResolvedMember perTypeWithinCreateAspectInstance(TypeX declaringType) { + // public static a.X ajc$createAspectInstance(java.lang.String) + ResolvedMember rm = new ResolvedMember( + Member.METHOD, + declaringType, + PUBLIC_STATIC, + declaringType, // return value + NameMangler.PERTYPEWITHIN_CREATEASPECTINSTANCE_METHOD, + new TypeX[]{TypeX.forSignature("Ljava/lang/String;")},new TypeX[]{} + ); + return rm; + } public static TypeX perObjectInterfaceType(TypeX aspectType) { @@ -163,8 +221,16 @@ public class AjcMemberMaker { "(" + aspectType.getSignature() + ")V"); } - - + // PTWIMPL ResolvedMember for localAspectOf() method, declared in matched type + public static ResolvedMember perTypeWithinLocalAspectOf(TypeX shadowType,TypeX aspectType) { + return new ResolvedMember( + Member.METHOD, + shadowType,//perTypeWithinInterfaceType(aspectType), + Modifier.PUBLIC | Modifier.STATIC, + NameMangler.perTypeWithinLocalAspectOf(aspectType), + "()" + aspectType.getSignature()); + } + public static ResolvedMember perSingletonAspectOfMethod(TypeX declaringType) { return new ResolvedMember(Member.METHOD, @@ -198,6 +264,20 @@ public class AjcMemberMaker { "(Ljava/lang/Object;)Z"); }; + // PTWIMPL ResolvedMember for aspectOf(), declared in aspect + public static ResolvedMember perTypeWithinAspectOfMethod(TypeX declaringType) { + return new ResolvedMember(Member.METHOD, + declaringType, PUBLIC_STATIC, "aspectOf", + "(Ljava/lang/Class;)" + declaringType.getSignature()); + } + + // PTWIMPL ResolvedMember for hasAspect(), declared in aspect + public static ResolvedMember perTypeWithinHasAspectMethod(TypeX declaringType) { + return new ResolvedMember(Member.METHOD, + declaringType, PUBLIC_STATIC, "hasAspect", + "(Ljava/lang/Class;)Z"); + }; + // -- privileged accessors public static ResolvedMember privilegedAccessMethodForMethod(TypeX aspectType, ResolvedMember method) { diff --git a/weaver/src/org/aspectj/weaver/NameMangler.java b/weaver/src/org/aspectj/weaver/NameMangler.java index 6d49a45fb..1888faef8 100644 --- a/weaver/src/org/aspectj/weaver/NameMangler.java +++ b/weaver/src/org/aspectj/weaver/NameMangler.java @@ -37,7 +37,12 @@ public class NameMangler { public static final String PERCFLOW_PUSH_METHOD = PREFIX + "perCflowPush"; public static final String PEROBJECT_BIND_METHOD = PREFIX + "perObjectBind"; - + + // PTWIMPL Method and field names + public static final String PERTYPEWITHIN_GETINSTANCE_METHOD = PREFIX + "getInstance"; + public static final String PERTYPEWITHIN_CREATEASPECTINSTANCE_METHOD = PREFIX + "createAspectInstance"; + public static final String PERTYPEWITHIN_WITHINTYPEFIELD = PREFIX + "withinType"; + public static final String AJC_PRE_CLINIT_NAME = PREFIX + "preClinit"; public static final String AJC_POST_CLINIT_NAME = PREFIX + "postClinit"; @@ -57,6 +62,17 @@ public class NameMangler { } + // PTWIMPL method names that must include aspect type + public static String perTypeWithinFieldForTarget(TypeX aspectType) { + String s = makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance"); + return s; + } + + public static String perTypeWithinLocalAspectOf(TypeX aspectType) { + return makeName(aspectType.getNameAsIdentifier(), "localAspectOf"); + } + + public static String privilegedAccessMethodForMethod(String name, TypeX objectType, TypeX aspectType) { return makeName("privMethod", aspectType.getNameAsIdentifier(), diff --git a/weaver/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java b/weaver/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java new file mode 100644 index 000000000..4da7f1116 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/PerTypeWithinTargetTypeMunger.java @@ -0,0 +1,52 @@ +/* ******************************************************************* + * Copyright (c) 2005 + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * ******************************************************************/ + +package org.aspectj.weaver; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.weaver.patterns.PerTypeWithin; +import org.aspectj.weaver.patterns.Pointcut; +import org.aspectj.weaver.patterns.TypePattern; + +// PTWIMPL Target type munger adds the localAspectOf() method +public class PerTypeWithinTargetTypeMunger extends ResolvedTypeMunger { + private ResolvedMember localAspectOfMethod; + private TypeX aspectType; + private PerTypeWithin testPointcut; + + + public PerTypeWithinTargetTypeMunger(TypeX aspectType, PerTypeWithin testPointcut) { + super(PerTypeWithinInterface, null); + this.aspectType = aspectType; + this.testPointcut = testPointcut; + } + + + public void write(DataOutputStream s) throws IOException { + throw new RuntimeException("shouldn't be serialized"); + } + + public TypeX getAspectType() { + return aspectType; + } + + public Pointcut getTestPointcut() { + return testPointcut; + } + + public boolean matches(ResolvedTypeX matchType, ResolvedTypeX aspectType) { + return testPointcut.getTypePattern().matches(matchType,TypePattern.STATIC).alwaysTrue(); + } + +} diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java index f28e87535..17c87c9d3 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java @@ -224,6 +224,7 @@ public abstract class ResolvedTypeMunger { public static final Kind PrivilegedAccess = new Kind("PrivilegedAccess", 4); public static final Kind Parent = new Kind("Parent", 6); + public static final Kind PerTypeWithinInterface = new Kind("PerTypeWithinInterface",7); // PTWIMPL not serialized, used during concretization of aspects public static final String SUPER_DISPATCH_NAME = "superDispatch"; diff --git a/weaver/src/org/aspectj/weaver/TypeX.java b/weaver/src/org/aspectj/weaver/TypeX.java index c13349eb3..3dad1b8fa 100644 --- a/weaver/src/org/aspectj/weaver/TypeX.java +++ b/weaver/src/org/aspectj/weaver/TypeX.java @@ -584,6 +584,9 @@ public class TypeX implements AnnotatedElement { public static final TypeX AT_RETENTION = forSignature("Ljava/lang/annotation/Retention;"); public static final TypeX ENUM = forSignature("Ljava/lang/Enum;"); public static final TypeX ANNOTATION = forSignature("Ljava/lang/annotation/Annotation;"); + public static final TypeX JAVA_LANG_CLASS = forSignature("Ljava/lang/Class;"); + public static final TypeX JAVA_LANG_EXCEPTION = forSignature("Ljava/lang/Exception;"); + public static final TypeX JAVA_LANG_REFLECT_METHOD = forSignature("Ljava/lang/reflect/Method;"); // ---- helpers diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java index 76589720f..344602d97 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java @@ -160,6 +160,9 @@ public class BcelAdvice extends Advice { shadow.weavePerObjectEntry(this, (BcelVar)shadow.getTargetVar()); } else if (getKind() == AdviceKind.Softener) { shadow.weaveSoftener(this, ((ExactTypePattern)exceptionType).getType()); + } else if (getKind() == AdviceKind.PerTypeWithinEntry) { + // PTWIMPL Entry to ptw is the static initialization of a type that matched the ptw type pattern + shadow.weavePerTypeWithinAspectInitialization(this,shadow.getEnclosingType()); } else { throw new BCException("unimplemented kind: " + getKind()); } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index fe32b0aa6..aa03a51ab 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -43,6 +43,7 @@ import org.aspectj.apache.bcel.generic.LoadInstruction; import org.aspectj.apache.bcel.generic.MULTIANEWARRAY; import org.aspectj.apache.bcel.generic.NEW; import org.aspectj.apache.bcel.generic.ObjectType; +import org.aspectj.apache.bcel.generic.PUSH; import org.aspectj.apache.bcel.generic.ReturnInstruction; import org.aspectj.apache.bcel.generic.SWAP; import org.aspectj.apache.bcel.generic.StoreInstruction; @@ -1510,6 +1511,32 @@ public class BcelShadow extends Shadow { range.insert(entryInstructions, Range.InsideBefore); } + + // PTWIMPL Create static initializer to call the aspect factory + /** + * Causes the aspect instance to be *set* for later retrievable through localAspectof()/aspectOf() + */ + public void weavePerTypeWithinAspectInitialization(final BcelAdvice munger,TypeX t) { + final InstructionFactory fact = getFactory(); + + InstructionList entryInstructions = new InstructionList(); + InstructionList entrySuccessInstructions = new InstructionList(); + + BcelObjectType aspectType = BcelWorld.getBcelObjectType(munger.getConcreteAspect()); + String aspectname = munger.getConcreteAspect().getName(); + + String ptwField = NameMangler.perTypeWithinFieldForTarget(munger.getConcreteAspect()); + entrySuccessInstructions.append(new PUSH(fact.getConstantPool(),t.getName())); + + entrySuccessInstructions.append(fact.createInvoke(aspectname,"ajc$createAspectInstance",new ObjectType(aspectname), + new Type[]{new ObjectType("java.lang.String")},Constants.INVOKESTATIC)); + entrySuccessInstructions.append(fact.createPutStatic(t.getName(),ptwField, + new ObjectType(aspectname))); + + entryInstructions.append(entrySuccessInstructions); + + range.insert(entryInstructions, Range.InsideBefore); + } public void weaveCflowEntry(final BcelAdvice munger, final Member cflowField) { diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 935d2f966..d8e755a8c 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -42,6 +42,7 @@ import org.aspectj.weaver.NewFieldTypeMunger; import org.aspectj.weaver.NewMethodTypeMunger; import org.aspectj.weaver.NewParentTypeMunger; import org.aspectj.weaver.PerObjectInterfaceTypeMunger; +//import org.aspectj.weaver.PerTypeWithinTargetTypeMunger; import org.aspectj.weaver.PrivilegedAccessMunger; import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedTypeMunger; @@ -74,6 +75,10 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) { changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger); worthReporting = false; + } else if (munger.getKind() == ResolvedTypeMunger.PerTypeWithinInterface) { + // PTWIMPL Transform the target type (add the aspect instance field) + changed = mungePerTypeWithinTransformer(weaver); + worthReporting = false; } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) { changed = mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger); worthReporting = false; @@ -646,7 +651,42 @@ public class BcelTypeMunger extends ConcreteTypeMunger { return false; } } + + // PTWIMPL Add field to hold aspect instance and an accessor + private boolean mungePerTypeWithinTransformer(BcelClassWeaver weaver) { + LazyClassGen gen = weaver.getLazyClassGen(); + + // if (couldMatch(gen.getBcelObjectType(), munger.getTestPointcut())) { + + // Add (to the target type) the field that will hold the aspect instance + // e.g ajc$com_blah_SecurityAspect$ptwAspectInstance + FieldGen fg = makeFieldGen(gen, AjcMemberMaker.perTypeWithinField(gen.getType(), aspectType)); + gen.addField(fg.getField(),getSourceLocation()); + + // Add an accessor for this new field, the ajc$<aspectname>$localAspectOf() method + // e.g. "public com_blah_SecurityAspect ajc$com_blah_SecurityAspect$localAspectOf()" + Type fieldType = BcelWorld.makeBcelType(aspectType); + LazyMethodGen mg = new LazyMethodGen( + Modifier.PUBLIC | Modifier.STATIC,fieldType, + NameMangler.perTypeWithinLocalAspectOf(aspectType), + new Type[0], new String[0],gen); + InstructionList il = new InstructionList(); + //PTWIMPL ?? Should check if it is null and throw NoAspectBoundException + InstructionFactory fact = gen.getFactory(); + il.append(fact.createFieldAccess( + gen.getClassName(), + fg.getName(), + fieldType, Constants.GETSTATIC)); + il.append(InstructionFactory.createReturn(fieldType)); + mg.getBody().insert(il); + gen.addMethodGen(mg); + return true; +// } else { +// return false; +// } + } + // ??? Why do we have this method? I thought by now we would know if it matched or not private boolean couldMatch( BcelObjectType bcelObjectType, Pointcut pointcut) { diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java index 9b994deb8..575bcc7e1 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java @@ -51,6 +51,8 @@ public class PatternParser { return parsePerCflow(false); } else if (name.equals("percflowbelow")) { return parsePerCflow(true); + } else if (name.equals("pertypewithin")) { // PTWIMPL Parse the pertypewithin clause + return parsePerTypeWithin(); } else { return null; } @@ -74,6 +76,14 @@ public class PatternParser { eat(")"); return new PerObject(entry, isThis); } + + private PerClause parsePerTypeWithin() { + parseIdentifier(); + eat("("); + TypePattern withinTypePattern = parseTypePattern(); + eat(")"); + return new PerTypeWithin(withinTypePattern); + } private PerClause parsePerSingleton() { diff --git a/weaver/src/org/aspectj/weaver/patterns/PerClause.java b/weaver/src/org/aspectj/weaver/patterns/PerClause.java index 5bff424eb..8b59094d1 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerClause.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerClause.java @@ -18,6 +18,7 @@ import java.io.IOException; import org.aspectj.util.TypeSafeEnum; import org.aspectj.weaver.*; +// PTWIMPL New kind added to this class, can be (de)serialized public abstract class PerClause extends Pointcut { protected ResolvedTypeX inAspect; @@ -27,6 +28,7 @@ public abstract class PerClause extends Pointcut { else if (kind == PERCFLOW) return PerCflow.readPerClause(s, context); else if (kind == PEROBJECT) return PerObject.readPerClause(s, context); else if (kind == FROMSUPER) return PerFromSuper.readPerClause(s, context); + else if (kind == PERTYPEWITHIN) return PerTypeWithin.readPerClause(s,context); throw new BCException("unknown kind: " + kind); } @@ -49,6 +51,7 @@ public abstract class PerClause extends Pointcut { case 2: return PERCFLOW; case 3: return PEROBJECT; case 4: return FROMSUPER; + case 5: return PERTYPEWITHIN; } throw new BCException("weird kind " + key); } @@ -62,4 +65,5 @@ public abstract class PerClause extends Pointcut { public static final Kind PERCFLOW = new Kind("percflow", 2); public static final Kind PEROBJECT = new Kind("perobject", 3); public static final Kind FROMSUPER = new Kind("fromsuper", 4); + public static final Kind PERTYPEWITHIN = new Kind("pertypewithin",5); } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java b/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java new file mode 100644 index 000000000..4e29e138b --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java @@ -0,0 +1,175 @@ +/* ******************************************************************* + * Copyright (c) 2005 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * ******************************************************************/ + +package org.aspectj.weaver.patterns; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.bridge.Message; +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.Advice; +import org.aspectj.weaver.AjcMemberMaker; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.Member; +//import org.aspectj.weaver.PerTypeWithinTargetTypeMunger; +import org.aspectj.weaver.PerTypeWithinTargetTypeMunger; +import org.aspectj.weaver.ResolvedTypeMunger; +import org.aspectj.weaver.ResolvedTypeX; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.VersionedDataInputStream; +import org.aspectj.weaver.World; +import org.aspectj.weaver.ast.Expr; +import org.aspectj.weaver.ast.Literal; +import org.aspectj.weaver.ast.Test; + + +// PTWIMPL Represents a parsed pertypewithin() +public class PerTypeWithin extends PerClause { + + private TypePattern typePattern; + + // Any shadow could be considered within a pertypewithin() type pattern + private static final Set kindSet = new HashSet(Shadow.ALL_SHADOW_KINDS); + + public TypePattern getTypePattern() { + return typePattern; + } + + public PerTypeWithin(TypePattern p) { + this.typePattern = p; + } + + public Set couldMatchKinds() { + return kindSet; + } + + // ----- + public FuzzyBoolean fastMatch(FastMatchInfo info) { + if (typePattern.annotationPattern instanceof AnyAnnotationTypePattern) { + return isWithinType(info.getType()); + } + return FuzzyBoolean.MAYBE; + } + + + protected FuzzyBoolean matchInternal(Shadow shadow) { + ResolvedTypeX enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true); + if (enclosingType == ResolvedTypeX.MISSING) { + //PTWIMPL ?? Add a proper message + IMessage msg = new Message( + "Cant find type pertypewithin matching...", + shadow.getSourceLocation(),true,new ISourceLocation[]{getSourceLocation()}); + shadow.getIWorld().getMessageHandler().handleMessage(msg); + } + typePattern.resolve(shadow.getIWorld()); + return isWithinType(enclosingType); + } + + public void resolveBindings(IScope scope, Bindings bindings) { + typePattern = typePattern.resolveBindings(scope, bindings, false, false); + } + + protected Test findResidueInternal(Shadow shadow, ExposedState state) { + Member ptwField = AjcMemberMaker.perTypeWithinField(shadow.getEnclosingType(),inAspect); + + Expr myInstance = + Expr.makeCallExpr(AjcMemberMaker.perTypeWithinLocalAspectOf(shadow.getEnclosingType(),inAspect/*shadow.getEnclosingType()*/), + Expr.NONE,inAspect); + state.setAspectInstance(myInstance); + + // this worked at one point + //Expr myInstance = Expr.makeFieldGet(ptwField,shadow.getEnclosingType().resolve(shadow.getIWorld()));//inAspect); + //state.setAspectInstance(myInstance); + + +// return Test.makeFieldGetCall(ptwField,null,Expr.NONE); + // cflowField, cflowCounterIsValidMethod, Expr.NONE + + // This is what is in the perObject variant of this ... +// Expr myInstance = +// Expr.makeCallExpr(AjcMemberMaker.perTypeWithinAspectOfMethod(inAspect), +// new Expr[] {getVar(shadow)}, inAspect); +// state.setAspectInstance(myInstance); +// return Test.makeCall(AjcMemberMaker.perTypeWithinHasAspectMethod(inAspect), +// new Expr[] { getVar(shadow) }); +// + + + return match(shadow).alwaysTrue()?Literal.TRUE:Literal.FALSE; + } + + + public PerClause concretize(ResolvedTypeX inAspect) { + PerTypeWithin ret = new PerTypeWithin(typePattern); + ret.copyLocationFrom(this); + ret.inAspect = inAspect; + if (inAspect.isAbstract()) return ret; + + + World world = inAspect.getWorld(); + + SignaturePattern sigpat = new SignaturePattern( + Member.STATIC_INITIALIZATION, + ModifiersPattern.ANY, + TypePattern.ANY, + typePattern, + NamePattern.ANY, + TypePatternList.ANY, + ThrowsPattern.ANY, + AnnotationTypePattern.ANY + ); + Pointcut testPc = new KindedPointcut(Shadow.StaticInitialization,sigpat); + Pointcut testPc2= new WithinPointcut(typePattern); + // This munger will initialize the aspect instance field in the matched type + inAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makePerTypeWithinEntry(world, testPc, inAspect)); + + ResolvedTypeMunger munger = new PerTypeWithinTargetTypeMunger(inAspect, ret); + inAspect.crosscuttingMembers.addTypeMunger(world.concreteTypeMunger(munger, inAspect)); + return ret; + + } + + public void write(DataOutputStream s) throws IOException { + PERTYPEWITHIN.write(s); + typePattern.write(s); + writeLocation(s); + } + + public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException { + PerClause ret = new PerTypeWithin(TypePattern.read(s, context)); + ret.readLocation(context, s); + return ret; + } + + public PerClause.Kind getKind() { + return PERTYPEWITHIN; + } + + public String toString() { + return "pertypewithin("+typePattern+")"; + } + + private FuzzyBoolean isWithinType(ResolvedTypeX type) { + while (type != null) { + if (typePattern.matchesStatically(type)) { + return FuzzyBoolean.YES; + } + type = type.getDeclaringType(); + } + return FuzzyBoolean.NO; + } +} |