Browse Source

refactoring

tags/V1_6_6
aclement 14 years ago
parent
commit
f7fd9e7bf3
18 changed files with 1465 additions and 1655 deletions
  1. 84
    50
      bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java
  2. 74
    68
      bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java
  3. 48
    87
      bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantClass.java
  4. 45
    77
      bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantDouble.java
  5. 7
    10
      bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantObject.java
  6. 605
    549
      bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java
  7. 26
    64
      bcel-builder/src/org/aspectj/apache/bcel/classfile/JavaClass.java
  8. 35
    49
      bcel-builder/src/org/aspectj/apache/bcel/classfile/Utility.java
  9. 80
    94
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java
  10. 23
    34
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementNameValuePairGen.java
  11. 228
    207
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValueGen.java
  12. 146
    264
      bcel-builder/src/org/aspectj/apache/bcel/generic/ClassGen.java
  13. 3
    2
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java
  14. 12
    22
      bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java
  15. 3
    3
      bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java
  16. 9
    32
      bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java
  17. 36
    42
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnclosingMethodAttributeTest.java
  18. 1
    1
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/UtilTests.java

+ 84
- 50
bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java View File

@@ -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);
}

+ 74
- 68
bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java View File

@@ -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);
}
}
}

+ 48
- 87
bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantClass.java View File

@@ -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 + ")";
}
}

+ 45
- 77
bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantDouble.java View File

@@ -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);
}
}

+ 7
- 10
bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantObject.java View File

@@ -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);
}

+ 605
- 549
bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java
File diff suppressed because it is too large
View File


+ 26
- 64
bcel-builder/src/org/aspectj/apache/bcel/classfile/JavaClass.java View File

@@ -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;
}

+ 35
- 49
bcel-builder/src/org/aspectj/apache/bcel/classfile/Utility.java View File

@@ -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();
}
}

+ 80
- 94
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java View File

@@ -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;
}

+ 23
- 34
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementNameValuePairGen.java View File

@@ -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();
}
}

+ 228
- 207
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValueGen.java View File

@@ -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);
}
}

}

+ 146
- 264
bcel-builder/src/org/aspectj/apache/bcel/generic/ClassGen.java View File

@@ -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;
}

+ 3
- 2
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java View File

@@ -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)

+ 12
- 22
bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionList.java View File

@@ -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;
}

/**

+ 3
- 3
bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java View File

@@ -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));


+ 9
- 32
bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java View File

@@ -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;
}


+ 36
- 42
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnclosingMethodAttributeTest.java View File

@@ -21,82 +21,76 @@ import org.aspectj.apache.bcel.classfile.EnclosingMethod;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.util.SyntheticRepository;


public class EnclosingMethodAttributeTest extends BcelTestCase {

@Override
protected void setUp() throws Exception {
super.setUp();
}

/**
* Verify for an inner class declared inside the 'main' method that the enclosing method
* attribute is set correctly.
* Verify for an inner class declared inside the 'main' method that the enclosing method attribute is set correctly.
*/
public void testCheckMethodLevelNamedInnerClass() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AttributeTestClassEM01$1S");
ConstantPool pool = clazz.getConstantPool();
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length,
encMethodAttrs.length==1);
EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getBytes(pool);
String enclosingMethodName= em.getEnclosingMethod().getName(pool);
assertTrue("Expected class name to be 'AttributeTestClassEM01' but was "+enclosingClassName,
enclosingClassName.equals("AttributeTestClassEM01"));
assertTrue("Expected method name to be 'main' but was "+enclosingMethodName,
enclosingMethodName.equals("main"));
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod", clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found " + encMethodAttrs.length, encMethodAttrs.length == 1);
EnclosingMethod em = (EnclosingMethod) encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getConstantValue(pool);
String enclosingMethodName = em.getEnclosingMethod().getName(pool);
assertTrue("Expected class name to be 'AttributeTestClassEM01' but was " + enclosingClassName, enclosingClassName
.equals("AttributeTestClassEM01"));
assertTrue("Expected method name to be 'main' but was " + enclosingMethodName, enclosingMethodName.equals("main"));
}

/**
* Verify for an inner class declared at the type level that the EnclosingMethod attribute
* is set correctly (i.e. to a null value)
* Verify for an inner class declared at the type level that the EnclosingMethod attribute is set correctly (i.e. to a null
* value)
*/
public void testCheckClassLevelNamedInnerClass() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AttributeTestClassEM02$1");
ConstantPool pool = clazz.getConstantPool();
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length,
encMethodAttrs.length==1);
EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getBytes(pool);
assertTrue("The class is not within a method, so method_index should be null, but it is "+
em.getEnclosingMethodIndex(),em.getEnclosingMethodIndex() == 0);
assertTrue("Expected class name to be 'AttributeTestClassEM02' but was "+enclosingClassName,
enclosingClassName.equals("AttributeTestClassEM02"));
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod", clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found " + encMethodAttrs.length, encMethodAttrs.length == 1);
EnclosingMethod em = (EnclosingMethod) encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getConstantValue(pool);
assertTrue("The class is not within a method, so method_index should be null, but it is " + em.getEnclosingMethodIndex(),
em.getEnclosingMethodIndex() == 0);
assertTrue("Expected class name to be 'AttributeTestClassEM02' but was " + enclosingClassName, enclosingClassName
.equals("AttributeTestClassEM02"));
}
/**
* Check that we can save and load the attribute correctly.
*/
public void testAttributeSerializtion() throws ClassNotFoundException,IOException {
public void testAttributeSerializtion() throws ClassNotFoundException, IOException {
// Read in the class
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AttributeTestClassEM02$1");
ConstantPool pool = clazz.getConstantPool();
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length,
encMethodAttrs.length==1);
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod", clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found " + encMethodAttrs.length, encMethodAttrs.length == 1);

// Write it out
File tfile = createTestdataFile("AttributeTestClassEM02$1.class");
clazz.dump(tfile);
// Read in the new version and check it is OK
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AttributeTestClassEM02$1");
EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getBytes(pool);
assertTrue("The class is not within a method, so method_index should be null, but it is "+
em.getEnclosingMethodIndex(),em.getEnclosingMethodIndex() == 0);
assertTrue("Expected class name to be 'AttributeTestClassEM02' but was "+enclosingClassName,
enclosingClassName.equals("AttributeTestClassEM02"));
EnclosingMethod em = (EnclosingMethod) encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getConstantValue(pool);
assertTrue("The class is not within a method, so method_index should be null, but it is " + em.getEnclosingMethodIndex(),
em.getEnclosingMethodIndex() == 0);
assertTrue("Expected class name to be 'AttributeTestClassEM02' but was " + enclosingClassName, enclosingClassName
.equals("AttributeTestClassEM02"));
assertTrue(tfile.delete());
}

@Override
protected void tearDown() throws Exception {
super.tearDown();
}

+ 1
- 1
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/UtilTests.java View File

@@ -40,7 +40,7 @@ public class UtilTests extends TestCase {
}
public void testTypeUtilMethods1() {
String s = Type.getMethodSignature(Type.DOUBLE,new Type[]{Type.INT,Type.STRING,Type.SHORT});
String s = Utility.toMethodSignature(Type.DOUBLE,new Type[]{Type.INT,Type.STRING,Type.SHORT});
System.err.println(s);
}

Loading…
Cancel
Save