From 2cae45bf7161568d469ad75592b73c10ca5dfede Mon Sep 17 00:00:00 2001 From: aclement Date: Fri, 22 Jan 2010 22:46:23 +0000 Subject: [PATCH] 299552: private ITD fields stay private in target (with unmangled name): all of it --- .../weaver/AbstractReferenceTypeDelegate.java | 5 + .../src/org/aspectj/weaver/AjAttribute.java | 30 ++-- .../org/aspectj/weaver/AjcMemberMaker.java | 150 +++++++++++++----- .../aspectj/weaver/CrosscuttingMembers.java | 7 +- .../weaver/CrosscuttingMembersSet.java | 47 +++++- .../org/aspectj/weaver/ExposeTypeMunger.java | 2 +- .../aspectj/weaver/NewFieldTypeMunger.java | 22 ++- .../weaver/PrivilegedAccessMunger.java | 22 ++- .../src/org/aspectj/weaver/ReferenceType.java | 5 + .../aspectj/weaver/ReferenceTypeDelegate.java | 9 ++ .../src/org/aspectj/weaver/ResolvedType.java | 58 ++++++- .../aspectj/weaver/ResolvedTypeMunger.java | 1 + .../ReflectionBasedReferenceTypeDelegate.java | 5 + 13 files changed, 296 insertions(+), 67 deletions(-) diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AbstractReferenceTypeDelegate.java b/org.aspectj.matcher/src/org/aspectj/weaver/AbstractReferenceTypeDelegate.java index 454771cc5..6315570ee 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/AbstractReferenceTypeDelegate.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/AbstractReferenceTypeDelegate.java @@ -19,6 +19,7 @@ import org.aspectj.bridge.ISourceLocation; import org.aspectj.util.GenericSignature; import org.aspectj.util.GenericSignatureParser; import org.aspectj.util.GenericSignature.ClassSignature; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDelegate { @@ -135,4 +136,8 @@ public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDele return true; } + public int getCompilerVersion() { + return WeaverVersionInfo.getCurrentWeaverMajorVersion(); + } + } \ No newline at end of file diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AjAttribute.java b/org.aspectj.matcher/src/org/aspectj/weaver/AjAttribute.java index af984174d..a86f21b5c 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/AjAttribute.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/AjAttribute.java @@ -246,14 +246,18 @@ public abstract class AjAttribute { public final static short WEAVER_VERSION_MINOR_AJ160 = 0; // These are the weaver major/minor numbers for AspectJ 1.6.1 - public final static short WEAVER_VERSION_MAJOR_AJ161 = 6; // annotation - // value - // binding + // added annotation value binding + public final static short WEAVER_VERSION_MAJOR_AJ161 = 6; public final static short WEAVER_VERSION_MINOR_AJ161 = 0; + // 1.6.9 adds new style ITDs. This is used to see what version of AJ was used to + // build the ITDs so we know id the generated get/set dispatchers are using old + // or new style (new style will be get/setters for private ITD fields) + public final static short WEAVER_VERSION_AJ169 = 1609; + // These are the weaver major/minor versions for *this* weaver - private final static short CURRENT_VERSION_MAJOR = WEAVER_VERSION_MAJOR_AJ161; - private final static short CURRENT_VERSION_MINOR = WEAVER_VERSION_MINOR_AJ161; + private final static short CURRENT_VERSION_MAJOR = WEAVER_VERSION_AJ169; + private final static short CURRENT_VERSION_MINOR = 0; public final static WeaverVersionInfo UNKNOWN = new WeaverVersionInfo(WEAVER_VERSION_MAJOR_UNKNOWN, WEAVER_VERSION_MINOR_UNKNOWN); @@ -647,12 +651,8 @@ public abstract class AjAttribute { } public static class PrivilegedAttribute extends AjAttribute { - public static final String AttributeName = "org.aspectj.weaver.Privileged"; - @Override - public String getNameString() { - return AttributeName; - } + public static final String AttributeName = "org.aspectj.weaver.Privileged"; private final ResolvedMember[] accessedMembers; @@ -669,8 +669,14 @@ public abstract class AjAttribute { return accessedMembers; } - public static PrivilegedAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException { - return new PrivilegedAttribute(ResolvedMemberImpl.readResolvedMemberArray(s, context)); + public static PrivilegedAttribute read(VersionedDataInputStream stream, ISourceContext context) throws IOException { + PrivilegedAttribute pa = new PrivilegedAttribute(ResolvedMemberImpl.readResolvedMemberArray(stream, context)); + return pa; + } + + @Override + public String getNameString() { + return AttributeName; } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java b/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java index 5144b0992..1e533918d 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/AjcMemberMaker.java @@ -16,7 +16,12 @@ import java.lang.reflect.Modifier; //import org.aspectj.weaver.ResolvedType.Name; +/** + * The AjcMemberMaker is responsible for creating the representations of methods/fields/etc that are placed in both aspects and + * affected target types. It uses the NameMangler class to create the actual names that will be used. + */ public class AjcMemberMaker { + private static final int PUBLIC_STATIC_FINAL = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; private static final int PRIVATE_STATIC = Modifier.PRIVATE | Modifier.STATIC; @@ -28,6 +33,7 @@ public class AjcMemberMaker { private static final int VISIBILITY = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; public static final UnresolvedType CFLOW_STACK_TYPE = UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE); + public static final UnresolvedType AROUND_CLOSURE_TYPE = UnresolvedType .forSignature("Lorg/aspectj/runtime/internal/AroundClosure;"); @@ -229,34 +235,77 @@ public class AjcMemberMaker { public static ResolvedMember privilegedAccessMethodForMethod(UnresolvedType aspectType, ResolvedMember method) { return new ResolvedMemberImpl(Member.METHOD, method.getDeclaringType(), Modifier.PUBLIC - | (Modifier.isStatic(method.getModifiers()) ? Modifier.STATIC : 0), method.getReturnType(), NameMangler.privilegedAccessMethodForMethod( - method.getName(), method.getDeclaringType(), aspectType), method.getParameterTypes(), method.getExceptions()); + | (Modifier.isStatic(method.getModifiers()) ? Modifier.STATIC : 0), method.getReturnType(), NameMangler + .privilegedAccessMethodForMethod(method.getName(), method.getDeclaringType(), aspectType), method + .getParameterTypes(), method.getExceptions()); } - public static ResolvedMember privilegedAccessMethodForFieldGet(UnresolvedType aspectType, Member field) { - String sig; - if (Modifier.isStatic(field.getModifiers())) { - sig = "()" + field.getReturnType().getSignature(); + /** + * Return a resolvedmember representing the synthetic getter for the field. The old style (<1.6.9) is a heavyweight static + * method with a long name. The new style (1.6.9 and later) is short, and reusable across aspects. + * + * @param aspectType the aspect attempting the access + * @param field the field to be accessed + * @param shortSyntax is the old (long) or new (short) style format being used + * @return a resolvedmember representing the synthetic getter + */ + public static ResolvedMember privilegedAccessMethodForFieldGet(UnresolvedType aspectType, Member field, boolean shortSyntax) { + UnresolvedType fieldDeclaringType = field.getDeclaringType(); + if (shortSyntax) { + UnresolvedType[] args = null; + if (Modifier.isStatic(field.getModifiers())) { + args = ResolvedType.NONE; + } else { + args = new UnresolvedType[] { fieldDeclaringType }; + } + StringBuffer name = new StringBuffer("ajc$get$"); + name.append(field.getName()); + return new ResolvedMemberImpl(Member.METHOD, fieldDeclaringType, PUBLIC_STATIC, field.getReturnType(), name.toString(), + args); } else { - sig = "(" + field.getDeclaringType().getSignature() + ")" + field.getReturnType().getSignature(); + String getterName = NameMangler.privilegedAccessMethodForFieldGet(field.getName(), fieldDeclaringType, aspectType); + String sig; + if (Modifier.isStatic(field.getModifiers())) { + sig = "()" + field.getReturnType().getSignature(); + } else { + sig = "(" + fieldDeclaringType.getSignature() + ")" + field.getReturnType().getSignature(); + } + return new ResolvedMemberImpl(Member.METHOD, fieldDeclaringType, PUBLIC_STATIC, getterName, sig); } - - return new ResolvedMemberImpl(Member.METHOD, field.getDeclaringType(), PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic() - // ? Modifier.STATIC : 0), - NameMangler.privilegedAccessMethodForFieldGet(field.getName(), field.getDeclaringType(), aspectType), sig); } - public static ResolvedMember privilegedAccessMethodForFieldSet(UnresolvedType aspectType, Member field) { - String sig; - if (Modifier.isStatic(field.getModifiers())) { - sig = "(" + field.getReturnType().getSignature() + ")V"; + /** + * Return a resolvedmember representing the synthetic setter for the field. The old style (<1.6.9) is a heavyweight static + * method with a long name. The new style (1.6.9 and later) is short, not always static, and reusable across aspects. + * + * @param aspectType the aspect attempting the access + * @param field the field to be accessed + * @param shortSyntax is the old or new style format being used + * @return a resolvedmember representing the synthetic setter + */ + public static ResolvedMember privilegedAccessMethodForFieldSet(UnresolvedType aspectType, Member field, boolean shortSyntax) { + UnresolvedType fieldDeclaringType = field.getDeclaringType(); + if (shortSyntax) { + UnresolvedType[] args = null; + if (Modifier.isStatic(field.getModifiers())) { + args = new UnresolvedType[] { field.getType() }; + } else { + args = new UnresolvedType[] { fieldDeclaringType, field.getType() }; + } + StringBuffer name = new StringBuffer("ajc$set$"); + name.append(field.getName()); + return new ResolvedMemberImpl(Member.METHOD, fieldDeclaringType, PUBLIC_STATIC, ResolvedType.VOID, name.toString(), + args); } else { - sig = "(" + field.getDeclaringType().getSignature() + field.getReturnType().getSignature() + ")V"; + String setterName = NameMangler.privilegedAccessMethodForFieldSet(field.getName(), fieldDeclaringType, aspectType); + String sig; + if (Modifier.isStatic(field.getModifiers())) { + sig = "(" + field.getReturnType().getSignature() + ")V"; + } else { + sig = "(" + fieldDeclaringType.getSignature() + field.getReturnType().getSignature() + ")V"; + } + return new ResolvedMemberImpl(Member.METHOD, fieldDeclaringType, PUBLIC_STATIC, setterName, sig); } - - return new ResolvedMemberImpl(Member.METHOD, field.getDeclaringType(), PUBLIC_STATIC, // Modifier.PUBLIC | (field.isStatic() - // ? Modifier.STATIC : 0), - NameMangler.privilegedAccessMethodForFieldSet(field.getName(), field.getDeclaringType(), aspectType), sig); } // --- inline accessors @@ -362,36 +411,39 @@ public class AjcMemberMaker { ResolvedMember ret = new ResolvedMemberImpl(Member.CONSTRUCTOR, targetType, Modifier.PUBLIC, ResolvedType.VOID, "", constructor.getParameterTypes(), constructor.getExceptions()); // System.out.println("ret: " + ret + " mods: " + Modifier.toString(modifiers)); - if (Modifier.isPublic(constructor.getModifiers())) + if (Modifier.isPublic(constructor.getModifiers())) { return ret; + } while (true) { ret = addCookieTo(ret, aspectType); - if (targetType.lookupMemberNoSupers(ret) == null) + if (targetType.lookupMemberNoSupers(ret) == null) { return ret; + } } } public static ResolvedMember interFieldInitializer(ResolvedMember field, UnresolvedType aspectType) { return new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, NameMangler.interFieldInitializer(aspectType, field - .getDeclaringType(), field.getName()), Modifier.isStatic(field.getModifiers()) ? "()V" : "(" + field.getDeclaringType().getSignature() - + ")V"); + .getDeclaringType(), field.getName()), Modifier.isStatic(field.getModifiers()) ? "()V" : "(" + + field.getDeclaringType().getSignature() + ")V"); } - /** - * Makes public and non-final - */ private static int makePublicNonFinal(int modifiers) { return (modifiers & ~VISIBILITY & ~Modifier.FINAL) | Modifier.PUBLIC; } + private static int makeNonFinal(int modifiers) { + return (modifiers & ~Modifier.FINAL); + } + /** * This static method goes on the aspect that declares the inter-type field */ public static ResolvedMember interFieldSetDispatcher(ResolvedMember field, UnresolvedType aspectType) { ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, ResolvedType.VOID, NameMangler - .interFieldSetDispatcher(aspectType, field.getDeclaringType(), field.getName()), - Modifier.isStatic(field.getModifiers()) ? new UnresolvedType[] { field.getReturnType() } : new UnresolvedType[] { - field.getDeclaringType(), field.getReturnType() }); + .interFieldSetDispatcher(aspectType, field.getDeclaringType(), field.getName()), Modifier.isStatic(field + .getModifiers()) ? new UnresolvedType[] { field.getReturnType() } : new UnresolvedType[] { + field.getDeclaringType(), field.getReturnType() }); rm.setTypeVariables(field.getTypeVariables()); return rm; } @@ -401,8 +453,8 @@ public class AjcMemberMaker { */ public static ResolvedMember interFieldGetDispatcher(ResolvedMember field, UnresolvedType aspectType) { ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, aspectType, PUBLIC_STATIC, field.getReturnType(), NameMangler - .interFieldGetDispatcher(aspectType, field.getDeclaringType(), field.getName()), - Modifier.isStatic(field.getModifiers()) ? UnresolvedType.NONE : new UnresolvedType[] { field.getDeclaringType() }, UnresolvedType.NONE); + .interFieldGetDispatcher(aspectType, field.getDeclaringType(), field.getName()), Modifier.isStatic(field + .getModifiers()) ? UnresolvedType.NONE : new UnresolvedType[] { field.getDeclaringType() }, UnresolvedType.NONE); rm.setTypeVariables(field.getTypeVariables()); return rm; } @@ -415,12 +467,18 @@ public class AjcMemberMaker { // } /** - * This field goes on the class the field is declared onto + * This field goes on the class the field is declared onto. Field names for ITDs onto interfaces are handled below. */ - public static ResolvedMember interFieldClassField(ResolvedMember field, UnresolvedType aspectType) { - return new ResolvedMemberImpl(Member.FIELD, field.getDeclaringType(), makePublicNonFinal(field.getModifiers()), field - .getReturnType(), NameMangler.interFieldClassField(field.getModifiers(), aspectType, field.getDeclaringType(), - field.getName()), UnresolvedType.NONE, UnresolvedType.NONE); + public static ResolvedMember interFieldClassField(ResolvedMember field, UnresolvedType aspectType, boolean newStyle) { + int modifiers = (newStyle ? makeNonFinal(field.getModifiers()) : makePublicNonFinal(field.getModifiers())); + String name = null; + if (newStyle) { + name = field.getName(); + } else { + name = NameMangler.interFieldClassField(field.getModifiers(), aspectType, field.getDeclaringType(), field.getName()); + } + return new ResolvedMemberImpl(Member.FIELD, field.getDeclaringType(), modifiers, field.getReturnType(), name, + UnresolvedType.NONE, UnresolvedType.NONE); } /** @@ -437,8 +495,9 @@ public class AjcMemberMaker { */ public static ResolvedMember interFieldInterfaceSetter(ResolvedMember field, ResolvedType onType, UnresolvedType aspectType) { int modifiers = Modifier.PUBLIC; - if (onType.isInterface()) + if (onType.isInterface()) { modifiers |= Modifier.ABSTRACT; + } ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, onType, modifiers, ResolvedType.VOID, NameMangler .interFieldInterfaceSetter(aspectType, field.getDeclaringType(), field.getName()), new UnresolvedType[] { field .getReturnType() }, UnresolvedType.NONE); @@ -451,8 +510,9 @@ public class AjcMemberMaker { */ public static ResolvedMember interFieldInterfaceGetter(ResolvedMember field, ResolvedType onType, UnresolvedType aspectType) { int modifiers = Modifier.PUBLIC; - if (onType.isInterface()) + if (onType.isInterface()) { modifiers |= Modifier.ABSTRACT; + } ResolvedMember rm = new ResolvedMemberImpl(Member.METHOD, onType, modifiers, field.getReturnType(), NameMangler .interFieldInterfaceGetter(aspectType, field.getDeclaringType(), field.getName()), UnresolvedType.NONE, UnresolvedType.NONE); @@ -465,12 +525,14 @@ public class AjcMemberMaker { * an interface). The implementation will call the interMethodDispatch method on the aspect. */ public static ResolvedMember interMethod(ResolvedMember meth, UnresolvedType aspectType, boolean onInterface) { - if (Modifier.isPublic(meth.getModifiers()) && !onInterface) + if (Modifier.isPublic(meth.getModifiers()) && !onInterface) { return meth; + } int modifiers = makePublicNonFinal(meth.getModifiers()); - if (onInterface) + if (onInterface) { modifiers |= Modifier.ABSTRACT; + } ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, meth.getDeclaringType(), modifiers, meth.getReturnType(), NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth @@ -489,8 +551,9 @@ public class AjcMemberMaker { // return meth; int modifiers = makePublicNonFinal(meth.getModifiers()) | BRIDGE; - if (onInterface) + if (onInterface) { modifiers |= Modifier.ABSTRACT; + } ResolvedMemberImpl rmi = new ResolvedMemberImpl(Member.METHOD, meth.getDeclaringType(), modifiers, meth.getReturnType(), NameMangler.interMethod(meth.getModifiers(), aspectType, meth.getDeclaringType(), meth.getName()), meth @@ -576,8 +639,9 @@ public class AjcMemberMaker { public static Member interfaceConstructor(ResolvedType resolvedTypeX) { // AMC next two lines should not be needed when sig for generic type is changed ResolvedType declaringType = resolvedTypeX; - if (declaringType.isRawType()) + if (declaringType.isRawType()) { declaringType = declaringType.getGenericType(); + } return new ResolvedMemberImpl(Member.CONSTRUCTOR, declaringType, Modifier.PUBLIC, "", "()V"); } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java b/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java index 3ff22daa0..14de71e79 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembers.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; import org.aspectj.weaver.patterns.Declare; import org.aspectj.weaver.patterns.DeclareAnnotation; import org.aspectj.weaver.patterns.DeclareErrorOrWarning; @@ -198,8 +199,12 @@ public class CrosscuttingMembers { } public void addPrivilegedAccesses(Collection accessedMembers) { + int version = inAspect.getCompilerVersion(); for (ResolvedMember member : accessedMembers) { - addTypeMunger(world.getWeavingSupport().concreteTypeMunger(new PrivilegedAccessMunger(member), inAspect)); + PrivilegedAccessMunger privilegedAccessMunger = new PrivilegedAccessMunger(member, + version >= WeaverVersionInfo.WEAVER_VERSION_AJ169); + ConcreteTypeMunger concreteTypeMunger = world.getWeavingSupport().concreteTypeMunger(privilegedAccessMunger, inAspect); + addTypeMunger(concreteTypeMunger); } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembersSet.java b/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembersSet.java index aef04dd98..d81ef0b2c 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembersSet.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/CrosscuttingMembersSet.java @@ -175,14 +175,57 @@ public class CrosscuttingMembersSet { public List getTypeMungers() { if (typeMungers == null) { List ret = new ArrayList(); - for (Iterator i = members.values().iterator(); i.hasNext();) { - ret.addAll(i.next().getTypeMungers()); + for (CrosscuttingMembers xmembers : members.values()) { + // With 1.6.9 there is a change that enables use of more optimal accessors (accessors for private fields). + // Here is where we determine if two aspects are asking for access to the same field. If they are + // and + // In the new style multiple aspects can share the same privileged accessors, so here we check if + // two aspects are asking for access to the same field. If they are then we don't add a duplicate + // accessor. + for (ConcreteTypeMunger mungerToAdd : xmembers.getTypeMungers()) { + ResolvedTypeMunger resolvedMungerToAdd = mungerToAdd.getMunger(); + if (isNewStylePrivilegedAccessMunger(resolvedMungerToAdd)) { + String newFieldName = resolvedMungerToAdd.getSignature().getName(); + boolean alreadyExists = false; + for (ConcreteTypeMunger existingMunger : ret) { + ResolvedTypeMunger existing = existingMunger.getMunger(); + if (isNewStylePrivilegedAccessMunger(existing)) { + String existingFieldName = existing.getSignature().getName(); + if (existingFieldName.equals(newFieldName) + && existing.getSignature().getDeclaringType().equals( + resolvedMungerToAdd.getSignature().getDeclaringType())) { + alreadyExists = true; + break; + } + } + } + if (!alreadyExists) { + ret.add(mungerToAdd); + } + } else { + ret.add(mungerToAdd); + } + } } typeMungers = ret; } return typeMungers; } + /** + * Determine if the type munger is: (1) for privileged access (2) for a normally non visible field (3) is from an aspect wanting + * 'old style' (ie. long) accessor names + */ + private boolean isNewStylePrivilegedAccessMunger(ResolvedTypeMunger typeMunger) { + boolean b = (typeMunger != null && typeMunger.getKind() == ResolvedTypeMunger.PrivilegedAccess && typeMunger.getSignature() + .getKind() == Member.FIELD); + if (!b) { + return b; + } + PrivilegedAccessMunger privAccessMunger = (PrivilegedAccessMunger) typeMunger; + return privAccessMunger.shortSyntax; + } + public List getLateTypeMungers() { if (lateTypeMungers == null) { List ret = new ArrayList(); diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ExposeTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/ExposeTypeMunger.java index 9a90c139d..2f2409744 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ExposeTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ExposeTypeMunger.java @@ -18,7 +18,7 @@ public class ExposeTypeMunger extends PrivilegedAccessMunger { public ExposeTypeMunger(UnresolvedType typeToExpose) { super(new ResolvedMemberImpl(Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID, "", - UnresolvedType.NONE)); + UnresolvedType.NONE), false); } public String toString() { diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java index ba7bad239..8427ca74b 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/NewFieldTypeMunger.java @@ -19,11 +19,24 @@ import java.util.Map; import java.util.Set; import org.aspectj.bridge.ISourceLocation; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; +/** + * Code that created version one style ITD type mungers will be using direct field access from the dispatchers + * + * @author Andy + * + */ public class NewFieldTypeMunger extends ResolvedTypeMunger { + public static final int VersionOne = 1; + public static final int VersionTwo = 2; // new style ITDs + + public int version = VersionOne; + public NewFieldTypeMunger(ResolvedMember signature, Set superMethodsCalled, List typeVariableAliases) { super(Field, signature); + this.version = VersionTwo; this.typeVariableAliases = typeVariableAliases; signature.setAnnotatedElsewhere(true); this.setSuperMethodsCalled(superMethodsCalled); @@ -39,6 +52,7 @@ public class NewFieldTypeMunger extends ResolvedTypeMunger { writeSuperMethodsCalled(s); writeSourceLocation(s); writeOutTypeAliases(s); + s.writeInt(version); } public static ResolvedTypeMunger readField(VersionedDataInputStream s, ISourceContext context) throws IOException { @@ -47,9 +61,15 @@ public class NewFieldTypeMunger extends ResolvedTypeMunger { Set superMethodsCalled = readSuperMethodsCalled(s); sloc = readSourceLocation(s); List aliases = readInTypeAliases(s); - ResolvedTypeMunger munger = new NewFieldTypeMunger(fieldSignature, superMethodsCalled, aliases); + NewFieldTypeMunger munger = new NewFieldTypeMunger(fieldSignature, superMethodsCalled, aliases); if (sloc != null) munger.setSourceLocation(sloc); + if (s.getMajorVersion() >= WeaverVersionInfo.WEAVER_VERSION_AJ169) { + // there is a version int + munger.version = s.readInt(); + } else { + munger.version = VersionOne; + } return munger; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/PrivilegedAccessMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/PrivilegedAccessMunger.java index e08798613..5083a304b 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/PrivilegedAccessMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/PrivilegedAccessMunger.java @@ -15,13 +15,26 @@ package org.aspectj.weaver; import java.io.DataOutputStream; import java.io.IOException; +/** + * A privileged access munger is for handling privileged access to a member. It determines the names of the getter/setter that will + * be used to access a private field in some type, or the special method that provides access to a private method. + * + * There are two syntax styles for field access, the older style was in use up to AspectJ 1.6.9 and involves long named getters and + * setters which include the requesting aspect and the target type. The short style syntax is use from AspectJ 1.6.9 onwards is + * simply 'ajc$get$' and 'ajc$set$' - as the requesting aspect isn't included in the name they can be shared + * across aspects. + */ public class PrivilegedAccessMunger extends ResolvedTypeMunger { - public PrivilegedAccessMunger(ResolvedMember member) { + + public boolean shortSyntax = false; + + public PrivilegedAccessMunger(ResolvedMember member, boolean shortSyntax) { super(PrivilegedAccess, member); + this.shortSyntax = shortSyntax; } public void write(DataOutputStream s) throws IOException { - throw new RuntimeException("shouldn't be serialized"); + throw new RuntimeException("should not be serialized"); } public ResolvedMember getMember() { @@ -30,11 +43,12 @@ public class PrivilegedAccessMunger extends ResolvedTypeMunger { public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedType aspectType) { ResolvedMember ret; + // assert if shortSyntax then aspectType.getCompilerVersion()>=169 if (getSignature().getKind() == Member.FIELD) { - ret = AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, getSignature()); + ret = AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, getSignature(), shortSyntax); if (ResolvedType.matches(ret, member)) return getSignature(); - ret = AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, getSignature()); + ret = AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, getSignature(), shortSyntax); if (ResolvedType.matches(ret, member)) return getSignature(); } else { diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java index 7990566f2..065c11b6f 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java @@ -135,6 +135,11 @@ public class ReferenceType extends ResolvedType { return delegate.isClass(); } + @Override + public int getCompilerVersion() { + return delegate.getCompilerVersion(); + } + @Override public boolean isGenericType() { return !isParameterizedType() && !isRawType() && delegate.isGeneric(); diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceTypeDelegate.java b/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceTypeDelegate.java index d16e0b364..1e5c09255 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceTypeDelegate.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceTypeDelegate.java @@ -14,6 +14,7 @@ package org.aspectj.weaver; import java.util.Collection; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; import org.aspectj.weaver.patterns.Declare; import org.aspectj.weaver.patterns.PerClause; @@ -122,4 +123,12 @@ public interface ReferenceTypeDelegate { */ public boolean isCacheable(); + /** + * If known, return the compiler/weaver version used to build this delegate. Default is the most recent level as specified in + * {@link WeaverVersionInfo}. + * + * @return the major version + */ + public int getCompilerVersion(); + } \ No newline at end of file diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java index 4672f7bd7..0b7f27c08 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedType.java @@ -32,6 +32,7 @@ import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; import org.aspectj.bridge.MessageUtil; import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; import org.aspectj.weaver.Iterators.Getter; import org.aspectj.weaver.patterns.Declare; import org.aspectj.weaver.patterns.PerClause; @@ -1672,7 +1673,12 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl return munger; } - public void addInterTypeMunger(ConcreteTypeMunger munger) { + /** + * Add an intertype munger to this type. isDuringCompilation tells us if we should be checking for an error scenario where two + * ITD fields are trying to use the same name. When this happens during compilation one of them is altered to get mangled name + * but when it happens during weaving it is too late and we need to put out an error asking them to recompile. + */ + public void addInterTypeMunger(ConcreteTypeMunger munger, boolean isDuringCompilation) { ResolvedMember sig = munger.getSignature(); bits = (bits & ~MungersAnalyzed); // clear the bit - as the mungers have changed if (sig == null || munger.getMunger() == null || munger.getMunger().getKind() == ResolvedTypeMunger.PrivilegedAccess) { @@ -1706,6 +1712,44 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl if (clashesWithExistingMember(munger, Arrays.asList(getDeclaredFields()).iterator())) { return; } + // Cannot cope with two version '2' style mungers for the same field on the same type + // Must error and request the user recompile at least one aspect with the + // -Xset:itdStyle=1 option + if (!isDuringCompilation) { + ResolvedTypeMunger thisRealMunger = munger.getMunger(); + if (thisRealMunger instanceof NewFieldTypeMunger) { + NewFieldTypeMunger newFieldTypeMunger = (NewFieldTypeMunger) thisRealMunger; + if (newFieldTypeMunger.version == NewFieldTypeMunger.VersionTwo) { + String thisRealMungerSignatureName = newFieldTypeMunger.getSignature().getName(); + for (ConcreteTypeMunger typeMunger : interTypeMungers) { + if (typeMunger.getMunger() instanceof NewFieldTypeMunger) { + if (typeMunger.getSignature().getKind() == Member.FIELD) { + NewFieldTypeMunger existing = (NewFieldTypeMunger) typeMunger.getMunger(); + if (existing.getSignature().getName().equals(thisRealMungerSignatureName) + && existing.version == NewFieldTypeMunger.VersionTwo + // this check ensures no problem for a clash with an ITD on an interface + && existing.getSignature().getDeclaringType().equals( + newFieldTypeMunger.getSignature().getDeclaringType())) { + + // report error on the aspect + StringBuffer sb = new StringBuffer(); + sb + .append("Cannot handle two aspects both attempting to use new style ITDs for the same named field "); + sb + .append("on the same target type. Please recompile at least one aspect with '-Xset:itdVersion=1'."); + sb.append(" Aspects involved: " + munger.getAspectType().getName() + " and " + + typeMunger.getAspectType().getName() + "."); + sb.append(" Field is named '" + existing.getSignature().getName() + "'"); + getWorld().getMessageHandler().handleMessage( + new Message(sb.toString(), getSourceLocation(), true)); + return; + } + } + } + } + } + } + } } else { if (clashesWithExistingMember(munger, Arrays.asList(getDeclaredMethods()).iterator())) { return; @@ -2181,8 +2225,8 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl public ResolvedType next() { ResolvedType next = delegate.next(); // BUG should check for generics and erase? -// if (!visited.contains(next)) { -// visited.add(next); + // if (!visited.contains(next)) { + // visited.add(next); if (visited.add(next)) { toPersue.add(next); // pushes on interfaces already visited? } @@ -2690,4 +2734,12 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl return (bits & TypeHierarchyCompleteBit) != 0; } + /** + * return the weaver version used to build this type - defaults to the most recent version unless discovered otherwise. + * + * @return the (major) version, {@link WeaverVersionInfo} + */ + public int getCompilerVersion() { + return WeaverVersionInfo.getCurrentWeaverMajorVersion(); + } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java index 20a5bbe29..1c2cd4ca2 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ResolvedTypeMunger.java @@ -36,6 +36,7 @@ import org.aspectj.util.TypeSafeEnum; * is the thing that is used on the eclipse side and serialized into a ConcreteTypeMunger. */ public abstract class ResolvedTypeMunger { + protected Kind kind; protected ResolvedMember signature; diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java index 16bf0c59b..cb2a497a8 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java @@ -33,6 +33,7 @@ import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeakClassLoaderReference; import org.aspectj.weaver.WeaverStateInfo; import org.aspectj.weaver.World; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; import org.aspectj.weaver.patterns.PerClause; /** @@ -404,4 +405,8 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega public boolean copySourceContext() { return true; } + + public int getCompilerVersion() { + return WeaverVersionInfo.getCurrentWeaverMajorVersion(); + } } -- 2.39.5