]> source.dussan.org Git - aspectj.git/commitdiff
Declare annotation: manages a set of annotations now
authoraclement <aclement>
Thu, 10 Mar 2005 17:49:53 +0000 (17:49 +0000)
committeraclement <aclement>
Thu, 10 Mar 2005 17:49:53 +0000 (17:49 +0000)
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 042947543cc4c2a855d69f7ff53c6dc961af557f..0f415ffb2c9ab6700ce9ef3b3e830f6b55b0f785 100644 (file)
@@ -21,6 +21,7 @@ import org.aspectj.apache.bcel.classfile.Field;
 import org.aspectj.apache.bcel.classfile.Synthetic;
 import org.aspectj.apache.bcel.classfile.annotation.Annotation;
 import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AnnotationX;
 import org.aspectj.weaver.BCException;
 import org.aspectj.weaver.ResolvedMember;
 import org.aspectj.weaver.ResolvedTypeX;
@@ -32,7 +33,8 @@ final class BcelField extends ResolvedMember {
        private Field field;
        private boolean isAjSynthetic;
        private boolean isSynthetic = false;
-       private ResolvedTypeX[] resolvedAnnotations;
+       private ResolvedTypeX[] annotationTypes;
+       private AnnotationX[] annotations;
        private World world;
 
        BcelField(BcelObjectType declaringType, Field field) {
@@ -89,15 +91,43 @@ final class BcelField extends ResolvedMember {
        }
        
        public ResolvedTypeX[] getAnnotationTypes() {
-               if (resolvedAnnotations == null) {
-                       Annotation[] annotations = field.getAnnotations();
-                       resolvedAnnotations = new ResolvedTypeX[annotations.length];
-                       for (int i = 0; i < annotations.length; i++) {
-                               Annotation annotation = annotations[i];
+               ensureAnnotationTypesRetrieved();
+               return annotationTypes;
+    }
+    
+       private void ensureAnnotationTypesRetrieved() {
+               if (annotationTypes == null) {
+               Annotation annos[] = field.getAnnotations();
+               annotationTypes = new ResolvedTypeX[annos.length];
+               annotations = new AnnotationX[annos.length];
+               for (int i = 0; i < annos.length; i++) {
+                               Annotation annotation = annos[i];
                                ResolvedTypeX rtx = world.resolve(TypeX.forName(annotation.getTypeName()));
-                               resolvedAnnotations[i] = rtx;
+                               annotationTypes[i] = rtx;
+                               annotations[i] = new AnnotationX(annotation,world);
                        }
-               }
-               return resolvedAnnotations;
-    }
-}
+       }
+       }
+    
+        public void addAnnotation(AnnotationX annotation) {
+           ensureAnnotationTypesRetrieved();   
+               // Add it to the set of annotations
+               int len = annotations.length;
+               AnnotationX[] ret = new AnnotationX[len+1];
+               System.arraycopy(annotations, 0, ret, 0, len);
+               ret[len] = annotation;
+               annotations = ret;
+               
+               // Add it to the set of annotation types
+               len = annotationTypes.length;
+               ResolvedTypeX[] ret2 = new ResolvedTypeX[len+1];
+               System.arraycopy(annotationTypes,0,ret2,0,len);
+               ret2[len] =world.resolve(TypeX.forName(annotation.getTypeName()));
+               annotationTypes = ret2;
+               // FIXME asc this call here suggests we are managing the annotations at
+               // too many levels, here in BcelField we keep a set and in the lower 'field'
+               // object we keep a set - we should think about reducing this to one
+               // level??
+               field.addAnnotation(annotation.getBcelAnnotation());
+       }
+}
\ No newline at end of file
index 3b9a6daff8cc969285d4581ef923068473d37da3..69e67b7a215664a5a4b775752a5f55875cb47763 100644 (file)
@@ -25,6 +25,7 @@ import org.aspectj.apache.bcel.classfile.annotation.Annotation;
 import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.bridge.SourceLocation;
 import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AnnotationX;
 import org.aspectj.weaver.BCException;
 import org.aspectj.weaver.ISourceContext;
 import org.aspectj.weaver.ResolvedMember;
@@ -38,6 +39,10 @@ final class BcelMethod extends ResolvedMember {
        private Method method;
        private boolean isAjSynthetic;
        private ShadowMunger associatedShadowMunger;
+       
+    private ResolvedTypeX[] annotationTypes = null;
+    private AnnotationX[] annotations = null;
+       
        private AjAttribute.EffectiveSignatureAttribute effectiveSignature;
        private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber;
        private ResolvedTypeX[] resolvedAnnotations;
@@ -115,7 +120,7 @@ final class BcelMethod extends ResolvedMember {
                return isAjSynthetic; // || getName().startsWith(NameMangler.PREFIX);
        }
        
-       //FIXME needs an isSynthetic method
+       //FIXME ??? needs an isSynthetic method
        
        public ShadowMunger getAssociatedShadowMunger() {
                return associatedShadowMunger;
@@ -157,28 +162,55 @@ final class BcelMethod extends ResolvedMember {
        }
        
        public boolean hasAnnotation(TypeX ofType) {
-               Annotation[] anns = method.getAnnotations();
-               for (int i = 0; i < anns.length; i++) {
-                       Annotation annotation = anns[i];
-                       if (annotation.getTypeName().equals(ofType.getName())) return true;
+               ensureAnnotationTypesRetrieved();
+               for (int i=0; i<annotationTypes.length; i++) {
+                       ResolvedTypeX aType = annotationTypes[i];
+                       if (aType.equals(ofType)) return true;
                }
                return false;
        }
        
-       public Annotation[] getAnnotations() {
-               return method.getAnnotations();
+       public AnnotationX[] getAnnotations() {
+               ensureAnnotationTypesRetrieved();
+               return annotations;
        }
        
         public ResolvedTypeX[] getAnnotationTypes() {
-               if (resolvedAnnotations == null) {
-                       Annotation[] annotations = method.getAnnotations();
-                       resolvedAnnotations = new ResolvedTypeX[annotations.length];
-                       for (int i = 0; i < annotations.length; i++) {
-                               Annotation annotation = annotations[i];
+           ensureAnnotationTypesRetrieved();
+           return annotationTypes;
+     }
+        
+        public void addAnnotation(AnnotationX annotation) {
+           ensureAnnotationTypesRetrieved();   
+               // Add it to the set of annotations
+               int len = annotations.length;
+               AnnotationX[] ret = new AnnotationX[len+1];
+               System.arraycopy(annotations, 0, ret, 0, len);
+               ret[len] = annotation;
+               annotations = ret;
+               
+               // Add it to the set of annotation types
+               len = annotationTypes.length;
+               ResolvedTypeX[] ret2 = new ResolvedTypeX[len+1];
+               System.arraycopy(annotationTypes,0,ret2,0,len);
+               ret2[len] =world.resolve(TypeX.forName(annotation.getTypeName()));
+               annotationTypes = ret2;
+               // FIXME asc looks like we are managing two 'bunches' of annotations, one
+               // here and one in the real 'method' - should we reduce it to one layer?
+               method.addAnnotation(annotation.getBcelAnnotation());
+        }
+        
+        private void ensureAnnotationTypesRetrieved() {
+               if (annotationTypes == null) {
+               Annotation annos[] = method.getAnnotations();
+               annotationTypes = new ResolvedTypeX[annos.length];
+               annotations = new AnnotationX[annos.length];
+               for (int i = 0; i < annos.length; i++) {
+                               Annotation annotation = annos[i];
                                ResolvedTypeX rtx = world.resolve(TypeX.forName(annotation.getTypeName()));
-                               resolvedAnnotations[i] = rtx;
+                               annotationTypes[i] = rtx;
+                               annotations[i] = new AnnotationX(annotation,world);
                        }
-               }
-               return resolvedAnnotations;
-    }
+       }
+       }
 }
index 34f9c6577e40bdc905ef3c8ae62ea9a4c6f91ce9..6fc2d7e930d16b8942b87d3d750282480590a395 100644 (file)
@@ -29,6 +29,7 @@ import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
 import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
 import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AnnotationX;
 import org.aspectj.weaver.BCException;
 import org.aspectj.weaver.ResolvedMember;
 import org.aspectj.weaver.ResolvedPointcutDefinition;
@@ -48,7 +49,8 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
     private ResolvedTypeX superClass = null;
     private ResolvedMember[] fields = null;
     private ResolvedMember[] methods = null;
-    private ResolvedTypeX[] resolvedAnnotations = null;
+    private ResolvedTypeX[] annotationTypes = null;
+    private AnnotationX[] annotations = null;
             
     // strangely non-lazy
     private ResolvedPointcutDefinition[] pointcuts = null;
@@ -225,6 +227,8 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
        this.perClause = null;
        this.weaverState = null;
        this.lazyClassGen = null;
+       this.annotations = null;
+       this.annotationTypes = null;
        
        isObject = (javaClass.getSuperclassNameIndex() == 0);
         unpackAspectAttributes();
@@ -293,6 +297,23 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
                return javaClass.isAnnotation();
        }
        
+       public void addAnnotation(AnnotationX annotation) {
+               
+               // Add it to the set of annotations
+               int len = annotations.length;
+               AnnotationX[] ret = new AnnotationX[len+1];
+               System.arraycopy(annotations, 0, ret, 0, len);
+               ret[len] = annotation;
+               annotations = ret;
+               
+               // Add it to the set of annotation types
+               len = annotationTypes.length;
+               ResolvedTypeX[] ret2 = new ResolvedTypeX[len+1];
+               System.arraycopy(annotationTypes,0,ret2,0,len);
+               ret2[len] = getResolvedTypeX().getWorld().resolve(TypeX.forName(annotation.getTypeName()));
+               annotationTypes = ret2;
+       }
+       
        public boolean isAnnotationWithRuntimeRetention() {
            if (!isAnnotation()) {
                return false;
@@ -320,7 +341,7 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
        }
 
        public ISourceLocation getSourceLocation() {
-               return getResolvedTypeX().getSourceContext().makeSourceLocation(0); //FIXME, we can do better than this
+               return getResolvedTypeX().getSourceContext().makeSourceLocation(0); //FIXME ??? we can do better than this
        }
        
        public AjAttribute.WeaverVersionInfo getWeaverVersionAttribute() {
@@ -346,26 +367,40 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
 
 
        public boolean hasAnnotation(TypeX ofType) {
-               Annotation[] annotationsOnThisType = javaClass.getAnnotations();
-               for (int i = 0; i < annotationsOnThisType.length; i++) {
-                       Annotation a = annotationsOnThisType[i];
-                       if (a.getTypeName().equals(ofType.getName())) return true;
+               ensureAnnotationTypesRetrieved();
+               for (int i = 0; i < annotationTypes.length; i++) {
+                       ResolvedTypeX annX = annotationTypes[i];
+                       if (annX.equals(ofType)) return true;
                }
                return false;
        }
        
-       public ResolvedTypeX[] getAnnotationTypes() {
-       if (resolvedAnnotations == null) {
-               Annotation annotations[] = javaClass.getAnnotations();
-               resolvedAnnotations = new ResolvedTypeX[annotations.length];
-               for (int i = 0; i < annotations.length; i++) {
-                               Annotation annotation = annotations[i];
+       private void ensureAnnotationTypesRetrieved() {
+               if (annotationTypes == null) {
+               Annotation annos[] = javaClass.getAnnotations();
+               annotationTypes = new ResolvedTypeX[annos.length];
+               annotations = new AnnotationX[annos.length];
+               for (int i = 0; i < annos.length; i++) {
+                               Annotation annotation = annos[i];
                                ResolvedTypeX rtx = getResolvedTypeX().getWorld().resolve(TypeX.forName(annotation.getTypeName()));
-                               resolvedAnnotations[i] = rtx;
+                               annotationTypes[i] = rtx;
+                               annotations[i] = new AnnotationX(annotation,getResolvedTypeX().getWorld());
                        }
        }
-       return resolvedAnnotations;
+       }
+       
+       public ResolvedTypeX[] getAnnotationTypes() {
+       ensureAnnotationTypesRetrieved();
+       return annotationTypes;
     }
+       
+       /** 
+        * Releases annotations wrapped in an annotationX
+        */
+       public AnnotationX[] getAnnotations() {
+               ensureAnnotationTypesRetrieved();
+               return annotations;
+       }
 } 
     
     
index 21c2e50592b395207b84ad59e4b07fca4acceadf..f644a6501e37953f45037cea6c60eeb7bb0556a4 100644 (file)
@@ -36,6 +36,7 @@ import org.aspectj.apache.bcel.classfile.Field;
 import org.aspectj.apache.bcel.classfile.JavaClass;
 import org.aspectj.apache.bcel.classfile.Method;
 import org.aspectj.apache.bcel.classfile.Unknown;
+import org.aspectj.apache.bcel.classfile.annotation.Annotation;
 import org.aspectj.apache.bcel.generic.ClassGen;
 import org.aspectj.apache.bcel.generic.ConstantPoolGen;
 import org.aspectj.apache.bcel.generic.FieldGen;
@@ -47,6 +48,7 @@ import org.aspectj.apache.bcel.generic.ObjectType;
 import org.aspectj.apache.bcel.generic.PUSH;
 import org.aspectj.apache.bcel.generic.RETURN;
 import org.aspectj.apache.bcel.generic.Type;
+import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
 import org.aspectj.bridge.IMessage;
 import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.bridge.SourceLocation;
@@ -63,6 +65,13 @@ import org.aspectj.weaver.WeaverMessages;
 import org.aspectj.weaver.WeaverStateInfo;
 import org.aspectj.weaver.World;
 
+/**
+ * Lazy lazy lazy.
+ * We don't unpack the underlying class unless necessary.  Things
+ * like new methods and annotations accumulate in here until they
+ * must be written out, don't add them to the underlying MethodGen!
+ * Things are slightly different if this represents an Aspect.
+ */
 public final class LazyClassGen {
        
        // ---- JSR 45 info
@@ -197,11 +206,9 @@ public final class LazyClassGen {
        private ClassGen myGen;
        private ConstantPoolGen constantPoolGen;
 
-    private List /*LazyMethodGen*/
-        methodGens = new ArrayList();
-    private List /*LazyClassGen*/
-        classGens = new ArrayList();
-
+    private List /*LazyMethodGen*/ methodGens  = new ArrayList();
+    private List /*LazyClassGen*/  classGens   = new ArrayList();
+    private List /*AnnotationGen*/ annotations = new ArrayList();
     private int childCounter = 0;
 
     public int getNewGeneratedNameTag() {
@@ -374,28 +381,38 @@ public final class LazyClassGen {
 
     public List getMethodGens() {
         return methodGens; //???Collections.unmodifiableList(methodGens);
-
+    }
+    
+    // FIXME asc Should be collection returned here
+    public Field[] getFieldGens() {
+      return myGen.getFields();
+    }
+    
+    // FIXME asc How do the ones on the underlying class surface if this just returns new ones added?
+    // FIXME asc ...although no one calls this right now !
+    public List getAnnotations() {
+       return annotations;
     }
 
     private void writeBack(BcelWorld world) {
         if (getConstantPoolGen().getSize() > Short.MAX_VALUE) {
-            // PR 59208
-            // we've generated a class that is just toooooooooo big (you've been generating programs
-            // again haven't you? come on, admit it, no-one writes classes this big by hand).
-            // create an empty myGen so that we can give back a return value that doesn't upset the
-            // rest of the process.
-            myGen = new ClassGen(myGen.getClassName(), myGen.getSuperclassName(), 
-                    myGen.getFileName(), myGen.getAccessFlags(), myGen.getInterfaceNames());
-            // raise an error against this compilation unit.
-                       getWorld().showMessage(
-                               IMessage.ERROR, 
-                               WeaverMessages.format(WeaverMessages.CLASS_TOO_BIG,
-                                                             this.getClassName()),
-                           new SourceLocation(new File(myGen.getFileName()),0), null
-                           );
+            reportClassTooBigProblem();
                return;
         }
         
+        if (annotations.size()>0) {
+               for (Iterator iter = annotations.iterator(); iter.hasNext();) {
+                               AnnotationGen element = (AnnotationGen) iter.next();
+                               myGen.addAnnotation(element);
+                       }
+//         Attribute[] annAttributes  = org.aspectj.apache.bcel.classfile.Utility.getAnnotationAttributes(getConstantPoolGen(),annotations);
+//        for (int i = 0; i < annAttributes.length; i++) {
+//                     Attribute attribute = annAttributes[i];
+//                     System.err.println("Adding attribute for "+attribute);
+//                     myGen.addAttribute(attribute);
+//             }
+        }
+        
         // Add a weaver version attribute to the file being produced
         myGen.addAttribute(BcelAttributes.bcelAttribute(new AjAttribute.WeaverVersionInfo(),getConstantPoolGen()));
 
@@ -431,6 +448,26 @@ public final class LazyClassGen {
                }
     }
 
+       /**
+        * 
+        */
+       private void reportClassTooBigProblem() {
+               // PR 59208
+               // we've generated a class that is just toooooooooo big (you've been generating programs
+               // again haven't you? come on, admit it, no-one writes classes this big by hand).
+               // create an empty myGen so that we can give back a return value that doesn't upset the
+               // rest of the process.
+               myGen = new ClassGen(myGen.getClassName(), myGen.getSuperclassName(), 
+                       myGen.getFileName(), myGen.getAccessFlags(), myGen.getInterfaceNames());
+               // raise an error against this compilation unit.
+               getWorld().showMessage(
+                               IMessage.ERROR, 
+                               WeaverMessages.format(WeaverMessages.CLASS_TOO_BIG,
+                                                             this.getClassName()),
+                           new SourceLocation(new File(myGen.getFileName()),0), null
+                           );
+       }
+
        private static boolean hasSourceDebugExtensionAttribute(ClassGen gen) {
                ConstantPoolGen pool = gen.getConstantPool();
                Attribute[] attrs = gen.getAttributes();
@@ -848,4 +885,26 @@ public final class LazyClassGen {
                myGen.setAccessFlags(Utility.makePublic(myGen.getAccessFlags()));
        }
 
+       
+       public boolean hasAnnotation(TypeX t) {
+               
+               // annotations on the real thing
+               AnnotationGen agens[] = myGen.getAnnotations();
+               if (agens==null) return false;
+               for (int i = 0; i < agens.length; i++) {
+                       AnnotationGen gen = agens[i];
+                       if (t.equals(TypeX.forSignature(gen.getTypeSignature()))) return true;
+               }
+               
+               // annotations added during this weave
+               
+               return false;
+       }
+       
+       public void addAnnotation(Annotation a) {
+               if (!hasAnnotation(TypeX.forSignature(a.getTypeSignature()))) {
+                 annotations.add(new AnnotationGen(a,getConstantPoolGen(),true));
+               }
+       }
+
 }
index f4b24adff08ac4a0ee01142c99262829211eaa50..d97fefac63e51774702880c01ef2f84424fed713 100644 (file)
@@ -53,6 +53,7 @@ import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
 import org.aspectj.bridge.IMessage;
 import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AnnotationX;
 import org.aspectj.weaver.BCException;
 import org.aspectj.weaver.ISourceContext;
 import org.aspectj.weaver.Member;
@@ -178,6 +179,19 @@ public final class LazyMethodGen {
        }
     }
     
+    public void addAnnotation(AnnotationX ax) {
+       initialize();
+//             if (!hasAnnotation(TypeX.forSignature(a.getTypeSignature()))) {
+       AnnotationGen ag = new AnnotationGen(ax.getBcelAnnotation(),enclosingClass.getConstantPoolGen(),true);
+       AnnotationGen[] newAnnotations = new AnnotationGen[annotations.length+1];
+       System.arraycopy(annotations,0,newAnnotations,0,annotations.length);
+       newAnnotations[annotations.length]=ag;
+       annotations = newAnnotations;
+       // FIXME asc does this mean we are managing two levels of annotations again?
+       // one here and one in the memberView??!?
+       memberView.addAnnotation(ax);
+    }
+    
     private void initialize() {
        if (returnType != null) return;