]> source.dussan.org Git - aspectj.git/commitdiff
refactoring
authoraclement <aclement>
Wed, 9 Sep 2009 22:18:20 +0000 (22:18 +0000)
committeraclement <aclement>
Wed, 9 Sep 2009 22:18:20 +0000 (22:18 +0000)
bcel-builder/src/org/aspectj/apache/bcel/Repository.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/JavaClass.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/Utility.java
bcel-builder/src/org/aspectj/apache/bcel/generic/ClassGen.java
bcel-builder/src/org/aspectj/apache/bcel/generic/FieldGenOrMethodGen.java
bcel-builder/src/org/aspectj/apache/bcel/generic/ReferenceType.java
bcel-builder/src/org/aspectj/apache/bcel/util/ClassQueue.java [deleted file]
bcel-builder/src/org/aspectj/apache/bcel/util/ClassVector.java [deleted file]

index 32832f90e000569d92dcb8492fc3e0b0d4bed6c7..073355b5b21f2e858e0f72042627ddc9e857eda5 100644 (file)
@@ -67,7 +67,7 @@ import org.aspectj.apache.bcel.util.SyntheticRepository;
  * @see org.aspectj.apache.bcel.util.Repository
  * @see org.aspectj.apache.bcel.util.SyntheticRepository
  * 
- * @version $Id: Repository.java,v 1.5 2008/08/28 15:36:59 aclement Exp $
+ * @version $Id: Repository.java,v 1.6 2009/09/09 22:18:20 aclement Exp $
  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  */
 public abstract class Repository {
@@ -166,29 +166,30 @@ public abstract class Repository {
        // getRepository().removeClass(clazz);
        // }
 
-       /**
-        * @return list of super classes of clazz in ascending order, i.e., Object is always the last element
-        */
-       public static JavaClass[] getSuperClasses(JavaClass clazz) {
-               return clazz.getSuperClasses();
-       }
-
-       /**
-        * @return list of super classes of clazz in ascending order, i.e., Object is always the last element. return "null", if class
-        *         cannot be found.
-        */
-       public static JavaClass[] getSuperClasses(String class_name) {
-               JavaClass jc = lookupClass(class_name);
-               return jc == null ? null : getSuperClasses(jc);
-       }
-
-       /**
-        * @return all interfaces implemented by class and its super classes and the interfaces that those interfaces extend, and so on.
-        *         (Some people call this a transitive hull).
-        */
-       public static JavaClass[] getInterfaces(JavaClass clazz) {
-               return clazz.getAllInterfaces();
-       }
+       // /**
+       // * @return list of super classes of clazz in ascending order, i.e., Object is always the last element
+       // */
+       // public static JavaClass[] getSuperClasses(JavaClass clazz) {
+       // return clazz.getSuperClasses();
+       // }
+       //
+       // /**
+       // * @return list of super classes of clazz in ascending order, i.e., Object is always the last element. return "null", if class
+       // * cannot be found.
+       // */
+       // public static JavaClass[] getSuperClasses(String class_name) {
+       // JavaClass jc = lookupClass(class_name);
+       // return jc == null ? null : getSuperClasses(jc);
+       // }
+       //
+       // /**
+       // * @return all interfaces implemented by class and its super classes and the interfaces that those interfaces extend, and so
+       // on.
+       // * (Some people call this a transitive hull).
+       // */
+       // public static JavaClass[] getInterfaces(JavaClass clazz) {
+       // return clazz.getAllInterfaces();
+       // }
 
        // /**
        // * @return all interfaces implemented by class and its super classes and the interfaces that extend those interfaces, and so
index ac3fae655c30ddd58956db94a9233c2e623a9f30..0d62fb57340391d0148ec3e2df3ab61ec0678993 100644 (file)
@@ -61,15 +61,16 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Queue;
 import java.util.StringTokenizer;
 
 import org.aspectj.apache.bcel.Constants;
 import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnotations;
 import org.aspectj.apache.bcel.generic.Type;
-import org.aspectj.apache.bcel.util.ClassQueue;
-import org.aspectj.apache.bcel.util.ClassVector;
 import org.aspectj.apache.bcel.util.SyntheticRepository;
 
 /**
@@ -79,7 +80,7 @@ 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.16 2009/09/09 21:26:54 aclement Exp $
+ * @version $Id: JavaClass.java,v 1.17 2009/09/09 22:18:20 aclement Exp $
  * @see org.aspectj.apache.bcel.generic.ClassGen
  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  */
@@ -789,13 +790,18 @@ public class JavaClass extends Modifiers implements Cloneable, Node {
                        return true;
                }
 
-               JavaClass[] super_interfaces = getAllInterfaces();
+               Collection<JavaClass> superInterfaces = getAllInterfaces();
 
-               for (int i = 0; i < super_interfaces.length; i++) {
-                       if (super_interfaces[i].equals(inter)) {
+               for (JavaClass superInterface : superInterfaces) {
+                       if (superInterface.equals(inter)) {
                                return true;
                        }
                }
+               // for (int i = 0; i < super_interfaces.length; i++) {
+               // if (super_interfaces[i].equals(inter)) {
+               // return true;
+               // }
+               // }
 
                return false;
        }
@@ -821,13 +827,11 @@ public class JavaClass extends Modifiers implements Cloneable, Node {
         */
        public JavaClass[] getSuperClasses() {
                JavaClass clazz = this;
-               ClassVector vec = new ClassVector();
-
+               List<JavaClass> vec = new ArrayList<JavaClass>();
                for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
-                       vec.addElement(clazz);
+                       vec.add(clazz);
                }
-
-               return vec.toArray();
+               return vec.toArray(new JavaClass[vec.size()]);
        }
 
        /**
@@ -852,33 +856,33 @@ public class JavaClass extends Modifiers implements Cloneable, Node {
        /**
         * Get all interfaces implemented by this JavaClass (transitively).
         */
-       // OPTIMIZE get rid of ClassQueue and ClassVector
-       public JavaClass[] getAllInterfaces() {
-               ClassQueue queue = new ClassQueue();
-               ClassVector vec = new ClassVector();
+       public Collection<JavaClass> getAllInterfaces() {
+               Queue<JavaClass> queue = new LinkedList<JavaClass>();
+               List<JavaClass> interfaceList = new ArrayList<JavaClass>();
 
-               queue.enqueue(this);
+               queue.add(this);
 
-               while (!queue.empty()) {
-                       JavaClass clazz = queue.dequeue();
+               while (!queue.isEmpty()) {
+                       JavaClass clazz = queue.remove();
 
                        JavaClass souper = clazz.getSuperClass();
                        JavaClass[] interfaces = clazz.getInterfaces();
 
                        if (clazz.isInterface()) {
-                               vec.addElement(clazz);
+                               interfaceList.add(clazz);
                        } else {
                                if (souper != null) {
-                                       queue.enqueue(souper);
+                                       queue.add(souper);
                                }
                        }
 
                        for (int i = 0; i < interfaces.length; i++) {
-                               queue.enqueue(interfaces[i]);
+                               queue.add(interfaces[i]);
                        }
                }
 
-               return vec.toArray();
+               return interfaceList;
+               // return interfaceList.toArray(new JavaClass[interfaceList.size()]);
        }
 
        /**
index f8770affe30c70f38db490eddfbd00607fca05f7..b121d803b8b27187c962ccdc6e6940420e0e7a7c 100644 (file)
@@ -58,6 +58,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -73,966 +74,1019 @@ 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.8 2009/09/09 19:56:20 aclement Exp $
- * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  * 
- * modified: Andy Clement  2-mar-05  Removed unnecessary static and optimized
+ * @version $Id: Utility.java,v 1.9 2009/09/09 22:18:20 aclement Exp $
+ * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
+ * 
+ *         modified: Andy Clement 2-mar-05 Removed unnecessary static and optimized
  */
 public abstract class Utility {
 
-  /* The 'WIDE' instruction is used in the byte code to allow 16-bit wide indices for local 
-   * variables. This opcode precedes an 'ILOAD', e.g.. The opcode immediately following takes 
-   * an extra byte which is combined with the following byte to form a 16-bit value.
-   */
-  private static boolean wide = false; 
-  
-  /**
-   * Convert bit field of flags into string such as 'static final'.
-   *
-   * @param  access_flags Access flags
-   * @return String representation of flags
-   */
-  public static final String accessToString(int access_flags) {
-    return accessToString(access_flags, false);
-  }
-  
-  /**
-   * Convert bit field of flags into string such as 'static final'.
-   *
-   * Special case: Classes compiled with new compilers and with the
-   * 'ACC_SUPER' flag would be said to be "synchronized". This is
-   * because SUN used the same value for the flags 'ACC_SUPER' and
-   * 'ACC_SYNCHRONIZED'. 
-   *
-   * @param  access_flags Access flags
-   * @param  for_class access flags are for class qualifiers ?
-   * @return String representation of flags
-   */
-  public static final String accessToString(int access_flags, boolean for_class) {
-    StringBuffer buf = new StringBuffer();
-
-    int p = 0;
-    for (int i=0; p < Constants.MAX_ACC_FLAG; i++) { // Loop through known flags
-      p = pow2(i);
-      if ((access_flags & p) != 0) {
-           // Special case: see comment at top of class...
-           if (for_class && ((p == Constants.ACC_SUPER) || (p == Constants.ACC_INTERFACE)))
-              continue;            
-           buf.append(Constants.ACCESS_NAMES[i]).append(" ");
-      }
-    }
-    return buf.toString().trim();
-  }
-
-  
-  /**
-   * @return "class" or "interface", depending on the ACC_INTERFACE flag
-   */
-  public static final String classOrInterface(int access_flags) {
-    return ((access_flags & Constants.ACC_INTERFACE) != 0)? "interface" : "class";
-  }
-
-  
-  /**
-   * Disassemble a byte array of JVM byte codes starting from code line 
-   * 'index' and return the disassembled string representation. Decode only
-   * 'num' opcodes (including their operands), use -1 if you want to
-   * decompile everything.
-   *
-   * @param  code byte code array
-   * @param  constant_pool Array of constants
-   * @param  index offset in `code' array
-   * <EM>(number of opcodes, not bytes!)</EM>
-   * @param  length number of opcodes to decompile, -1 for all
-   * @param  verbose be verbose, e.g. print constant pool index
-   * @return String representation of byte codes
-   */
-  public static final String codeToString(byte[] code, 
-                                         ConstantPool constant_pool, 
-                                         int index, int length, boolean verbose)
-  {
-    StringBuffer buf    = new StringBuffer(code.length * 20); // Should be sufficient
-    ByteSequence stream = new ByteSequence(code);
-
-    try {
-      for (int i=0; i < index; i++) // Skip `index' lines of code
-           codeToString(stream, constant_pool, verbose);
-
-      for (int i=0; stream.available() > 0; i++) {
-           if ((length < 0) || (i < length)) {
-             String indices = fillup(stream.getIndex() + ":", 6, true, ' ');
-             buf.append(indices + codeToString(stream, constant_pool, verbose) + '\n');
-           }
-      }
-    } catch(IOException e) {
-      System.out.println(buf.toString());
-      e.printStackTrace();
-      throw new ClassFormatException("Byte code error: " + e);
-    }
-
-    return buf.toString();
-  }
-
-  
-  
-  /** 
-   * Disassemble a stream of byte codes and return the
-   * string representation.
-   */
-  public static final String codeToString(byte[] code, ConstantPool constant_pool, int index, int length) {
-    return codeToString(code, constant_pool, index, length, true);
-  }
-
-
-
-  public static final String codeToString(ByteSequence bytes, ConstantPool constant_pool)
-    throws IOException {
-    return codeToString(bytes, constant_pool, true);
-  }
-
-  /**
-   * Shorten long class names, <em>java/lang/String</em> becomes <em>String</em>.
-   *
-   * @param str The long class name
-   * @return Compacted class name
-   */
-  public static final String compactClassName(String str) {
-    return compactClassName(str, true);
-  }
-  /**
-   * Shorten long class name <em>str</em>, i.e., chop off the <em>prefix</em>,
-   * if the
-   * class name starts with this string and the flag <em>chopit</em> is true.
-   * Slashes <em>/</em> are converted to dots <em>.</em>.
-   *
-   * @param str The long class name
-   * @param prefix The prefix the get rid off
-   * @param chopit Flag that determines whether chopping is executed or not
-   * @return Compacted class name
-   */
-  public static final String compactClassName(String str, 
-                                             String prefix,
-                                             boolean chopit)
-  {
-    int len = prefix.length();
-
-    str = str.replace('/', '.'); // Is '/' on all systems, even DOS
-
-    if (chopit) {
-         // If string starts with 'prefix' and contains no further dots
-         if (str.startsWith(prefix)) {
-                 String result = str.substring(len);
-                 if ( result.indexOf('.') == -1) {
-                           str = result;                 
-                 }
-         }
-    }
-    return str;
-  }
-
-  
-  
-  /**
-   * Shorten long class names, <em>java/lang/String</em> becomes 
-   * <em>java.lang.String</em>,
-   * e.g.. If <em>chopit</em> is <em>true</em> the prefix <em>java.lang</em>
-   * is also removed.
-   *
-   * @param str The long class name
-   * @param chopit Flag that determines whether chopping is executed or not
-   * @return Compacted class name
-   */
-  public static final String compactClassName(String str, boolean chopit) {
-    return compactClassName(str, "java.lang.", chopit);
-  }    
-  
-  public static final String methodSignatureToString(String signature,String name,String access) {
-    return methodSignatureToString(signature, name, access, true);
-  }
-
-  public static final String methodSignatureToString(String signature,String name,
-                                                              String access,boolean chopit) {
-    return methodSignatureToString(signature, name, access, chopit, null);
-  }
-
-  /**
-   * 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;
-    int          var_index = (access.indexOf("static") >= 0)? 0 : 1;
-
-    try { // Read all declarations between for `(' and `)'
-      if (signature.charAt(0) != '(')
-            throw new ClassFormatException("Invalid method signature: " + signature);
-
-      index = 1; // current string position
-
-      while(signature.charAt(index) != ')') {
-       ResultHolder rh = signatureToStringInternal(signature.substring(index), chopit);
-           String param_type = rh.getResult();
-           buf.append(param_type);
-
-           if(vars != null) {
-             LocalVariable l = vars.getLocalVariable(var_index);
-
-             if(l != null)
-               buf.append(" " + l.getName());
-           } else
-             buf.append(" arg" + var_index);
-
-             if("double".equals(param_type) || "long".equals(param_type))
-             var_index += 2;
-          else
-             var_index++;
-
-          buf.append(", ");
-             index += rh.getConsumedChars(); 
-      }
-
-      index++;
-
-      // Read return type after `)'
-      type = signatureToString(signature.substring(index), chopit);
-
-    } catch(StringIndexOutOfBoundsException e) { // Should never occur
-      throw new ClassFormatException("Invalid method signature: " + signature);
-    }
-
-    if(buf.length() > 1) // Tack off the extra ", "
-      buf.setLength(buf.length() - 2);
-
-    buf.append(")");
-
-    return access + ((access.length() > 0)? " " : "") + // May be an empty string
-      type + " " + name + buf.toString();
-  }
-  
-
-    
-  /**
-   * Replace all occurences of <em>old</em> in <em>str</em> with <em>new</em>.
-   *
-   * @param str String to permute
-   * @param old String to be replaced
-   * @param new Replacement string
-   * @return new String object
-   */
-  public static final String replace(String str, String old, String new_) {
-    int          index, old_index;
-    StringBuffer buf = new StringBuffer();
-
-    try {
-         index = str.indexOf(old);
-      if ( index != -1) {
-           old_index = 0;
-         
-           // While we have something to replace
-           while((index = str.indexOf(old, old_index)) != -1) {
-             buf.append(str.substring(old_index, index)); // append prefix
-             buf.append(new_);                            // append replacement
-             old_index = index + old.length(); // Skip 'old'.length chars
-           }
-
-           buf.append(str.substring(old_index)); // append rest of string
-           str = buf.toString();       
-      }
-    } catch(StringIndexOutOfBoundsException e) { 
-      System.err.println(e);
-    }
-
-    return str;
-  }
-
-  /**
-   * Converts signature to string with all class names compacted.
-   *
-   * @param signature to convert
-   * @return Human readable signature
-   */
-  public static final String signatureToString(String signature) {
-    return signatureToString(signature, true);
-  }    
-  
-
-  public static final String signatureToString(String signature,boolean chopit) {
-       ResultHolder rh = signatureToStringInternal(signature,chopit);
-       return rh.getResult();
-  }
-
-  /**
-   * 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
-    try {
-      switch(signature.charAt(0)) {
-        case 'B' : return ResultHolder.BYTE;
-        case 'C' : return ResultHolder.CHAR;
-        case 'D' : return ResultHolder.DOUBLE;
-        case 'F' : return ResultHolder.FLOAT;
-        case 'I' : 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)=='>') index = index+2;
-
-             if (index < 0)
-               throw new ClassFormatException("Invalid signature: " + signature);
-       
-             int genericStart = signature.indexOf('<');
-             int genericEnd = signature.indexOf('>');
-             if (genericStart !=-1) {
-               // FIXME asc going to need a lot more work in here for generics
-               ResultHolder rh = signatureToStringInternal(signature.substring(genericStart+1,genericEnd),chopit);
-                   ResultHolder retval = new ResultHolder(compactClassName(signature.substring(1,genericStart)+"<"+
-                                   rh.getResult()+">",chopit),genericEnd+1);
-                                   return retval;
-             } else {
-               processedChars = index + 1; // "Lblabla;" `L' and `;' are removed
-               ResultHolder retval = new ResultHolder(compactClassName(signature.substring(1, index), chopit),processedChars);
-               return retval;
-             }
-        }
-
-      case 'S' : return ResultHolder.SHORT;
-      case 'Z' : return ResultHolder.BOOLEAN;
-
-      case '[' : { // Array declaration
-       StringBuffer  brackets;
-       int          consumedChars,n;
-
-           brackets = new StringBuffer(); // Accumulate []'s
-           // Count opening brackets and look for optional size argument
-           for(n=0; signature.charAt(n) == '['; n++)
-             brackets.append("[]");
-             consumedChars = n;
-             // The rest of the string denotes a `<field_type>'
-             ResultHolder restOfIt = signatureToStringInternal(signature.substring(n),chopit);
-             
-             //  type = signatureToString(signature.substring(n), chopit);
-       
-             consumedChars+= restOfIt.getConsumedChars();
-             return new ResultHolder(restOfIt.getResult() + brackets.toString(),consumedChars);
-        }
-               
-      case 'V' : return ResultHolder.VOID;
-
-      default  : throw new ClassFormatException("Invalid signature: `" +
-                                           signature + "'");
-      }
-    } catch(StringIndexOutOfBoundsException e) { // Should never occur
-      throw new ClassFormatException("Invalid signature: " + e + ":" + signature);
-    }
-  }
-  
-  
-
-
-  /**
-   * Return type of method signature as a byte value as defined in <em>Constants</em>
-   *
-   * @param  signature in format described above
-   * @return type of method signature
-   * @see    Constants
-   */
-  public static final byte typeOfMethodSignature(String signature) throws ClassFormatException {
-    int index;
-
-    try {
-      if (signature.charAt(0) != '(')
-           throw new ClassFormatException("Invalid method signature: " + signature);
-      index = signature.lastIndexOf(')') + 1;
-      return typeOfSignature(signature.substring(index));
-    } catch(StringIndexOutOfBoundsException e) {
-      throw new ClassFormatException("Invalid method signature: " + signature);
-    }
-  }
-
-  /**
-   * Convert (signed) byte to (unsigned) short value, i.e., all negative
-   * values become positive.
-   */
-  private static final short byteToShort(byte b) {
-    return (b < 0)? (short)(256 + b) : (short)b;
-  }
-
-  /** 
-   * Convert bytes into hexidecimal string
-   *
-   * @return bytes as hexidecimal string, e.g. 00 FA 12 ...
-   */
-  public static final String toHexString(byte[] bytes) {
-    StringBuffer buf = new StringBuffer();
-
-    for(int i=0; i < bytes.length; i++) {
-      short  b   = byteToShort(bytes[i]);
-      String hex = Integer.toString(b, 0x10);
-
-         // Just one digit, so prepend 0
-      if (b < 0x10) buf.append('0');
-
-      buf.append(hex);
-
-      if (i < bytes.length - 1) buf.append(' ');
-    }
-
-    return buf.toString();
-  }
-
-  /**
-   * Return a string for an integer justified left or right and filled up with
-   * 'fill' characters if necessary.
-   *
-   * @param i integer to format
-   * @param length length of desired string
-   * @param left_justify format left or right
-   * @param fill fill character
-   * @return formatted int
-   */
-  public static final String format(int i, int length, boolean left_justify, char fill) {
-    return fillup(Integer.toString(i), length, left_justify, fill);
-  }
-
-  /**
-   * Fillup char with up to length characters with char `fill' and justify it left or right.
-   *
-   * @param str string to format
-   * @param length length of desired string
-   * @param left_justify format left or right
-   * @param fill fill character
-   * @return formatted string
-   */
-  public static final String fillup(String str, int length, boolean left_justify, char fill) {
-    int    len = length - str.length();
-    char[] buf = new char[(len < 0)? 0 : len];
-
-    for(int j=0; j < buf.length; j++)
-      buf[j] = fill;
-
-    if(left_justify)
-      return str + new String(buf);    
-    else
-      return new String(buf) + str;
-  }
-  /**
-   * Escape all occurences of newline chars '\n', quotes \", etc.
-   */
-  public static final String convertString(String label) {
-    char[]       ch  = label.toCharArray();
-    StringBuffer buf = new StringBuffer();
-
-    for(int i=0; i < ch.length; i++) {
-      switch(ch[i]) {
-      case '\n':
-       buf.append("\\n"); break;
-      case '\r':
-       buf.append("\\r"); break;
-      case '\"':
-       buf.append("\\\""); break;
-      case '\'':
-       buf.append("\\'"); break;
-      case '\\':
-       buf.append("\\\\"); break;
-      default:
-       buf.append(ch[i]); break;
-      }
-    }
-
-    return buf.toString();
-  }
-
-  /**
-   * 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
-   */
-  public static Attribute[] getAnnotationAttributes(ConstantPool cp,List<AnnotationGen> vec) {
-       
-       if (vec.size()==0) return null;
-       
-       try {
-               int countVisible   = 0;
-               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()) countVisible++;
-                       else                       countInvisible++;
-               }
-       
-               ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream();
-               ByteArrayOutputStream riaBytes = new ByteArrayOutputStream();
-               DataOutputStream rvaDos = new DataOutputStream(rvaBytes);
-               DataOutputStream riaDos = new DataOutputStream(riaBytes);
-       
-               rvaDos.writeShort(countVisible);
-               riaDos.writeShort(countInvisible);
-
-               // put the annotations in the right output stream
-               for (int i=0; i<vec.size(); i++) {
-                       AnnotationGen a = vec.get(i);
-                       if (a.isRuntimeVisible()) a.dump(rvaDos);
-                       else                       a.dump(riaDos);
-               }
-
-    rvaDos.close();
-    riaDos.close();
-    
-    byte[] rvaData = rvaBytes.toByteArray();
-    byte[] riaData = riaBytes.toByteArray();
-    
-    int rvaIndex = -1;
-    int riaIndex = -1;
-    
-    if (rvaData.length>2) rvaIndex = cp.addUtf8("RuntimeVisibleAnnotations");
-    if (riaData.length>2) riaIndex = cp.addUtf8("RuntimeInvisibleAnnotations");
-
-       List<RuntimeAnnotations> newAttributes = new ArrayList<RuntimeAnnotations>();
-       if (rvaData.length>2) {
-               newAttributes.add(
-                 new RuntimeVisibleAnnotations(rvaIndex,rvaData.length,rvaData,cp));
-       }
-       if (riaData.length>2) {
-               newAttributes.add(
-                 new RuntimeInvisibleAnnotations(riaIndex,riaData.length,riaData,cp));
-       }
-
-       return newAttributes.toArray(new Attribute[]{});
-       } catch (IOException e) {
-               System.err.println("IOException whilst processing annotations");
-               e.printStackTrace();
+       /*
+        * The 'WIDE' instruction is used in the byte code to allow 16-bit wide indices for local variables. This opcode precedes an
+        * 'ILOAD', e.g.. The opcode immediately following takes an extra byte which is combined with the following byte to form a
+        * 16-bit value.
+        */
+       private static boolean wide = false;
+
+       /**
+        * Convert bit field of flags into string such as 'static final'.
+        * 
+        * @param access_flags Access flags
+        * @return String representation of flags
+        */
+       public static final String accessToString(int access_flags) {
+               return accessToString(access_flags, false);
+       }
+
+       /**
+        * Convert bit field of flags into string such as 'static final'.
+        * 
+        * Special case: Classes compiled with new compilers and with the 'ACC_SUPER' flag would be said to be "synchronized". This is
+        * because SUN used the same value for the flags 'ACC_SUPER' and 'ACC_SYNCHRONIZED'.
+        * 
+        * @param access_flags Access flags
+        * @param for_class access flags are for class qualifiers ?
+        * @return String representation of flags
+        */
+       public static final String accessToString(int access_flags, boolean for_class) {
+               StringBuffer buf = new StringBuffer();
+
+               int p = 0;
+               for (int i = 0; p < Constants.MAX_ACC_FLAG; i++) { // Loop through known flags
+                       p = pow2(i);
+                       if ((access_flags & p) != 0) {
+                               // Special case: see comment at top of class...
+                               if (for_class && ((p == Constants.ACC_SUPER) || (p == Constants.ACC_INTERFACE)))
+                                       continue;
+                               buf.append(Constants.ACCESS_NAMES[i]).append(" ");
+                       }
+               }
+               return buf.toString().trim();
+       }
+
+       /**
+        * @return "class" or "interface", depending on the ACC_INTERFACE flag
+        */
+       public static final String classOrInterface(int access_flags) {
+               return ((access_flags & Constants.ACC_INTERFACE) != 0) ? "interface" : "class";
        }
-       return null;
-  }
-
-  /**
-   * Annotations against a class are stored in one of four attribute kinds:
-   * - RuntimeVisibleParameterAnnotations
-   * - RuntimeInvisibleParameterAnnotations
-   */
-  // OPTIMIZE looks heavyweight?
-  public static Attribute[] getParameterAnnotationAttributes(ConstantPool cp,List[] /*Array of lists, array size depends on #params */ vec) {
-       
-       int visCount[]   = new int[vec.length]; 
-       int totalVisCount = 0;
-       int invisCount[] = new int[vec.length];
-       int totalInvisCount = 0;
-       try {
-       
-               for (int i=0; i<vec.length; i++) {
-                       List l = vec[i];
-                       if (l!=null) {
-                         for (Iterator iter = l.iterator(); iter.hasNext();) {
-                               AnnotationGen element = (AnnotationGen) iter.next();
-                               if (element.isRuntimeVisible()) {visCount[i]++;totalVisCount++;}
-                               else                            {invisCount[i]++;totalInvisCount++;}
-                         }
-                       }
-               }               
-               
-               // Lets do the visible ones
-               ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream();
-               DataOutputStream rvaDos = new DataOutputStream(rvaBytes);
-               rvaDos.writeByte(vec.length); // First goes number of parameters
-               
-               for (int i=0; i<vec.length; i++) {
-                       rvaDos.writeShort(visCount[i]);
-                       if (visCount[i]>0) {
-                               List l = vec[i];
-                               for (Iterator iter = l.iterator(); iter.hasNext();) {
-                                       AnnotationGen element = (AnnotationGen) iter.next();
-                                       if (element.isRuntimeVisible()) element.dump(rvaDos);
+
+       /**
+        * Disassemble a byte array of JVM byte codes starting from code line 'index' and return the disassembled string representation.
+        * Decode only 'num' opcodes (including their operands), use -1 if you want to decompile everything.
+        * 
+        * @param code byte code array
+        * @param constant_pool Array of constants
+        * @param index offset in `code' array <EM>(number of opcodes, not bytes!)</EM>
+        * @param length number of opcodes to decompile, -1 for all
+        * @param verbose be verbose, e.g. print constant pool index
+        * @return String representation of byte codes
+        */
+       public static final String codeToString(byte[] code, ConstantPool constant_pool, int index, int length, boolean verbose) {
+               StringBuffer buf = new StringBuffer(code.length * 20); // Should be sufficient
+               ByteSequence stream = new ByteSequence(code);
+
+               try {
+                       for (int i = 0; i < index; i++)
+                               // Skip `index' lines of code
+                               codeToString(stream, constant_pool, verbose);
+
+                       for (int i = 0; stream.available() > 0; i++) {
+                               if ((length < 0) || (i < length)) {
+                                       String indices = fillup(stream.getIndex() + ":", 6, true, ' ');
+                                       buf.append(indices + codeToString(stream, constant_pool, verbose) + '\n');
                                }
-                       }
-               }
-           rvaDos.close();
-               
-               // Lets do the invisible ones
-               ByteArrayOutputStream riaBytes = new ByteArrayOutputStream();
-               DataOutputStream riaDos = new DataOutputStream(riaBytes);
-               riaDos.writeByte(vec.length); // First goes number of parameters
-               
-               for (int i=0; i<vec.length; i++) {
-                       riaDos.writeShort(invisCount[i]);
-                       if (invisCount[i]>0) {
-                               List l = vec[i];
-                               for (Iterator iter = l.iterator(); iter.hasNext();) {
-                                       AnnotationGen element = (AnnotationGen) iter.next();
-                                       if (!element.isRuntimeVisible()) element.dump(riaDos);
+                       }
+               } catch (IOException e) {
+                       System.out.println(buf.toString());
+                       e.printStackTrace();
+                       throw new ClassFormatException("Byte code error: " + e);
+               }
+
+               return buf.toString();
+       }
+
+       /**
+        * Disassemble a stream of byte codes and return the string representation.
+        */
+       public static final String codeToString(byte[] code, ConstantPool constant_pool, int index, int length) {
+               return codeToString(code, constant_pool, index, length, true);
+       }
+
+       public static final String codeToString(ByteSequence bytes, ConstantPool constant_pool) throws IOException {
+               return codeToString(bytes, constant_pool, true);
+       }
+
+       /**
+        * Shorten long class names, <em>java/lang/String</em> becomes <em>String</em>.
+        * 
+        * @param str The long class name
+        * @return Compacted class name
+        */
+       public static final String compactClassName(String str) {
+               return compactClassName(str, true);
+       }
+
+       /**
+        * Shorten long class name <em>str</em>, i.e., chop off the <em>prefix</em>, if the class name starts with this string and the
+        * flag <em>chopit</em> is true. Slashes <em>/</em> are converted to dots <em>.</em>.
+        * 
+        * @param str The long class name
+        * @param prefix The prefix the get rid off
+        * @param chopit Flag that determines whether chopping is executed or not
+        * @return Compacted class name
+        */
+       public static final String compactClassName(String str, String prefix, boolean chopit) {
+               int len = prefix.length();
+
+               str = str.replace('/', '.'); // Is '/' on all systems, even DOS
+
+               if (chopit) {
+                       // If string starts with 'prefix' and contains no further dots
+                       if (str.startsWith(prefix)) {
+                               String result = str.substring(len);
+                               if (result.indexOf('.') == -1) {
+                                       str = result;
                                }
-                       }
-               }
-           riaDos.close();
-               
-           byte[] rvaData = rvaBytes.toByteArray();
-           byte[] riaData = riaBytes.toByteArray();
-    
-           int rvaIndex = -1;
-           int riaIndex = -1;
-    
-           if (totalVisCount>0)   rvaIndex = cp.addUtf8("RuntimeVisibleParameterAnnotations");
-           if (totalInvisCount>0) riaIndex = cp.addUtf8("RuntimeInvisibleParameterAnnotations");
-
-           List<RuntimeParameterAnnotations> newAttributes = new ArrayList<RuntimeParameterAnnotations>();
-
-           if (totalVisCount>0) {
-                   newAttributes.add(
-                       new RuntimeVisibleParameterAnnotations(rvaIndex,rvaData.length,rvaData,cp));
-           }
-       
-
-           if (totalInvisCount>0) {
-               newAttributes.add(
-                   new RuntimeInvisibleParameterAnnotations(riaIndex,riaData.length,riaData,cp));
-           }
-
-           return newAttributes.toArray(new Attribute[]{});
-       } catch (IOException e) {
-               System.err.println("IOException whilst processing parameter annotations");
-               e.printStackTrace();
+                       }
+               }
+               return str;
+       }
+
+       /**
+        * Shorten long class names, <em>java/lang/String</em> becomes <em>java.lang.String</em>, e.g.. If <em>chopit</em> is
+        * <em>true</em> the prefix <em>java.lang</em> is also removed.
+        * 
+        * @param str The long class name
+        * @param chopit Flag that determines whether chopping is executed or not
+        * @return Compacted class name
+        */
+       public static final String compactClassName(String str, boolean chopit) {
+               return compactClassName(str, "java.lang.", chopit);
+       }
+
+       public static final String methodSignatureToString(String signature, String name, String access) {
+               return methodSignatureToString(signature, name, access, true);
+       }
+
+       public static final String methodSignatureToString(String signature, String name, String access, boolean chopit) {
+               return methodSignatureToString(signature, name, access, chopit, null);
+       }
+
+       /**
+        * 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;
+               int var_index = (access.indexOf("static") >= 0) ? 0 : 1;
+
+               try { // Read all declarations between for `(' and `)'
+                       if (signature.charAt(0) != '(')
+                               throw new ClassFormatException("Invalid method signature: " + signature);
+
+                       index = 1; // current string position
+
+                       while (signature.charAt(index) != ')') {
+                               ResultHolder rh = signatureToStringInternal(signature.substring(index), chopit);
+                               String param_type = rh.getResult();
+                               buf.append(param_type);
+
+                               if (vars != null) {
+                                       LocalVariable l = vars.getLocalVariable(var_index);
+
+                                       if (l != null)
+                                               buf.append(" " + l.getName());
+                               } else
+                                       buf.append(" arg" + var_index);
+
+                               if ("double".equals(param_type) || "long".equals(param_type))
+                                       var_index += 2;
+                               else
+                                       var_index++;
+
+                               buf.append(", ");
+                               index += rh.getConsumedChars();
+                       }
+
+                       index++;
+
+                       // Read return type after `)'
+                       type = signatureToString(signature.substring(index), chopit);
+
+               } catch (StringIndexOutOfBoundsException e) { // Should never occur
+                       throw new ClassFormatException("Invalid method signature: " + signature);
+               }
+
+               if (buf.length() > 1) // Tack off the extra ", "
+                       buf.setLength(buf.length() - 2);
+
+               buf.append(")");
+
+               return access + ((access.length() > 0) ? " " : "") + // May be an empty string
+                               type + " " + name + buf.toString();
+       }
+
+       /**
+        * Replace all occurences of <em>old</em> in <em>str</em> with <em>new</em>.
+        * 
+        * @param str String to permute
+        * @param old String to be replaced
+        * @param new Replacement string
+        * @return new String object
+        */
+       public static final String replace(String str, String old, String new_) {
+               int index, old_index;
+               StringBuffer buf = new StringBuffer();
+
+               try {
+                       index = str.indexOf(old);
+                       if (index != -1) {
+                               old_index = 0;
+
+                               // While we have something to replace
+                               while ((index = str.indexOf(old, old_index)) != -1) {
+                                       buf.append(str.substring(old_index, index)); // append prefix
+                                       buf.append(new_); // append replacement
+                                       old_index = index + old.length(); // Skip 'old'.length chars
+                               }
+
+                               buf.append(str.substring(old_index)); // append rest of string
+                               str = buf.toString();
+                       }
+               } catch (StringIndexOutOfBoundsException e) {
+                       System.err.println(e);
+               }
+
+               return str;
+       }
+
+       /**
+        * Converts signature to string with all class names compacted.
+        * 
+        * @param signature to convert
+        * @return Human readable signature
+        */
+       public static final String signatureToString(String signature) {
+               return signatureToString(signature, true);
+       }
+
+       public static final String signatureToString(String signature, boolean chopit) {
+               ResultHolder rh = signatureToStringInternal(signature, chopit);
+               return rh.getResult();
+       }
+
+       /**
+        * 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
+               try {
+                       switch (signature.charAt(0)) {
+                       case 'B':
+                               return ResultHolder.BYTE;
+                       case 'C':
+                               return ResultHolder.CHAR;
+                       case 'D':
+                               return ResultHolder.DOUBLE;
+                       case 'F':
+                               return ResultHolder.FLOAT;
+                       case 'I':
+                               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) == '>')
+                                       index = index + 2;
+
+                               if (index < 0)
+                                       throw new ClassFormatException("Invalid signature: " + signature);
+
+                               int genericStart = signature.indexOf('<');
+                               int genericEnd = signature.indexOf('>');
+                               if (genericStart != -1) {
+                                       // FIXME asc going to need a lot more work in here for generics
+                                       ResultHolder rh = signatureToStringInternal(signature.substring(genericStart + 1, genericEnd), chopit);
+                                       ResultHolder retval = new ResultHolder(compactClassName(signature.substring(1, genericStart) + "<"
+                                                       + rh.getResult() + ">", chopit), genericEnd + 1);
+                                       return retval;
+                               } else {
+                                       processedChars = index + 1; // "Lblabla;" `L' and `;' are removed
+                                       ResultHolder retval = new ResultHolder(compactClassName(signature.substring(1, index), chopit), processedChars);
+                                       return retval;
+                               }
+                       }
+
+                       case 'S':
+                               return ResultHolder.SHORT;
+                       case 'Z':
+                               return ResultHolder.BOOLEAN;
+
+                       case '[': { // Array declaration
+                               StringBuffer brackets;
+                               int consumedChars, n;
+
+                               brackets = new StringBuffer(); // Accumulate []'s
+                               // Count opening brackets and look for optional size argument
+                               for (n = 0; signature.charAt(n) == '['; n++)
+                                       brackets.append("[]");
+                               consumedChars = n;
+                               // The rest of the string denotes a `<field_type>'
+                               ResultHolder restOfIt = signatureToStringInternal(signature.substring(n), chopit);
+
+                               // type = signatureToString(signature.substring(n), chopit);
+
+                               consumedChars += restOfIt.getConsumedChars();
+                               return new ResultHolder(restOfIt.getResult() + brackets.toString(), consumedChars);
+                       }
+
+                       case 'V':
+                               return ResultHolder.VOID;
+
+                       default:
+                               throw new ClassFormatException("Invalid signature: `" + signature + "'");
+                       }
+               } catch (StringIndexOutOfBoundsException e) { // Should never occur
+                       throw new ClassFormatException("Invalid signature: " + e + ":" + signature);
+               }
+       }
+
+       /**
+        * Return type of method signature as a byte value as defined in <em>Constants</em>
+        * 
+        * @param signature in format described above
+        * @return type of method signature
+        * @see Constants
+        */
+       public static final byte typeOfMethodSignature(String signature) throws ClassFormatException {
+               int index;
+
+               try {
+                       if (signature.charAt(0) != '(')
+                               throw new ClassFormatException("Invalid method signature: " + signature);
+                       index = signature.lastIndexOf(')') + 1;
+                       return typeOfSignature(signature.substring(index));
+               } catch (StringIndexOutOfBoundsException e) {
+                       throw new ClassFormatException("Invalid method signature: " + signature);
+               }
+       }
+
+       /**
+        * Convert (signed) byte to (unsigned) short value, i.e., all negative values become positive.
+        */
+       private static final short byteToShort(byte b) {
+               return (b < 0) ? (short) (256 + b) : (short) b;
+       }
+
+       /**
+        * Convert bytes into hexidecimal string
+        * 
+        * @return bytes as hexidecimal string, e.g. 00 FA 12 ...
+        */
+       public static final String toHexString(byte[] bytes) {
+               StringBuffer buf = new StringBuffer();
+
+               for (int i = 0; i < bytes.length; i++) {
+                       short b = byteToShort(bytes[i]);
+                       String hex = Integer.toString(b, 0x10);
+
+                       // Just one digit, so prepend 0
+                       if (b < 0x10)
+                               buf.append('0');
+
+                       buf.append(hex);
+
+                       if (i < bytes.length - 1)
+                               buf.append(' ');
+               }
+
+               return buf.toString();
+       }
+
+       /**
+        * Return a string for an integer justified left or right and filled up with 'fill' characters if necessary.
+        * 
+        * @param i integer to format
+        * @param length length of desired string
+        * @param left_justify format left or right
+        * @param fill fill character
+        * @return formatted int
+        */
+       public static final String format(int i, int length, boolean left_justify, char fill) {
+               return fillup(Integer.toString(i), length, left_justify, fill);
+       }
+
+       /**
+        * Fillup char with up to length characters with char `fill' and justify it left or right.
+        * 
+        * @param str string to format
+        * @param length length of desired string
+        * @param left_justify format left or right
+        * @param fill fill character
+        * @return formatted string
+        */
+       public static final String fillup(String str, int length, boolean left_justify, char fill) {
+               int len = length - str.length();
+               char[] buf = new char[(len < 0) ? 0 : len];
+
+               for (int j = 0; j < buf.length; j++)
+                       buf[j] = fill;
+
+               if (left_justify)
+                       return str + new String(buf);
+               else
+                       return new String(buf) + str;
+       }
+
+       /**
+        * Escape all occurences of newline chars '\n', quotes \", etc.
+        */
+       public static final String convertString(String label) {
+               char[] ch = label.toCharArray();
+               StringBuffer buf = new StringBuffer();
+
+               for (int i = 0; i < ch.length; i++) {
+                       switch (ch[i]) {
+                       case '\n':
+                               buf.append("\\n");
+                               break;
+                       case '\r':
+                               buf.append("\\r");
+                               break;
+                       case '\"':
+                               buf.append("\\\"");
+                               break;
+                       case '\'':
+                               buf.append("\\'");
+                               break;
+                       case '\\':
+                               buf.append("\\\\");
+                               break;
+                       default:
+                               buf.append(ch[i]);
+                               break;
+                       }
+               }
+
+               return buf.toString();
+       }
+
+       /**
+        * 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
+        */
+       public static Collection<RuntimeAnnotations> getAnnotationAttributes(ConstantPool cp, List<AnnotationGen> vec) {
+
+               if (vec.size() == 0)
+                       return null;
+
+               try {
+                       int countVisible = 0;
+                       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())
+                                       countVisible++;
+                               else
+                                       countInvisible++;
+                       }
+
+                       ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream();
+                       ByteArrayOutputStream riaBytes = new ByteArrayOutputStream();
+                       DataOutputStream rvaDos = new DataOutputStream(rvaBytes);
+                       DataOutputStream riaDos = new DataOutputStream(riaBytes);
+
+                       rvaDos.writeShort(countVisible);
+                       riaDos.writeShort(countInvisible);
+
+                       // put the annotations in the right output stream
+                       for (int i = 0; i < vec.size(); i++) {
+                               AnnotationGen a = vec.get(i);
+                               if (a.isRuntimeVisible())
+                                       a.dump(rvaDos);
+                               else
+                                       a.dump(riaDos);
+                       }
+
+                       rvaDos.close();
+                       riaDos.close();
+
+                       byte[] rvaData = rvaBytes.toByteArray();
+                       byte[] riaData = riaBytes.toByteArray();
+
+                       int rvaIndex = -1;
+                       int riaIndex = -1;
+
+                       if (rvaData.length > 2)
+                               rvaIndex = cp.addUtf8("RuntimeVisibleAnnotations");
+                       if (riaData.length > 2)
+                               riaIndex = cp.addUtf8("RuntimeInvisibleAnnotations");
+
+                       List<RuntimeAnnotations> newAttributes = new ArrayList<RuntimeAnnotations>();
+                       if (rvaData.length > 2) {
+                               newAttributes.add(new RuntimeVisibleAnnotations(rvaIndex, rvaData.length, rvaData, cp));
+                       }
+                       if (riaData.length > 2) {
+                               newAttributes.add(new RuntimeInvisibleAnnotations(riaIndex, riaData.length, riaData, cp));
+                       }
+
+                       return newAttributes;
+               } catch (IOException e) {
+                       System.err.println("IOException whilst processing annotations");
+                       e.printStackTrace();
+               }
+               return null;
+       }
+
+       /**
+        * Annotations against a class are stored in one of four attribute kinds: - RuntimeVisibleParameterAnnotations -
+        * RuntimeInvisibleParameterAnnotations
+        */
+       // OPTIMIZE looks heavyweight?
+       public static Attribute[] getParameterAnnotationAttributes(ConstantPool cp, List[] /*
+                                                                                                                                                                                * Array of lists, array size depends on
+                                                                                                                                                                                * #params
+                                                                                                                                                                                */vec) {
+
+               int visCount[] = new int[vec.length];
+               int totalVisCount = 0;
+               int invisCount[] = new int[vec.length];
+               int totalInvisCount = 0;
+               try {
+
+                       for (int i = 0; i < vec.length; i++) {
+                               List l = vec[i];
+                               if (l != null) {
+                                       for (Iterator iter = l.iterator(); iter.hasNext();) {
+                                               AnnotationGen element = (AnnotationGen) iter.next();
+                                               if (element.isRuntimeVisible()) {
+                                                       visCount[i]++;
+                                                       totalVisCount++;
+                                               } else {
+                                                       invisCount[i]++;
+                                                       totalInvisCount++;
+                                               }
+                                       }
+                               }
+                       }
+
+                       // Lets do the visible ones
+                       ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream();
+                       DataOutputStream rvaDos = new DataOutputStream(rvaBytes);
+                       rvaDos.writeByte(vec.length); // First goes number of parameters
+
+                       for (int i = 0; i < vec.length; i++) {
+                               rvaDos.writeShort(visCount[i]);
+                               if (visCount[i] > 0) {
+                                       List l = vec[i];
+                                       for (Iterator iter = l.iterator(); iter.hasNext();) {
+                                               AnnotationGen element = (AnnotationGen) iter.next();
+                                               if (element.isRuntimeVisible())
+                                                       element.dump(rvaDos);
+                                       }
+                               }
+                       }
+                       rvaDos.close();
+
+                       // Lets do the invisible ones
+                       ByteArrayOutputStream riaBytes = new ByteArrayOutputStream();
+                       DataOutputStream riaDos = new DataOutputStream(riaBytes);
+                       riaDos.writeByte(vec.length); // First goes number of parameters
+
+                       for (int i = 0; i < vec.length; i++) {
+                               riaDos.writeShort(invisCount[i]);
+                               if (invisCount[i] > 0) {
+                                       List l = vec[i];
+                                       for (Iterator iter = l.iterator(); iter.hasNext();) {
+                                               AnnotationGen element = (AnnotationGen) iter.next();
+                                               if (!element.isRuntimeVisible())
+                                                       element.dump(riaDos);
+                                       }
+                               }
+                       }
+                       riaDos.close();
+
+                       byte[] rvaData = rvaBytes.toByteArray();
+                       byte[] riaData = riaBytes.toByteArray();
+
+                       int rvaIndex = -1;
+                       int riaIndex = -1;
+
+                       if (totalVisCount > 0)
+                               rvaIndex = cp.addUtf8("RuntimeVisibleParameterAnnotations");
+                       if (totalInvisCount > 0)
+                               riaIndex = cp.addUtf8("RuntimeInvisibleParameterAnnotations");
+
+                       List<RuntimeParameterAnnotations> newAttributes = new ArrayList<RuntimeParameterAnnotations>();
+
+                       if (totalVisCount > 0) {
+                               newAttributes.add(new RuntimeVisibleParameterAnnotations(rvaIndex, rvaData.length, rvaData, cp));
+                       }
+
+                       if (totalInvisCount > 0) {
+                               newAttributes.add(new RuntimeInvisibleParameterAnnotations(riaIndex, riaData.length, riaData, cp));
+                       }
+
+                       return newAttributes.toArray(new Attribute[] {});
+               } catch (IOException e) {
+                       System.err.println("IOException whilst processing parameter annotations");
+                       e.printStackTrace();
+               }
+               return null;
+       }
+
+       public static class ResultHolder {
+               private String result;
+               private int consumed;
+
+               public static final ResultHolder BYTE = new ResultHolder("byte", 1);
+               public static final ResultHolder CHAR = new ResultHolder("char", 1);
+               public static final ResultHolder DOUBLE = new ResultHolder("double", 1);
+               public static final ResultHolder FLOAT = new ResultHolder("float", 1);
+               public static final ResultHolder INT = new ResultHolder("int", 1);
+               public static final ResultHolder LONG = new ResultHolder("long", 1);
+               public static final ResultHolder SHORT = new ResultHolder("short", 1);
+               public static final ResultHolder BOOLEAN = new ResultHolder("boolean", 1);
+               public static final ResultHolder VOID = new ResultHolder("void", 1);
+
+               public ResultHolder(String s, int c) {
+                       result = s;
+                       consumed = c;
+               }
+
+               public String getResult() {
+                       return result;
+               }
+
+               public int getConsumedChars() {
+                       return consumed;
+               }
+       }
+
+       /**
+        * Return type of signature as a byte value as defined in <em>Constants</em>
+        * 
+        * @param signature in format described above
+        * @return type of signature
+        * @see Constants
+        */
+       public static final byte typeOfSignature(String signature) throws ClassFormatException {
+               try {
+                       switch (signature.charAt(0)) {
+                       case 'B':
+                               return Constants.T_BYTE;
+                       case 'C':
+                               return Constants.T_CHAR;
+                       case 'D':
+                               return Constants.T_DOUBLE;
+                       case 'F':
+                               return Constants.T_FLOAT;
+                       case 'I':
+                               return Constants.T_INT;
+                       case 'J':
+                               return Constants.T_LONG;
+                       case 'L':
+                               return Constants.T_REFERENCE;
+                       case '[':
+                               return Constants.T_ARRAY;
+                       case 'V':
+                               return Constants.T_VOID;
+                       case 'Z':
+                               return Constants.T_BOOLEAN;
+                       case 'S':
+                               return Constants.T_SHORT;
+                       default:
+                               throw new ClassFormatException("Invalid method signature: " + signature);
+                       }
+               } catch (StringIndexOutOfBoundsException e) {
+                       throw new ClassFormatException("Invalid method signature: " + signature);
+               }
+       }
+
+       public static final byte typeOfSignature(char c) throws ClassFormatException {
+               switch (c) {
+               case 'B':
+                       return Constants.T_BYTE;
+               case 'C':
+                       return Constants.T_CHAR;
+               case 'D':
+                       return Constants.T_DOUBLE;
+               case 'F':
+                       return Constants.T_FLOAT;
+               case 'I':
+                       return Constants.T_INT;
+               case 'J':
+                       return Constants.T_LONG;
+               case 'L':
+                       return Constants.T_REFERENCE;
+               case '[':
+                       return Constants.T_ARRAY;
+               case 'V':
+                       return Constants.T_VOID;
+               case 'Z':
+                       return Constants.T_BOOLEAN;
+               case 'S':
+                       return Constants.T_SHORT;
+               default:
+                       throw new ClassFormatException("Invalid type of signature: " + c);
+               }
+       }
+
+       /**
+        * Disassemble a stream of byte codes and return the string representation.
+        * 
+        * @param bytes stream of bytes
+        * @param constant_pool Array of constants
+        * @param verbose be verbose, e.g. print constant pool index
+        * @return String representation of byte code
+        */
+       public static final String codeToString(ByteSequence bytes, ConstantPool constant_pool, boolean verbose) throws IOException {
+               short opcode = (short) bytes.readUnsignedByte();
+               int default_offset = 0, low, high, npairs;
+               int index, vindex, constant;
+               int[] match, jump_table;
+               int no_pad_bytes = 0, offset;
+               StringBuffer buf = new StringBuffer(Constants.OPCODE_NAMES[opcode]);
+
+               /*
+                * Special case: Skip (0-3) padding bytes, i.e., the following bytes are 4-byte-aligned
+                */
+               if ((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) {
+                       int remainder = bytes.getIndex() % 4;
+                       no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
+
+                       for (int i = 0; i < no_pad_bytes; i++) {
+                               byte b = bytes.readByte();
+                               if (b != 0)
+                                       System.err.println("Warning: Padding byte != 0 in " + Constants.OPCODE_NAMES[opcode] + ":" + b);
+                       }
+
+                       // Both cases have a field default_offset in common
+                       default_offset = bytes.readInt();
+               }
+
+               switch (opcode) {
+               /*
+                * Table switch has variable length arguments.
+                */
+               case Constants.TABLESWITCH:
+                       low = bytes.readInt();
+                       high = bytes.readInt();
+
+                       offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
+                       default_offset += offset;
+
+                       buf.append("\tdefault = " + default_offset + ", low = " + low + ", high = " + high + "(");
+
+                       jump_table = new int[high - low + 1];
+                       for (int i = 0; i < jump_table.length; i++) {
+                               jump_table[i] = offset + bytes.readInt();
+                               buf.append(jump_table[i]);
+                               if (i < jump_table.length - 1)
+                                       buf.append(", ");
+                       }
+                       buf.append(")");
+                       break;
+
+               /*
+                * Lookup switch has variable length arguments.
+                */
+               case Constants.LOOKUPSWITCH: {
+
+                       npairs = bytes.readInt();
+                       offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
+
+                       match = new int[npairs];
+                       jump_table = new int[npairs];
+                       default_offset += offset;
+
+                       buf.append("\tdefault = " + default_offset + ", npairs = " + npairs + " (");
+
+                       for (int i = 0; i < npairs; i++) {
+                               match[i] = bytes.readInt();
+                               jump_table[i] = offset + bytes.readInt();
+                               buf.append("(" + match[i] + ", " + jump_table[i] + ")");
+                               if (i < npairs - 1)
+                                       buf.append(", ");
+                       }
+                       buf.append(")");
+               }
+                       break;
+
+               // Two address bytes + offset from start of byte stream form the jump target
+               case Constants.GOTO:
+               case Constants.IFEQ:
+               case Constants.IFGE:
+               case Constants.IFGT:
+               case Constants.IFLE:
+               case Constants.IFLT:
+               case Constants.JSR:
+               case Constants.IFNE:
+               case Constants.IFNONNULL:
+               case Constants.IFNULL:
+               case Constants.IF_ACMPEQ:
+               case Constants.IF_ACMPNE:
+               case Constants.IF_ICMPEQ:
+               case Constants.IF_ICMPGE:
+               case Constants.IF_ICMPGT:
+               case Constants.IF_ICMPLE:
+               case Constants.IF_ICMPLT:
+               case Constants.IF_ICMPNE:
+                       buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readShort()));
+                       break;
+
+               // 32-bit wide jumps
+               case Constants.GOTO_W:
+               case Constants.JSR_W:
+                       buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readInt()));
+                       break;
+
+               // Index byte references local variable (register)
+               case Constants.ALOAD:
+               case Constants.ASTORE:
+               case Constants.DLOAD:
+               case Constants.DSTORE:
+               case Constants.FLOAD:
+               case Constants.FSTORE:
+               case Constants.ILOAD:
+               case Constants.ISTORE:
+               case Constants.LLOAD:
+               case Constants.LSTORE:
+               case Constants.RET:
+                       if (wide) {
+                               vindex = bytes.readUnsignedShort();
+                               wide = false; // Clear flag
+                       } else
+                               vindex = bytes.readUnsignedByte();
+                       buf.append("\t\t%" + vindex);
+                       break;
+
+               /*
+                * Remember wide byte which is used to form a 16-bit address in the following instruction. Relies on that the method is
+                * called again with the following opcode.
+                */
+               case Constants.WIDE:
+                       wide = true;
+                       buf.append("\t(wide)");
+                       break;
+
+               // Array of basic type
+               case Constants.NEWARRAY:
+                       buf.append("\t\t<" + Constants.TYPE_NAMES[bytes.readByte()] + ">");
+                       break;
+
+               // Access object/class fields
+               case Constants.GETFIELD:
+               case Constants.GETSTATIC:
+               case Constants.PUTFIELD:
+               case Constants.PUTSTATIC:
+                       index = bytes.readUnsignedShort();
+                       buf.append("\t\t" + constant_pool.constantToString(index, Constants.CONSTANT_Fieldref)
+                                       + (verbose ? " (" + index + ")" : ""));
+                       break;
+
+               // Operands are references to classes in constant pool
+               case Constants.NEW:
+               case Constants.CHECKCAST:
+                       buf.append("\t");
+               case Constants.INSTANCEOF:
+                       index = bytes.readUnsignedShort();
+                       buf.append("\t<" + constant_pool.constantToString(index, Constants.CONSTANT_Class) + ">"
+                                       + (verbose ? " (" + index + ")" : ""));
+                       break;
+
+               // Operands are references to methods in constant pool
+               case Constants.INVOKESPECIAL:
+               case Constants.INVOKESTATIC:
+               case Constants.INVOKEVIRTUAL:
+                       index = bytes.readUnsignedShort();
+                       buf.append("\t" + constant_pool.constantToString(index, Constants.CONSTANT_Methodref)
+                                       + (verbose ? " (" + index + ")" : ""));
+                       break;
+
+               case Constants.INVOKEINTERFACE:
+                       index = bytes.readUnsignedShort();
+                       int nargs = bytes.readUnsignedByte(); // historical, redundant
+                       buf.append("\t" + constant_pool.constantToString(index, Constants.CONSTANT_InterfaceMethodref)
+                                       + (verbose ? " (" + index + ")\t" : "") + nargs + "\t" + bytes.readUnsignedByte()); // Last byte is a reserved
+                       // space
+                       break;
+
+               // Operands are references to items in constant pool
+               case Constants.LDC_W:
+               case Constants.LDC2_W:
+                       index = bytes.readUnsignedShort();
+                       buf.append("\t\t" + constant_pool.constantToString(index, constant_pool.getConstant(index).getTag())
+                                       + (verbose ? " (" + index + ")" : ""));
+                       break;
+
+               case Constants.LDC:
+                       index = bytes.readUnsignedByte();
+                       buf.append("\t\t" + constant_pool.constantToString(index, constant_pool.getConstant(index).getTag())
+                                       + (verbose ? " (" + index + ")" : ""));
+                       break;
+
+               // Array of references
+               case Constants.ANEWARRAY:
+                       index = bytes.readUnsignedShort();
+                       buf.append("\t\t<" + compactClassName(constant_pool.getConstantString(index, Constants.CONSTANT_Class), false) + ">"
+                                       + (verbose ? " (" + index + ")" : ""));
+                       break;
+
+               // Multidimensional array of references
+               case Constants.MULTIANEWARRAY: {
+                       index = bytes.readUnsignedShort();
+                       int dimensions = bytes.readUnsignedByte();
+
+                       buf.append("\t<" + compactClassName(constant_pool.getConstantString(index, Constants.CONSTANT_Class), false) + ">\t"
+                                       + dimensions + (verbose ? " (" + index + ")" : ""));
+               }
+                       break;
+
+               // Increment local variable
+               case Constants.IINC:
+                       if (wide) {
+                               vindex = bytes.readUnsignedShort();
+                               constant = bytes.readShort();
+                               wide = false;
+                       } else {
+                               vindex = bytes.readUnsignedByte();
+                               constant = bytes.readByte();
+                       }
+                       buf.append("\t\t%" + vindex + "\t" + constant);
+                       break;
+
+               default:
+                       if ((Constants.iLen[opcode] - 1) > 0) {
+                               for (int i = 0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) {
+                                       buf.append("\t\t");
+                                       switch (Constants.TYPE_OF_OPERANDS[opcode][i]) {
+                                       case Constants.T_BYTE:
+                                               buf.append(bytes.readByte());
+                                               break;
+                                       case Constants.T_SHORT:
+                                               buf.append(bytes.readShort());
+                                               break;
+                                       case Constants.T_INT:
+                                               buf.append(bytes.readInt());
+                                               break;
+
+                                       default: // Never reached
+                                               System.err.println("Unreachable default case reached!");
+                                               System.exit(-1);
+                                       }
+                               }
+                       }
+               }
+               return buf.toString();
+       }
+
+       // private helpers
+       private static final int pow2(int n) {
+               return 1 << n;
        }
-       return null;
-  }
-  
-  public static class ResultHolder {
-       private String result;
-       private int consumed;
-       
-       public static final ResultHolder BYTE     = new ResultHolder("byte",1);
-       public static final ResultHolder CHAR     = new ResultHolder("char",1);
-       public static final ResultHolder DOUBLE   = new ResultHolder("double",1);
-       public static final ResultHolder FLOAT    = new ResultHolder("float",1);
-       public static final ResultHolder INT      = new ResultHolder("int",1);
-       public static final ResultHolder LONG     = new ResultHolder("long",1);
-       public static final ResultHolder SHORT    = new ResultHolder("short",1);
-       public static final ResultHolder BOOLEAN  = new ResultHolder("boolean",1);
-       public static final ResultHolder VOID     = new ResultHolder("void",1);
-       
-       public ResultHolder(String s,int c) {
-               result = s;
-               consumed = c;
-       }
-       
-       public String getResult() { return result;}
-       public int getConsumedChars() { return consumed; }
-  }
-
-  
-  /**
-   * Return type of signature as a byte value as defined in <em>Constants</em>
-   *
-   * @param  signature in format described above
-   * @return type of signature
-   * @see    Constants
-   */
-  public static final byte typeOfSignature(String signature) throws ClassFormatException {
-    try {
-      switch(signature.charAt(0)) {
-          case 'B' : return Constants.T_BYTE;
-          case 'C' : return Constants.T_CHAR;
-          case 'D' : return Constants.T_DOUBLE;
-             case 'F' : return Constants.T_FLOAT;
-             case 'I' : return Constants.T_INT;
-             case 'J' : return Constants.T_LONG;
-             case 'L' : return Constants.T_REFERENCE;
-             case '[' : return Constants.T_ARRAY;
-             case 'V' : return Constants.T_VOID;
-             case 'Z' : return Constants.T_BOOLEAN;
-             case 'S' : return Constants.T_SHORT;
-          default:  
-               throw new ClassFormatException("Invalid method signature: " + signature);
-      }
-    } catch(StringIndexOutOfBoundsException e) {
-      throw new ClassFormatException("Invalid method signature: " + signature);
-    }
-  }
-  
-  public static final byte typeOfSignature(char c) throws ClassFormatException {
-      switch(c) {
-          case 'B' : return Constants.T_BYTE;
-          case 'C' : return Constants.T_CHAR;
-          case 'D' : return Constants.T_DOUBLE;
-             case 'F' : return Constants.T_FLOAT;
-             case 'I' : return Constants.T_INT;
-             case 'J' : return Constants.T_LONG;
-             case 'L' : return Constants.T_REFERENCE;
-             case '[' : return Constants.T_ARRAY;
-             case 'V' : return Constants.T_VOID;
-             case 'Z' : return Constants.T_BOOLEAN;
-             case 'S' : return Constants.T_SHORT;
-          default:  
-               throw new ClassFormatException("Invalid type of signature: " + c);
-      }
-  }
-  
-  /**
-   * Disassemble a stream of byte codes and return the string representation.
-   *
-   * @param  bytes stream of bytes
-   * @param  constant_pool Array of constants
-   * @param  verbose be verbose, e.g. print constant pool index
-   * @return String representation of byte code
-   */
-  public static final String codeToString(ByteSequence bytes,
-                                         ConstantPool constant_pool, boolean verbose) throws IOException {
-    short        opcode = (short)bytes.readUnsignedByte();
-    int          default_offset=0, low, high, npairs;
-    int          index, vindex, constant;
-    int[]        match, jump_table;
-    int          no_pad_bytes=0, offset;
-    StringBuffer buf = new StringBuffer(Constants.OPCODE_NAMES[opcode]);
-
-    /* Special case: Skip (0-3) padding bytes, i.e., the
-     * following bytes are 4-byte-aligned
-     */
-    if ((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) {
-      int remainder = bytes.getIndex() % 4;
-      no_pad_bytes  = (remainder == 0)? 0 : 4 - remainder;
-
-      for (int i=0; i < no_pad_bytes; i++) {
-           byte b = bytes.readByte();
-           if (b != 0)
-              System.err.println("Warning: Padding byte != 0 in " + Constants.OPCODE_NAMES[opcode] + ":" + b);
-      }
-
-      // Both cases have a field default_offset in common
-      default_offset = bytes.readInt();
-    }
-
-    switch(opcode) {
-      /* Table switch has variable length arguments.
-       */
-      case Constants.TABLESWITCH:
-        low  = bytes.readInt();
-        high = bytes.readInt();
-
-        offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
-        default_offset += offset;
-
-        buf.append("\tdefault = " + default_offset + ", low = " + low + 
-                  ", high = " + high + "(");
-
-        jump_table = new int[high - low + 1];
-        for (int i=0; i < jump_table.length; i++) {
-             jump_table[i] = offset + bytes.readInt();
-             buf.append(jump_table[i]);
-             if (i < jump_table.length - 1) buf.append(", ");
-        }
-        buf.append(")");
-        break;
-
-      /* Lookup switch has variable length arguments.
-       */
-      case Constants.LOOKUPSWITCH: {
-
-        npairs = bytes.readInt();
-        offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
-         
-        match      = new int[npairs];
-        jump_table = new int[npairs];
-        default_offset += offset;
-
-        buf.append("\tdefault = " + default_offset + ", npairs = " + npairs + " (");
-
-        for (int i=0; i < npairs; i++) {
-             match[i]      = bytes.readInt();
-             jump_table[i] = offset + bytes.readInt();
-             buf.append("(" + match[i] + ", " + jump_table[i] + ")");
-             if(i < npairs - 1) buf.append(", ");
-        }
-        buf.append(")");
-      }
-      break;
-
-      // Two address bytes + offset from start of byte stream form the jump target
-      case Constants.GOTO:      case Constants.IFEQ:      case Constants.IFGE:      case Constants.IFGT:
-      case Constants.IFLE:      case Constants.IFLT:      case Constants.JSR: case Constants.IFNE:
-      case Constants.IFNONNULL: case Constants.IFNULL:    case Constants.IF_ACMPEQ:
-      case Constants.IF_ACMPNE: case Constants.IF_ICMPEQ: case Constants.IF_ICMPGE: case Constants.IF_ICMPGT:
-      case Constants.IF_ICMPLE: case Constants.IF_ICMPLT: case Constants.IF_ICMPNE:
-        buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readShort()));
-        break;
-         
-      // 32-bit wide jumps
-      case Constants.GOTO_W: case Constants.JSR_W:
-        buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readInt()));
-        break;
-
-      // Index byte references local variable (register)
-      case Constants.ALOAD:  case Constants.ASTORE: case Constants.DLOAD:  case Constants.DSTORE: case Constants.FLOAD:
-      case Constants.FSTORE: case Constants.ILOAD:  case Constants.ISTORE: case Constants.LLOAD:  case Constants.LSTORE:
-      case Constants.RET: 
-        if (wide) {
-             vindex = bytes.readUnsignedShort();
-             wide=false; // Clear flag
-        } else
-             vindex = bytes.readUnsignedByte();
-        buf.append("\t\t%" + vindex);
-        break;
-
-      /*
-       * Remember wide byte which is used to form a 16-bit address in the
-       * following instruction. Relies on that the method is called again with
-       * the following opcode.
-       */
-      case Constants.WIDE: wide=true; buf.append("\t(wide)"); break;
-
-      // Array of basic type
-      case Constants.NEWARRAY: buf.append("\t\t<" + Constants.TYPE_NAMES[bytes.readByte()] + ">"); break;
-
-      // Access object/class fields
-      case Constants.GETFIELD: case Constants.GETSTATIC: case Constants.PUTFIELD: case Constants.PUTSTATIC:
-        index = bytes.readUnsignedShort();
-        buf.append("\t\t" +
-                 constant_pool.constantToString(index, Constants.CONSTANT_Fieldref) +
-                 (verbose? " (" + index + ")" : ""));
-        break;
-         
-      // Operands are references to classes in constant pool
-      case Constants.NEW:
-      case Constants.CHECKCAST:
-        buf.append("\t");
-      case Constants.INSTANCEOF:
-        index = bytes.readUnsignedShort();
-        buf.append("\t<" + constant_pool.constantToString(index,Constants.CONSTANT_Class) +
-                 ">" + (verbose? " (" + index + ")" : ""));
-        break;
-
-      // Operands are references to methods in constant pool
-      case Constants.INVOKESPECIAL: case Constants.INVOKESTATIC: case Constants.INVOKEVIRTUAL:
-        index = bytes.readUnsignedShort();
-        buf.append("\t" + constant_pool.constantToString(index,Constants.CONSTANT_Methodref) +
-                 (verbose? " (" + index + ")" : ""));
-        break;
-
-      case Constants.INVOKEINTERFACE:
-        index = bytes.readUnsignedShort();
-        int nargs = bytes.readUnsignedByte(); // historical, redundant
-        buf.append("\t" + 
-                 constant_pool.constantToString(index,Constants.CONSTANT_InterfaceMethodref) +
-                 (verbose? " (" + index + ")\t" : "") + nargs + "\t" + 
-                 bytes.readUnsignedByte()); // Last byte is a reserved space
-        break;
-       
-      // Operands are references to items in constant pool
-      case Constants.LDC_W: case Constants.LDC2_W:
-        index = bytes.readUnsignedShort();
-        buf.append("\t\t" + constant_pool.constantToString
-                 (index, constant_pool.getConstant(index).getTag()) +
-                 (verbose? " (" + index + ")" : ""));
-        break;
-
-      case Constants.LDC:
-        index = bytes.readUnsignedByte();
-        buf.append("\t\t" + 
-                 constant_pool.constantToString
-                 (index, constant_pool.getConstant(index).getTag()) +
-                 (verbose? " (" + index + ")" : ""));
-        break;
-       
-      // Array of references
-      case Constants.ANEWARRAY:
-        index = bytes.readUnsignedShort();
-        buf.append("\t\t<" + compactClassName(constant_pool.getConstantString
-             (index, Constants.CONSTANT_Class), false) +
-                 ">" + (verbose? " (" + index + ")": ""));
-        break;
-       
-      // Multidimensional array of references
-      case Constants.MULTIANEWARRAY: {
-        index          = bytes.readUnsignedShort();
-        int dimensions = bytes.readUnsignedByte();
-
-        buf.append("\t<" + compactClassName(constant_pool.getConstantString
-                 (index, Constants.CONSTANT_Class), false) +
-                 ">\t" + dimensions + (verbose? " (" + index + ")" : ""));
-        }
-        break;
-
-      // Increment local variable
-      case Constants.IINC:
-        if (wide) {
-             vindex   = bytes.readUnsignedShort();
-             constant = bytes.readShort();
-             wide     = false;
-        } else {
-             vindex   = bytes.readUnsignedByte();
-             constant = bytes.readByte();
-        }
-        buf.append("\t\t%" + vindex + "\t" + constant);
-        break;
-
-      default:
-        if ((Constants.iLen[opcode]-1) > 0) {
-           for (int i=0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) {
-             buf.append("\t\t");
-             switch(Constants.TYPE_OF_OPERANDS[opcode][i]) {
-               case Constants.T_BYTE:  buf.append(bytes.readByte()); break;
-               case Constants.T_SHORT: buf.append(bytes.readShort());       break;
-               case Constants.T_INT:   buf.append(bytes.readInt());         break;
-                                             
-               default: // Never reached
-                 System.err.println("Unreachable default case reached!");
-                 System.exit(-1);
-             }
-           }
-      }
-    }
-    return buf.toString();
-  }
-  
-  // private helpers
-  private static final int pow2(int n) {
-    return 1 << n;
-  }
 }
index 03ed2d91027c131897c68397c88f1fd0c1fc5bca..1fcd4d53e1214fc372bd94731695ec1d5f51fc36 100644 (file)
@@ -60,641 +60,696 @@ import java.lang.reflect.Modifier;
 import java.security.MessageDigest;
 import java.util.ArrayList;
 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.FieldOrMethod;
-import org.aspectj.apache.bcel.classfile.Modifiers;
 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;
 import org.aspectj.apache.bcel.classfile.SourceFile;
 import org.aspectj.apache.bcel.classfile.Utility;
 import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
 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 (file).
+ * 
  * @see JavaClass
- * @version $Id: ClassGen.java,v 1.11 2009/09/09 19:56:20 aclement Exp $
- * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
- *
- * Upgraded, Andy Clement 9th Mar 06 - calculates SUID
+ * @version $Id: ClassGen.java,v 1.12 2009/09/09 22:18:20 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 ArrayList<Field>   field_vec     = new ArrayList<Field>();
-  private ArrayList<Method>   method_vec    = new ArrayList<Method>();
-  private ArrayList<Attribute>   attributesList = new ArrayList<Attribute>();
-  private ArrayList<String>   interface_vec = new ArrayList<String>();
-  private ArrayList<AnnotationGen>   annotation_vec= 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));
-    }
-
-    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]);
-    }
-  }
-
-  /** 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());
-  }
-
-  /**
-   * 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();
-    modifiers             = clazz.getModifiers();
-    cp                    = 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++)
-      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*/<AnnotationGen> annotationGenObjs = new ArrayList<AnnotationGen>();
-       for (int i = 0; i < attrs.length; i++) {
-               Attribute attr = attrs[i];
-               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));
+       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 List<Attribute> attributesList = new ArrayList<Attribute>();
+       private List<String> interface_vec = 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));
+               }
+
+               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]);
+               }
+       }
+
+       /**
+        * 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());
+       }
+
+       /**
+        * 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();
+               modifiers = clazz.getModifiers();
+               cp = 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++)
+                       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]);
                        }
-               } 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 (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 */<AnnotationGen> annotationGenObjs = new ArrayList<AnnotationGen>();
+               for (int i = 0; i < attrs.length; i++) {
+                       Attribute attr = attrs[i];
+                       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));
+                               }
+                       } 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));
+                               }
                        }
                }
+               return annotationGenObjs.toArray(new AnnotationGen[] {});
        }
-       return annotationGenObjs.toArray(new AnnotationGen[]{});
-  }
-
-  /**
-   * @return the (finally) built up Java class object.
-   */
-  public JavaClass getJavaClass() {
-    int[]        interfaces = getInterfaces();
-    Field[]      fields     = getFields();
-    Method[]     methods    = getMethods();
-    
-    // OPTIMIZE sort out this mangling of arrays and collections
-    Attribute[] attributes = null;
-    if (annotation_vec.size()==0) {
-       attributes = getAttributes();
-    } else {
-       // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations'
-        Attribute[] annAttributes  = Utility.getAnnotationAttributes(cp,annotation_vec);
-        attributes = new Attribute[attributesList.size()+annAttributes.length];
-        attributesList.toArray(attributes);
-        System.arraycopy(annAttributes,0,attributes,attributesList.size(),annAttributes.length);
-    }
-
-    // Must be last since the above calls may still add something to it
-    ConstantPool cp         = this.cp.getFinalConstantPool();
-    
-    return new JavaClass(class_name_index, superclass_name_index,
-                        file_name, major, minor, modifiers,
-                        cp, interfaces, fields, methods, attributes);
-  }
-
-  /**
-   * 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);
-  }
-
-  /**
-   * Remove an interface from this class.
-   * @param name interface to remove (fully qualified name)
-   */
-  public void removeInterface(String name) {
-    interface_vec.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); }
-
-  public void addAnnotation(AnnotationGen a) { annotation_vec.add(a); }
-  /**
-   * Add a method to this class.
-   * @param m method to add
-   */
-  public void addMethod(Method m)          { method_vec.add(m); }
-
-  /**
-   * Convenience method.
-   *
-   * Add an empty constructor to this class that does nothing but calling super().
-   * @param access rights for constructor
-   */
-  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(InstructionConstants.RETURN);
-
-    MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null,
-                      "<init>", class_name, il, cp);
-    mg.setMaxStack(1);
-    mg.setMaxLocals();
-    addMethod(mg.getMethod());
-  }
-
-  /**
-   * Add a field to this class.
-   * @param f field to add
-   */
-  public void addField(Field f)            { field_vec.add(f); }
-
-  public boolean containsField(Field f)    { return field_vec.contains(f); }
-  
-  /** @return field object with given name, or null
-   */
-  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;
-    }
-
-    return null;
-  }
-
-  /** @return method object with given name and signature, or null
-   */
-  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;
-    }
-
-    return null;
-  }
-
-  /**
-   * Remove an attribute from this class.
-   * @param a attribute to remove
-   */
-  public void removeAttribute(Attribute a) { attributesList.remove(a); }
-  public void removeAnnotation(AnnotationGen a) {annotation_vec.remove(a);}
-
-  /**
-   * Remove a method from this class.
-   * @param m method to remove
-   */
-  public void removeMethod(Method m)       { method_vec.remove(m); }
-
-  /** Replace given method with new one. If the old one does not exist
-   * add the new_ method to the class anyway.
-   */
-  public void replaceMethod(Method old, Method new_) {
-    if(new_ == null)
-      throw new ClassGenException("Replacement method must not be null");
-
-    int i = method_vec.indexOf(old);
-
-    if (i < 0)
-      method_vec.add(new_);
-    else
-      method_vec.set(i, new_);
-  }
-
-  /** Replace given field with new one. If the old one does not exist
-   * add the new_ field to the class anyway.
-   */
-  public void replaceField(Field old, Field new_) {
-    if(new_ == null)
-      throw new ClassGenException("Replacement method must not be null");
-
-    int i = field_vec.indexOf(old);
-
-    if(i < 0)
-      field_vec.add(new_);
-    else
-      field_vec.set(i, new_);
-  }
-
-  /**
-   * Remove a field to this class.
-   * @param f field to remove
-   */
-  public void removeField(Field f)         { field_vec.remove(f); }
-
-  public String getClassName()      { return class_name; }
-  public String getSuperclassName() { return super_class_name; }
-  public String getFileName()       { return file_name; }
-
-  public void setClassName(String name) {
-    class_name = name.replace('/', '.');
-    class_name_index = cp.addClass(name);
-  }
-
-  public void setSuperclassName(String name) {
-    super_class_name = name.replace('/', '.');
-    superclass_name_index = cp.addClass(name);
-  }
-
-  public Method[] getMethods() {
-    Method[] methods = new Method[method_vec.size()];
-    method_vec.toArray(methods);
-    return methods;
-  }
-
-  public void setMethods(Method[] methods) {
-    method_vec.clear();
-    for(int m=0; m<methods.length; m++)
-      addMethod(methods[m]);
-  }
-
-  public void setFields(Field[] fs) {
-    field_vec.clear();
-    for(int m=0; m<fs.length; m++)
-      addField(fs[m]);
-  }
-
-  public void setMethodAt(Method method, int pos) {
-    method_vec.set(pos, method);
-  }
-
-  public Method getMethodAt(int pos) {
-    return method_vec.get(pos);
-  }
-
-  public String[] getInterfaceNames() {
-    int      size = interface_vec.size();
-    String[] interfaces = new String[size];
-
-    interface_vec.toArray(interfaces);
-    return interfaces;
-  }
-
-  public int[] getInterfaces() {
-    int   size = interface_vec.size();
-    int[] interfaces = new int[size];
-
-    for(int i=0; i < size; i++)
-      interfaces[i] = cp.addClass(interface_vec.get(i));
-
-    return interfaces;
-  }
-
-  public Field[] getFields() {
-    Field[] fields = new Field[field_vec.size()];
-    field_vec.toArray(fields);
-    return fields;
-  }
-
-  public Attribute[] getAttributes() {
-    Attribute[] attributes = new Attribute[attributesList.size()];
-    attributesList.toArray(attributes);
-    return attributes;
-  }
-  
-  // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here?
-  public AnnotationGen[] getAnnotations() {
-       AnnotationGen[] annotations = new AnnotationGen[annotation_vec.size()];
-       annotation_vec.toArray(annotations);
-       return annotations;
-  }
-  
-  public ConstantPool getConstantPool() { return cp; }
-  public void setConstantPool(ConstantPool constant_pool) {
-    cp = 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('/', '.');
-  }
-
-  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('/', '.');
-  }
-
-  public int getSuperclassNameIndex() { return superclass_name_index; }    
-
-  public int getClassNameIndex()   { return class_name_index; }
-
-  public Object clone() {
-    try {
-      return super.clone();
-    } catch(CloneNotSupportedException e) {
-      System.err.println(e);
-      return null;
-    }
-  }
-
-  // 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;
-  }
-  
-  /**
-   * Calculate the SerialVersionUID for a class.
-   */  
-  public long getSUID() {
-       try {
-        Field[] fields   = getFields();
-        Method[] methods = getMethods();
-        
-       ByteArrayOutputStream baos = new ByteArrayOutputStream();
-       DataOutputStream dos = new DataOutputStream(baos);
-       
-       // 1. classname
-       dos.writeUTF(getClassName());
-       
-       // 2. classmodifiers: ACC_PUBLIC, ACC_FINAL, ACC_INTERFACE, and ACC_ABSTRACT
-       int classmods = 0; 
-       classmods|=(isPublic()?Constants.ACC_PUBLIC:0); 
-       classmods|=(isFinal()?Constants.ACC_FINAL:0);
-       classmods|=(isInterface()?Constants.ACC_INTERFACE:0);
-       
-       if (isAbstract()) {
-               // if an interface then abstract is only set if it has methods
-               if (isInterface()) {
-                       if (methods.length>0) classmods|=Constants.ACC_ABSTRACT;
-               } else {
-                       classmods|=Constants.ACC_ABSTRACT;
-               }
-       }
-       
-       dos.writeInt(classmods);
-       
-       // 3. ordered list of interfaces
-       List<FieldOrMethod> list = new ArrayList<FieldOrMethod>();
-        String[] names = getInterfaceNames();
-        if (names!=null) {
-               Arrays.sort(names);
-               for (int i = 0; i < names.length; i++) dos.writeUTF(names[i]);
-        }
-    
-        // 4. ordered list of fields (ignoring private static and private transient fields):
-        //  (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);
+
+       /**
+        * @return the (finally) built up Java class object.
+        */
+       public JavaClass getJavaClass() {
+               int[] interfaces = getInterfaces();
+               Field[] fields = getFields();
+               Method[] methods = getMethods();
+
+               Collection<Attribute> attributes = null;
+               if (annotationsList.size() == 0) {
+                       attributes = attributesList;
+               } else {
+                       // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations'
+                       attributes = new ArrayList<Attribute>();
+                       attributes.addAll(Utility.getAnnotationAttributes(cp, annotationsList));
+                       attributes.addAll(attributesList);
                }
-        Collections.sort(list,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();
-                       dos.writeUTF(f.getName());
-               dos.writeInt(relevantFlags&f.getModifiers());
-               dos.writeUTF(f.getType().getSignature());
+
+               // Must be last since the above calls may still add something to it
+               ConstantPool cp = this.cp.getFinalConstantPool();
+
+               return new JavaClass(class_name_index, superclass_name_index, file_name, 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);
+       }
+
+       /**
+        * Remove an interface from this class.
+        * 
+        * @param name interface to remove (fully qualified name)
+        */
+       public void removeInterface(String name) {
+               interface_vec.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);
+       }
+
+       public void addAnnotation(AnnotationGen a) {
+               annotationsList.add(a);
+       }
+
+       /**
+        * Add a method to this class.
+        * 
+        * @param m method to add
+        */
+       public void addMethod(Method m) {
+               method_vec.add(m);
+       }
+
+       /**
+        * Convenience method.
+        * 
+        * Add an empty constructor to this class that does nothing but calling super().
+        * 
+        * @param access rights for constructor
+        */
+       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(InstructionConstants.RETURN);
+
+               MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>", class_name, il, cp);
+               mg.setMaxStack(1);
+               mg.setMaxLocals();
+               addMethod(mg.getMethod());
+       }
+
+       /**
+        * Add a field to this class.
+        * 
+        * @param f field to add
+        */
+       public void addField(Field f) {
+               field_vec.add(f);
+       }
+
+       public boolean containsField(Field f) {
+               return field_vec.contains(f);
+       }
+
+       /**
+        * @return field object with given name, or null
+        */
+       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;
                }
 
-        // 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>();
-        boolean hasClinit = false;
-        for (int i = 0; i < methods.length; i++) {
-               Method m = methods[i];
-               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);
-               } else {
-                   if (!m.isPrivate()) list.add(m);
-               }
+               return null;
+       }
+
+       /**
+        * @return method object with given name and signature, or null
+        */
+       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;
                }
-        Collections.sort(ctors, new ConstructorComparator());
-        Collections.sort(list, new MethodComparator());
-        
-        
-               //      5. If a class initializer exists, write out the following:
-               //            1. The name of the method, <clinit>.
-               //            2. The modifier of the method, java.lang.reflect.Modifier.STATIC, written as a 32-bit integer.
-               //            3. The descriptor of the method, ()V. 
-        if (hasClinit) {
-               dos.writeUTF("<clinit>");
-               dos.writeInt(Modifier.STATIC);
-               dos.writeUTF("()V");
-        }
-        
-        // for methods and constructors: 
-        //               ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, 
-        //               ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT
-        relevantFlags =        
-               Constants.ACC_PUBLIC | Constants.ACC_PRIVATE | Constants.ACC_PROTECTED |
-               Constants.ACC_STATIC | Constants.ACC_FINAL | Constants.ACC_SYNCHRONIZED | 
-               Constants.ACC_NATIVE | Constants.ACC_ABSTRACT | 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('/','.'));
+
+               return null;
+       }
+
+       /**
+        * Remove an attribute from this class.
+        * 
+        * @param a attribute to remove
+        */
+       public void removeAttribute(Attribute a) {
+               attributesList.remove(a);
+       }
+
+       public void removeAnnotation(AnnotationGen a) {
+               annotationsList.remove(a);
+       }
+
+       /**
+        * Remove a method from this class.
+        * 
+        * @param m method to remove
+        */
+       public void removeMethod(Method m) {
+               method_vec.remove(m);
+       }
+
+       /**
+        * Replace given method with new one. If the old one does not exist add the new_ method to the class anyway.
+        */
+       public void replaceMethod(Method old, Method new_) {
+               if (new_ == null)
+                       throw new ClassGenException("Replacement method must not be null");
+
+               int i = method_vec.indexOf(old);
+
+               if (i < 0)
+                       method_vec.add(new_);
+               else
+                       method_vec.set(i, new_);
+       }
+
+       /**
+        * Replace given field with new one. If the old one does not exist add the new_ field to the class anyway.
+        */
+       public void replaceField(Field old, Field new_) {
+               if (new_ == null)
+                       throw new ClassGenException("Replacement method must not be null");
+
+               int i = field_vec.indexOf(old);
+
+               if (i < 0)
+                       field_vec.add(new_);
+               else
+                       field_vec.set(i, new_);
+       }
+
+       /**
+        * Remove a field to this class.
+        * 
+        * @param f field to remove
+        */
+       public void removeField(Field f) {
+               field_vec.remove(f);
+       }
+
+       public String getClassName() {
+               return class_name;
+       }
+
+       public String getSuperclassName() {
+               return super_class_name;
+       }
+
+       public String getFileName() {
+               return file_name;
+       }
+
+       public void setClassName(String name) {
+               class_name = name.replace('/', '.');
+               class_name_index = cp.addClass(name);
+       }
+
+       public void setSuperclassName(String name) {
+               super_class_name = name.replace('/', '.');
+               superclass_name_index = cp.addClass(name);
+       }
+
+       public Method[] getMethods() {
+               Method[] methods = new Method[method_vec.size()];
+               method_vec.toArray(methods);
+               return methods;
+       }
+
+       public void setMethods(Method[] methods) {
+               method_vec.clear();
+               for (int m = 0; m < methods.length; m++)
+                       addMethod(methods[m]);
+       }
+
+       public void setFields(Field[] fs) {
+               field_vec.clear();
+               for (int m = 0; m < fs.length; m++)
+                       addField(fs[m]);
+       }
+
+       public void setMethodAt(Method method, int pos) {
+               method_vec.set(pos, method);
+       }
+
+       public Method getMethodAt(int pos) {
+               return method_vec.get(pos);
+       }
+
+       public String[] getInterfaceNames() {
+               int size = interface_vec.size();
+               String[] interfaces = new String[size];
+
+               interface_vec.toArray(interfaces);
+               return interfaces;
+       }
+
+       public int[] getInterfaces() {
+               int size = interface_vec.size();
+               int[] interfaces = new int[size];
+
+               for (int i = 0; i < size; i++)
+                       interfaces[i] = cp.addClass(interface_vec.get(i));
+
+               return interfaces;
+       }
+
+       public Field[] getFields() {
+               Field[] fields = new Field[field_vec.size()];
+               field_vec.toArray(fields);
+               return fields;
+       }
+
+       public Collection<Attribute> getAttributes() {
+               return attributesList;
+       }
+
+       // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here?
+       public AnnotationGen[] getAnnotations() {
+               AnnotationGen[] annotations = new AnnotationGen[annotationsList.size()];
+               annotationsList.toArray(annotations);
+               return annotations;
+       }
+
+       public ConstantPool getConstantPool() {
+               return cp;
+       }
+
+       public void setConstantPool(ConstantPool constant_pool) {
+               cp = 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('/', '.');
+       }
+
+       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('/', '.');
+       }
+
+       public int getSuperclassNameIndex() {
+               return superclass_name_index;
+       }
+
+       public int getClassNameIndex() {
+               return class_name_index;
+       }
+
+       @Override
+       public Object clone() {
+               try {
+                       return super.clone();
+               } catch (CloneNotSupportedException e) {
+                       System.err.println(e);
+                       return null;
                }
+       }
+
+       // 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;
+       }
+
+       /**
+        * Calculate the SerialVersionUID for a class.
+        */
+       public long getSUID() {
+               try {
+                       Field[] fields = getFields();
+                       Method[] methods = getMethods();
+
+                       ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                       DataOutputStream dos = new DataOutputStream(baos);
+
+                       // 1. classname
+                       dos.writeUTF(getClassName());
+
+                       // 2. classmodifiers: ACC_PUBLIC, ACC_FINAL, ACC_INTERFACE, and ACC_ABSTRACT
+                       int classmods = 0;
+                       classmods |= (isPublic() ? Constants.ACC_PUBLIC : 0);
+                       classmods |= (isFinal() ? Constants.ACC_FINAL : 0);
+                       classmods |= (isInterface() ? Constants.ACC_INTERFACE : 0);
+
+                       if (isAbstract()) {
+                               // if an interface then abstract is only set if it has methods
+                               if (isInterface()) {
+                                       if (methods.length > 0)
+                                               classmods |= Constants.ACC_ABSTRACT;
+                               } else {
+                                       classmods |= Constants.ACC_ABSTRACT;
+                               }
+                       }
+
+                       dos.writeInt(classmods);
+
+                       // 3. ordered list of interfaces
+                       List<FieldOrMethod> list = new ArrayList<FieldOrMethod>();
+                       String[] names = getInterfaceNames();
+                       if (names != null) {
+                               Arrays.sort(names);
+                               for (int i = 0; i < names.length; i++)
+                                       dos.writeUTF(names[i]);
+                       }
+
+                       // 4. ordered list of fields (ignoring private static and private transient fields):
+                       // (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);
+                       }
+                       Collections.sort(list, 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();
+                               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>();
+                       boolean hasClinit = false;
+                       for (int i = 0; i < methods.length; i++) {
+                               Method m = methods[i];
+                               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);
+                               } else {
+                                       if (!m.isPrivate())
+                                               list.add(m);
+                               }
+                       }
+                       Collections.sort(ctors, new ConstructorComparator());
+                       Collections.sort(list, new MethodComparator());
+
+                       // 5. If a class initializer exists, write out the following:
+                       // 1. The name of the method, <clinit>.
+                       // 2. The modifier of the method, java.lang.reflect.Modifier.STATIC, written as a 32-bit integer.
+                       // 3. The descriptor of the method, ()V.
+                       if (hasClinit) {
+                               dos.writeUTF("<clinit>");
+                               dos.writeInt(Modifier.STATIC);
+                               dos.writeUTF("()V");
+                       }
 
-        // 7. sorted non-private methods 
-        for (Iterator<FieldOrMethod> iter = list.iterator(); iter.hasNext();) {
-                       Method m = (Method) iter.next();
-                       dos.writeUTF(m.getName());
-                       dos.writeInt(relevantFlags & m.getModifiers());
-                       dos.writeUTF(m.getSignature().replace('/','.'));
+                       // for methods and constructors:
+                       // ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED,
+                       // ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT
+                       relevantFlags = Constants.ACC_PUBLIC | Constants.ACC_PRIVATE | Constants.ACC_PROTECTED | Constants.ACC_STATIC
+                                       | Constants.ACC_FINAL | Constants.ACC_SYNCHRONIZED | Constants.ACC_NATIVE | Constants.ACC_ABSTRACT
+                                       | 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('/', '.'));
+                       }
+
+                       // 7. sorted non-private methods
+                       for (Iterator<FieldOrMethod> iter = list.iterator(); iter.hasNext();) {
+                               Method m = (Method) iter.next();
+                               dos.writeUTF(m.getName());
+                               dos.writeInt(relevantFlags & m.getModifiers());
+                               dos.writeUTF(m.getSignature().replace('/', '.'));
+                       }
+                       dos.flush();
+                       dos.close();
+                       byte[] bs = baos.toByteArray();
+                       MessageDigest md = MessageDigest.getInstance("SHA");
+                       byte[] result = md.digest(bs);
+
+                       long suid = 0L;
+                       int pos = result.length > 8 ? 7 : result.length - 1; // use the bytes we have
+                       while (pos >= 0) {
+                               suid = suid << 8 | ((long) result[pos--] & 0xff);
+                       }
+
+                       // if it was definetly 8 everytime...
+                       // long suid = ((long)(sha[0]&0xff) | (long)(sha[1]&0xff) << 8 |
+                       // (long)(sha[2]&0xff) << 16 | (long)(sha[3]&0xff) << 24 |
+                       // (long)(sha[4]&0xff) << 32 | (long)(sha[5]&0xff) << 40 |
+                       // (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());
                }
-        dos.flush();
-        dos.close();
-        byte[] bs = baos.toByteArray();
-        MessageDigest md = MessageDigest.getInstance("SHA");
-        byte[] result = md.digest(bs);
-                
-        long suid = 0L;
-        int pos = result.length>8?7:result.length-1; // use the bytes we have
-        while (pos>=0) {
-               suid = suid<<8 | ((long)result[pos--]&0xff);
-        }
-
-        // if it was definetly 8 everytime...
-        //         long suid = ((long)(sha[0]&0xff) | (long)(sha[1]&0xff) << 8  |
-               //                       (long)(sha[2]&0xff) << 16 | (long)(sha[3]&0xff) << 24 |
-               //                       (long)(sha[4]&0xff) << 32 | (long)(sha[5]&0xff) << 40 |
-               //                       (long)(sha[6]&0xff) << 48 | (long)(sha[7]&0xff) << 56);
-           return suid;
-       } catch (Exception e) {
-               System.err.println("Unable to calculate suid for "+getClassName());
-               e.printStackTrace();
-               throw new RuntimeException("Unable to calculate suid for "+getClassName()+": "+e.toString());
-       }
-  }
-  
-  private static class FieldComparator implements Comparator {
-               public int compare(Object arg0, Object arg1) { 
-                       return ((Field)arg0).getName().compareTo(((Field)arg1).getName());
+       }
+
+       private static class FieldComparator implements Comparator {
+               public int compare(Object arg0, Object arg1) {
+                       return ((Field) arg0).getName().compareTo(((Field) arg1).getName());
                }
-  }
-  private static class ConstructorComparator implements Comparator {
-               public int compare(Object arg0, Object arg1) { 
+       }
+
+       private static class ConstructorComparator implements Comparator {
+               public int compare(Object arg0, Object arg1) {
                        // can ignore the name...
-                       return ((Method)arg0).getSignature().compareTo(((Method)arg1).getSignature());
+                       return ((Method) arg0).getSignature().compareTo(((Method) arg1).getSignature());
                }
-  }
-  private static class MethodComparator implements Comparator {
-               public int compare(Object arg0, Object arg1) { 
-                       Method m1 = (Method)arg0;
-                       Method m2 = (Method)arg1;
+       }
+
+       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;
+                       if (result != 0)
+                               return result;
                        return m1.getSignature().compareTo(m2.getSignature());
                }
-  }
-  
-  public boolean hasAttribute(String attributeName) {
-         for (Iterator<Attribute> iter = attributesList.iterator(); iter.hasNext();) {
-               Attribute attr = iter.next();
-               if (attr.getName().equals(attributeName)) return true;
-       }        
-       return false;
-  }
-
-  public Attribute getAttribute(String attributeName) {
-         for (Iterator<Attribute> iter = attributesList.iterator(); iter.hasNext();) {
+       }
+
+       public boolean hasAttribute(String attributeName) {
+               for (Attribute attr : attributesList) {
+                       if (attr.getName().equals(attributeName)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       public Attribute getAttribute(String attributeName) {
+               for (Iterator<Attribute> iter = attributesList.iterator(); iter.hasNext();) {
                        Attribute attr = iter.next();
-                       if (attr.getName().equals(attributeName)) return attr;
-               }        
+                       if (attr.getName().equals(attributeName))
+                               return attr;
+               }
                return null;
-  }
+       }
 }
index 94437abd5cb4faef89e6a53c49fc052af67cfbbf..372c7b7b99bf745b07fe011a5936bb1523b79d5e 100644 (file)
@@ -55,27 +55,28 @@ package org.aspectj.apache.bcel.generic;
  */
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
-import org.aspectj.apache.bcel.classfile.Modifiers;
 import org.aspectj.apache.bcel.classfile.Attribute;
 import org.aspectj.apache.bcel.classfile.ConstantPool;
+import org.aspectj.apache.bcel.classfile.Modifiers;
 import org.aspectj.apache.bcel.classfile.Utility;
 import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnotations;
 
 /**
- * Super class for FieldGen and MethodGen objects, since they have some methods
- * in common!
+ * Super class for FieldGen and MethodGen objects, since they have some methods in common!
  * 
- * @version $Id: FieldGenOrMethodGen.java,v 1.5 2009/09/09 19:56:20 aclement Exp $
+ * @version $Id: FieldGenOrMethodGen.java,v 1.6 2009/09/09 22:18:20 aclement Exp $
  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  */
 public abstract class FieldGenOrMethodGen extends Modifiers implements Cloneable {
-       
+
        protected String name;
        protected Type type;
        protected ConstantPool cp;
-       private ArrayList/*<Attribute>*/<Attribute> attributeList    = new ArrayList<Attribute>();
+       private ArrayList/* <Attribute> */<Attribute> attributeList = new ArrayList<Attribute>();
        private ArrayList<AnnotationGen> annotationList = new ArrayList<AnnotationGen>();
 
        protected FieldGenOrMethodGen() {
@@ -129,10 +130,10 @@ public abstract class FieldGenOrMethodGen extends Modifiers implements Cloneable
                annotationList.clear();
        }
 
-       public List/*<Attribute>*/<Attribute> getAttributes() {
+       public List/* <Attribute> */<Attribute> getAttributes() {
                return attributeList;
        }
-       
+
        public Attribute[] getAttributesImmutable() {
                Attribute[] attributes = new Attribute[attributeList.size()];
                attributeList.toArray(attributes);
@@ -140,12 +141,12 @@ public abstract class FieldGenOrMethodGen extends Modifiers implements Cloneable
        }
 
        protected void addAnnotationsAsAttribute(ConstantPool cp) {
-               Attribute[] attrs = Utility.getAnnotationAttributes(cp,annotationList);
-               if (attrs!=null) {
-             for (int i = 0; i < attrs.length; i++) {
-                         addAttribute(attrs[i]);
-                 }
-               }
+               Collection<RuntimeAnnotations> attrs = Utility.getAnnotationAttributes(cp, annotationList);
+               if (attrs != null) {
+                       for (Attribute attr : attrs) {
+                               addAttribute(attr);
+                       }
+               }
        }
 
        public AnnotationGen[] getAnnotations() {
@@ -157,6 +158,7 @@ public abstract class FieldGenOrMethodGen extends Modifiers implements Cloneable
        public abstract String getSignature();
 
        // OPTIMIZE clone any use???
+       @Override
        public Object clone() {
                try {
                        return super.clone();
index 37e28b3f3c203046259407dea52f2789e0017583..ae3be0c003eabfa899b65d7dd7889a08905a80ed 100644 (file)
@@ -61,7 +61,7 @@ import org.aspectj.apache.bcel.classfile.JavaClass;
 /**
  * Super class for object and array types.
  * 
- * @version $Id: ReferenceType.java,v 1.5 2008/08/28 15:36:59 aclement Exp $
+ * @version $Id: ReferenceType.java,v 1.6 2009/09/09 22:18:20 aclement Exp $
  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  */
 public abstract class ReferenceType extends Type {
@@ -265,8 +265,8 @@ public abstract class ReferenceType extends Type {
                // this and t are ObjectTypes, see above.
                ObjectType thiz = (ObjectType) this;
                ObjectType other = (ObjectType) t;
-               JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
-               JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
+               JavaClass[] thiz_sups = Repository.lookupClass(thiz.getClassName()).getSuperClasses();// getSuperClasses(thiz.getClassName());
+               JavaClass[] other_sups = Repository.lookupClass(other.getClassName()).getSuperClasses();// getSuperClasses(other.getClassName());
 
                if (thiz_sups == null || other_sups == null) {
                        return null;
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassQueue.java b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassQueue.java
deleted file mode 100644 (file)
index d424a26..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.aspectj.apache.bcel.util;
-
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" and
- *    "Apache BCEL" must not be used to endorse or promote products
- *    derived from this software without prior written permission. For
- *    written permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    "Apache BCEL", nor may "Apache" appear in their name, without
- *    prior written permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-import java.util.LinkedList;
-import org.aspectj.apache.bcel.classfile.JavaClass;
-
-/** 
- * Utility class implementing a (typesafe) queue of JavaClass
- * objects.
- *
- * @version $Id: ClassQueue.java,v 1.4 2009/09/09 19:56:20 aclement Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 
- * @see ClassVector
-*/
-public class ClassQueue implements java.io.Serializable {
-  protected LinkedList<JavaClass> vec  = new LinkedList<JavaClass>();
-
-  public void enqueue(JavaClass clazz) { vec.addLast(clazz); }
-
-  public JavaClass dequeue()                {
-    return vec.removeFirst();
-  }
-
-  public boolean empty() { return vec.isEmpty(); }
-
-  public String toString() {
-    return vec.toString();
-  }
-}  
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassVector.java b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassVector.java
deleted file mode 100644 (file)
index bb12c40..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.aspectj.apache.bcel.util;
-
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" and
- *    "Apache BCEL" must not be used to endorse or promote products
- *    derived from this software without prior written permission. For
- *    written permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    "Apache BCEL", nor may "Apache" appear in their name, without
- *    prior written permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-import java.util.ArrayList;
-import org.aspectj.apache.bcel.classfile.JavaClass;
-
-/** 
- * Utility class implementing a (typesafe) collection of JavaClass
- * objects. Contains the most important methods of a Vector.
- *
- * @version $Id: ClassVector.java,v 1.4 2009/09/09 19:56:20 aclement Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 
- * @see ClassQueue
-*/
-public class ClassVector implements java.io.Serializable {
-  protected ArrayList<JavaClass> vec = new ArrayList<JavaClass>();
-  
-  public void      addElement(JavaClass clazz) { vec.add(clazz); }
-  public JavaClass elementAt(int index)        { return vec.get(index); }
-  public void      removeElementAt(int index)  { vec.remove(index); }
-
-  public JavaClass[] toArray() {
-    JavaClass[] classes = new JavaClass[vec.size()];
-    vec.toArray(classes);
-    return classes;
-  }
-}