Browse Source

splitting - move world weaver specific operations to an interface

tags/PRE_251277
aclement 15 years ago
parent
commit
410753eaa6

+ 41
- 42
weaver/src/org/aspectj/weaver/AbstractReferenceTypeDelegate.java View File

@@ -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;
}


}

+ 37
- 20
weaver/src/org/aspectj/weaver/Advice.java View File

@@ -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
;

}

+ 237
- 215
weaver/src/org/aspectj/weaver/AjAttribute.java View File

@@ -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;
}

}

}

}

+ 45
- 26
weaver/src/org/aspectj/weaver/CrosscuttingMembers.java View File

@@ -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;

+ 42
- 0
weaver/src/org/aspectj/weaver/IWeavingSupport.java View File

@@ -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);
}

+ 204
- 125
weaver/src/org/aspectj/weaver/World.java View File

@@ -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
*/

+ 17
- 12
weaver/src/org/aspectj/weaver/bcel/BcelMethod.java View File

@@ -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

+ 62
- 0
weaver/src/org/aspectj/weaver/bcel/BcelWeavingSupport.java View File

@@ -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);
}
}

+ 57
- 141
weaver/src/org/aspectj/weaver/bcel/BcelWorld.java View File

@@ -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;
}

}

+ 182
- 163
weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java View File

@@ -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);
}

}

+ 87
- 87
weaver/src/org/aspectj/weaver/patterns/PerCflow.java View File

@@ -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;
}
}

+ 99
- 101
weaver/src/org/aspectj/weaver/patterns/PerObject.java View File

@@ -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;
}
}

+ 105
- 104
weaver/src/org/aspectj/weaver/patterns/PerSingleton.java View File

@@ -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;
}

}

+ 129
- 124
weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java View File

@@ -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;
}

}

+ 40
- 84
weaver/src/org/aspectj/weaver/reflect/ReflectionWorld.java View File

@@ -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;
}

}

Loading…
Cancel
Save