]> source.dussan.org Git - aspectj.git/commitdiff
Fix for Bugzilla Bug 76798: Add versions to woven class files - enabling better backw...
authoraclement <aclement>
Fri, 22 Oct 2004 10:53:11 +0000 (10:53 +0000)
committeraclement <aclement>
Fri, 22 Oct 2004 10:53:11 +0000 (10:53 +0000)
weaver/src/org/aspectj/weaver/AjAttribute.java
weaver/src/org/aspectj/weaver/bcel/BcelAttributes.java
weaver/src/org/aspectj/weaver/bcel/BcelField.java
weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java

index ed14f5865ffcfbe8e9f5f193f1f4e611b899829e..77909614a6ae93cece293d980b541350bbef0930 100644 (file)
@@ -19,7 +19,10 @@ import java.io.DataInputStream;
 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;
@@ -81,7 +84,7 @@ public abstract class AjAttribute {
                }
        }
 
-       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));
@@ -91,6 +94,8 @@ public abstract class AjAttribute {
                           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)) {
@@ -108,7 +113,10 @@ public abstract class AjAttribute {
                        } 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);
@@ -177,6 +185,82 @@ public abstract class AjAttribute {
                }
        }
        
+       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";
                
index 9906a29bd204567b1b643c3d9ddce0133a02b147..9fb4b451e4306c8b4e19f01d681c8f866cd19777 100644 (file)
@@ -19,6 +19,7 @@ import java.util.List;
 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;
 
@@ -27,7 +28,7 @@ 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];
@@ -35,7 +36,8 @@ class BcelAttributes {
                                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);
                                }
                        }
                }
index 14f7367e2360e357a74434d23d7b27212ce90408..972571b77717190881fa3fac5f5ce03a8ce5bebc 100644 (file)
@@ -47,7 +47,7 @@ final class BcelField extends ResolvedMember {
        
        private void unpackAttributes(World world) {
                Attribute[] attrs = field.getAttributes();
-               List as = BcelAttributes.readAjAttributes(attrs, getSourceContext(world));
+               List as = BcelAttributes.readAjAttributes(attrs, getSourceContext(world),world.getMessageHandler());
                for (Iterator iter = as.iterator(); iter.hasNext();) {
                        AjAttribute a = (AjAttribute) iter.next();
                        if (a instanceof AjAttribute.AjSynthetic) {
index 202982d769ba921beddfbb16094525f3ba483e15..cf15b093eaaebef7ce5dd03bfa55ff7cd5a407e6 100644 (file)
@@ -81,7 +81,7 @@ final class BcelMethod extends ResolvedMember {
        }
 
        private void unpackAjAttributes(World world) {
-               List as = BcelAttributes.readAjAttributes(method.getAttributes(), getSourceContext(world));
+               List as = BcelAttributes.readAjAttributes(method.getAttributes(), getSourceContext(world),world.getMessageHandler());
                //System.out.println("unpack: " + this + ", " + as);
                for (Iterator iter = as.iterator(); iter.hasNext();) {
                        AjAttribute a = (AjAttribute) iter.next();
index edc5bbe9ad0a6a69686882b2ce817d956c70ae02..0b4bd9c7c99c8643c04b945a3e1cffc22da3befc 100644 (file)
@@ -50,6 +50,7 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
     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;
@@ -163,7 +164,7 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
                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);
@@ -183,6 +184,15 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
                                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);
                        }
@@ -279,6 +289,10 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
        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()) {
index 285a0a77e787bb65997b5e627f400f7927695048..4e105fb0cf82105a1cd7cfa45c8efdbae061705f 100644 (file)
@@ -395,7 +395,11 @@ public final class LazyClassGen {
                            );
                return;
         }
-       if (myType != null && myType.getWeaverState() != null) {
+        
+        // Add a weaver version attribute to the file being produced
+        myGen.addAttribute(BcelAttributes.bcelAttribute(new AjAttribute.WeaverVersionInfo(),getConstantPoolGen()));
+
+        if (myType != null && myType.getWeaverState() != null) {
                        myGen.addAttribute(BcelAttributes.bcelAttribute(
                                new AjAttribute.WeaverState(myType.getWeaverState()), 
                                getConstantPoolGen()));
index 47076f35100ee7ab8ce55f8d4addb139994dd87c..fac4f8eab9b0d5ff21f2c3daa9b5e2f57808c9bf 100644 (file)
@@ -439,7 +439,7 @@ public final class LazyMethodGen {
                if (enclosingClass != null && enclosingClass.getType() != null) {
                        context = enclosingClass.getType().getSourceContext();
                }
-               List as = BcelAttributes.readAjAttributes(attributes, context);
+               List as = BcelAttributes.readAjAttributes(attributes, context,null);
                if (! as.isEmpty()) {
                        out.println("    " + as.get(0)); // XXX assuming exactly one attribute, munger...
                }