]> source.dussan.org Git - javassist.git/commitdiff
reformatted the files and added javadoc comments.
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Sat, 11 Jun 2005 14:57:05 +0000 (14:57 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Sat, 11 Jun 2005 14:57:05 +0000 (14:57 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@179 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

src/main/javassist/CtClass.java
src/main/javassist/CtClassType.java
src/main/javassist/bytecode/ClassFile.java
src/main/javassist/bytecode/FieldInfo.java
src/main/javassist/bytecode/MethodInfo.java

index 91123108352308b8727727a348f19a9c8a0cfaa0..673788629f9941afd28af221437808800f360e89 100644 (file)
@@ -43,7 +43,7 @@ public abstract class CtClass {
     /**
      * The version number of this release.
      */
-    public static final String version = "3.1";
+    public static final String version = "3.1RC1";
 
     /**
      * Prints the version number and the copyright notice.
@@ -1111,10 +1111,12 @@ public abstract class CtClass {
         }
     }
 
-   public void prune()
-   {
-
-   }
+    /**
+     * Discards unnecessary data to minimize the memory footprint.
+     * After calling this method, the class is read only.
+     * It cannot be modified any more.
+     */
+    public void prune() {}
 
     /**
      * Converts this class to a class file.
index 17dfab27e51afcad89db00ae8fabad5f49c4236d..6b1ad068400dc2bd8b8cae6016bc1666fb614ad3 100644 (file)
@@ -175,7 +175,6 @@ class CtClassType extends CtClass {
 
        /*
         if (readCounter++ > READ_THRESHOLD) {
-            System.out.println("COMPACTING!!!!: " + getName());
             doCompaction();
             readCounter = 0;
         }
@@ -964,10 +963,11 @@ class CtClassType extends CtClass {
         }
     }
 
-   public void prune()
-   {
-      if (wasPruned) return;
-      wasPruned = true;
+   public void prune() {
+      if (wasPruned)
+          return;
+
+      wasPruned = wasFrozen = true;
       getClassFile2().prune();
    }
 
@@ -990,7 +990,7 @@ class CtClassType extends CtClass {
                 fieldInitializers = null;
                 if (doPruning) {
                     // to save memory
-                    cf. prune();
+                    cf.prune();
                     wasPruned = true;
                 }
             }
index 77ba885b132254f524aeaf4a04752a1f92c26cbd..4a8fa4ab5569190fa0d1ab413ed2b697a8e5403f 100644 (file)
@@ -26,731 +26,671 @@ import java.util.Map;
 import javassist.CannotCompileException;
 
 /**
- * <code>ClassFile</code> represents a Java <code>.class</code> file,
- * which consists of a constant pool, methods, fields, and attributes.
- *
+ * <code>ClassFile</code> represents a Java <code>.class</code> file, which
+ * consists of a constant pool, methods, fields, and attributes.
+ * 
  * @see javassist.CtClass#getClassFile()
  */
-public final class ClassFile
-{
-   int major, minor;           // version number
-   ConstPool constPool;
-   int thisClass;
-   int accessFlags;
-   int superClass;
-   int[] interfaces;
-   ArrayList fields;
-   ArrayList methods;
-   LinkedList attributes;
-
-   String thisclassname;       // not JVM-internal name
-   String[] cachedInterfaces;
-   String cachedSuperclass;
-
-   /**
-    * Constructs a class file from a byte stream.
-    */
-   public ClassFile(DataInputStream in) throws IOException
-   {
-      read(in);
-   }
-
-   /**
-    * Constructs a class file including no members.
-    *
-    * @param isInterface true if this is an interface.
-    *                    false if this is a class.
-    * @param classname   a fully-qualified class name
-    * @param superclass  a fully-qualified super class name
-    */
-   public ClassFile(boolean isInterface,
-                    String classname, String superclass)
-   {
-      major = 45;
-      minor = 3;      // JDK 1.1 or later
-      constPool = new ConstPool(classname);
-      thisClass = constPool.getThisClassInfo();
-      if (isInterface)
-         accessFlags = AccessFlag.SUPER | AccessFlag.INTERFACE
-                       | AccessFlag.ABSTRACT;
-      else
-         accessFlags = AccessFlag.SUPER;
-
-      initSuperclass(superclass);
-      interfaces = null;
-      fields = new ArrayList();
-      methods = new ArrayList();
-      thisclassname = classname;
-
-      attributes = new LinkedList();
-      attributes.add(new SourceFileAttribute(constPool,
-                                             getSourcefileName(thisclassname)));
-   }
-
-   private void initSuperclass(String superclass)
-   {
-      if (superclass != null)
-      {
-         this.superClass = constPool.addClassInfo(superclass);
-         cachedSuperclass = superclass;
-      }
-      else
-      {
-         this.superClass = constPool.addClassInfo("java.lang.Object");
-         cachedSuperclass = "java.lang.Object";
-      }
-   }
-
-   private static String getSourcefileName(String qname)
-   {
-      int index = qname.lastIndexOf('.');
-      if (index >= 0)
-         qname = qname.substring(index + 1);
-
-      return qname + ".java";
-   }
-
-   /**
-    * Eliminates dead constant pool items.  If a method or a field is removed,
-    * the constant pool items used by that method/field become dead items.
-    * This method recreates a constant pool.
-    */
-   public void compact()
-   {
-      ConstPool cp = compact0();
-      ArrayList list = methods;
-      int n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         minfo.compact(cp);
-      }
-
-      list = fields;
-      n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         FieldInfo finfo = (FieldInfo) list.get(i);
-         finfo.compact(cp);
-      }
-
-      attributes = AttributeInfo.copyAll(attributes, cp);
-      constPool = cp;
-   }
-
-   private ConstPool compact0()
-   {
-      ConstPool cp = new ConstPool(thisclassname);
-      thisClass = cp.getThisClassInfo();
-      String sc = getSuperclass();
-      if (sc != null)
-      {
-         superClass = cp.addClassInfo(getSuperclass());
-      }
-
-      if (interfaces != null)
-      {
-         int n = interfaces.length;
-         for (int i = 0; i < n; ++i)
-            interfaces[i]
-            = cp.addClassInfo(constPool.getClassInfo(interfaces[i]));
-      }
-
-      return cp;
-   }
-
-   /**
-    * Discards all attributes, associated with both the class file and
-    * the members such as a code attribute and exceptions attribute.
-    * The unused constant pool entries are also discarded (a new packed
-    * constant pool is constructed).
-    */
-   public void prune()
-   {
-      ConstPool cp = compact0();
-      AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag);
-      LinkedList newAttributes = new LinkedList();
-      if (invisibleAnnotations != null)
-      {
-         invisibleAnnotations = invisibleAnnotations.copy(cp, null);
-         newAttributes.add(invisibleAnnotations);
-      }
-      AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag);
-      if (visibleAnnotations != null)
-      {
-         visibleAnnotations = visibleAnnotations.copy(cp, null);
-         newAttributes.add(visibleAnnotations);
-      }
-
-      ArrayList list = methods;
-      int n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         minfo.prune(cp);
-      }
-
-      list = fields;
-      n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         FieldInfo finfo = (FieldInfo) list.get(i);
-         finfo.prune(cp);
-      }
-      attributes = newAttributes;
-      cp.prune();
-      constPool = cp;
-   }
-
-   /**
-    * Returns a constant pool table.
-    */
-   public ConstPool getConstPool()
-   {
-      return constPool;
-   }
-
-   /**
-    * Returns true if this is an interface.
-    */
-   public boolean isInterface()
-   {
-      return (accessFlags & AccessFlag.INTERFACE) != 0;
-   }
-
-   /**
-    * Returns true if this is a final class or interface.
-    */
-   public boolean isFinal()
-   {
-      return (accessFlags & AccessFlag.FINAL) != 0;
-   }
-
-   /**
-    * Returns true if this is an abstract class or an interface.
-    */
-   public boolean isAbstract()
-   {
-      return (accessFlags & AccessFlag.ABSTRACT) != 0;
-   }
-
-   /**
-    * Returns access flags.
-    *
-    * @see javassist.bytecode.AccessFlag
-    */
-   public int getAccessFlags()
-   {
-      return accessFlags;
-   }
-
-   /**
-    * Changes access flags.
-    *
-    * @see javassist.bytecode.AccessFlag
-    */
-   public void setAccessFlags(int acc)
-   {
-      accessFlags = acc | AccessFlag.SUPER;
-   }
-
-   /**
-    * Returns the class name.
-    */
-   public String getName()
-   {
-      return thisclassname;
-   }
-
-   /**
-    * Sets the class name.  This method substitutes the new name
-    * for all occurrences of the old class name in the class file.
-    */
-   public void setName(String name)
-   {
-      renameClass(thisclassname, name);
-   }
-
-   /**
-    * Returns the super class name.
-    */
-   public String getSuperclass()
-   {
-      if (cachedSuperclass == null) cachedSuperclass = constPool.getClassInfo(superClass);
-      return cachedSuperclass;
-   }
-
-   /**
-    * Returns the index of the constant pool entry representing
-    * the super class.
-    */
-   public int getSuperclassId()
-   {
-      return superClass;
-   }
-
-   /**
-    * Sets the super class.
-    * <p/>
-    * <p>This method modifies constructors so that they call
-    * constructors declared in the new super class.
-    */
-   public void setSuperclass(String superclass)
-           throws CannotCompileException
-   {
-      if (superclass == null)
-         superclass = "java.lang.Object";
-
-      try
-      {
-         this.superClass = constPool.addClassInfo(superclass);
-         ArrayList list = methods;
-         int n = list.size();
-         for (int i = 0; i < n; ++i)
-         {
-            MethodInfo minfo = (MethodInfo) list.get(i);
-            minfo.setSuperclass(superclass);
-         }
-      }
-      catch (BadBytecode e)
-      {
-         throw new CannotCompileException(e);
-      }
-      cachedSuperclass = superclass;
-   }
-
-   /**
-    * Replaces all occurrences of a class name in the class file.
-    * <p/>
-    * <p>If class X is substituted for class Y in the class file,
-    * X and Y must have the same signature.  If Y provides a method
-    * m(), X must provide it even if X inherits m() from the super class.
-    * If this fact is not guaranteed, the bytecode verifier may cause
-    * an error.
-    *
-    * @param oldname the replaced class name
-    * @param newname the substituted class name
-    */
-   public final void renameClass(String oldname, String newname)
-   {
-      ArrayList list;
-      int n;
-
-      if (oldname.equals(newname))
-         return;
-
-      if (oldname.equals(thisclassname))
-         thisclassname = newname;
-
-      oldname = Descriptor.toJvmName(oldname);
-      newname = Descriptor.toJvmName(newname);
-      constPool.renameClass(oldname, newname);
-
-      list = methods;
-      n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         String desc = minfo.getDescriptor();
-         minfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
-      }
-
-      list = fields;
-      n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         FieldInfo finfo = (FieldInfo) list.get(i);
-         String desc = finfo.getDescriptor();
-         finfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
-      }
-   }
-
-   /**
-    * Replaces all occurrences of several class names in the class file.
-    *
-    * @param classnames specifies which class name is replaced
-    *                   with which new name.  Class names must
-    *                   be described with the JVM-internal
-    *                   representation like
-    *                   <code>java/lang/Object</code>.
-    * @see #renameClass(String,String)
-    */
-   public final void renameClass(Map classnames)
-   {
-      String jvmNewThisName
-              = (String) classnames.get(Descriptor.toJvmName(thisclassname));
-      if (jvmNewThisName != null)
-         thisclassname = Descriptor.toJavaName(jvmNewThisName);
-
-      constPool.renameClass(classnames);
-
-      ArrayList list = methods;
-      int n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         String desc = minfo.getDescriptor();
-         minfo.setDescriptor(Descriptor.rename(desc, classnames));
-      }
-
-      list = fields;
-      n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         FieldInfo finfo = (FieldInfo) list.get(i);
-         String desc = finfo.getDescriptor();
-         finfo.setDescriptor(Descriptor.rename(desc, classnames));
-      }
-   }
-
-   /**
-    * Returns the names of the interfaces implemented by the class.
-    */
-   public String[] getInterfaces()
-   {
-      if (cachedInterfaces != null) return cachedInterfaces;
-      String[] rtn = null;
-      if (interfaces == null)
-         rtn = new String[0];
-      else
-      {
-         int n = interfaces.length;
-         String[] list = new String[n];
-         for (int i = 0; i < n; ++i)
-            list[i] = constPool.getClassInfo(interfaces[i]);
-
-         rtn = list;
-      }
-      cachedInterfaces = rtn;
-      return rtn;
-   }
-
-   /**
-    * Sets the interfaces.
-    *
-    * @param nameList the names of the interfaces.
-    */
-   public void setInterfaces(String[] nameList)
-   {
-      cachedInterfaces = null;
-      if (nameList != null)
-      {
-         int n = nameList.length;
-         interfaces = new int[n];
-         for (int i = 0; i < n; ++i)
-            interfaces[i] = constPool.addClassInfo(nameList[i]);
-      }
-   }
-
-   /**
-    * Appends an interface to the
-    * interfaces implemented by the class.
-    */
-   public void addInterface(String name)
-   {
-      cachedInterfaces = null;
-      int info = constPool.addClassInfo(name);
-      if (interfaces == null)
-      {
-         interfaces = new int[1];
-         interfaces[0] = info;
-      }
-      else
-      {
-         int n = interfaces.length;
-         int[] newarray = new int[n + 1];
-         System.arraycopy(interfaces, 0, newarray, 0, n);
-         newarray[n] = info;
-         interfaces = newarray;
-      }
-   }
-
-   /**
-    * Returns all the fields declared in the class.
-    *
-    * @return a list of <code>FieldInfo</code>.
-    * @see FieldInfo
-    */
-   public List getFields()
-   {
-      return fields;
-   }
-
-   /**
-    * Appends a field to the class.
-    */
-   public void addField(FieldInfo finfo) throws CannotCompileException
-   {
-      testExistingField(finfo.getName(), finfo.getDescriptor());
-      fields.add(finfo);
-   }
-
-   private void addField0(FieldInfo finfo)
-   {
-      fields.add(finfo);
-   }
-
-   private void testExistingField(String name, String descriptor)
-           throws CannotCompileException
-   {
-      ListIterator it = fields.listIterator(0);
-      while (it.hasNext())
-      {
-         FieldInfo minfo = (FieldInfo) it.next();
-         if (minfo.getName().equals(name))
-            throw new CannotCompileException("duplicate field: " + name);
-      }
-   }
-
-   /**
-    * Returns all the methods declared in the class.
-    *
-    * @return a list of <code>MethodInfo</code>.
-    * @see MethodInfo
-    */
-   public List getMethods()
-   {
-      return methods;
-   }
-
-   /**
-    * Returns the method with the specified name.  If there are multiple
-    * methods with that name, this method returns one of them.
-    *
-    * @return null             if no such a method is found.
-    */
-   public MethodInfo getMethod(String name)
-   {
-      ArrayList list = methods;
-      int n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         if (minfo.getName().equals(name))
-            return minfo;
-      }
-
-      return null;
-   }
-
-   /**
-    * Returns a static initializer (class initializer), or null if
-    * it does not exist.
-    */
-   public MethodInfo getStaticInitializer()
-   {
-      return getMethod(MethodInfo.nameClinit);
-   }
-
-   /**
-    * Appends a method to the class.
-    */
-   public void addMethod(MethodInfo minfo) throws CannotCompileException
-   {
-      testExistingMethod(minfo.getName(), minfo.getDescriptor());
-      methods.add(minfo);
-   }
-
-   private void addMethod0(MethodInfo minfo)
-   {
-      methods.add(minfo);
-   }
-
-   private void testExistingMethod(String name, String descriptor)
-           throws CannotCompileException
-   {
-      ListIterator it = methods.listIterator(0);
-      while (it.hasNext())
-      {
-         MethodInfo minfo = (MethodInfo) it.next();
-         if (minfo.getName().equals(name)
-             && Descriptor.eqParamTypes(minfo.getDescriptor(), descriptor))
-            throw new CannotCompileException("duplicate method: " + name);
-      }
-   }
-
-   /**
-    * Returns all the attributes.
-    *
-    * @return a list of <code>AttributeInfo</code> objects.
-    * @see AttributeInfo
-    */
-   public List getAttributes()
-   {
-      return attributes;
-   }
-
-   /**
-    * Returns the attribute with the specified name.
-    *
-    * @param name attribute name
-    */
-   public AttributeInfo getAttribute(String name)
-   {
-      LinkedList list = attributes;
-      int n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         AttributeInfo ai = (AttributeInfo) list.get(i);
-         if (ai.getName().equals(name))
-            return ai;
-      }
-
-      return null;
-   }
-
-   /**
-    * Appends an attribute.  If there is already an attribute with
-    * the same name, the new one substitutes for it.
-    */
-   public void addAttribute(AttributeInfo info)
-   {
-      AttributeInfo.remove(attributes, info.getName());
-      attributes.add(info);
-   }
-
-   /**
-    * Returns the source file containing this class.
-    *
-    * @return null     if this information is not available.
-    */
-   public String getSourceFile()
-   {
-      SourceFileAttribute sf
-              = (SourceFileAttribute) getAttribute(SourceFileAttribute.tag);
-      if (sf == null)
-         return null;
-      else
-         return sf.getFileName();
-   }
-
-   private void read(DataInputStream in) throws IOException
-   {
-      int i, n;
-      int magic = in.readInt();
-      if (magic != 0xCAFEBABE)
-         throw new IOException("non class file");
-
-      minor = in.readUnsignedShort();
-      major = in.readUnsignedShort();
-      constPool = new ConstPool(in);
-      accessFlags = in.readUnsignedShort();
-      thisClass = in.readUnsignedShort();
-      constPool.setThisClassInfo(thisClass);
-      superClass = in.readUnsignedShort();
-      n = in.readUnsignedShort();
-      if (n == 0)
-         interfaces = null;
-      else
-      {
-         interfaces = new int[n];
-         for (i = 0; i < n; ++i)
-            interfaces[i] = in.readUnsignedShort();
-      }
-
-      ConstPool cp = constPool;
-      n = in.readUnsignedShort();
-      fields = new ArrayList();
-      for (i = 0; i < n; ++i)
-         addField0(new FieldInfo(cp, in));
-
-      n = in.readUnsignedShort();
-      methods = new ArrayList();
-      for (i = 0; i < n; ++i)
-         addMethod0(new MethodInfo(cp, in));
-
-      attributes = new LinkedList();
-      n = in.readUnsignedShort();
-      for (i = 0; i < n; ++i)
-         addAttribute(AttributeInfo.read(cp, in));
-
-      thisclassname = constPool.getClassInfo(thisClass);
-   }
-
-   /**
-    * Writes a class file represened by this object
-    * into an output stream.
-    */
-   public void write(DataOutputStream out) throws IOException
-   {
-      int i, n;
-
-      out.writeInt(0xCAFEBABE);       // magic
-      out.writeShort(minor);          // minor version
-      out.writeShort(major);          // major version
-      constPool.write(out);           // constant pool
-      out.writeShort(accessFlags);
-      out.writeShort(thisClass);
-      out.writeShort(superClass);
-
-      if (interfaces == null)
-         n = 0;
-      else
-         n = interfaces.length;
-
-      out.writeShort(n);
-      for (i = 0; i < n; ++i)
-         out.writeShort(interfaces[i]);
-
-      ArrayList list = fields;
-      n = list.size();
-      out.writeShort(n);
-      for (i = 0; i < n; ++i)
-      {
-         FieldInfo finfo = (FieldInfo) list.get(i);
-         finfo.write(out);
-      }
-
-      list = methods;
-      n = list.size();
-      out.writeShort(n);
-      for (i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         minfo.write(out);
-      }
-
-      out.writeShort(attributes.size());
-      AttributeInfo.writeAll(attributes, out);
-   }
-
-   /**
-    * Get the Major version.
-    *
-    * @return the major version
-    */
-   public int getMajorVersion()
-   {
-      return major;
-   }
-
-   /**
-    * Set the Major version.
-    *
-    * @param major the major version
-    */
-   public void setMajorVersion(int major)
-   {
-      this.major = major;
-   }
-
-   /**
-    * Get the Minor version.
-    *
-    * @return the minor version
-    */
-   public int getMinorVersion()
-   {
-      return minor;
-   }
-
-   /**
-    * Set the Minor version.
-    *
-    * @param minor the minor version
-    */
-   public void setMinorVersion(int minor)
-   {
-      this.minor = minor;
-   }
+public final class ClassFile {
+    int major, minor; // version number
+    ConstPool constPool;
+    int thisClass;
+    int accessFlags;
+    int superClass;
+    int[] interfaces;
+    ArrayList fields;
+    ArrayList methods;
+    LinkedList attributes;
+    String thisclassname; // not JVM-internal name
+    String[] cachedInterfaces;
+    String cachedSuperclass;
+
+    /**
+     * Constructs a class file from a byte stream.
+     */
+    public ClassFile(DataInputStream in) throws IOException {
+        read(in);
+    }
+
+    /**
+     * Constructs a class file including no members.
+     * 
+     * @param isInterface
+     *            true if this is an interface. false if this is a class.
+     * @param classname
+     *            a fully-qualified class name
+     * @param superclass
+     *            a fully-qualified super class name
+     */
+    public ClassFile(boolean isInterface, String classname, String superclass) {
+        major = 45;
+        minor = 3; // JDK 1.1 or later
+        constPool = new ConstPool(classname);
+        thisClass = constPool.getThisClassInfo();
+        if (isInterface)
+            accessFlags = AccessFlag.SUPER | AccessFlag.INTERFACE
+                    | AccessFlag.ABSTRACT;
+        else
+            accessFlags = AccessFlag.SUPER;
+
+        initSuperclass(superclass);
+        interfaces = null;
+        fields = new ArrayList();
+        methods = new ArrayList();
+        thisclassname = classname;
+
+        attributes = new LinkedList();
+        attributes.add(new SourceFileAttribute(constPool,
+                getSourcefileName(thisclassname)));
+    }
+
+    private void initSuperclass(String superclass) {
+        if (superclass != null) {
+            this.superClass = constPool.addClassInfo(superclass);
+            cachedSuperclass = superclass;
+        }
+        else {
+            this.superClass = constPool.addClassInfo("java.lang.Object");
+            cachedSuperclass = "java.lang.Object";
+        }
+    }
+
+    private static String getSourcefileName(String qname) {
+        int index = qname.lastIndexOf('.');
+        if (index >= 0)
+            qname = qname.substring(index + 1);
+
+        return qname + ".java";
+    }
+
+    /**
+     * Eliminates dead constant pool items. If a method or a field is removed,
+     * the constant pool items used by that method/field become dead items. This
+     * method recreates a constant pool.
+     */
+    public void compact() {
+        ConstPool cp = compact0();
+        ArrayList list = methods;
+        int n = list.size();
+        for (int i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            minfo.compact(cp);
+        }
+
+        list = fields;
+        n = list.size();
+        for (int i = 0; i < n; ++i) {
+            FieldInfo finfo = (FieldInfo)list.get(i);
+            finfo.compact(cp);
+        }
+
+        attributes = AttributeInfo.copyAll(attributes, cp);
+        constPool = cp;
+    }
+
+    private ConstPool compact0() {
+        ConstPool cp = new ConstPool(thisclassname);
+        thisClass = cp.getThisClassInfo();
+        String sc = getSuperclass();
+        if (sc != null)
+            superClass = cp.addClassInfo(getSuperclass());
+
+        if (interfaces != null) {
+            int n = interfaces.length;
+            for (int i = 0; i < n; ++i)
+                interfaces[i]
+                    = cp.addClassInfo(constPool.getClassInfo(interfaces[i]));
+        }
+
+        return cp;
+    }
+
+    /**
+     * Discards all attributes, associated with both the class file and the
+     * members such as a code attribute and exceptions attribute. The unused
+     * constant pool entries are also discarded (a new packed constant pool is
+     * constructed).
+     */
+    public void prune() {
+        ConstPool cp = compact0();
+        LinkedList newAttributes = new LinkedList();
+        AttributeInfo invisibleAnnotations
+            = getAttribute(AnnotationsAttribute.invisibleTag);
+        if (invisibleAnnotations != null) {
+            invisibleAnnotations = invisibleAnnotations.copy(cp, null);
+            newAttributes.add(invisibleAnnotations);
+        }
+
+        AttributeInfo visibleAnnotations
+            = getAttribute(AnnotationsAttribute.visibleTag);
+        if (visibleAnnotations != null) {
+            visibleAnnotations = visibleAnnotations.copy(cp, null);
+            newAttributes.add(visibleAnnotations);
+        }
+
+        ArrayList list = methods;
+        int n = list.size();
+        for (int i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            minfo.prune(cp);
+        }
+
+        list = fields;
+        n = list.size();
+        for (int i = 0; i < n; ++i) {
+            FieldInfo finfo = (FieldInfo)list.get(i);
+            finfo.prune(cp);
+        }
+
+        attributes = newAttributes;
+        cp.prune();
+        constPool = cp;
+    }
+
+    /**
+     * Returns a constant pool table.
+     */
+    public ConstPool getConstPool() {
+        return constPool;
+    }
+
+    /**
+     * Returns true if this is an interface.
+     */
+    public boolean isInterface() {
+        return (accessFlags & AccessFlag.INTERFACE) != 0;
+    }
+
+    /**
+     * Returns true if this is a final class or interface.
+     */
+    public boolean isFinal() {
+        return (accessFlags & AccessFlag.FINAL) != 0;
+    }
+
+    /**
+     * Returns true if this is an abstract class or an interface.
+     */
+    public boolean isAbstract() {
+        return (accessFlags & AccessFlag.ABSTRACT) != 0;
+    }
+
+    /**
+     * Returns access flags.
+     * 
+     * @see javassist.bytecode.AccessFlag
+     */
+    public int getAccessFlags() {
+        return accessFlags;
+    }
+
+    /**
+     * Changes access flags.
+     * 
+     * @see javassist.bytecode.AccessFlag
+     */
+    public void setAccessFlags(int acc) {
+        accessFlags = acc | AccessFlag.SUPER;
+    }
+
+    /**
+     * Returns the class name.
+     */
+    public String getName() {
+        return thisclassname;
+    }
+
+    /**
+     * Sets the class name. This method substitutes the new name for all
+     * occurrences of the old class name in the class file.
+     */
+    public void setName(String name) {
+        renameClass(thisclassname, name);
+    }
+
+    /**
+     * Returns the super class name.
+     */
+    public String getSuperclass() {
+        if (cachedSuperclass == null)
+            cachedSuperclass = constPool.getClassInfo(superClass);
+
+        return cachedSuperclass;
+    }
+
+    /**
+     * Returns the index of the constant pool entry representing the super
+     * class.
+     */
+    public int getSuperclassId() {
+        return superClass;
+    }
+
+    /**
+     * Sets the super class.
+     * 
+     * <p>
+     * This method modifies constructors so that they call constructors declared
+     * in the new super class.
+     */
+    public void setSuperclass(String superclass) throws CannotCompileException {
+        if (superclass == null)
+            superclass = "java.lang.Object";
+
+        try {
+            this.superClass = constPool.addClassInfo(superclass);
+            ArrayList list = methods;
+            int n = list.size();
+            for (int i = 0; i < n; ++i) {
+                MethodInfo minfo = (MethodInfo)list.get(i);
+                minfo.setSuperclass(superclass);
+            }
+        }
+        catch (BadBytecode e) {
+            throw new CannotCompileException(e);
+        }
+        cachedSuperclass = superclass;
+    }
+
+    /**
+     * Replaces all occurrences of a class name in the class file.
+     * 
+     * <p>
+     * If class X is substituted for class Y in the class file, X and Y must
+     * have the same signature. If Y provides a method m(), X must provide it
+     * even if X inherits m() from the super class. If this fact is not
+     * guaranteed, the bytecode verifier may cause an error.
+     * 
+     * @param oldname
+     *            the replaced class name
+     * @param newname
+     *            the substituted class name
+     */
+    public final void renameClass(String oldname, String newname) {
+        ArrayList list;
+        int n;
+
+        if (oldname.equals(newname))
+            return;
+
+        if (oldname.equals(thisclassname))
+            thisclassname = newname;
+
+        oldname = Descriptor.toJvmName(oldname);
+        newname = Descriptor.toJvmName(newname);
+        constPool.renameClass(oldname, newname);
+
+        list = methods;
+        n = list.size();
+        for (int i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            String desc = minfo.getDescriptor();
+            minfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
+        }
+
+        list = fields;
+        n = list.size();
+        for (int i = 0; i < n; ++i) {
+            FieldInfo finfo = (FieldInfo)list.get(i);
+            String desc = finfo.getDescriptor();
+            finfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
+        }
+    }
+
+    /**
+     * Replaces all occurrences of several class names in the class file.
+     * 
+     * @param classnames
+     *            specifies which class name is replaced with which new name.
+     *            Class names must be described with the JVM-internal
+     *            representation like <code>java/lang/Object</code>.
+     * @see #renameClass(String,String)
+     */
+    public final void renameClass(Map classnames) {
+        String jvmNewThisName = (String)classnames.get(Descriptor
+                .toJvmName(thisclassname));
+        if (jvmNewThisName != null)
+            thisclassname = Descriptor.toJavaName(jvmNewThisName);
+
+        constPool.renameClass(classnames);
+
+        ArrayList list = methods;
+        int n = list.size();
+        for (int i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            String desc = minfo.getDescriptor();
+            minfo.setDescriptor(Descriptor.rename(desc, classnames));
+        }
+
+        list = fields;
+        n = list.size();
+        for (int i = 0; i < n; ++i) {
+            FieldInfo finfo = (FieldInfo)list.get(i);
+            String desc = finfo.getDescriptor();
+            finfo.setDescriptor(Descriptor.rename(desc, classnames));
+        }
+    }
+
+    /**
+     * Returns the names of the interfaces implemented by the class.
+     */
+    public String[] getInterfaces() {
+        if (cachedInterfaces != null)
+            return cachedInterfaces;
+
+        String[] rtn = null;
+        if (interfaces == null)
+            rtn = new String[0];
+        else {
+            int n = interfaces.length;
+            String[] list = new String[n];
+            for (int i = 0; i < n; ++i)
+                list[i] = constPool.getClassInfo(interfaces[i]);
+
+            rtn = list;
+        }
+
+        cachedInterfaces = rtn;
+        return rtn;
+    }
+
+    /**
+     * Sets the interfaces.
+     * 
+     * @param nameList
+     *            the names of the interfaces.
+     */
+    public void setInterfaces(String[] nameList) {
+        cachedInterfaces = null;
+        if (nameList != null) {
+            int n = nameList.length;
+            interfaces = new int[n];
+            for (int i = 0; i < n; ++i)
+                interfaces[i] = constPool.addClassInfo(nameList[i]);
+        }
+    }
+
+    /**
+     * Appends an interface to the interfaces implemented by the class.
+     */
+    public void addInterface(String name) {
+        cachedInterfaces = null;
+        int info = constPool.addClassInfo(name);
+        if (interfaces == null) {
+            interfaces = new int[1];
+            interfaces[0] = info;
+        }
+        else {
+            int n = interfaces.length;
+            int[] newarray = new int[n + 1];
+            System.arraycopy(interfaces, 0, newarray, 0, n);
+            newarray[n] = info;
+            interfaces = newarray;
+        }
+    }
+
+    /**
+     * Returns all the fields declared in the class.
+     * 
+     * @return a list of <code>FieldInfo</code>.
+     * @see FieldInfo
+     */
+    public List getFields() {
+        return fields;
+    }
+
+    /**
+     * Appends a field to the class.
+     */
+    public void addField(FieldInfo finfo) throws CannotCompileException {
+        testExistingField(finfo.getName(), finfo.getDescriptor());
+        fields.add(finfo);
+    }
+
+    private void addField0(FieldInfo finfo) {
+        fields.add(finfo);
+    }
+
+    private void testExistingField(String name, String descriptor)
+            throws CannotCompileException {
+        ListIterator it = fields.listIterator(0);
+        while (it.hasNext()) {
+            FieldInfo minfo = (FieldInfo)it.next();
+            if (minfo.getName().equals(name))
+                throw new CannotCompileException("duplicate field: " + name);
+        }
+    }
+
+    /**
+     * Returns all the methods declared in the class.
+     * 
+     * @return a list of <code>MethodInfo</code>.
+     * @see MethodInfo
+     */
+    public List getMethods() {
+        return methods;
+    }
+
+    /**
+     * Returns the method with the specified name. If there are multiple methods
+     * with that name, this method returns one of them.
+     * 
+     * @return null if no such a method is found.
+     */
+    public MethodInfo getMethod(String name) {
+        ArrayList list = methods;
+        int n = list.size();
+        for (int i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            if (minfo.getName().equals(name))
+                return minfo;
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns a static initializer (class initializer), or null if it does not
+     * exist.
+     */
+    public MethodInfo getStaticInitializer() {
+        return getMethod(MethodInfo.nameClinit);
+    }
+
+    /**
+     * Appends a method to the class.
+     */
+    public void addMethod(MethodInfo minfo) throws CannotCompileException {
+        testExistingMethod(minfo.getName(), minfo.getDescriptor());
+        methods.add(minfo);
+    }
+
+    private void addMethod0(MethodInfo minfo) {
+        methods.add(minfo);
+    }
+
+    private void testExistingMethod(String name, String descriptor)
+            throws CannotCompileException {
+        ListIterator it = methods.listIterator(0);
+        while (it.hasNext()) {
+            MethodInfo minfo = (MethodInfo)it.next();
+            if (minfo.getName().equals(name)
+                    && Descriptor.eqParamTypes(minfo.getDescriptor(),
+                            descriptor))
+                throw new CannotCompileException("duplicate method: " + name);
+        }
+    }
+
+    /**
+     * Returns all the attributes.
+     * 
+     * @return a list of <code>AttributeInfo</code> objects.
+     * @see AttributeInfo
+     */
+    public List getAttributes() {
+        return attributes;
+    }
+
+    /**
+     * Returns the attribute with the specified name.
+     * 
+     * @param name
+     *            attribute name
+     */
+    public AttributeInfo getAttribute(String name) {
+        LinkedList list = attributes;
+        int n = list.size();
+        for (int i = 0; i < n; ++i) {
+            AttributeInfo ai = (AttributeInfo)list.get(i);
+            if (ai.getName().equals(name))
+                return ai;
+        }
+
+        return null;
+    }
+
+    /**
+     * Appends an attribute. If there is already an attribute with the same
+     * name, the new one substitutes for it.
+     */
+    public void addAttribute(AttributeInfo info) {
+        AttributeInfo.remove(attributes, info.getName());
+        attributes.add(info);
+    }
+
+    /**
+     * Returns the source file containing this class.
+     * 
+     * @return null if this information is not available.
+     */
+    public String getSourceFile() {
+        SourceFileAttribute sf
+            = (SourceFileAttribute)getAttribute(SourceFileAttribute.tag);
+        if (sf == null)
+            return null;
+        else
+            return sf.getFileName();
+    }
+
+    private void read(DataInputStream in) throws IOException {
+        int i, n;
+        int magic = in.readInt();
+        if (magic != 0xCAFEBABE)
+            throw new IOException("non class file");
+
+        minor = in.readUnsignedShort();
+        major = in.readUnsignedShort();
+        constPool = new ConstPool(in);
+        accessFlags = in.readUnsignedShort();
+        thisClass = in.readUnsignedShort();
+        constPool.setThisClassInfo(thisClass);
+        superClass = in.readUnsignedShort();
+        n = in.readUnsignedShort();
+        if (n == 0)
+            interfaces = null;
+        else {
+            interfaces = new int[n];
+            for (i = 0; i < n; ++i)
+                interfaces[i] = in.readUnsignedShort();
+        }
+
+        ConstPool cp = constPool;
+        n = in.readUnsignedShort();
+        fields = new ArrayList();
+        for (i = 0; i < n; ++i)
+            addField0(new FieldInfo(cp, in));
+
+        n = in.readUnsignedShort();
+        methods = new ArrayList();
+        for (i = 0; i < n; ++i)
+            addMethod0(new MethodInfo(cp, in));
+
+        attributes = new LinkedList();
+        n = in.readUnsignedShort();
+        for (i = 0; i < n; ++i)
+            addAttribute(AttributeInfo.read(cp, in));
+
+        thisclassname = constPool.getClassInfo(thisClass);
+    }
+
+    /**
+     * Writes a class file represened by this object into an output stream.
+     */
+    public void write(DataOutputStream out) throws IOException {
+        int i, n;
+
+        out.writeInt(0xCAFEBABE); // magic
+        out.writeShort(minor); // minor version
+        out.writeShort(major); // major version
+        constPool.write(out); // constant pool
+        out.writeShort(accessFlags);
+        out.writeShort(thisClass);
+        out.writeShort(superClass);
+
+        if (interfaces == null)
+            n = 0;
+        else
+            n = interfaces.length;
+
+        out.writeShort(n);
+        for (i = 0; i < n; ++i)
+            out.writeShort(interfaces[i]);
+
+        ArrayList list = fields;
+        n = list.size();
+        out.writeShort(n);
+        for (i = 0; i < n; ++i) {
+            FieldInfo finfo = (FieldInfo)list.get(i);
+            finfo.write(out);
+        }
+
+        list = methods;
+        n = list.size();
+        out.writeShort(n);
+        for (i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            minfo.write(out);
+        }
+
+        out.writeShort(attributes.size());
+        AttributeInfo.writeAll(attributes, out);
+    }
+
+    /**
+     * Get the Major version.
+     * 
+     * @return the major version
+     */
+    public int getMajorVersion() {
+        return major;
+    }
+
+    /**
+     * Set the Major version.
+     * 
+     * @param major
+     *            the major version
+     */
+    public void setMajorVersion(int major) {
+        this.major = major;
+    }
+
+    /**
+     * Get the Minor version.
+     * 
+     * @return the minor version
+     */
+    public int getMinorVersion() {
+        return minor;
+    }
+
+    /**
+     * Set the Minor version.
+     * 
+     * @param minor
+     *            the minor version
+     */
+    public void setMinorVersion(int minor) {
+        this.minor = minor;
+    }
 }
index 21ec3ffbaddd6701e405d441c4dd51015f1e5685..744a57e948d8a0f74a80bf211e09f704485e6fe1 100644 (file)
@@ -30,8 +30,8 @@ public final class FieldInfo {
     ConstPool constPool;
     int accessFlags;
     int name;
-   String cachedName;
-   String cachedType;
+    String cachedName;
+    String cachedType;
     int descriptor;
     LinkedList attribute;       // may be null.
 
@@ -53,7 +53,7 @@ public final class FieldInfo {
     public FieldInfo(ConstPool cp, String fieldName, String desc) {
         this(cp);
         name = cp.addUtf8Info(fieldName);
-       cachedName = fieldName;
+        cachedName = fieldName;
         descriptor = cp.addUtf8Info(desc);
     }
 
@@ -62,6 +62,13 @@ public final class FieldInfo {
         read(in);
     }
 
+    /**
+     * Returns a string representation of the object.
+     */
+    public String toString() {
+        return getName() + " " + getDescriptor();
+    }
+
     /**
      * Copies all constant pool items to a given new constant pool
      * and replaces the original items with the new ones.
@@ -78,23 +85,24 @@ public final class FieldInfo {
     }
 
     void prune(ConstPool cp) {
-       AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag);
-       LinkedList newAttributes = new LinkedList();
-       if (invisibleAnnotations != null)
-       {
-          invisibleAnnotations = invisibleAnnotations.copy(cp, null);
-          newAttributes.add(invisibleAnnotations);
-       }
-       AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag);
-       if (visibleAnnotations != null)
-       {
-          visibleAnnotations = visibleAnnotations.copy(cp, null);
-          newAttributes.add(visibleAnnotations);
-       }
-        int index = getConstantValue();
+        LinkedList newAttributes = new LinkedList();
+        AttributeInfo invisibleAnnotations
+            = getAttribute(AnnotationsAttribute.invisibleTag);
+        if (invisibleAnnotations != null) {
+            invisibleAnnotations = invisibleAnnotations.copy(cp, null);
+            newAttributes.add(invisibleAnnotations);
+         }
+
+        AttributeInfo visibleAnnotations
+            = getAttribute(AnnotationsAttribute.visibleTag);
+        if (visibleAnnotations != null) {
+            visibleAnnotations = visibleAnnotations.copy(cp, null);
+            newAttributes.add(visibleAnnotations);
+        }
+
         attribute = newAttributes;
-        if (index != 0)
-        {
+        int index = getConstantValue();
+        if (index != 0) {
             index = constPool.copy(index, cp, null);
             attribute.add(new ConstantAttribute(cp, index));
         }
@@ -116,7 +124,9 @@ public final class FieldInfo {
      * Returns the field name.
      */
     public String getName() {
-       if (cachedName == null) cachedName = constPool.getUtf8Info(name);
+       if (cachedName == null)
+           cachedName = constPool.getUtf8Info(name);
+
        return cachedName;
     }
 
@@ -125,7 +135,7 @@ public final class FieldInfo {
      */
     public void setName(String newName) {
         name = constPool.addUtf8Info(newName);
-       cachedName = newName;
+        cachedName = newName;
     }
 
     /**
index ef94be444862e4d971ac796e222af98994457910..80eac2436b9417fc53ee10f5f1195c96ecf1a56e 100644 (file)
@@ -32,13 +32,10 @@ public final class MethodInfo {
     ConstPool constPool;
     int accessFlags;
     int name;
-   String cachedName;
+    String cachedName;
     int descriptor;
     LinkedList attribute; // may be null
 
-    // Bill, do you really need this?
-    // public Exception created = new Exception();
-
     /**
      * The name of constructors: <code>&lt;init&gt</code>.
      */
@@ -109,8 +106,7 @@ public final class MethodInfo {
      * Returns a string representation of the object.
      */
     public String toString() {
-        return getName() + " "
-                + constPool.getUtf8Info(descriptor);
+        return getName() + " " + getDescriptor();
     }
 
     /**
@@ -129,33 +125,38 @@ public final class MethodInfo {
     }
 
     void prune(ConstPool cp) {
-       AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag);
-       LinkedList newAttributes = new LinkedList();
-       if (invisibleAnnotations != null)
-       {
-          invisibleAnnotations = invisibleAnnotations.copy(cp, null);
-          newAttributes.add(invisibleAnnotations);
-       }
-       AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag);
-       if (visibleAnnotations != null)
-       {
-          visibleAnnotations = visibleAnnotations.copy(cp, null);
-          newAttributes.add(visibleAnnotations);
-       }
-       ExceptionsAttribute ea = getExceptionsAttribute();
-       if (ea != null) newAttributes.add(ea);
-       
-        attribute = newAttributes;
-        name = cp.addUtf8Info(getName());
-        descriptor = cp.addUtf8Info(getDescriptor());
-        constPool = cp;
+        LinkedList newAttributes = new LinkedList();
+        AttributeInfo invisibleAnnotations
+            = getAttribute(AnnotationsAttribute.invisibleTag);
+        if (invisibleAnnotations != null) {
+            invisibleAnnotations = invisibleAnnotations.copy(cp, null);
+            newAttributes.add(invisibleAnnotations);
+         }
+
+        AttributeInfo visibleAnnotations
+            = getAttribute(AnnotationsAttribute.visibleTag);
+        if (visibleAnnotations != null) {
+            visibleAnnotations = visibleAnnotations.copy(cp, null);
+            newAttributes.add(visibleAnnotations);
+         }
+
+         ExceptionsAttribute ea = getExceptionsAttribute();
+         if (ea != null)
+             newAttributes.add(ea);
+
+         attribute = newAttributes;
+         name = cp.addUtf8Info(getName());
+         descriptor = cp.addUtf8Info(getDescriptor());
+         constPool = cp;
     }
 
     /**
      * Returns a method name.
      */
     public String getName() {
-       if (cachedName == null) cachedName = constPool.getUtf8Info(name);
+       if (cachedName == null)
+           cachedName = constPool.getUtf8Info(name);
+
        return cachedName;
     }