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;
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) {
}
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
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;
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;
return isAjSynthetic; // || getName().startsWith(NameMangler.PREFIX);
}
- //FIXME needs an isSynthetic method
+ //FIXME ??? needs an isSynthetic method
public ShadowMunger getAssociatedShadowMunger() {
return associatedShadowMunger;
}
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;
- }
+ }
+ }
}
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;
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;
this.perClause = null;
this.weaverState = null;
this.lazyClassGen = null;
+ this.annotations = null;
+ this.annotationTypes = null;
isObject = (javaClass.getSuperclassNameIndex() == 0);
unpackAspectAttributes();
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;
}
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() {
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;
+ }
}
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;
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;
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
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() {
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()));
}
}
+ /**
+ *
+ */
+ 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();
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));
+ }
+ }
+
}
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;
}
}
+ 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;