diff options
author | aclement <aclement> | 2005-03-10 17:49:53 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-03-10 17:49:53 +0000 |
commit | 5d8ffc2c706139a7e4622a6442f2e0fbf5ffe9e1 (patch) | |
tree | 5941eee69d955f825eb2d4ed9d7939996b2ea3fc | |
parent | 826e7ba5f34af654e2c895afcfcecf8d46c17d3c (diff) | |
download | aspectj-5d8ffc2c706139a7e4622a6442f2e0fbf5ffe9e1.tar.gz aspectj-5d8ffc2c706139a7e4622a6442f2e0fbf5ffe9e1.zip |
Declare annotation: manages a set of annotations now
5 files changed, 231 insertions, 61 deletions
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelField.java b/weaver/src/org/aspectj/weaver/bcel/BcelField.java index 042947543..0f415ffb2 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelField.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelField.java @@ -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 diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java index 3b9a6daff..69e67b7a2 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java @@ -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; - } + } + } } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java index 34f9c6577..6fc2d7e93 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java index 21c2e5059..f644a6501 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java @@ -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)); + } + } + } diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java index f4b24adff..d97fefac6 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java @@ -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; |