@@ -21,27 +21,29 @@ import org.aspectj.apache.bcel.classfile.Signature.ClassSignature; | |||
import org.aspectj.bridge.ISourceLocation; | |||
public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDelegate { | |||
public final static String UNKNOWN_SOURCE_FILE = "<Unknown>"; // Just randomly picked, happens to match BCEL javaclass default | |||
private String sourcefilename = UNKNOWN_SOURCE_FILE; // Sourcefilename is stored only here | |||
private String sourcefilename = UNKNOWN_SOURCE_FILE; | |||
private ISourceContext sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT; | |||
protected boolean exposedToWeaver; | |||
protected ReferenceType resolvedTypeX; | |||
private ISourceContext sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT; | |||
protected ClassSignature cachedGenericClassTypeSignature; | |||
public AbstractReferenceTypeDelegate(ReferenceType resolvedTypeX, boolean exposedToWeaver) { | |||
this.resolvedTypeX = resolvedTypeX; | |||
this.exposedToWeaver = exposedToWeaver; | |||
} | |||
// Happens to match Bcel javaClass default of '<Unknown>' | |||
public final static String UNKNOWN_SOURCE_FILE = "<Unknown>"; | |||
public AbstractReferenceTypeDelegate(ReferenceType resolvedTypeX, boolean exposedToWeaver) { | |||
this.resolvedTypeX = resolvedTypeX; | |||
this.exposedToWeaver = exposedToWeaver; | |||
} | |||
public final boolean isClass() { | |||
return !isAspect() && !isInterface(); | |||
} | |||
return !isAspect() && !isInterface(); | |||
} | |||
/** | |||
* Designed to be overriden by EclipseType to disable collection of shadow mungers | |||
* during pre-weave compilation phase | |||
* Designed to be overriden by EclipseType to disable collection of shadow | |||
* mungers during pre-weave compilation phase | |||
*/ | |||
public boolean doesNotExposeShadowMungers() { | |||
return false; | |||
@@ -54,54 +56,52 @@ public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDele | |||
public ReferenceType getResolvedTypeX() { | |||
return resolvedTypeX; | |||
} | |||
public final String getSourcefilename() { | |||
return sourcefilename; | |||
} | |||
public final void setSourcefilename(String sourceFileName) { | |||
this.sourcefilename = sourceFileName; | |||
if (sourceFileName!=null && sourceFileName.equals(AbstractReferenceTypeDelegate.UNKNOWN_SOURCE_FILE)) { | |||
this.sourcefilename = "Type '"+ getResolvedTypeX().getName()+"' (no debug info available)"; | |||
public final String getSourcefilename() { | |||
return sourcefilename; | |||
} | |||
public final void setSourcefilename(String sourceFileName) { | |||
sourcefilename = sourceFileName; | |||
if (sourceFileName != null && sourceFileName.equals(AbstractReferenceTypeDelegate.UNKNOWN_SOURCE_FILE)) { | |||
sourcefilename = "Type '" + getResolvedTypeX().getName() + "' (no debug info available)"; | |||
} else { | |||
String pname = getResolvedTypeX().getPackageName(); | |||
if (pname != null) { | |||
this.sourcefilename = pname.replace('.', '/') + '/' + sourceFileName; | |||
sourcefilename = pname.replace('.', '/') + '/' + sourceFileName; | |||
} | |||
} | |||
if (this.sourcefilename!=null && sourceContext instanceof SourceContextImpl) { | |||
((SourceContextImpl)sourceContext).setSourceFileName(this.sourcefilename); | |||
if (sourcefilename != null && sourceContext instanceof SourceContextImpl) { | |||
((SourceContextImpl) sourceContext).setSourceFileName(sourcefilename); | |||
} | |||
} | |||
} | |||
public ISourceLocation getSourceLocation() { | |||
return getSourceContext().makeSourceLocation(0, 0); | |||
return getSourceContext().makeSourceLocation(0, 0); | |||
} | |||
public ISourceContext getSourceContext() { | |||
return sourceContext; | |||
} | |||
public void setSourceContext(ISourceContext isc) { | |||
this.sourceContext = isc; | |||
sourceContext = isc; | |||
} | |||
public Signature.ClassSignature getGenericClassTypeSignature() { | |||
if (cachedGenericClassTypeSignature==null) { | |||
if (cachedGenericClassTypeSignature == null) { | |||
String sig = getDeclaredGenericSignature(); | |||
if (sig!=null) { | |||
if (sig != null) { | |||
GenericSignatureParser parser = new GenericSignatureParser(); | |||
cachedGenericClassTypeSignature = parser.parseAsClassSignature(sig); | |||
} | |||
} | |||
return cachedGenericClassTypeSignature; | |||
} | |||
protected Signature.FormalTypeParameter[] getFormalTypeParametersFromOuterClass() { | |||
List typeParameters = new ArrayList(); | |||
ReferenceType outer = (ReferenceType)getOuterClass(); | |||
ReferenceType outer = (ReferenceType) getOuterClass(); | |||
ReferenceTypeDelegate outerDelegate = outer.getDelegate(); | |||
AbstractReferenceTypeDelegate outerObjectType = (AbstractReferenceTypeDelegate) outerDelegate; | |||
if (outerObjectType.isNested()) { | |||
@@ -112,15 +112,14 @@ public abstract class AbstractReferenceTypeDelegate implements ReferenceTypeDele | |||
} | |||
Signature.ClassSignature outerSig = outerObjectType.getGenericClassTypeSignature(); | |||
if (outerSig != null) { | |||
for (int i = 0; i < outerSig.formalTypeParameters .length; i++) { | |||
for (int i = 0; i < outerSig.formalTypeParameters.length; i++) { | |||
typeParameters.add(outerSig.formalTypeParameters[i]); | |||
} | |||
} | |||
} | |||
Signature.FormalTypeParameter[] ret = new Signature.FormalTypeParameter[typeParameters.size()]; | |||
typeParameters.toArray(ret); | |||
return ret; | |||
} | |||
} |
@@ -25,7 +25,8 @@ import org.aspectj.weaver.patterns.TypePattern; | |||
public abstract class Advice extends ShadowMunger { | |||
protected AjAttribute.AdviceAttribute attribute; // the pointcut field is ignored | |||
protected AjAttribute.AdviceAttribute attribute; // the pointcut field is | |||
// ignored | |||
protected AdviceKind kind; // alias of attribute.getKind() | |||
protected Member signature; | |||
@@ -34,15 +35,20 @@ public abstract class Advice extends ShadowMunger { | |||
// not necessarily declaring aspect, this is a semantics change from 1.0 | |||
protected ResolvedType concreteAspect; // null until after concretize | |||
protected List innerCflowEntries = Collections.EMPTY_LIST; // just for cflow*Entry kinds | |||
protected List innerCflowEntries = Collections.EMPTY_LIST; // just for | |||
// cflow*Entry | |||
// kinds | |||
protected int nFreeVars; // just for cflow*Entry kinds | |||
protected TypePattern exceptionType; // just for Softener kind | |||
// if we are parameterized, these type may be different to the advice signature types | |||
// if we are parameterized, these type may be different to the advice | |||
// signature types | |||
protected UnresolvedType[] bindingParameterTypes; | |||
protected List/* Lint.Kind */suppressedLintKinds = null; // based on annotations on this advice | |||
protected List/* Lint.Kind */suppressedLintKinds = null; // based on | |||
// annotations on | |||
// this advice | |||
ISourceLocation lastReportedMonitorExitJoinpointLocation = null; | |||
@@ -73,7 +79,8 @@ public abstract class Advice extends ShadowMunger { | |||
return ret; | |||
} | |||
// PTWIMPL per type within entry advice is what initializes the aspect instance in the matched type | |||
// PTWIMPL per type within entry advice is what initializes the aspect | |||
// instance in the matched type | |||
public static Advice makePerTypeWithinEntry(World world, Pointcut p, ResolvedType inAspect) { | |||
Advice ret = world.createAdviceMunger(AdviceKind.PerTypeWithinEntry, p, null, 0, p); | |||
ret.concreteAspect = inAspect; | |||
@@ -93,12 +100,12 @@ public abstract class Advice extends ShadowMunger { | |||
public Advice(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature) { | |||
super(pointcut, attribute.getStart(), attribute.getEnd(), attribute.getSourceContext()); | |||
this.attribute = attribute; | |||
this.kind = attribute.getKind(); // alias | |||
kind = attribute.getKind(); // alias | |||
this.signature = signature; | |||
if (signature != null) { | |||
this.bindingParameterTypes = signature.getParameterTypes(); | |||
bindingParameterTypes = signature.getParameterTypes(); | |||
} else { | |||
this.bindingParameterTypes = new UnresolvedType[0]; | |||
bindingParameterTypes = new UnresolvedType[0]; | |||
} | |||
} | |||
@@ -163,7 +170,8 @@ public abstract class Advice extends ShadowMunger { | |||
.getEnclosingType().getName()), getSourceLocation(), shadow.getSourceLocation()); | |||
return false; | |||
} else { | |||
// System.err.println(getSignature().getReturnType() + " from " + shadow.getReturnType()); | |||
// System.err.println(getSignature().getReturnType() + | |||
// " from " + shadow.getReturnType()); | |||
if (getSignature().getReturnType() == ResolvedType.VOID) { | |||
if (shadow.getReturnType() != ResolvedType.VOID) { | |||
world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.NON_VOID_RETURN, shadow), | |||
@@ -176,7 +184,12 @@ public abstract class Advice extends ShadowMunger { | |||
ResolvedType shadowReturnType = shadow.getReturnType().resolve(world); | |||
ResolvedType adviceReturnType = getSignature().getGenericReturnType().resolve(world); | |||
if (shadowReturnType.isParameterizedType() && adviceReturnType.isRawType()) { // Set<Integer> and Set | |||
if (shadowReturnType.isParameterizedType() && adviceReturnType.isRawType()) { // Set | |||
// < | |||
// Integer | |||
// > | |||
// and | |||
// Set | |||
ResolvedType shadowReturnGenericType = shadowReturnType.getGenericType(); // Set | |||
ResolvedType adviceReturnGenericType = adviceReturnType.getGenericType(); // Set | |||
if (shadowReturnGenericType.isAssignableFrom(adviceReturnGenericType) | |||
@@ -186,7 +199,8 @@ public abstract class Advice extends ShadowMunger { | |||
new ISourceLocation[] { getSourceLocation() }); | |||
} | |||
} else if (!shadowReturnType.isAssignableFrom(adviceReturnType)) { | |||
// System.err.println(this + ", " + sourceContext + ", " + start); | |||
// System.err.println(this + ", " + sourceContext + | |||
// ", " + start); | |||
world.showMessage(IMessage.ERROR, WeaverMessages | |||
.format(WeaverMessages.INCOMPATIBLE_RETURN_TYPE, shadow), getSourceLocation(), shadow | |||
.getSourceLocation()); | |||
@@ -202,10 +216,11 @@ public abstract class Advice extends ShadowMunger { | |||
} | |||
/** | |||
* In after returning advice if we are binding the extra parameter to a parameterized type we may not be able to do a type-safe | |||
* conversion. | |||
* In after returning advice if we are binding the extra parameter to a | |||
* parameterized type we may not be able to do a type-safe conversion. | |||
* | |||
* @param resolvedExtraParameterType the type in the after returning declaration | |||
* @param resolvedExtraParameterType the type in the after returning | |||
* declaration | |||
* @param shadowReturnType the type at the shadow | |||
* @param world | |||
*/ | |||
@@ -248,11 +263,11 @@ public abstract class Advice extends ShadowMunger { | |||
} | |||
public UnresolvedType[] getBindingParameterTypes() { | |||
return this.bindingParameterTypes; | |||
return bindingParameterTypes; | |||
} | |||
public void setBindingParameterTypes(UnresolvedType[] types) { | |||
this.bindingParameterTypes = types; | |||
bindingParameterTypes = types; | |||
} | |||
public static int countOnes(int bits) { | |||
@@ -344,11 +359,12 @@ public abstract class Advice extends ShadowMunger { | |||
p.m_ignoreUnboundBindingForNames = oldP.m_ignoreUnboundBindingForNames; | |||
} | |||
Advice munger = world.createAdviceMunger(attribute, p, signature); | |||
Advice munger = world.getWeavingSupport().createAdviceMunger(attribute, p, signature); | |||
munger.concreteAspect = fromType; | |||
munger.bindingParameterTypes = this.bindingParameterTypes; | |||
munger.bindingParameterTypes = bindingParameterTypes; | |||
munger.setDeclaringType(getDeclaringType()); | |||
// System.err.println("concretizing here " + p + " with clause " + clause); | |||
// System.err.println("concretizing here " + p + " with clause " + | |||
// clause); | |||
return munger; | |||
} | |||
@@ -379,7 +395,8 @@ public abstract class Advice extends ShadowMunger { | |||
&& ((o.signature == null) ? (signature == null) : o.signature.equals(signature)) | |||
&& (AsmManager.getDefault().getHandleProvider().dependsOnLocation() ? ((o.getSourceLocation() == null) ? (getSourceLocation() == null) | |||
: o.getSourceLocation().equals(getSourceLocation())) | |||
: true) // pr134471 - remove when handles are improved to be independent of location | |||
: true) // pr134471 - remove when handles are improved | |||
// to be independent of location | |||
; | |||
} |
@@ -10,7 +10,6 @@ | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.ByteArrayInputStream; | |||
@@ -28,16 +27,18 @@ import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
/** | |||
* These attributes are written to and read from .class files (see the JVM spec). | |||
* These attributes are written to and read from .class files (see the JVM | |||
* spec). | |||
* | |||
* <p>Each member or type can have a number of AjAttributes. Each | |||
* such attribute is in 1-1 correspondence with an Unknown bcel attribute. | |||
* Creating one of these does NOTHING to the underlying thing, so if you really | |||
* want to add an attribute to a particular thing, well, you'd better actually do that. | |||
* <p> | |||
* Each member or type can have a number of AjAttributes. Each such attribute is | |||
* in 1-1 correspondence with an Unknown bcel attribute. Creating one of these | |||
* does NOTHING to the underlying thing, so if you really want to add an | |||
* attribute to a particular thing, well, you'd better actually do that. | |||
* | |||
* @author Erik Hilsdale | |||
* @author Jim Hugunin | |||
*/ | |||
*/ | |||
public abstract class AjAttribute { | |||
public static final String AttributePrefix = "org.aspectj.weaver"; | |||
@@ -45,10 +46,11 @@ public abstract class AjAttribute { | |||
protected abstract void write(DataOutputStream s) throws IOException; | |||
public abstract String getNameString(); | |||
public char[] getNameChars() { | |||
return getNameString().toCharArray(); | |||
} | |||
/** | |||
* Just writes the contents | |||
*/ | |||
@@ -57,12 +59,12 @@ public abstract class AjAttribute { | |||
ByteArrayOutputStream b0 = new ByteArrayOutputStream(); | |||
DataOutputStream s0 = new DataOutputStream(b0); | |||
write(s0); | |||
return b0.toByteArray(); | |||
return b0.toByteArray(); | |||
} catch (IOException e) { | |||
// shouldn't happen with ByteArrayOutputStreams | |||
throw new RuntimeException("sanity check"); | |||
} | |||
} | |||
} | |||
/** | |||
* Writes the full attribute, i.e. name_index, length, and contents | |||
@@ -70,40 +72,41 @@ public abstract class AjAttribute { | |||
public byte[] getAllBytes(short nameIndex) { | |||
try { | |||
byte[] bytes = getBytes(); | |||
ByteArrayOutputStream b0 = new ByteArrayOutputStream(); | |||
DataOutputStream s0 = new DataOutputStream(b0); | |||
s0.writeShort(nameIndex); | |||
s0.writeInt(bytes.length); | |||
s0.write(bytes); | |||
return b0.toByteArray(); | |||
return b0.toByteArray(); | |||
} catch (IOException e) { | |||
// shouldn't happen with ByteArrayOutputStreams | |||
throw new RuntimeException("sanity check"); | |||
} | |||
} | |||
public static AjAttribute read(AjAttribute.WeaverVersionInfo v, String name, byte[] bytes, ISourceContext context,World w) { | |||
public static AjAttribute read(AjAttribute.WeaverVersionInfo v, String name, byte[] bytes, ISourceContext context, World w) { | |||
try { | |||
if (bytes == null) bytes = new byte[0]; | |||
if (bytes == null) | |||
bytes = new byte[0]; | |||
VersionedDataInputStream s = new VersionedDataInputStream(new ByteArrayInputStream(bytes)); | |||
s.setVersion(v); | |||
if (name.equals(Aspect.AttributeName)) { | |||
return new Aspect(PerClause.readPerClause(s, context)); | |||
} else if (name.equals(MethodDeclarationLineNumberAttribute.AttributeName)) { | |||
return MethodDeclarationLineNumberAttribute.read(s); | |||
return MethodDeclarationLineNumberAttribute.read(s); | |||
} else if (name.equals(WeaverState.AttributeName)) { | |||
return new WeaverState(WeaverStateInfo.read(s, context)); | |||
} else if (name.equals(WeaverVersionInfo.AttributeName)) { | |||
return WeaverVersionInfo.read(s); | |||
} else if (name.equals(AdviceAttribute.AttributeName)) { | |||
AdviceAttribute aa = AdviceAttribute.read(s, context); | |||
aa.getPointcut().check(context,w); | |||
aa.getPointcut().check(context, w); | |||
return aa; | |||
} else if (name.equals(PointcutDeclarationAttribute.AttributeName)) { | |||
PointcutDeclarationAttribute pda = new PointcutDeclarationAttribute(ResolvedPointcutDefinition.read(s, context)); | |||
pda.pointcutDef.getPointcut().check(context,w); | |||
PointcutDeclarationAttribute pda = new PointcutDeclarationAttribute(ResolvedPointcutDefinition.read(s, context)); | |||
pda.pointcutDef.getPointcut().check(context, w); | |||
return pda; | |||
} else if (name.equals(TypeMunger.AttributeName)) { | |||
return new TypeMunger(ResolvedTypeMunger.read(s, context)); | |||
@@ -119,47 +122,54 @@ public abstract class AjAttribute { | |||
return EffectiveSignatureAttribute.read(s, context); | |||
} else { | |||
// We have to tell the user about this... | |||
if (w == null || w.getMessageHandler()==null) throw new BCException("unknown attribute" + name); | |||
w.getMessageHandler().handleMessage(MessageUtil.warn("unknown attribute encountered "+name)); | |||
if (w == null || w.getMessageHandler() == null) | |||
throw new BCException("unknown attribute" + name); | |||
w.getMessageHandler().handleMessage(MessageUtil.warn("unknown attribute encountered " + name)); | |||
return null; | |||
} | |||
} catch (BCException e) { | |||
throw new BCException("malformed " + name + " attribute (length:"+bytes.length+")" + e ); | |||
throw new BCException("malformed " + name + " attribute (length:" + bytes.length + ")" + e); | |||
} catch (IOException e) { | |||
throw new BCException("malformed " + name + " attribute (length:"+bytes.length+")" + e ); | |||
throw new BCException("malformed " + name + " attribute (length:" + bytes.length + ")" + e); | |||
} | |||
} | |||
//---- | |||
// ---- | |||
/** Synthetic members should have NO advice put on them or on their contents. | |||
* This attribute is currently unused as we consider all members starting | |||
* with NameMangler.PREFIX to automatically be synthetic. As we use this we might | |||
* find that we want multiple | |||
* kinds of synthetic. In particular, if we want to treat the call to a synthetic getter | |||
* (say, of an introduced field) as a field reference itself, then a method might want | |||
* a particular kind of AjSynthetic attribute that also includes a signature of what | |||
* it stands for. | |||
/** | |||
* Synthetic members should have NO advice put on them or on their contents. | |||
* This attribute is currently unused as we consider all members starting | |||
* with NameMangler.PREFIX to automatically be synthetic. As we use this we | |||
* might find that we want multiple kinds of synthetic. In particular, if we | |||
* want to treat the call to a synthetic getter (say, of an introduced | |||
* field) as a field reference itself, then a method might want a particular | |||
* kind of AjSynthetic attribute that also includes a signature of what it | |||
* stands for. | |||
*/ | |||
public static class AjSynthetic extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.AjSynthetic"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
// private ResolvedTypeMunger munger; | |||
public AjSynthetic() {} | |||
public AjSynthetic() { | |||
} | |||
public void write(DataOutputStream s) throws IOException {} | |||
public void write(DataOutputStream s) throws IOException { | |||
} | |||
} | |||
public static class TypeMunger extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.TypeMunger"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private ResolvedTypeMunger munger; | |||
private final ResolvedTypeMunger munger; | |||
public TypeMunger(ResolvedTypeMunger munger) { | |||
this.munger = munger; | |||
} | |||
@@ -167,54 +177,61 @@ public abstract class AjAttribute { | |||
public void write(DataOutputStream s) throws IOException { | |||
munger.write(s); | |||
} | |||
public ConcreteTypeMunger reify(World world, ResolvedType aspectType) { | |||
return world.concreteTypeMunger(munger, aspectType); | |||
return world.getWeavingSupport().concreteTypeMunger(munger, aspectType); | |||
} | |||
} | |||
public static class WeaverState extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.WeaverState"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private WeaverStateInfo kind; | |||
private final WeaverStateInfo kind; | |||
public WeaverState(WeaverStateInfo kind) { | |||
this.kind = kind; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
} | |||
public WeaverStateInfo reify() { | |||
return kind; | |||
} | |||
} | |||
public static class WeaverVersionInfo extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.WeaverVersion"; | |||
// If you change the format of an AspectJ class file, you have two options: | |||
// - changing the minor version means you have not added anything that prevents | |||
// previous versions of the weaver from operating (e.g. MethodDeclarationLineNumber attribute) | |||
// - changing the major version means you have added something that prevents previous | |||
// versions of the weaver from operating correctly. | |||
// If you change the format of an AspectJ class file, you have two | |||
// options: | |||
// - changing the minor version means you have not added anything that | |||
// prevents | |||
// previous versions of the weaver from operating (e.g. | |||
// MethodDeclarationLineNumber attribute) | |||
// - changing the major version means you have added something that | |||
// prevents previous | |||
// versions of the weaver from operating correctly. | |||
// | |||
// The user will get a warning for any org.aspectj.weaver attributes the weaver does | |||
// The user will get a warning for any org.aspectj.weaver attributes the | |||
// weaver does | |||
// not recognize. | |||
// When we don't know ... (i.e. pre 1.2.1) | |||
public final static short WEAVER_VERSION_MAJOR_UNKNOWN = 0; | |||
public final static short WEAVER_VERSION_MINOR_UNKNOWN = 0; | |||
// These are the weaver major/minor numbers for AspectJ 1.2.1 | |||
public final static short WEAVER_VERSION_MAJOR_AJ121 = 1; | |||
public final static short WEAVER_VERSION_MINOR_AJ121 = 0; | |||
// These are the weaver major/minor numbers for AspectJ 1.5.0 | |||
public final static short WEAVER_VERSION_MAJOR_AJ150M4 = 3; | |||
public final static short WEAVER_VERSION_MAJOR_AJ150M4 = 3; | |||
public final static short WEAVER_VERSION_MAJOR_AJ150 = 2; | |||
public final static short WEAVER_VERSION_MINOR_AJ150 = 0; | |||
@@ -223,120 +240,123 @@ public abstract class AjAttribute { | |||
public final static short WEAVER_VERSION_MAJOR_AJ160 = 4; | |||
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 | |||
public final static short WEAVER_VERSION_MINOR_AJ161 = 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 | |||
public final static short WEAVER_VERSION_MINOR_AJ161 = 0; | |||
// 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; | |||
public final static WeaverVersionInfo UNKNOWN = | |||
new WeaverVersionInfo(WEAVER_VERSION_MAJOR_UNKNOWN,WEAVER_VERSION_MINOR_UNKNOWN); | |||
public final static WeaverVersionInfo CURRENT = | |||
new WeaverVersionInfo(CURRENT_VERSION_MAJOR,CURRENT_VERSION_MINOR); | |||
private final static short CURRENT_VERSION_MINOR = WEAVER_VERSION_MINOR_AJ161; | |||
public final static WeaverVersionInfo UNKNOWN = new WeaverVersionInfo(WEAVER_VERSION_MAJOR_UNKNOWN, | |||
WEAVER_VERSION_MINOR_UNKNOWN); | |||
public final static WeaverVersionInfo CURRENT = new WeaverVersionInfo(CURRENT_VERSION_MAJOR, CURRENT_VERSION_MINOR); | |||
// These are the versions read in from a particular class file. | |||
private short major_version; | |||
private short minor_version; | |||
private final short major_version; | |||
private final short minor_version; | |||
private long buildstamp = Version.NOTIME; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
// Default ctor uses the current version numbers | |||
public WeaverVersionInfo() { | |||
this.major_version = CURRENT_VERSION_MAJOR; | |||
this.minor_version = CURRENT_VERSION_MINOR; | |||
major_version = CURRENT_VERSION_MAJOR; | |||
minor_version = CURRENT_VERSION_MINOR; | |||
} | |||
public WeaverVersionInfo(short major,short minor) { | |||
public WeaverVersionInfo(short major, short minor) { | |||
major_version = major; | |||
minor_version = minor; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeShort(CURRENT_VERSION_MAJOR); | |||
s.writeShort(CURRENT_VERSION_MINOR); | |||
s.writeLong(Version.getTime()); // build used to construct the class... | |||
s.writeLong(Version.getTime()); // build used to construct the | |||
// class... | |||
} | |||
public static WeaverVersionInfo read(VersionedDataInputStream s) throws IOException { | |||
short major = s.readShort(); | |||
short minor = s.readShort(); | |||
WeaverVersionInfo wvi = new WeaverVersionInfo(major,minor); | |||
if (s.getMajorVersion()>=WEAVER_VERSION_MAJOR_AJ150M4) { | |||
long stamp = 0; | |||
WeaverVersionInfo wvi = new WeaverVersionInfo(major, minor); | |||
if (s.getMajorVersion() >= WEAVER_VERSION_MAJOR_AJ150M4) { | |||
long stamp = 0; | |||
try { | |||
stamp = s.readLong(); | |||
wvi.setBuildstamp(stamp); | |||
} catch (EOFException eof) { | |||
// didnt find that build stamp - its not the end of the world | |||
// didnt find that build stamp - its not the end of the | |||
// world | |||
} | |||
} | |||
return wvi; | |||
} | |||
public short getMajorVersion() { | |||
return major_version; | |||
} | |||
public short getMinorVersion() { | |||
return minor_version; | |||
} | |||
public static short getCurrentWeaverMajorVersion() { | |||
return CURRENT_VERSION_MAJOR; | |||
} | |||
public static short getCurrentWeaverMinorVersion() { | |||
return CURRENT_VERSION_MINOR; | |||
} | |||
public void setBuildstamp(long stamp) { | |||
this.buildstamp = stamp; | |||
buildstamp = stamp; | |||
} | |||
public long getBuildstamp() { | |||
return buildstamp; | |||
} | |||
public String toString() { | |||
return major_version+"."+minor_version; | |||
return major_version + "." + minor_version; | |||
} | |||
public static String toCurrentVersionString() { | |||
return CURRENT_VERSION_MAJOR+"."+CURRENT_VERSION_MINOR; | |||
return CURRENT_VERSION_MAJOR + "." + CURRENT_VERSION_MINOR; | |||
} | |||
} | |||
public static class SourceContextAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.SourceContext"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private String sourceFileName; | |||
private int[] lineBreaks; | |||
private final String sourceFileName; | |||
private final int[] lineBreaks; | |||
public SourceContextAttribute(String sourceFileName, int[] lineBreaks) { | |||
this.sourceFileName = sourceFileName; | |||
this.lineBreaks = lineBreaks; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeUTF(sourceFileName); | |||
FileUtil.writeIntArray(lineBreaks, s); | |||
} | |||
public static SourceContextAttribute read(VersionedDataInputStream s) throws IOException { | |||
return new SourceContextAttribute(s.readUTF(), FileUtil.readIntArray(s)); | |||
} | |||
public int[] getLineBreaks() { | |||
return lineBreaks; | |||
} | |||
@@ -349,36 +369,41 @@ public abstract class AjAttribute { | |||
public static class MethodDeclarationLineNumberAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.MethodDeclarationLineNumber"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private int lineNumber; | |||
// AV: added in 1.5 M3 thus handling cases where we don't have that information | |||
private int offset; | |||
private final int lineNumber; | |||
// AV: added in 1.5 M3 thus handling cases where we don't have that | |||
// information | |||
private final int offset; | |||
public MethodDeclarationLineNumberAttribute(int line, int offset) { | |||
this.lineNumber = line; | |||
this.offset = offset; | |||
lineNumber = line; | |||
this.offset = offset; | |||
} | |||
public int getLineNumber() { | |||
return lineNumber; | |||
} | |||
public int getLineNumber() { return lineNumber; } | |||
public int getOffset() { return offset; } | |||
public int getOffset() { | |||
return offset; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeInt(lineNumber); | |||
s.writeInt(offset); | |||
s.writeInt(offset); | |||
} | |||
public static MethodDeclarationLineNumberAttribute read(VersionedDataInputStream s) throws IOException { | |||
int line = s.readInt(); | |||
int offset = 0; | |||
if (s.available()>0) { | |||
offset = s.readInt(); | |||
} | |||
int line = s.readInt(); | |||
int offset = 0; | |||
if (s.available() > 0) { | |||
offset = s.readInt(); | |||
} | |||
return new MethodDeclarationLineNumberAttribute(line, offset); | |||
} | |||
@@ -386,132 +411,128 @@ public abstract class AjAttribute { | |||
return AttributeName + ": " + lineNumber + ":" + offset; | |||
} | |||
} | |||
public static class PointcutDeclarationAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.PointcutDeclaration"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private ResolvedPointcutDefinition pointcutDef; | |||
private final ResolvedPointcutDefinition pointcutDef; | |||
public PointcutDeclarationAttribute(ResolvedPointcutDefinition pointcutDef) { | |||
this.pointcutDef = pointcutDef; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
pointcutDef.write(s); | |||
} | |||
public ResolvedPointcutDefinition reify() { | |||
return pointcutDef; | |||
} | |||
} | |||
} | |||
public static class DeclareAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.Declare"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private Declare declare; | |||
private final Declare declare; | |||
public DeclareAttribute(Declare declare) { | |||
this.declare = declare; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
declare.write(s); | |||
} | |||
} | |||
public Declare getDeclare() { | |||
return declare; | |||
} | |||
} | |||
} | |||
public static class AdviceAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.Advice"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private AdviceKind kind; | |||
private Pointcut pointcut; | |||
private int extraParameterFlags; | |||
private int start; | |||
private int end; | |||
private ISourceContext sourceContext; | |||
private final AdviceKind kind; | |||
private final Pointcut pointcut; | |||
private final int extraParameterFlags; | |||
private final int start; | |||
private final int end; | |||
private final ISourceContext sourceContext; | |||
// these are only used by around advice | |||
private boolean proceedInInners; | |||
private ResolvedMember[] proceedCallSignatures; // size == # of proceed calls in body | |||
private ResolvedMember[] proceedCallSignatures; // size == # of proceed | |||
// calls in body | |||
private boolean[] formalsUnchangedToProceed; // size == formals.size | |||
private UnresolvedType[] declaredExceptions; | |||
/** | |||
* @param lexicalPosition must be greater than the lexicalPosition | |||
* of any advice declared before this one in an aspect, otherwise, | |||
* it can be any value. | |||
* @param lexicalPosition must be greater than the lexicalPosition of | |||
* any advice declared before this one in an aspect, | |||
* otherwise, it can be any value. | |||
*/ | |||
public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags, | |||
int start, int end, ISourceContext sourceContext) { | |||
public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags, int start, int end, | |||
ISourceContext sourceContext) { | |||
this.kind = kind; | |||
this.pointcut = pointcut; | |||
this.extraParameterFlags = extraArgumentFlags; | |||
extraParameterFlags = extraArgumentFlags; | |||
this.start = start; | |||
this.end = end; | |||
this.sourceContext = sourceContext; | |||
//XXX put this back when testing works better (or fails better) | |||
//if (kind == AdviceKind.Around) throw new IllegalArgumentException("not for around"); | |||
// XXX put this back when testing works better (or fails better) | |||
// if (kind == AdviceKind.Around) throw new | |||
// IllegalArgumentException("not for around"); | |||
} | |||
public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags, | |||
int start, int end, ISourceContext sourceContext, | |||
boolean proceedInInners, ResolvedMember[] proceedCallSignatures, | |||
boolean[] formalsUnchangedToProceed, UnresolvedType[] declaredExceptions) { | |||
public AdviceAttribute(AdviceKind kind, Pointcut pointcut, int extraArgumentFlags, int start, int end, | |||
ISourceContext sourceContext, boolean proceedInInners, ResolvedMember[] proceedCallSignatures, | |||
boolean[] formalsUnchangedToProceed, UnresolvedType[] declaredExceptions) { | |||
this.kind = kind; | |||
this.pointcut = pointcut; | |||
this.extraParameterFlags = extraArgumentFlags; | |||
extraParameterFlags = extraArgumentFlags; | |||
this.start = start; | |||
this.end = end; | |||
this.sourceContext = sourceContext; | |||
if (kind != AdviceKind.Around) throw new IllegalArgumentException("only for around"); | |||
if (kind != AdviceKind.Around) | |||
throw new IllegalArgumentException("only for around"); | |||
this.proceedInInners = proceedInInners; | |||
this.proceedCallSignatures = proceedCallSignatures; | |||
this.formalsUnchangedToProceed = formalsUnchangedToProceed; | |||
this.declaredExceptions = declaredExceptions; | |||
} | |||
public static AdviceAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
AdviceKind kind = AdviceKind.read(s); | |||
if (kind == AdviceKind.Around) { | |||
return new AdviceAttribute( | |||
kind, | |||
Pointcut.read(s, context), | |||
s.readByte(), | |||
s.readInt(), s.readInt(), context, | |||
s.readBoolean(), | |||
ResolvedMemberImpl.readResolvedMemberArray(s, context), | |||
FileUtil.readBooleanArray(s), | |||
UnresolvedType.readArray(s)); | |||
return new AdviceAttribute(kind, Pointcut.read(s, context), s.readByte(), s.readInt(), s.readInt(), context, s | |||
.readBoolean(), ResolvedMemberImpl.readResolvedMemberArray(s, context), FileUtil.readBooleanArray(s), | |||
UnresolvedType.readArray(s)); | |||
} else { | |||
return new AdviceAttribute( | |||
kind, | |||
Pointcut.read(s, context), | |||
s.readByte(), | |||
s.readInt(), s.readInt(), context); | |||
return new AdviceAttribute(kind, Pointcut.read(s, context), s.readByte(), s.readInt(), s.readInt(), context); | |||
} | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
kind.write(s); | |||
pointcut.write(s); | |||
s.writeByte(extraParameterFlags); | |||
s.writeInt(start); | |||
s.writeInt(end); | |||
if (kind == AdviceKind.Around) { | |||
s.writeBoolean(proceedInInners); | |||
ResolvedMemberImpl.writeArray(proceedCallSignatures, s); | |||
@@ -519,16 +540,15 @@ public abstract class AjAttribute { | |||
UnresolvedType.writeArray(declaredExceptions, s); | |||
} | |||
} | |||
public Advice reify(Member signature, World world) { | |||
return world.createAdviceMunger(this, pointcut, signature); | |||
return world.getWeavingSupport().createAdviceMunger(this, pointcut, signature); | |||
} | |||
public String toString() { | |||
return "AdviceAttribute(" + kind + ", " + pointcut + ", " + | |||
extraParameterFlags + ", " + start+")"; | |||
return "AdviceAttribute(" + kind + ", " + pointcut + ", " + extraParameterFlags + ", " + start + ")"; | |||
} | |||
public int getExtraParameterFlags() { | |||
return extraParameterFlags; | |||
} | |||
@@ -570,53 +590,57 @@ public abstract class AjAttribute { | |||
} | |||
} | |||
public static class Aspect extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.Aspect"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private PerClause perClause; | |||
} | |||
private final PerClause perClause; | |||
private IScope resolutionScope; | |||
public Aspect(PerClause perClause) { | |||
this.perClause = perClause; | |||
} | |||
public PerClause reify(ResolvedType inAspect) { | |||
//XXXperClause.concretize(inAspect); | |||
return perClause; | |||
} | |||
public PerClause reifyFromAtAspectJ(ResolvedType inAspect) { | |||
perClause.resolve(resolutionScope); | |||
return perClause; | |||
} | |||
public PerClause reify(ResolvedType inAspect) { | |||
// XXXperClause.concretize(inAspect); | |||
return perClause; | |||
} | |||
public PerClause reifyFromAtAspectJ(ResolvedType inAspect) { | |||
perClause.resolve(resolutionScope); | |||
return perClause; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
perClause.write(s); | |||
} | |||
public void setResolutionScope(IScope binding) { | |||
this.resolutionScope = binding; | |||
resolutionScope = binding; | |||
} | |||
} | |||
public static class PrivilegedAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.Privileged"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private ResolvedMember[] accessedMembers; | |||
private final ResolvedMember[] accessedMembers; | |||
public PrivilegedAttribute(ResolvedMember[] accessedMembers) { | |||
this.accessedMembers = accessedMembers; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
ResolvedMemberImpl.writeArray(accessedMembers, s); | |||
} | |||
} | |||
public ResolvedMember[] getAccessedMembers() { | |||
return accessedMembers; | |||
} | |||
@@ -624,41 +648,40 @@ public abstract class AjAttribute { | |||
public static PrivilegedAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
return new PrivilegedAttribute(ResolvedMemberImpl.readResolvedMemberArray(s, context)); | |||
} | |||
} | |||
} | |||
public static class EffectiveSignatureAttribute extends AjAttribute { | |||
public static final String AttributeName = "org.aspectj.weaver.EffectiveSignature"; | |||
public String getNameString() { | |||
return AttributeName; | |||
} | |||
private ResolvedMember effectiveSignature; | |||
private Shadow.Kind shadowKind; | |||
private boolean weaveBody; | |||
private final ResolvedMember effectiveSignature; | |||
private final Shadow.Kind shadowKind; | |||
private final boolean weaveBody; | |||
public EffectiveSignatureAttribute(ResolvedMember effectiveSignature, Shadow.Kind shadowKind, boolean weaveBody) { | |||
this.effectiveSignature = effectiveSignature; | |||
this.shadowKind = shadowKind; | |||
this.weaveBody = weaveBody; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
effectiveSignature.write(s); | |||
shadowKind.write(s); | |||
s.writeBoolean(weaveBody); | |||
} | |||
} | |||
public static EffectiveSignatureAttribute read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
return new EffectiveSignatureAttribute( | |||
ResolvedMemberImpl.readResolvedMember(s, context), | |||
Shadow.Kind.read(s), | |||
s.readBoolean()); | |||
return new EffectiveSignatureAttribute(ResolvedMemberImpl.readResolvedMember(s, context), Shadow.Kind.read(s), s | |||
.readBoolean()); | |||
} | |||
public ResolvedMember getEffectiveSignature() { | |||
return effectiveSignature; | |||
} | |||
public String toString() { | |||
return "EffectiveSignatureAttribute(" + effectiveSignature + ", " + shadowKind + ")"; | |||
} | |||
@@ -671,7 +694,6 @@ public abstract class AjAttribute { | |||
return weaveBody; | |||
} | |||
} | |||
} | |||
} |
@@ -31,11 +31,12 @@ import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.weaver.patterns.PointcutRewriter; | |||
/** | |||
* This holds on to all members that have an invasive effect outside of there own compilation unit. These members need to be all | |||
* gathered up and in a world before any weaving can take place. | |||
* This holds on to all members that have an invasive effect outside of there | |||
* own compilation unit. These members need to be all gathered up and in a world | |||
* before any weaving can take place. | |||
* | |||
* They are also important in the compilation process and need to be gathered up before the inter-type declaration weaving stage | |||
* (unsurprisingly). | |||
* They are also important in the compilation process and need to be gathered up | |||
* before the inter-type declaration weaving stage (unsurprisingly). | |||
* | |||
* All members are concrete. | |||
* | |||
@@ -58,13 +59,14 @@ public class CrosscuttingMembers { | |||
// These are like declare parents type mungers | |||
private List declareAnnotationsOnType = new ArrayList(); | |||
private List declareAnnotationsOnField = new ArrayList(); | |||
private List declareAnnotationsOnMethods = new ArrayList(); // includes ctors | |||
private List declareAnnotationsOnMethods = new ArrayList(); // includes | |||
// ctors | |||
private boolean shouldConcretizeIfNeeded = true; | |||
public CrosscuttingMembers(ResolvedType inAspect, boolean shouldConcretizeIfNeeded) { | |||
this.inAspect = inAspect; | |||
this.world = inAspect.getWorld(); | |||
world = inAspect.getWorld(); | |||
this.shouldConcretizeIfNeeded = shouldConcretizeIfNeeded; | |||
} | |||
@@ -98,7 +100,8 @@ public class CrosscuttingMembers { | |||
public void addTypeMunger(ConcreteTypeMunger m) { | |||
if (m == null) | |||
throw new Error("FIXME AV - should not happen or what ?");// return; //??? | |||
throw new Error("FIXME AV - should not happen or what ?");// return; | |||
// //??? | |||
typeMungers.add(m); | |||
} | |||
@@ -130,7 +133,8 @@ public class CrosscuttingMembers { | |||
declareParents.add(dp); | |||
} else if (declare instanceof DeclareSoft) { | |||
DeclareSoft d = (DeclareSoft) declare; | |||
// Ordered so that during concretization we can check the related munger | |||
// Ordered so that during concretization we can check the related | |||
// munger | |||
ShadowMunger m = Advice.makeSoftener(world, d.getPointcut(), d.getException(), inAspect, d); | |||
m.setDeclaringType(d.getDeclaringType()); | |||
Pointcut concretePointcut = d.getPointcut().concretize(inAspect, d.getDeclaringType(), 0, m); | |||
@@ -138,10 +142,11 @@ public class CrosscuttingMembers { | |||
declareSofts.add(new DeclareSoft(d.getException(), concretePointcut)); | |||
addConcreteShadowMunger(m); | |||
} else if (declare instanceof DeclareAnnotation) { | |||
// FIXME asc perf Possible Improvement. Investigate why this is called twice in a weave ? | |||
// FIXME asc perf Possible Improvement. Investigate why this is | |||
// called twice in a weave ? | |||
DeclareAnnotation da = (DeclareAnnotation) declare; | |||
if (da.getAspect() == null) | |||
da.setAspect(this.inAspect); | |||
da.setAspect(inAspect); | |||
if (da.isDeclareAtType()) { | |||
declareAnnotationsOnType.add(da); | |||
} else if (da.isDeclareAtField()) { | |||
@@ -181,9 +186,10 @@ public class CrosscuttingMembers { | |||
return; // dont need to bother | |||
} | |||
} | |||
addTypeMunger(world.concreteTypeMunger(new ExposeTypeMunger(typeToExpose), inAspect)); | |||
addTypeMunger(world.getWeavingSupport().concreteTypeMunger(new ExposeTypeMunger(typeToExpose), inAspect)); | |||
// ResolvedMember member = new ResolvedMemberImpl( | |||
// Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID, "<clinit>", UnresolvedType.NONE); | |||
// Member.STATIC_INITIALIZATION, typeToExpose, 0, ResolvedType.VOID, | |||
// "<clinit>", UnresolvedType.NONE); | |||
// addTypeMunger(world.concreteTypeMunger( | |||
// new PrivilegedAccessMunger(member), inAspect)); | |||
} | |||
@@ -196,7 +202,7 @@ public class CrosscuttingMembers { | |||
private void addPrivilegedAccess(ResolvedMember member) { | |||
// System.err.println("add priv access: " + member); | |||
addTypeMunger(world.concreteTypeMunger(new PrivilegedAccessMunger(member), inAspect)); | |||
addTypeMunger(world.getWeavingSupport().concreteTypeMunger(new PrivilegedAccessMunger(member), inAspect)); | |||
} | |||
public Collection getCflowEntries() { | |||
@@ -214,15 +220,20 @@ public class CrosscuttingMembers { | |||
} | |||
/** | |||
* Updates the records if something has changed. This is called at most twice, firstly whilst collecting ITDs and declares. At | |||
* this point the CrosscuttingMembers we're comparing ourselves with doesn't know about shadowmungers. Therefore a straight | |||
* comparison with the existing list of shadowmungers would return that something has changed even though it might not have, so | |||
* in this first round we ignore the shadowMungers. The second time this is called is whilst we're preparing to weave. At this | |||
* point we know everything in the system and so we're able to compare the shadowMunger list. (see bug 129163) | |||
* Updates the records if something has changed. This is called at most | |||
* twice, firstly whilst collecting ITDs and declares. At this point the | |||
* CrosscuttingMembers we're comparing ourselves with doesn't know about | |||
* shadowmungers. Therefore a straight comparison with the existing list of | |||
* shadowmungers would return that something has changed even though it | |||
* might not have, so in this first round we ignore the shadowMungers. The | |||
* second time this is called is whilst we're preparing to weave. At this | |||
* point we know everything in the system and so we're able to compare the | |||
* shadowMunger list. (see bug 129163) | |||
* | |||
* @param other | |||
* @param careAboutShadowMungers | |||
* @return true if something has changed since the last time this method was called, false otherwise | |||
* @return true if something has changed since the last time this method was | |||
* called, false otherwise | |||
*/ | |||
public boolean replaceWith(CrosscuttingMembers other, boolean careAboutShadowMungers) { | |||
boolean changed = false; | |||
@@ -235,7 +246,8 @@ public class CrosscuttingMembers { | |||
} | |||
// XXX all of the below should be set equality rather than list equality | |||
// System.err.println("old: " + shadowMungers + " new: " + other.shadowMungers); | |||
// System.err.println("old: " + shadowMungers + " new: " + | |||
// other.shadowMungers); | |||
if (careAboutShadowMungers) { | |||
// bug 129163: use set equality rather than list equality | |||
@@ -338,18 +350,22 @@ public class CrosscuttingMembers { | |||
otherTypeMungers.addAll(other.typeMungers); | |||
} | |||
// initial go at equivalence logic rather than set compare (see pr133532) | |||
// initial go at equivalence logic rather than set compare (see | |||
// pr133532) | |||
// if (theseTypeMungers.size()!=otherTypeMungers.size()) { | |||
// changed = true; | |||
// typeMungers = other.typeMungers; | |||
// } else { | |||
// boolean foundInequality=false; | |||
// for (Iterator iter = theseTypeMungers.iterator(); iter.hasNext() && !foundInequality;) { | |||
// for (Iterator iter = theseTypeMungers.iterator(); iter.hasNext() && | |||
// !foundInequality;) { | |||
// Object thisOne = (Object) iter.next(); | |||
// boolean foundInOtherSet = false; | |||
// for (Iterator iterator = otherTypeMungers.iterator(); iterator.hasNext();) { | |||
// for (Iterator iterator = otherTypeMungers.iterator(); | |||
// iterator.hasNext();) { | |||
// Object otherOne = (Object) iterator.next(); | |||
// if (thisOne instanceof ConcreteTypeMunger && otherOne instanceof ConcreteTypeMunger) { | |||
// if (thisOne instanceof ConcreteTypeMunger && otherOne instanceof | |||
// ConcreteTypeMunger) { | |||
// if (((ConcreteTypeMunger)thisOne).equivalentTo(otherOne)) { | |||
// foundInOtherSet=true; | |||
// } else if (thisOne.equals(otherOne)) { | |||
@@ -444,7 +460,10 @@ public class CrosscuttingMembers { | |||
PointcutRewriter pr = new PointcutRewriter(); | |||
Pointcut p = munger.getPointcut(); | |||
Pointcut newP = pr.rewrite(p); | |||
if (p.m_ignoreUnboundBindingForNames.length != 0) {// *sigh* dirty fix for dirty hacky implementation pr149305 | |||
if (p.m_ignoreUnboundBindingForNames.length != 0) {// *sigh* dirty fix | |||
// for dirty hacky | |||
// implementation | |||
// pr149305 | |||
newP.m_ignoreUnboundBindingForNames = p.m_ignoreUnboundBindingForNames; | |||
} | |||
munger.setPointcut(newP); | |||
@@ -452,7 +471,7 @@ public class CrosscuttingMembers { | |||
} | |||
public void setPerClause(PerClause perClause) { | |||
if (this.shouldConcretizeIfNeeded) { | |||
if (shouldConcretizeIfNeeded) { | |||
this.perClause = perClause.concretize(inAspect); | |||
} else { | |||
this.perClause = perClause; |
@@ -0,0 +1,42 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 Contributors | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
/** | |||
* Encapsulates operations that a world will need to support if it is actually | |||
* going to modify bytecode rather than just match against it. {@see | |||
* BcelWeavingSupport} | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public interface IWeavingSupport { | |||
public Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature); | |||
public abstract ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField); | |||
public abstract ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField); | |||
/** | |||
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to | |||
* them as needed | |||
* | |||
* @see org.aspectj.weaver.bcel.BcelWorld#makePerClauseAspect(ResolvedType, | |||
* org.aspectj.weaver.patterns.PerClause.Kind) | |||
*/ | |||
public abstract ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind); | |||
public abstract ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType); | |||
} |
@@ -37,7 +37,6 @@ import org.aspectj.bridge.IMessage.Kind; | |||
import org.aspectj.bridge.context.PinpointingMessageHandler; | |||
import org.aspectj.weaver.UnresolvedType.TypeKind; | |||
import org.aspectj.weaver.patterns.DeclarePrecedence; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.weaver.tools.PointcutDesignatorHandler; | |||
import org.aspectj.weaver.tools.Trace; | |||
@@ -50,10 +49,16 @@ public abstract class World implements Dump.INode { | |||
/** handler for any messages produced during resolution etc. */ | |||
private IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR; | |||
/** handler for cross-reference information produced during the weaving process */ | |||
/** | |||
* handler for cross-reference information produced during the weaving | |||
* process | |||
*/ | |||
private ICrossReferenceHandler xrefHandler = null; | |||
/** Currently 'active' scope in which to lookup (resolve) typevariable references */ | |||
/** | |||
* Currently 'active' scope in which to lookup (resolve) typevariable | |||
* references | |||
*/ | |||
private TypeVariableDeclaringElement typeVariableLookupScope; | |||
/** The heart of the world, a map from type signatures to resolved types */ | |||
@@ -87,7 +92,10 @@ public abstract class World implements Dump.INode { | |||
/** XhasMember option setting passed down to weaver */ | |||
private boolean XhasMember = false; | |||
/** Xpinpoint controls whether we put out developer info showing the source of messages */ | |||
/** | |||
* Xpinpoint controls whether we put out developer info showing the source | |||
* of messages | |||
*/ | |||
private boolean Xpinpoint = false; | |||
/** When behaving in a Java 5 way autoboxing is considered */ | |||
@@ -100,8 +108,12 @@ public abstract class World implements Dump.INode { | |||
private String targetAspectjRuntimeLevel = Constants.RUNTIME_LEVEL_DEFAULT; | |||
/** Flags for the new joinpoints that are 'optional' */ | |||
private boolean optionalJoinpoint_ArrayConstruction = false; // Command line flag: "-Xjoinpoints:arrayconstruction" | |||
private boolean optionalJoinpoint_Synchronization = false; // Command line flag: "-Xjoinpoints:synchronization" | |||
private boolean optionalJoinpoint_ArrayConstruction = false; // Command line | |||
// flag: | |||
// "-Xjoinpoints:arrayconstruction" | |||
private boolean optionalJoinpoint_Synchronization = false; // Command line | |||
// flag: | |||
// "-Xjoinpoints:synchronization" | |||
private boolean addSerialVerUID = false; | |||
@@ -124,12 +136,14 @@ public abstract class World implements Dump.INode { | |||
private long warningThreshold; | |||
/** | |||
* A list of RuntimeExceptions containing full stack information for every type we couldn't find. | |||
* A list of RuntimeExceptions containing full stack information for every | |||
* type we couldn't find. | |||
*/ | |||
private List dumpState_cantFindTypeExceptions = null; | |||
/** | |||
* Play God. On the first day, God created the primitive types and put them in the type map. | |||
* Play God. On the first day, God created the primitive types and put them | |||
* in the type map. | |||
*/ | |||
protected World() { | |||
super(); | |||
@@ -169,9 +183,11 @@ public abstract class World implements Dump.INode { | |||
} | |||
} | |||
// ============================================================================= | |||
//========================================================================== | |||
// === | |||
// T Y P E R E S O L U T I O N | |||
// ============================================================================= | |||
//========================================================================== | |||
// === | |||
/** | |||
* Resolve a type that we require to be present in the world | |||
@@ -181,8 +197,10 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Attempt to resolve a type - the source location gives you some context in which resolution is taking place. In the case of an | |||
* error where we can't find the type - we can then at least report why (source location) we were trying to resolve it. | |||
* Attempt to resolve a type - the source location gives you some context in | |||
* which resolution is taking place. In the case of an error where we can't | |||
* find the type - we can then at least report why (source location) we were | |||
* trying to resolve it. | |||
*/ | |||
public ResolvedType resolve(UnresolvedType ty, ISourceLocation isl) { | |||
ResolvedType ret = resolve(ty, true); | |||
@@ -190,9 +208,11 @@ public abstract class World implements Dump.INode { | |||
// IMessage msg = null; | |||
getLint().cantFindType.signal(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE, ty.getName()), isl); | |||
// if (isl!=null) { | |||
// msg = MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName()),isl); | |||
// msg = MessageUtil.error(WeaverMessages.format(WeaverMessages. | |||
// CANT_FIND_TYPE,ty.getName()),isl); | |||
// } else { | |||
// msg = MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName())); | |||
// msg = MessageUtil.error(WeaverMessages.format(WeaverMessages. | |||
// CANT_FIND_TYPE,ty.getName())); | |||
// } | |||
// messageHandler.handleMessage(msg); | |||
} | |||
@@ -200,8 +220,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Convenience method for resolving an array of unresolved types in one hit. Useful for e.g. resolving type parameters in | |||
* signatures. | |||
* Convenience method for resolving an array of unresolved types in one hit. | |||
* Useful for e.g. resolving type parameters in signatures. | |||
*/ | |||
public ResolvedType[] resolve(UnresolvedType[] types) { | |||
if (types == null) | |||
@@ -215,7 +235,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Resolve a type. This the hub of type resolution. The resolved type is added to the type map by signature. | |||
* Resolve a type. This the hub of type resolution. The resolved type is | |||
* added to the type map by signature. | |||
*/ | |||
public ResolvedType resolve(UnresolvedType ty, boolean allowMissing) { | |||
@@ -226,13 +247,16 @@ public abstract class World implements Dump.INode { | |||
return rty; | |||
} | |||
// dispatch back to the type variable reference to resolve its constituent parts | |||
// don't do this for other unresolved types otherwise you'll end up in a loop | |||
// dispatch back to the type variable reference to resolve its | |||
// constituent parts | |||
// don't do this for other unresolved types otherwise you'll end up in a | |||
// loop | |||
if (ty.isTypeVariableReference()) { | |||
return ty.resolve(this); | |||
} | |||
// if we've already got a resolved type for the signature, just return it | |||
// if we've already got a resolved type for the signature, just return | |||
// it | |||
// after updating the world | |||
String signature = ty.getSignature(); | |||
ResolvedType ret = typeMap.get(signature); | |||
@@ -240,9 +264,11 @@ public abstract class World implements Dump.INode { | |||
ret.world = this; // Set the world for the RTX | |||
return ret; | |||
} else if (signature.equals("?") || signature.equals("*")) { | |||
// might be a problem here, not sure '?' should make it to here as a signature, the | |||
// might be a problem here, not sure '?' should make it to here as a | |||
// signature, the | |||
// proper signature for wildcard '?' is '*' | |||
// fault in generic wildcard, can't be done earlier because of init issues | |||
// fault in generic wildcard, can't be done earlier because of init | |||
// issues | |||
// TODO ought to be shared single instance representing this | |||
ResolvedType something = new BoundedReferenceType("*", "Ljava/lang/Object", this); | |||
typeMap.put("?", something); | |||
@@ -252,7 +278,8 @@ public abstract class World implements Dump.INode { | |||
// no existing resolved type, create one | |||
if (ty.isArray()) { | |||
ResolvedType componentType = resolve(ty.getComponentType(), allowMissing); | |||
// String brackets = signature.substring(0,signature.lastIndexOf("[")+1); | |||
// String brackets = | |||
// signature.substring(0,signature.lastIndexOf("[")+1); | |||
ret = new ArrayReferenceType(signature, "[" + componentType.getErasureSignature(), this, componentType); | |||
} else { | |||
ret = resolveToReferenceType(ty, allowMissing); | |||
@@ -272,14 +299,16 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Called when a type is resolved - enables its type hierarchy to be finished off before we proceed | |||
* Called when a type is resolved - enables its type hierarchy to be | |||
* finished off before we proceed | |||
*/ | |||
protected void completeBinaryType(ResolvedType ret) { | |||
} | |||
/** | |||
* Return true if the classloader relating to this world is definetly the one that will define the specified class. Return false | |||
* otherwise or we don't know for certain. | |||
* Return true if the classloader relating to this world is definetly the | |||
* one that will define the specified class. Return false otherwise or we | |||
* don't know for certain. | |||
*/ | |||
public boolean isLocallyDefined(String classname) { | |||
return false; | |||
@@ -289,7 +318,8 @@ public abstract class World implements Dump.INode { | |||
* We tried to resolve a type and couldn't find it... | |||
*/ | |||
private ResolvedType handleRequiredMissingTypeDuringResolution(UnresolvedType ty) { | |||
// defer the message until someone asks a question of the type that we can't answer | |||
// defer the message until someone asks a question of the type that we | |||
// can't answer | |||
// just from the signature. | |||
// MessageUtil.error(messageHandler, | |||
// WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName())); | |||
@@ -303,8 +333,10 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Some TypeFactory operations create resolved types directly, but these won't be in the typeMap - this resolution process puts | |||
* them there. Resolved types are also told their world which is needed for the special autoboxing resolved types. | |||
* Some TypeFactory operations create resolved types directly, but these | |||
* won't be in the typeMap - this resolution process puts them there. | |||
* Resolved types are also told their world which is needed for the special | |||
* autoboxing resolved types. | |||
*/ | |||
public ResolvedType resolve(ResolvedType ty) { | |||
if (ty.isTypeVariableReference()) | |||
@@ -319,7 +351,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Convenience method for finding a type by name and resolving it in one step. | |||
* Convenience method for finding a type by name and resolving it in one | |||
* step. | |||
*/ | |||
public ResolvedType resolve(String name) { | |||
// trace.enter("resolve", this, new Object[] {name}); | |||
@@ -333,8 +366,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Resolve to a ReferenceType - simple, raw, parameterized, or generic. Raw, parameterized, and generic versions of a type share | |||
* a delegate. | |||
* Resolve to a ReferenceType - simple, raw, parameterized, or generic. Raw, | |||
* parameterized, and generic versions of a type share a delegate. | |||
*/ | |||
private final ResolvedType resolveToReferenceType(UnresolvedType ty, boolean allowMissing) { | |||
if (ty.isParameterizedType()) { | |||
@@ -364,13 +397,18 @@ public abstract class World implements Dump.INode { | |||
// 117854 | |||
// if (delegate == null) return ResolvedType.MISSING; | |||
if (delegate == null) | |||
return new MissingResolvedTypeWithKnownSignature(ty.getSignature(), erasedSignature, this);// ResolvedType.MISSING; | |||
return new MissingResolvedTypeWithKnownSignature(ty.getSignature(), erasedSignature, this);// ResolvedType | |||
// . | |||
// MISSING | |||
// ; | |||
if (delegate.isGeneric() && behaveInJava5Way) { | |||
// ======== raw type =========== | |||
simpleOrRawType.typeKind = TypeKind.RAW; | |||
ReferenceType genericType = makeGenericTypeFrom(delegate, simpleOrRawType); | |||
// name = ReferenceType.fromTypeX(UnresolvedType.forRawTypeNames(ty.getName()),this); | |||
// name = | |||
// ReferenceType.fromTypeX(UnresolvedType.forRawTypeNames( | |||
// ty.getName()),this); | |||
simpleOrRawType.setDelegate(delegate); | |||
genericType.setDelegate(delegate); | |||
simpleOrRawType.setGenericType(genericType); | |||
@@ -399,13 +437,16 @@ public abstract class World implements Dump.INode { | |||
return rawType; | |||
// Does the raw type know its generic form? (It will if we created the | |||
// raw type from a source type, it won't if its been created just through | |||
// raw type from a source type, it won't if its been created just | |||
// through | |||
// being referenced, e.g. java.util.List | |||
ResolvedType genericType = rawType.getGenericType(); | |||
// There is a special case to consider here (testGenericsBang_pr95993 highlights it) | |||
// There is a special case to consider here (testGenericsBang_pr95993 | |||
// highlights it) | |||
// You may have an unresolvedType for a parameterized type but it | |||
// is backed by a simple type rather than a generic type. This occurs for | |||
// is backed by a simple type rather than a generic type. This occurs | |||
// for | |||
// inner types of generic types that inherit their enclosing types | |||
// type variables. | |||
if (rawType.isSimpleType() && (anUnresolvedType.typeParameters == null || anUnresolvedType.typeParameters.length == 0)) { | |||
@@ -439,11 +480,13 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Go from an unresolved generic wildcard (represented by UnresolvedType) to a resolved version (BoundedReferenceType). | |||
* Go from an unresolved generic wildcard (represented by UnresolvedType) to | |||
* a resolved version (BoundedReferenceType). | |||
*/ | |||
private ReferenceType resolveGenericWildcardFor(WildcardedUnresolvedType aType) { | |||
BoundedReferenceType ret = null; | |||
// FIXME asc doesnt take account of additional interface bounds (e.g. ? super R & Serializable - can you do that?) | |||
// FIXME asc doesnt take account of additional interface bounds (e.g. ? | |||
// super R & Serializable - can you do that?) | |||
if (aType.isExtends()) { | |||
ReferenceType upperBound = (ReferenceType) resolve(aType.getUpperBound()); | |||
ret = new BoundedReferenceType(upperBound, true, this); | |||
@@ -458,15 +501,18 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Find the ReferenceTypeDelegate behind this reference type so that it can fulfill its contract. | |||
* Find the ReferenceTypeDelegate behind this reference type so that it can | |||
* fulfill its contract. | |||
*/ | |||
protected abstract ReferenceTypeDelegate resolveDelegate(ReferenceType ty); | |||
/** | |||
* Special resolution for "core" types like OBJECT. These are resolved just like any other type, but if they are not found it is | |||
* more serious and we issue an error message immediately. | |||
* Special resolution for "core" types like OBJECT. These are resolved just | |||
* like any other type, but if they are not found it is more serious and we | |||
* issue an error message immediately. | |||
*/ | |||
// OPTIMIZE streamline path for core types? They are just simple types, could look straight in the typemap? | |||
// OPTIMIZE streamline path for core types? They are just simple types, | |||
// could look straight in the typemap? | |||
public ResolvedType getCoreType(UnresolvedType tx) { | |||
ResolvedType coreTy = resolve(tx, true); | |||
if (coreTy.isMissing()) { | |||
@@ -476,7 +522,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Lookup a type by signature, if not found then build one and put it in the map. | |||
* Lookup a type by signature, if not found then build one and put it in the | |||
* map. | |||
*/ | |||
public ReferenceType lookupOrCreateName(UnresolvedType ty) { | |||
String signature = ty.getSignature(); | |||
@@ -489,18 +536,22 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Lookup a reference type in the world by its signature. Returns null if not found. | |||
* Lookup a reference type in the world by its signature. Returns null if | |||
* not found. | |||
*/ | |||
public ReferenceType lookupBySignature(String signature) { | |||
return (ReferenceType) typeMap.get(signature); | |||
} | |||
// ============================================================================= | |||
//========================================================================== | |||
// === | |||
// T Y P E R E S O L U T I O N -- E N D | |||
// ============================================================================= | |||
//========================================================================== | |||
// === | |||
/** | |||
* Member resolution is achieved by resolving the declaring type and then looking up the member in the resolved declaring type. | |||
* Member resolution is achieved by resolving the declaring type and then | |||
* looking up the member in the resolved declaring type. | |||
*/ | |||
public ResolvedMember resolve(Member member) { | |||
ResolvedType declaring = member.getDeclaringType().resolve(this); | |||
@@ -519,14 +570,13 @@ public abstract class World implements Dump.INode { | |||
return declaring.lookupSyntheticMember(member); | |||
} | |||
// Methods for creating various cross-cutting members... | |||
// =========================================================== | |||
public abstract IWeavingSupport getWeavingSupport(); | |||
/** | |||
* Create an advice shadow munger from the given advice attribute | |||
*/ | |||
public abstract Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature); | |||
// public abstract Advice createAdviceMunger(AjAttribute.AdviceAttribute | |||
// attribute, Pointcut pointcut, Member signature); | |||
/** | |||
* Create an advice shadow munger for the given advice kind | |||
*/ | |||
@@ -534,24 +584,12 @@ public abstract class World implements Dump.INode { | |||
IHasSourceLocation loc) { | |||
AjAttribute.AdviceAttribute attribute = new AjAttribute.AdviceAttribute(kind, p, extraParameterFlags, loc.getStart(), loc | |||
.getEnd(), loc.getSourceContext()); | |||
return createAdviceMunger(attribute, p, signature); | |||
return getWeavingSupport().createAdviceMunger(attribute, p, signature); | |||
} | |||
public abstract ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField); | |||
public abstract ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField); | |||
/** | |||
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to them as needed | |||
* | |||
* @see org.aspectj.weaver.bcel.BcelWorld#makePerClauseAspect(ResolvedType, org.aspectj.weaver.patterns.PerClause.Kind) | |||
*/ | |||
public abstract ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind); | |||
public abstract ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType); | |||
/** | |||
* Same signature as org.aspectj.util.PartialOrder.PartialComparable.compareTo | |||
* Same signature as | |||
* org.aspectj.util.PartialOrder.PartialComparable.compareTo | |||
*/ | |||
public int compareByPrecedence(ResolvedType aspect1, ResolvedType aspect2) { | |||
return precedenceCalculator.compareByPrecedence(aspect1, aspect2); | |||
@@ -562,7 +600,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* compares by precedence with the additional rule that a super-aspect is sorted before its sub-aspects | |||
* compares by precedence with the additional rule that a super-aspect is | |||
* sorted before its sub-aspects | |||
*/ | |||
public int compareByPrecedenceAndHierarchy(ResolvedType aspect1, ResolvedType aspect2) { | |||
return precedenceCalculator.compareByPrecedenceAndHierarchy(aspect1, aspect2); | |||
@@ -572,7 +611,8 @@ public abstract class World implements Dump.INode { | |||
// =========================================================== | |||
/** | |||
* Nobody should hold onto a copy of this message handler, or setMessageHandler won't work right. | |||
* Nobody should hold onto a copy of this message handler, or | |||
* setMessageHandler won't work right. | |||
*/ | |||
public IMessageHandler getMessageHandler() { | |||
return messageHandler; | |||
@@ -587,8 +627,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* convenenience method for creating and issuing messages via the message handler - if you supply two locations you will get two | |||
* messages. | |||
* convenenience method for creating and issuing messages via the message | |||
* handler - if you supply two locations you will get two messages. | |||
*/ | |||
public void showMessage(Kind kind, String message, ISourceLocation loc1, ISourceLocation loc2) { | |||
if (loc1 != null) { | |||
@@ -609,11 +649,11 @@ public abstract class World implements Dump.INode { | |||
* Get the cross-reference handler for the world, may be null. | |||
*/ | |||
public ICrossReferenceHandler getCrossReferenceHandler() { | |||
return this.xrefHandler; | |||
return xrefHandler; | |||
} | |||
public void setTypeVariableLookupScope(TypeVariableDeclaringElement scope) { | |||
this.typeVariableLookupScope = scope; | |||
typeVariableLookupScope = scope; | |||
} | |||
public TypeVariableDeclaringElement getTypeVariableLookupScope() { | |||
@@ -689,7 +729,7 @@ public abstract class World implements Dump.INode { | |||
} | |||
public void setPinpointMode(boolean b) { | |||
this.Xpinpoint = b; | |||
Xpinpoint = b; | |||
} | |||
public void setBehaveInJava5Way(boolean b) { | |||
@@ -697,7 +737,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Set the error and warning threashold which can be taken from CompilerOptions (see bug 129282) | |||
* Set the error and warning threashold which can be taken from | |||
* CompilerOptions (see bug 129282) | |||
* | |||
* @param errorThreshold | |||
* @param warningThreshold | |||
@@ -708,12 +749,13 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* @return true if ignoring the UnusedDeclaredThrownException and false if this compiler option is set to error or warning | |||
* @return true if ignoring the UnusedDeclaredThrownException and false if | |||
* this compiler option is set to error or warning | |||
*/ | |||
public boolean isIgnoringUnusedDeclaredThrownException() { | |||
// the 0x800000 is CompilerOptions.UnusedDeclaredThrownException | |||
// which is ASTNode.bit24 | |||
if ((this.errorThreshold & 0x800000) != 0 || (this.warningThreshold & 0x800000) != 0) | |||
if ((errorThreshold & 0x800000) != 0 || (warningThreshold & 0x800000) != 0) | |||
return false; | |||
return true; | |||
} | |||
@@ -752,12 +794,24 @@ public abstract class World implements Dump.INode { | |||
return extraConfiguration; | |||
} | |||
public final static String xsetWEAVE_JAVA_PACKAGES = "weaveJavaPackages"; // default false - controls LTW | |||
public final static String xsetWEAVE_JAVAX_PACKAGES = "weaveJavaxPackages"; // default false - controls LTW | |||
public final static String xsetCAPTURE_ALL_CONTEXT = "captureAllContext"; // default false | |||
public final static String xsetRUN_MINIMAL_MEMORY = "runMinimalMemory"; // default true | |||
public final static String xsetDEBUG_STRUCTURAL_CHANGES_CODE = "debugStructuralChangesCode"; // default false | |||
public final static String xsetDEBUG_BRIDGING = "debugBridging"; // default false | |||
public final static String xsetWEAVE_JAVA_PACKAGES = "weaveJavaPackages"; // default | |||
// false | |||
// - | |||
// controls | |||
// LTW | |||
public final static String xsetWEAVE_JAVAX_PACKAGES = "weaveJavaxPackages"; // default | |||
// false | |||
// - | |||
// controls | |||
// LTW | |||
public final static String xsetCAPTURE_ALL_CONTEXT = "captureAllContext"; // default | |||
// false | |||
public final static String xsetRUN_MINIMAL_MEMORY = "runMinimalMemory"; // default | |||
// true | |||
public final static String xsetDEBUG_STRUCTURAL_CHANGES_CODE = "debugStructuralChangesCode"; // default | |||
// false | |||
public final static String xsetDEBUG_BRIDGING = "debugBridging"; // default | |||
// false | |||
public final static String xsetBCEL_REPOSITORY_CACHING = "bcelRepositoryCaching"; | |||
public final static String xsetPIPELINE_COMPILATION = "pipelineCompilation"; | |||
public final static String xsetGENERATE_STACKMAPS = "generateStackMaps"; | |||
@@ -765,7 +819,9 @@ public abstract class World implements Dump.INode { | |||
public final static String xsetCOMPLETE_BINARY_TYPES = "completeBinaryTypes"; | |||
public final static String xsetCOMPLETE_BINARY_TYPES_DEFAULT = "false"; | |||
public final static String xsetBCEL_REPOSITORY_CACHING_DEFAULT = "true"; | |||
public final static String xsetFAST_PACK_METHODS = "fastPackMethods"; // default TRUE | |||
public final static String xsetFAST_PACK_METHODS = "fastPackMethods"; // default | |||
// TRUE | |||
public boolean isInJava5Mode() { | |||
return behaveInJava5Way; | |||
@@ -796,20 +852,23 @@ public abstract class World implements Dump.INode { | |||
return targetAspectjRuntimeLevel; | |||
} | |||
// OPTIMIZE are users falling foul of not supplying -1.5 and so targetting the old runtime? | |||
// OPTIMIZE are users falling foul of not supplying -1.5 and so targetting | |||
// the old runtime? | |||
public boolean isTargettingAspectJRuntime12() { | |||
boolean b = false; // pr116679 | |||
if (!isInJava5Mode()) | |||
b = true; | |||
else | |||
b = getTargetAspectjRuntimeLevel().equals(org.aspectj.weaver.Constants.RUNTIME_LEVEL_12); | |||
// System.err.println("Asked if targetting runtime 1.2 , returning: "+b); | |||
//System.err.println("Asked if targetting runtime 1.2 , returning: "+b); | |||
return b; | |||
} | |||
/* | |||
* Map of types in the world, can have 'references' to expendable ones which can be garbage collected to recover memory. An | |||
* expendable type is a reference type that is not exposed to the weaver (ie just pulled in for type resolution purposes). | |||
* Map of types in the world, can have 'references' to expendable ones which | |||
* can be garbage collected to recover memory. An expendable type is a | |||
* reference type that is not exposed to the weaver (ie just pulled in for | |||
* type resolution purposes). | |||
*/ | |||
protected static class TypeMap { | |||
@@ -818,24 +877,25 @@ public abstract class World implements Dump.INode { | |||
// Strategy for entries in the expendable map | |||
public final static int DONT_USE_REFS = 0; // Hang around forever | |||
public final static int USE_WEAK_REFS = 1; // Collected asap | |||
public final static int USE_SOFT_REFS = 2; // Collected when short on memory | |||
public final static int USE_SOFT_REFS = 2; // Collected when short on | |||
// memory | |||
// SECRETAPI - Can switch to a policy of choice ;) | |||
public static int policy = USE_SOFT_REFS; | |||
// Map of types that never get thrown away | |||
private Map /* String -> ResolvedType */tMap = new HashMap(); | |||
private final Map /* String -> ResolvedType */tMap = new HashMap(); | |||
// Map of types that may be ejected from the cache if we need space | |||
private Map expendableMap = Collections.synchronizedMap(new WeakHashMap()); | |||
private final Map expendableMap = Collections.synchronizedMap(new WeakHashMap()); | |||
private World w; | |||
private final World w; | |||
// profiling tools... | |||
private boolean memoryProfiling = false; | |||
private int maxExpendableMapSize = -1; | |||
private int collectedTypes = 0; | |||
private ReferenceQueue rq = new ReferenceQueue(); | |||
private final ReferenceQueue rq = new ReferenceQueue(); | |||
private static Trace trace = TraceFactory.getTraceFactory().getTrace(World.TypeMap.class); | |||
@@ -843,20 +903,25 @@ public abstract class World implements Dump.INode { | |||
if (trace.isTraceEnabled()) | |||
trace.enter("<init>", this, w); | |||
this.w = w; | |||
memoryProfiling = false;// !w.getMessageHandler().isIgnoring(Message.INFO); | |||
memoryProfiling = false;//!w.getMessageHandler().isIgnoring(Message. | |||
// INFO); | |||
if (trace.isTraceEnabled()) | |||
trace.exit("<init>"); | |||
} | |||
/** | |||
* Add a new type into the map, the key is the type signature. Some types do *not* go in the map, these are ones involving | |||
* *member* type variables. The reason is that when all you have is the signature which gives you a type variable name, you | |||
* cannot guarantee you are using the type variable in the same way as someone previously working with a similarly named | |||
* type variable. So, these do not go into the map: - TypeVariableReferenceType. - ParameterizedType where a member type | |||
* variable is involved. - BoundedReferenceType when one of the bounds is a type variable. | |||
* Add a new type into the map, the key is the type signature. Some | |||
* types do *not* go in the map, these are ones involving *member* type | |||
* variables. The reason is that when all you have is the signature | |||
* which gives you a type variable name, you cannot guarantee you are | |||
* using the type variable in the same way as someone previously working | |||
* with a similarly named type variable. So, these do not go into the | |||
* map: - TypeVariableReferenceType. - ParameterizedType where a member | |||
* type variable is involved. - BoundedReferenceType when one of the | |||
* bounds is a type variable. | |||
* | |||
* definition: "member type variables" - a tvar declared on a generic method/ctor as opposed to those you see declared on a | |||
* generic type. | |||
* definition: "member type variables" - a tvar declared on a generic | |||
* method/ctor as opposed to those you see declared on a generic type. | |||
*/ | |||
public ResolvedType put(String key, ResolvedType type) { | |||
if (type.isParameterizedType() && type.isParameterizedWithTypeVariable()) { | |||
@@ -871,7 +936,8 @@ public abstract class World implements Dump.INode { | |||
System.err.println("Not putting a type variable reference type into the typemap: key=" + key + " type=" + type); | |||
return type; | |||
} | |||
// this test should be improved - only avoid putting them in if one of the | |||
// this test should be improved - only avoid putting them in if one | |||
// of the | |||
// bounds is a member type variable | |||
if (type instanceof BoundedReferenceType) { | |||
if (debug) | |||
@@ -934,7 +1000,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Lookup a type by its signature, always look in the real map before the expendable map | |||
* Lookup a type by its signature, always look in the real map before | |||
* the expendable map | |||
*/ | |||
public ResolvedType get(String key) { | |||
checkq(); | |||
@@ -981,11 +1048,13 @@ public abstract class World implements Dump.INode { | |||
// | |||
// collectTypes(expendableMap, results); | |||
// collectTypes(tMap, results); | |||
// return (ResolvedType[]) results.toArray(new ResolvedType[results.size()]); | |||
// return (ResolvedType[]) results.toArray(new | |||
// ResolvedType[results.size()]); | |||
// } | |||
// | |||
// private void collectTypes(Map map, List/* ResolvedType */results) { | |||
// for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) { | |||
// for (Iterator iterator = map.keySet().iterator(); | |||
// iterator.hasNext();) { | |||
// String key = (String) iterator.next(); | |||
// ResolvedType type = get(key); | |||
// if (type != null) | |||
@@ -998,28 +1067,31 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Reference types we don't intend to weave may be ejected from the cache if we need the space. | |||
* Reference types we don't intend to weave may be ejected from the cache if | |||
* we need the space. | |||
*/ | |||
protected boolean isExpendable(ResolvedType type) { | |||
return (!type.equals(UnresolvedType.OBJECT) && (!type.isExposedToWeaver()) && (!type.isPrimitiveType())); | |||
} | |||
/** | |||
* This class is used to compute and store precedence relationships between aspects. | |||
* This class is used to compute and store precedence relationships between | |||
* aspects. | |||
*/ | |||
private static class AspectPrecedenceCalculator { | |||
private World world; | |||
private Map cachedResults; | |||
private final World world; | |||
private final Map cachedResults; | |||
public AspectPrecedenceCalculator(World forSomeWorld) { | |||
this.world = forSomeWorld; | |||
this.cachedResults = new HashMap(); | |||
world = forSomeWorld; | |||
cachedResults = new HashMap(); | |||
} | |||
/** | |||
* Ask every declare precedence in the world to order the two aspects. If more than one declare precedence gives an | |||
* ordering, and the orderings conflict, then that's an error. | |||
* Ask every declare precedence in the world to order the two aspects. | |||
* If more than one declare precedence gives an ordering, and the | |||
* orderings conflict, then that's an error. | |||
*/ | |||
public int compareByPrecedence(ResolvedType firstAspect, ResolvedType secondAspect) { | |||
PrecedenceCacheKey key = new PrecedenceCacheKey(firstAspect, secondAspect); | |||
@@ -1027,7 +1099,9 @@ public abstract class World implements Dump.INode { | |||
return ((Integer) cachedResults.get(key)).intValue(); | |||
} else { | |||
int order = 0; | |||
DeclarePrecedence orderer = null; // Records the declare precedence statement that gives the first ordering | |||
DeclarePrecedence orderer = null; // Records the declare | |||
// precedence statement that | |||
// gives the first ordering | |||
for (Iterator i = world.getCrosscuttingMembersSet().getDeclareDominates().iterator(); i.hasNext();) { | |||
DeclarePrecedence d = (DeclarePrecedence) i.next(); | |||
int thisOrder = d.compare(firstAspect, secondAspect); | |||
@@ -1076,8 +1150,8 @@ public abstract class World implements Dump.INode { | |||
public ResolvedType aspect2; | |||
public PrecedenceCacheKey(ResolvedType a1, ResolvedType a2) { | |||
this.aspect1 = a1; | |||
this.aspect2 = a2; | |||
aspect1 = a1; | |||
aspect2 = a2; | |||
} | |||
public boolean equals(Object obj) { | |||
@@ -1096,12 +1170,15 @@ public abstract class World implements Dump.INode { | |||
public void validateType(UnresolvedType type) { | |||
} | |||
// --- with java5 we can get into a recursive mess if we aren't careful when resolving types (*cough* java.lang.Enum) --- | |||
// --- with java5 we can get into a recursive mess if we aren't careful when | |||
// resolving types (*cough* java.lang.Enum) --- | |||
// --- this first map is for java15 delegates which may try and recursively access the same type variables. | |||
// --- I would rather stash this against a reference type - but we don't guarantee referencetypes are unique for | |||
// --- this first map is for java15 delegates which may try and recursively | |||
// access the same type variables. | |||
// --- I would rather stash this against a reference type - but we don't | |||
// guarantee referencetypes are unique for | |||
// so we can't :( | |||
private Map workInProgress1 = new HashMap(); | |||
private final Map workInProgress1 = new HashMap(); | |||
public TypeVariable[] getTypeVariablesCurrentlyBeingProcessed(Class baseClass) { | |||
return (TypeVariable[]) workInProgress1.get(baseClass); | |||
@@ -1147,7 +1224,7 @@ public abstract class World implements Dump.INode { | |||
s = p.getProperty(xsetPIPELINE_COMPILATION, xsetPIPELINE_COMPILATION_DEFAULT); | |||
shouldPipelineCompilation = s.equalsIgnoreCase("true"); | |||
s = p.getProperty(xsetGENERATE_STACKMAPS, "false"); | |||
shouldGenerateStackMaps = s.equalsIgnoreCase("true"); | |||
@@ -1162,7 +1239,8 @@ public abstract class World implements Dump.INode { | |||
runMinimalMemory = s.equalsIgnoreCase("true"); | |||
// if (runMinimalMemory) | |||
// getMessageHandler().handleMessage(MessageUtil.info( | |||
// "[runMinimalMemory=true] Optimizing bcel processing (and cost of performance) to use less memory")); | |||
// "[runMinimalMemory=true] Optimizing bcel processing (and cost of performance) to use less memory" | |||
// )); | |||
s = p.getProperty(xsetDEBUG_STRUCTURAL_CHANGES_CODE, "false"); | |||
forDEBUG_structuralChangesCode = s.equalsIgnoreCase("true"); | |||
@@ -1189,12 +1267,12 @@ public abstract class World implements Dump.INode { | |||
ensureAdvancedConfigurationProcessed(); | |||
return shouldPipelineCompilation; | |||
} | |||
public boolean shouldGenerateStackMaps() { | |||
ensureAdvancedConfigurationProcessed(); | |||
return shouldGenerateStackMaps; | |||
} | |||
public void setIncrementalCompileCouldFollow(boolean b) { | |||
incrementalCompileCouldFollow = b; | |||
} | |||
@@ -1216,7 +1294,8 @@ public abstract class World implements Dump.INode { | |||
} | |||
/** | |||
* Register a new pointcut designator handler with the world - this can be used by any pointcut parsers attached to the world. | |||
* Register a new pointcut designator handler with the world - this can be | |||
* used by any pointcut parsers attached to the world. | |||
* | |||
* @param designatorHandler handler for the new pointcut | |||
*/ |
@@ -50,7 +50,8 @@ import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException; | |||
public final class BcelMethod extends ResolvedMemberImpl { | |||
//public final | |||
class BcelMethod extends ResolvedMemberImpl { | |||
private Method method; | |||
@@ -65,7 +66,7 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber; | |||
private AnnotationAJ[] annotations = null; | |||
private AnnotationAJ[][] parameterAnnotations = null; | |||
private BcelObjectType bcelObjectType; | |||
private final BcelObjectType bcelObjectType; | |||
private int bitflags; | |||
private static final int KNOW_IF_SYNTHETIC = 0x0001; | |||
@@ -89,8 +90,8 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
: METHOD), declaringType.getResolvedTypeX(), declaringType.isInterface() ? method.getModifiers() | |||
| Modifier.INTERFACE : method.getModifiers(), method.getName(), method.getSignature()); | |||
this.method = method; | |||
this.sourceContext = declaringType.getResolvedTypeX().getSourceContext(); | |||
this.bcelObjectType = declaringType; | |||
sourceContext = declaringType.getResolvedTypeX().getSourceContext(); | |||
bcelObjectType = declaringType; | |||
unpackJavaAttributes(); | |||
unpackAjAttributes(bcelObjectType.getWorld()); | |||
} | |||
@@ -431,8 +432,9 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
} | |||
/** | |||
* A method can be parameterized if it has one or more generic parameters. A generic parameter (type variable parameter) is | |||
* identified by the prefix "T" | |||
* A method can be parameterized if it has one or more generic parameters. A | |||
* generic parameter (type variable parameter) is identified by the prefix | |||
* "T" | |||
*/ | |||
public boolean canBeParameterized() { | |||
unpackGenericSignature(); | |||
@@ -445,7 +447,8 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
} | |||
/** | |||
* Return the parameterized/generic return type or the normal return type if the method is not generic. | |||
* Return the parameterized/generic return type or the normal return type if | |||
* the method is not generic. | |||
*/ | |||
public UnresolvedType getGenericReturnType() { | |||
unpackGenericSignature(); | |||
@@ -463,13 +466,14 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
} | |||
bitflags |= UNPACKED_GENERIC_SIGNATURE; | |||
if (!bcelObjectType.getWorld().isInJava5Mode()) { | |||
this.genericReturnType = getReturnType(); | |||
this.genericParameterTypes = getParameterTypes(); | |||
genericReturnType = getReturnType(); | |||
genericParameterTypes = getParameterTypes(); | |||
return; | |||
} | |||
String gSig = method.getGenericSignature(); | |||
if (gSig != null) { | |||
Signature.MethodTypeSignature mSig = new GenericSignatureParser().parseAsMethodSignature(gSig);// method. | |||
Signature.MethodTypeSignature mSig = new GenericSignatureParser().parseAsMethodSignature(gSig);// method | |||
// . | |||
// getGenericSignature | |||
// ()); | |||
if (mSig.formalTypeParameters.length > 0) { | |||
@@ -576,8 +580,9 @@ public final class BcelMethod extends ResolvedMemberImpl { | |||
} | |||
/** | |||
* Returns whether or not the given object is equivalent to the current one. Returns true if | |||
* getMethod().getCode().getCodeString() are equal. Allows for different line number tables. | |||
* Returns whether or not the given object is equivalent to the current one. | |||
* Returns true if getMethod().getCode().getCodeString() are equal. Allows | |||
* for different line number tables. | |||
*/ | |||
// bug 154054: is similar to equals(Object) however | |||
// doesn't require implementing equals in Method and Code |
@@ -0,0 +1,62 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2008 Contributors | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.bcel; | |||
import org.aspectj.weaver.Advice; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.ConcreteTypeMunger; | |||
import org.aspectj.weaver.IWeavingSupport; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.ResolvedTypeMunger; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
/** | |||
* Bcel implementation of the weaving support required in a BcelWorld which will | |||
* actually modify bytecode. | |||
* | |||
* @author Andy Clement | |||
*/ | |||
public class BcelWeavingSupport implements IWeavingSupport { | |||
public Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature) { | |||
// System.err.println("concrete advice: " + signature + " context " + | |||
// sourceContext); | |||
return new BcelAdvice(attribute, pointcut, signature, null); | |||
} | |||
public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) { | |||
return new BcelCflowStackFieldAdder(cflowField); | |||
} | |||
public ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField) { | |||
return new BcelCflowCounterFieldAdder(cflowField); | |||
} | |||
/** | |||
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to | |||
* them as needed | |||
* | |||
* @param aspect | |||
* @param kind | |||
* @return munger | |||
*/ | |||
public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, PerClause.Kind kind) { | |||
return new BcelPerClauseAspectAdder(aspect, kind); | |||
} | |||
public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) { | |||
return new BcelTypeMunger(munger, aspectType); | |||
} | |||
} |
@@ -39,13 +39,11 @@ import org.aspectj.apache.bcel.util.ClassPath; | |||
import org.aspectj.apache.bcel.util.NonCachingClassLoaderRepository; | |||
import org.aspectj.apache.bcel.util.Repository; | |||
import org.aspectj.bridge.IMessageHandler; | |||
import org.aspectj.weaver.Advice; | |||
import org.aspectj.weaver.AjAttribute; | |||
import org.aspectj.weaver.AnnotationAJ; | |||
import org.aspectj.weaver.AnnotationOnTypeMunger; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ConcreteTypeMunger; | |||
import org.aspectj.weaver.ICrossReferenceHandler; | |||
import org.aspectj.weaver.IWeavingSupport; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.MemberImpl; | |||
import org.aspectj.weaver.MemberKind; | |||
@@ -61,24 +59,17 @@ import org.aspectj.weaver.WeakClassLoaderReference; | |||
import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.patterns.DeclareAnnotation; | |||
import org.aspectj.weaver.patterns.DeclareParents; | |||
import org.aspectj.weaver.patterns.PerClause; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.weaver.tools.Trace; | |||
import org.aspectj.weaver.tools.TraceFactory; | |||
public class BcelWorld extends World implements Repository { | |||
private ClassPathManager classPath; | |||
private final ClassPathManager classPath; | |||
protected Repository delegate; | |||
private WeakClassLoaderReference loaderRef; | |||
private final BcelWeavingSupport bcelWeavingSupport = new BcelWeavingSupport(); | |||
// private ClassPathManager aspectPath = null; | |||
// private List aspectPathEntries; | |||
private static Trace trace = TraceFactory.getTraceFactory().getTrace( | |||
BcelWorld.class); | |||
// ---- constructors | |||
private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelWorld.class); | |||
public BcelWorld() { | |||
this(""); | |||
@@ -92,7 +83,6 @@ public class BcelWorld extends World implements Repository { | |||
List classPath = new ArrayList(); | |||
classPath.addAll(getPathEntries(cp)); | |||
classPath.addAll(getPathEntries(ClassPath.getClassPath())); | |||
// System.err.println("classpath: " + classPath); | |||
return classPath; | |||
} | |||
@@ -107,8 +97,7 @@ public class BcelWorld extends World implements Repository { | |||
return ret; | |||
} | |||
public BcelWorld(List classPath, IMessageHandler handler, | |||
ICrossReferenceHandler xrefHandler) { | |||
public BcelWorld(List classPath, IMessageHandler handler, ICrossReferenceHandler xrefHandler) { | |||
// this.aspectPath = new ClassPathManager(aspectPath, handler); | |||
this.classPath = new ClassPathManager(classPath, handler); | |||
setMessageHandler(handler); | |||
@@ -117,9 +106,8 @@ public class BcelWorld extends World implements Repository { | |||
delegate = this; | |||
} | |||
public BcelWorld(ClassPathManager cpm, IMessageHandler handler, | |||
ICrossReferenceHandler xrefHandler) { | |||
this.classPath = cpm; | |||
public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) { | |||
classPath = cpm; | |||
setMessageHandler(handler); | |||
setCrossReferenceHandler(xrefHandler); | |||
// Tell BCEL to use us for resolving any classes | |||
@@ -133,10 +121,9 @@ public class BcelWorld extends World implements Repository { | |||
* @param handler | |||
* @param xrefHandler | |||
*/ | |||
public BcelWorld(ClassLoader loader, IMessageHandler handler, | |||
ICrossReferenceHandler xrefHandler) { | |||
this.classPath = null; | |||
this.loaderRef = new WeakClassLoaderReference(loader); | |||
public BcelWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) { | |||
classPath = null; | |||
loaderRef = new WeakClassLoaderReference(loader); | |||
setMessageHandler(handler); | |||
setCrossReferenceHandler(xrefHandler); | |||
// Tell BCEL to use us for resolving any classes | |||
@@ -210,10 +197,8 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
} | |||
public BcelObjectType buildBcelDelegate(ReferenceType resolvedTypeX, | |||
JavaClass jc, boolean exposedToWeaver) { | |||
BcelObjectType ret = new BcelObjectType(resolvedTypeX, jc, | |||
exposedToWeaver); | |||
public BcelObjectType buildBcelDelegate(ReferenceType resolvedTypeX, JavaClass jc, boolean exposedToWeaver) { | |||
BcelObjectType ret = new BcelObjectType(resolvedTypeX, jc, exposedToWeaver); | |||
return ret; | |||
} | |||
@@ -223,25 +208,21 @@ public class BcelWorld extends World implements Repository { | |||
ensureRepositorySetup(); | |||
JavaClass jc = delegate.loadClass(name); | |||
if (trace.isTraceEnabled()) | |||
trace.event("lookupJavaClass", this, new Object[] { name, | |||
jc }); | |||
trace.event("lookupJavaClass", this, new Object[] { name, jc }); | |||
return jc; | |||
} catch (ClassNotFoundException e) { | |||
if (trace.isTraceEnabled()) | |||
trace.error("Unable to find class '" + name | |||
+ "' in repository", e); | |||
trace.error("Unable to find class '" + name + "' in repository", e); | |||
return null; | |||
} | |||
} | |||
try { | |||
ClassPathManager.ClassFile file = classPath.find(UnresolvedType | |||
.forName(name)); | |||
ClassPathManager.ClassFile file = classPath.find(UnresolvedType.forName(name)); | |||
if (file == null) | |||
return null; | |||
ClassParser parser = new ClassParser(file.getInputStream(), file | |||
.getPath()); | |||
ClassParser parser = new ClassParser(file.getInputStream(), file.getPath()); | |||
JavaClass jc = parser.parse(); | |||
file.close(); | |||
@@ -253,18 +234,15 @@ public class BcelWorld extends World implements Repository { | |||
public BcelObjectType addSourceObjectType(JavaClass jc) { | |||
BcelObjectType ret = null; | |||
String signature = UnresolvedType.forName(jc.getClassName()) | |||
.getSignature(); | |||
String signature = UnresolvedType.forName(jc.getClassName()).getSignature(); | |||
Object fromTheMap = typeMap.get(signature); | |||
if (fromTheMap != null && !(fromTheMap instanceof ReferenceType)) { | |||
// what on earth is it then? See pr 112243 | |||
StringBuffer exceptionText = new StringBuffer(); | |||
exceptionText | |||
.append("Found invalid (not a ReferenceType) entry in the type map. "); | |||
exceptionText.append("Signature=[" + signature + "] Found=[" | |||
+ fromTheMap + "] Class=[" + fromTheMap.getClass() + "]"); | |||
exceptionText.append("Found invalid (not a ReferenceType) entry in the type map. "); | |||
exceptionText.append("Signature=[" + signature + "] Found=[" + fromTheMap + "] Class=[" + fromTheMap.getClass() + "]"); | |||
throw new BCException(exceptionText.toString()); | |||
} | |||
@@ -273,12 +251,10 @@ public class BcelWorld extends World implements Repository { | |||
if (nameTypeX == null) { | |||
if (jc.isGeneric() && isInJava5Mode()) { | |||
nameTypeX = ReferenceType.fromTypeX(UnresolvedType | |||
.forRawTypeName(jc.getClassName()), this); | |||
nameTypeX = ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()), this); | |||
ret = buildBcelDelegate(nameTypeX, jc, true); | |||
ReferenceType genericRefType = new ReferenceType(UnresolvedType | |||
.forGenericTypeSignature(signature, ret | |||
.getDeclaredGenericSignature()), this); | |||
ReferenceType genericRefType = new ReferenceType(UnresolvedType.forGenericTypeSignature(signature, ret | |||
.getDeclaredGenericSignature()), this); | |||
nameTypeX.setDelegate(ret); | |||
genericRefType.setDelegate(ret); | |||
nameTypeX.setGenericType(genericRefType); | |||
@@ -298,26 +274,21 @@ public class BcelWorld extends World implements Repository { | |||
typeMap.remove(ty.getSignature()); | |||
} | |||
public static Member makeFieldJoinPointSignature(LazyClassGen cg, | |||
FieldInstruction fi) { | |||
public static Member makeFieldJoinPointSignature(LazyClassGen cg, FieldInstruction fi) { | |||
ConstantPool cpg = cg.getConstantPool(); | |||
return MemberImpl | |||
.field( | |||
fi.getClassName(cpg), | |||
(fi.opcode == Constants.GETSTATIC || fi.opcode == Constants.PUTSTATIC) ? Modifier.STATIC | |||
: 0, fi.getName(cpg), fi.getSignature(cpg)); | |||
return MemberImpl.field(fi.getClassName(cpg), | |||
(fi.opcode == Constants.GETSTATIC || fi.opcode == Constants.PUTSTATIC) ? Modifier.STATIC : 0, fi.getName(cpg), fi | |||
.getSignature(cpg)); | |||
} | |||
public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, | |||
MemberKind kind) { | |||
public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, MemberKind kind) { | |||
Member ret = mg.getMemberView(); | |||
if (ret == null) { | |||
int mods = mg.getAccessFlags(); | |||
if (mg.getEnclosingClass().isInterface()) { | |||
mods |= Modifier.INTERFACE; | |||
} | |||
return new ResolvedMemberImpl(kind, UnresolvedType.forName(mg | |||
.getClassName()), mods, fromBcel(mg.getReturnType()), mg | |||
return new ResolvedMemberImpl(kind, UnresolvedType.forName(mg.getClassName()), mods, fromBcel(mg.getReturnType()), mg | |||
.getName(), fromBcel(mg.getArgumentTypes())); | |||
} else { | |||
return ret; | |||
@@ -325,18 +296,15 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
public Member makeJoinPointSignatureForMonitorEnter(LazyClassGen cg, | |||
InstructionHandle h) { | |||
public Member makeJoinPointSignatureForMonitorEnter(LazyClassGen cg, InstructionHandle h) { | |||
return MemberImpl.monitorEnter(); | |||
} | |||
public Member makeJoinPointSignatureForMonitorExit(LazyClassGen cg, | |||
InstructionHandle h) { | |||
public Member makeJoinPointSignatureForMonitorExit(LazyClassGen cg, InstructionHandle h) { | |||
return MemberImpl.monitorExit(); | |||
} | |||
public Member makeJoinPointSignatureForArrayConstruction(LazyClassGen cg, | |||
InstructionHandle handle) { | |||
public Member makeJoinPointSignatureForArrayConstruction(LazyClassGen cg, InstructionHandle handle) { | |||
Instruction i = handle.getInstruction(); | |||
ConstantPool cpg = cg.getConstantPool(); | |||
Member retval = null; | |||
@@ -346,8 +314,7 @@ public class BcelWorld extends World implements Repository { | |||
Type ot = i.getType(cpg); | |||
UnresolvedType ut = fromBcel(ot); | |||
ut = UnresolvedType.makeArray(ut, 1); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, | |||
"<init>", new ResolvedType[] { ResolvedType.INT }); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", new ResolvedType[] { ResolvedType.INT }); | |||
} else if (i instanceof MULTIANEWARRAY) { | |||
MULTIANEWARRAY arrayInstruction = (MULTIANEWARRAY) i; | |||
UnresolvedType ut = null; | |||
@@ -363,25 +330,20 @@ public class BcelWorld extends World implements Repository { | |||
ResolvedType[] parms = new ResolvedType[dimensions]; | |||
for (int ii = 0; ii < dimensions; ii++) | |||
parms[ii] = ResolvedType.INT; | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, | |||
"<init>", parms); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", parms); | |||
} else if (i.opcode == Constants.NEWARRAY) { | |||
// NEWARRAY arrayInstruction = (NEWARRAY)i; | |||
Type ot = i.getType(); | |||
UnresolvedType ut = fromBcel(ot); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, | |||
"<init>", new ResolvedType[] { ResolvedType.INT }); | |||
retval = MemberImpl.method(ut, Modifier.PUBLIC, ResolvedType.VOID, "<init>", new ResolvedType[] { ResolvedType.INT }); | |||
} else { | |||
throw new BCException( | |||
"Cannot create array construction signature for this non-array instruction:" | |||
+ i); | |||
throw new BCException("Cannot create array construction signature for this non-array instruction:" + i); | |||
} | |||
return retval; | |||
} | |||
public Member makeJoinPointSignatureForMethodInvocation(LazyClassGen cg, | |||
InvokeInstruction ii) { | |||
public Member makeJoinPointSignatureForMethodInvocation(LazyClassGen cg, InvokeInstruction ii) { | |||
ConstantPool cpg = cg.getConstantPool(); | |||
String name = ii.getName(cpg); | |||
String declaring = ii.getClassName(cpg); | |||
@@ -390,9 +352,8 @@ public class BcelWorld extends World implements Repository { | |||
String signature = ii.getSignature(cpg); | |||
int modifier = (ii instanceof INVOKEINTERFACE) ? Modifier.INTERFACE | |||
: (ii.opcode == Constants.INVOKESTATIC) ? Modifier.STATIC | |||
: (ii.opcode == Constants.INVOKESPECIAL && !name | |||
.equals("<init>")) ? Modifier.PRIVATE : 0; | |||
: (ii.opcode == Constants.INVOKESTATIC) ? Modifier.STATIC : (ii.opcode == Constants.INVOKESPECIAL && !name | |||
.equals("<init>")) ? Modifier.PRIVATE : 0; | |||
// in Java 1.4 and after, static method call of super class within | |||
// subclass method appears | |||
@@ -401,12 +362,10 @@ public class BcelWorld extends World implements Repository { | |||
if (ii.opcode == Constants.INVOKESTATIC) { | |||
ResolvedType appearsDeclaredBy = resolve(declaring); | |||
// look for the method there | |||
for (Iterator iterator = appearsDeclaredBy.getMethods(); iterator | |||
.hasNext();) { | |||
for (Iterator iterator = appearsDeclaredBy.getMethods(); iterator.hasNext();) { | |||
ResolvedMember method = (ResolvedMember) iterator.next(); | |||
if (method.isStatic()) { | |||
if (name.equals(method.getName()) | |||
&& signature.equals(method.getSignature())) { | |||
if (name.equals(method.getName()) && signature.equals(method.getSignature())) { | |||
// we found it | |||
declaringType = method.getDeclaringType(); | |||
break; | |||
@@ -433,48 +392,13 @@ public class BcelWorld extends World implements Repository { | |||
return buf.toString(); | |||
} | |||
public Advice createAdviceMunger(AjAttribute.AdviceAttribute attribute, | |||
Pointcut pointcut, Member signature) { | |||
// System.err.println("concrete advice: " + signature + " context " + | |||
// sourceContext); | |||
return new BcelAdvice(attribute, pointcut, signature, null); | |||
} | |||
public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, | |||
ResolvedType aspectType) { | |||
return new BcelTypeMunger(munger, aspectType); | |||
} | |||
public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) { | |||
return new BcelCflowStackFieldAdder(cflowField); | |||
} | |||
public ConcreteTypeMunger makeCflowCounterFieldAdder( | |||
ResolvedMember cflowField) { | |||
return new BcelCflowCounterFieldAdder(cflowField); | |||
} | |||
/** | |||
* Register a munger for perclause @AJ aspect so that we add aspectOf(..) to | |||
* them as needed | |||
* | |||
* @param aspect | |||
* @param kind | |||
* @return munger | |||
*/ | |||
public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, | |||
PerClause.Kind kind) { | |||
return new BcelPerClauseAspectAdder(aspect, kind); | |||
} | |||
/** | |||
* Retrieve a bcel delegate for an aspect - this will return NULL if the | |||
* delegate is an EclipseSourceType and not a BcelObjectType - this happens | |||
* quite often when incrementally compiling. | |||
*/ | |||
public static BcelObjectType getBcelObjectType(ResolvedType concreteAspect) { | |||
ReferenceTypeDelegate rtDelegate = ((ReferenceType) concreteAspect) | |||
.getDelegate(); | |||
ReferenceTypeDelegate rtDelegate = ((ReferenceType) concreteAspect).getDelegate(); | |||
if (rtDelegate instanceof BcelObjectType) { | |||
return (BcelObjectType) rtDelegate; | |||
} else { | |||
@@ -517,7 +441,6 @@ public class BcelWorld extends World implements Repository { | |||
// throw new RuntimeException("Not implemented"); | |||
} | |||
// @Override | |||
/** | |||
* The aim of this method is to make sure a particular type is 'ok'. Some | |||
* operations on the delegate for a type modify it and this method is | |||
@@ -563,12 +486,10 @@ public class BcelWorld extends World implements Repository { | |||
// (like transform super calls) - that is done in | |||
// BcelTypeMunger.mungeNewParent() | |||
classType.addParent(newParent); | |||
ResolvedTypeMunger newParentMunger = new NewParentTypeMunger( | |||
newParent); | |||
ResolvedTypeMunger newParentMunger = new NewParentTypeMunger(newParent); | |||
newParentMunger.setSourceLocation(p.getSourceLocation()); | |||
onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, | |||
getCrosscuttingMembersSet().findAspectDeclaringParents( | |||
p))); | |||
onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, getCrosscuttingMembersSet() | |||
.findAspectDeclaringParents(p))); | |||
} | |||
} | |||
return didSomething; | |||
@@ -577,8 +498,7 @@ public class BcelWorld extends World implements Repository { | |||
/** | |||
* Apply a declare @type - return true if we change the type | |||
*/ | |||
private boolean applyDeclareAtType(DeclareAnnotation decA, | |||
ResolvedType onType, boolean reportProblems) { | |||
private boolean applyDeclareAtType(DeclareAnnotation decA, ResolvedType onType, boolean reportProblems) { | |||
boolean didSomething = false; | |||
if (decA.matches(onType)) { | |||
@@ -594,11 +514,9 @@ public class BcelWorld extends World implements Repository { | |||
if (isOK) { | |||
didSomething = true; | |||
ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger( | |||
annoX); | |||
ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger(annoX); | |||
newAnnotationTM.setSourceLocation(decA.getSourceLocation()); | |||
onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM, | |||
decA.getAspect().resolve(this))); | |||
onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM, decA.getAspect().resolve(this))); | |||
decA.copyAnnotationTo(onType); | |||
} | |||
} | |||
@@ -609,11 +527,9 @@ public class BcelWorld extends World implements Repository { | |||
* Checks for an @target() on the annotation and if found ensures it allows | |||
* the annotation to be attached to the target type that matched. | |||
*/ | |||
private boolean checkTargetOK(DeclareAnnotation decA, ResolvedType onType, | |||
AnnotationAJ annoX) { | |||
private boolean checkTargetOK(DeclareAnnotation decA, ResolvedType onType, AnnotationAJ annoX) { | |||
if (annoX.specifiesTarget()) { | |||
if ((onType.isAnnotation() && !annoX.allowedOnAnnotationType()) | |||
|| (!annoX.allowedOnRegularType())) { | |||
if ((onType.isAnnotation() && !annoX.allowedOnAnnotationType()) || (!annoX.allowedOnRegularType())) { | |||
return false; | |||
} | |||
} | |||
@@ -626,8 +542,7 @@ public class BcelWorld extends World implements Repository { | |||
// weaving. | |||
protected void weaveInterTypeDeclarations(ResolvedType onType) { | |||
List declareParentsList = getCrosscuttingMembersSet() | |||
.getDeclareParents(); | |||
List declareParentsList = getCrosscuttingMembersSet().getDeclareParents(); | |||
if (onType.isRawType()) | |||
onType = onType.getGenericType(); | |||
onType.clearInterTypeMungers(); | |||
@@ -650,8 +565,7 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
// Still first pass - apply all dec @type mungers | |||
for (Iterator i = getCrosscuttingMembersSet() | |||
.getDeclareAnnotationOnTypes().iterator(); i.hasNext();) { | |||
for (Iterator i = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator(); i.hasNext();) { | |||
DeclareAnnotation decA = (DeclareAnnotation) i.next(); | |||
boolean typeChanged = applyDeclareAtType(decA, onType, true); | |||
if (typeChanged) { | |||
@@ -659,8 +573,7 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
} | |||
while ((aParentChangeOccurred || anAnnotationChangeOccurred) | |||
&& !decpToRepeat.isEmpty()) { | |||
while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) { | |||
anAnnotationChangeOccurred = aParentChangeOccurred = false; | |||
List decpToRepeatNextTime = new ArrayList(); | |||
for (Iterator iter = decpToRepeat.iterator(); iter.hasNext();) { | |||
@@ -673,8 +586,7 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
} | |||
for (Iterator iter = getCrosscuttingMembersSet() | |||
.getDeclareAnnotationOnTypes().iterator(); iter.hasNext();) { | |||
for (Iterator iter = getCrosscuttingMembersSet().getDeclareAnnotationOnTypes().iterator(); iter.hasNext();) { | |||
DeclareAnnotation decA = (DeclareAnnotation) iter.next(); | |||
boolean typeChanged = applyDeclareAtType(decA, onType, false); | |||
if (typeChanged) { | |||
@@ -685,4 +597,8 @@ public class BcelWorld extends World implements Repository { | |||
} | |||
} | |||
public IWeavingSupport getWeavingSupport() { | |||
return bcelWeavingSupport; | |||
} | |||
} |
@@ -10,7 +10,6 @@ | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.patterns; | |||
import java.io.DataOutputStream; | |||
@@ -41,29 +40,28 @@ import org.aspectj.weaver.WeaverMessages; | |||
import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.ast.Test; | |||
public class CflowPointcut extends Pointcut { | |||
private Pointcut entry; // The pointcut inside the cflow() that represents the 'entry' point | |||
private final Pointcut entry; // The pointcut inside the cflow() that | |||
// represents the 'entry' point | |||
boolean isBelow;// Is this cflowbelow? | |||
private int[] freeVars; | |||
/** | |||
* Used to indicate that we're in the context of a cflow when concretizing if's | |||
* Used to indicate that we're in the context of a cflow when concretizing | |||
* if's | |||
* | |||
* Will be removed or replaced with something better when we handle this | |||
* as a non-error | |||
* Will be removed or replaced with something better when we handle this as | |||
* a non-error | |||
*/ | |||
public static final ResolvedPointcutDefinition CFLOW_MARKER = | |||
new ResolvedPointcutDefinition(null, 0, null, UnresolvedType.NONE, Pointcut.makeMatchesNothing(Pointcut.RESOLVED)); | |||
public static final ResolvedPointcutDefinition CFLOW_MARKER = new ResolvedPointcutDefinition(null, 0, null, | |||
UnresolvedType.NONE, Pointcut.makeMatchesNothing(Pointcut.RESOLVED)); | |||
public CflowPointcut(Pointcut entry, boolean isBelow, int[] freeVars) { | |||
// System.err.println("Building cflow pointcut "+entry.toString()); | |||
// System.err.println("Building cflow pointcut "+entry.toString()); | |||
this.entry = entry; | |||
this.isBelow = isBelow; | |||
this.freeVars = freeVars; | |||
this.pointcutKind = CFLOW; | |||
pointcutKind = CFLOW; | |||
} | |||
/** | |||
@@ -76,18 +74,18 @@ public class CflowPointcut extends Pointcut { | |||
public int couldMatchKinds() { | |||
return Shadow.ALL_SHADOW_KINDS_BITS; | |||
} | |||
// enh 76055 | |||
public Pointcut getEntry() { | |||
return entry; | |||
return entry; | |||
} | |||
public FuzzyBoolean fastMatch(FastMatchInfo type) { | |||
public FuzzyBoolean fastMatch(FastMatchInfo type) { | |||
return FuzzyBoolean.MAYBE; | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
//??? this is not maximally efficient | |||
// ??? this is not maximally efficient | |||
return FuzzyBoolean.MAYBE; | |||
} | |||
@@ -98,15 +96,16 @@ public class CflowPointcut extends Pointcut { | |||
FileUtil.writeIntArray(freeVars, s); | |||
writeLocation(s); | |||
} | |||
public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
CflowPointcut ret = new CflowPointcut(Pointcut.read(s, context), s.readBoolean(), FileUtil.readIntArray(s)); | |||
ret.readLocation(context, s); | |||
return ret; | |||
} | |||
public Pointcut parameterizeWith(Map typeVariableMap,World w) { | |||
CflowPointcut ret = new CflowPointcut(entry.parameterizeWith(typeVariableMap,w),isBelow,freeVars); | |||
public Pointcut parameterizeWith(Map typeVariableMap, World w) { | |||
CflowPointcut ret = new CflowPointcut(entry.parameterizeWith(typeVariableMap, w), isBelow, freeVars); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} | |||
@@ -117,29 +116,32 @@ public class CflowPointcut extends Pointcut { | |||
entry.state = RESOLVED; | |||
freeVars = new int[0]; | |||
} else { | |||
//??? for if's sake we might need to be more careful here | |||
// ??? for if's sake we might need to be more careful here | |||
Bindings entryBindings = new Bindings(bindings.size()); | |||
entry.resolveBindings(scope, entryBindings); | |||
entry.state = RESOLVED; | |||
freeVars = entryBindings.getUsedFormals(); | |||
bindings.mergeIn(entryBindings, scope); | |||
} | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof CflowPointcut)) return false; | |||
CflowPointcut o = (CflowPointcut)other; | |||
return o.entry.equals(this.entry) && o.isBelow == this.isBelow; | |||
if (!(other instanceof CflowPointcut)) | |||
return false; | |||
CflowPointcut o = (CflowPointcut) other; | |||
return o.entry.equals(entry) && o.isBelow == isBelow; | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37 * result + entry.hashCode(); | |||
result = 37 * result + (isBelow ? 0 : 1); | |||
return result; | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37*result + entry.hashCode(); | |||
result = 37*result + (isBelow ? 0 : 1); | |||
return result; | |||
} | |||
public String toString() { | |||
return "cflow" + (isBelow ? "below" : "") + "(" + entry + ")"; | |||
} | |||
@@ -147,46 +149,45 @@ public class CflowPointcut extends Pointcut { | |||
protected Test findResidueInternal(Shadow shadow, ExposedState state) { | |||
throw new RuntimeException("unimplemented - did concretization fail?"); | |||
} | |||
public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) { | |||
// the pointcut is marked as CONCRETE after returning from this | |||
// the pointcut is marked as CONCRETE after returning from this | |||
// call - so we can't skip concretization | |||
// if (this.entry.state == Pointcut.SYMBOLIC) { | |||
// // too early to concretize, return unchanged | |||
// return this; | |||
// } | |||
// if (this.entry.state == Pointcut.SYMBOLIC) { | |||
// // too early to concretize, return unchanged | |||
// return this; | |||
// } | |||
// Enforce rule about which designators are supported in declare | |||
if (isDeclare(bindings.getEnclosingAdvice())) { | |||
inAspect.getWorld().showMessage(IMessage.ERROR, | |||
WeaverMessages.format(WeaverMessages.CFLOW_IN_DECLARE,isBelow?"below":""), | |||
WeaverMessages.format(WeaverMessages.CFLOW_IN_DECLARE, isBelow ? "below" : ""), | |||
bindings.getEnclosingAdvice().getSourceLocation(), null); | |||
return Pointcut.makeMatchesNothing(Pointcut.CONCRETE); | |||
} | |||
//make this remap from formal positions to arrayIndices | |||
// make this remap from formal positions to arrayIndices | |||
IntMap entryBindings = new IntMap(); | |||
if (freeVars!=null) { | |||
for (int i=0, len=freeVars.length; i < len; i++) { | |||
int freeVar = freeVars[i]; | |||
//int formalIndex = bindings.get(freeVar); | |||
entryBindings.put(freeVar, i); | |||
} | |||
if (freeVars != null) { | |||
for (int i = 0, len = freeVars.length; i < len; i++) { | |||
int freeVar = freeVars[i]; | |||
// int formalIndex = bindings.get(freeVar); | |||
entryBindings.put(freeVar, i); | |||
} | |||
} | |||
entryBindings.copyContext(bindings); | |||
//System.out.println(this + " bindings: " + entryBindings); | |||
// System.out.println(this + " bindings: " + entryBindings); | |||
World world = inAspect.getWorld(); | |||
Pointcut concreteEntry; | |||
ResolvedType concreteAspect = bindings.getConcreteAspect(); | |||
CrosscuttingMembers xcut = concreteAspect.crosscuttingMembers; | |||
CrosscuttingMembers xcut = concreteAspect.crosscuttingMembers; | |||
Collection previousCflowEntries = xcut.getCflowEntries(); | |||
entryBindings.pushEnclosingDefinition(CFLOW_MARKER); | |||
// This block concretizes the pointcut within the cflow pointcut | |||
try { | |||
@@ -198,139 +199,157 @@ public class CflowPointcut extends Pointcut { | |||
List innerCflowEntries = new ArrayList(xcut.getCflowEntries()); | |||
innerCflowEntries.removeAll(previousCflowEntries); | |||
// Four routes of interest through this code (did I hear someone say refactor??) | |||
// 1) no state in the cflow - we can use a counter *and* we have seen this pointcut | |||
// before - so use the same counter as before. | |||
// 2) no state in the cflow - we can use a counter, but this is the first time | |||
// we have seen this pointcut, so build the infrastructure. | |||
// 3) state in the cflow - we need to use a stack *and* we have seen this pointcut | |||
// before - so share the stack. | |||
// 4) state in the cflow - we need to use a stack, but this is the first time | |||
// we have seen this pointcut, so build the infrastructure. | |||
if (freeVars==null || freeVars.length == 0) { // No state, so don't use a stack, use a counter. | |||
ResolvedMember localCflowField = null; | |||
Object field = getCflowfield(xcut, concreteEntry, concreteAspect, "counter"); | |||
// Check if we have already got a counter for this cflow pointcut | |||
if (field != null) { | |||
localCflowField = (ResolvedMember)field; // Use the one we already have | |||
} else { | |||
// Create a counter field in the aspect | |||
localCflowField = new ResolvedMemberImpl(Member.FIELD,concreteAspect,Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL, | |||
NameMangler.cflowCounter(xcut),UnresolvedType.forName(NameMangler.CFLOW_COUNTER_TYPE).getSignature()); | |||
// Create type munger to add field to the aspect | |||
concreteAspect.crosscuttingMembers.addTypeMunger(world.makeCflowCounterFieldAdder(localCflowField)); | |||
// Create shadow munger to push stuff onto the stack | |||
concreteAspect.crosscuttingMembers.addConcreteShadowMunger( | |||
Advice.makeCflowEntry(world,concreteEntry,isBelow,localCflowField,freeVars==null?0:freeVars.length,innerCflowEntries,inAspect)); | |||
putCflowfield(xcut,concreteEntry,concreteAspect,localCflowField,"counter"); // Remember it | |||
} | |||
Pointcut ret = new ConcreteCflowPointcut(localCflowField, null,true); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
// Four routes of interest through this code (did I hear someone say | |||
// refactor??) | |||
// 1) no state in the cflow - we can use a counter *and* we have seen | |||
// this pointcut | |||
// before - so use the same counter as before. | |||
// 2) no state in the cflow - we can use a counter, but this is the | |||
// first time | |||
// we have seen this pointcut, so build the infrastructure. | |||
// 3) state in the cflow - we need to use a stack *and* we have seen | |||
// this pointcut | |||
// before - so share the stack. | |||
// 4) state in the cflow - we need to use a stack, but this is the first | |||
// time | |||
// we have seen this pointcut, so build the infrastructure. | |||
if (freeVars == null || freeVars.length == 0) { // No state, so don't | |||
// use a stack, use a | |||
// counter. | |||
ResolvedMember localCflowField = null; | |||
Object field = getCflowfield(xcut, concreteEntry, concreteAspect, "counter"); | |||
// Check if we have already got a counter for this cflow pointcut | |||
if (field != null) { | |||
localCflowField = (ResolvedMember) field; // Use the one we | |||
// already have | |||
} else { | |||
// Create a counter field in the aspect | |||
localCflowField = new ResolvedMemberImpl(Member.FIELD, concreteAspect, Modifier.STATIC | Modifier.PUBLIC | |||
| Modifier.FINAL, NameMangler.cflowCounter(xcut), UnresolvedType.forName(NameMangler.CFLOW_COUNTER_TYPE) | |||
.getSignature()); | |||
// Create type munger to add field to the aspect | |||
concreteAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport().makeCflowCounterFieldAdder( | |||
localCflowField)); | |||
// Create shadow munger to push stuff onto the stack | |||
concreteAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makeCflowEntry(world, concreteEntry, isBelow, | |||
localCflowField, freeVars == null ? 0 : freeVars.length, innerCflowEntries, inAspect)); | |||
putCflowfield(xcut, concreteEntry, concreteAspect, localCflowField, "counter"); // Remember | |||
// it | |||
} | |||
Pointcut ret = new ConcreteCflowPointcut(localCflowField, null, true); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} else { | |||
List slots = new ArrayList(); | |||
for (int i=0, len=freeVars.length; i < len; i++) { | |||
for (int i = 0, len = freeVars.length; i < len; i++) { | |||
int freeVar = freeVars[i]; | |||
// we don't need to keep state that isn't actually exposed to advice | |||
//??? this means that we will store some state that we won't actually use, optimize this later | |||
if (!bindings.hasKey(freeVar)) continue; | |||
// we don't need to keep state that isn't actually exposed to | |||
// advice | |||
// ??? this means that we will store some state that we won't | |||
// actually use, optimize this later | |||
if (!bindings.hasKey(freeVar)) | |||
continue; | |||
int formalIndex = bindings.get(freeVar); | |||
// We need to look in the right place for the type of the formal. Suppose the advice looks like this: | |||
// before(String s): somePointcut(*,s) | |||
// We need to look in the right place for the type of the | |||
// formal. Suppose the advice looks like this: | |||
// before(String s): somePointcut(*,s) | |||
// where the first argument in somePointcut is of type Number | |||
// for free variable 0 we want to ask the pointcut for the type of its first argument, if we only | |||
// ask the advice for the type of its first argument then we'll get the wrong type (pr86903) | |||
// for free variable 0 we want to ask the pointcut for the type | |||
// of its first argument, if we only | |||
// ask the advice for the type of its first argument then we'll | |||
// get the wrong type (pr86903) | |||
ResolvedPointcutDefinition enclosingDef = bindings.peekEnclosingDefinition(); | |||
ResolvedType formalType = null; | |||
// Is there a useful enclosing pointcut? | |||
if (enclosingDef!=null && enclosingDef.getParameterTypes().length>0) { | |||
if (enclosingDef != null && enclosingDef.getParameterTypes().length > 0) { | |||
formalType = enclosingDef.getParameterTypes()[freeVar].resolve(world); | |||
} else { | |||
formalType = bindings.getAdviceSignature().getParameterTypes()[formalIndex].resolve(world); | |||
} | |||
ConcreteCflowPointcut.Slot slot = | |||
new ConcreteCflowPointcut.Slot(formalIndex, formalType, i); | |||
ConcreteCflowPointcut.Slot slot = new ConcreteCflowPointcut.Slot(formalIndex, formalType, i); | |||
slots.add(slot); | |||
} | |||
ResolvedMember localCflowField = null; | |||
Object field = getCflowfield(xcut,concreteEntry,concreteAspect,"stack"); | |||
Object field = getCflowfield(xcut, concreteEntry, concreteAspect, "stack"); | |||
if (field != null) { | |||
localCflowField = (ResolvedMember)field; | |||
localCflowField = (ResolvedMember) field; | |||
} else { | |||
localCflowField = new ResolvedMemberImpl( | |||
Member.FIELD, concreteAspect, Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL, | |||
NameMangler.cflowStack(xcut), | |||
UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE).getSignature()); | |||
//System.out.println("adding field to: " + inAspect + " field " + cflowField); | |||
// add field and initializer to inAspect | |||
//XXX and then that info above needs to be mapped down here to help with | |||
//XXX getting the exposed state right | |||
concreteAspect.crosscuttingMembers.addConcreteShadowMunger( | |||
Advice.makeCflowEntry(world, concreteEntry, isBelow, localCflowField, freeVars.length, innerCflowEntries,inAspect)); | |||
concreteAspect.crosscuttingMembers.addTypeMunger( | |||
world.makeCflowStackFieldAdder(localCflowField)); | |||
putCflowfield(xcut,concreteEntry,concreteAspect,localCflowField,"stack"); | |||
} | |||
Pointcut ret = new ConcreteCflowPointcut(localCflowField, slots,false); | |||
localCflowField = new ResolvedMemberImpl(Member.FIELD, concreteAspect, Modifier.STATIC | Modifier.PUBLIC | |||
| Modifier.FINAL, NameMangler.cflowStack(xcut), UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE) | |||
.getSignature()); | |||
// System.out.println("adding field to: " + inAspect + " field " | |||
// + cflowField); | |||
// add field and initializer to inAspect | |||
// XXX and then that info above needs to be mapped down here to | |||
// help with | |||
// XXX getting the exposed state right | |||
concreteAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makeCflowEntry(world, concreteEntry, isBelow, | |||
localCflowField, freeVars.length, innerCflowEntries, inAspect)); | |||
concreteAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport() | |||
.makeCflowStackFieldAdder(localCflowField)); | |||
putCflowfield(xcut, concreteEntry, concreteAspect, localCflowField, "stack"); | |||
} | |||
Pointcut ret = new ConcreteCflowPointcut(localCflowField, slots, false); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} | |||
} | |||
private String getKey(Pointcut p,ResolvedType a,String stackOrCounter) { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(a.getName()); | |||
sb.append("::"); | |||
sb.append(p.toString()); | |||
sb.append("::"); | |||
sb.append(stackOrCounter); | |||
return sb.toString(); | |||
private String getKey(Pointcut p, ResolvedType a, String stackOrCounter) { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(a.getName()); | |||
sb.append("::"); | |||
sb.append(p.toString()); | |||
sb.append("::"); | |||
sb.append(stackOrCounter); | |||
return sb.toString(); | |||
} | |||
private Object getCflowfield(CrosscuttingMembers xcut, Pointcut pcutkey, ResolvedType concreteAspect,String stackOrCounter) { | |||
String key = getKey(pcutkey,concreteAspect,stackOrCounter); | |||
Object o =null; | |||
if (isBelow) o = xcut.getCflowBelowFields().get(key); | |||
else o = xcut.getCflowFields().get(key); | |||
//System.err.println("Retrieving for key "+key+" returning "+o); | |||
private Object getCflowfield(CrosscuttingMembers xcut, Pointcut pcutkey, ResolvedType concreteAspect, String stackOrCounter) { | |||
String key = getKey(pcutkey, concreteAspect, stackOrCounter); | |||
Object o = null; | |||
if (isBelow) | |||
o = xcut.getCflowBelowFields().get(key); | |||
else | |||
o = xcut.getCflowFields().get(key); | |||
// System.err.println("Retrieving for key "+key+" returning "+o); | |||
return o; | |||
} | |||
private void putCflowfield(CrosscuttingMembers xcut, Pointcut pcutkey,ResolvedType concreteAspect,Object o,String stackOrCounter) { | |||
String key = getKey(pcutkey,concreteAspect,stackOrCounter); | |||
//System.err.println("Storing cflow field for key"+key); | |||
private void putCflowfield(CrosscuttingMembers xcut, Pointcut pcutkey, ResolvedType concreteAspect, Object o, | |||
String stackOrCounter) { | |||
String key = getKey(pcutkey, concreteAspect, stackOrCounter); | |||
// System.err.println("Storing cflow field for key"+key); | |||
if (isBelow) { | |||
xcut.getCflowBelowFields().put(key,o); | |||
xcut.getCflowBelowFields().put(key, o); | |||
} else { | |||
xcut.getCflowFields().put(key,o); | |||
xcut.getCflowFields().put(key, o); | |||
} | |||
} | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this, data); | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this, data); | |||
} | |||
} |
@@ -10,7 +10,6 @@ | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.patterns; | |||
import java.io.DataOutputStream; | |||
@@ -39,133 +38,134 @@ import org.aspectj.weaver.ast.Test; | |||
import org.aspectj.weaver.bcel.BcelAccessForInlineMunger; | |||
public class PerCflow extends PerClause { | |||
private boolean isBelow; | |||
private Pointcut entry; | |||
private final boolean isBelow; | |||
private final Pointcut entry; | |||
public PerCflow(Pointcut entry, boolean isBelow) { | |||
this.entry = entry; | |||
this.isBelow = isBelow; | |||
} | |||
// ----- | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this,data); | |||
return visitor.visit(this, data); | |||
} | |||
public int couldMatchKinds() { | |||
return Shadow.ALL_SHADOW_KINDS_BITS; | |||
} | |||
public FuzzyBoolean fastMatch(FastMatchInfo type) { | |||
return FuzzyBoolean.MAYBE; | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
return FuzzyBoolean.YES; | |||
} | |||
public void resolveBindings(IScope scope, Bindings bindings) { | |||
// assert bindings == null; | |||
entry.resolve(scope); | |||
} | |||
public Pointcut parameterizeWith(Map typeVariableMap,World w) { | |||
PerCflow ret = new PerCflow(entry.parameterizeWith(typeVariableMap,w),isBelow); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} | |||
protected Test findResidueInternal(Shadow shadow, ExposedState state) { | |||
Expr myInstance = | |||
Expr.makeCallExpr(AjcMemberMaker.perCflowAspectOfMethod(inAspect), | |||
Expr.NONE, inAspect); | |||
state.setAspectInstance(myInstance); | |||
return Test.makeCall(AjcMemberMaker.perCflowHasAspectMethod(inAspect), Expr.NONE); | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
return FuzzyBoolean.YES; | |||
} | |||
public void resolveBindings(IScope scope, Bindings bindings) { | |||
// assert bindings == null; | |||
entry.resolve(scope); | |||
} | |||
public Pointcut parameterizeWith(Map typeVariableMap, World w) { | |||
PerCflow ret = new PerCflow(entry.parameterizeWith(typeVariableMap, w), isBelow); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} | |||
protected Test findResidueInternal(Shadow shadow, ExposedState state) { | |||
Expr myInstance = Expr.makeCallExpr(AjcMemberMaker.perCflowAspectOfMethod(inAspect), Expr.NONE, inAspect); | |||
state.setAspectInstance(myInstance); | |||
return Test.makeCall(AjcMemberMaker.perCflowHasAspectMethod(inAspect), Expr.NONE); | |||
} | |||
public PerClause concretize(ResolvedType inAspect) { | |||
PerCflow ret = new PerCflow(entry, isBelow); | |||
ret.inAspect = inAspect; | |||
if (inAspect.isAbstract()) return ret; | |||
Member cflowStackField = new ResolvedMemberImpl( | |||
Member.FIELD, inAspect, Modifier.STATIC|Modifier.PUBLIC|Modifier.FINAL, | |||
UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE), NameMangler.PERCFLOW_FIELD_NAME, UnresolvedType.NONE); | |||
if (inAspect.isAbstract()) | |||
return ret; | |||
Member cflowStackField = new ResolvedMemberImpl(Member.FIELD, inAspect, Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL, | |||
UnresolvedType.forName(NameMangler.CFLOW_STACK_TYPE), NameMangler.PERCFLOW_FIELD_NAME, UnresolvedType.NONE); | |||
World world = inAspect.getWorld(); | |||
CrosscuttingMembers xcut = inAspect.crosscuttingMembers; | |||
Collection previousCflowEntries = xcut.getCflowEntries(); | |||
Pointcut concreteEntry = entry.concretize(inAspect, inAspect, 0, null); //IntMap.EMPTY); | |||
Pointcut concreteEntry = entry.concretize(inAspect, inAspect, 0, null); // IntMap | |||
// . | |||
// EMPTY | |||
// ) | |||
// ; | |||
List innerCflowEntries = new ArrayList(xcut.getCflowEntries()); | |||
innerCflowEntries.removeAll(previousCflowEntries); | |||
xcut.addConcreteShadowMunger( | |||
Advice.makePerCflowEntry(world, concreteEntry, isBelow, cflowStackField, | |||
inAspect, innerCflowEntries)); | |||
//ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) { | |||
inAspect.crosscuttingMembers.addLateTypeMunger( | |||
inAspect.getWorld().makePerClauseAspect(inAspect, getKind()) | |||
); | |||
} | |||
//ATAJ inline around advice support - don't use a late munger to allow around inling for itself | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) { | |||
inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); | |||
} | |||
xcut.addConcreteShadowMunger(Advice.makePerCflowEntry(world, concreteEntry, isBelow, cflowStackField, inAspect, | |||
innerCflowEntries)); | |||
// ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) { | |||
inAspect.crosscuttingMembers.addLateTypeMunger(inAspect.getWorld().getWeavingSupport().makePerClauseAspect(inAspect, | |||
getKind())); | |||
} | |||
// ATAJ inline around advice support - don't use a late munger to allow | |||
// around inling for itself | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) { | |||
inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); | |||
} | |||
return ret; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
PERCFLOW.write(s); | |||
entry.write(s); | |||
s.writeBoolean(isBelow); | |||
writeLocation(s); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
PERCFLOW.write(s); | |||
entry.write(s); | |||
s.writeBoolean(isBelow); | |||
writeLocation(s); | |||
} | |||
public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
PerCflow ret = new PerCflow(Pointcut.read(s, context), s.readBoolean()); | |||
ret.readLocation(context, s); | |||
return ret; | |||
} | |||
public PerClause.Kind getKind() { | |||
return PERCFLOW; | |||
} | |||
public Pointcut getEntry(){ | |||
public Pointcut getEntry() { | |||
return entry; | |||
} | |||
public String toString() { | |||
return "percflow(" + inAspect + " on " + entry + ")"; | |||
} | |||
public String toDeclarationString() { | |||
if (isBelow) return "percflowbelow(" + entry + ")"; | |||
if (isBelow) | |||
return "percflowbelow(" + entry + ")"; | |||
return "percflow(" + entry + ")"; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerCflow)) return false; | |||
PerCflow pc = (PerCflow)other; | |||
return (pc.isBelow && isBelow) | |||
&& ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect)) | |||
&& ((pc.entry == null) ? (entry == null) : pc.entry.equals(entry)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37*result + (isBelow?0:1); | |||
result = 37*result + ((inAspect == null) ? 0 : inAspect.hashCode()); | |||
result = 37*result + ((entry == null) ? 0 : entry.hashCode()); | |||
return result; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerCflow)) | |||
return false; | |||
PerCflow pc = (PerCflow) other; | |||
return (pc.isBelow && isBelow) && ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect)) | |||
&& ((pc.entry == null) ? (entry == null) : pc.entry.equals(entry)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37 * result + (isBelow ? 0 : 1); | |||
result = 37 * result + ((inAspect == null) ? 0 : inAspect.hashCode()); | |||
result = 37 * result + ((entry == null) ? 0 : entry.hashCode()); | |||
return result; | |||
} | |||
} |
@@ -10,7 +10,6 @@ | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.patterns; | |||
import java.io.DataOutputStream; | |||
@@ -33,158 +32,157 @@ import org.aspectj.weaver.ast.Var; | |||
import org.aspectj.weaver.bcel.BcelAccessForInlineMunger; | |||
public class PerObject extends PerClause { | |||
private boolean isThis; | |||
private Pointcut entry; | |||
private final boolean isThis; | |||
private final Pointcut entry; | |||
private static final int thisKindSet; | |||
private static final int targetKindSet; | |||
static { | |||
int thisFlags = Shadow.ALL_SHADOW_KINDS_BITS; | |||
int targFlags = Shadow.ALL_SHADOW_KINDS_BITS; | |||
for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) { | |||
Shadow.Kind kind = Shadow.SHADOW_KINDS[i]; | |||
if (kind.neverHasThis()) thisFlags-=kind.bit; | |||
if (kind.neverHasTarget()) targFlags-=kind.bit; | |||
if (kind.neverHasThis()) | |||
thisFlags -= kind.bit; | |||
if (kind.neverHasTarget()) | |||
targFlags -= kind.bit; | |||
} | |||
thisKindSet = thisFlags; | |||
targetKindSet=targFlags; | |||
targetKindSet = targFlags; | |||
} | |||
public PerObject(Pointcut entry, boolean isThis) { | |||
this.entry = entry; | |||
this.isThis = isThis; | |||
} | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this,data); | |||
return visitor.visit(this, data); | |||
} | |||
public int couldMatchKinds() { | |||
return isThis ? thisKindSet : targetKindSet; | |||
} | |||
// ----- | |||
public FuzzyBoolean fastMatch(FastMatchInfo type) { | |||
return FuzzyBoolean.MAYBE; | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
//System.err.println("matches " + this + " ? " + shadow + ", " + shadow.hasTarget()); | |||
//??? could probably optimize this better by testing could match | |||
if (isThis) return FuzzyBoolean.fromBoolean(shadow.hasThis()); | |||
else return FuzzyBoolean.fromBoolean(shadow.hasTarget()); | |||
} | |||
public void resolveBindings(IScope scope, Bindings bindings) { | |||
// assert bindings == null; | |||
entry.resolve(scope); | |||
} | |||
public Pointcut parameterizeWith(Map typeVariableMap,World w) { | |||
PerObject ret = new PerObject(entry.parameterizeWith(typeVariableMap,w),isThis); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} | |||
private Var getVar(Shadow shadow) { | |||
return isThis ? shadow.getThisVar() : shadow.getTargetVar(); | |||
} | |||
protected Test findResidueInternal(Shadow shadow, ExposedState state) { | |||
Expr myInstance = | |||
Expr.makeCallExpr(AjcMemberMaker.perObjectAspectOfMethod(inAspect), | |||
new Expr[] {getVar(shadow)}, inAspect); | |||
state.setAspectInstance(myInstance); | |||
return Test.makeCall(AjcMemberMaker.perObjectHasAspectMethod(inAspect), | |||
new Expr[] { getVar(shadow) }); | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
// System.err.println("matches " + this + " ? " + shadow + ", " + | |||
// shadow.hasTarget()); | |||
// ??? could probably optimize this better by testing could match | |||
if (isThis) | |||
return FuzzyBoolean.fromBoolean(shadow.hasThis()); | |||
else | |||
return FuzzyBoolean.fromBoolean(shadow.hasTarget()); | |||
} | |||
public void resolveBindings(IScope scope, Bindings bindings) { | |||
// assert bindings == null; | |||
entry.resolve(scope); | |||
} | |||
public Pointcut parameterizeWith(Map typeVariableMap, World w) { | |||
PerObject ret = new PerObject(entry.parameterizeWith(typeVariableMap, w), isThis); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} | |||
private Var getVar(Shadow shadow) { | |||
return isThis ? shadow.getThisVar() : shadow.getTargetVar(); | |||
} | |||
protected Test findResidueInternal(Shadow shadow, ExposedState state) { | |||
Expr myInstance = Expr.makeCallExpr(AjcMemberMaker.perObjectAspectOfMethod(inAspect), new Expr[] { getVar(shadow) }, | |||
inAspect); | |||
state.setAspectInstance(myInstance); | |||
return Test.makeCall(AjcMemberMaker.perObjectHasAspectMethod(inAspect), new Expr[] { getVar(shadow) }); | |||
} | |||
public PerClause concretize(ResolvedType inAspect) { | |||
PerObject ret = new PerObject(entry, isThis); | |||
ret.inAspect = inAspect; | |||
if (inAspect.isAbstract()) return ret; | |||
if (inAspect.isAbstract()) | |||
return ret; | |||
World world = inAspect.getWorld(); | |||
Pointcut concreteEntry = entry.concretize(inAspect, inAspect, 0, null); | |||
//concreteEntry = new AndPointcut(this, concreteEntry); | |||
//concreteEntry.state = Pointcut.CONCRETE; | |||
inAspect.crosscuttingMembers.addConcreteShadowMunger( | |||
Advice.makePerObjectEntry(world, concreteEntry, isThis, inAspect)); | |||
// FIXME AV - don't use lateMunger here due to test "inheritance, around advice and abstract pointcuts" | |||
// see #75442 thread. Issue with weaving order. | |||
ResolvedTypeMunger munger = | |||
new PerObjectInterfaceTypeMunger(inAspect, concreteEntry); | |||
inAspect.crosscuttingMembers.addLateTypeMunger(world.concreteTypeMunger(munger, inAspect)); | |||
//ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) { | |||
inAspect.crosscuttingMembers.addLateTypeMunger( | |||
inAspect.getWorld().makePerClauseAspect(inAspect, getKind()) | |||
); | |||
} | |||
//ATAJ inline around advice support - don't use a late munger to allow around inling for itself | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) { | |||
inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); | |||
} | |||
// concreteEntry = new AndPointcut(this, concreteEntry); | |||
// concreteEntry.state = Pointcut.CONCRETE; | |||
inAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makePerObjectEntry(world, concreteEntry, isThis, inAspect)); | |||
// FIXME AV - don't use lateMunger here due to test | |||
// "inheritance, around advice and abstract pointcuts" | |||
// see #75442 thread. Issue with weaving order. | |||
ResolvedTypeMunger munger = new PerObjectInterfaceTypeMunger(inAspect, concreteEntry); | |||
inAspect.crosscuttingMembers.addLateTypeMunger(world.getWeavingSupport().concreteTypeMunger(munger, inAspect)); | |||
// ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) { | |||
inAspect.crosscuttingMembers.addLateTypeMunger(inAspect.getWorld().getWeavingSupport().makePerClauseAspect(inAspect, | |||
getKind())); | |||
} | |||
// ATAJ inline around advice support - don't use a late munger to allow | |||
// around inling for itself | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) { | |||
inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); | |||
} | |||
return ret; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
PEROBJECT.write(s); | |||
entry.write(s); | |||
s.writeBoolean(isThis); | |||
writeLocation(s); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
PEROBJECT.write(s); | |||
entry.write(s); | |||
s.writeBoolean(isThis); | |||
writeLocation(s); | |||
} | |||
public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
PerClause ret = new PerObject(Pointcut.read(s, context), s.readBoolean()); | |||
ret.readLocation(context, s); | |||
return ret; | |||
} | |||
public PerClause.Kind getKind() { | |||
return PEROBJECT; | |||
} | |||
public boolean isThis() { | |||
return isThis; | |||
} | |||
public boolean isThis() { | |||
return isThis; | |||
} | |||
public String toString() { | |||
return "per" + (isThis ? "this" : "target") + | |||
"(" + entry + ")"; | |||
return "per" + (isThis ? "this" : "target") + "(" + entry + ")"; | |||
} | |||
public String toDeclarationString() { | |||
return toString(); | |||
} | |||
public Pointcut getEntry() { | |||
return entry; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerObject)) return false; | |||
PerObject pc = (PerObject)other; | |||
return (pc.isThis && isThis) | |||
&& ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect)) | |||
&& ((pc.entry == null) ? (entry == null) : pc.entry.equals(entry)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37*result + (isThis?0:1); | |||
result = 37*result + ((inAspect == null) ? 0 : inAspect.hashCode()); | |||
result = 37*result + ((entry == null) ? 0 : entry.hashCode()); | |||
return result; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerObject)) | |||
return false; | |||
PerObject pc = (PerObject) other; | |||
return (pc.isThis && isThis) && ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect)) | |||
&& ((pc.entry == null) ? (entry == null) : pc.entry.equals(entry)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37 * result + (isThis ? 0 : 1); | |||
result = 37 * result + ((inAspect == null) ? 0 : inAspect.hashCode()); | |||
result = 37 * result + ((entry == null) ? 0 : entry.hashCode()); | |||
return result; | |||
} | |||
} |
@@ -10,7 +10,6 @@ | |||
* PARC initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.patterns; | |||
import java.io.DataOutputStream; | |||
@@ -32,15 +31,15 @@ import org.aspectj.weaver.bcel.BcelAccessForInlineMunger; | |||
public class PerSingleton extends PerClause { | |||
private ResolvedMember perSingletonAspectOfMethod; | |||
private ResolvedMember perSingletonAspectOfMethod; | |||
public PerSingleton() { | |||
} | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this,data); | |||
return visitor.visit(this, data); | |||
} | |||
public int couldMatchKinds() { | |||
return Shadow.ALL_SHADOW_KINDS_BITS; | |||
} | |||
@@ -48,126 +47,128 @@ public class PerSingleton extends PerClause { | |||
public FuzzyBoolean fastMatch(FastMatchInfo type) { | |||
return FuzzyBoolean.YES; | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
return FuzzyBoolean.YES; | |||
} | |||
public void resolveBindings(IScope scope, Bindings bindings) { | |||
// this method intentionally left blank | |||
} | |||
public Pointcut parameterizeWith(Map typeVariableMap,World w) { | |||
return this; | |||
} | |||
public Test findResidueInternal(Shadow shadow, ExposedState state) { | |||
// TODO: the commented code is for slow Aspects.aspectOf() style - keep or remove | |||
// | |||
// Expr myInstance = | |||
// Expr.makeCallExpr(AjcMemberMaker.perSingletonAspectOfMethod(inAspect), | |||
// Expr.NONE, inAspect); | |||
// | |||
// state.setAspectInstance(myInstance); | |||
// | |||
// // we have no test | |||
// // a NoAspectBoundException will be thrown if we need an instance of this | |||
// // aspect before we are bound | |||
// return Literal.TRUE; | |||
// if (!Ajc5MemberMaker.isSlowAspect(inAspect)) { | |||
if (perSingletonAspectOfMethod==null) { | |||
// Build this just once | |||
perSingletonAspectOfMethod = AjcMemberMaker.perSingletonAspectOfMethod(inAspect); | |||
} | |||
Expr myInstance = Expr.makeCallExpr(perSingletonAspectOfMethod, Expr.NONE, inAspect); | |||
state.setAspectInstance(myInstance); | |||
// we have no test | |||
// a NoAspectBoundException will be thrown if we need an instance of this | |||
// aspect before we are bound | |||
return Literal.TRUE; | |||
// } else { | |||
// CallExpr callAspectOf =Expr.makeCallExpr( | |||
// Ajc5MemberMaker.perSingletonAspectOfMethod(inAspect), | |||
// new Expr[]{ | |||
// Expr.makeStringConstantExpr(inAspect.getName(), inAspect), | |||
// //FieldGet is using ResolvedType and I don't need that here | |||
// new FieldGetOn(Member.ajClassField, shadow.getEnclosingType()) | |||
// }, | |||
// inAspect | |||
// ); | |||
// Expr castedCallAspectOf = new CastExpr(callAspectOf, inAspect.getName()); | |||
// state.setAspectInstance(castedCallAspectOf); | |||
// return Literal.TRUE; | |||
// } | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
return FuzzyBoolean.YES; | |||
} | |||
public void resolveBindings(IScope scope, Bindings bindings) { | |||
// this method intentionally left blank | |||
} | |||
public Pointcut parameterizeWith(Map typeVariableMap, World w) { | |||
return this; | |||
} | |||
public Test findResidueInternal(Shadow shadow, ExposedState state) { | |||
// TODO: the commented code is for slow Aspects.aspectOf() style - keep | |||
// or remove | |||
// | |||
// Expr myInstance = | |||
//Expr.makeCallExpr(AjcMemberMaker.perSingletonAspectOfMethod(inAspect), | |||
// Expr.NONE, inAspect); | |||
// | |||
// state.setAspectInstance(myInstance); | |||
// | |||
// // we have no test | |||
// // a NoAspectBoundException will be thrown if we need an instance of | |||
// this | |||
// // aspect before we are bound | |||
// return Literal.TRUE; | |||
// if (!Ajc5MemberMaker.isSlowAspect(inAspect)) { | |||
if (perSingletonAspectOfMethod == null) { | |||
// Build this just once | |||
perSingletonAspectOfMethod = AjcMemberMaker.perSingletonAspectOfMethod(inAspect); | |||
} | |||
Expr myInstance = Expr.makeCallExpr(perSingletonAspectOfMethod, Expr.NONE, inAspect); | |||
state.setAspectInstance(myInstance); | |||
// we have no test | |||
// a NoAspectBoundException will be thrown if we need an instance of | |||
// this | |||
// aspect before we are bound | |||
return Literal.TRUE; | |||
// } else { | |||
// CallExpr callAspectOf =Expr.makeCallExpr( | |||
// Ajc5MemberMaker.perSingletonAspectOfMethod(inAspect), | |||
// new Expr[]{ | |||
// Expr.makeStringConstantExpr(inAspect.getName(), inAspect), | |||
// //FieldGet is using ResolvedType and I don't need that here | |||
// new FieldGetOn(Member.ajClassField, shadow.getEnclosingType()) | |||
// }, | |||
// inAspect | |||
// ); | |||
// Expr castedCallAspectOf = new CastExpr(callAspectOf, | |||
// inAspect.getName()); | |||
// state.setAspectInstance(castedCallAspectOf); | |||
// return Literal.TRUE; | |||
// } | |||
} | |||
public PerClause concretize(ResolvedType inAspect) { | |||
PerSingleton ret = new PerSingleton(); | |||
ret.copyLocationFrom(this); | |||
ret.copyLocationFrom(this); | |||
ret.inAspect = inAspect; | |||
//ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) { | |||
//TODO will those change be ok if we add a serializable aspect ? | |||
// dig: "can't be Serializable/Cloneable unless -XserializableAspects" | |||
if (getKind()==SINGLETON) { // pr149560 | |||
inAspect.crosscuttingMembers.addTypeMunger( | |||
inAspect.getWorld().makePerClauseAspect(inAspect, getKind()) | |||
); | |||
} else { | |||
inAspect.crosscuttingMembers.addLateTypeMunger( | |||
inAspect.getWorld().makePerClauseAspect(inAspect, getKind()) | |||
); | |||
} | |||
} | |||
//ATAJ inline around advice support | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) { | |||
inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); | |||
} | |||
return ret; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
SINGLETON.write(s); | |||
writeLocation(s); | |||
} | |||
// ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) { | |||
// TODO will those change be ok if we add a serializable aspect ? | |||
// dig: | |||
// "can't be Serializable/Cloneable unless -XserializableAspects" | |||
if (getKind() == SINGLETON) { // pr149560 | |||
inAspect.crosscuttingMembers.addTypeMunger(inAspect.getWorld().getWeavingSupport().makePerClauseAspect(inAspect, | |||
getKind())); | |||
} else { | |||
inAspect.crosscuttingMembers.addLateTypeMunger(inAspect.getWorld().getWeavingSupport().makePerClauseAspect( | |||
inAspect, getKind())); | |||
} | |||
} | |||
// ATAJ inline around advice support | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) { | |||
inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); | |||
} | |||
return ret; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
SINGLETON.write(s); | |||
writeLocation(s); | |||
} | |||
public static PerClause readPerClause(VersionedDataInputStream s, ISourceContext context) throws IOException { | |||
PerSingleton ret = new PerSingleton(); | |||
ret.readLocation(context, s); | |||
return ret; | |||
} | |||
public PerClause.Kind getKind() { | |||
return SINGLETON; | |||
} | |||
public String toString() { | |||
return "persingleton(" + inAspect + ")"; | |||
} | |||
public String toDeclarationString() { | |||
return ""; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerSingleton)) return false; | |||
PerSingleton pc = (PerSingleton)other; | |||
return ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37*result + ((inAspect == null) ? 0 : inAspect.hashCode()); | |||
return result; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerSingleton)) | |||
return false; | |||
PerSingleton pc = (PerSingleton) other; | |||
return ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37 * result + ((inAspect == null) ? 0 : inAspect.hashCode()); | |||
return result; | |||
} | |||
} |
@@ -35,37 +35,36 @@ import org.aspectj.weaver.ast.Literal; | |||
import org.aspectj.weaver.ast.Test; | |||
import org.aspectj.weaver.bcel.BcelAccessForInlineMunger; | |||
// 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 int kindSet = Shadow.ALL_SHADOW_KINDS_BITS; | |||
public TypePattern getTypePattern() { | |||
return typePattern; | |||
} | |||
public PerTypeWithin(TypePattern p) { | |||
this.typePattern = p; | |||
typePattern = p; | |||
} | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this,data); | |||
return visitor.visit(this, data); | |||
} | |||
public int couldMatchKinds() { | |||
return kindSet; | |||
} | |||
public Pointcut parameterizeWith(Map typeVariableMap,World w) { | |||
PerTypeWithin ret = new PerTypeWithin(typePattern.parameterizeWith(typeVariableMap,w)); | |||
public Pointcut parameterizeWith(Map typeVariableMap, World w) { | |||
PerTypeWithin ret = new PerTypeWithin(typePattern.parameterizeWith(typeVariableMap, w)); | |||
ret.copyLocationFrom(this); | |||
return ret; | |||
} | |||
// ----- | |||
public FuzzyBoolean fastMatch(FastMatchInfo info) { | |||
if (typePattern.annotationPattern instanceof AnyAnnotationTypePattern) { | |||
@@ -73,133 +72,138 @@ public class PerTypeWithin extends PerClause { | |||
} | |||
return FuzzyBoolean.MAYBE; | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
ResolvedType enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true); | |||
if (enclosingType.isMissing()) { | |||
//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); | |||
} | |||
// See pr106554 - we can't put advice calls in an interface when the advice is defined | |||
// in a pertypewithin aspect - the JPs only exist in the static initializer and can't | |||
// call the localAspectOf() method. | |||
if (enclosingType.isInterface()) return FuzzyBoolean.NO; | |||
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; | |||
} | |||
protected FuzzyBoolean matchInternal(Shadow shadow) { | |||
ResolvedType enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(), true); | |||
if (enclosingType.isMissing()) { | |||
// 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); | |||
} | |||
// See pr106554 - we can't put advice calls in an interface when the | |||
// advice is defined | |||
// in a pertypewithin aspect - the JPs only exist in the static | |||
// initializer and can't | |||
// call the localAspectOf() method. | |||
if (enclosingType.isInterface()) | |||
return FuzzyBoolean.NO; | |||
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(ResolvedType inAspect) { | |||
PerTypeWithin ret = new PerTypeWithin(typePattern); | |||
ret.copyLocationFrom(this); | |||
ret.inAspect = inAspect; | |||
if (inAspect.isAbstract()) return ret; | |||
if (inAspect.isAbstract()) | |||
return ret; | |||
World world = inAspect.getWorld(); | |||
SignaturePattern sigpat = new SignaturePattern( | |||
Member.STATIC_INITIALIZATION, | |||
ModifiersPattern.ANY, | |||
TypePattern.ANY, | |||
TypePattern.ANY,//typePattern, | |||
NamePattern.ANY, | |||
TypePatternList.ANY, | |||
ThrowsPattern.ANY, | |||
AnnotationTypePattern.ANY | |||
); | |||
Pointcut staticInitStar = new KindedPointcut(Shadow.StaticInitialization,sigpat); | |||
Pointcut withinTp= new WithinPointcut(typePattern); | |||
Pointcut andPcut = new AndPointcut(staticInitStar,withinTp); | |||
// We want the pointcut to be 'staticinitialization(*) && within(<typepattern>' - | |||
// we *cannot* shortcut this to staticinitialization(<typepattern>) because it | |||
SignaturePattern sigpat = new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY, TypePattern.ANY, | |||
TypePattern.ANY,// typePattern, | |||
NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY, AnnotationTypePattern.ANY); | |||
Pointcut staticInitStar = new KindedPointcut(Shadow.StaticInitialization, sigpat); | |||
Pointcut withinTp = new WithinPointcut(typePattern); | |||
Pointcut andPcut = new AndPointcut(staticInitStar, withinTp); | |||
// We want the pointcut to be 'staticinitialization(*) && | |||
// within(<typepattern>' - | |||
// we *cannot* shortcut this to staticinitialization(<typepattern>) | |||
// because it | |||
// doesnt mean the same thing. | |||
// This munger will initialize the aspect instance field in the matched type | |||
// This munger will initialize the aspect instance field in the matched | |||
// type | |||
inAspect.crosscuttingMembers.addConcreteShadowMunger(Advice.makePerTypeWithinEntry(world, andPcut, inAspect)); | |||
ResolvedTypeMunger munger = new PerTypeWithinTargetTypeMunger(inAspect, ret); | |||
inAspect.crosscuttingMembers.addTypeMunger(world.concreteTypeMunger(munger, inAspect)); | |||
inAspect.crosscuttingMembers.addTypeMunger(world.getWeavingSupport().concreteTypeMunger(munger, inAspect)); | |||
//ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) { | |||
inAspect.crosscuttingMembers.addLateTypeMunger( | |||
inAspect.getWorld().makePerClauseAspect(inAspect, getKind()) | |||
); | |||
} | |||
// ATAJ: add a munger to add the aspectOf(..) to the @AJ aspects | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.isAbstract()) { | |||
inAspect.crosscuttingMembers.addLateTypeMunger(inAspect.getWorld().getWeavingSupport().makePerClauseAspect(inAspect, | |||
getKind())); | |||
} | |||
//ATAJ inline around advice support - don't use a late munger to allow around inling for itself | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) { | |||
inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); | |||
} | |||
// ATAJ inline around advice support - don't use a late munger to allow | |||
// around inling for itself | |||
if (inAspect.isAnnotationStyleAspect() && !inAspect.getWorld().isXnoInline()) { | |||
inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect)); | |||
} | |||
return ret; | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
PERTYPEWITHIN.write(s); | |||
typePattern.write(s); | |||
writeLocation(s); | |||
} | |||
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+")"; | |||
return "pertypewithin(" + typePattern + ")"; | |||
} | |||
public String toDeclarationString() { | |||
return toString(); | |||
} | |||
private FuzzyBoolean isWithinType(ResolvedType type) { | |||
while (type != null) { | |||
if (typePattern.matchesStatically(type)) { | |||
@@ -209,19 +213,20 @@ public class PerTypeWithin extends PerClause { | |||
} | |||
return FuzzyBoolean.NO; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerTypeWithin)) return false; | |||
PerTypeWithin pc = (PerTypeWithin)other; | |||
return ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect)) | |||
&& ((pc.typePattern == null) ? (typePattern == null) : pc.typePattern.equals(typePattern)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37*result + ((inAspect == null) ? 0 : inAspect.hashCode()); | |||
result = 37*result + ((typePattern == null) ? 0 : typePattern.hashCode()); | |||
return result; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof PerTypeWithin)) | |||
return false; | |||
PerTypeWithin pc = (PerTypeWithin) other; | |||
return ((pc.inAspect == null) ? (inAspect == null) : pc.inAspect.equals(inAspect)) | |||
&& ((pc.typePattern == null) ? (typePattern == null) : pc.typePattern.equals(typePattern)); | |||
} | |||
public int hashCode() { | |||
int result = 17; | |||
result = 37 * result + ((inAspect == null) ? 0 : inAspect.hashCode()); | |||
result = 37 * result + ((typePattern == null) ? 0 : typePattern.hashCode()); | |||
return result; | |||
} | |||
} |
@@ -15,47 +15,43 @@ import org.aspectj.bridge.AbortException; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.IMessageHandler; | |||
import org.aspectj.util.LangUtil; | |||
import org.aspectj.weaver.Advice; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ConcreteTypeMunger; | |||
import org.aspectj.weaver.Member; | |||
import org.aspectj.weaver.IWeavingSupport; | |||
import org.aspectj.weaver.ReferenceType; | |||
import org.aspectj.weaver.ReferenceTypeDelegate; | |||
import org.aspectj.weaver.ResolvedMember; | |||
import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.ResolvedTypeMunger; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.WeakClassLoaderReference; | |||
import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.AjAttribute.AdviceAttribute; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
import org.aspectj.weaver.patterns.PerClause.Kind; | |||
/** | |||
* A ReflectionWorld is used solely for purposes of type resolution based on | |||
* the runtime classpath (java.lang.reflect). It does not support weaving operations | |||
* A ReflectionWorld is used solely for purposes of type resolution based on the | |||
* runtime classpath (java.lang.reflect). It does not support weaving operations | |||
* (creation of mungers etc..). | |||
* | |||
* | |||
*/ | |||
public class ReflectionWorld extends World implements IReflectionWorld { | |||
private WeakClassLoaderReference classLoaderReference; | |||
private AnnotationFinder annotationFinder; | |||
private ReflectionWorld() { | |||
// super(); | |||
// this.setMessageHandler(new ExceptionBasedMessageHandler()); | |||
// setBehaveInJava5Way(LangUtil.is15VMOrGreater()); | |||
// this.classLoaderReference = new WeakClassLoaderReference(ReflectionWorld.class.getClassLoader()); | |||
// this.annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this); | |||
// super(); | |||
// this.setMessageHandler(new ExceptionBasedMessageHandler()); | |||
// setBehaveInJava5Way(LangUtil.is15VMOrGreater()); | |||
// this.classLoaderReference = new | |||
// WeakClassLoaderReference(ReflectionWorld.class.getClassLoader()); | |||
// this.annotationFinder = | |||
// makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), | |||
// this); | |||
} | |||
public ReflectionWorld(ClassLoader aClassLoader) { | |||
super(); | |||
this.setMessageHandler(new ExceptionBasedMessageHandler()); | |||
setBehaveInJava5Way(LangUtil.is15VMOrGreater()); | |||
this.classLoaderReference = new WeakClassLoaderReference(aClassLoader); | |||
this.annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this); | |||
classLoaderReference = new WeakClassLoaderReference(aClassLoader); | |||
annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this); | |||
} | |||
public static AnnotationFinder makeAnnotationFinderIfAny(ClassLoader loader, World world) { | |||
@@ -67,88 +63,44 @@ public class ReflectionWorld extends World implements IReflectionWorld { | |||
annotationFinder.setClassLoader(loader); | |||
annotationFinder.setWorld(world); | |||
} | |||
} catch(ClassNotFoundException ex) { | |||
} catch (ClassNotFoundException ex) { | |||
// must be on 1.4 or earlier | |||
} catch(IllegalAccessException ex) { | |||
} catch (IllegalAccessException ex) { | |||
// not so good | |||
throw new BCException("AspectJ internal error",ex); | |||
} catch(InstantiationException ex) { | |||
throw new BCException("AspectJ internal error",ex); | |||
throw new BCException("AspectJ internal error", ex); | |||
} catch (InstantiationException ex) { | |||
throw new BCException("AspectJ internal error", ex); | |||
} | |||
return annotationFinder; | |||
} | |||
public ClassLoader getClassLoader() { | |||
return this.classLoaderReference.getClassLoader(); | |||
return classLoaderReference.getClassLoader(); | |||
} | |||
public AnnotationFinder getAnnotationFinder() { | |||
return this.annotationFinder; | |||
return annotationFinder; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.reflect.IReflectionWorld#resolve(java.lang.Class) | |||
*/ | |||
public ResolvedType resolve(Class aClass) { | |||
return resolve(this, aClass); | |||
} | |||
public static ResolvedType resolve(World world, Class aClass) { | |||
// classes that represent arrays return a class name that is the signature of the array type, ho-hum... | |||
// classes that represent arrays return a class name that is the | |||
// signature of the array type, ho-hum... | |||
String className = aClass.getName(); | |||
if (aClass.isArray()) { | |||
return world.resolve(UnresolvedType.forSignature(className.replace('.','/'))); | |||
} | |||
else{ | |||
return world.resolve(UnresolvedType.forSignature(className.replace('.', '/'))); | |||
} else { | |||
return world.resolve(className); | |||
} | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.World#resolveDelegate(org.aspectj.weaver.ReferenceType) | |||
*/ | |||
protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) { | |||
return ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, this.classLoaderReference.getClassLoader()); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.World#createAdviceMunger(org.aspectj.weaver.AjAttribute.AdviceAttribute, org.aspectj.weaver.patterns.Pointcut, org.aspectj.weaver.Member) | |||
*/ | |||
public Advice createAdviceMunger(AdviceAttribute attribute, | |||
Pointcut pointcut, Member signature) { | |||
throw new UnsupportedOperationException("Cannot create advice munger in ReflectionWorld"); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.World#makeCflowStackFieldAdder(org.aspectj.weaver.ResolvedMember) | |||
*/ | |||
public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) { | |||
throw new UnsupportedOperationException("Cannot create cflow stack in ReflectionWorld"); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.World#makeCflowCounterFieldAdder(org.aspectj.weaver.ResolvedMember) | |||
*/ | |||
public ConcreteTypeMunger makeCflowCounterFieldAdder( | |||
ResolvedMember cflowField) { | |||
throw new UnsupportedOperationException("Cannot create cflow counter in ReflectionWorld"); | |||
} | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.World#makePerClauseAspect(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.patterns.PerClause.Kind) | |||
*/ | |||
public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, Kind kind) { | |||
throw new UnsupportedOperationException("Cannot create per clause in ReflectionWorld"); | |||
protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) { | |||
return ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, classLoaderReference.getClassLoader()); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.aspectj.weaver.World#concreteTypeMunger(org.aspectj.weaver.ResolvedTypeMunger, org.aspectj.weaver.ResolvedType) | |||
*/ | |||
public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, | |||
ResolvedType aspectType) { | |||
throw new UnsupportedOperationException("Cannot create type munger in ReflectionWorld"); | |||
} | |||
public static class ReflectionWorldException extends RuntimeException { | |||
private static final long serialVersionUID = -3432261918302793005L; | |||
@@ -157,7 +109,7 @@ public class ReflectionWorld extends World implements IReflectionWorld { | |||
super(message); | |||
} | |||
} | |||
private static class ExceptionBasedMessageHandler implements IMessageHandler { | |||
public boolean handleMessage(IMessage message) throws AbortException { | |||
@@ -179,7 +131,11 @@ public class ReflectionWorld extends World implements IReflectionWorld { | |||
public void ignore(org.aspectj.bridge.IMessage.Kind kind) { | |||
// empty | |||
} | |||
} | |||
public IWeavingSupport getWeavingSupport() { | |||
return null; | |||
} | |||
} |