From f7fd9e7bf37d14fad7cacc6b24221d811e5077fa Mon Sep 17 00:00:00 2001 From: aclement Date: Thu, 10 Sep 2009 03:59:33 +0000 Subject: [PATCH] refactoring --- .../apache/bcel/classfile/ClassVisitor.java | 134 +- .../apache/bcel/classfile/Constant.java | 142 +- .../apache/bcel/classfile/ConstantClass.java | 135 +- .../apache/bcel/classfile/ConstantDouble.java | 122 +- .../apache/bcel/classfile/ConstantObject.java | 17 +- .../apache/bcel/classfile/ConstantPool.java | 1154 +++++++++-------- .../apache/bcel/classfile/JavaClass.java | 90 +- .../apache/bcel/classfile/Utility.java | 84 +- .../classfile/annotation/AnnotationGen.java | 174 ++- .../annotation/ElementNameValuePairGen.java | 57 +- .../annotation/SimpleElementValueGen.java | 435 ++++--- .../aspectj/apache/bcel/generic/ClassGen.java | 410 +++--- .../bcel/generic/InstructionFactory.java | 5 +- .../apache/bcel/generic/InstructionList.java | 34 +- .../apache/bcel/generic/MethodGen.java | 6 +- .../org/aspectj/apache/bcel/generic/Type.java | 41 +- .../tests/EnclosingMethodAttributeTest.java | 78 +- .../bcel/classfile/tests/UtilTests.java | 2 +- 18 files changed, 1465 insertions(+), 1655 deletions(-) diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java index f44b178ba..9513e02f9 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java @@ -60,56 +60,90 @@ import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleParameterAnnot */ /** - * Interface to make use of the Visitor pattern programming style. - * I.e. a class that implements this interface can traverse the contents of - * a Java class just by calling the `accept' method which all classes have. - * - * Implemented by wish of - * Boris Bokowski. - * - * @version $Id: ClassVisitor.java,v 1.2 2008/05/28 23:53:01 aclement Exp $ - * @author M. Dahm + * Interface to make use of the Visitor pattern programming style. I.e. a class that implements this interface can traverse the + * contents of a Java class just by calling the `accept' method which all classes have. + * + * Implemented by wish of Boris Bokowski. + * + * @version $Id: ClassVisitor.java,v 1.3 2009/09/10 03:59:33 aclement Exp $ + * @author M. Dahm */ public interface ClassVisitor { - public void visitCode(Code obj); - public void visitCodeException(CodeException obj); - public void visitConstantClass(ConstantClass obj); - public void visitConstantDouble(ConstantDouble obj); - public void visitConstantFieldref(ConstantFieldref obj); - public void visitConstantFloat(ConstantFloat obj); - public void visitConstantInteger(ConstantInteger obj); - public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj); - public void visitConstantLong(ConstantLong obj); - public void visitConstantMethodref(ConstantMethodref obj); - public void visitConstantNameAndType(ConstantNameAndType obj); - public void visitConstantPool(ConstantPool obj); - public void visitConstantString(ConstantString obj); - public void visitConstantUtf8(ConstantUtf8 obj); - public void visitConstantValue(ConstantValue obj); - public void visitDeprecated(Deprecated obj); - public void visitExceptionTable(ExceptionTable obj); - public void visitField(Field obj); - public void visitInnerClass(InnerClass obj); - public void visitInnerClasses(InnerClasses obj); - public void visitJavaClass(JavaClass obj); - public void visitLineNumber(LineNumber obj); - public void visitLineNumberTable(LineNumberTable obj); - public void visitLocalVariable(LocalVariable obj); - public void visitLocalVariableTable(LocalVariableTable obj); - public void visitMethod(Method obj); - public void visitSignature(Signature obj); - public void visitSourceFile(SourceFile obj); - public void visitSynthetic(Synthetic obj); - public void visitUnknown(Unknown obj); - public void visitStackMap(StackMap obj); - public void visitStackMapEntry(StackMapEntry obj); - - // Java5 - public void visitEnclosingMethod(EnclosingMethod obj); - public void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations obj); - public void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations obj); - public void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations obj); - public void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations obj); - public void visitAnnotationDefault(AnnotationDefault obj); - public void visitLocalVariableTypeTable(LocalVariableTypeTable obj); + public void visitCode(Code obj); + + public void visitCodeException(CodeException obj); + + public void visitConstantClass(ConstantClass obj); + + public void visitConstantDouble(ConstantDouble obj); + + public void visitConstantFieldref(ConstantFieldref obj); + + public void visitConstantFloat(ConstantFloat obj); + + public void visitConstantInteger(ConstantInteger obj); + + public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj); + + public void visitConstantLong(ConstantLong obj); + + public void visitConstantMethodref(ConstantMethodref obj); + + public void visitConstantNameAndType(ConstantNameAndType obj); + + public void visitConstantPool(ConstantPool obj); + + public void visitConstantString(ConstantString obj); + + public void visitConstantUtf8(ConstantUtf8 obj); + + public void visitConstantValue(ConstantValue obj); + + public void visitDeprecated(Deprecated obj); + + public void visitExceptionTable(ExceptionTable obj); + + public void visitField(Field obj); + + public void visitInnerClass(InnerClass obj); + + public void visitInnerClasses(InnerClasses obj); + + public void visitJavaClass(JavaClass obj); + + public void visitLineNumber(LineNumber obj); + + public void visitLineNumberTable(LineNumberTable obj); + + public void visitLocalVariable(LocalVariable obj); + + public void visitLocalVariableTable(LocalVariableTable obj); + + public void visitMethod(Method obj); + + public void visitSignature(Signature obj); + + public void visitSourceFile(SourceFile obj); + + public void visitSynthetic(Synthetic obj); + + public void visitUnknown(Unknown obj); + + public void visitStackMap(StackMap obj); + + public void visitStackMapEntry(StackMapEntry obj); + + public void visitEnclosingMethod(EnclosingMethod obj); + + public void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations obj); + + public void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations obj); + + public void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations obj); + + public void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations obj); + + public void visitAnnotationDefault(AnnotationDefault obj); + + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj); } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java index 32ee205ca..53a5c4c7f 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java @@ -54,85 +54,91 @@ package org.aspectj.apache.bcel.classfile; * . */ -import org.aspectj.apache.bcel.Constants; -import java.io.*; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +import org.aspectj.apache.bcel.Constants; /** - * Abstract superclass for classes to represent the different constant types - * in the constant pool of a class file. The classes keep closely to - * the JVM specification. - * - * @version $Id: Constant.java,v 1.3 2008/05/28 23:53:01 aclement Exp $ - * @author M. Dahm + * Abstract superclass for classes to represent the different constant types in the constant pool of a class file. The classes keep + * closely to the JVM specification. + * + * @version $Id: Constant.java,v 1.4 2009/09/10 03:59:33 aclement Exp $ + * @author M. Dahm */ public abstract class Constant implements Cloneable, Node, Serializable { - /* In fact this tag is redundant since we can distinguish different - * `Constant' objects by their type, i.e., via `instanceof'. In some - * places we will use the tag for switch()es anyway. - * - * First, we want match the specification as closely as possible. Second we - * need the tag as an index to select the corresponding class name from the - * `CONSTANT_NAMES' array. - */ - protected byte tag; - Constant(byte tag) { this.tag = tag; } + protected byte tag; + + Constant(byte tag) { + this.tag = tag; + } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public abstract void accept(ClassVisitor v); + /** + * Visitor pattern + */ + public abstract void accept(ClassVisitor v); - public abstract void dump(DataOutputStream file) throws IOException; + /** + * Serialize the constant to an output stream + */ + public abstract void dump(DataOutputStream dataOutputStream) throws IOException; - /** - * @return Tag of constant, i.e., its type. No setTag() method to avoid - * confusion. - */ - public final byte getTag() { return tag; } + public final byte getTag() { + return tag; + } - /** - * @return String representation. - */ - public String toString() { - return Constants.CONSTANT_NAMES[tag] + "[" + tag + "]"; - } + @Override + public String toString() { + return Constants.CONSTANT_NAMES[tag] + "[" + tag + "]"; + } - /** - * @return deep copy of this constant - */ - public Constant copy() { - try { - return (Constant)super.clone(); - } catch(CloneNotSupportedException e) {} + /** + * @return deep copy of this constant + */ + public Constant copy() { + try { + return (Constant) super.clone(); + } catch (CloneNotSupportedException e) { + } - return null; - } + return null; + } - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } - static final Constant readConstant(DataInputStream file) throws IOException, ClassFormatException { - byte b = file.readByte(); - switch(b) { - case Constants.CONSTANT_Class: return new ConstantClass(file); - case Constants.CONSTANT_NameAndType: return new ConstantNameAndType(file); - case Constants.CONSTANT_Utf8: return new ConstantUtf8(file); - case Constants.CONSTANT_Fieldref: return new ConstantFieldref(file); - case Constants.CONSTANT_Methodref: return new ConstantMethodref(file); - case Constants.CONSTANT_InterfaceMethodref: return new ConstantInterfaceMethodref(file); - case Constants.CONSTANT_String: return new ConstantString(file); - case Constants.CONSTANT_Integer: return new ConstantInteger(file); - case Constants.CONSTANT_Float: return new ConstantFloat(file); - case Constants.CONSTANT_Long: return new ConstantLong(file); - case Constants.CONSTANT_Double: return new ConstantDouble(file); - default: - throw new ClassFormatException("Invalid byte tag in constant pool: " + b); - } - } + static final Constant readConstant(DataInputStream file) throws IOException, ClassFormatException { + byte b = file.readByte(); + switch (b) { + case Constants.CONSTANT_Class: + return new ConstantClass(file); + case Constants.CONSTANT_NameAndType: + return new ConstantNameAndType(file); + case Constants.CONSTANT_Utf8: + return new ConstantUtf8(file); + case Constants.CONSTANT_Fieldref: + return new ConstantFieldref(file); + case Constants.CONSTANT_Methodref: + return new ConstantMethodref(file); + case Constants.CONSTANT_InterfaceMethodref: + return new ConstantInterfaceMethodref(file); + case Constants.CONSTANT_String: + return new ConstantString(file); + case Constants.CONSTANT_Integer: + return new ConstantInteger(file); + case Constants.CONSTANT_Float: + return new ConstantFloat(file); + case Constants.CONSTANT_Long: + return new ConstantLong(file); + case Constants.CONSTANT_Double: + return new ConstantDouble(file); + default: + throw new ClassFormatException("Invalid byte tag in constant pool: " + b); + } + } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantClass.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantClass.java index 9c3b7d69c..da6326245 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantClass.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantClass.java @@ -54,103 +54,64 @@ package org.aspectj.apache.bcel.classfile; * . */ -import org.aspectj.apache.bcel.Constants; -import java.io.*; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to a (external) class. - * - * @version $Id: ConstantClass.java,v 1.3 2008/05/28 23:53:01 aclement Exp $ - * @author M. Dahm - * @see Constant +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract Constant class and + * represents a reference to a (external) class. + * + * @version $Id: ConstantClass.java,v 1.4 2009/09/10 03:59:33 aclement Exp $ + * @author M. Dahm + * @author Andy Clement */ public final class ConstantClass extends Constant implements ConstantObject { - private int name_index; // Identical to ConstantString except for the name - - /** - * Initialize from another object. - */ - public ConstantClass(ConstantClass c) { - this(c.getNameIndex()); - } - - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantClass(DataInputStream file) throws IOException - { - super(Constants.CONSTANT_Class); - this.name_index = file.readUnsignedShort(); -// this(file.readUnsignedShort()); - } + private int nameIndex; - /** - * @param name_index Name index in constant pool. Should refer to a - * ConstantUtf8. - */ - public ConstantClass(int name_index) { - super(Constants.CONSTANT_Class); - this.name_index = name_index; - } + public ConstantClass(ConstantClass c) { + this(c.getNameIndex()); + } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(ClassVisitor v) { - v.visitConstantClass(this); - } + ConstantClass(DataInputStream file) throws IOException { + super(Constants.CONSTANT_Class); + this.nameIndex = file.readUnsignedShort(); + } - /** - * Dump constant class to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeShort(name_index); - } + public ConstantClass(int nameIndex) { + super(Constants.CONSTANT_Class); + this.nameIndex = nameIndex; + } - /** - * @return Name index in constant pool of class name. - */ - public final int getNameIndex() { return name_index; } + @Override + public void accept(ClassVisitor v) { + v.visitConstantClass(this); + } - /** - * @param name_index. - */ - public final void setNameIndex(int name_index) { - this.name_index = name_index; - } + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(nameIndex); + } + public final int getNameIndex() { + return nameIndex; + } - /** @return String object - */ - public Object getConstantValue(ConstantPool cp) { - Constant c = cp.getConstant(name_index, Constants.CONSTANT_Utf8); - return ((ConstantUtf8)c).getBytes(); - } + public final void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } - /** @return dereferenced string - */ - public String getBytes(ConstantPool cp) { - return (String)getConstantValue(cp); - } + public String getConstantValue(ConstantPool cp) { + return cp.getConstantUtf8(nameIndex).getBytes(); + // Constant c = cp.getConstant(nameIndex, Constants.CONSTANT_Utf8); + // return ((ConstantUtf8) c).getBytes(); + } - /** - * @return String representation. - */ - public final String toString() { - return super.toString() + "(name_index = " + name_index + ")"; - } + @Override + public final String toString() { + return super.toString() + "(name_index = " + nameIndex + ")"; + } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantDouble.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantDouble.java index 7c9c95732..34e5b3cfc 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantDouble.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantDouble.java @@ -54,89 +54,57 @@ package org.aspectj.apache.bcel.classfile; * . */ -import org.aspectj.apache.bcel.Constants; -import java.io.*; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; -/** - * This class is derived from the abstract - * Constant class - * and represents a reference to a Double object. - * - * @version $Id: ConstantDouble.java,v 1.3 2008/05/28 23:53:01 aclement Exp $ - * @author M. Dahm - * @see Constant +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract Constant class and + * represents a reference to a Double object. + * + * @version $Id: ConstantDouble.java,v 1.4 2009/09/10 03:59:33 aclement Exp $ + * @author M. Dahm + * @author Andy Clement */ public final class ConstantDouble extends Constant implements ConstantObject { - private double bytes; + private double value; + + public ConstantDouble(double value) { + super(Constants.CONSTANT_Double); + this.value = value; + } + + public ConstantDouble(ConstantDouble c) { + this(c.getBytes()); + } + + ConstantDouble(DataInputStream file) throws IOException { + this(file.readDouble()); + } - /** - * @param bytes Data - */ - public ConstantDouble(double bytes) { - super(Constants.CONSTANT_Double); - this.bytes = bytes; - } + @Override + public void accept(ClassVisitor v) { + v.visitConstantDouble(this); + } - /** - * Initialize from another object. - */ - public ConstantDouble(ConstantDouble c) { - this(c.getBytes()); - } + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeDouble(value); + } - /** - * Initialize instance from file data. - * - * @param file Input stream - * @throws IOException - */ - ConstantDouble(DataInputStream file) throws IOException - { - this(file.readDouble()); - } + public final double getBytes() { + return value; + } - /** - * Called by objects that are traversing the nodes of the tree implicitely - * defined by the contents of a Java class. I.e., the hierarchy of methods, - * fields, attributes, etc. spawns a tree of objects. - * - * @param v Visitor object - */ - public void accept(ClassVisitor v) { - v.visitConstantDouble(this); - } - /** - * Dump constant double to file stream in binary format. - * - * @param file Output file stream - * @throws IOException - */ - public final void dump(DataOutputStream file) throws IOException - { - file.writeByte(tag); - file.writeDouble(bytes); - } - /** - * @return data, i.e., 8 bytes. - */ - public final double getBytes() { return bytes; } - /** - * @param bytes. - */ - public final void setBytes(double bytes) { - this.bytes = bytes; - } - /** - * @return String representation. - */ - public final String toString() - { - return super.toString() + "(bytes = " + bytes + ")"; - } + @Override + public final String toString() { + return super.toString() + "(bytes = " + value + ")"; + } - /** @return Double object - */ - public Object getConstantValue(ConstantPool cp) { - return new Double(bytes); - } + public Double getConstantValue(ConstantPool cp) { + return new Double(value); + } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantObject.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantObject.java index 1468b4ae8..70e9b1d0d 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantObject.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantObject.java @@ -54,16 +54,13 @@ package org.aspectj.apache.bcel.classfile; * . */ -/** - * This interface denotes those constants that have a "natural" value, - * such as ConstantLong, ConstantString, etc.. - * - * @version $Id: ConstantObject.java,v 1.3 2008/05/28 23:53:02 aclement Exp $ - * @author M. Dahm - * @see Constant +/** + * This interface denotes those constants that have a "natural" value, such as ConstantLong, ConstantString, etc.. + * + * @version $Id: ConstantObject.java,v 1.4 2009/09/10 03:59:33 aclement Exp $ + * @author M. Dahm + * @see Constant */ public interface ConstantObject { - /** @return object representing the constant, e.g., Long for ConstantLong - */ - public abstract Object getConstantValue(ConstantPool cp); + public abstract Object getConstantValue(ConstantPool cp); } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java index 9dd4264f7..20cd3d13d 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java @@ -11,625 +11,681 @@ import org.aspectj.apache.bcel.generic.ArrayType; import org.aspectj.apache.bcel.generic.ObjectType; /** - * This class represents the constant pool, i.e., a table of constants, of - * a parsed classfile. It may contain null references, due to the JVM - * specification that skips an entry after an 8-byte constant (double, - * long) entry. + * This class represents the constant pool, i.e., a table of constants, of a parsed classfile. It may contain null references, due + * to the JVM specification that skips an entry after an 8-byte constant (double, long) entry. */ public class ConstantPool implements Node { private Constant[] pool; - private int poolSize; // number of entries in the pool (could be < pool.length as the array is resized in 'chunks') - - private Map utf8Cache = new HashMap(); - private Map methodCache = new HashMap(); - private Map fieldCache = new HashMap(); - - public int getSize() { return poolSize; } - - public ConstantPool() { + private int poolSize; // number of entries in the pool (could be < pool.length as the array is resized in 'chunks') + + private Map utf8Cache = new HashMap(); + private Map methodCache = new HashMap(); + private Map fieldCache = new HashMap(); + + public int getSize() { + return poolSize; + } + + public ConstantPool() { pool = new Constant[10]; - poolSize=0; + poolSize = 0; } - - public ConstantPool(Constant[] constants) { - pool = constants; - poolSize = (constants==null?0:constants.length); + + public ConstantPool(Constant[] constants) { + pool = constants; + poolSize = (constants == null ? 0 : constants.length); } ConstantPool(DataInputStream file) throws IOException { - byte tag; - poolSize = file.readUnsignedShort(); - pool = new Constant[poolSize]; - // pool[0] is unused by the compiler and may be used freely by the implementation - for (int i=1; i= pool.length || index < 0) - throw new ClassFormatException("Invalid constant pool reference: " + - index + ". Constant pool size is: " + pool.length); - return pool[index]; - } - - /** - * @return deep copy of this constant pool - */ - public ConstantPool copy() { - Constant[] newConstants = new Constant[poolSize]; // use the correct size - for (int i=1;i= pool.length || index < 0) + throw new ClassFormatException("Invalid constant pool reference: " + index + ". Constant pool size is: " + pool.length); + return pool[index]; + } + + /** + * @return deep copy of this constant pool + */ + public ConstantPool copy() { + Constant[] newConstants = new Constant[poolSize]; // use the correct size + for (int i = 1; i < poolSize; i++) { + if (pool[i] != null) { + newConstants[i] = pool[i].copy(); + } + } + return new ConstantPool(newConstants); + } + + /** + * Get string from constant pool and bypass the indirection of `ConstantClass' and `ConstantString' objects. I.e. these classes + * have an index field that points to another entry of the constant pool of type `ConstantUtf8' which contains the real data. + * + * @param index Index in constant pool + * @param tag Tag of expected constant, either ConstantClass or ConstantString + * @return Contents of string reference + * @see ConstantClass + * @see ConstantString + * @throws ClassFormatException + */ + public String getConstantString(int index, byte tag) throws ClassFormatException { + Constant c = getConstant(index, tag); + int i; + /* + * This switch() is not that elegant, since the two classes have the same contents, they just differ in the name of the + * index field variable. But we want to stick to the JVM naming conventions closely though we could have solved these more + * elegantly by using the same variable name or by subclassing. + */ + // OPTIMIZE remove the difference - use the an interface and same index methods for string ref id + switch (tag) { + case Constants.CONSTANT_Class: + i = ((ConstantClass) c).getNameIndex(); + break; + case Constants.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + break; + default: + throw new RuntimeException("getConstantString called with illegal tag " + tag); + } + // Finally get the string from the constant pool + c = getConstant(i, Constants.CONSTANT_Utf8); + return ((ConstantUtf8) c).getBytes(); + } + + /** + * Resolve constant to a string representation. + */ + public String constantToString(Constant c) { + String str; + int i; + + switch (c.tag) { + case Constants.CONSTANT_Class: + i = ((ConstantClass) c).getNameIndex(); + c = getConstant(i, Constants.CONSTANT_Utf8); + str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false); + break; + + case Constants.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + c = getConstant(i, Constants.CONSTANT_Utf8); + str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\""; + break; + + case Constants.CONSTANT_Utf8: + str = ((ConstantUtf8) c).getBytes(); + break; + case Constants.CONSTANT_Double: + str = Double.toString(((ConstantDouble) c).getBytes()); + break; + case Constants.CONSTANT_Float: + str = Float.toString(((ConstantFloat) c).getBytes()); + break; + case Constants.CONSTANT_Long: + str = Long.toString(((ConstantLong) c).getBytes()); + break; + case Constants.CONSTANT_Integer: + str = Integer.toString(((ConstantInteger) c).getBytes()); + break; + + case Constants.CONSTANT_NameAndType: + str = (constantToString(((ConstantNameAndType) c).getNameIndex(), Constants.CONSTANT_Utf8) + " " + constantToString( + ((ConstantNameAndType) c).getSignatureIndex(), Constants.CONSTANT_Utf8)); + break; + + case Constants.CONSTANT_InterfaceMethodref: + case Constants.CONSTANT_Methodref: + case Constants.CONSTANT_Fieldref: + str = (constantToString(((ConstantCP) c).getClassIndex(), Constants.CONSTANT_Class) + "." + constantToString( + ((ConstantCP) c).getNameAndTypeIndex(), Constants.CONSTANT_NameAndType)); + break; + + default: // Never reached + throw new RuntimeException("Unknown constant type " + c.tag); + } + + return str; + } + + private static final String escape(String str) { + int len = str.length(); + StringBuffer buf = new StringBuffer(len + 5); + char[] ch = str.toCharArray(); + + for (int i = 0; i < len; i++) { + switch (ch[i]) { + case '\n': + buf.append("\\n"); + break; + case '\r': + buf.append("\\r"); + break; + case '\t': + buf.append("\\t"); + break; + case '\b': + buf.append("\\b"); + break; + case '"': + buf.append("\\\""); + break; + default: + buf.append(ch[i]); + } + } + + return buf.toString(); + } + public String constantToString(int index, byte tag) { Constant c = getConstant(index, tag); return constantToString(c); } - - public void accept(ClassVisitor v) { - v.visitConstantPool(this); - } - - public Constant[] getConstantPool() { return pool; } // TEMPORARY, DONT LIKE PASSING THIS DATA OUT! - - public void dump(DataOutputStream file) throws IOException { - file.writeShort(poolSize); - for(int i=1; i < poolSize; i++) if (pool[i]!=null) pool[i].dump(file); - } - + + public void accept(ClassVisitor v) { + v.visitConstantPool(this); + } + + public Constant[] getConstantPool() { + return pool; + } // TEMPORARY, DONT LIKE PASSING THIS DATA OUT! + + public void dump(DataOutputStream file) throws IOException { + file.writeShort(poolSize); + for (int i = 1; i < poolSize; i++) + if (pool[i] != null) + pool[i].dump(file); + } + public ConstantUtf8 getConstantUtf8(int idx) { - try { - Constant c = pool[idx]; - if (c==null) - throw new ClassFormatException("Constant pool at index " + idx + " is null."); - if (c.tag!=Constants.CONSTANT_Utf8) - throw new ClassFormatException("Expected UTF8Constant "+ - " at index " + idx + " and got " + c); - return (ConstantUtf8)c; - } catch (ArrayIndexOutOfBoundsException aioobe) { - throw new ClassFormatException("Index "+idx+" into constant pool (size:"+poolSize+") is invalid"); - } - } - - public String getConstantString_CONSTANTClass(int index) { - ConstantClass c = (ConstantClass)getConstant(index,Constants.CONSTANT_Class); - index = c.getNameIndex(); - return ((ConstantUtf8)getConstant(index,Constants.CONSTANT_Utf8)).getBytes(); - } - - public int getLength() { return poolSize; } - - public String toString() { - StringBuffer buf = new StringBuffer(); - - for(int i=1; i < poolSize; i++) - buf.append(i + ")" + pool[i] + "\n"); - - return buf.toString(); - } - - public int lookupInteger(int n) { - for (int i=1; i < poolSize; i++) { - if (pool[i] instanceof ConstantInteger) { - ConstantInteger c = (ConstantInteger)pool[i]; - if (c.getBytes() == n) return i; - } - } - return -1; - } - - - public int lookupUtf8(String string) { - Integer pos = utf8Cache.get(string); - if (pos!=null) return pos.intValue(); - for (int i=1;i= pool.length) { - Constant[] cs = pool; - pool = new Constant[cs.length+8]; - System.arraycopy(cs, 0, pool, 0, cs.length); - } - if (poolSize==0) poolSize = 1; // someone about to do something in here! - } - + try { + Constant c = pool[idx]; + if (c == null) { + throw new ClassFormatException("Constant pool at index " + idx + " is null."); + } + if (c.tag != Constants.CONSTANT_Utf8) { + throw new ClassFormatException("Expected UTF8Constant " + " at index " + idx + " and got " + c); + } + return (ConstantUtf8) c; + } catch (ArrayIndexOutOfBoundsException aioobe) { + throw new ClassFormatException("Index " + idx + " into constant pool (size:" + poolSize + ") is invalid"); + } + } + + public String getConstantString_CONSTANTClass(int index) { + ConstantClass c = (ConstantClass) getConstant(index, Constants.CONSTANT_Class); + index = c.getNameIndex(); + return ((ConstantUtf8) getConstant(index, Constants.CONSTANT_Utf8)).getBytes(); + } + + public int getLength() { + return poolSize; + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(); + + for (int i = 1; i < poolSize; i++) + buf.append(i + ")" + pool[i] + "\n"); + + return buf.toString(); + } + + public int lookupInteger(int n) { + for (int i = 1; i < poolSize; i++) { + if (pool[i] instanceof ConstantInteger) { + ConstantInteger c = (ConstantInteger) pool[i]; + if (c.getBytes() == n) + return i; + } + } + return -1; + } + + public int lookupUtf8(String string) { + Integer pos = utf8Cache.get(string); + if (pos != null) { + return pos; + } + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Utf8) { + if (((ConstantUtf8) c).getBytes().equals(string)) { + utf8Cache.put(string, i); + return i; + } + } + } + return -1; + } + + public int lookupClass(String classname) { + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Class) { + int cIndex = ((ConstantClass) c).getNameIndex(); + String cName = ((ConstantUtf8) pool[cIndex]).getBytes(); + if (cName.equals(classname)) + return i; + } + } + return -1; + } + + public int addUtf8(String n) { + int ret = lookupUtf8(n); + if (ret != -1) + return ret; + adjustSize(); + ret = poolSize; + pool[poolSize++] = new ConstantUtf8(n); + return ret; + } + + public int addInteger(int n) { + int ret = lookupInteger(n); + if (ret != -1) + return ret; + adjustSize(); + ret = poolSize; + pool[poolSize++] = new ConstantInteger(n); + return ret; + } + + public int addArrayClass(ArrayType type) { + return addClass(type.getSignature()); + } + + public int addClass(ObjectType type) { + return addClass(type.getClassName()); + } + + public int addClass(String classname) { + String toAdd = classname.replace('.', '/'); + int ret = lookupClass(toAdd); + if (ret != -1) + return ret; + adjustSize(); + ConstantClass c = new ConstantClass(addUtf8(toAdd)); + ret = poolSize; + pool[poolSize++] = c; + return ret; + } + + private void adjustSize() { + if (poolSize + 3 >= pool.length) { + Constant[] cs = pool; + pool = new Constant[cs.length + 8]; + System.arraycopy(cs, 0, pool, 0, cs.length); + } + if (poolSize == 0) + poolSize = 1; // someone about to do something in here! + } + public int addFieldref(String class_name, String field_name, String signature) { - int ret = lookupFieldref(class_name, field_name, signature); - int class_index, name_and_type_index; - - if (ret != -1) return ret; - - adjustSize(); - - class_index = addClass(class_name); - name_and_type_index = addNameAndType(field_name, signature); - ret = poolSize; - pool[poolSize++] = new ConstantFieldref(class_index, name_and_type_index); - - return ret; - } - - public int lookupFieldref(String searchClassname, String searchFieldname, String searchSignature) { - searchClassname = searchClassname.replace('.','/'); - String k = new StringBuffer().append(searchClassname).append(searchFieldname).append(searchSignature).toString(); - Integer pos = fieldCache.get(k); - if (pos!=null) return pos.intValue(); - for (int i=1;iClassGen class. * - * @version $Id: JavaClass.java,v 1.17 2009/09/09 22:18:20 aclement Exp $ + * @version $Id: JavaClass.java,v 1.18 2009/09/10 03:59:33 aclement Exp $ * @see org.aspectj.apache.bcel.generic.ClassGen * @author M. Dahm */ public class JavaClass extends Modifiers implements Cloneable, Node { - private static final String[] NO_INTERFACE_NAMES = new String[0]; + + private static final String[] NoInterfaceNames = new String[0]; + private static final Field[] NoFields = new Field[0]; + private static final Method[] NoMethod = new Method[0]; + private static final int[] NoInterfaceIndices = new int[0]; + private static final Attribute[] NoAttributes = new Attribute[0]; private String fileName; private String packageName; @@ -121,48 +126,23 @@ public class JavaClass extends Modifiers implements Cloneable, Node { */ private transient org.aspectj.apache.bcel.util.Repository repository = null; - /** - * Constructor gets all contents as arguments. - * - * @param class_name_index Index into constant pool referencing a ConstantClass that represents this class. - * @param superclass_name_index Index into constant pool referencing a ConstantClass that represents this class's superclass. - * @param file_name File name - * @param major Major compiler version - * @param minor Minor compiler version - * @param access_flags Access rights defined by bit flags - * @param constant_pool Array of constants - * @param interfaces Implemented interfaces - * @param fields Class fields - * @param methods Class methods - * @param attributes Class attributes - * @param source Read from file or generated in memory? - */ - public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major, int minor, int access_flags, - ConstantPool constant_pool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes) { + public JavaClass(int classnameIndex, int superclassnameIndex, String filename, int major, int minor, int access_flags, + ConstantPool cpool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes) { if (interfaces == null) { - interfaces = new int[0]; - } - if (attributes == null) { - this.attributes = Attribute.NoAttributes; - } - if (fields == null) { - fields = new Field[0]; // TODO create a constant for no fields - } - if (methods == null) { - methods = new Method[0]; // TODO create a constant for no methods + interfaces = NoInterfaceIndices; } - this.classnameIdx = class_name_index; - this.superclassnameIdx = superclass_name_index; - this.fileName = file_name; + this.classnameIdx = classnameIndex; + this.superclassnameIdx = superclassnameIndex; + this.fileName = filename; this.major = major; this.minor = minor; this.modifiers = access_flags; - this.cpool = constant_pool; + this.cpool = cpool; this.interfaces = interfaces; - this.fields = fields; - this.methods = methods; - this.attributes = attributes; + this.fields = (fields == null ? NoFields : fields); + this.methods = (methods == null ? NoMethod : methods); + this.attributes = (attributes == null ? NoAttributes : attributes); annotationsOutOfDate = true; // Get source file name if available @@ -173,7 +153,7 @@ public class JavaClass extends Modifiers implements Cloneable, Node { * According to the specification the following entries must be of type `ConstantClass' but we check that anyway via the * `ConstPool.getConstant' method. */ - classname = constant_pool.getConstantString(class_name_index, Constants.CONSTANT_Class); + classname = cpool.getConstantString(classnameIndex, Constants.CONSTANT_Class); classname = Utility.compactClassName(classname, false); int index = classname.lastIndexOf('.'); @@ -183,19 +163,19 @@ public class JavaClass extends Modifiers implements Cloneable, Node { packageName = classname.substring(0, index); } - if (superclass_name_index > 0) { // May be zero -> class is java.lang.Object - superclassname = constant_pool.getConstantString(superclass_name_index, Constants.CONSTANT_Class); + if (superclassnameIndex > 0) { // May be zero -> class is java.lang.Object + superclassname = cpool.getConstantString(superclassnameIndex, Constants.CONSTANT_Class); superclassname = Utility.compactClassName(superclassname, false); } else { superclassname = "java.lang.Object"; } if (interfaces.length == 0) { - interfacenames = NO_INTERFACE_NAMES; + interfacenames = NoInterfaceNames; } else { interfacenames = new String[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { - String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class); + String str = cpool.getConstantString(interfaces[i], Constants.CONSTANT_Class); interfacenames[i] = Utility.compactClassName(str, false); } } @@ -343,16 +323,10 @@ public class JavaClass extends Modifiers implements Cloneable, Node { return packageName; } - /** - * @return Class name index. - */ public int getClassNameIndex() { return classnameIdx; } - /** - * @return Constant pool. - */ public ConstantPool getConstantPool() { return cpool; } @@ -386,9 +360,6 @@ public class JavaClass extends Modifiers implements Cloneable, Node { return interfaces; } - /** - * @return Major number of class file version. - */ public int getMajor() { return major; } @@ -419,7 +390,6 @@ public class JavaClass extends Modifiers implements Cloneable, Node { public Method getMethod(java.lang.reflect.Constructor c) { for (int i = 0; i < methods.length; i++) { Method method = methods[i]; - if (method.getName().equals("") && c.getModifiers() == method.getModifiers() && Type.getSignature(c).equals(method.getSignature())) { return method; @@ -430,9 +400,10 @@ public class JavaClass extends Modifiers implements Cloneable, Node { } public Field getField(java.lang.reflect.Field field) { - for (int i = 0; i < fields.length; i++) { - if (fields[i].getName().equals(field.getName())) { - return fields[i]; + String fieldName = field.getName(); + for (Field f : fields) { + if (f.getName().equals(fieldName)) { + return f; } } return null; @@ -523,23 +494,14 @@ public class JavaClass extends Modifiers implements Cloneable, Node { this.interfaces = interfaces; } - /** - * @param major . - */ public void setMajor(int major) { this.major = major; } - /** - * @param methods . - */ public void setMethods(Method[] methods) { this.methods = methods; } - /** - * @param minor . - */ public void setMinor(int minor) { this.minor = minor; } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Utility.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Utility.java index b121d803b..66a0635f4 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Utility.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Utility.java @@ -70,12 +70,13 @@ import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisibleParameterAnn import org.aspectj.apache.bcel.classfile.annotation.RuntimeParameterAnnotations; import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations; import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleParameterAnnotations; +import org.aspectj.apache.bcel.generic.Type; import org.aspectj.apache.bcel.util.ByteSequence; /** * Utility functions that do not really belong to any class in particular. * - * @version $Id: Utility.java,v 1.9 2009/09/09 22:18:20 aclement Exp $ + * @version $Id: Utility.java,v 1.10 2009/09/10 03:59:33 aclement Exp $ * @author M. Dahm * * modified: Andy Clement 2-mar-05 Removed unnecessary static and optimized @@ -200,7 +201,7 @@ public abstract class Utility { public static final String compactClassName(String str, String prefix, boolean chopit) { int len = prefix.length(); - str = str.replace('/', '.'); // Is '/' on all systems, even DOS + str = str.replace('/', '.'); if (chopit) { // If string starts with 'prefix' and contains no further dots @@ -237,37 +238,9 @@ public abstract class Utility { /** * This method converts such a string into a Java type declaration like 'void main(String[])' and throws a * 'ClassFormatException' when the parsed type is invalid. - * - * @param signature Method signature - * @param name Method name - * @param access Method access rights - * @return Java type declaration - * @throws ClassFormatException */ public static final String methodSignatureToString(String signature, String name, String access, boolean chopit, LocalVariableTable vars) throws ClassFormatException { - // - // - // if (signature.charAt(0)!='(') - // throw new ClassFormatException("Invalid method signature: " + signature); - // - // // Break the signature into two pieces: ([PARAMS])[RETURNTYPE] - // int lastBracketPos = signature.lastIndexOf(")"); - // String parameters = signature.substring(1,lastBracketPos); - // String returnType = signature.substring(lastBracketPos+1); - // - // // e.g. parameters="Ljava/util/List;" - // // returnType="V" - // - // // Break signature into its parts - // // dont want lots of substringing so lets use an index - // int posn=0; - // StringBuffer piece; - // while (posn index + 1 && signature.charAt(index + 1) == '>') + int index = signature.indexOf(';'); // Look for closing ';' + + if (index != -1 && signature.length() > index + 1 && signature.charAt(index + 1) == '>') { index = index + 2; + } if (index < 0) throw new ClassFormatException("Invalid signature: " + signature); @@ -460,10 +429,10 @@ public abstract class Utility { */ public static final byte typeOfMethodSignature(String signature) throws ClassFormatException { int index; - try { - if (signature.charAt(0) != '(') + if (signature.charAt(0) != '(') { throw new ClassFormatException("Invalid method signature: " + signature); + } index = signature.lastIndexOf(')') + 1; return typeOfSignature(signature.substring(index)); } catch (StringIndexOutOfBoundsException e) { @@ -575,11 +544,11 @@ public abstract class Utility { * Converts a list of AnnotationGen objects into a set of attributes that can be attached to the class file. * * @param cp The constant pool gen where we can create the necessary name refs - * @param vec A list of AnnotationGen objects + * @param annotations A list of AnnotationGen objects */ - public static Collection getAnnotationAttributes(ConstantPool cp, List vec) { + public static Collection getAnnotationAttributes(ConstantPool cp, List annotations) { - if (vec.size() == 0) + if (annotations.size() == 0) return null; try { @@ -587,12 +556,12 @@ public abstract class Utility { int countInvisible = 0; // put the annotations in the right output stream - for (int i = 0; i < vec.size(); i++) { - AnnotationGen a = vec.get(i); - if (a.isRuntimeVisible()) + for (AnnotationGen a : annotations) { + if (a.isRuntimeVisible()) { countVisible++; - else + } else { countInvisible++; + } } ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream(); @@ -604,8 +573,7 @@ public abstract class Utility { riaDos.writeShort(countInvisible); // put the annotations in the right output stream - for (int i = 0; i < vec.size(); i++) { - AnnotationGen a = vec.get(i); + for (AnnotationGen a : annotations) { if (a.isRuntimeVisible()) a.dump(rvaDos); else @@ -1089,4 +1057,22 @@ public abstract class Utility { private static final int pow2(int n) { return 1 << n; } + + /** + * Convert type to Java method signature, e.g. int[] f(java.lang.String x) becomes (Ljava/lang/String;)[I + * + * @param returnType what the method returns + * @param argTypes what are the argument types + * @return method signature for given type(s). + */ + public static String toMethodSignature(Type returnType, Type[] argTypes) { + StringBuffer buf = new StringBuffer("("); + int length = (argTypes == null) ? 0 : argTypes.length; + for (int i = 0; i < length; i++) { + buf.append(argTypes[i].getSignature()); + } + buf.append(')'); + buf.append(returnType.getSignature()); + return buf.toString(); + } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java index da9fb7f08..4f0a00d54 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java @@ -16,177 +16,163 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; +import java.util.Collections; import java.util.List; -import org.aspectj.apache.bcel.classfile.ConstantUtf8; import org.aspectj.apache.bcel.classfile.ConstantPool; -import org.aspectj.apache.bcel.generic.ObjectType; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; import org.aspectj.apache.bcel.classfile.Utility; +import org.aspectj.apache.bcel.generic.ObjectType; public class AnnotationGen { public static final AnnotationGen[] NO_ANNOTATIONS = new AnnotationGen[0]; - + private int typeIndex; - private List /* ElementNameValuePairGen */ evs; + private List pairs = Collections.emptyList(); private ConstantPool cpool; private boolean isRuntimeVisible = false; - + /** - * Here we are taking a fixed annotation of type Annotation and building a - * modifiable AnnotationGen object. If the pool passed in is for a different - * class file, then copyPoolEntries should have been passed as true as that - * will force us to do a deep copy of the annotation and move the cpool entries - * across. - * We need to copy the type and the element name value pairs and the visibility. + * Here we are taking a fixed annotation of type Annotation and building a modifiable AnnotationGen object. If the pool passed + * in is for a different class file, then copyPoolEntries should have been passed as true as that will force us to do a deep + * copy of the annotation and move the cpool entries across. We need to copy the type and the element name value pairs and the + * visibility. */ - public AnnotationGen(AnnotationGen a,ConstantPool cpool,boolean copyPoolEntries) { + public AnnotationGen(AnnotationGen a, ConstantPool cpool, boolean copyPoolEntries) { this.cpool = cpool; - if (copyPoolEntries) { - typeIndex = cpool.addUtf8(a.getTypeSignature()); + typeIndex = cpool.addUtf8(a.getTypeSignature()); } else { typeIndex = a.getTypeIndex(); } - - isRuntimeVisible = a.isRuntimeVisible(); - - evs = copyValues(a.getValues(),cpool,copyPoolEntries); + isRuntimeVisible = a.isRuntimeVisible(); + pairs = copyValues(a.getValues(), cpool, copyPoolEntries); } - - private List copyValues(List in,ConstantPool cpool,boolean copyPoolEntries) { + + private List copyValues(List in, ConstantPool cpool, boolean copyPoolEntries) { List out = new ArrayList(); - for (Iterator iter = in.iterator(); iter.hasNext();) { - ElementNameValuePairGen nvp = iter.next(); - out.add(new ElementNameValuePairGen(nvp,cpool,copyPoolEntries)); + for (ElementNameValuePairGen nvp : in) { + out.add(new ElementNameValuePairGen(nvp, cpool, copyPoolEntries)); } return out; } - + private AnnotationGen(ConstantPool cpool) { this.cpool = cpool; - this.evs=new ArrayList(); } - + /** * Retrieve an immutable version of this AnnotationGen */ -// public AnnotationGen getAnnotation() { -// return this; -//// AnnotationGen a = new AnnotationGen(typeIndex,cpool,isRuntimeVisible); -//// for (Iterator iter = evs.iterator(); iter.hasNext();) { -//// ElementNameValuePairGen element = (ElementNameValuePairGen) iter.next(); -//// a.addElementNameValuePair(element.getElementNameValuePair()); -//// } -//// return a; -// } - - public AnnotationGen(ObjectType type,List /*ElementNameValuePairGen*/ elements,boolean vis,ConstantPool cpool) { + public AnnotationGen(ObjectType type, List pairs, boolean runtimeVisible, ConstantPool cpool) { this.cpool = cpool; - if (type!=null) this.typeIndex = cpool.addUtf8(type.getSignature()); // Only null for funky *temporary* FakeAnnotation objects - evs = elements; - isRuntimeVisible = vis; + if (type != null) { + this.typeIndex = cpool.addUtf8(type.getSignature()); // Only null for funky *temporary* FakeAnnotation objects + } + this.pairs = pairs; + isRuntimeVisible = runtimeVisible; } - - public static AnnotationGen read(DataInputStream dis,ConstantPool cpool,boolean b) throws IOException { + + public static AnnotationGen read(DataInputStream dis, ConstantPool cpool, boolean b) throws IOException { AnnotationGen a = new AnnotationGen(cpool); a.typeIndex = dis.readUnsignedShort(); int elemValuePairCount = dis.readUnsignedShort(); - for (int i=0;i(); - evs.add(evp); + if (pairs == Collections.EMPTY_LIST) { + pairs = new ArrayList(); + } + pairs.add(evp); } - - + public int getTypeIndex() { return typeIndex; } - + public String getTypeSignature() { -// ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex); - ConstantUtf8 utf8 = (ConstantUtf8)cpool.getConstant(typeIndex/*c.getNameIndex()*/); - return utf8.getBytes(); + ConstantUtf8 utf8 = (ConstantUtf8) cpool.getConstant(typeIndex); + return utf8.getBytes(); } - + public String getTypeName() { return Utility.signatureToString(getTypeSignature()); } - - /** - * Returns list of ElementNameValuePair objects - */ + public List getValues() { - return evs; + return pairs; } - + + @Override public String toString() { StringBuffer s = new StringBuffer(); - s.append("AnnotationGen:["+getTypeName()+" #"+evs.size()+" {"); - for (int i = 0; iM. Dahm * * Upgraded, Andy Clement 9th Mar 06 - calculates SUID */ public class ClassGen extends Modifiers implements Cloneable { - private String class_name, super_class_name, file_name; - private int class_name_index = -1, superclass_name_index = -1; - private int major = Constants.MAJOR_1_1, minor = Constants.MINOR_1_1; - - private ConstantPool cp; - - private List field_vec = new ArrayList(); - private List method_vec = new ArrayList(); + private String classname; + private String superclassname; + private String filename; + private int classnameIndex = -1; + private int superclassnameIndex = -1; + private int major = Constants.MAJOR_1_1; + private int minor = Constants.MINOR_1_1; + private ConstantPool cpool; + private List fieldsList = new ArrayList(); + private List methodsList = new ArrayList(); private List attributesList = new ArrayList(); - private List interface_vec = new ArrayList(); + private List interfaceList = new ArrayList(); private List annotationsList = new ArrayList(); - /** - * Convenience constructor to set up some important values initially. - * - * @param class_name fully qualified class name - * @param super_class_name fully qualified superclass name - * @param file_name source file name - * @param access_flags access qualifiers - * @param interfaces implemented interfaces - * @param cp constant pool to use - */ - public ClassGen(String class_name, String super_class_name, String file_name, int access_flags, String[] interfaces, - ConstantPool cp) { - this.class_name = class_name; - this.super_class_name = super_class_name; - this.file_name = file_name; - this.modifiers = access_flags; - this.cp = cp; - - // Put everything needed by default into the constant pool and the vectors - if (file_name != null) { - addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2, cp.addUtf8(file_name), cp)); + public ClassGen(String classname, String superclassname, String filename, int modifiers, String[] interfacenames, + ConstantPool cpool) { + this.classname = classname; + this.superclassname = superclassname; + this.filename = filename; + this.modifiers = modifiers; + this.cpool = cpool; + if (filename != null) { + addAttribute(new SourceFile(cpool.addUtf8("SourceFile"), 2, cpool.addUtf8(filename), cpool)); } - - class_name_index = cp.addClass(class_name); - superclass_name_index = cp.addClass(super_class_name); - - if (interfaces != null) { - for (int i = 0; i < interfaces.length; i++) - addInterface(interfaces[i]); + this.classnameIndex = cpool.addClass(classname); + this.superclassnameIndex = cpool.addClass(superclassname); + if (interfacenames != null) { + for (String interfacename : interfacenames) { + addInterface(interfacename); + } } } - /** - * Convenience constructor to set up some important values initially. - * - * @param class_name fully qualified class name - * @param super_class_name fully qualified superclass name - * @param file_name source file name - * @param access_flags access qualifiers - * @param interfaces implemented interfaces - */ - public ClassGen(String class_name, String super_class_name, String file_name, int access_flags, String[] interfaces) { - this(class_name, super_class_name, file_name, access_flags, interfaces, new ConstantPool()); + public ClassGen(String classname, String superclassname, String filename, int modifiers, String[] interfacenames) { + this(classname, superclassname, filename, modifiers, interfacenames, new ConstantPool()); } - /** - * Initialize with existing class. - * - * @param clazz JavaClass object (e.g. read from file) - */ public ClassGen(JavaClass clazz) { - class_name_index = clazz.getClassNameIndex(); - superclass_name_index = clazz.getSuperclassNameIndex(); - class_name = clazz.getClassName(); - super_class_name = clazz.getSuperclassName(); - file_name = clazz.getSourceFileName(); + classnameIndex = clazz.getClassNameIndex(); + superclassnameIndex = clazz.getSuperclassNameIndex(); + classname = clazz.getClassName(); + superclassname = clazz.getSuperclassName(); + filename = clazz.getSourceFileName(); modifiers = clazz.getModifiers(); - cp = clazz.getConstantPool().copy(); + cpool = clazz.getConstantPool().copy(); major = clazz.getMajor(); minor = clazz.getMinor(); - Attribute[] attributes = clazz.getAttributes(); - // J5TODO: Could make unpacking lazy, done on first reference - AnnotationGen[] annotations = unpackAnnotations(attributes); Method[] methods = clazz.getMethods(); Field[] fields = clazz.getFields(); String[] interfaces = clazz.getInterfaceNames(); - for (int i = 0; i < interfaces.length; i++) + for (int i = 0; i < interfaces.length; i++) { addInterface(interfaces[i]); - - // Attribute[] attrs = attributes.getAttributes(); - for (int i = 0; i < attributes.length; i++) { - // Dont add attributes for annotations as those will have been unpacked - if (annotations.length == 0) { - addAttribute(attributes[i]); - } else if (!attributes[i].getName().equals("RuntimeVisibleAnnotations") - && !attributes[i].getName().equals("RuntimeInvisibleAnnotations")) { - addAttribute(attributes[i]); - } - } - for (int i = 0; i < annotations.length; i++) - addAnnotation(annotations[i]); - - for (int i = 0; i < methods.length; i++) { - Method m = methods[i]; - addMethod(m); } - for (int i = 0; i < fields.length; i++) - addField(fields[i]); - } - - /** - * Look for attributes representing annotations and unpack them. - */ - private AnnotationGen[] unpackAnnotations(Attribute[] attrs) { - List annotationGenObjs = new ArrayList(); - for (int i = 0; i < attrs.length; i++) { - Attribute attr = attrs[i]; + // OPTIMIZE Could make unpacking lazy, done on first reference + Attribute[] attributes = clazz.getAttributes(); + for (Attribute attr : attributes) { if (attr instanceof RuntimeVisibleAnnotations) { RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; List annos = rva.getAnnotations(); - for (Iterator iter = annos.iterator(); iter.hasNext();) { - AnnotationGen a = iter.next(); - annotationGenObjs.add(new AnnotationGen(a, getConstantPool(), false)); + for (AnnotationGen a : annos) { + annotationsList.add(new AnnotationGen(a, cpool, false)); } } else if (attr instanceof RuntimeInvisibleAnnotations) { RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; List annos = ria.getAnnotations(); - for (Iterator iter = annos.iterator(); iter.hasNext();) { - AnnotationGen a = iter.next(); - annotationGenObjs.add(new AnnotationGen(a, getConstantPool(), false)); + for (AnnotationGen anno : annos) { + annotationsList.add(new AnnotationGen(anno, cpool, false)); } + } else { + attributesList.add(attr); } } - return annotationGenObjs.toArray(new AnnotationGen[] {}); + + for (int i = 0; i < methods.length; i++) { + addMethod(methods[i]); + } + + for (int i = 0; i < fields.length; i++) { + addField(fields[i]); + } } /** - * @return the (finally) built up Java class object. + * @return build and return a JavaClass */ public JavaClass getJavaClass() { int[] interfaces = getInterfaces(); @@ -236,72 +188,41 @@ public class ClassGen extends Modifiers implements Cloneable { } else { // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations' attributes = new ArrayList(); - attributes.addAll(Utility.getAnnotationAttributes(cp, annotationsList)); + attributes.addAll(Utility.getAnnotationAttributes(cpool, annotationsList)); attributes.addAll(attributesList); } // Must be last since the above calls may still add something to it - ConstantPool cp = this.cp.getFinalConstantPool(); + ConstantPool cp = this.cpool.getFinalConstantPool(); - return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor, modifiers, cp, interfaces, fields, + return new JavaClass(classnameIndex, superclassnameIndex, filename, major, minor, modifiers, cp, interfaces, fields, methods, attributes.toArray(new Attribute[attributes.size()]));// OPTIMIZE avoid toArray()? } - /** - * Add an interface to this class, i.e., this class has to implement it. - * - * @param name interface to implement (fully qualified class name) - */ public void addInterface(String name) { - interface_vec.add(name); + interfaceList.add(name); } - /** - * Remove an interface from this class. - * - * @param name interface to remove (fully qualified name) - */ public void removeInterface(String name) { - interface_vec.remove(name); + interfaceList.remove(name); } - /** - * @return major version number of class file - */ public int getMajor() { return major; } - /** - * Set major version number of class file, default value is 45 (JDK 1.1) - * - * @param major major version number - */ public void setMajor(int major) { this.major = major; } - /** - * Set minor version number of class file, default value is 3 (JDK 1.1) - * - * @param minor minor version number - */ public void setMinor(int minor) { this.minor = minor; } - /** - * @return minor version number of class file - */ public int getMinor() { return minor; } - /** - * Add an attribute to this class. - * - * @param a attribute to add - */ public void addAttribute(Attribute a) { attributesList.add(a); } @@ -310,13 +231,8 @@ public class ClassGen extends Modifiers implements Cloneable { annotationsList.add(a); } - /** - * Add a method to this class. - * - * @param m method to add - */ public void addMethod(Method m) { - method_vec.add(m); + methodsList.add(m); } /** @@ -329,10 +245,10 @@ public class ClassGen extends Modifiers implements Cloneable { public void addEmptyConstructor(int access_flags) { InstructionList il = new InstructionList(); il.append(InstructionConstants.THIS); // Push `this' - il.append(new InvokeInstruction(Constants.INVOKESPECIAL, cp.addMethodref(super_class_name, "", "()V"))); + il.append(new InvokeInstruction(Constants.INVOKESPECIAL, cpool.addMethodref(superclassname, "", "()V"))); il.append(InstructionConstants.RETURN); - MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "", class_name, il, cp); + MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "", classname, il, cpool); mg.setMaxStack(1); mg.setMaxLocals(); addMethod(mg.getMethod()); @@ -344,44 +260,37 @@ public class ClassGen extends Modifiers implements Cloneable { * @param f field to add */ public void addField(Field f) { - field_vec.add(f); + fieldsList.add(f); } public boolean containsField(Field f) { - return field_vec.contains(f); + return fieldsList.contains(f); } /** - * @return field object with given name, or null + * @return field object with given name, or null if not found */ public Field containsField(String name) { - for (Iterator e = field_vec.iterator(); e.hasNext();) { - Field f = e.next(); - if (f.getName().equals(name)) - return f; + for (Field field : fieldsList) { + if (field.getName().equals(name)) { + return field; + } } - return null; } /** - * @return method object with given name and signature, or null + * @return method object with given name and signature, or null if not found */ public Method containsMethod(String name, String signature) { - for (Iterator e = method_vec.iterator(); e.hasNext();) { - Method m = e.next(); - if (m.getName().equals(name) && m.getSignature().equals(signature)) - return m; + for (Method method : methodsList) { + if (method.getName().equals(name) && method.getSignature().equals(signature)) { + return method; + } } - return null; } - /** - * Remove an attribute from this class. - * - * @param a attribute to remove - */ public void removeAttribute(Attribute a) { attributesList.remove(a); } @@ -390,13 +299,8 @@ public class ClassGen extends Modifiers implements Cloneable { annotationsList.remove(a); } - /** - * Remove a method from this class. - * - * @param m method to remove - */ public void removeMethod(Method m) { - method_vec.remove(m); + methodsList.remove(m); } /** @@ -406,12 +310,12 @@ public class ClassGen extends Modifiers implements Cloneable { if (new_ == null) throw new ClassGenException("Replacement method must not be null"); - int i = method_vec.indexOf(old); + int i = methodsList.indexOf(old); if (i < 0) - method_vec.add(new_); + methodsList.add(new_); else - method_vec.set(i, new_); + methodsList.set(i, new_); } /** @@ -421,92 +325,87 @@ public class ClassGen extends Modifiers implements Cloneable { if (new_ == null) throw new ClassGenException("Replacement method must not be null"); - int i = field_vec.indexOf(old); + int i = fieldsList.indexOf(old); if (i < 0) - field_vec.add(new_); + fieldsList.add(new_); else - field_vec.set(i, new_); + fieldsList.set(i, new_); } - /** - * Remove a field to this class. - * - * @param f field to remove - */ public void removeField(Field f) { - field_vec.remove(f); + fieldsList.remove(f); } public String getClassName() { - return class_name; + return classname; } public String getSuperclassName() { - return super_class_name; + return superclassname; } public String getFileName() { - return file_name; + return filename; } public void setClassName(String name) { - class_name = name.replace('/', '.'); - class_name_index = cp.addClass(name); + classname = name.replace('/', '.'); + classnameIndex = cpool.addClass(name); } public void setSuperclassName(String name) { - super_class_name = name.replace('/', '.'); - superclass_name_index = cp.addClass(name); + superclassname = name.replace('/', '.'); + superclassnameIndex = cpool.addClass(name); } public Method[] getMethods() { - Method[] methods = new Method[method_vec.size()]; - method_vec.toArray(methods); + Method[] methods = new Method[methodsList.size()]; + methodsList.toArray(methods); return methods; } public void setMethods(Method[] methods) { - method_vec.clear(); + methodsList.clear(); for (int m = 0; m < methods.length; m++) addMethod(methods[m]); } public void setFields(Field[] fs) { - field_vec.clear(); + fieldsList.clear(); for (int m = 0; m < fs.length; m++) addField(fs[m]); } public void setMethodAt(Method method, int pos) { - method_vec.set(pos, method); + methodsList.set(pos, method); } public Method getMethodAt(int pos) { - return method_vec.get(pos); + return methodsList.get(pos); } public String[] getInterfaceNames() { - int size = interface_vec.size(); + int size = interfaceList.size(); String[] interfaces = new String[size]; - interface_vec.toArray(interfaces); + interfaceList.toArray(interfaces); return interfaces; } public int[] getInterfaces() { - int size = interface_vec.size(); + int size = interfaceList.size(); int[] interfaces = new int[size]; for (int i = 0; i < size; i++) - interfaces[i] = cp.addClass(interface_vec.get(i)); + interfaces[i] = cpool.addClass(interfaceList.get(i)); return interfaces; } public Field[] getFields() { - Field[] fields = new Field[field_vec.size()]; - field_vec.toArray(fields); + Field[] fields = new Field[fieldsList.size()]; + fieldsList.toArray(fields); return fields; } @@ -522,29 +421,29 @@ public class ClassGen extends Modifiers implements Cloneable { } public ConstantPool getConstantPool() { - return cp; + return cpool; } public void setConstantPool(ConstantPool constant_pool) { - cp = constant_pool; + cpool = constant_pool; } public void setClassNameIndex(int class_name_index) { - this.class_name_index = class_name_index; - class_name = cp.getConstantString(class_name_index, Constants.CONSTANT_Class).replace('/', '.'); + this.classnameIndex = class_name_index; + classname = cpool.getConstantString(class_name_index, Constants.CONSTANT_Class).replace('/', '.'); } public void setSuperclassNameIndex(int superclass_name_index) { - this.superclass_name_index = superclass_name_index; - super_class_name = cp.getConstantString(superclass_name_index, Constants.CONSTANT_Class).replace('/', '.'); + this.superclassnameIndex = superclass_name_index; + superclassname = cpool.getConstantString(superclass_name_index, Constants.CONSTANT_Class).replace('/', '.'); } public int getSuperclassNameIndex() { - return superclass_name_index; + return superclassnameIndex; } public int getClassNameIndex() { - return class_name_index; + return classnameIndex; } @Override @@ -557,18 +456,10 @@ public class ClassGen extends Modifiers implements Cloneable { } } - // J5SUPPORT: - - /** - * Returns true if this class represents an annotation type - */ public final boolean isAnnotation() { return (modifiers & Constants.ACC_ANNOTATION) != 0; } - /** - * Returns true if this class represents an enum type - */ public final boolean isEnum() { return (modifiers & Constants.ACC_ENUM) != 0; } @@ -578,8 +469,6 @@ public class ClassGen extends Modifiers implements Cloneable { */ public long getSUID() { try { - Field[] fields = getFields(); - Method[] methods = getMethods(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); @@ -596,7 +485,7 @@ public class ClassGen extends Modifiers implements Cloneable { if (isAbstract()) { // if an interface then abstract is only set if it has methods if (isInterface()) { - if (methods.length > 0) + if (methodsList.size() > 0) classmods |= Constants.ACC_ABSTRACT; } else { classmods |= Constants.ACC_ABSTRACT; @@ -606,7 +495,6 @@ public class ClassGen extends Modifiers implements Cloneable { dos.writeInt(classmods); // 3. ordered list of interfaces - List list = new ArrayList(); String[] names = getInterfaceNames(); if (names != null) { Arrays.sort(names); @@ -618,41 +506,39 @@ public class ClassGen extends Modifiers implements Cloneable { // (relevant modifiers are ACC_PUBLIC, ACC_PRIVATE, // ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_VOLATILE, // ACC_TRANSIENT) - list.clear(); - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - if (!(field.isPrivate() && field.isStatic()) && !(field.isPrivate() && field.isTransient())) - list.add(field); + List relevantFields = new ArrayList(); + for (Field field : fieldsList) { + if (!(field.isPrivate() && field.isStatic()) && !(field.isPrivate() && field.isTransient())) { + relevantFields.add(field); + } } - Collections.sort(list, new FieldComparator()); + Collections.sort(relevantFields, new FieldComparator()); int relevantFlags = Constants.ACC_PUBLIC | Constants.ACC_PRIVATE | Constants.ACC_PROTECTED | Constants.ACC_STATIC | Constants.ACC_FINAL | Constants.ACC_VOLATILE | Constants.ACC_TRANSIENT; - for (Iterator iter = list.iterator(); iter.hasNext();) { - Field f = (Field) iter.next(); + for (Field f : relevantFields) { dos.writeUTF(f.getName()); dos.writeInt(relevantFlags & f.getModifiers()); dos.writeUTF(f.getType().getSignature()); } // some up front method processing: discover clinit, init and ordinary methods of interest: - list.clear(); // now used for methods - List ctors = new ArrayList(); + List relevantMethods = new ArrayList(); + List relevantCtors = new ArrayList(); boolean hasClinit = false; - for (int i = 0; i < methods.length; i++) { - Method m = methods[i]; + for (Method m : methodsList) { boolean couldBeInitializer = m.getName().charAt(0) == '<'; if (couldBeInitializer && m.getName().equals("")) { hasClinit = true; } else if (couldBeInitializer && m.getName().equals("")) { if (!m.isPrivate()) - ctors.add(m); + relevantCtors.add(m); } else { if (!m.isPrivate()) - list.add(m); + relevantMethods.add(m); } } - Collections.sort(ctors, new ConstructorComparator()); - Collections.sort(list, new MethodComparator()); + Collections.sort(relevantCtors, new ConstructorComparator()); + Collections.sort(relevantMethods, new MethodComparator()); // 5. If a class initializer exists, write out the following: // 1. The name of the method, . @@ -672,16 +558,14 @@ public class ClassGen extends Modifiers implements Cloneable { | Constants.ACC_STRICT; // 6. sorted non-private constructors - for (Iterator iter = ctors.iterator(); iter.hasNext();) { - Method m = iter.next(); - dos.writeUTF(m.getName()); // - dos.writeInt(relevantFlags & m.getModifiers()); - dos.writeUTF(m.getSignature().replace('/', '.')); + for (Method ctor : relevantCtors) { + dos.writeUTF(ctor.getName()); // + dos.writeInt(relevantFlags & ctor.getModifiers()); + dos.writeUTF(ctor.getSignature().replace('/', '.')); } // 7. sorted non-private methods - for (Iterator iter = list.iterator(); iter.hasNext();) { - Method m = (Method) iter.next(); + for (Method m : relevantMethods) { dos.writeUTF(m.getName()); dos.writeInt(relevantFlags & m.getModifiers()); dos.writeUTF(m.getSignature().replace('/', '.')); @@ -705,33 +589,31 @@ public class ClassGen extends Modifiers implements Cloneable { // (long)(sha[6]&0xff) << 48 | (long)(sha[7]&0xff) << 56); return suid; } catch (Exception e) { - System.err.println("Unable to calculate suid for " + getClassName()); e.printStackTrace(); throw new RuntimeException("Unable to calculate suid for " + getClassName() + ": " + e.toString()); } } - private static class FieldComparator implements Comparator { - public int compare(Object arg0, Object arg1) { - return ((Field) arg0).getName().compareTo(((Field) arg1).getName()); + private static class FieldComparator implements Comparator { + public int compare(Field f0, Field f1) { + return f0.getName().compareTo(f1.getName()); } } - private static class ConstructorComparator implements Comparator { - public int compare(Object arg0, Object arg1) { + private static class ConstructorComparator implements Comparator { + public int compare(Method m0, Method m1) { // can ignore the name... - return ((Method) arg0).getSignature().compareTo(((Method) arg1).getSignature()); + return (m0).getSignature().compareTo(m1.getSignature()); } } - private static class MethodComparator implements Comparator { - public int compare(Object arg0, Object arg1) { - Method m1 = (Method) arg0; - Method m2 = (Method) arg1; - int result = m1.getName().compareTo(m2.getName()); - if (result != 0) - return result; - return m1.getSignature().compareTo(m2.getSignature()); + private static class MethodComparator implements Comparator { + public int compare(Method m0, Method m1) { + int result = m0.getName().compareTo(m1.getName()); + if (result == 0) { + result = m0.getSignature().compareTo(m1.getSignature()); + } + return result; } } @@ -745,10 +627,10 @@ public class ClassGen extends Modifiers implements Cloneable { } public Attribute getAttribute(String attributeName) { - for (Iterator iter = attributesList.iterator(); iter.hasNext();) { - Attribute attr = iter.next(); - if (attr.getName().equals(attributeName)) + for (Attribute attr : attributesList) { + if (attr.getName().equals(attributeName)) { return attr; + } } return null; } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java index 8c34b7f88..ee02524e2 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java @@ -55,6 +55,7 @@ package org.aspectj.apache.bcel.generic; */ import org.aspectj.apache.bcel.Constants; import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.Utility; /** * Instances of this class may be used, e.g., to generate typed @@ -62,7 +63,7 @@ import org.aspectj.apache.bcel.classfile.ConstantPool; * byte code generating backend of a compiler. You can subclass it to * add your own create methods. * - * @version $Id: InstructionFactory.java,v 1.5 2008/08/28 00:03:24 aclement Exp $ + * @version $Id: InstructionFactory.java,v 1.6 2009/09/10 03:59:34 aclement Exp $ * @author M. Dahm * @see Constants */ @@ -95,7 +96,7 @@ public class InstructionFactory implements InstructionConstants { public InvokeInstruction createInvoke(String class_name, String name, Type ret_type, Type[] arg_types, short kind) { - String signature = Type.getMethodSignature(ret_type, arg_types); + String signature = Utility.toMethodSignature(ret_type, arg_types); int index; if (kind == Constants.INVOKEINTERFACE) diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java index 3475c35f5..46d1198d1 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java @@ -76,7 +76,7 @@ import org.aspectj.apache.bcel.util.ByteSequence; * * A list is finally dumped to a byte code array with getByteCode. * - * @version $Id: InstructionList.java,v 1.8 2009/09/09 19:56:20 aclement Exp $ + * @version $Id: InstructionList.java,v 1.9 2009/09/10 03:59:33 aclement Exp $ * @author M. Dahm * @see Instruction * @see InstructionHandle @@ -84,27 +84,16 @@ import org.aspectj.apache.bcel.util.ByteSequence; */ public class InstructionList implements Serializable { private InstructionHandle start = null, end = null; - private int length = 0; // number of elements in list - private int[] byte_positions; // byte code offsets corresponding to instructions + private int length = 0; + private int[] positions; // byte code offsets corresponding to instructions - /** - * Create (empty) instruction list. - */ public InstructionList() { } - /** - * Create instruction list containing one instruction. - * - * @param i initial instruction - */ public InstructionList(Instruction i) { append(i); } - /** - * Test for empty list. - */ public boolean isEmpty() { return start == null; } // && end == null @@ -158,7 +147,7 @@ public class InstructionList implements Serializable { */ public InstructionHandle findHandle(int pos) { InstructionHandle[] ihs = getInstructionHandles(); - return findHandle(ihs, byte_positions, length, pos); + return findHandle(ihs, positions, length, pos); } public InstructionHandle[] getInstructionsAsArray() { @@ -166,11 +155,11 @@ public class InstructionList implements Serializable { } public InstructionHandle findHandle(int pos, InstructionHandle[] instructionArray) { - return findHandle(instructionArray, byte_positions, length, pos); + return findHandle(instructionArray, positions, length, pos); } public InstructionHandle findHandle(int pos, InstructionHandle[] instructionArray, boolean useClosestApproximationIfNoExactFound) { - return findHandle(instructionArray, byte_positions, length, pos, useClosestApproximationIfNoExactFound); + return findHandle(instructionArray, positions, length, pos, useClosestApproximationIfNoExactFound); } /** @@ -213,8 +202,8 @@ public class InstructionList implements Serializable { throw new ClassGenException(e.toString()); } - byte_positions = new int[count]; // Trim to proper size - System.arraycopy(pos, 0, byte_positions, 0, count); + positions = new int[count]; // Trim to proper size + System.arraycopy(pos, 0, positions, 0, count); /* * Pass 2: Look for BranchInstruction and update their targets, i.e., convert offsets to instruction handles. @@ -945,8 +934,8 @@ public class InstructionList implements Serializable { index += i.getLength(); } - byte_positions = new int[count]; // Trim to proper size - System.arraycopy(pos, 0, byte_positions, 0, count); + positions = new int[count]; // Trim to proper size + System.arraycopy(pos, 0, positions, 0, count); } /** @@ -998,6 +987,7 @@ public class InstructionList implements Serializable { return result; } + @Override public String toString() { return toString(true); } @@ -1061,7 +1051,7 @@ public class InstructionList implements Serializable { * @return array containing all instruction's offset in byte code */ public int[] getInstructionPositions() { - return byte_positions; + return positions; } /** diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java index 0f723cf8d..67dfb11a5 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java @@ -84,7 +84,7 @@ import org.aspectj.apache.bcel.classfile.annotation.RuntimeParameterAnnotations; * While generating code it may be necessary to insert NOP operations. You can use the `removeNOPs' method to get rid off them. The * resulting method object can be obtained via the `getMethod()' method. * - * @version $Id: MethodGen.java,v 1.12 2009/09/09 19:56:20 aclement Exp $ + * @version $Id: MethodGen.java,v 1.13 2009/09/10 03:59:34 aclement Exp $ * @author M. Dahm * @author Patrick C. Beard [setMaxStack()] * @see InstructionList @@ -846,7 +846,7 @@ public class MethodGen extends FieldGenOrMethodGen { } public String getSignature() { - return Type.getMethodSignature(type, parameterTypes); + return Utility.toMethodSignature(type, parameterTypes); } /** @@ -1016,7 +1016,7 @@ public class MethodGen extends FieldGenOrMethodGen { */ public final String toString() { String access = Utility.accessToString(modifiers); - String signature = Type.getMethodSignature(type, parameterTypes); + String signature = Utility.toMethodSignature(type, parameterTypes); signature = Utility.methodSignatureToString(signature, name, access, true, getLocalVariableTable(cp)); diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java index 66c11f1e8..a98facde2 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java @@ -56,6 +56,7 @@ package org.aspectj.apache.bcel.generic; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.aspectj.apache.bcel.Constants; @@ -66,14 +67,14 @@ import org.aspectj.apache.bcel.classfile.Utility; * Abstract super class for all possible java types, namely basic types such as int, object types like String and array types, e.g. * int[] * - * @version $Id: Type.java,v 1.11 2009/09/09 19:56:20 aclement Exp $ + * @version $Id: Type.java,v 1.12 2009/09/10 03:59:34 aclement Exp $ * @author M. Dahm * * modified: AndyClement 2-mar-05: Removed unnecessary static and optimized */ -public abstract class Type implements java.io.Serializable { +public abstract class Type { protected byte type; - protected String signature; // signature for the type + protected String signature; /* Predefined constants */ public static final BasicType VOID = new BasicType(Constants.T_VOID); @@ -142,16 +143,10 @@ public abstract class Type implements java.io.Serializable { signature = s; } - /** - * @return signature for given type. - */ public String getSignature() { return signature; } - /** - * @return type as defined in Constants - */ public byte getType() { return type; } @@ -180,24 +175,6 @@ public abstract class Type implements java.io.Serializable { .signatureToString(signature, false); } - /** - * Convert type to Java method signature, e.g. int[] f(java.lang.String x) becomes (Ljava/lang/String;)[I - * - * @param return_type what the method returns - * @param arg_types what are the argument types - * @return method signature for given type(s). - */ - public static String getMethodSignature(Type return_type, Type[] arg_types) { - StringBuffer buf = new StringBuffer("("); - int length = (arg_types == null) ? 0 : arg_types.length; - for (int i = 0; i < length; i++) { - buf.append(arg_types[i].getSignature()); - } - buf.append(')'); - buf.append(return_type.getSignature()); - return buf.toString(); - } - public static final Type getType(String signature) { Type t = commonTypes.get(signature); if (t != null) @@ -314,7 +291,7 @@ public abstract class Type implements java.io.Serializable { */ public static Type getReturnType(String signature) { try { - // Read return type after `)' + // Read return type after ')' int index = signature.lastIndexOf(')') + 1; return getType(signature.substring(index)); } catch (StringIndexOutOfBoundsException e) { // Should never occur @@ -330,7 +307,7 @@ public abstract class Type implements java.io.Serializable { */ // OPTIMIZE crap impl public static Type[] getArgumentTypes(String signature) { - ArrayList vec = new ArrayList(); + List argumentTypes = new ArrayList(); int index; Type[] types; @@ -342,15 +319,15 @@ public abstract class Type implements java.io.Serializable { while (signature.charAt(index) != ')') { TypeHolder th = getTypeInternal(signature.substring(index)); - vec.add(th.getType()); + argumentTypes.add(th.getType()); index += th.getConsumed(); // update position } } catch (StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatException("Invalid method signature: " + signature); } - types = new Type[vec.size()]; - vec.toArray(types); + types = new Type[argumentTypes.size()]; + argumentTypes.toArray(types); return types; } diff --git a/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnclosingMethodAttributeTest.java b/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnclosingMethodAttributeTest.java index 305179a3c..bcf4403bb 100644 --- a/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnclosingMethodAttributeTest.java +++ b/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnclosingMethodAttributeTest.java @@ -21,82 +21,76 @@ import org.aspectj.apache.bcel.classfile.EnclosingMethod; import org.aspectj.apache.bcel.classfile.JavaClass; import org.aspectj.apache.bcel.util.SyntheticRepository; - public class EnclosingMethodAttributeTest extends BcelTestCase { - + + @Override protected void setUp() throws Exception { super.setUp(); } - - + /** - * Verify for an inner class declared inside the 'main' method that the enclosing method - * attribute is set correctly. + * Verify for an inner class declared inside the 'main' method that the enclosing method attribute is set correctly. */ public void testCheckMethodLevelNamedInnerClass() throws ClassNotFoundException { SyntheticRepository repos = createRepos("testcode.jar"); JavaClass clazz = repos.loadClass("AttributeTestClassEM01$1S"); ConstantPool pool = clazz.getConstantPool(); - Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz); - assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length, - encMethodAttrs.length==1); - EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0]; - String enclosingClassName = em.getEnclosingClass().getBytes(pool); - String enclosingMethodName= em.getEnclosingMethod().getName(pool); - assertTrue("Expected class name to be 'AttributeTestClassEM01' but was "+enclosingClassName, - enclosingClassName.equals("AttributeTestClassEM01")); - assertTrue("Expected method name to be 'main' but was "+enclosingMethodName, - enclosingMethodName.equals("main")); + Attribute[] encMethodAttrs = findAttribute("EnclosingMethod", clazz); + assertTrue("Expected 1 EnclosingMethod attribute but found " + encMethodAttrs.length, encMethodAttrs.length == 1); + EnclosingMethod em = (EnclosingMethod) encMethodAttrs[0]; + String enclosingClassName = em.getEnclosingClass().getConstantValue(pool); + String enclosingMethodName = em.getEnclosingMethod().getName(pool); + assertTrue("Expected class name to be 'AttributeTestClassEM01' but was " + enclosingClassName, enclosingClassName + .equals("AttributeTestClassEM01")); + assertTrue("Expected method name to be 'main' but was " + enclosingMethodName, enclosingMethodName.equals("main")); } - + /** - * Verify for an inner class declared at the type level that the EnclosingMethod attribute - * is set correctly (i.e. to a null value) + * Verify for an inner class declared at the type level that the EnclosingMethod attribute is set correctly (i.e. to a null + * value) */ public void testCheckClassLevelNamedInnerClass() throws ClassNotFoundException { SyntheticRepository repos = createRepos("testcode.jar"); JavaClass clazz = repos.loadClass("AttributeTestClassEM02$1"); ConstantPool pool = clazz.getConstantPool(); - Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz); - assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length, - encMethodAttrs.length==1); - EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0]; - String enclosingClassName = em.getEnclosingClass().getBytes(pool); - assertTrue("The class is not within a method, so method_index should be null, but it is "+ - em.getEnclosingMethodIndex(),em.getEnclosingMethodIndex() == 0); - assertTrue("Expected class name to be 'AttributeTestClassEM02' but was "+enclosingClassName, - enclosingClassName.equals("AttributeTestClassEM02")); + Attribute[] encMethodAttrs = findAttribute("EnclosingMethod", clazz); + assertTrue("Expected 1 EnclosingMethod attribute but found " + encMethodAttrs.length, encMethodAttrs.length == 1); + EnclosingMethod em = (EnclosingMethod) encMethodAttrs[0]; + String enclosingClassName = em.getEnclosingClass().getConstantValue(pool); + assertTrue("The class is not within a method, so method_index should be null, but it is " + em.getEnclosingMethodIndex(), + em.getEnclosingMethodIndex() == 0); + assertTrue("Expected class name to be 'AttributeTestClassEM02' but was " + enclosingClassName, enclosingClassName + .equals("AttributeTestClassEM02")); } - + /** * Check that we can save and load the attribute correctly. */ - public void testAttributeSerializtion() throws ClassNotFoundException,IOException { + public void testAttributeSerializtion() throws ClassNotFoundException, IOException { // Read in the class SyntheticRepository repos = createRepos("testcode.jar"); JavaClass clazz = repos.loadClass("AttributeTestClassEM02$1"); ConstantPool pool = clazz.getConstantPool(); - Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz); - assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length, - encMethodAttrs.length==1); - + Attribute[] encMethodAttrs = findAttribute("EnclosingMethod", clazz); + assertTrue("Expected 1 EnclosingMethod attribute but found " + encMethodAttrs.length, encMethodAttrs.length == 1); + // Write it out File tfile = createTestdataFile("AttributeTestClassEM02$1.class"); clazz.dump(tfile); - + // Read in the new version and check it is OK SyntheticRepository repos2 = createRepos("."); JavaClass clazz2 = repos2.loadClass("AttributeTestClassEM02$1"); - EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0]; - String enclosingClassName = em.getEnclosingClass().getBytes(pool); - assertTrue("The class is not within a method, so method_index should be null, but it is "+ - em.getEnclosingMethodIndex(),em.getEnclosingMethodIndex() == 0); - assertTrue("Expected class name to be 'AttributeTestClassEM02' but was "+enclosingClassName, - enclosingClassName.equals("AttributeTestClassEM02")); + EnclosingMethod em = (EnclosingMethod) encMethodAttrs[0]; + String enclosingClassName = em.getEnclosingClass().getConstantValue(pool); + assertTrue("The class is not within a method, so method_index should be null, but it is " + em.getEnclosingMethodIndex(), + em.getEnclosingMethodIndex() == 0); + assertTrue("Expected class name to be 'AttributeTestClassEM02' but was " + enclosingClassName, enclosingClassName + .equals("AttributeTestClassEM02")); assertTrue(tfile.delete()); } - + @Override protected void tearDown() throws Exception { super.tearDown(); } diff --git a/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/UtilTests.java b/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/UtilTests.java index 8c9fb5024..750dbf4f1 100644 --- a/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/UtilTests.java +++ b/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/UtilTests.java @@ -40,7 +40,7 @@ public class UtilTests extends TestCase { } public void testTypeUtilMethods1() { - String s = Type.getMethodSignature(Type.DOUBLE,new Type[]{Type.INT,Type.STRING,Type.SHORT}); + String s = Utility.toMethodSignature(Type.DOUBLE,new Type[]{Type.INT,Type.STRING,Type.SHORT}); System.err.println(s); } -- 2.39.5