@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
@@ -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, "<init>", | |||
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, "<init>", "()V"); | |||
} | |||
@@ -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<ResolvedMember> 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); | |||
} | |||
} | |||
@@ -175,14 +175,57 @@ public class CrosscuttingMembersSet { | |||
public List<ConcreteTypeMunger> getTypeMungers() { | |||
if (typeMungers == null) { | |||
List<ConcreteTypeMunger> ret = new ArrayList<ConcreteTypeMunger>(); | |||
for (Iterator<CrosscuttingMembers> 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<ConcreteTypeMunger> getLateTypeMungers() { | |||
if (lateTypeMungers == null) { | |||
List<ConcreteTypeMunger> ret = new ArrayList<ConcreteTypeMunger>(); |
@@ -18,7 +18,7 @@ public class ExposeTypeMunger extends PrivilegedAccessMunger { | |||
public ExposeTypeMunger(UnresolvedType typeToExpose) { | |||
super(new ResolvedMemberImpl(Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID, "<clinit>", | |||
UnresolvedType.NONE)); | |||
UnresolvedType.NONE), false); | |||
} | |||
public String toString() { |
@@ -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; | |||
} | |||
@@ -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$<fieldname>' and 'ajc$set$<fieldname>' - 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 { |
@@ -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(); |
@@ -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(); | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
@@ -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(); | |||
} | |||
} |