diff options
author | avasseur <avasseur> | 2005-12-19 13:09:20 +0000 |
---|---|---|
committer | avasseur <avasseur> | 2005-12-19 13:09:20 +0000 |
commit | 2afe12a528f424404d4c88a0db65602fce78254e (patch) | |
tree | 473d06f36ff723c4af7f7998f8c1a582950dcd84 /weaver | |
parent | 4676acbde531b3c00f5572ff4053435e9ba9b1eb (diff) | |
download | aspectj-2afe12a528f424404d4c88a0db65602fce78254e.tar.gz aspectj-2afe12a528f424404d4c88a0db65602fce78254e.zip |
rearchitect @decp
Diffstat (limited to 'weaver')
6 files changed, 243 insertions, 99 deletions
diff --git a/weaver/src/org/aspectj/weaver/AjcMemberMaker.java b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java index 978f80ffd..a0add374c 100644 --- a/weaver/src/org/aspectj/weaver/AjcMemberMaker.java +++ b/weaver/src/org/aspectj/weaver/AjcMemberMaker.java @@ -499,8 +499,18 @@ public class AjcMemberMaker { NameMangler.postIntroducedConstructor(aspectType, targetType), UnresolvedType.insert(targetType, paramTypes)); } - - public static ResolvedMember interConstructor(ResolvedType targetType, ResolvedMember constructor, UnresolvedType aspectType) { + + public static ResolvedMember itdAtDeclareParentsField(ResolvedType targetType, UnresolvedType itdType, UnresolvedType aspectType) { + return new ResolvedMemberImpl( + Member.FIELD, + targetType, + Modifier.PRIVATE, + itdType, + NameMangler.itdAtDeclareParentsField(aspectType, itdType), + null); + } + + public static ResolvedMember interConstructor(ResolvedType targetType, ResolvedMember constructor, UnresolvedType aspectType) { // // ResolvedType targetType, // UnresolvedType[] argTypes, diff --git a/weaver/src/org/aspectj/weaver/MethodDelegateTypeMunger.java b/weaver/src/org/aspectj/weaver/MethodDelegateTypeMunger.java index e7bc20d3b..fbfccd606 100644 --- a/weaver/src/org/aspectj/weaver/MethodDelegateTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/MethodDelegateTypeMunger.java @@ -28,10 +28,12 @@ import org.aspectj.weaver.patterns.TypePattern; */ public class MethodDelegateTypeMunger extends ResolvedTypeMunger { + private final UnresolvedType aspect; + /** - * The field in the aspect that hosts the mixin instance + * The mixin impl (no arg ctor) */ - private final ResolvedMember aspectFieldDelegate; + private final String implClassName; /** * Type pattern this munger applies to @@ -43,52 +45,42 @@ public class MethodDelegateTypeMunger extends ResolvedTypeMunger { * * @param signature * @param aspect - * @param fieldName + * @param implClassName * @param typePattern */ - public MethodDelegateTypeMunger(ResolvedMember signature, ResolvedType aspect, String fieldName, TypePattern typePattern) { + public MethodDelegateTypeMunger(ResolvedMember signature, UnresolvedType aspect, String implClassName, TypePattern typePattern) { super(MethodDelegate, signature); + this.aspect = aspect; this.typePattern = typePattern; - - ResolvedMember[] fields = aspect.getDeclaredFields();//note: will unpack attributes - ResolvedMember field = null; - for (int i = 0; i < fields.length; i++) { - if (fieldName.equals(fields[i].getName())) { - field = fields[i]; - break; - } - } - if (field == null) { - throw new RuntimeException("Should not happen: aspect field not found for @DeclareParents delegate"); - } else { - aspectFieldDelegate = field; - } + this.implClassName = implClassName; } - private MethodDelegateTypeMunger(ResolvedMember signature, ResolvedMember fieldDelegate, TypePattern typePattern) { - super(MethodDelegate, signature); - this.aspectFieldDelegate = fieldDelegate; - this.typePattern = typePattern; + public ResolvedMember getDelegate(ResolvedType targetType) { + return AjcMemberMaker.itdAtDeclareParentsField( + targetType, + signature.getDeclaringType(), + aspect + ); } - public ResolvedMember getDelegate() { - return aspectFieldDelegate; + public String getImplClassName() { + return implClassName; } public void write(DataOutputStream s) throws IOException { kind.write(s); signature.write(s); - aspectFieldDelegate.write(s); + aspect.write(s); + s.writeUTF(implClassName); typePattern.write(s); } - - public static ResolvedTypeMunger readMethod(VersionedDataInputStream s, ISourceContext context) throws IOException { ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context); - ResolvedMemberImpl field = ResolvedMemberImpl.readResolvedMember(s, context); + UnresolvedType aspect = UnresolvedType.read(s); + String implClassName = s.readUTF(); TypePattern tp = TypePattern.read(s, context); - return new MethodDelegateTypeMunger(signature, field, tp); + return new MethodDelegateTypeMunger(signature, aspect, implClassName, tp); } /** @@ -115,4 +107,62 @@ public class MethodDelegateTypeMunger extends ResolvedTypeMunger { public boolean changesPublicSignature() { return true; } + + public static class FieldHostTypeMunger extends ResolvedTypeMunger { + + private UnresolvedType aspect; + + /** + * Type pattern this munger applies to + */ + private final TypePattern typePattern; + + /** + * Construct a new type munger for @AspectJ ITD + * + * @param field + * @param aspect + * @param typePattern + */ + public FieldHostTypeMunger(ResolvedMember field, UnresolvedType aspect, TypePattern typePattern) { + super(FieldHost, field); + this.aspect = aspect; + this.typePattern = typePattern; + } + + public void write(DataOutputStream s) throws IOException { + kind.write(s); + signature.write(s); + aspect.write(s); + typePattern.write(s); + } + + public static ResolvedTypeMunger readFieldHost(VersionedDataInputStream s, ISourceContext context) throws IOException { + ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context); + UnresolvedType aspect = UnresolvedType.read(s); + TypePattern tp = TypePattern.read(s, context); + return new FieldHostTypeMunger(signature, aspect, tp); + } + + /** + * Match based on given type pattern, only classes can be matched + * + * @param matchType + * @param aspectType + * @return true if match + */ + public boolean matches(ResolvedType matchType, ResolvedType aspectType) { + // match only on class + if (matchType.isEnum() || matchType.isInterface() || matchType.isAnnotation()) { + return false; + } + + return typePattern.matchesStatically(matchType); + } + + public boolean changesPublicSignature() { + return false; + } + + } } diff --git a/weaver/src/org/aspectj/weaver/NameMangler.java b/weaver/src/org/aspectj/weaver/NameMangler.java index 17a29a528..4dfd751b9 100644 --- a/weaver/src/org/aspectj/weaver/NameMangler.java +++ b/weaver/src/org/aspectj/weaver/NameMangler.java @@ -64,16 +64,17 @@ public class NameMangler { // PTWIMPL method names that must include aspect type public static String perTypeWithinFieldForTarget(UnresolvedType aspectType) { - String s = makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance"); - return s; + return makeName(aspectType.getNameAsIdentifier(), "ptwAspectInstance"); } - - public static String perTypeWithinLocalAspectOf(UnresolvedType aspectType) { + + public static String perTypeWithinLocalAspectOf(UnresolvedType aspectType) { return makeName(aspectType.getNameAsIdentifier(), "localAspectOf"); } - - + public static String itdAtDeclareParentsField(UnresolvedType aspectType, UnresolvedType itdType) { + return makeName(aspectType.getNameAsIdentifier(), itdType.getNameAsIdentifier()); + } + public static String privilegedAccessMethodForMethod(String name, UnresolvedType objectType, UnresolvedType aspectType) { return makeName("privMethod", aspectType.getNameAsIdentifier(), objectType.getNameAsIdentifier(), name); diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java index 0e95d39c5..5891b9bc8 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java @@ -135,6 +135,8 @@ public abstract class ResolvedTypeMunger { return NewConstructorTypeMunger.readConstructor(s, context); } else if (kind == MethodDelegate) { return MethodDelegateTypeMunger.readMethod(s, context); + } else if (kind == FieldHost) { + return MethodDelegateTypeMunger.FieldHostTypeMunger.readFieldHost(s, context); } else { throw new RuntimeException("unimplemented"); } @@ -237,12 +239,14 @@ public abstract class ResolvedTypeMunger { case 2: return Method; case 5: return Constructor; case 9: return MethodDelegate; + case 10: return FieldHost; } throw new BCException("bad kind: " + key); } public String toString() { // we want MethodDelegate to appear as Method in WeaveInfo messages + //TODO we may want something for fieldhost ? if (MethodDelegate.getName().equals(getName())) { return Method.toString(); } else { @@ -267,6 +271,7 @@ public abstract class ResolvedTypeMunger { public static final Kind AnnotationOnType = new Kind("AnnotationOnType",8); // not serialized public static final Kind MethodDelegate = new Kind("MethodDelegate", 9);// serialized, @AJ ITDs + public static final Kind FieldHost = new Kind("FieldHost", 10);// serialized, @AJ ITDs public static final String SUPER_DISPATCH_NAME = "superDispatch"; diff --git a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java index e07f44c42..9297f1d16 100644 --- a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java +++ b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java @@ -17,6 +17,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.lang.reflect.Modifier; import org.aspectj.apache.bcel.Constants; import org.aspectj.apache.bcel.classfile.Attribute; @@ -31,6 +32,7 @@ import org.aspectj.apache.bcel.classfile.annotation.Annotation; import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair; import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnotations; import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations; +import org.aspectj.apache.bcel.classfile.annotation.ClassElementValue; import org.aspectj.apache.bcel.generic.Type; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHandler; @@ -50,6 +52,9 @@ import org.aspectj.weaver.ResolvedPointcutDefinition; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeaverMessages; +import org.aspectj.weaver.NewFieldTypeMunger; +import org.aspectj.weaver.ResolvedMemberImpl; +import org.aspectj.weaver.Member; import org.aspectj.weaver.patterns.AndPointcut; import org.aspectj.weaver.patterns.DeclareErrorOrWarning; import org.aspectj.weaver.patterns.DeclareParents; @@ -317,7 +322,6 @@ public class AtAjAttributes { if (acceptAttribute(fattribute)) { RuntimeAnnotations frvs = (RuntimeAnnotations) fattribute; if (handleDeclareErrorOrWarningAnnotation(frvs, fstruct) - || handleDeclareImplementsAnnotation(frvs, fstruct) || handleDeclareParentsAnnotation(frvs, fstruct)) { // semantic check - must be in an @Aspect [remove if previous block bypassed in advance] if (!type.isAnnotationStyleAspect()) { @@ -338,7 +342,7 @@ public class AtAjAttributes { } struct.ajAttributes.addAll(fstruct.ajAttributes); } - + return struct.ajAttributes; } @@ -463,8 +467,8 @@ public class AtAjAttributes { // Note: field annotation are for ITD and DEOW - processed at class level directly return Collections.EMPTY_LIST; } - - + + /** * Read @Aspect * @@ -518,12 +522,12 @@ public class AtAjAttributes { struct.context, bindings ); - + // // we can't resolve here since the perclause typically refers to pointcuts // // defined in the aspect that we haven't told the BcelObjectType about yet. -// +// // perClause.resolve(binding); - + // so we prepare to do it later... aspectAttribute.setResolutionScope(binding); return true; @@ -607,47 +611,47 @@ public class AtAjAttributes { return false; } - /** - * Read @DeclareImplements - * - * @param runtimeAnnotations - * @param struct - * @return true if found - */ - private static boolean handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) {//, ResolvedPointcutDefinition preResolvedPointcut) { - Annotation deci = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION); - if (deci != null) { - ElementNameValuePair deciPatternNVP = getAnnotationElement(deci, VALUE); - String deciPattern = deciPatternNVP.getValue().stringifyValue(); - if (deciPattern != null) { - TypePattern typePattern = parseTypePattern(deciPattern, struct); - ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld()); - if (fieldType.isPrimitiveType()) { - return false; - } else if (fieldType.isInterface()) { - TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false); - parent.resolve(struct.enclosingType.getWorld()); - List parents = new ArrayList(1); - parents.add(parent); - //TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ?? - struct.ajAttributes.add( - new AjAttribute.DeclareAttribute( - new DeclareParents( - typePattern, - parents, - false - ) - ) - ); - return true; - } else { - reportError("@DeclareImplements: can only be used on field whose type is an interface", struct); - return false; - } - } - } - return false; - } +// /** +// * Read @DeclareImplements +// * +// * @param runtimeAnnotations +// * @param struct +// * @return true if found +// */ +// private static boolean handleDeclareImplementsAnnotation(RuntimeAnnotations runtimeAnnotations, AjAttributeFieldStruct struct) {//, ResolvedPointcutDefinition preResolvedPointcut) { +// Annotation deci = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREIMPLEMENTS_ANNOTATION); +// if (deci != null) { +// ElementNameValuePair deciPatternNVP = getAnnotationElement(deci, VALUE); +// String deciPattern = deciPatternNVP.getValue().stringifyValue(); +// if (deciPattern != null) { +// TypePattern typePattern = parseTypePattern(deciPattern, struct); +// ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld()); +// if (fieldType.isPrimitiveType()) { +// return false; +// } else if (fieldType.isInterface()) { +// TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false); +// parent.resolve(struct.enclosingType.getWorld()); +// List parents = new ArrayList(1); +// parents.add(parent); +// //TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ?? +// struct.ajAttributes.add( +// new AjAttribute.DeclareAttribute( +// new DeclareParents( +// typePattern, +// parents, +// false +// ) +// ) +// ); +// return true; +// } else { +// reportError("@DeclareImplements: can only be used on field whose type is an interface", struct); +// return false; +// } +// } +// } +// return false; +// } /** * Read @DeclareParents @@ -664,9 +668,7 @@ public class AtAjAttributes { if (decpPattern != null) { TypePattern typePattern = parseTypePattern(decpPattern, struct); ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve(struct.enclosingType.getWorld()); - if (fieldType.isPrimitiveType()) { - return false; - } else if (fieldType.isInterface() && (struct.field.isPublic() && struct.field.isStatic())) { + if (fieldType.isInterface()) { TypePattern parent = new ExactTypePattern(UnresolvedType.forSignature(struct.field.getSignature()), false, false); parent.resolve(struct.enclosingType.getWorld()); //TODO kick ISourceLocation sl = struct.bField.getSourceLocation(); ?? @@ -681,25 +683,66 @@ public class AtAjAttributes { ) ) ); + + + // do we have a defaultImpl=xxx.class (ie implementation) + String defaultImplClassName = null; + ElementNameValuePair defaultImplNVP = getAnnotationElement(decp, "defaultImpl"); + if (defaultImplNVP != null) { + ClassElementValue defaultImpl = (ClassElementValue) defaultImplNVP.getValue(); + defaultImplClassName = UnresolvedType.forSignature(defaultImpl.getClassString()).getName(); + if (defaultImplClassName.equals("org.aspectj.lang.annotation.DeclareParents")) { + defaultImplClassName = null; + } + //TODO check public no arg ctor + } + // then iterate on field interface hierarchy (not object) - for (Iterator it = fieldType.getMethods(); it.hasNext();) { - ResolvedMember method = (ResolvedMember)it.next(); + boolean hasAtLeastOneMethod = false; + ResolvedMember[] methods = (ResolvedMember[])fieldType.getMethodsWithoutIterator(true, false).toArray(new ResolvedMember[0]); + for (int i = 0; i < methods.length; i++) { + ResolvedMember method = (ResolvedMember)methods[i]; if (method.isAbstract()) { + if (defaultImplClassName == null) { + // non marker interface with no default impl provided + reportError("@DeclareParents: used with a non marker interface and no defaultImpl=\"...\" provided", struct); + return false; + } + hasAtLeastOneMethod = true; + struct.ajAttributes.add( new AjAttribute.TypeMunger( new MethodDelegateTypeMunger( method, struct.enclosingType, - struct.field.getName(), + defaultImplClassName, typePattern ) ) ); } } + // successfull so far, we thus need a bcel type munger to have + // a field hosting the mixin in the target type + if (hasAtLeastOneMethod) { + struct.ajAttributes.add( + new AjAttribute.TypeMunger( + new MethodDelegateTypeMunger.FieldHostTypeMunger( + AjcMemberMaker.itdAtDeclareParentsField( + null,//prototyped + fieldType, + struct.enclosingType + ), + struct.enclosingType, + typePattern + ) + ) + ); + } + return true; } else { - reportError("@DeclareParents: can only be used on a public static field whose type is an interface", struct); + reportError("@DeclareParents: can only be used on a field whose type is an interface", struct); return false; } } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 9bbd0d49e..46332675a 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -29,6 +29,7 @@ import org.aspectj.apache.bcel.generic.InstructionFactory; import org.aspectj.apache.bcel.generic.InstructionHandle; import org.aspectj.apache.bcel.generic.InstructionList; import org.aspectj.apache.bcel.generic.Type; +import org.aspectj.apache.bcel.generic.BranchInstruction; import org.aspectj.apache.bcel.generic.annotation.AnnotationGen; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; @@ -63,7 +64,7 @@ import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.World; import org.aspectj.weaver.patterns.DeclareAnnotation; import org.aspectj.weaver.patterns.Pointcut; - +import org.aspectj.lang.Signature; //XXX addLazyMethodGen is probably bad everywhere public class BcelTypeMunger extends ConcreteTypeMunger { @@ -87,6 +88,8 @@ public class BcelTypeMunger extends ConcreteTypeMunger { changed = mungeNewMethod(weaver, (NewMethodTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.MethodDelegate) { changed = mungeMethodDelegate(weaver, (MethodDelegateTypeMunger)munger); + } else if (munger.getKind() == ResolvedTypeMunger.FieldHost) { + changed = mungeFieldHost(weaver, (MethodDelegateTypeMunger.FieldHostTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) { changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger); worthReporting = false; @@ -147,7 +150,9 @@ public class BcelTypeMunger extends ConcreteTypeMunger { // reportDeclareParentsMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent); } - } else { + } else if (munger.getKind().equals(ResolvedTypeMunger.FieldHost)) { + ;//hidden + } else { ResolvedMember declaredSig = munger.getDeclaredSignature(); if (declaredSig==null) declaredSig= munger.getSignature(); weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ITD, @@ -1103,11 +1108,23 @@ public class BcelTypeMunger extends ConcreteTypeMunger { InstructionList body = new InstructionList(); InstructionFactory fact = gen.getFactory(); - // getstatic field from aspect - body.append(Utility.createGet(fact, munger.getDelegate())); - + // getfield + body.append(InstructionConstants.ALOAD_0); + body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType()))); + BranchInstruction ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNULL, null); + body.append(ifNonNull); + InstructionHandle ifNonNullElse = body.append(InstructionConstants.ALOAD_0); + body.append(fact.createNew(munger.getImplClassName())); + body.append(InstructionConstants.DUP); + body.append(fact.createInvoke(munger.getImplClassName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); + body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType()))); + ifNonNull.setTarget(ifNonNullElse); + body.append(InstructionConstants.ALOAD_0); + body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType()))); + + //args int pos = 0; - if (!introduced.isStatic()) { // skip 'this' + if (!introduced.isStatic()) { // skip 'this' (?? can this really happen) //body.append(InstructionFactory.createThis()); pos++; } @@ -1133,7 +1150,25 @@ public class BcelTypeMunger extends ConcreteTypeMunger { return false; } - private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor,boolean isCtorRelated) { + private boolean mungeFieldHost(BcelClassWeaver weaver, MethodDelegateTypeMunger.FieldHostTypeMunger munger) { + LazyClassGen gen = weaver.getLazyClassGen(); + if (gen.getType().isAnnotation() || gen.getType().isEnum()) { + // don't signal error as it could be a consequence of a wild type pattern + return false; + } + boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType); + ResolvedMember host = AjcMemberMaker.itdAtDeclareParentsField( + weaver.getLazyClassGen().getType(), + munger.getSignature().getType(), + aspectType); + weaver.getLazyClassGen().addField(makeFieldGen( + weaver.getLazyClassGen(), + host).getField(), null); + return true; + } + + + private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor,boolean isCtorRelated) { World world = aspectType.getWorld(); boolean debug = false; if (debug) { |