From 88e28464f1dac4cb824af1ab761891c57e9ba95a Mon Sep 17 00:00:00 2001 From: aclement Date: Wed, 22 Feb 2006 15:04:01 +0000 Subject: [PATCH] optimizationasm: the asm visitors and actual delegate classes --- .../aspectj/weaver/asm/AjASMAttribute.java | 66 ++ .../org/aspectj/weaver/asm/AnnVisitor.java | 80 +++ .../weaver/asm/ArrayAnnotationVisitor.java | 77 +++ .../org/aspectj/weaver/asm/AsmConstants.java | 39 ++ .../org/aspectj/weaver/asm/AsmDelegate.java | 634 ++++++++++++++++++ .../src/org/aspectj/weaver/asm/AsmField.java | 110 +++ .../src/org/aspectj/weaver/asm/AsmMethod.java | 272 ++++++++ .../org/aspectj/weaver/asm/EmptyVisitor.java | 28 + .../src/org/aspectj/weaver/asm/FdVisitor.java | 38 ++ .../org/aspectj/weaver/asm/MethVisitor.java | 72 ++ .../org/aspectj/weaver/asm/TypeVisitor.java | 222 ++++++ 11 files changed, 1638 insertions(+) create mode 100644 weaver/src/org/aspectj/weaver/asm/AjASMAttribute.java create mode 100644 weaver/src/org/aspectj/weaver/asm/AnnVisitor.java create mode 100644 weaver/src/org/aspectj/weaver/asm/ArrayAnnotationVisitor.java create mode 100644 weaver/src/org/aspectj/weaver/asm/AsmConstants.java create mode 100644 weaver/src/org/aspectj/weaver/asm/AsmDelegate.java create mode 100644 weaver/src/org/aspectj/weaver/asm/AsmField.java create mode 100644 weaver/src/org/aspectj/weaver/asm/AsmMethod.java create mode 100644 weaver/src/org/aspectj/weaver/asm/EmptyVisitor.java create mode 100644 weaver/src/org/aspectj/weaver/asm/FdVisitor.java create mode 100644 weaver/src/org/aspectj/weaver/asm/MethVisitor.java create mode 100644 weaver/src/org/aspectj/weaver/asm/TypeVisitor.java diff --git a/weaver/src/org/aspectj/weaver/asm/AjASMAttribute.java b/weaver/src/org/aspectj/weaver/asm/AjASMAttribute.java new file mode 100644 index 000000000..2a13514cf --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/AjASMAttribute.java @@ -0,0 +1,66 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import org.aspectj.weaver.AjAttribute; +import org.aspectj.weaver.BCException; +import org.aspectj.org.objectweb.asm.Attribute; +import org.aspectj.org.objectweb.asm.ByteVector; +import org.aspectj.org.objectweb.asm.ClassReader; +import org.aspectj.org.objectweb.asm.ClassWriter; +import org.aspectj.org.objectweb.asm.Label; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +class AjASMAttribute extends Attribute { + + private boolean unpacked = false; + private byte[] data; + + protected AjASMAttribute(String type) { + super(type); + } + + protected AjASMAttribute(String type,byte[] data) { + super(type); + this.data=data; + } + + /** + * Initial read of the attribute is super lightweight - no unpacking + */ + protected Attribute read(ClassReader cr, int off, int len, char[] buf, + int codeOff, Label[] labels) { + byte[] data = new byte[len]; + System.arraycopy(cr.b, off, data, 0, len); + return new AjASMAttribute(this.type, data); + } + + /** + * These attributes are read only, an attempt to write them violates this fundamental assumption. + */ + protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) { + throw new NotImplementedException();// "Attempt to write out the AjASMAttribute for "+this.type); + // return new ByteVector().putByteArray(data, 0, data.length); + } + + public boolean isUnknown() { return false; } + + // --- + + public AjAttribute unpack(AsmDelegate relatedDelegate) { + if (unpacked) throw new BCException("Don't unpack an attribute twice!"); + AjAttribute attr = AjAttribute.read(relatedDelegate.weaverVersion,type,data,relatedDelegate.getSourceContext(),relatedDelegate.getWorld().getMessageHandler()); + unpacked=true; + return attr; + } +} \ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/asm/AnnVisitor.java b/weaver/src/org/aspectj/weaver/asm/AnnVisitor.java new file mode 100644 index 000000000..e27a6dd92 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/AnnVisitor.java @@ -0,0 +1,80 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import org.aspectj.weaver.AnnotationAJ; +import org.aspectj.weaver.AnnotationAnnotationValue; +import org.aspectj.weaver.AnnotationNameValuePair; +import org.aspectj.weaver.AnnotationValue; +import org.aspectj.weaver.ArrayAnnotationValue; +import org.aspectj.weaver.ClassAnnotationValue; +import org.aspectj.weaver.EnumAnnotationValue; +import org.aspectj.weaver.SimpleAnnotationValue; +import org.aspectj.org.objectweb.asm.AnnotationVisitor; +import org.aspectj.org.objectweb.asm.Type; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +/** + * Constructed with an annotation to 'fill in' with the values we encounter whilst visting it. + */ +class AnnVisitor implements AnnotationVisitor { + private AnnotationAJ a; + + public AnnVisitor(AnnotationAJ annotationToPopulate) { + a = annotationToPopulate; + } + + public void visitEnum(String name, String type, String value) { + AnnotationValue val = new EnumAnnotationValue(type,value); + a.addNameValuePair(new AnnotationNameValuePair(name,val)); + } + + public void visit(String name, Object value) { + AnnotationValue val = null; + if (value instanceof Integer) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_INT,value); + if (value instanceof Boolean) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_BOOLEAN,value); + if (value instanceof Long) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_LONG,value); + if (value instanceof Short) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_SHORT,value); + if (value instanceof Double) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_DOUBLE,value); + if (value instanceof Float) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_FLOAT,value); + if (value instanceof Character) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_CHAR,value); + if (value instanceof Byte) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_BYTE,value); + if (value instanceof String) val = new SimpleAnnotationValue(AnnotationValue.STRING,value); + + if (val==null && value instanceof Type) { + String classSignature = ((Type)value).getDescriptor(); + val = new ClassAnnotationValue(classSignature); + } + if (val!=null) { + a.addNameValuePair(new AnnotationNameValuePair(name,val)); + } else { + System.err.println("Choking on "+name+" = "+value); + throw new NotImplementedException(); + } + } + + public AnnotationVisitor visitAnnotation(String name, String desc) { + AnnotationAJ annotation = new AnnotationAJ(desc,a.isRuntimeVisible()); + AnnotationValue val = new AnnotationAnnotationValue(annotation); + a.addNameValuePair(new AnnotationNameValuePair(name,val)); + return new AnnVisitor(annotation); + } + + public AnnotationVisitor visitArray(String name) { + ArrayAnnotationValue val = new ArrayAnnotationValue(); + a.addNameValuePair(new AnnotationNameValuePair(name,val)); + return new ArrayAnnotationVisitor(val,a.isRuntimeVisible()); + } + + public void visitEnd() {} +} \ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/asm/ArrayAnnotationVisitor.java b/weaver/src/org/aspectj/weaver/asm/ArrayAnnotationVisitor.java new file mode 100644 index 000000000..4f0a3a5e6 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/ArrayAnnotationVisitor.java @@ -0,0 +1,77 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import java.util.ArrayList; +import java.util.List; + +import org.aspectj.weaver.AnnotationAJ; +import org.aspectj.weaver.AnnotationAnnotationValue; +import org.aspectj.weaver.AnnotationValue; +import org.aspectj.weaver.ArrayAnnotationValue; +import org.aspectj.weaver.ClassAnnotationValue; +import org.aspectj.weaver.EnumAnnotationValue; +import org.aspectj.weaver.SimpleAnnotationValue; +import org.aspectj.org.objectweb.asm.AnnotationVisitor; +import org.aspectj.org.objectweb.asm.Type; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +class ArrayAnnotationVisitor implements AnnotationVisitor { + List arrayValues = new ArrayList(); + boolean vis; + ArrayAnnotationValue val; + + public ArrayAnnotationVisitor(ArrayAnnotationValue val,boolean visibility) {this.val = val;this.vis = visibility;} + + public void visit(String name, Object value) { + AnnotationValue val = null; + if (value instanceof Integer) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_INT,value); + if (value instanceof Boolean) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_BOOLEAN,value); + if (value instanceof String) val = new SimpleAnnotationValue(AnnotationValue.STRING,value); + if (value instanceof Long) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_LONG,value); + if (value instanceof Short) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_SHORT,value); + if (value instanceof Double) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_DOUBLE,value); + if (value instanceof Float) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_FLOAT,value); + if (value instanceof Character) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_CHAR,value); + if (value instanceof Byte) val = new SimpleAnnotationValue(AnnotationValue.PRIMITIVE_BYTE,value); + if (val==null && value instanceof Type) { + String classSignature = ((Type)value).getDescriptor(); + val = new ClassAnnotationValue(classSignature); + } + if (val!=null) { + arrayValues.add(val); + } else { + System.err.println("Choking on "+name+" = "+value); + throw new NotImplementedException(); + } + } + + public void visitEnum(String name, String type, String value) { + AnnotationValue val = new EnumAnnotationValue(type,value); + arrayValues.add(val);//new AnnotationNameValuePair(name,val)); + } + public AnnotationVisitor visitAnnotation(String name, String desc) { + AnnotationAJ annotation = new AnnotationAJ(desc,vis); + AnnotationValue val = new AnnotationAnnotationValue(annotation); + arrayValues.add(val); + return new AnnVisitor(annotation); + } + public AnnotationVisitor visitArray(String arg0) { + ArrayAnnotationValue val = new ArrayAnnotationValue(); + arrayValues.add(val); + return new ArrayAnnotationVisitor(val,vis); + } + public void visitEnd() { + val.setValues((AnnotationValue[])arrayValues.toArray(new AnnotationValue[]{})); + } +} \ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/asm/AsmConstants.java b/weaver/src/org/aspectj/weaver/asm/AsmConstants.java new file mode 100644 index 000000000..483e9205a --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/AsmConstants.java @@ -0,0 +1,39 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import org.aspectj.weaver.AjAttribute.Aspect; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; +import org.aspectj.org.objectweb.asm.Attribute; + +public class AsmConstants { + + public static Attribute[] ajAttributes; // attributes ASM needs to know about + + static { + ajAttributes = new Attribute[]{ + new AjASMAttribute(Aspect.AttributeName), + new AjASMAttribute(WeaverVersionInfo.AttributeName), + new AjASMAttribute("org.aspectj.weaver.WeaverState"), + new AjASMAttribute("org.aspectj.weaver.PointcutDeclaration"), + new AjASMAttribute("org.aspectj.weaver.Declare"), + new AjASMAttribute("org.aspectj.weaver.TypeMunger"), + new AjASMAttribute("org.aspectj.weaver.Privileged"), + new AjASMAttribute("org.aspectj.weaver.MethodDeclarationLineNumber"), + new AjASMAttribute("org.aspectj.weaver.SourceContext"), + new AjASMAttribute("org.aspectj.weaver.Advice"), + new AjASMAttribute("org.aspectj.weaver.EffectiveSignature"), + new AjASMAttribute("org.aspectj.weaver.AjSynthetic") + }; + } + +} diff --git a/weaver/src/org/aspectj/weaver/asm/AsmDelegate.java b/weaver/src/org/aspectj/weaver/asm/AsmDelegate.java new file mode 100644 index 000000000..d73edc012 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/AsmDelegate.java @@ -0,0 +1,634 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.aspectj.apache.bcel.classfile.GenericSignatureParser; +import org.aspectj.apache.bcel.classfile.Signature; +import org.aspectj.weaver.AbstractReferenceTypeDelegate; +import org.aspectj.weaver.AjAttribute; +import org.aspectj.weaver.AnnotationAJ; +import org.aspectj.weaver.AnnotationTargetKind; +import org.aspectj.weaver.AnnotationX; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.ReferenceType; +import org.aspectj.weaver.ReferenceTypeDelegate; +import org.aspectj.weaver.ResolvedMember; +import org.aspectj.weaver.ResolvedMemberImpl; +import org.aspectj.weaver.ResolvedPointcutDefinition; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.SourceContextImpl; +import org.aspectj.weaver.TypeVariable; +import org.aspectj.weaver.UnresolvedType; +import org.aspectj.weaver.WeaverStateInfo; +import org.aspectj.weaver.World; +import org.aspectj.weaver.AjAttribute.DeclareAttribute; +import org.aspectj.weaver.AjAttribute.PointcutDeclarationAttribute; +import org.aspectj.weaver.AjAttribute.PrivilegedAttribute; +import org.aspectj.weaver.AjAttribute.SourceContextAttribute; +import org.aspectj.weaver.AjAttribute.TypeMunger; +import org.aspectj.weaver.AjAttribute.WeaverState; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; +import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter; +import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException; +import org.aspectj.weaver.patterns.PerClause; +import org.aspectj.org.objectweb.asm.Attribute; +import org.aspectj.org.objectweb.asm.ClassReader; +import org.aspectj.org.objectweb.asm.Opcodes; + +/** + * A lightweight fast delegate that is an alternative to a BCEL delegate. + * The type being represented is being referenced during a compile + * or weave but is not exposed to the weaver, for example java.lang.String. + * Unnecessary information is not processed - for example the linenumbertable. + * + * What might need visiting that currently isnt? + * - methods so we can get their annotations + * + * Implementation: + * The state in this type is populated by an ASM ClassVisitor, attributes and + * annotations are mostly unpacked lazily. + * + * @author AndyClement + */ +public class AsmDelegate extends AbstractReferenceTypeDelegate { + + public static boolean careAboutMemberAnnotationsAndAttributes = true; + + private World w; + + int classModifiers; + + ResolvedPointcutDefinition[] pointcuts = null; + TypeVariable[] typeVariables; // filled in when signature is parsed + + ResolvedType[] annotationTypes; + AnnotationX[] annotationXs; + List annotations = Collections.EMPTY_LIST; + + ResolvedMember[] methods; + ResolvedMember[] fields; + List attributes = Collections.EMPTY_LIST; + Collection /*of Declare*/ declares = null; + Collection /*of ConcreteTypeMunger*/ typeMungers = null; + Collection /*of ResolvedMember*/ privilegedAccesses = null; + + private int bitflag = 0; // see below for the relevant bits + + private final static int DISCOVERED_POINTCUTS = 0x0001;// guard for lazy initialization of pointcuts + private final static int DISCOVERED_DECLARES = 0x0002;// guard for lazy initialization of declares + private final static int DISCOVERED_TYPEMUNGERS = 0x0004;// guard for lazy initialization of type mungers + private final static int DISCOVERED_PRIVILEGEDACCESSES = 0x0008;// guard for lazy initialization of privileged access list + private final static int DISCOVERED_SOURCECONTEXT = 0x0010;// Sourcecontext is actually held in supertype + private final static int DISCOVERED_WEAVERSTATEINFO = 0x0020; + private final static int SIGNATURE_UNPACKED = 0x0040; + private final static int ANNOTATION_TYPES_CORRECT = 0x0080; + private final static int ANNOTATIONX_CORRECT = 0x0100; + private final static int SUPERSET = 0x0200; + private final static int FIELDSFIXEDUP = 0x0400; + private final static int METHODSFIXEDUP = 0x0800; + + private ResolvedType superclassType = null; + String superclassName = null; + + private ResolvedType[] interfaceTypes = null; + String[] interfaceNames = null; + + // For the fields below, which are set based on attribute or annotation values, + // some are 'eager' and set as the visitor goes through the type. Some are + // lazy and only set when someone requests their value + + // eager: populated from the 'Aspect' attribute + boolean isAspect = false; + PerClause perClause = null; + + // eager: populated from the 'WeaverVersionInfo' attribute + WeaverVersionInfo weaverVersion = AjAttribute.WeaverVersionInfo.UNKNOWN; + + // lazy: populated from the 'WeaverStateInfo' attribute + WeaverStateInfo weaverStateInfo = null; + + // eager: populated from the visitInnerClass method in the TypeVisitor + boolean isAnonymous = false; + boolean isNested = false; + + // eager: populated from the visit method in the TypeVisitor + boolean isGenericType = false; + String declaredSignature = null; + + // eager: populated from the 'Retention' annotation + boolean isRuntimeRetention = false; + String retentionPolicy = null; + + // eager: populated from the 'Target' annotation + boolean canAnnotationTargetType = true; // true unless we learn otherwise + AnnotationTargetKind[] targetKinds = null; + + // ----- + + public AsmDelegate(ReferenceType rt,InputStream inputStream) { + super(rt,false); + w = rt.getWorld(); + try { + new ClassReader(inputStream).accept(new TypeVisitor(this),AsmConstants.ajAttributes,true); + inputStream.close(); + // why-o-why-o-why ? + if ((classModifiers&4096)>0) classModifiers-=4096; // remove SYNTHETIC + if ((classModifiers&131072)>0) classModifiers-=131072; // remove DEPRECATED + } catch (IOException ioe) { + ioe.printStackTrace(); + } + setSourceContext(new SourceContextImpl(this)); + } + + + public boolean isAnnotationStyleAspect() { + return false; + } + + + public boolean canAnnotationTargetType() { + return canAnnotationTargetType; + } + + public AnnotationTargetKind[] getAnnotationTargetKinds() { + return targetKinds; + } + + public boolean isGeneric() { + return isGenericType; + } + + public boolean isAnonymous() { + return isAnonymous; + } + + public boolean isNested() { + return isNested; + } + + public boolean hasAnnotation(UnresolvedType ofType) { + ensureAnnotationsUnpacked(); + for (int i = 0; i < annotationTypes.length; i++) { + if (annotationTypes[i].equals(ofType)) return true; + } + return false; + } + + public AnnotationX[] getAnnotations() { + ensureAnnotationXsUnpacked(); + return annotationXs; + } + + public ResolvedType[] getAnnotationTypes() { + ensureAnnotationsUnpacked(); + return annotationTypes; + } + + private void ensureAnnotationXsUnpacked() { + if ( (bitflag&ANNOTATION_TYPES_CORRECT)!=0 && (bitflag&ANNOTATIONX_CORRECT)!=0) return; + ensureAnnotationsUnpacked(); + if (annotations.size()==0) { + annotationXs = AnnotationX.NONE; + } else { + annotationXs = new AnnotationX[annotations.size()]; + int pos = 0; + for (Iterator iter = annotations.iterator(); iter.hasNext();) { + AnnotationAJ element = (AnnotationAJ) iter.next(); + annotationXs[pos++] = new AnnotationX(element,w); + } + annotations = null; // dont need them any more! + } + bitflag|=ANNOTATIONX_CORRECT; + } + + private void ensureAnnotationsUnpacked() { + if ((bitflag&ANNOTATION_TYPES_CORRECT)!=0) return; + if (annotations.size()==0) { + annotationTypes = ResolvedType.NONE; + } else { + annotationTypes = new ResolvedType[annotations.size()]; + int pos = 0; + for (Iterator iter = annotations.iterator(); iter.hasNext();) { + AnnotationAJ element = (AnnotationAJ) iter.next(); + annotationTypes[pos++] = w.resolve(UnresolvedType.forSignature(element.getTypeSignature())); + } + } + bitflag|=ANNOTATION_TYPES_CORRECT; + } + + public Signature.FormalTypeParameter[] getAllFormals() { + ensureSignatureUnpacked(); + if (formalsForResolution == null) { + return new Signature.FormalTypeParameter[0]; + } else { + return formalsForResolution; + } + } + + // for testing - if we have this attribute, return it - will return null if it doesnt know anything + public AjAttribute[] getAttributes(String name) { + List results = new ArrayList(); + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Attribute element = (Attribute) iter.next(); + if (element.type.equals(name) && (element instanceof AjASMAttribute)) { + results.add(((AjASMAttribute)element).unpack(this)); + } + } + if (results.size()>0) { + return (AjAttribute[])results.toArray(new AjAttribute[]{}); + } + return null; + } + + // for testing - use with the method above + public String[] getAttributeNames() { + String[] strs = new String[attributes.size()]; + int i = 0; + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Attribute element = (Attribute) iter.next(); + strs[i++] = element.type; + } + return strs; + } + + + + public ISourceContext getSourceContext() { + if ((bitflag&DISCOVERED_SOURCECONTEXT)==0) { + bitflag|=DISCOVERED_SOURCECONTEXT; + Attribute foundIt = null; + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (o instanceof AjASMAttribute) { + AjASMAttribute element = (AjASMAttribute) o; + if (element.type.equals(AjAttribute.SourceContextAttribute.AttributeName)) { + foundIt = element; + SourceContextAttribute sca = (SourceContextAttribute)((AjASMAttribute)element).unpack(this); + if (super.getSourceContext()==SourceContextImpl.UNKNOWN_SOURCE_CONTEXT) { + super.setSourceContext(new SourceContextImpl(this)); + } + ((SourceContextImpl)super.getSourceContext()).configureFromAttribute(sca.getSourceFileName(),sca.getLineBreaks()); + break; + } + } + } + if (foundIt!=null) attributes.remove(foundIt); // Save space + } + return super.getSourceContext(); + } + + public WeaverStateInfo getWeaverState() { + if ((bitflag&DISCOVERED_WEAVERSTATEINFO)==0) { + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (o instanceof AjASMAttribute) { + AjASMAttribute element = (AjASMAttribute) o; + if (element.type.equals(AjAttribute.WeaverState.AttributeName)) { + WeaverState wsInfo = (WeaverState)((AjASMAttribute)element).unpack(this); + weaverStateInfo = wsInfo.reify(); + break; + } + } + } + bitflag|=DISCOVERED_WEAVERSTATEINFO; + } + return weaverStateInfo; + } + + public String getDeclaredGenericSignature() { + return declaredSignature; + } + + public Collection getTypeMungers() { + if ((bitflag&DISCOVERED_TYPEMUNGERS)==0) { + typeMungers = new ArrayList(); + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (o instanceof AjASMAttribute) { + AjASMAttribute element = (AjASMAttribute) o; + if (element.type.equals(AjAttribute.TypeMunger.AttributeName)) { + TypeMunger typeMunger = (TypeMunger)((AjASMAttribute)element).unpack(this); + typeMungers.add(typeMunger.reify(w,getResolvedTypeX())); + } + } + } + bitflag|=DISCOVERED_TYPEMUNGERS; + } + return typeMungers; + } + + public Collection getPrivilegedAccesses() { + if ((bitflag&DISCOVERED_PRIVILEGEDACCESSES)==0) { + privilegedAccesses = new ArrayList(); + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (o instanceof AjASMAttribute) { + AjASMAttribute element = (AjASMAttribute) o; + if (element.type.equals(AjAttribute.PrivilegedAttribute.AttributeName)) { + PrivilegedAttribute privilegedAttribute = (PrivilegedAttribute)((AjASMAttribute)element).unpack(this); + ResolvedMember[] pas =privilegedAttribute.getAccessedMembers(); + for (int i = 0; i < pas.length; i++) { + privilegedAccesses.add(pas[i]); + } + } + } + } + bitflag|=DISCOVERED_PRIVILEGEDACCESSES; + } + return privilegedAccesses; + } + + public TypeVariable[] getTypeVariables() { + ensureSignatureUnpacked(); + return typeVariables; + } + + private Signature.FormalTypeParameter[] formalsForResolution = null; + + private void ensureSignatureUnpacked() { + if ((bitflag&SIGNATURE_UNPACKED)!=0) return; + typeVariables=TypeVariable.NONE; + if (!getResolvedTypeX().getWorld().isInJava5Mode()) { + bitflag|=SIGNATURE_UNPACKED; + return; + } + if (declaredSignature!=null) { + GenericSignatureParser parser = new GenericSignatureParser(); + Signature.ClassSignature cSig = parser.parseAsClassSignature(declaredSignature); + typeVariables = new TypeVariable[cSig.formalTypeParameters.length]; + for (int i = 0; i < typeVariables.length; i++) { + Signature.FormalTypeParameter ftp = cSig.formalTypeParameters[i]; + try { + typeVariables[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable( + ftp, + cSig.formalTypeParameters, + getResolvedTypeX().getWorld()); + } catch (GenericSignatureFormatException e) { + // this is a development bug, so fail fast with good info + throw new IllegalStateException( + "While getting the type variables for type " + this.toString() + + " with generic signature " + cSig + + " the following error condition was detected: " + e.getMessage()); + } + } + if (cSig != null) { + formalsForResolution = cSig.formalTypeParameters; + if (isNested()) { + // we have to find any type variables from the outer type before proceeding with resolution. + Signature.FormalTypeParameter[] extraFormals = getFormalTypeParametersFromOuterClass(); + if (extraFormals.length > 0) { + List allFormals = new ArrayList(); + for (int i = 0; i < formalsForResolution.length; i++) { + allFormals.add(formalsForResolution[i]); + } + for (int i = 0; i < extraFormals.length; i++) { + allFormals.add(extraFormals[i]); + } + formalsForResolution = new Signature.FormalTypeParameter[allFormals.size()]; + allFormals.toArray(formalsForResolution); + } + } + Signature.ClassTypeSignature superSig = cSig.superclassSignature; + try { + this.superclassType = + BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX( + superSig, formalsForResolution, getResolvedTypeX().getWorld()); + bitflag|=SUPERSET; + } catch (GenericSignatureFormatException e) { + // development bug, fail fast with good info + throw new IllegalStateException( + "While determing the generic superclass of " + getResolvedTypeX() + + " with generic signature " + declaredSignature + " the following error was detected: " + + e.getMessage()); + } + this.interfaceTypes = new ResolvedType[cSig.superInterfaceSignatures.length]; + for (int i = 0; i < cSig.superInterfaceSignatures.length; i++) { + try { + this.interfaceTypes[i] = + BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX( + cSig.superInterfaceSignatures[i], + formalsForResolution, + getResolvedTypeX().getWorld()); + + } catch (GenericSignatureFormatException e) { + // development bug, fail fast with good info + throw new IllegalStateException( + "While determing the generic superinterfaces of " + getResolvedTypeX() + + " with generic signature " + declaredSignature + " the following error was detected: " + + e.getMessage()); + } + } + if (isGeneric()) { + // update resolved typex to point at generic type not raw type. + ReferenceType genericType = (ReferenceType) this.resolvedTypeX.getGenericType(); + //genericType.setSourceContext(this.resolvedTypeX.getSourceContext()); + genericType.setStartPos(this.resolvedTypeX.getStartPos()); + this.resolvedTypeX = genericType; + } + } + + } + bitflag|=SIGNATURE_UNPACKED; + } + + + private ReferenceType getOuterClass() { + if (!isNested()) throw new IllegalStateException("Can't get the outer class of a non-nested type"); + int lastDollar = getResolvedTypeX().getName().lastIndexOf('$'); + String superClassName = getResolvedTypeX().getName().substring(0,lastDollar); + UnresolvedType outer = UnresolvedType.forName(superClassName); + return (ReferenceType) outer.resolve(getResolvedTypeX().getWorld()); + } + + private Signature.FormalTypeParameter[] getFormalTypeParametersFromOuterClass() { + List typeParameters = new ArrayList(); + ReferenceType outer = getOuterClass(); + ReferenceTypeDelegate outerDelegate = outer.getDelegate(); + if (!(outerDelegate instanceof AsmDelegate)) { + throw new IllegalStateException("How come we're in AsmObjectType resolving an inner type of something that is NOT a AsmObjectType??"); + } + AsmDelegate outerObjectType = (AsmDelegate) outerDelegate; + if (outerObjectType.isNested()) { + Signature.FormalTypeParameter[] parentParams = outerObjectType.getFormalTypeParametersFromOuterClass(); + for (int i = 0; i < parentParams.length; i++) { + typeParameters.add(parentParams[i]); + } + } + GenericSignatureParser parser = new GenericSignatureParser(); + String sig = outerObjectType.getDeclaredGenericSignature(); + if (sig!=null) { + Signature.ClassSignature outerSig = parser.parseAsClassSignature(sig); + if (outerSig != null) { + for (int i = 0; i < outerSig.formalTypeParameters .length; i++) { + typeParameters.add(outerSig.formalTypeParameters[i]); + } + } + } + + Signature.FormalTypeParameter[] ret = new Signature.FormalTypeParameter[typeParameters.size()]; + typeParameters.toArray(ret); + return ret; + } + // --- + + public boolean isInterface() { + return (classModifiers & Opcodes.ACC_INTERFACE)!=0; + } + + public String getRetentionPolicy() { + return retentionPolicy; + } + + public boolean isAnnotationWithRuntimeRetention() { + return isRuntimeRetention; + } + + public boolean isAnnotation() { + return (classModifiers & Opcodes.ACC_ANNOTATION)!=0; + } + + public boolean isEnum() { + return(classModifiers & Opcodes.ACC_ENUM)!=0; + } + + public int getModifiers() { + return classModifiers; + } + + + public ResolvedMember[] getDeclaredFields() { + ensureSignatureUnpacked(); + if ((bitflag&FIELDSFIXEDUP)==0) { + for (int i = 0; i < fields.length; i++) { + ((ResolvedMemberImpl)fields[i]).setDeclaringType(getResolvedTypeX()); + } + bitflag|=FIELDSFIXEDUP; + } + return fields; + } + + public ResolvedType[] getDeclaredInterfaces() { + if (interfaceTypes == null) { + if (interfaceNames==null || interfaceNames.length==0) { + interfaceTypes = new ResolvedType[0]; + } else { + interfaceTypes = new ResolvedType[interfaceNames.length]; + for (int i = 0; i < interfaceNames.length; i++) { + interfaceTypes[i] = w.resolve(interfaceNames[i].replace('/','.')); + } + } + interfaceNames=null; + ensureSignatureUnpacked(); + } + return interfaceTypes; + } + + + + public ResolvedMember[] getDeclaredMethods() { + ensureSignatureUnpacked(); + if ((bitflag&METHODSFIXEDUP)==0) { + for (int i = 0; i < methods.length; i++) { + ((ResolvedMemberImpl)methods[i]).setDeclaringType(getResolvedTypeX()); + } + bitflag|=METHODSFIXEDUP; + } + return methods; + } + + public ResolvedMember[] getDeclaredPointcuts() { + if ((bitflag & DISCOVERED_POINTCUTS)==0) { + List pcts = new ArrayList(); + List forRemoval = new ArrayList(); + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (o instanceof AjASMAttribute) { + AjASMAttribute element = (AjASMAttribute) o; + if (element.type.equals(AjAttribute.PointcutDeclarationAttribute.AttributeName)) { + PointcutDeclarationAttribute pointcut = (PointcutDeclarationAttribute)((AjASMAttribute)element).unpack(this); + pcts.add(pointcut.reify()); + forRemoval.add(element); + } + } + } + pointcuts = (ResolvedPointcutDefinition[])pcts.toArray(new ResolvedPointcutDefinition[]{}); + attributes.removeAll(forRemoval); + bitflag|=DISCOVERED_POINTCUTS; + } + return pointcuts; + } + + public Collection getDeclares() { + if ((bitflag & DISCOVERED_DECLARES)==0) { + declares = new ArrayList(); + List forRemoval = new ArrayList(); + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Object o = iter.next(); + if (o instanceof AjASMAttribute) { + AjASMAttribute element = (AjASMAttribute) o; + if (element.type.equals(AjAttribute.DeclareAttribute.AttributeName)) { + DeclareAttribute declare = (DeclareAttribute)((AjASMAttribute)element).unpack(this); + declares.add(declare.getDeclare()); + forRemoval.add(element); + } + } + } + attributes.removeAll(forRemoval); + bitflag|=DISCOVERED_DECLARES;//discoveredDeclares=true; + } + return declares; + } + + public ResolvedType getSuperclass() { + if ((bitflag&SUPERSET)==0) { + if (superclassName == null) { + // this type must be jlObject + superclassType = null; + } else { + superclassType = w.resolve(superclassName.replace('/','.')); + } + ensureSignatureUnpacked(); + superclassName=null; + bitflag|=SUPERSET; + } + return superclassType; + } + + public PerClause getPerClause() { + return perClause; + } + + public boolean isAspect() { + return isAspect; + } + + World getWorld() { return w; } + + // --- + // 14-Feb-06 the AsmDelegate is only for types that won't be 'woven', so they can't be a target + // to have new annotations added + public void addAnnotation(AnnotationX annotationX) { /* this method left blank on purpose*/ } + + public void ensureDelegateConsistent() { + // doesnt need to do anything until methods like addAnnotation() are implemented (i.e. methods that + // modify the delegate such that it differs from the on-disk contents) + } + +} diff --git a/weaver/src/org/aspectj/weaver/asm/AsmField.java b/weaver/src/org/aspectj/weaver/asm/AsmField.java new file mode 100644 index 000000000..d841a170a --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/AsmField.java @@ -0,0 +1,110 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + + +import org.aspectj.apache.bcel.classfile.GenericSignatureParser; +import org.aspectj.apache.bcel.classfile.Signature; +import org.aspectj.weaver.AnnotationAJ; +import org.aspectj.weaver.AnnotationX; +import org.aspectj.weaver.AnnotationsForMemberHolder; +import org.aspectj.weaver.ResolvedMemberImpl; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.UnresolvedType; +import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter; +import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException; + +public class AsmField extends ResolvedMemberImpl { + + private AsmDelegate classDelegate; + private AnnotationsForMemberHolder annos; + + private String genericSignature = null; + private boolean unpackedGenericSignature = false; + private UnresolvedType genericFieldType = null; + + public void setClassDelegate(AsmDelegate del) { classDelegate = del;} + public void setGenericSignature(String sig) { genericSignature = sig; } + + public AsmField(Kind kind, UnresolvedType declaringType,int modifiers,String name,String signature) { + super(kind,declaringType,modifiers,name,signature); + } + + public UnresolvedType getGenericReturnType() { + unpackGenericSignature(); + return genericFieldType; + } + + private void unpackGenericSignature() { + if (unpackedGenericSignature) { return; } + if (!classDelegate.getWorld().isInJava5Mode()) { + this.genericFieldType = getReturnType(); + return; + } + unpackedGenericSignature = true; + String gSig = genericSignature; + if (gSig != null) { + // get from generic + Signature.FieldTypeSignature fts = new GenericSignatureParser().parseAsFieldSignature(gSig); +// Signature.ClassSignature genericTypeSig = classDelegate.getGenericClassTypeSignature(); +// +// Signature.ClassSignature cSig = parser.parseAsClassSignature(declaredSignature); + + Signature.FormalTypeParameter[] parentFormals = classDelegate.getAllFormals(); + Signature.FormalTypeParameter[] typeVars = + ((parentFormals == null) ? new Signature.FormalTypeParameter[0] : parentFormals);//.formalTypeParameters); + Signature.FormalTypeParameter[] formals = + new Signature.FormalTypeParameter[parentFormals.length + typeVars.length]; + // put method formal in front of type formals for overriding in + // lookup + System.arraycopy(typeVars, 0, formals, 0, typeVars.length); + System.arraycopy(parentFormals, 0, formals, typeVars.length,parentFormals.length); + + try { + genericFieldType = BcelGenericSignatureToTypeXConverter + .fieldTypeSignature2TypeX(fts, formals, classDelegate.getWorld()); + } catch (GenericSignatureFormatException e) { + // development bug, fail fast with good info + throw new IllegalStateException( + "While determing the generic field type of " + + this.toString() + " with generic signature " + + gSig + " the following error was detected: " + + e.getMessage()); + } + } else { + genericFieldType = getReturnType(); + } + } + + + // --- + // annotation manipulation + public void addAnAnnotation(AnnotationAJ oneAnnotation) { + if (annos==null) annos = new AnnotationsForMemberHolder(classDelegate.getWorld()); + annos.addAnnotation(oneAnnotation); + } + + public AnnotationX[] getAnnotations() { + if (annos==null) return AnnotationX.NONE; + return annos.getAnnotations(); + } + + public ResolvedType[] getAnnotationTypes() { + if (annos==null) return ResolvedType.NONE; + return annos.getAnnotationTypes(); + } + + public boolean hasAnnotation(UnresolvedType ofType) { + if (annos==null) return false; + return annos.hasAnnotation(ofType); + } +} diff --git a/weaver/src/org/aspectj/weaver/asm/AsmMethod.java b/weaver/src/org/aspectj/weaver/asm/AsmMethod.java new file mode 100644 index 000000000..896e8d3f8 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/AsmMethod.java @@ -0,0 +1,272 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.aspectj.apache.bcel.classfile.GenericSignatureParser; +import org.aspectj.apache.bcel.classfile.Signature; +import org.aspectj.apache.bcel.classfile.Signature.TypeVariableSignature; +import org.aspectj.weaver.AjAttribute; +import org.aspectj.weaver.AnnotationAJ; +import org.aspectj.weaver.AnnotationX; +import org.aspectj.weaver.AnnotationsForMemberHolder; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.ResolvedMemberImpl; +import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.ShadowMunger; +import org.aspectj.weaver.TypeVariable; +import org.aspectj.weaver.UnresolvedType; +import org.aspectj.weaver.World; +import org.aspectj.weaver.AjAttribute.AdviceAttribute; +import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute; +import org.aspectj.weaver.AjAttribute.MethodDeclarationLineNumberAttribute; +import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter; +import org.aspectj.weaver.bcel.Utility; +import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException; +import org.aspectj.org.objectweb.asm.Attribute; + +public class AsmMethod extends ResolvedMemberImpl { + + // genericized version of return and parameter types + private boolean unpackedGenericSignature = false; + private String genericSignature = null; + private UnresolvedType genericReturnType = null; + private UnresolvedType[] genericParameterTypes = null; + private boolean canBeParameterized = false; + + private AnnotationsForMemberHolder annos; + + private EffectiveSignatureAttribute esAttribute = null; + private MethodDeclarationLineNumberAttribute mdlnAttribute = null; + private ShadowMunger shadowMunger = null; + private AsmDelegate classDelegate; + public List /*Attribute*/ attributes = Collections.EMPTY_LIST; + private boolean unpackedAspectJAttributes = false; + + + public AsmMethod(Kind kind, UnresolvedType declaringType,int modifiers,String name,String signature) { + super(kind,declaringType,modifiers,name,signature); + } + + public void setClassDelegate(AsmDelegate del) { classDelegate = del;} + public void setGenericSignature(String sig) { genericSignature = sig; } + + public boolean canBeParameterized() { + unpackGenericSignature(); + return canBeParameterized; + } + + public UnresolvedType[] getGenericParameterTypes() { + unpackGenericSignature(); + return genericParameterTypes; + } + + public UnresolvedType getGenericReturnType() { + unpackGenericSignature(); + return genericReturnType; + } + + + public World getWorld() { + return classDelegate.getWorld(); + } + + + private void unpackGenericSignature() { + if (unpackedGenericSignature) return; + if (!getWorld().isInJava5Mode()) { + this.genericReturnType = getReturnType(); + this.genericParameterTypes = getParameterTypes(); + return; + } + // ok, we have work to do... + unpackedGenericSignature = true; + String gSig = genericSignature; + if (gSig != null) { + Signature.MethodTypeSignature mSig = new GenericSignatureParser().parseAsMethodSignature(gSig); + if (mSig.formalTypeParameters.length > 0) { + // generic method declaration + canBeParameterized = true; + } + Signature.FormalTypeParameter[] parentFormals = classDelegate.getAllFormals(); + Signature.FormalTypeParameter[] formals = new + Signature.FormalTypeParameter[parentFormals.length + mSig.formalTypeParameters.length]; + // put method formal in front of type formals for overriding in lookup + System.arraycopy(mSig.formalTypeParameters,0,formals,0,mSig.formalTypeParameters.length); + System.arraycopy(parentFormals,0,formals,mSig.formalTypeParameters.length,parentFormals.length); + + typeVariables = new TypeVariable[mSig.formalTypeParameters.length]; + for (int i = 0; i < typeVariables.length; i++) { + Signature.FormalTypeParameter methodFtp = mSig.formalTypeParameters[i]; + try { + typeVariables[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable( + methodFtp, + mSig.formalTypeParameters, + getWorld()); + } catch (GenericSignatureFormatException e) { + // this is a development bug, so fail fast with good info + throw new IllegalStateException( + "While getting the type variables for method " + this.toString() + + " with generic signature " + mSig + + " the following error condition was detected: " + e.getMessage()); + } + } + + + + Signature.TypeSignature returnTypeSignature = mSig.returnType; + try { + genericReturnType = BcelGenericSignatureToTypeXConverter.typeSignature2TypeX( + returnTypeSignature, formals, + getWorld()); + } catch (GenericSignatureFormatException e) { +// development bug, fail fast with good info + throw new IllegalStateException( + "While determing the generic return type of " + this.toString() + + " with generic signature " + gSig + " the following error was detected: " + + e.getMessage()); + } + Signature.TypeSignature[] paramTypeSigs = mSig.parameters; + genericParameterTypes = new UnresolvedType[paramTypeSigs.length]; + for (int i = 0; i < paramTypeSigs.length; i++) { + try { + genericParameterTypes[i] = + BcelGenericSignatureToTypeXConverter.typeSignature2TypeX( + paramTypeSigs[i],formals,getWorld()); + } catch (GenericSignatureFormatException e) { +// development bug, fail fast with good info + throw new IllegalStateException( + "While determining the generic parameter types of " + this.toString() + + " with generic signature " + gSig + " the following error was detected: " + + e.getMessage()); + } + if (paramTypeSigs[i] instanceof TypeVariableSignature) { + canBeParameterized = true; + } + } + } else { + genericReturnType = getReturnType(); + genericParameterTypes = getParameterTypes(); + } + } + + public EffectiveSignatureAttribute getEffectiveSignature() { + unpackAspectJAttributes(); + return esAttribute; + } + + public ShadowMunger getAssociatedShadowMunger() { + unpackAspectJAttributes(); + return shadowMunger; + } + + public int getDeclarationLineNumber() { + unpackAspectJAttributes(); + if (mdlnAttribute==null) return -1; + else return (mdlnAttribute.getLineNumber()); + } + + public boolean isAjSynthetic() { + unpackAspectJAttributes(); + return super.isAjSynthetic(); + } + + private void unpackAspectJAttributes() { + if (unpackedAspectJAttributes) return; + List forRemoval = new ArrayList(); + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Attribute element = (Attribute) iter.next(); + if (element instanceof AjASMAttribute) { + if (element.type.equals(AjAttribute.AjSynthetic.AttributeName)) { + setAjSynthetic(true); + forRemoval.add(element); + } + if (element.type.equals(AjAttribute.MethodDeclarationLineNumberAttribute.AttributeName)) { + mdlnAttribute = (MethodDeclarationLineNumberAttribute)((AjASMAttribute)element).unpack(classDelegate); + forRemoval.add(element); + } + if (element.type.equals(AjAttribute.AdviceAttribute.AttributeName)) { + shadowMunger = ((AdviceAttribute)((AjASMAttribute)element).unpack(classDelegate)).reify(this,getWorld()); + forRemoval.add(element); + } + if (element.type.equals(AjAttribute.EffectiveSignatureAttribute.AttributeName)) { + esAttribute = (EffectiveSignatureAttribute)((AjASMAttribute)element).unpack(classDelegate); + forRemoval.add(element); + } + } + } + attributes.remove(forRemoval); + unpackedAspectJAttributes = true; + } + + // for testing - if we have this attribute, return it + public AjAttribute[] getAttributes(String name) { + List results = new ArrayList(); + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Attribute element = (Attribute) iter.next(); + if (element.type.equals(name) && (element instanceof AjASMAttribute)) { + results.add(((AjASMAttribute)element).unpack(this.classDelegate)); + } + } + return (AjAttribute[])results.toArray(new AjAttribute[]{}); + } + + // for testing - use with the method above + public String[] getAttributeNames(boolean onlyIncludeAjOnes) { + List strs = new ArrayList(); + int i = 0; + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Attribute element = (Attribute) iter.next(); + if (!onlyIncludeAjOnes || (element.type.startsWith(AjAttribute.AttributePrefix) && element instanceof AjASMAttribute)) + strs.add(element.type); + } + return (String[])strs.toArray(new String[]{}); + } + + public String[] getParameterNames() { + if (super.getParameterNames()==null) setParameterNames(Utility.makeArgNames(getArity())); + return super.getParameterNames(); + } + + public ISourceContext getSourceContext() { + return classDelegate.getSourceContext(); + } + + // --- + // annotation manipulation + + public void addAnAnnotation(AnnotationAJ oneAnnotation) { + if (annos==null) annos = new AnnotationsForMemberHolder(getWorld()); + annos.addAnnotation(oneAnnotation); + } + + public AnnotationX[] getAnnotations() { + if (annos==null) return AnnotationX.NONE; + return annos.getAnnotations(); + } + + public ResolvedType[] getAnnotationTypes() { + if (annos==null) return ResolvedType.NONE; + return annos.getAnnotationTypes(); + } + + public boolean hasAnnotation(UnresolvedType ofType) { + if (annos==null) return false; + return annos.hasAnnotation(ofType); + } + // --- + +} diff --git a/weaver/src/org/aspectj/weaver/asm/EmptyVisitor.java b/weaver/src/org/aspectj/weaver/asm/EmptyVisitor.java new file mode 100644 index 000000000..89776027e --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/EmptyVisitor.java @@ -0,0 +1,28 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import org.aspectj.org.objectweb.asm.AnnotationVisitor; + +class EmptyVisitor implements AnnotationVisitor { + + public void visit(String arg0, Object arg1) {} + + public void visitEnum(String arg0, String arg1, String arg2) {} + + public AnnotationVisitor visitAnnotation(String arg0, String arg1) {return this;} + + public AnnotationVisitor visitArray(String arg0) {return this;} + + public void visitEnd() {} + +} \ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/asm/FdVisitor.java b/weaver/src/org/aspectj/weaver/asm/FdVisitor.java new file mode 100644 index 000000000..7263f0297 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/FdVisitor.java @@ -0,0 +1,38 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + + +import org.aspectj.org.objectweb.asm.AnnotationVisitor; +import org.aspectj.org.objectweb.asm.Attribute; +import org.aspectj.org.objectweb.asm.FieldVisitor; +import org.aspectj.weaver.AnnotationAJ; + +/** + * Constructed with an AsmField to 'fill in' with attributes and annotations + */ +class FdVisitor implements FieldVisitor { + AsmField field; + public FdVisitor(AsmField rm) { field = rm;} + + public AnnotationVisitor visitAnnotation(String desc, boolean isVisible) { + AnnotationAJ annotation = new AnnotationAJ(desc,isVisible); + field.addAnAnnotation(annotation); +// if (am.annotations==null) am.annotations = new ArrayList(); +// am.annotations.add(annotation); + return new AnnVisitor(annotation); + } + + public void visitAttribute(Attribute arg0) {} + public void visitEnd() {} + +} \ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/asm/MethVisitor.java b/weaver/src/org/aspectj/weaver/asm/MethVisitor.java new file mode 100644 index 000000000..74a510716 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/MethVisitor.java @@ -0,0 +1,72 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import java.util.ArrayList; +import java.util.Collections; + +import org.aspectj.weaver.AnnotationAJ; +import org.aspectj.org.objectweb.asm.AnnotationVisitor; +import org.aspectj.org.objectweb.asm.Attribute; +import org.aspectj.org.objectweb.asm.Label; +import org.aspectj.org.objectweb.asm.MethodVisitor; + +/** + * Constructed with an AsmMethod to 'fill in' with attributes and annotations. + * Bit of a shame we can't "terminate" before visiting the code as we know + * we aren't interested in any of it. + */ +class MethVisitor implements MethodVisitor { + AsmMethod am; + + public MethVisitor(AsmMethod rm) { am = rm;} + + public AnnotationVisitor visitAnnotationDefault() { + return new EmptyVisitor(); // means we are ignoring default values - is that a problem? + } + + public AnnotationVisitor visitAnnotation(String desc, boolean isVisible) { + AnnotationAJ annotation = new AnnotationAJ(desc,isVisible); + am.addAnAnnotation(annotation); + return new AnnVisitor(annotation); + } + + public void visitAttribute(Attribute attr) { + if (am.attributes==Collections.EMPTY_LIST) am.attributes = new ArrayList(); + am.attributes.add(attr); + } + + public AnnotationVisitor visitParameterAnnotation(int arg0, String arg1, boolean arg2) { + return null; // AJ doesnt support these yet + } + + public void visitCode() {} + public void visitInsn(int arg0) {} + public void visitIntInsn(int arg0, int arg1) {} + public void visitVarInsn(int arg0, int arg1) {} + public void visitTypeInsn(int arg0, String arg1) {} + public void visitFieldInsn(int arg0, String arg1, String arg2, String arg3) {} + public void visitMethodInsn(int arg0, String arg1, String arg2, String arg3) {} + public void visitJumpInsn(int arg0, Label arg1) {} + public void visitLabel(Label arg0) {} + public void visitLdcInsn(Object arg0) {} + public void visitIincInsn(int arg0, int arg1) {} + public void visitTableSwitchInsn(int arg0, int arg1, Label arg2, Label[] arg3) {} + public void visitLookupSwitchInsn(Label arg0, int[] arg1, Label[] arg2) {} + public void visitMultiANewArrayInsn(String arg0, int arg1) {} + public void visitTryCatchBlock(Label arg0, Label arg1, Label arg2, String arg3) {} + public void visitLocalVariable(String arg0, String arg1, String arg2, Label arg3, Label arg4, int arg5) {} + public void visitLineNumber(int arg0, Label arg1) {} + public void visitMaxs(int arg0, int arg1) {} + public void visitEnd() {} + +} \ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/asm/TypeVisitor.java b/weaver/src/org/aspectj/weaver/asm/TypeVisitor.java new file mode 100644 index 000000000..31cac4ded --- /dev/null +++ b/weaver/src/org/aspectj/weaver/asm/TypeVisitor.java @@ -0,0 +1,222 @@ +/* ******************************************************************* + * Copyright (c) 2006 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement IBM initial implementation + * ******************************************************************/ +package org.aspectj.weaver.asm; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.aspectj.weaver.AnnotationAJ; +import org.aspectj.weaver.AnnotationNameValuePair; +import org.aspectj.weaver.AnnotationTargetKind; +import org.aspectj.weaver.AnnotationValue; +import org.aspectj.weaver.ArrayAnnotationValue; +import org.aspectj.weaver.ResolvedMember; +import org.aspectj.weaver.UnresolvedType; +import org.aspectj.weaver.AjAttribute.Aspect; +import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; +import org.aspectj.org.objectweb.asm.AnnotationVisitor; +import org.aspectj.org.objectweb.asm.Attribute; +import org.aspectj.org.objectweb.asm.ClassVisitor; +import org.aspectj.org.objectweb.asm.FieldVisitor; +import org.aspectj.org.objectweb.asm.MethodVisitor; + + +public class TypeVisitor implements ClassVisitor { + + private final AsmDelegate relatedDelegate; + + // Populated as we go along, then dealt with at the end of the visit - setting + // state on the relatedDelegate as appropriate + private List methodsList = new ArrayList(); + private List fieldsList = new ArrayList(); + private List attributes = new ArrayList(); + protected List annotations = new ArrayList(); + + private String name = null; + + TypeVisitor(AsmDelegate delegate) { + relatedDelegate = delegate; + } + + public void visit(int version, int mods, String name, String signature, String superclassname, String[] interfacenames) { + relatedDelegate.superclassName = superclassname; + relatedDelegate.interfaceNames = interfacenames; + relatedDelegate.classModifiers = mods; + relatedDelegate.declaredSignature = signature; // Ljava/lang/Object;Ljava/util/Collection; + relatedDelegate.isGenericType = (signature!=null && signature.charAt(0)=='<'); +// relatedDelegate.erasureSignature=name; // java/util/List; + this.name = name; + } + + public AnnotationVisitor visitAnnotation(String typeSignature, boolean vis) { + AnnotationAJ annotation = new AnnotationAJ(typeSignature,vis); + annotations.add(annotation); + return new AnnVisitor(annotation); + } + + /** + * Store up the attributes - the only one to look out for is the version one, + * as it will tell us the format of all the others. + */ + public void visitAttribute(Attribute attr) { +// System.err.println("encountered attribute "+attr.type); + if (attr.type.equals(WeaverVersionInfo.AttributeName)) { + WeaverVersionInfo wv = (WeaverVersionInfo)((AjASMAttribute)attr).unpack(relatedDelegate); + relatedDelegate.weaverVersion = wv; + } else { + attributes.add(attr); + } + } + + public void visitInnerClass(String name, String outer, String inner, int access) { + if (name.equals(this.name)) { + relatedDelegate.isNested=true; + relatedDelegate.isAnonymous = (inner==null); + } + } + + public FieldVisitor visitField(int modifiers, String name, String descType, String signature, Object value) { + AsmField rm = new AsmField(ResolvedMember.FIELD,this.relatedDelegate.getResolvedTypeX(),modifiers,name,descType); + rm.setGenericSignature(signature); + rm.setClassDelegate(relatedDelegate); + fieldsList.add(rm); + if (AsmDelegate.careAboutMemberAnnotationsAndAttributes) { + return new FdVisitor(rm); + } else { + return null; + } + } + + public MethodVisitor visitMethod(int modifiers, String name, String desc, String signature, String[] exceptions) { + if (Modifier.isInterface(relatedDelegate.getModifiers()) && Modifier.isAbstract(modifiers)) // wtf? (see testIterator in WorldTestCase) + modifiers = modifiers | Modifier.INTERFACE; + AsmMethod rm = new AsmMethod(ResolvedMember.METHOD,this.relatedDelegate.getResolvedTypeX(),modifiers,name,desc); + rm.setGenericSignature(signature); + rm.setClassDelegate(relatedDelegate); + if (exceptions!=null && exceptions.length!=0) { + UnresolvedType[] excs = new UnresolvedType[exceptions.length]; + for (int i = 0; i < exceptions.length; i++) { + excs[i]=UnresolvedType.forSignature("L"+exceptions[i]+";"); + } + rm.setCheckedExceptions(excs); + } + methodsList.add(rm); + if (AsmDelegate.careAboutMemberAnnotationsAndAttributes) { + return new MethVisitor(rm); + } else { + return null; + } + } + + public void visitSource(String sourcefilename, String debug) { + relatedDelegate.setSourcefilename(sourcefilename); + } + + public void visitOuterClass(String arg0, String arg1, String arg2) {/*DeliberatelyBlank*/} + + // --- + + /** + * Pick through what we learned whilst visiting the type - and set what we need to on the + * related delegate. Discard what we can now. + */ + public void visitEnd() { + relatedDelegate.methods = (ResolvedMember[])methodsList.toArray(new ResolvedMember[]{}); + methodsList.clear(); + relatedDelegate.fields = (ResolvedMember[])fieldsList.toArray(new ResolvedMember[]{}); + fieldsList.clear(); + // Fast pass of the attributes, unpacking lightweight ones. Fast ones are: + // Aspect + if (attributes.size()>0) { + relatedDelegate.attributes = new ArrayList(); + for (Iterator iter = attributes.iterator(); iter.hasNext();) { + Attribute element = (Attribute) iter.next(); + //System.err.println("Processing:"+element); + if (element instanceof AjASMAttribute) { + // Aspect + if (element.type.equals(Aspect.AttributeName)) { + Aspect aspectAttribute = (Aspect)((AjASMAttribute)element).unpack(relatedDelegate); + relatedDelegate.perClause = aspectAttribute.reify(null); // param not used + relatedDelegate.isAspect = true; + continue; + } + } + relatedDelegate.attributes.add(element); + } + } + + // Similar thing for annotations, unpacking lightweight/common ones. These are: + // Retention + // For annotations, retention policy should default to CLASS if not set. + boolean retentionPolicySet = false; + if (annotations.size()>0) relatedDelegate.annotations = new ArrayList(); + for (Iterator iter = annotations.iterator(); iter.hasNext();) { + AnnotationAJ element = (AnnotationAJ) iter.next(); + + // Retention + if (element.getTypeSignature().equals(AnnotationRetention)) { + relatedDelegate.retentionPolicy = element.getStringValueOf("value"); + relatedDelegate.isRuntimeRetention = relatedDelegate.retentionPolicy.equals("RUNTIME"); + retentionPolicySet=true; +// continue; // possible optimization - dont store them, we've pulled out all the relevant stuff + } + + // Target + if (element.getTypeSignature().equals(AnnotationTarget)) { + setDelegateFieldsForAnnotationTarget(element.getNameValuePairs()); +// continue; // possible optimization - dont store them, we've pulled out all the relevant stuff + } + + relatedDelegate.annotations.add(element); + } + if (relatedDelegate.isAnnotation() && !retentionPolicySet) { relatedDelegate.retentionPolicy="CLASS"; relatedDelegate.isRuntimeRetention=false;} + } + + private void setDelegateFieldsForAnnotationTarget(List/*AnnotationNameValuePair*/ nvpairs) { + // Should only be one nvpair, thats the value + if (nvpairs.size()>0) { + boolean canTargetType = false; + ArrayAnnotationValue targetsArray = (ArrayAnnotationValue)((AnnotationNameValuePair)nvpairs.get(0)).getValue(); + AnnotationValue[] targets = targetsArray.getValues(); + List targetKinds = new ArrayList(); + for (int i = 0; i < targets.length; i++) { + String targetKind = targets[i].stringify(); + if (targetKind.equals("ANNOTATION_TYPE")) { + targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE); + } else if (targetKind.equals("CONSTRUCTOR")) { + targetKinds.add(AnnotationTargetKind.CONSTRUCTOR); + } else if (targetKind.equals("FIELD")) { + targetKinds.add(AnnotationTargetKind.FIELD); + } else if (targetKind.equals("LOCAL_VARIABLE")) { + targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE); + } else if (targetKind.equals("METHOD")) { + targetKinds.add(AnnotationTargetKind.METHOD); + } else if (targetKind.equals("PACKAGE")) { + targetKinds.add(AnnotationTargetKind.PACKAGE); + } else if (targetKind.equals("PARAMETER")) { + targetKinds.add(AnnotationTargetKind.PARAMETER); + } else if (targetKind.equals("TYPE")) { + targetKinds.add(AnnotationTargetKind.TYPE); canTargetType = true; + } + } + relatedDelegate.targetKinds = (AnnotationTargetKind[])targetKinds.toArray(new AnnotationTargetKind[]{}); + relatedDelegate.canAnnotationTargetType = canTargetType; + } + } + + // --- + private static final String AnnotationRetention = "Ljava/lang/annotation/Retention;"; + private static final String AnnotationTarget = "Ljava/lang/annotation/Target;"; + +} \ No newline at end of file -- 2.39.5