public abstract class Advice extends ShadowMunger {
- protected AjAttribute.AdviceAttribute attribute; // the pointcut field is
- // ignored
-
- protected AdviceKind kind; // alias of attribute.getKind()
+ protected AjAttribute.AdviceAttribute attribute;
+ protected transient AdviceKind kind; // alias for attribute.getKind()
protected Member signature;
- protected boolean hasMatchedAtLeastOnce = false;
// 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 int nFreeVars; // just for cflow*Entry kinds
+ // Just for Cflow*entry kinds
+ protected List innerCflowEntries = Collections.EMPTY_LIST;
+ protected int nFreeVars;
protected TypePattern exceptionType; // just for Softener kind
// signature types
protected UnresolvedType[] bindingParameterTypes;
+ protected boolean hasMatchedAtLeastOnce = false;
+
protected List/* Lint.Kind */suppressedLintKinds = null; // based on
// annotations on
// this advice
}
public Advice(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member signature) {
- super(pointcut, attribute.getStart(), attribute.getEnd(), attribute.getSourceContext());
+ super(pointcut, attribute.getStart(), attribute.getEnd(), attribute.getSourceContext(), ShadowMungerAdvice);
this.attribute = attribute;
- kind = attribute.getKind(); // alias
+ this.kind = attribute.getKind(); // alias
this.signature = signature;
if (signature != null) {
bindingParameterTypes = signature.getParameterTypes();
return matches;
} else if (hasExtraParameter() && kind == AdviceKind.AfterThrowing) { // pr119749
ResolvedType exceptionType = getExtraParameterType().resolve(world);
- if (!exceptionType.isCheckedException())
+ if (!exceptionType.isCheckedException()) {
return true;
+ }
UnresolvedType[] shadowThrows = shadow.getSignature().getExceptions(world);
boolean matches = false;
for (int i = 0; i < shadowThrows.length && !matches; i++) {
ResolvedType type = shadowThrows[i].resolve(world);
- if (exceptionType.isAssignableFrom(type))
+ if (exceptionType.isAssignableFrom(type)) {
matches = true;
+ }
}
return matches;
} else if (kind == AdviceKind.PerTargetEntry) {
public static int countOnes(int bits) {
int ret = 0;
while (bits != 0) {
- if ((bits & 1) != 0)
+ if ((bits & 1) != 0) {
ret += 1;
+ }
bits = bits >> 1;
}
return ret;
public String[] getBaseParameterNames(World world) {
String[] allNames = getSignature().getParameterNames(world);
int extras = getExtraParameterCount();
- if (extras == 0)
+ if (extras == 0) {
return allNames;
+ }
String[] result = new String[getBaseParameterCount()];
for (int i = 0; i < result.length; i++) {
result[i] = allNames[i];
// XXX this perhaps ought to take account of the other fields in advice ...
public boolean equals(Object other) {
- if (!(other instanceof Advice))
+ if (!(other instanceof Advice)) {
return false;
+ }
Advice o = (Advice) other;
return o.kind.equals(kind) && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut))
&& ((o.signature == null) ? (signature == null) : o.signature.equals(signature));
public static final int ThisEnclosingJoinPointStaticPart = 0x08;
public static final int ParameterMask = 0x0f;
// For an if pointcut, this indicates it is hard wired to access a constant of either true or false
- public static final int ConstantReference = 0x10;
+ public static final int ConstantReference = 0x10;
// When the above flag is set, this indicates whether it is true or false
- public static final int ConstantValue = 0x20;
+ public static final int ConstantValue = 0x20;
public static final int CanInline = 0x40;
// for testing only
*/
public class Checker extends ShadowMunger {
- private final String message;
- private final boolean isError; // if not error then it is a warning
+ private boolean isError; // if not error then it is a warning
+ private String message;
private volatile int hashCode = -1;
+ private Checker() {
+ }
+
/**
- * Create a Checker for a deow.
+ * Create a Checker for a declare error or declare warning.
*
- * @param deow the declare error or warning for which to create the checker munger
+ * @param deow the declare error or declare warning for which to create the checker munger
*/
public Checker(DeclareErrorOrWarning deow) {
- super(deow.getPointcut(), deow.getStart(), deow.getEnd(), deow.getSourceContext());
+ super(deow.getPointcut(), deow.getStart(), deow.getEnd(), deow.getSourceContext(), ShadowMungerDeow);
this.message = deow.getMessage();
this.isError = deow.isError();
}
/**
- * Only used when filling in a parameterized Checker.
- *
- * @param pc the pointcut
- * @param start the start
- * @param end the end
- * @param context the source context
- * @param message the message string
- * @param isError whether it is an error or just a warning
+ * Only used when filling in a parameterized Checker
*/
- private Checker(Pointcut pc, int start, int end, ISourceContext context, String message, boolean isError) {
- super(pc, start, end, context);
+ private Checker(Pointcut pointcut, int start, int end, ISourceContext context, String message, boolean isError) {
+ super(pointcut, start, end, context, ShadowMungerDeow);
this.message = message;
this.isError = isError;
}
return isError;
}
- /**
- * Not supported for a Checker
- */
+ public String getMessage() {
+ return this.message;
+ }
+
public void specializeOn(Shadow shadow) {
- throw new RuntimeException("illegal state");
+ throw new IllegalStateException("Cannot call specializeOn(...) for a Checker");
}
- /**
- * Not supported for a Checker
- */
public boolean implementOn(Shadow shadow) {
- throw new RuntimeException("illegal state");
+ throw new IllegalStateException("Cannot call implementOn(...) for a Checker");
}
/**
- * Determine if the Checker matches at a shadow. If it does then we can immediately report the message. There (currently) can
+ * Determine if the Checker matches at a shadow. If it does then we can immediately report the message. Currently, there can
* never be a non-statically determinable match.
*
* @param shadow the shadow which to match against
return false;
}
- // FIXME what the hell?
+ // implementation for PartialOrder.PartialComparable
public int compareTo(Object other) {
return 0;
}
- // FIXME Alex: ATAJ is that ok in all cases ?
- /**
- * Default to true
- *
- * @return
- */
public boolean mustCheckExceptions() {
return true;
}
return Collections.EMPTY_LIST;
}
- // FIXME this perhaps ought to take account of the other fields in advice ...
+ // FIXME this perhaps ought to take account of the other fields in advice (use super.equals?)
public boolean equals(Object other) {
if (!(other instanceof Checker)) {
return false;
return hashCode;
}
+ /**
+ * Parameterize the Checker by parameterizing the pointcut
+ */
public ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap) {
Checker ret = new Checker(this.pointcut.parameterizeWith(typeVariableMap, declaringType.getWorld()), this.start, this.end,
this.sourceContext, this.message, this.isError);
}
/**
- * Concretize this Checker by concretizing the pointcut.
- *
+ * Concretize this Checker by concretizing the pointcut
*/
public ShadowMunger concretize(ResolvedType theAspect, World world, PerClause clause) {
this.pointcut = this.pointcut.concretize(theAspect, getDeclaringType(), 0, this);
return this;
}
- public String getMessage() {
- return this.message;
- }
-
+ // public void write(DataOutputStream stream) throws IOException {
+ // super.write(stream);
+ // stream.writeBoolean(isError);
+ // stream.writeUTF(message);
+ // }
+ //
+ // public static Checker read(DataInputStream stream, World world) throws IOException {
+ // Checker checker = new Checker();
+ // checker.isError = stream.readBoolean();
+ // checker.message = stream.readUTF();
+ // return checker;
+ // }
}
}
private void addShadowMunger(ShadowMunger m) {
- if (inAspect.isAbstract())
- return; // we don't do mungers for abstract aspects
+ if (inAspect.isAbstract()) {
+ return; // mungers for abstract aspects are not added
+ }
addConcreteShadowMunger(m.concretize(inAspect, world, perClause));
}
/* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * Copyright (c) 2002-2009 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
package org.aspectj.weaver;
+import java.io.DataOutputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
* This holds on to all CrosscuttingMembers for a world. It handles management of change.
*
* @author Jim Hugunin
+ * @author Andy Clement
*/
public class CrosscuttingMembersSet {
+
+ private static Trace trace = TraceFactory.getTraceFactory().getTrace(CrosscuttingMembersSet.class);
+
+ private transient World world;
+
// FIXME AV - ? we may need a sequencedHashMap there to ensure source based precedence for @AJ advice
private final Map /* ResolvedType (the aspect) > CrosscuttingMembers */members = new HashMap();
- private World world;
- private List shadowMungers = null;
+ // List of things to be verified once the type system is 'complete'
+ private transient List /* IVerificationRequired */verificationList = null;
+
+ private List /* ShadowMunger */shadowMungers = null;
private List typeMungers = null;
private List lateTypeMungers = null;
private List declareSofts = null;
private List declareParents = null;
private List declareAnnotationOnTypes = null;
private List declareAnnotationOnFields = null;
- private List declareAnnotationOnMethods = null; // includes ctors
+ private List declareAnnotationOnMethods = null; // includes constructors
private List declareDominates = null;
private boolean changedSinceLastReset = false;
- private List /* IVerificationRequired */verificationList = null; // List of things to be verified once the type system is
- // 'complete'
-
- private static Trace trace = TraceFactory.getTraceFactory().getTrace(CrosscuttingMembersSet.class);
-
public CrosscuttingMembersSet(World world) {
this.world = world;
}
ResolvedType element = (ResolvedType) iter.next();
for (Iterator i = ((CrosscuttingMembers) members.get(element)).getDeclareParents().iterator(); i.hasNext();) {
DeclareParents dp = (DeclareParents) i.next();
- if (dp.equals(p))
+ if (dp.equals(p)) {
return element;
+ }
}
}
return null;
* we go along - for example some recursive type variable references (pr133307)
*/
public void recordNecessaryCheck(IVerificationRequired verification) {
- if (verificationList == null)
+ if (verificationList == null) {
verificationList = new ArrayList();
+ }
verificationList.add(verification);
}
* Called when type bindings are complete - calls all registered verification objects in turn.
*/
public void verify() {
- if (verificationList == null)
+ if (verificationList == null) {
return;
+ }
for (Iterator iter = verificationList.iterator(); iter.hasNext();) {
IVerificationRequired element = (IVerificationRequired) iter.next();
element.verify();
verificationList = null;
}
+ public int serializationVersion = 1;
+
+ public void write(DataOutputStream stream) throws IOException {
+ // stream.writeInt(serializationVersion);
+ stream.writeInt(shadowMungers.size());
+ for (Iterator iterator = shadowMungers.iterator(); iterator.hasNext();) {
+ ShadowMunger shadowMunger = (ShadowMunger) iterator.next();
+ shadowMunger.write(stream);
+ }
+ // // private List /* ShadowMunger */shadowMungers = null;
+ // // private List typeMungers = null;
+ // // private List lateTypeMungers = null;
+ // // private List declareSofts = null;
+ // // private List declareParents = null;
+ // // private List declareAnnotationOnTypes = null;
+ // // private List declareAnnotationOnFields = null;
+ // // private List declareAnnotationOnMethods = null; // includes constructors
+ // // private List declareDominates = null;
+ // // private boolean changedSinceLastReset = false;
+ //
+ }
}
* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver;
import org.aspectj.bridge.ISourceLocation;
public interface ISourceContext {
public ISourceLocation makeSourceLocation(IHasPosition position);
+
public ISourceLocation makeSourceLocation(int line, int offset);
+
public int getOffset();
+
public void tidy();
}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2009 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
+ *
+ * ******************************************************************/
+ package org.aspectj.weaver;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * @author Andy Clement
+ */
+public class PersistenceSupport {
+
+ public static void write(DataOutputStream stream, ISourceContext sourceContext) throws IOException {
+ throw new IllegalStateException();
+ }
+
+ public static void write(DataOutputStream stream, Serializable serializableObject) throws IOException {
+ ObjectOutputStream oos = new ObjectOutputStream(stream);
+ oos.writeObject(serializableObject);
+ oos.flush();
+ }
+
+}
}
public final Collection collectDeclares(boolean includeAdviceLike) {
- if (!this.isAspect())
+ if (!this.isAspect()) {
return Collections.EMPTY_LIST;
+ }
ArrayList ret = new ArrayList();
// if (this.isAbstract()) {
package org.aspectj.weaver;
+import java.io.DataOutputStream;
import java.io.File;
+import java.io.IOException;
import java.util.Collection;
import java.util.Map;
*/
public abstract class ShadowMunger implements PartialOrder.PartialComparable, IHasPosition {
- protected Pointcut pointcut;
+ public static final ShadowMunger[] NONE = new ShadowMunger[0];
+
+ private static int VERSION_1 = 1; // ShadowMunger version for serialization
+
+ protected static final int ShadowMungerAdvice = 1;
+ protected static final int ShadowMungerDeow = 2;
+
+ public String handle = null;
+
+ private int shadowMungerKind;
- // these three fields hold the source location of this munger
protected int start, end;
protected ISourceContext sourceContext;
private ISourceLocation sourceLocation;
private ISourceLocation binarySourceLocation;
private File binaryFile;
- public String handle = null;
- private ResolvedType declaringType; // the type that declared this munger.
+ private ResolvedType declaringType;
+ private boolean isBinary;
+ private boolean checkedIsBinary;
+
+ protected Pointcut pointcut;
- public ShadowMunger(Pointcut pointcut, int start, int end, ISourceContext sourceContext) {
+ protected ShadowMunger() {
+ }
+
+ public ShadowMunger(Pointcut pointcut, int start, int end, ISourceContext sourceContext, int shadowMungerKind) {
+ this.shadowMungerKind = shadowMungerKind;
this.pointcut = pointcut;
this.start = start;
this.end = end;
this.sourceContext = sourceContext;
}
- public abstract ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause);
-
- public abstract void specializeOn(Shadow shadow);
-
- /**
- * Implement this munger at the specified shadow, returning a boolean to indicate success.
- *
- * @param shadow the shadow where this munger should be applied
- * @return true if the munger was successful
- */
- public abstract boolean implementOn(Shadow shadow);
-
/**
* All overriding methods should call super
*/
return pointcut.match(shadow).maybeTrue();
}
- public abstract ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap);
-
public int fallbackCompareTo(Object other) {
return toString().compareTo(toString());
}
return sourceLocation;
}
- // ---- fields
-
- public static final ShadowMunger[] NONE = new ShadowMunger[0];
-
public Pointcut getPointcut() {
return pointcut;
}
return declaringType;
}
- /**
- * @return a Collection of ResolvedType for all checked exceptions that might be thrown by this munger
- */
- public abstract Collection getThrownExceptions();
-
- /**
- * Does the munger has to check that its exception are accepted by the shadow ? ATAJ: It s not the case for @AJ around advice
- * f.e. that can throw Throwable, even if the advised method does not throw any exceptions.
- *
- * @return true if munger has to check that its exceptions can be throwned based on the shadow
- */
- public abstract boolean mustCheckExceptions();
-
/**
* Returns the binarySourceLocation for the given sourcelocation. This isn't cached because it's used when faulting in the
* binary nodes and is called with ISourceLocations for all advice, pointcuts and deows contained within the
* resolvedDeclaringAspect.
*/
public ISourceLocation getBinarySourceLocation(ISourceLocation sl) {
- if (sl == null)
+ if (sl == null) {
return null;
+ }
String sourceFileName = null;
if (getDeclaringType() instanceof ReferenceType) {
String s = ((ReferenceType) getDeclaringType()).getDelegate().getSourcefilename();
private File getBinaryFile() {
if (binaryFile == null) {
String s = getDeclaringType().getBinaryPath();
- if (s.indexOf("!")==-1) {
+ if (s.indexOf("!") == -1) {
File f = getDeclaringType().getSourceLocation().getSourceFile();
// Replace the source file suffix with .class
int i = f.getPath().lastIndexOf('.');
return isBinary;
}
- private boolean isBinary;
- private boolean checkedIsBinary;
+ public abstract ShadowMunger concretize(ResolvedType fromType, World world, PerClause clause);
+
+ public abstract void specializeOn(Shadow shadow);
+
+ /**
+ * Implement this munger at the specified shadow, returning a boolean to indicate success.
+ *
+ * @param shadow the shadow where this munger should be applied
+ * @return true if the implement was successful
+ */
+ public abstract boolean implementOn(Shadow shadow);
+
+ public abstract ShadowMunger parameterizeWith(ResolvedType declaringType, Map typeVariableMap);
+
+ /**
+ * @return a Collection of ResolvedTypes for all checked exceptions that might be thrown by this munger
+ */
+ public abstract Collection getThrownExceptions();
+
+ /**
+ * Does the munger have to check that its exception are accepted by the shadow ? It is not the case for annotation style around
+ * advice, for example: that can throw Throwable, even if the advised method does not throw any exceptions.
+ *
+ * @return true if munger has to check that its exceptions can be thrown based on the shadow
+ */
+ public abstract boolean mustCheckExceptions();
+ public void write(DataOutputStream stream) throws IOException {
+ stream.writeInt(VERSION_1);
+ stream.writeInt(shadowMungerKind); // determines real subclass
+ stream.writeInt(start);
+ stream.writeInt(end);
+ PersistenceSupport.write(stream, sourceContext);
+ PersistenceSupport.write(stream, sourceLocation);
+ PersistenceSupport.write(stream, binarySourceLocation);
+ PersistenceSupport.write(stream, binaryFile);
+ declaringType.write(stream);
+ stream.writeBoolean(isBinary);
+ stream.writeBoolean(checkedIsBinary);
+ pointcut.write(stream);
+ }
+ //
+ // public static ShadowMunger read(VersionedDataInputStream stream, World world) throws IOException {
+ // stream.readInt();
+ // int kind = stream.readInt();
+ // ShadowMunger newShadowMunger = null;
+ // switch (kind) {
+ // case ShadowMungerAdvice:
+ // // world.getWeavingSupport().createAdviceMunger(attribute, pointcut, signature)
+ // case ShadowMungerDeow:
+ // newShadowMunger = Checker.read(stream, world);
+ // default:
+ // throw new IllegalStateException("Unexpected type of shadow munger found on deserialization: " + kind);
+ // }
+ // newShadowMunger.binaryFile = null;
+ // }
}
* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver;
import java.io.File;
import org.aspectj.bridge.SourceLocation;
public class SourceContextImpl implements ISourceContext {
-
-// private AbstractReferenceTypeDelegate delegate;
+
private int[] lineBreaks;
- String sfname;
-
+ String sourceFilename;
+
public SourceContextImpl(AbstractReferenceTypeDelegate delegate) {
-// this.delegate = delegate;
- sfname = delegate.getSourcefilename();
+ sourceFilename = delegate.getSourcefilename();
}
-
- public void configureFromAttribute(String name,int []linebreaks) {
-// this.delegate.setSourcefilename(name);
- sfname = name;
+
+ public void configureFromAttribute(String name, int[] linebreaks) {
+ this.sourceFilename = name;
this.lineBreaks = linebreaks;
}
-
+
public void setSourceFileName(String name) {
- sfname = name;
+ sourceFilename = name;
}
-
+
private File getSourceFile() {
- return new File(sfname);
-// return new File(delegate.getSourcefilename());
+ return new File(sourceFilename);
}
-
- public void tidy() {}
-
- public int getOffset() { return 0; }
-
- /*
- // AMC - a temporary "fudge" to give as much information as possible about the identity of the
- // source file this source location points to.
- String internalClassName = getEnclosingClass().getInternalClassName();
- String fileName = getEnclosingClass().getFileName();
- String extension = fileName.substring( fileName.lastIndexOf("."), fileName.length());
- String filePrefix = fileName.substring( 0, fileName.lastIndexOf("."));
- // internal class name is e.g. figures/Point, we don't know whether the file was
- // .aj or .java so we put it together with the file extension of the enclosing class
- // BUT... sometimes internalClassName is a different class (an aspect), so we only use it if it
- // matches the file name.
- String mostAccurateFileNameGuess;
- if ( internalClassName.endsWith(filePrefix)) {
- mostAccurateFileNameGuess = internalClassName + extension;
- } else {
- mostAccurateFileNameGuess = fileName;
- }
- return new SourceLocation(new File(mostAccurateFileNameGuess), getSourceLine());
- */
+ public void tidy() {
+ }
+ public int getOffset() {
+ return 0;
+ }
public ISourceLocation makeSourceLocation(IHasPosition position) {
if (lineBreaks != null) {
int line = Arrays.binarySearch(lineBreaks, position.getStart());
- if (line < 0) line = -line;
- return new SourceLocation(getSourceFile(), line); //??? have more info
+ if (line < 0) {
+ line = -line;
+ }
+ return new SourceLocation(getSourceFile(), line); // ??? have more info
} else {
return new SourceLocation(getSourceFile(), 0);
}
}
-
+
public ISourceLocation makeSourceLocation(int line, int offset) {
- if (line < 0) line = 0;
+ if (line < 0) {
+ line = 0;
+ }
SourceLocation sl = new SourceLocation(getSourceFile(), line);
- if (offset > 0) {
- sl.setOffset(offset);
- } else {
- if (lineBreaks != null) {
- int likelyOffset = 0;
- if (line > 0 && line < lineBreaks.length) {
- //1st char of given line is next char after previous end of line
- likelyOffset = lineBreaks[line-1] + 1;
- }
- sl.setOffset(likelyOffset);
- }
- }
- return sl;
+ if (offset > 0) {
+ sl.setOffset(offset);
+ } else {
+ if (lineBreaks != null) {
+ int likelyOffset = 0;
+ if (line > 0 && line < lineBreaks.length) {
+ // 1st char of given line is next char after previous end of line
+ likelyOffset = lineBreaks[line - 1] + 1;
+ }
+ sl.setOffset(likelyOffset);
+ }
+ }
+ return sl;
}
-
public final static ISourceContext UNKNOWN_SOURCE_CONTEXT = new ISourceContext() {
- public ISourceLocation makeSourceLocation(IHasPosition position) {return null;}
- public ISourceLocation makeSourceLocation(int line, int offset) {return null;}
- public int getOffset() {return 0;}
- public void tidy() {}
+ public ISourceLocation makeSourceLocation(IHasPosition position) {
+ return null;
+ }
+
+ public ISourceLocation makeSourceLocation(int line, int offset) {
+ return null;
+ }
+
+ public int getOffset() {
+ return 0;
+ }
+
+ public void tidy() {
+ }
};
}