diff options
Diffstat (limited to 'bcel-builder/src')
16 files changed, 1428 insertions, 1612 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 - * <A HREF="http://www.inf.fu-berlin.de/~bokowski">Boris Bokowski</A>. - * - * @version $Id: ClassVisitor.java,v 1.2 2008/05/28 23:53:01 aclement Exp $ - * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * 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 <A HREF="http://www.inf.fu-berlin.de/~bokowski">Boris Bokowski</A>. + * + * @version $Id: ClassVisitor.java,v 1.3 2009/09/10 03:59:33 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> */ 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; * <http://www.apache.org/>. */ -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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> */ 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; * <http://www.apache.org/>. */ -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 - * <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> - * @see Constant +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @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; * <http://www.apache.org/>. */ -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 - * <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> - * @see Constant +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @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; * <http://www.apache.org/>. */ -/** - * 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> - * @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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @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<String, Integer> utf8Cache = new HashMap<String, Integer>(); - private Map<String, Integer> methodCache = new HashMap<String, Integer>(); - private Map<String, Integer> fieldCache = new HashMap<String, Integer>(); - - 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<String, Integer> utf8Cache = new HashMap<String, Integer>(); + private Map<String, Integer> methodCache = new HashMap<String, Integer>(); + private Map<String, Integer> fieldCache = new HashMap<String, Integer>(); + + 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<poolSize; i++) { - pool[i] = Constant.readConstant(file); - tag = pool[i].getTag(); - if ((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) i++; - } - } - - public Constant getConstant(int index, byte tag) { - Constant c = getConstant(index); - //if (c == null) throw new ClassFormatException("Constant pool at index " + index + " is null."); - if(c.tag == tag) return c; - throw new ClassFormatException("Expected class '"+Constants.CONSTANT_NAMES[tag]+"' at index "+index+" and found "+c); - } - - public Constant getConstant(int index) { - if (index >= 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(); - } - + 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 < poolSize; i++) { + pool[i] = Constant.readConstant(file); + tag = pool[i].getTag(); + if ((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) { + i++; + } + } + } + + public Constant getConstant(int index, byte tag) { + Constant c = getConstant(index); + // if (c == null) throw new ClassFormatException("Constant pool at index " + index + " is null."); + if (c.tag == tag) + return c; + throw new ClassFormatException("Expected class '" + Constants.CONSTANT_NAMES[tag] + "' at index " + index + " and found " + + c); + } + + public Constant getConstant(int index) { + if (index >= 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<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_Utf8) { - if (((ConstantUtf8)c).getBytes().equals(string)) { - utf8Cache.put(string,new Integer(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! - } - + 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;i<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_Fieldref) { - ConstantFieldref cfr = (ConstantFieldref)c; - ConstantNameAndType cnat = (ConstantNameAndType)pool[cfr.getNameAndTypeIndex()]; - - // check the class - int cIndex = cfr.getClassIndex(); - ConstantClass cc = (ConstantClass)pool[cIndex]; - String cName = ((ConstantUtf8)pool[cc.getNameIndex()]).getBytes(); - if (!cName.equals(searchClassname)) continue; - - // check the name and type - String name = ((ConstantUtf8)pool[cnat.getNameIndex()]).getBytes(); - if (!name.equals(searchFieldname)) continue; // not this one - String typeSignature = ((ConstantUtf8)pool[cnat.getSignatureIndex()]).getBytes(); - if (!typeSignature.equals(searchSignature)) continue; - fieldCache.put(k,new Integer(i)); - return i; - } - } - return -1; - } - - - - public int addNameAndType(String name, String signature) { - int ret = lookupNameAndType(name, signature); - if (ret != -1) return ret; - adjustSize(); - int name_index = addUtf8(name); - int signature_index = addUtf8(signature); - ret = poolSize; - pool[poolSize++] = new ConstantNameAndType(name_index, signature_index); - return ret; - } - - public int lookupNameAndType(String searchName, String searchTypeSignature) { - for (int i=1;i<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_NameAndType) { - ConstantNameAndType cnat = (ConstantNameAndType)c; - String name = ((ConstantUtf8)pool[cnat.getNameIndex()]).getBytes(); - if (!name.equals(searchName)) continue; // not this one - String typeSignature = ((ConstantUtf8)pool[cnat.getSignatureIndex()]).getBytes(); - if (!typeSignature.equals(searchTypeSignature)) continue; - return i; - } - } - return -1; - } - + 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; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Fieldref) { + ConstantFieldref cfr = (ConstantFieldref) c; + ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()]; + + // check the class + int cIndex = cfr.getClassIndex(); + ConstantClass cc = (ConstantClass) pool[cIndex]; + String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getBytes(); + if (!cName.equals(searchClassname)) + continue; + + // check the name and type + String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getBytes(); + if (!name.equals(searchFieldname)) + continue; // not this one + String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getBytes(); + if (!typeSignature.equals(searchSignature)) + continue; + fieldCache.put(k, new Integer(i)); + return i; + } + } + return -1; + } + + public int addNameAndType(String name, String signature) { + int ret = lookupNameAndType(name, signature); + if (ret != -1) + return ret; + adjustSize(); + int name_index = addUtf8(name); + int signature_index = addUtf8(signature); + ret = poolSize; + pool[poolSize++] = new ConstantNameAndType(name_index, signature_index); + return ret; + } + + public int lookupNameAndType(String searchName, String searchTypeSignature) { + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_NameAndType) { + ConstantNameAndType cnat = (ConstantNameAndType) c; + String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getBytes(); + if (!name.equals(searchName)) + continue; // not this one + String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getBytes(); + if (!typeSignature.equals(searchTypeSignature)) + continue; + return i; + } + } + return -1; + } + public int addFloat(float f) { - int ret= lookupFloat(f); - if (ret != -1) return ret; + int ret = lookupFloat(f); + if (ret != -1) + return ret; adjustSize(); ret = poolSize; pool[poolSize++] = new ConstantFloat(f); return ret; } - - public int lookupFloat(float f) { - int bits = Float.floatToIntBits(f); - for (int i=1;i<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_Float) { - ConstantFloat cf = (ConstantFloat)c; - if (Float.floatToIntBits(cf.getBytes())==bits) return i; - } + public int lookupFloat(float f) { + int bits = Float.floatToIntBits(f); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Float) { + ConstantFloat cf = (ConstantFloat) c; + if (Float.floatToIntBits(cf.getBytes()) == bits) + return i; + } + } + return -1; } - return -1; - } - public int addDouble(double d) { - int ret= lookupDouble(d); - if (ret != -1) return ret; + + public int addDouble(double d) { + int ret = lookupDouble(d); + if (ret != -1) + return ret; adjustSize(); ret = poolSize; pool[poolSize] = new ConstantDouble(d); - poolSize+=2; + poolSize += 2; return ret; } - -public int lookupDouble(double d) { - long bits = Double.doubleToLongBits(d); - for (int i=1;i<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_Double) { - ConstantDouble cf = (ConstantDouble)c; - if (Double.doubleToLongBits(cf.getBytes())==bits) return i; + public int lookupDouble(double d) { + long bits = Double.doubleToLongBits(d); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Double) { + ConstantDouble cf = (ConstantDouble) c; + if (Double.doubleToLongBits(cf.getBytes()) == bits) + return i; + } } + return -1; } - return -1; -} -public int addLong(long l) { - int ret= lookupLong(l); - if (ret != -1) return ret; + public int addLong(long l) { + int ret = lookupLong(l); + if (ret != -1) + return ret; adjustSize(); ret = poolSize; pool[poolSize] = new ConstantLong(l); - poolSize+=2; + poolSize += 2; return ret; } - -public int lookupString(String s) { - for (int i=1;i<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_String) { - ConstantString cs = (ConstantString)c; - ConstantUtf8 cu8 = (ConstantUtf8)pool[cs.getStringIndex()]; - if (cu8.getBytes().equals(s)) return i; + public int lookupString(String s) { + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_String) { + ConstantString cs = (ConstantString) c; + ConstantUtf8 cu8 = (ConstantUtf8) pool[cs.getStringIndex()]; + if (cu8.getBytes().equals(s)) + return i; + } } + return -1; } - return -1; -} public int addString(String str) { int ret = lookupString(str); - if (ret!=-1) return ret; + if (ret != -1) + return ret; int utf8 = addUtf8(str); adjustSize(); - ConstantString s = new ConstantString(utf8); + ConstantString s = new ConstantString(utf8); ret = poolSize; pool[poolSize++] = s; return ret; } -public int lookupLong(long l) { - for (int i=1;i<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_Long) { - ConstantLong cf = (ConstantLong)c; - if (cf.getBytes()==l) return i; + public int lookupLong(long l) { + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Long) { + ConstantLong cf = (ConstantLong) c; + if (cf.getBytes() == l) + return i; + } } + return -1; } - return -1; -} - public int addConstant(Constant c, ConstantPool cp) { - Constant[] constants = cp.getConstantPool(); - switch(c.getTag()) { + public int addConstant(Constant c, ConstantPool cp) { + Constant[] constants = cp.getConstantPool(); + switch (c.getTag()) { - case Constants.CONSTANT_String: { - ConstantString s = (ConstantString)c; - ConstantUtf8 u8 = (ConstantUtf8)constants[s.getStringIndex()]; - - return addString(u8.getBytes()); - } + case Constants.CONSTANT_String: { + ConstantString s = (ConstantString) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; -case Constants.CONSTANT_Class: { - ConstantClass s = (ConstantClass)c; - ConstantUtf8 u8 = (ConstantUtf8)constants[s.getNameIndex()]; + return addString(u8.getBytes()); + } + + case Constants.CONSTANT_Class: { + ConstantClass s = (ConstantClass) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; - return addClass(u8.getBytes()); -} + return addClass(u8.getBytes()); + } -case Constants.CONSTANT_NameAndType: { - ConstantNameAndType n = (ConstantNameAndType)c; - ConstantUtf8 u8 = (ConstantUtf8)constants[n.getNameIndex()]; - ConstantUtf8 u8_2 = (ConstantUtf8)constants[n.getSignatureIndex()]; + case Constants.CONSTANT_NameAndType: { + ConstantNameAndType n = (ConstantNameAndType) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; + ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; - return addNameAndType(u8.getBytes(), u8_2.getBytes()); -} + return addNameAndType(u8.getBytes(), u8_2.getBytes()); + } -case Constants.CONSTANT_Utf8: - return addUtf8(((ConstantUtf8)c).getBytes()); + case Constants.CONSTANT_Utf8: + return addUtf8(((ConstantUtf8) c).getBytes()); -case Constants.CONSTANT_Double: - return addDouble(((ConstantDouble)c).getBytes()); + case Constants.CONSTANT_Double: + return addDouble(((ConstantDouble) c).getBytes()); -case Constants.CONSTANT_Float: - return addFloat(((ConstantFloat)c).getBytes()); + case Constants.CONSTANT_Float: + return addFloat(((ConstantFloat) c).getBytes()); -case Constants.CONSTANT_Long: - return addLong(((ConstantLong)c).getBytes()); + case Constants.CONSTANT_Long: + return addLong(((ConstantLong) c).getBytes()); -case Constants.CONSTANT_Integer: - return addInteger(((ConstantInteger)c).getBytes()); + case Constants.CONSTANT_Integer: + return addInteger(((ConstantInteger) c).getBytes()); -case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Methodref: -case Constants.CONSTANT_Fieldref: { - ConstantCP m = (ConstantCP)c; - ConstantClass clazz = (ConstantClass)constants[m.getClassIndex()]; - ConstantNameAndType n = (ConstantNameAndType)constants[m.getNameAndTypeIndex()]; - ConstantUtf8 u8 = (ConstantUtf8)constants[clazz.getNameIndex()]; - String class_name = u8.getBytes().replace('/', '.'); + case Constants.CONSTANT_InterfaceMethodref: + case Constants.CONSTANT_Methodref: + case Constants.CONSTANT_Fieldref: { + ConstantCP m = (ConstantCP) c; + ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; + ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; + ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; + String class_name = u8.getBytes().replace('/', '.'); - u8 = (ConstantUtf8)constants[n.getNameIndex()]; - String name = u8.getBytes(); + u8 = (ConstantUtf8) constants[n.getNameIndex()]; + String name = u8.getBytes(); - u8 = (ConstantUtf8)constants[n.getSignatureIndex()]; - String signature = u8.getBytes(); + u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; + String signature = u8.getBytes(); - switch(c.getTag()) { - case Constants.CONSTANT_InterfaceMethodref: -return addInterfaceMethodref(class_name, name, signature); + switch (c.getTag()) { + case Constants.CONSTANT_InterfaceMethodref: + return addInterfaceMethodref(class_name, name, signature); - case Constants.CONSTANT_Methodref: -return addMethodref(class_name, name, signature); // OPTIMIZE indicate it should be cached! + case Constants.CONSTANT_Methodref: + return addMethodref(class_name, name, signature); // OPTIMIZE indicate it should be cached! - case Constants.CONSTANT_Fieldref: -return addFieldref(class_name, name, signature); + case Constants.CONSTANT_Fieldref: + return addFieldref(class_name, name, signature); - default: // Never reached -throw new RuntimeException("Unknown constant type " + c); - } -} + default: // Never reached + throw new RuntimeException("Unknown constant type " + c); + } + } -default: // Never reached - throw new RuntimeException("Unknown constant type " + c); -} -} + default: // Never reached + throw new RuntimeException("Unknown constant type " + c); + } + } - // OPTIMIZE should put it in the cache now + // OPTIMIZE should put it in the cache now public int addMethodref(String class_name, String method_name, String signature) { - int ret, class_index, name_and_type_index; - if((ret = lookupMethodref(class_name, method_name, signature)) != -1) - return ret; // Already in CP - - adjustSize(); - - name_and_type_index = addNameAndType(method_name, signature); - class_index = addClass(class_name); - ret = poolSize; - pool[poolSize++] = new ConstantMethodref(class_index, name_and_type_index); - return ret; - } - - public int addInterfaceMethodref(String class_name, String method_name, String signature) { - int ret = lookupInterfaceMethodref(class_name, method_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(method_name, signature); - ret = poolSize; - pool[poolSize++] = new ConstantInterfaceMethodref(class_index, name_and_type_index); - return ret; - } - - public int lookupInterfaceMethodref(String searchClassname, String searchMethodName, String searchSignature) { - searchClassname = searchClassname.replace('.','/'); - for (int i=1;i<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_InterfaceMethodref) { - ConstantInterfaceMethodref cfr = (ConstantInterfaceMethodref)c; - - ConstantClass cc = (ConstantClass)pool[cfr.getClassIndex()]; - String cName = ((ConstantUtf8)pool[cc.getNameIndex()]).getBytes(); - if (!cName.equals(searchClassname)) continue; - - // check the name and type - ConstantNameAndType cnat = (ConstantNameAndType)pool[cfr.getNameAndTypeIndex()]; - String name = ((ConstantUtf8)pool[cnat.getNameIndex()]).getBytes(); - if (!name.equals(searchMethodName)) continue; // not this one - String typeSignature = ((ConstantUtf8)pool[cnat.getSignatureIndex()]).getBytes(); - if (!typeSignature.equals(searchSignature)) continue; - return i; - } - } - return -1; - } - - - public int lookupMethodref(String searchClassname, String searchMethodName, String searchSignature) { - String key = new StringBuffer().append(searchClassname).append(searchMethodName).append(searchSignature).toString(); - Integer cached = methodCache.get(key); - if (cached!=null) return cached.intValue(); - searchClassname = searchClassname.replace('.','/'); - for (int i=1;i<poolSize;i++) { - Constant c = pool[i]; - if (c!=null && c.tag==Constants.CONSTANT_Methodref) { - ConstantMethodref cfr = (ConstantMethodref)c; - ConstantNameAndType cnat = (ConstantNameAndType)pool[cfr.getNameAndTypeIndex()]; - - // check the class - int cIndex = cfr.getClassIndex(); - ConstantClass cc = (ConstantClass)pool[cIndex]; - String cName = ((ConstantUtf8)pool[cc.getNameIndex()]).getBytes(); - if (!cName.equals(searchClassname)) continue; - - // check the name and type - String name = ((ConstantUtf8)pool[cnat.getNameIndex()]).getBytes(); - if (!name.equals(searchMethodName)) continue; // not this one - String typeSignature = ((ConstantUtf8)pool[cnat.getSignatureIndex()]).getBytes(); - if (!typeSignature.equals(searchSignature)) continue; - methodCache.put(key,new Integer(i)); - return i; - } - } - return -1; - } - - public ConstantPool getFinalConstantPool() { - Constant[] cs = new Constant[poolSize]; // create it the exact size we need - System.arraycopy(pool, 0, cs, 0, poolSize); - return new ConstantPool(cs); - } + int ret, class_index, name_and_type_index; + if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) + return ret; // Already in CP + + adjustSize(); + + name_and_type_index = addNameAndType(method_name, signature); + class_index = addClass(class_name); + ret = poolSize; + pool[poolSize++] = new ConstantMethodref(class_index, name_and_type_index); + return ret; + } + + public int addInterfaceMethodref(String class_name, String method_name, String signature) { + int ret = lookupInterfaceMethodref(class_name, method_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(method_name, signature); + ret = poolSize; + pool[poolSize++] = new ConstantInterfaceMethodref(class_index, name_and_type_index); + return ret; + } + + public int lookupInterfaceMethodref(String searchClassname, String searchMethodName, String searchSignature) { + searchClassname = searchClassname.replace('.', '/'); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_InterfaceMethodref) { + ConstantInterfaceMethodref cfr = (ConstantInterfaceMethodref) c; + + ConstantClass cc = (ConstantClass) pool[cfr.getClassIndex()]; + String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getBytes(); + if (!cName.equals(searchClassname)) + continue; + + // check the name and type + ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()]; + String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getBytes(); + if (!name.equals(searchMethodName)) + continue; // not this one + String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getBytes(); + if (!typeSignature.equals(searchSignature)) + continue; + return i; + } + } + return -1; + } + + public int lookupMethodref(String searchClassname, String searchMethodName, String searchSignature) { + String key = new StringBuffer().append(searchClassname).append(searchMethodName).append(searchSignature).toString(); + Integer cached = methodCache.get(key); + if (cached != null) + return cached.intValue(); + searchClassname = searchClassname.replace('.', '/'); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Methodref) { + ConstantMethodref cfr = (ConstantMethodref) c; + ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()]; + + // check the class + int cIndex = cfr.getClassIndex(); + ConstantClass cc = (ConstantClass) pool[cIndex]; + String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getBytes(); + if (!cName.equals(searchClassname)) + continue; + + // check the name and type + String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getBytes(); + if (!name.equals(searchMethodName)) + continue; // not this one + String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getBytes(); + if (!typeSignature.equals(searchSignature)) + continue; + methodCache.put(key, new Integer(i)); + return i; + } + } + return -1; + } + + public ConstantPool getFinalConstantPool() { + Constant[] cs = new Constant[poolSize]; // create it the exact size we need + System.arraycopy(pool, 0, cs, 0, poolSize); + return new ConstantPool(cs); + } }
\ No newline at end of file diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/JavaClass.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/JavaClass.java index 0d62fb573..1a1ef3c00 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/JavaClass.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/JavaClass.java @@ -80,12 +80,17 @@ import org.aspectj.apache.bcel.util.SyntheticRepository; * The intent of this class is to represent a parsed or otherwise existing class file. Those interested in programatically * generating classes should see the <a href="../generic/ClassGen.html">ClassGen</a> 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> */ 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("<init>") && 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> * * 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<Ljava/lang/String;>;" - // // returnType="V" - // - // // Break signature into its parts - // // dont want lots of substringing so lets use an index - // int posn=0; - // StringBuffer piece; - // while (posn<parameters.length()) { - // piece = new StringBuffer(); - // posn+=getSignatureFrom(parameters,piece); - // } - // StringBuffer buf = new StringBuffer("("); String type; int index; @@ -371,10 +344,6 @@ public abstract class Utility { /** * This method converts this string into a Java type declaration such as 'String[]' and throws a `ClassFormatException' when the * parsed type is invalid. - * - * @param signature Class signature - * @param chopit Flag that determines whether chopping is executed or not - * @return Java type declaration */ public static final ResultHolder signatureToStringInternal(String signature, boolean chopit) { int processedChars = 1; // This is the default, read just one char @@ -392,12 +361,12 @@ public abstract class Utility { return ResultHolder.INT; case 'J': return ResultHolder.LONG; - case 'L': { // Full class name - int index = signature.indexOf(';'); // Look for closing `;' - // Jump to the correct ';' - if (index != -1 && signature.length() > 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<RuntimeAnnotations> getAnnotationAttributes(ConstantPool cp, List<AnnotationGen> vec) { + public static Collection<RuntimeAnnotations> getAnnotationAttributes(ConstantPool cp, List<AnnotationGen> 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 */<ElementNameValuePairGen> evs; + private List<ElementNameValuePairGen> 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<ElementNameValuePairGen> copyValues(List<ElementNameValuePairGen> in,ConstantPool cpool,boolean copyPoolEntries) { + + private List<ElementNameValuePairGen> copyValues(List<ElementNameValuePairGen> in, ConstantPool cpool, boolean copyPoolEntries) { List<ElementNameValuePairGen> out = new ArrayList<ElementNameValuePairGen>(); - for (Iterator<ElementNameValuePairGen> 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<ElementNameValuePairGen>(); } - + /** * 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*/<ElementNameValuePairGen> elements,boolean vis,ConstantPool cpool) { + public AnnotationGen(ObjectType type, List<ElementNameValuePairGen> 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<elemValuePairCount;i++) { - int nidx = dis.readUnsignedShort(); - a.addElementNameValuePair( - new ElementNameValuePairGen(nidx,ElementValueGen.readElementValue(dis,cpool),cpool)); + for (int i = 0; i < elemValuePairCount; i++) { + int nidx = dis.readUnsignedShort(); + a.addElementNameValuePair(new ElementNameValuePairGen(nidx, ElementValueGen.readElementValue(dis, cpool), cpool)); } a.isRuntimeVisible(b); return a; } - + public void dump(DataOutputStream dos) throws IOException { - dos.writeShort(typeIndex); // u2 index of type name in cpool - dos.writeShort(evs.size()); // u2 element_value pair count - for (int i = 0 ; i<evs.size();i++) { - ElementNameValuePairGen envp = evs.get(i); + dos.writeShort(typeIndex); // u2 index of type name in cpool + dos.writeShort(pairs.size()); // u2 element_value pair count + for (int i = 0; i < pairs.size(); i++) { + ElementNameValuePairGen envp = pairs.get(i); envp.dump(dos); } } - + public void addElementNameValuePair(ElementNameValuePairGen evp) { - if (evs == null) evs = new ArrayList<ElementNameValuePairGen>(); - evs.add(evp); + if (pairs == Collections.EMPTY_LIST) { + pairs = new ArrayList<ElementNameValuePairGen>(); + } + 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<ElementNameValuePairGen> getValues() { - return evs; + return pairs; } - + + @Override public String toString() { StringBuffer s = new StringBuffer(); - s.append("AnnotationGen:["+getTypeName()+" #"+evs.size()+" {"); - for (int i = 0; i<evs.size();i++) { - s.append(evs.get(i)); - if (i+1<evs.size()) s.append(","); + s.append("AnnotationGen:[" + getTypeName() + " #" + pairs.size() + " {"); + for (int i = 0; i < pairs.size(); i++) { + s.append(pairs.get(i)); + if (i + 1 < pairs.size()) + s.append(","); } s.append("}]"); return s.toString(); } - + public String toShortString() { StringBuffer s = new StringBuffer(); - s.append("@"+getTypeName()+"("); - for (int i = 0; i<evs.size();i++) { - s.append(evs.get(i)); - if (i+1<evs.size()) s.append(","); + s.append("@" + getTypeName() + "("); + for (int i = 0; i < pairs.size(); i++) { + s.append(pairs.get(i)); + if (i + 1 < pairs.size()) + s.append(","); } s.append(")"); return s.toString(); } private void isRuntimeVisible(boolean b) { - isRuntimeVisible = b; + isRuntimeVisible = b; } - + public boolean isRuntimeVisible() { return isRuntimeVisible; } - + /** - * Return true if the annotation has a value with the specified name (n) and value (v) - */ - public boolean hasNameValuePair(String n, String v) { - for (int i=0;i<evs.size();i++) { - ElementNameValuePairGen pair = evs.get(i); - if (pair.getNameString().equals(n)) { - if (pair.getValue().stringifyValue().equals(v)) return true; + * @return true if the annotation has a value with the specified name and (toString'd) value + */ + public boolean hasNameValuePair(String name, String value) { + for (ElementNameValuePairGen pair : pairs) { + if (pair.getNameString().equals(name)) { + if (pair.getValue().stringifyValue().equals(value)) { + return true; + } } } return false; } - /** - * Return true if the annotation has a value with the specified name (n) - */ - public boolean hasNamedValue(String n) { - for (int i=0;i<evs.size();i++) { - ElementNameValuePairGen pair = evs.get(i); - if (pair.getNameString().equals(n)) return true; + /** + * @return true if the annotation has a value with the specified name + */ + public boolean hasNamedValue(String name) { + for (ElementNameValuePairGen pair : pairs) { + if (pair.getNameString().equals(name)) { + return true; + } } return false; } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementNameValuePairGen.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementNameValuePairGen.java index 451c504b8..4996051d7 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementNameValuePairGen.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementNameValuePairGen.java @@ -15,72 +15,61 @@ package org.aspectj.apache.bcel.classfile.annotation; import java.io.DataOutputStream; import java.io.IOException; -import org.aspectj.apache.bcel.classfile.ConstantUtf8; import org.aspectj.apache.bcel.classfile.ConstantPool; - public class ElementNameValuePairGen { private int nameIdx; private ElementValueGen value; private ConstantPool cpool; - public ElementNameValuePairGen(ElementNameValuePairGen nvp, ConstantPool cpool, boolean copyPoolEntries) { + public ElementNameValuePairGen(ElementNameValuePairGen pair, ConstantPool cpool, boolean copyPoolEntries) { this.cpool = cpool; // J5ASSERT: // Could assert nvp.getNameString() points to the same thing as cpool.getConstant(nvp.getNameIndex()) -// if (!nvp.getNameString().equals(((ConstantUtf8)cpool.getConstant(nvp.getNameIndex())).getBytes())) { -// throw new RuntimeException("envp buggered"); -// } - if (copyPoolEntries) { - nameIdx = cpool.addUtf8(nvp.getNameString()); + // if (!nvp.getNameString().equals(((ConstantUtf8)cpool.getConstant(nvp.getNameIndex())).getBytes())) { + // throw new RuntimeException("envp buggered"); + // } + if (copyPoolEntries) { + nameIdx = cpool.addUtf8(pair.getNameString()); } else { - nameIdx = nvp.getNameIndex(); + nameIdx = pair.getNameIndex(); } - value = ElementValueGen.copy(nvp.getValue(),cpool,copyPoolEntries); + value = ElementValueGen.copy(pair.getValue(), cpool, copyPoolEntries); } - - /** - * Retrieve an immutable version of this ElementNameValuePairGen - */ -// public ElementNameValuePairGen getElementNameValuePair() { -// ElementValueGen immutableValue = value.getElementValue(); -// return new ElementNameValuePairGen(nameIdx,immutableValue,cpool); -// } - - protected ElementNameValuePairGen(int idx,ElementValueGen value,ConstantPool cpool) { + protected ElementNameValuePairGen(int idx, ElementValueGen value, ConstantPool cpool) { this.nameIdx = idx; - this.value = value; - this.cpool = cpool; + this.value = value; + this.cpool = cpool; } - - public ElementNameValuePairGen(String name,ElementValueGen value,ConstantPool cpool) { + + public ElementNameValuePairGen(String name, ElementValueGen value, ConstantPool cpool) { this.nameIdx = cpool.addUtf8(name); - this.value = value; - this.cpool = cpool; + this.value = value; + this.cpool = cpool; } - + protected void dump(DataOutputStream dos) throws IOException { dos.writeShort(nameIdx); // u2 name of the element value.dump(dos); } - + public int getNameIndex() { return nameIdx; } - + public final String getNameString() { -// ConstantString cu8 = (ConstantString)cpool.getConstant(nameIdx); - return ((ConstantUtf8)cpool.getConstant(nameIdx)).getBytes(); + return cpool.getConstantUtf8(nameIdx).getBytes(); } - + public final ElementValueGen getValue() { return value; } - + + @Override public String toString() { StringBuffer sb = new StringBuffer(); - sb.append(getNameString()+"="+value.stringifyValue()); + sb.append(getNameString()).append("=").append(value.stringifyValue()); return sb.toString(); } } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValueGen.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValueGen.java index 7f5030f98..927e6d026 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValueGen.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValueGen.java @@ -15,240 +15,261 @@ package org.aspectj.apache.bcel.classfile.annotation; import java.io.DataOutputStream; import java.io.IOException; +import org.aspectj.apache.bcel.Constants; import org.aspectj.apache.bcel.classfile.ConstantDouble; import org.aspectj.apache.bcel.classfile.ConstantFloat; import org.aspectj.apache.bcel.classfile.ConstantInteger; import org.aspectj.apache.bcel.classfile.ConstantLong; -import org.aspectj.apache.bcel.classfile.ConstantUtf8; import org.aspectj.apache.bcel.classfile.ConstantPool; -import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; + +public class SimpleElementValueGen extends ElementValueGen { -public class SimpleElementValueGen extends ElementValueGen { - // For primitive types and string type, this points to the value entry in the cpGen // For 'class' this points to the class entry in the cpGen private int idx; - - - // ctors for each supported type... type could be inferred but for now lets + + // ctors for each supported type... type could be inferred but for now lets // force it to be passed - + /** - * Protected ctor used for deserialization, doesn't *put* an entry in the constant pool, - * assumes the one at the supplied index is correct. + * Protected ctor used for deserialization, doesn't *put* an entry in the constant pool, assumes the one at the supplied index + * is correct. */ - protected SimpleElementValueGen(int type,int idx,ConstantPool cpGen) { - super(type,cpGen); - this.idx = idx; - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,int value) { - super(type,cpGen); - idx = cpGen.addInteger(value); - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,long value) { - super(type,cpGen); - idx = cpGen.addLong(value); - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,double value) { - super(type,cpGen); - idx = cpGen.addDouble(value); - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,float value) { - super(type,cpGen); - idx = cpGen.addFloat(value); - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,short value) { - super(type,cpGen); - idx = cpGen.addInteger(value); - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,byte value) { - super(type,cpGen); - idx = cpGen.addInteger(value); - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,char value) { - super(type,cpGen); - idx = cpGen.addInteger(value); - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,boolean value) { - super(type,cpGen); - if (value) idx = cpGen.addInteger(1); - else idx = cpGen.addInteger(0); - } - - public SimpleElementValueGen(int type,ConstantPool cpGen,String value) { - super(type,cpGen); - idx = cpGen.addUtf8(value); - } - - - public byte getValueByte() { - if (type != PRIMITIVE_BYTE) - throw new RuntimeException("Dont call getValueByte() on a non BYTE ElementValue"); - ConstantInteger c = (ConstantInteger)cpGen.getConstant(idx,Constants.CONSTANT_Integer); - return (byte)c.getBytes(); - } - - public char getValueChar() { - if (type != PRIMITIVE_CHAR) - throw new RuntimeException("Dont call getValueChar() on a non CHAR ElementValue"); - ConstantInteger c = (ConstantInteger)cpGen.getConstant(idx,Constants.CONSTANT_Integer); - return (char)c.getBytes(); - } - - public long getValueLong() { - if (type != PRIMITIVE_LONG) - throw new RuntimeException("Dont call getValueLong() on a non LONG ElementValue"); - ConstantLong j = (ConstantLong)cpGen.getConstant(idx); - return j.getBytes(); - } - - public float getValueFloat() { - if (type != PRIMITIVE_FLOAT) - throw new RuntimeException("Dont call getValueFloat() on a non FLOAT ElementValue"); - ConstantFloat f = (ConstantFloat)cpGen.getConstant(idx); - return f.getBytes(); - } - - - public double getValueDouble() { - if (type != PRIMITIVE_DOUBLE) - throw new RuntimeException("Dont call getValueDouble() on a non DOUBLE ElementValue"); - ConstantDouble d = (ConstantDouble)cpGen.getConstant(idx); - return d.getBytes(); - } - - public boolean getValueBoolean() { - if (type != PRIMITIVE_BOOLEAN) - throw new RuntimeException("Dont call getValueBoolean() on a non BOOLEAN ElementValue"); - ConstantInteger bo = (ConstantInteger)cpGen.getConstant(idx); - return (bo.getBytes()!=0); - } - - public short getValueShort() { - if (type != PRIMITIVE_SHORT) - throw new RuntimeException("Dont call getValueShort() on a non SHORT ElementValue"); - ConstantInteger s = (ConstantInteger)cpGen.getConstant(idx); - return (short)s.getBytes(); - } - /** - * The boolean controls whether we copy info from the 'old' constant pool - * to the 'new'. You need to use this ctor if the annotation is - * being copied from one file to another. - */ - public SimpleElementValueGen(SimpleElementValueGen value,ConstantPool cpool,boolean copyPoolEntries) { - super(value.getElementValueType(),cpool); + protected SimpleElementValueGen(int type, int idx, ConstantPool cpGen) { + super(type, cpGen); + this.idx = idx; + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, int value) { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, long value) { + super(type, cpGen); + idx = cpGen.addLong(value); + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, double value) { + super(type, cpGen); + idx = cpGen.addDouble(value); + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, float value) { + super(type, cpGen); + idx = cpGen.addFloat(value); + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, short value) { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, byte value) { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, char value) { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, boolean value) { + super(type, cpGen); + if (value) + idx = cpGen.addInteger(1); + else + idx = cpGen.addInteger(0); + } + + public SimpleElementValueGen(int type, ConstantPool cpGen, String value) { + super(type, cpGen); + idx = cpGen.addUtf8(value); + } + + public byte getValueByte() { + if (type != PRIMITIVE_BYTE) + throw new RuntimeException("Dont call getValueByte() on a non BYTE ElementValue"); + ConstantInteger c = (ConstantInteger) cpGen.getConstant(idx, Constants.CONSTANT_Integer); + return (byte) c.getBytes(); + } + + public char getValueChar() { + if (type != PRIMITIVE_CHAR) + throw new RuntimeException("Dont call getValueChar() on a non CHAR ElementValue"); + ConstantInteger c = (ConstantInteger) cpGen.getConstant(idx, Constants.CONSTANT_Integer); + return (char) c.getBytes(); + } + + public long getValueLong() { + if (type != PRIMITIVE_LONG) + throw new RuntimeException("Dont call getValueLong() on a non LONG ElementValue"); + ConstantLong j = (ConstantLong) cpGen.getConstant(idx); + return j.getBytes(); + } + + public float getValueFloat() { + if (type != PRIMITIVE_FLOAT) + throw new RuntimeException("Dont call getValueFloat() on a non FLOAT ElementValue"); + ConstantFloat f = (ConstantFloat) cpGen.getConstant(idx); + return f.getBytes(); + } + + public double getValueDouble() { + if (type != PRIMITIVE_DOUBLE) + throw new RuntimeException("Dont call getValueDouble() on a non DOUBLE ElementValue"); + ConstantDouble d = (ConstantDouble) cpGen.getConstant(idx); + return d.getBytes(); + } + + public boolean getValueBoolean() { + if (type != PRIMITIVE_BOOLEAN) + throw new RuntimeException("Dont call getValueBoolean() on a non BOOLEAN ElementValue"); + ConstantInteger bo = (ConstantInteger) cpGen.getConstant(idx); + return (bo.getBytes() != 0); + } + + public short getValueShort() { + if (type != PRIMITIVE_SHORT) + throw new RuntimeException("Dont call getValueShort() on a non SHORT ElementValue"); + ConstantInteger s = (ConstantInteger) cpGen.getConstant(idx); + return (short) s.getBytes(); + } + + /** + * The boolean controls whether we copy info from the 'old' constant pool to the 'new'. You need to use this ctor if the + * annotation is being copied from one file to another. + */ + public SimpleElementValueGen(SimpleElementValueGen value, ConstantPool cpool, boolean copyPoolEntries) { + super(value.getElementValueType(), cpool); if (!copyPoolEntries) { // J5ASSERT: Could assert value.stringifyValue() is the same as // cpool.getConstant(SimpleElementValuevalue.getIndex()) idx = value.getIndex(); } else { switch (value.getElementValueType()) { - case STRING: idx = cpool.addUtf8(value.getValueString()); break; - case PRIMITIVE_INT: idx = cpool.addInteger(value.getValueInt()); break; - case PRIMITIVE_BYTE: idx = cpool.addInteger(value.getValueByte()); break; - case PRIMITIVE_CHAR: idx = cpool.addInteger(value.getValueChar()); break; - case PRIMITIVE_LONG: idx = cpool.addLong(value.getValueLong()); break; - case PRIMITIVE_FLOAT: idx = cpool.addFloat(value.getValueFloat());break; - case PRIMITIVE_DOUBLE:idx = cpool.addDouble(value.getValueDouble());break; - case PRIMITIVE_BOOLEAN: - if (value.getValueBoolean()) { idx = cpool.addInteger(1); - } else { idx = cpool.addInteger(0);} - break; - case PRIMITIVE_SHORT: idx = cpool.addInteger(value.getValueShort());break; - default: - throw new RuntimeException("SimpleElementValueGen class does not know how "+ - "to copy this type "+type); + case STRING: + idx = cpool.addUtf8(value.getValueString()); + break; + case PRIMITIVE_INT: + idx = cpool.addInteger(value.getValueInt()); + break; + case PRIMITIVE_BYTE: + idx = cpool.addInteger(value.getValueByte()); + break; + case PRIMITIVE_CHAR: + idx = cpool.addInteger(value.getValueChar()); + break; + case PRIMITIVE_LONG: + idx = cpool.addLong(value.getValueLong()); + break; + case PRIMITIVE_FLOAT: + idx = cpool.addFloat(value.getValueFloat()); + break; + case PRIMITIVE_DOUBLE: + idx = cpool.addDouble(value.getValueDouble()); + break; + case PRIMITIVE_BOOLEAN: + if (value.getValueBoolean()) { + idx = cpool.addInteger(1); + } else { + idx = cpool.addInteger(0); + } + break; + case PRIMITIVE_SHORT: + idx = cpool.addInteger(value.getValueShort()); + break; + default: + throw new RuntimeException("SimpleElementValueGen class does not know how " + "to copy this type " + type); } } } - + /** - * Return immutable variant - */ + * Return immutable variant + */ public ElementValueGen getElementValue() { - return new SimpleElementValueGen(type,idx,cpGen); + return new SimpleElementValueGen(type, idx, cpGen); } public int getIndex() { - return idx; - } + return idx; + } - public String getValueString() { - if (type != STRING) - throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); - ConstantUtf8 c = (ConstantUtf8)cpGen.getConstant(idx); + public String getValueString() { + if (type != STRING) + throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); + ConstantUtf8 c = (ConstantUtf8) cpGen.getConstant(idx); return c.getBytes(); - } - - public int getValueInt() { - if (type != PRIMITIVE_INT) - throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); - ConstantInteger c = (ConstantInteger)cpGen.getConstant(idx); + } + + public int getValueInt() { + if (type != PRIMITIVE_INT) + throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); + ConstantInteger c = (ConstantInteger) cpGen.getConstant(idx); return c.getBytes(); - } - - // Whatever kind of value it is, return it as a string - public String stringifyValue() { - switch (type) { - case PRIMITIVE_INT: - ConstantInteger c = (ConstantInteger)cpGen.getConstant(idx); - return Integer.toString(c.getBytes()); - case PRIMITIVE_LONG: - ConstantLong j = (ConstantLong)cpGen.getConstant(idx); - return Long.toString(j.getBytes()); - case PRIMITIVE_DOUBLE: - ConstantDouble d = (ConstantDouble)cpGen.getConstant(idx); - return Double.toString(d.getBytes()); - case PRIMITIVE_FLOAT: - ConstantFloat f = (ConstantFloat)cpGen.getConstant(idx); - return Float.toString(f.getBytes()); - case PRIMITIVE_SHORT: - ConstantInteger s = (ConstantInteger)cpGen.getConstant(idx); - return Integer.toString(s.getBytes()); - case PRIMITIVE_BYTE: - ConstantInteger b = (ConstantInteger)cpGen.getConstant(idx); - return Integer.toString(b.getBytes()); - case PRIMITIVE_CHAR: - ConstantInteger ch = (ConstantInteger)cpGen.getConstant(idx); - return new Character((char)ch.getBytes()).toString(); - case PRIMITIVE_BOOLEAN: - ConstantInteger bo = (ConstantInteger)cpGen.getConstant(idx); - if (bo.getBytes() == 0) return "false"; - else return "true"; - case STRING: - ConstantUtf8 cu8 = (ConstantUtf8)cpGen.getConstant(idx); - return cu8.getBytes(); - - default: - throw new RuntimeException("SimpleElementValueGen class does not know how to stringify type "+type); - } - } - - public void dump(DataOutputStream dos) throws IOException { - dos.writeByte(type); // u1 kind of value - switch (type) { - case PRIMITIVE_INT: - case PRIMITIVE_BYTE: - case PRIMITIVE_CHAR: - case PRIMITIVE_FLOAT: - case PRIMITIVE_LONG: - case PRIMITIVE_BOOLEAN: - case PRIMITIVE_SHORT: - case PRIMITIVE_DOUBLE: - case STRING: - dos.writeShort(idx); - break; - default: - throw new RuntimeException("SimpleElementValueGen doesnt know how to write out type "+type); - } - } - + } + + // Whatever kind of value it is, return it as a string + @Override + public String stringifyValue() { + switch (type) { + case PRIMITIVE_INT: + ConstantInteger c = (ConstantInteger) cpGen.getConstant(idx); + return Integer.toString(c.getBytes()); + case PRIMITIVE_LONG: + ConstantLong j = (ConstantLong) cpGen.getConstant(idx); + return Long.toString(j.getBytes()); + case PRIMITIVE_DOUBLE: + ConstantDouble d = (ConstantDouble) cpGen.getConstant(idx); + return Double.toString(d.getBytes()); + case PRIMITIVE_FLOAT: + ConstantFloat f = (ConstantFloat) cpGen.getConstant(idx); + return Float.toString(f.getBytes()); + case PRIMITIVE_SHORT: + ConstantInteger s = (ConstantInteger) cpGen.getConstant(idx); + return Integer.toString(s.getBytes()); + case PRIMITIVE_BYTE: + ConstantInteger b = (ConstantInteger) cpGen.getConstant(idx); + return Integer.toString(b.getBytes()); + case PRIMITIVE_CHAR: + ConstantInteger ch = (ConstantInteger) cpGen.getConstant(idx); + return new Character((char) ch.getBytes()).toString(); + case PRIMITIVE_BOOLEAN: + ConstantInteger bo = (ConstantInteger) cpGen.getConstant(idx); + if (bo.getBytes() == 0) + return "false"; + else + return "true"; + case STRING: + ConstantUtf8 cu8 = (ConstantUtf8) cpGen.getConstant(idx); + return cu8.getBytes(); + + default: + throw new RuntimeException("SimpleElementValueGen class does not know how to stringify type " + type); + } + } + + @Override + public void dump(DataOutputStream dos) throws IOException { + dos.writeByte(type); // u1 kind of value + switch (type) { + case PRIMITIVE_INT: + case PRIMITIVE_BYTE: + case PRIMITIVE_CHAR: + case PRIMITIVE_FLOAT: + case PRIMITIVE_LONG: + case PRIMITIVE_BOOLEAN: + case PRIMITIVE_SHORT: + case PRIMITIVE_DOUBLE: + case STRING: + dos.writeShort(idx); + break; + default: + throw new RuntimeException("SimpleElementValueGen doesnt know how to write out type " + type); + } + } + } diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/ClassGen.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/ClassGen.java index 8c8504eaf..bafc63359 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/ClassGen.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/ClassGen.java @@ -63,14 +63,12 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.Iterator; import java.util.List; import org.aspectj.apache.bcel.Constants; import org.aspectj.apache.bcel.classfile.Attribute; import org.aspectj.apache.bcel.classfile.ConstantPool; import org.aspectj.apache.bcel.classfile.Field; -import org.aspectj.apache.bcel.classfile.FieldOrMethod; import org.aspectj.apache.bcel.classfile.JavaClass; import org.aspectj.apache.bcel.classfile.Method; import org.aspectj.apache.bcel.classfile.Modifiers; @@ -81,149 +79,103 @@ import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisibleAnnotations; import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations; /** - * Template class for building up a java class. May be initialized with an existing java class (file). + * Template class for building up a java class. May be initialized with an existing java class. * * @see JavaClass - * @version $Id: ClassGen.java,v 1.13 2009/09/09 23:13:20 aclement Exp $ + * @version $Id: ClassGen.java,v 1.14 2009/09/10 03:59:34 aclement Exp $ * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> * * 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> field_vec = new ArrayList<Field>(); - private List<Method> method_vec = new ArrayList<Method>(); + 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<Field> fieldsList = new ArrayList<Field>(); + private List<Method> methodsList = new ArrayList<Method>(); private List<Attribute> attributesList = new ArrayList<Attribute>(); - private List<String> interface_vec = new ArrayList<String>(); + private List<String> interfaceList = new ArrayList<String>(); private List<AnnotationGen> annotationsList = new ArrayList<AnnotationGen>(); - /** - * 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<AnnotationGen> annotationGenObjs = new ArrayList<AnnotationGen>(); - 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<AnnotationGen> annos = rva.getAnnotations(); - for (Iterator<AnnotationGen> 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<AnnotationGen> annos = ria.getAnnotations(); - for (Iterator<AnnotationGen> 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<Attribute>(); - 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, "<init>", "()V"))); + il.append(new InvokeInstruction(Constants.INVOKESPECIAL, cpool.addMethodref(superclassname, "<init>", "()V"))); il.append(InstructionConstants.RETURN); - MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>", class_name, il, cp); + MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>", 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<Field> 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<Method> 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<FieldOrMethod> list = new ArrayList<FieldOrMethod>(); 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<Field> relevantFields = new ArrayList<Field>(); + 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<FieldOrMethod> 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<Method> ctors = new ArrayList<Method>(); + List<Method> relevantMethods = new ArrayList<Method>(); + List<Method> relevantCtors = new ArrayList<Method>(); 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("<clinit>")) { hasClinit = true; } else if (couldBeInitializer && m.getName().equals("<init>")) { 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, <clinit>. @@ -672,16 +558,14 @@ public class ClassGen extends Modifiers implements Cloneable { | Constants.ACC_STRICT; // 6. sorted non-private constructors - for (Iterator<Method> iter = ctors.iterator(); iter.hasNext();) { - Method m = iter.next(); - dos.writeUTF(m.getName()); // <init> - dos.writeInt(relevantFlags & m.getModifiers()); - dos.writeUTF(m.getSignature().replace('/', '.')); + for (Method ctor : relevantCtors) { + dos.writeUTF(ctor.getName()); // <init> + dos.writeInt(relevantFlags & ctor.getModifiers()); + dos.writeUTF(ctor.getSignature().replace('/', '.')); } // 7. sorted non-private methods - for (Iterator<FieldOrMethod> 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<Field> { + 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<Method> { + 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<Method> { + 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<Attribute> 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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> * @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 <a href="#getByteCode()">getByteCode</a>. * - * @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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> * @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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> * @author <A HREF="http://www.vmeng.com/beard">Patrick C. Beard</A> [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 <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> * * 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<Type> vec = new ArrayList<Type>(); + List<Type> argumentTypes = new ArrayList<Type>(); 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; } |