import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FileUtil;
+import org.aspectj.weaver.bcel.BcelWorld;
import org.aspectj.weaver.patterns.Declare;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.Pointcut;
}
}
- public static AjAttribute read(String name, byte[] bytes, ISourceContext context) {
+ public static AjAttribute read(String name, byte[] bytes, ISourceContext context,IMessageHandler msgHandler) {
try {
if (bytes == null) bytes = new byte[0];
DataInputStream s = new DataInputStream(new ByteArrayInputStream(bytes));
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)) {
return AdviceAttribute.read(s, context);
} else if (name.equals(PointcutDeclarationAttribute.AttributeName)) {
} else if (name.equals(EffectiveSignatureAttribute.AttributeName)) {
return EffectiveSignatureAttribute.read(s, context);
} else {
- throw new BCException("unknown attribute" + name);
+ // We have to tell the user about this...
+ if (msgHandler == null) throw new BCException("unknown attribute" + name);
+ msgHandler.handleMessage(MessageUtil.warn("unknown attribute encountered "+name));
+ return null;
}
} catch (IOException e) {
throw new BCException("malformed " + name + " attribute " + e);
}
}
+ 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.
+ //
+ // The user will get a warning for any org.aspectj.weaver attributes the weaver does
+ // not recognize.
+
+ // These are the weaver major/minor numbers for AspectJ 1.2.1
+ private static short WEAVER_VERSION_MAJOR_AJ121 = 1;
+ private static short WEAVER_VERSION_MINOR_AJ121 = 0;
+
+ // These are the weaver major/minor versions for *this* weaver
+ private static short CURRENT_VERSION_MAJOR = WEAVER_VERSION_MAJOR_AJ121;
+ private static short CURRENT_VERSION_MINOR = WEAVER_VERSION_MINOR_AJ121;
+
+ // These are the versions read in from a particular class file.
+ private short major_version;
+ private short minor_version;
+
+ 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;
+ }
+
+ 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);
+ }
+
+ public static WeaverVersionInfo read(DataInputStream s) throws IOException {
+ short major = s.readShort();
+ short minor = s.readShort();
+ return new WeaverVersionInfo(major,minor);
+ }
+
+ 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 String toString() {
+ return major_version+"."+minor_version;
+ }
+
+ public static String toCurrentVersionString() {
+ return CURRENT_VERSION_MAJOR+"."+CURRENT_VERSION_MINOR;
+ }
+
+ }
+
public static class SourceContextAttribute extends AjAttribute {
public static final String AttributeName = "org.aspectj.weaver.SourceContext";
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.Unknown;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
+import org.aspectj.bridge.IMessageHandler;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.ISourceContext;
// bcel to AjAttribute.
class BcelAttributes {
- public static List readAjAttributes(Attribute[] as, ISourceContext context) {
+ public static List readAjAttributes(Attribute[] as, ISourceContext context,IMessageHandler msgHandler) {
List l = new ArrayList();
for (int i = as.length - 1; i >= 0; i--) {
Attribute a = as[i];
Unknown u = (Unknown) a;
String name = u.getName();
if (name.startsWith(AjAttribute.AttributePrefix)) {
- l.add(AjAttribute.read(name, u.getBytes(), context));
+ AjAttribute attr = AjAttribute.read(name, u.getBytes(), context,msgHandler);
+ if (attr!=null) l.add(attr);
}
}
}
private ResolvedPointcutDefinition[] pointcuts = null;
private PerClause perClause = null;
private WeaverStateInfo weaverState = null;
+ private AjAttribute.WeaverVersionInfo wvInfo = null;
private List typeMungers = Collections.EMPTY_LIST;
private List declares = Collections.EMPTY_LIST;
private ResolvedMember[] privilegedAccess = null;
List pointcuts = new ArrayList();
typeMungers = new ArrayList();
declares = new ArrayList();
- List l = BcelAttributes.readAjAttributes(javaClass.getAttributes(), getResolvedTypeX().getSourceContext());
+ List l = BcelAttributes.readAjAttributes(javaClass.getAttributes(), getResolvedTypeX().getSourceContext(),getResolvedTypeX().getWorld().getMessageHandler());
for (Iterator iter = l.iterator(); iter.hasNext();) {
AjAttribute a = (AjAttribute) iter.next();
//System.err.println("unpacking: " + this + " and " + a);
if (getResolvedTypeX().getSourceContext() instanceof BcelSourceContext) {
((BcelSourceContext)getResolvedTypeX().getSourceContext()).addAttributeInfo((AjAttribute.SourceContextAttribute)a);
}
+ } else if (a instanceof AjAttribute.WeaverVersionInfo) {
+ wvInfo = (AjAttribute.WeaverVersionInfo)a;
+ if (wvInfo.getMajorVersion() > wvInfo.getCurrentWeaverMajorVersion()) {
+ // The class file containing this attribute was created by a version of AspectJ that
+ // added some behavior that 'this' version of AspectJ doesn't understand. And the
+ // class file contains changes that mean 'this' version of AspectJ cannot continue.
+ throw new BCException("Unable to continue, this version of AspectJ supports classes built with weaver version "+
+ wvInfo.toCurrentVersionString()+" but the class "+ javaClass.getClassName()+" is version "+wvInfo.toString());
+ }
} else {
throw new BCException("bad attribute " + a);
}
public ISourceLocation getSourceLocation() {
return getResolvedTypeX().getSourceContext().makeSourceLocation(0); //FIXME, we can do better than this
}
+
+ public AjAttribute.WeaverVersionInfo getWeaverVersionAttribute() {
+ return wvInfo;
+ }
public void addParent(ResolvedTypeX newParent) {
if (newParent.isClass()) {