]> source.dussan.org Git - javassist.git/commitdiff
reformatted the files edited by Bill.
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Tue, 28 Sep 2004 17:06:56 +0000 (17:06 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Tue, 28 Sep 2004 17:06:56 +0000 (17:06 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@138 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

build.xml
src/main/javassist/ClassPool.java
src/main/javassist/CtClass.java
src/main/javassist/CtClassType.java
src/main/javassist/bytecode/AnnotationsAttribute.java
src/main/javassist/bytecode/MethodInfo.java
src/main/javassist/bytecode/annotation/ClassMemberValue.java

index 7cf28e6af8c81a564acec7b9c5e94bb273d08223..d8e08e2dd20f6bedf951018d0e2ed11cce71ed5d 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -96,6 +96,7 @@ Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.</i>]]></bottom>
     <zip zipfile="${dist-version}.zip">
        <zipfileset dir="${basedir}" prefix="${dist-version}">
           <include name="**"/>
+          <exclude name=".*"/>
           <exclude name="build/**"/>
           <exclude name="local/**"/>
           <exclude name="${dist-version}.zip"/>
index b0a2066c1bcb82207122f1e20e652e7db88fc41e..50143d6a7e944012d776f3b8a2b4d41442931082 100644 (file)
@@ -31,9 +31,9 @@ import java.util.Hashtable;
  * to find a class file and then it creates a <code>CtClass</code> object
  * representing that class file.  The created object is returned to the
  * caller.
- * <p/>
+ *
  * <p><b>Memory consumption memo:</b>
- * <p/>
+ *
  * <p><code>ClassPool</code> objects hold all the <code>CtClass</code>es
  * that have been created so that the consistency among modified classes
  * can be guaranteed.  Thus if a large number of <code>CtClass</code>es
@@ -43,9 +43,9 @@ import java.util.Hashtable;
  * Note that <code>getDefault()</code> is a singleton factory.
  * Otherwise, <code>detach()</code> in <code>CtClass</code> should be used
  * to avoid huge memory consumption.
- * <p/>
+ *
  * <p><b><code>ClassPool</code> hierarchy:</b>
- * <p/>
+ *
  * <p><code>ClassPool</code>s can make a parent-child hierarchy as
  * <code>java.lang.ClassLoader</code>s.  If a <code>ClassPool</code> has
  * a parent pool, <code>get()</code> first asks the parent pool to find
@@ -57,709 +57,660 @@ import java.util.Hashtable;
  * @see javassist.CtClass
  * @see javassist.ClassPath
  */
-public class ClassPool
-{
-
-   /**
-    * Determines the search order.
-    * <p/>
-    * <p>If this field is true, <code>get()</code> first searches the
-    * class path associated to this <code>ClassPool</code> and then
-    * the class path associated with the parent <code>ClassPool</code>.
-    * Otherwise, the class path associated with the parent is searched
-    * first.
-    * <p/>
-    * <p>The default value is false.
-    */
-   public boolean childFirstLookup = false;
-
-   protected ClassPoolTail source;
-   protected ClassPool parent;
-   protected Hashtable classes;        // should be synchronous
-
-   /**
-    * Table of registered cflow variables.
-    */
-   private Hashtable cflow = null;     // should be synchronous.
-
-   private static final int INIT_HASH_SIZE = 191;
-
-   /**
-    * Creates a root class pool.  No parent class pool is specified.
-    */
-   public ClassPool()
-   {
-      this(null);
-   }
-
-   /**
-    * Creates a class pool.
-    *
-    * @param parent the parent of this class pool.  If this is a root
-    *               class pool, this parameter must be <code>null</code>.
-    * @see javassist.ClassPool#getDefault()
-    */
-   public ClassPool(ClassPool parent)
-   {
-      this.classes = new Hashtable(INIT_HASH_SIZE);
-      this.source = new ClassPoolTail();
-      this.parent = parent;
-      if (parent == null)
-      {
-         CtClass[] pt = CtClass.primitiveTypes;
-         for (int i = 0; i < pt.length; ++i)
-            classes.put(pt[i].getName(), pt[i]);
-      }
-
-      this.cflow = null;
-   }
-
-   /**
-    * Returns the default class pool.
-    * The returned object is always identical since this method is
-    * a singleton factory.
-    * <p/>
-    * <p>The default class pool searches the system search path,
-    * which usually includes the platform library, extension
-    * libraries, and the search path specified by the
-    * <code>-classpath</code> option or the <code>CLASSPATH</code>
-    * environment variable.
-    * <p/>
-    * <p>When this method is called for the first time, the default
-    * class pool is created with the following code snippet:
-    * <p/>
-    * <ul><code>ClassPool cp = new ClassPool();
-    * cp.appendSystemPath();
-    * </code></ul>
-    * <p/>
-    * <p>If the default class pool cannot find any class files,
-    * try <code>ClassClassPath</code> and <code>LoaderClassPath</code>.
-    *
-    * @see ClassClassPath
-    * @see LoaderClassPath
-    */
-   public static synchronized ClassPool getDefault()
-   {
-      if (defaultPool == null)
-      {
-         defaultPool = new ClassPool(null);
-         defaultPool.appendSystemPath();
-      }
-
-      return defaultPool;
-   }
-
-   private static ClassPool defaultPool = null;
-
-   /**
-    * Provide a hook so that subclasses can do their own
-    * caching of classes.
-    *
-    * @see #cacheCtClass(String,CtClass)
-    * @see #removeCached(String)
-    */
-   protected CtClass getCached(String classname)
-   {
-      return (CtClass) classes.get(classname);
-   }
-
-   /**
-    * Provides a hook so that subclasses can do their own
-    * caching of classes.
-    *
-    * @see #getCached(String)
-    * @see #removeCached(String,CtClass)
-    */
-   protected void cacheCtClass(String classname, CtClass c)
-   {
-      classes.put(classname, c);
-   }
-
-   /**
-    * Provide a hook so that subclasses can do their own
-    * caching of classes.
-    *
-    * @see #getCached(String)
-    * @see #cacheCtClass(String,CtClass)
-    */
-   protected CtClass removeCached(String classname)
-   {
-      return (CtClass) classes.remove(classname);
-   }
-
-   /**
-    * Returns the class search path.
-    */
-   public String toString()
-   {
-      return source.toString();
-   }
-
-   /**
-    * Records a name that never exists.
-    * For example, a package name can be recorded by this method.
-    * This would improve execution performance
-    * since <code>get()</code> does not search the class path at all
-    * if the given name is an invalid name recorded by this method.
-    * Note that searching the class path takes relatively long time.
-    *
-    * @param name a class name (separeted by dot).
-    */
-   public void recordInvalidClassName(String name)
-   {
-      source.recordInvalidClassName(name);
-   }
-
-   /**
-    * Records the <code>$cflow</code> variable for the field specified
-    * by <code>cname</code> and <code>fname</code>.
-    *
-    * @param name  variable name
-    * @param cname class name
-    * @param fname field name
-    */
-   void recordCflow(String name, String cname, String fname)
-   {
-      if (cflow == null)
-         cflow = new Hashtable();
-
-      cflow.put(name, new Object[]{cname, fname});
-   }
-
-   /**
-    * Undocumented method.  Do not use; internal-use only.
-    *
-    * @param name the name of <code>$cflow</code> variable
-    */
-   public Object[] lookupCflow(String name)
-   {
-      if (cflow == null)
-         cflow = new Hashtable();
-
-      return (Object[]) cflow.get(name);
-   }
-
-   /**
-    * Reads a class file and constructs a <code>CtClass</code>
-    * object with a new name.
-    * This method is useful if you want to generate a new class as a copy
-    * of another class (except the class name).  For example,
-    * <p/>
-    * <ul><pre>
-    * getAndRename("Point", "Pair")
-    * </pre></ul>
-    * <p/>
-    * returns a <code>CtClass</code> object representing <code>Pair</code>
-    * class.  The definition of <code>Pair</code> is the same as that of
-    * <code>Point</code> class except the class name since <code>Pair</code>
-    * is defined by reading <code>Point.class</code>.
-    *
-    * @param orgName the original (fully-qualified) class name
-    * @param newName the new class name
-    */
-   public CtClass getAndRename(String orgName, String newName)
-           throws NotFoundException
-   {
-      CtClass clazz = get0(orgName, false);
-      if (clazz instanceof CtClassType)
-         ((CtClassType) clazz).setClassPool(this);
-
-      clazz.setName(newName);         // indirectly calls
-      // classNameChanged() in this class
-      return clazz;
-   }
-
-   /*
-    * This method is invoked by CtClassType.setName().  It removes a
-    * CtClass object from the hash table and inserts it with the new
-    * name.  Don't delegate to the parent.
-    */
-   synchronized void classNameChanged(String oldname, CtClass clazz)
-   {
-      CtClass c = (CtClass) getCached(oldname);
-      if (c == clazz)             // must check this equation.
-         removeCached(oldname);  // see getAndRename().
-
-      String newName = clazz.getName();
-      checkNotFrozen(newName);
-      cacheCtClass(newName, clazz);
-   }
-
-   /**
-    * Reads a class file from the source and returns a reference
-    * to the <code>CtClass</code>
-    * object representing that class file.  If that class file has been
-    * already read, this method returns a reference to the
-    * <code>CtClass</code> created when that class file was read at the
-    * first time.
-    * <p/>
-    * <p>If <code>classname</code> ends with "[]", then this method
-    * returns a <code>CtClass</code> object for that array type.
-    * <p/>
-    * <p>To obtain an inner class, use "$" instead of "." for separating
-    * the enclosing class name and the inner class name.
-    *
-    * @param classname a fully-qualified class name.
-    */
-   public CtClass get(String classname) throws NotFoundException
-   {
-      CtClass clazz;
-      if (classname == null)
-         clazz = null;
-      else
-         clazz = get0(classname, true);
-
-      if (clazz == null)
-         throw new NotFoundException(classname);
-      else
-      {
-         clazz.incGetCounter();
-         return clazz;
-      }
-   }
-
-   /**
-    * @param useCache     false if the cached CtClass must be ignored.
-    * @param searchParent false if the parent class pool is not searched.
-    * @return null     if the class could not be found.
-    */
-   protected synchronized CtClass get0(String classname, boolean useCache)
-           throws NotFoundException
-   {
-      CtClass clazz = null;
-      if (useCache)
-      {
-         clazz = getCached(classname);
-         if (clazz != null)
+public class ClassPool {
+
+    /**
+     * Determines the search order.
+     *
+     * <p>If this field is true, <code>get()</code> first searches the
+     * class path associated to this <code>ClassPool</code> and then
+     * the class path associated with the parent <code>ClassPool</code>.
+     * Otherwise, the class path associated with the parent is searched
+     * first.
+     *
+     * <p>The default value is false.
+     */
+    public boolean childFirstLookup = false;
+
+    protected ClassPoolTail source;
+    protected ClassPool parent;
+    protected Hashtable classes;        // should be synchronous
+
+    /**
+     * Table of registered cflow variables.
+     */
+    private Hashtable cflow = null;     // should be synchronous.
+
+    private static final int INIT_HASH_SIZE = 191;
+
+    /**
+     * Creates a root class pool.  No parent class pool is specified.
+     */
+    public ClassPool() {
+        this(null);
+    }
+
+    /**
+     * Creates a class pool.
+     *
+     * @param parent    the parent of this class pool.  If this is a root
+     *                  class pool, this parameter must be <code>null</code>.
+     * @see javassist.ClassPool#getDefault()
+     */
+    public ClassPool(ClassPool parent) {
+        this.classes = new Hashtable(INIT_HASH_SIZE);
+        this.source = new ClassPoolTail();
+        this.parent = parent;
+        if (parent == null) {
+            CtClass[] pt = CtClass.primitiveTypes;
+            for (int i = 0; i < pt.length; ++i)
+                classes.put(pt[i].getName(), pt[i]);
+        }
+
+        this.cflow = null;
+    }
+
+    /**
+     * Returns the default class pool.
+     * The returned object is always identical since this method is
+     * a singleton factory.
+     *
+     * <p>The default class pool searches the system search path,
+     * which usually includes the platform library, extension
+     * libraries, and the search path specified by the
+     * <code>-classpath</code> option or the <code>CLASSPATH</code>
+     * environment variable.
+     *
+     * <p>When this method is called for the first time, the default
+     * class pool is created with the following code snippet:
+     *
+     * <ul><code>ClassPool cp = new ClassPool();
+     * cp.appendSystemPath();
+     * </code></ul>
+     *
+     * <p>If the default class pool cannot find any class files,
+     * try <code>ClassClassPath</code> and <code>LoaderClassPath</code>.
+     *
+     * @see ClassClassPath
+     * @see LoaderClassPath
+     */
+    public static synchronized ClassPool getDefault() {
+        if (defaultPool == null) {
+            defaultPool = new ClassPool(null);
+            defaultPool.appendSystemPath();
+        }
+
+        return defaultPool;
+    }
+
+    private static ClassPool defaultPool = null;
+
+    /**
+     * Provide a hook so that subclasses can do their own
+     * caching of classes.
+     *
+     * @see #cacheCtClass(String,CtClass)
+     * @see #removeCached(String)
+     */
+    protected CtClass getCached(String classname) {
+        return (CtClass)classes.get(classname);
+    }
+
+    /**
+     * Provides a hook so that subclasses can do their own
+     * caching of classes.
+     *
+     * @see #getCached(String)
+     * @see #removeCached(String,CtClass)
+     */
+    protected void cacheCtClass(String classname, CtClass c) {
+        classes.put(classname, c);
+    }
+
+    /**
+     * Provide a hook so that subclasses can do their own
+     * caching of classes.
+     *
+     * @see #getCached(String)
+     * @see #cacheCtClass(String,CtClass)
+     */
+    protected CtClass removeCached(String classname) {
+        return (CtClass)classes.remove(classname);
+    }
+
+    /**
+     * Returns the class search path.
+     */
+    public String toString() {
+        return source.toString();
+    }
+
+    /**
+     * Records a name that never exists.
+     * For example, a package name can be recorded by this method.
+     * This would improve execution performance
+     * since <code>get()</code> does not search the class path at all
+     * if the given name is an invalid name recorded by this method.
+     * Note that searching the class path takes relatively long time.
+     *
+     * @param name          a class name (separeted by dot).
+     */
+    public void recordInvalidClassName(String name) {
+        source.recordInvalidClassName(name);
+    }
+
+    /**
+     * Records the <code>$cflow</code> variable for the field specified
+     * by <code>cname</code> and <code>fname</code>.
+     *
+     * @param name      variable name
+     * @param cname     class name
+     * @param fname     field name
+     */
+    void recordCflow(String name, String cname, String fname) {
+        if (cflow == null)
+            cflow = new Hashtable();
+
+        cflow.put(name, new Object[] { cname, fname });
+    }
+
+    /**
+     * Undocumented method.  Do not use; internal-use only.
+     *
+     * @param name      the name of <code>$cflow</code> variable
+     */
+    public Object[] lookupCflow(String name) {
+        if (cflow == null)
+            cflow = new Hashtable();
+
+        return (Object[])cflow.get(name);
+    }
+
+    /**
+     * Reads a class file and constructs a <code>CtClass</code>
+     * object with a new name.
+     * This method is useful if you want to generate a new class as a copy
+     * of another class (except the class name).  For example,
+     *
+     * <ul><pre>
+     * getAndRename("Point", "Pair")
+     * </pre></ul>
+     *
+     * returns a <code>CtClass</code> object representing <code>Pair</code>
+     * class.  The definition of <code>Pair</code> is the same as that of
+     * <code>Point</code> class except the class name since <code>Pair</code>
+     * is defined by reading <code>Point.class</code>.
+     *
+     * @param orgName   the original (fully-qualified) class name
+     * @param newName   the new class name
+     */
+    public CtClass getAndRename(String orgName, String newName)
+        throws NotFoundException
+    {
+        CtClass clazz = get0(orgName, false);
+        if (clazz instanceof CtClassType)
+            ((CtClassType)clazz).setClassPool(this);
+
+        clazz.setName(newName);         // indirectly calls
+                                        // classNameChanged() in this class
+        return clazz;
+    }
+
+    /*
+     * This method is invoked by CtClassType.setName().  It removes a
+     * CtClass object from the hash table and inserts it with the new
+     * name.  Don't delegate to the parent.
+     */
+    synchronized void classNameChanged(String oldname, CtClass clazz) {
+        CtClass c = (CtClass)getCached(oldname);
+        if (c == clazz)             // must check this equation.
+            removeCached(oldname);  // see getAndRename().
+
+        String newName = clazz.getName();
+        checkNotFrozen(newName);
+        cacheCtClass(newName, clazz);
+    }
+
+    /**
+     * Reads a class file from the source and returns a reference
+     * to the <code>CtClass</code>
+     * object representing that class file.  If that class file has been
+     * already read, this method returns a reference to the
+     * <code>CtClass</code> created when that class file was read at the
+     * first time.
+     *
+     * <p>If <code>classname</code> ends with "[]", then this method
+     * returns a <code>CtClass</code> object for that array type.
+     *
+     * <p>To obtain an inner class, use "$" instead of "." for separating
+     * the enclosing class name and the inner class name.
+     *
+     * @param classname         a fully-qualified class name.
+     */
+    public CtClass get(String classname) throws NotFoundException {
+        CtClass clazz;
+        if (classname == null)
+            clazz = null;
+        else
+            clazz = get0(classname, true);
+
+        if (clazz == null)
+            throw new NotFoundException(classname);
+        else {
+            clazz.incGetCounter();
             return clazz;
-      }
+        }
+    }
+
+    /**
+     * @param useCache      false if the cached CtClass must be ignored.
+     * @param searchParent  false if the parent class pool is not searched.
+     * @return null     if the class could not be found.
+     */
+    protected synchronized CtClass get0(String classname, boolean useCache)
+        throws NotFoundException
+    {
+        CtClass clazz = null;
+        if (useCache) {
+            clazz = getCached(classname);
+            if (clazz != null)
+                return clazz;
+        }
+
+        if (!childFirstLookup && parent != null) {
+            clazz = parent.get0(classname, useCache);
+            if (clazz != null)
+                return clazz;
+        }
+
+        clazz = createCtClass(classname, useCache);
+        if (clazz != null) {
+            if (useCache)
+                cacheCtClass(classname, clazz);
 
-      if (!childFirstLookup && parent != null)
-      {
-         clazz = parent.get0(classname, useCache);
-         if (clazz != null)
             return clazz;
-      }
-
-      clazz = createCtClass(classname, useCache);
-      if (clazz != null)
-      {
-         if (useCache)
-            cacheCtClass(classname, clazz);
-
-         return clazz;
-      }
-
-      if (childFirstLookup && parent != null)
-         clazz = parent.get0(classname, useCache);
-
-      return clazz;
-   }
-
-   /**
-    * Creates a CtClass object representing the specified class.
-    * It first examines whether or not the corresponding class
-    * file exists.  If yes, it creates a CtClass object.
-    *
-    * @return null if the class file could not be found.
-    */
-   protected CtClass createCtClass(String classname, boolean useCache)
-   {
-      if (classname.endsWith("[]"))
-      {
-         String base = classname.substring(0, classname.indexOf('['));
-         if ((!useCache || getCached(base) == null) && find(base) == null)
-            return null;
-         else
-            return new CtArray(classname, this);
-      }
-      else if (find(classname) == null)
-         return null;
-      else
-         return new CtClassType(classname, this);
-   }
-
-   /**
-    * Searches the class path to obtain the URL of the class file
-    * specified by classname.  It is also used to determine whether
-    * the class file exists.
-    *
-    * @param classname a fully-qualified class name.
-    * @return null if the class file could not be found.
-    * @see CtClass#getURL()
-    */
-   public URL find(String classname)
-   {
-      return source.find(classname);
-   }
-
-   /*
-    * Is invoked by CtClassType.setName() and methods in this class.
-    * This method throws an exception if the class is already frozen or
-    * if this class pool cannot edit the class since it is in a parent
-    * class pool.
-    */
-   void checkNotFrozen(String classname) throws RuntimeException
-   {
-      CtClass clazz = getCached(classname);
-      if (clazz == null)
-      {
-         if (!childFirstLookup && parent != null)
-         {
-            try
-            {
-               clazz = parent.get0(classname, true);
+        }
+
+        if (childFirstLookup && parent != null)
+            clazz = parent.get0(classname, useCache);
+
+        return clazz;
+    }
+
+    /**
+     * Creates a CtClass object representing the specified class.
+     * It first examines whether or not the corresponding class
+     * file exists.  If yes, it creates a CtClass object.
+     *
+     * @return null if the class file could not be found.
+     */
+    protected CtClass createCtClass(String classname, boolean useCache) {
+        if (classname.endsWith("[]")) {
+            String base = classname.substring(0, classname.indexOf('['));
+            if ((!useCache || getCached(base) == null) && find(base) == null)
+                return null;
+            else
+                return new CtArray(classname, this);
+        }
+        else
+            if (find(classname) == null)
+                return null;
+            else
+                return new CtClassType(classname, this);
+    }
+
+    /**
+     * Searches the class path to obtain the URL of the class file
+     * specified by classname.  It is also used to determine whether
+     * the class file exists.
+     *
+     * @param classname     a fully-qualified class name.
+     * @return null if the class file could not be found.
+     * @see CtClass#getURL()
+     */
+    public URL find(String classname) {
+        return source.find(classname);
+    }
+
+    /*
+     * Is invoked by CtClassType.setName() and methods in this class.
+     * This method throws an exception if the class is already frozen or
+     * if this class pool cannot edit the class since it is in a parent
+     * class pool.
+     */
+    void checkNotFrozen(String classname) throws RuntimeException {
+        CtClass clazz = getCached(classname);
+        if (clazz == null) {
+            if (!childFirstLookup && parent != null) {
+                try {
+                    clazz = parent.get0(classname, true);
+                }
+                catch (NotFoundException e) {}
+                if (clazz != null)
+                    throw new RuntimeException(classname
+                            + " is in a parent ClassPool.  Use the parent.");
             }
-            catch (NotFoundException e)
-            {
+        }
+        else
+            if (clazz.isFrozen())
+                throw new RuntimeException(classname
+                                        + ": frozen class (cannot edit)");
+    }
+
+    /* for CtClassType.getClassFile2().  Don't delegate to the parent.
+     */
+    InputStream openClassfile(String classname) throws NotFoundException {
+        return source.openClassfile(classname);
+    }
+
+    void writeClassfile(String classname, OutputStream out)
+        throws NotFoundException, IOException, CannotCompileException
+    {
+        source.writeClassfile(classname, out);
+    }
+
+    /**
+     * Reads class files from the source and returns an array of
+     * <code>CtClass</code>
+     * objects representing those class files.
+     *
+     * <p>If an element of <code>classnames</code> ends with "[]",
+     * then this method
+     * returns a <code>CtClass</code> object for that array type.
+     *
+     * @param classnames        an array of fully-qualified class name.
+     */
+    public CtClass[] get(String[] classnames) throws NotFoundException {
+        if (classnames == null)
+            return new CtClass[0];
+
+        int num = classnames.length;
+        CtClass[] result = new CtClass[num];
+        for (int i = 0; i < num; ++i)
+            result[i] = get(classnames[i]);
+
+        return result;
+    }
+
+    /**
+     * Reads a class file and obtains a compile-time method.
+     *
+     * @param classname         the class name
+     * @param methodname        the method name
+     * @see CtClass#getDeclaredMethod(String)
+     */
+    public CtMethod getMethod(String classname, String methodname)
+        throws NotFoundException
+    {
+        CtClass c = get(classname);
+        return c.getDeclaredMethod(methodname);
+    }
+
+    /**
+     * Creates a new class (or interface) from the given class file.
+     * If there already exists a class with the same name, the new class
+     * overwrites that previous class.
+     *
+     * <p>This method is used for creating a <code>CtClass</code> object
+     * directly from a class file.  The qualified class name is obtained
+     * from the class file; you do not have to explicitly give the name.
+     *
+     * @param classfile class file.
+     * @throws RuntimeException if there is a frozen class with the
+     *                          the same name.
+     * @see javassist.ByteArrayClassPath
+     */
+    public CtClass makeClass(InputStream classfile)
+        throws IOException, RuntimeException {
+        classfile = new BufferedInputStream(classfile);
+        CtClass clazz = new CtClassType(classfile, this);
+        clazz.checkModify();
+        String classname = clazz.getName();
+        checkNotFrozen(classname);
+        cacheCtClass(classname, clazz);
+        return clazz;
+    }
+
+    /**
+     * Creates a new public class.
+     * If there already exists a class with the same name, the new class
+     * overwrites that previous class.
+     *
+     * @param classname                 a fully-qualified class name.
+     * @throws RuntimeException         if the existing class is frozen.
+     */
+    public CtClass makeClass(String classname) throws RuntimeException {
+        return makeClass(classname, null);
+    }
+
+    /**
+     * Creates a new public class.
+     * If there already exists a class/interface with the same name,
+     * the new class overwrites that previous class.
+     *
+     * @param classname  a fully-qualified class name.
+     * @param superclass the super class.
+     * @throws RuntimeException if the existing class is frozen.
+     */
+    public synchronized CtClass makeClass(String classname, CtClass superclass)
+        throws RuntimeException
+    {
+        checkNotFrozen(classname);
+        CtClass clazz = new CtNewClass(classname, this, false, superclass);
+        cacheCtClass(classname, clazz);
+        return clazz;
+    }
+
+    /**
+     * Creates a new nested class.
+     * This method is called by CtClassType.makeNestedClass().
+     *
+     * @param classname     a fully-qualified class name.
+     * @return      the nested class.
+     */
+    synchronized CtClass makeNestedClass(String classname) {
+        checkNotFrozen(classname);
+        CtClass clazz = new CtNewNestedClass(classname, this, false, null);
+        cacheCtClass(classname, clazz);
+        return clazz;
+    }
+
+    /**
+     * Creates a new public interface.
+     * If there already exists a class/interface with the same name,
+     * the new interface overwrites that previous one.
+     *
+     * @param name          a fully-qualified interface name.
+     * @throws RuntimeException if the existing interface is frozen.
+     */
+    public CtClass makeInterface(String name) throws RuntimeException {
+        return makeInterface(name, null);
+    }
+
+    /**
+     * Creates a new public interface.
+     * If there already exists a class/interface with the same name,
+     * the new interface overwrites that previous one.
+     *
+     * @param name       a fully-qualified interface name.
+     * @param superclass the super interface.
+     * @throws RuntimeException if the existing interface is frozen.
+     */
+    public synchronized CtClass makeInterface(String name, CtClass superclass)
+        throws RuntimeException
+    {
+        checkNotFrozen(name);
+        CtClass clazz = new CtNewClass(name, this, true, superclass);
+        cacheCtClass(name, clazz);
+        return clazz;
+    }
+
+    /**
+     * Appends the system search path to the end of the
+     * search path.  The system search path
+     * usually includes the platform library, extension
+     * libraries, and the search path specified by the
+     * <code>-classpath</code> option or the <code>CLASSPATH</code>
+     * environment variable.
+     *
+     * @return the appended class path.
+     */
+    public ClassPath appendSystemPath() {
+        return source.appendSystemPath();
+    }
+
+    /**
+     * Insert a <code>ClassPath</code> object at the head of the
+     * search path.
+     *
+     * @return the inserted class path.
+     * @see javassist.ClassPath
+     * @see javassist.URLClassPath
+     * @see javassist.ByteArrayClassPath
+     */
+    public ClassPath insertClassPath(ClassPath cp) {
+        return source.insertClassPath(cp);
+    }
+
+    /**
+     * Appends a <code>ClassPath</code> object to the end of the
+     * search path.
+     *
+     * @return the appended class path.
+     * @see javassist.ClassPath
+     * @see javassist.URLClassPath
+     * @see javassist.ByteArrayClassPath
+     */
+    public ClassPath appendClassPath(ClassPath cp) {
+        return source.appendClassPath(cp);
+    }
+
+    /**
+     * Inserts a directory or a jar (or zip) file at the head of the
+     * search path.
+     *
+     * @param pathname      the path name of the directory or jar file.
+     *                      It must not end with a path separator ("/").
+     * @return the inserted class path.
+     * @throws NotFoundException    if the jar file is not found.
+     */
+    public ClassPath insertClassPath(String pathname)
+        throws NotFoundException
+    {
+        return source.insertClassPath(pathname);
+    }
+
+    /**
+     * Appends a directory or a jar (or zip) file to the end of the
+     * search path.
+     *
+     * @param pathname the path name of the directory or jar file.
+     *                 It must not end with a path separator ("/").
+     * @return the appended class path.
+     * @throws NotFoundException if the jar file is not found.
+     */
+    public ClassPath appendClassPath(String pathname)
+        throws NotFoundException
+    {
+        return source.appendClassPath(pathname);
+    }
+
+    /**
+     * Detatches the <code>ClassPath</code> object from the search path.
+     * The detached <code>ClassPath</code> object cannot be added
+     * to the pathagain.
+     */
+    public void removeClassPath(ClassPath cp) {
+        source.removeClassPath(cp);
+    }
+
+    /**
+     * Appends directories and jar files for search.
+     *
+     * <p>The elements of the given path list must be separated by colons
+     * in Unix or semi-colons in Windows.
+     *
+     * @param pathlist      a (semi)colon-separated list of
+     *                      the path names of directories and jar files.
+     *                      The directory name must not end with a path
+     *                      separator ("/").
+     * @throws NotFoundException if a jar file is not found.
+     */
+    public void appendPathList(String pathlist) throws NotFoundException {
+        char sep = File.pathSeparatorChar;
+        int i = 0;
+        for (;;) {
+            int j = pathlist.indexOf(sep, i);
+            if (j < 0) {
+                appendClassPath(pathlist.substring(i));
+                break;
             }
-            if (clazz != null)
-               throw new RuntimeException(classname
-                       + " is in a parent ClassPool.  Use the parent.");
-         }
-      }
-      else if (clazz.isFrozen())
-         throw new RuntimeException(classname +
-                 ": frozen class (cannot edit)");
-   }
-
-   /* for CtClassType.getClassFile2().  Don't delegate to the parent.
-    */
-   InputStream openClassfile(String classname)
-           throws NotFoundException
-   {
-      return source.openClassfile(classname);
-   }
-
-   void writeClassfile(String classname, OutputStream out)
-           throws NotFoundException, IOException, CannotCompileException
-   {
-      source.writeClassfile(classname, out);
-   }
-
-   /**
-    * Reads class files from the source and returns an array of
-    * <code>CtClass</code>
-    * objects representing those class files.
-    * <p/>
-    * <p>If an element of <code>classnames</code> ends with "[]",
-    * then this method
-    * returns a <code>CtClass</code> object for that array type.
-    *
-    * @param classnames an array of fully-qualified class name.
-    */
-   public CtClass[] get(String[] classnames) throws NotFoundException
-   {
-      if (classnames == null)
-         return new CtClass[0];
-
-      int num = classnames.length;
-      CtClass[] result = new CtClass[num];
-      for (int i = 0; i < num; ++i)
-         result[i] = get(classnames[i]);
-
-      return result;
-   }
-
-   /**
-    * Reads a class file and obtains a compile-time method.
-    *
-    * @param classname  the class name
-    * @param methodname the method name
-    * @see CtClass#getDeclaredMethod(String)
-    */
-   public CtMethod getMethod(String classname, String methodname)
-           throws NotFoundException
-   {
-      CtClass c = get(classname);
-      return c.getDeclaredMethod(methodname);
-   }
-
-   /**
-    * Creates a new class (or interface) from the given class file.
-    * If there already exists a class with the same name, the new class
-    * overwrites that previous class.
-    * <p/>
-    * <p>This method is used for creating a <code>CtClass</code> object
-    * directly from a class file.  The qualified class name is obtained
-    * from the class file; you do not have to explicitly give the name.
-    *
-    * @param classfile class file.
-    * @throws RuntimeException if there is a frozen class with the
-    *                          the same name.
-    * @see javassist.ByteArrayClassPath
-    */
-   public CtClass makeClass(InputStream classfile)
-           throws IOException, RuntimeException
-   {
-      classfile = new BufferedInputStream(classfile);
-      CtClass clazz = new CtClassType(classfile, this);
-      clazz.checkModify();
-      String classname = clazz.getName();
-      checkNotFrozen(classname);
-      cacheCtClass(classname, clazz);
-      return clazz;
-   }
-
-   /**
-    * Creates a new public class.
-    * If there already exists a class with the same name, the new class
-    * overwrites that previous class.
-    *
-    * @param classname a fully-qualified class name.
-    * @throws RuntimeException if the existing class is frozen.
-    */
-   public CtClass makeClass(String classname) throws RuntimeException
-   {
-      return makeClass(classname, null);
-   }
-
-   /**
-    * Creates a new public class.
-    * If there already exists a class/interface with the same name,
-    * the new class overwrites that previous class.
-    *
-    * @param classname  a fully-qualified class name.
-    * @param superclass the super class.
-    * @throws RuntimeException if the existing class is frozen.
-    */
-   public synchronized CtClass makeClass(String classname, CtClass superclass)
-           throws RuntimeException
-   {
-      checkNotFrozen(classname);
-      CtClass clazz = new CtNewClass(classname, this, false, superclass);
-      cacheCtClass(classname, clazz);
-      return clazz;
-   }
-
-   /**
-    * Creates a new nested class.
-    * This method is called by CtClassType.makeNestedClass().
-    *
-    * @param classname a fully-qualified class name.
-    * @return the nested class.
-    */
-   synchronized CtClass makeNestedClass(String classname)
-   {
-      checkNotFrozen(classname);
-      CtClass clazz = new CtNewNestedClass(classname, this, false, null);
-      cacheCtClass(classname, clazz);
-      return clazz;
-   }
-
-   /**
-    * Creates a new public interface.
-    * If there already exists a class/interface with the same name,
-    * the new interface overwrites that previous one.
-    *
-    * @param name a fully-qualified interface name.
-    * @throws RuntimeException if the existing interface is frozen.
-    */
-   public CtClass makeInterface(String name) throws RuntimeException
-   {
-      return makeInterface(name, null);
-   }
-
-   /**
-    * Creates a new public interface.
-    * If there already exists a class/interface with the same name,
-    * the new interface overwrites that previous one.
-    *
-    * @param name       a fully-qualified interface name.
-    * @param superclass the super interface.
-    * @throws RuntimeException if the existing interface is frozen.
-    */
-   public synchronized CtClass makeInterface(String name, CtClass superclass)
-           throws RuntimeException
-   {
-      checkNotFrozen(name);
-      CtClass clazz = new CtNewClass(name, this, true, superclass);
-      cacheCtClass(name, clazz);
-      return clazz;
-   }
-
-   /**
-    * Appends the system search path to the end of the
-    * search path.  The system search path
-    * usually includes the platform library, extension
-    * libraries, and the search path specified by the
-    * <code>-classpath</code> option or the <code>CLASSPATH</code>
-    * environment variable.
-    *
-    * @return the appended class path.
-    */
-   public ClassPath appendSystemPath()
-   {
-      return source.appendSystemPath();
-   }
-
-   /**
-    * Insert a <code>ClassPath</code> object at the head of the
-    * search path.
-    *
-    * @return the inserted class path.
-    * @see javassist.ClassPath
-    * @see javassist.URLClassPath
-    * @see javassist.ByteArrayClassPath
-    */
-   public ClassPath insertClassPath(ClassPath cp)
-   {
-      return source.insertClassPath(cp);
-   }
-
-   /**
-    * Appends a <code>ClassPath</code> object to the end of the
-    * search path.
-    *
-    * @return the appended class path.
-    * @see javassist.ClassPath
-    * @see javassist.URLClassPath
-    * @see javassist.ByteArrayClassPath
-    */
-   public ClassPath appendClassPath(ClassPath cp)
-   {
-      return source.appendClassPath(cp);
-   }
-
-   /**
-    * Inserts a directory or a jar (or zip) file at the head of the
-    * search path.
-    *
-    * @param pathname the path name of the directory or jar file.
-    *                 It must not end with a path separator ("/").
-    * @return the inserted class path.
-    * @throws NotFoundException if the jar file is not found.
-    */
-   public ClassPath insertClassPath(String pathname)
-           throws NotFoundException
-   {
-      return source.insertClassPath(pathname);
-   }
-
-   /**
-    * Appends a directory or a jar (or zip) file to the end of the
-    * search path.
-    *
-    * @param pathname the path name of the directory or jar file.
-    *                 It must not end with a path separator ("/").
-    * @return the appended class path.
-    * @throws NotFoundException if the jar file is not found.
-    */
-   public ClassPath appendClassPath(String pathname)
-           throws NotFoundException
-   {
-      return source.appendClassPath(pathname);
-   }
-
-   /**
-    * Detatches the <code>ClassPath</code> object from the search path.
-    * The detached <code>ClassPath</code> object cannot be added
-    * to the pathagain.
-    */
-   public void removeClassPath(ClassPath cp)
-   {
-      source.removeClassPath(cp);
-   }
-
-   /**
-    * Appends directories and jar files for search.
-    * <p/>
-    * <p>The elements of the given path list must be separated by colons
-    * in Unix or semi-colons in Windows.
-    *
-    * @param pathlist a (semi)colon-separated list of
-    *                 the path names of directories and jar files.
-    *                 The directory name must not end with a path
-    *                 separator ("/").
-    * @throws NotFoundException if a jar file is not found.
-    */
-   public void appendPathList(String pathlist) throws NotFoundException
-   {
-      char sep = File.pathSeparatorChar;
-      int i = 0;
-      for (; ;)
-      {
-         int j = pathlist.indexOf(sep, i);
-         if (j < 0)
-         {
-            appendClassPath(pathlist.substring(i));
-            break;
-         }
-         else
-         {
-            appendClassPath(pathlist.substring(i, j));
-            i = j + 1;
-         }
-      }
-   }
-
-   /**
-    * Converts this class to a <code>java.lang.Class</code> object.
-    * Once this method is called, further modifications are not
-    * allowed any more.
-    * To load the class, this method uses the context class loader
-    * of the current thread.  If the program is running on some application
-    * server, the context class loader might be inappropriate to load the
-    * class.
-    * <p/>
-    * <p>This method is provided for convenience.  If you need more
-    * complex functionality, you should write your own class loader.
-    *
-    * @see #toClass(java.lang.ClassLoader)
-    */
-   public Class toClass(CtClass clazz)
-           throws CannotCompileException
-   {
-      return toClass(clazz, Thread.currentThread().getContextClassLoader());
-   }
-
-   /**
-    * Converts this class to a <code>java.lang.Class</code> object.
-    * Once this method is called, further modifications are not allowed
-    * any more.
-    * <p/>
-    * <p>The class file represented by this <code>CtClass</code> is
-    * loaded by the given class loader to construct a
-    * <code>java.lang.Class</code> object.  Since a private method
-    * on the class loader is invoked through the reflection API,
-    * the caller must have permissions to do that.
-    * <p/>
-    * <p>This method is provided for convenience.  If you need more
-    * complex functionality, you should write your own class loader.
-    *
-    * @param loader the class loader used to load this class.
-    */
-   public Class toClass(CtClass ct, ClassLoader loader)
-           throws CannotCompileException
-   {
-      try
-      {
-         byte[] b = ct.toBytecode();
-         Class cl = Class.forName("java.lang.ClassLoader");
-         java.lang.reflect.Method method
-                 = cl.getDeclaredMethod("defineClass",
-                         new Class[]{String.class, byte[].class,
-                                     int.class, int.class});
-         method.setAccessible(true);
-         Object[] args = new Object[]{ct.getName(), b, new Integer(0),
-                                      new Integer(b.length)};
-         Class clazz = (Class) method.invoke(loader, args);
-         method.setAccessible(false);
-         return clazz;
-      }
-      catch (RuntimeException e)
-      {
-         throw e;
-      }
-      catch (java.lang.reflect.InvocationTargetException e)
-      {
-         throw new CannotCompileException(e.getTargetException());
-      }
-      catch (Exception e)
-      {
-         throw new CannotCompileException(e);
-      }
-   }
-
+            else {
+                appendClassPath(pathlist.substring(i, j));
+                i = j + 1;
+            }
+        }
+    }
+
+    /**
+     * Converts the given class to a <code>java.lang.Class</code> object.
+     * Once this method is called, further modifications are not
+     * allowed any more.
+     * To load the class, this method uses the context class loader
+     * of the current thread.  If the program is running on some application
+     * server, the context class loader might be inappropriate to load the
+     * class.
+     *
+     * <p>This method is provided for convenience.  If you need more
+     * complex functionality, you should write your own class loader.
+     *
+     * @see #toClass(CtClass, java.lang.ClassLoader)
+     */
+    public Class toClass(CtClass clazz) throws CannotCompileException {
+        return toClass(clazz, Thread.currentThread().getContextClassLoader());
+    }
+
+    /**
+     * Converts the class to a <code>java.lang.Class</code> object.
+     * Once this method is called, further modifications are not allowed
+     * any more.
+     *
+     * <p>The class file represented by the given <code>CtClass</code> is
+     * loaded by the given class loader to construct a
+     * <code>java.lang.Class</code> object.  Since a private method
+     * on the class loader is invoked through the reflection API,
+     * the caller must have permissions to do that.
+     *
+     * <p>This method is provided for convenience.  If you need more
+     * complex functionality, you should write your own class loader.
+     *
+     * @param loader        the class loader used to load this class.
+     */
+    public Class toClass(CtClass ct, ClassLoader loader)
+        throws CannotCompileException
+    {
+        try {
+            byte[] b = ct.toBytecode();
+            Class cl = Class.forName("java.lang.ClassLoader");
+            java.lang.reflect.Method method =
+                cl.getDeclaredMethod("defineClass",
+                                new Class[] { String.class, byte[].class,
+                                              int.class, int.class });
+            method.setAccessible(true);
+            Object[] args = new Object[] { ct.getName(), b, new Integer(0),
+                                           new Integer(b.length)};
+            Class clazz = (Class)method.invoke(loader, args);
+            method.setAccessible(false);
+            return clazz;
+        }
+        catch (RuntimeException e) {
+            throw e;
+        }
+        catch (java.lang.reflect.InvocationTargetException e) {
+            throw new CannotCompileException(e.getTargetException());
+        }
+        catch (Exception e) {
+            throw new CannotCompileException(e);
+        }
+    }
 }
-
index 5a1805ccdddf23ed1f4f366362a1f5efb65aec18..29512ace24c53cd9e543837250dd2b8d3f5ba23d 100644 (file)
@@ -38,1141 +38,1052 @@ import java.util.Collection;
  *
  * @see ClassPool#get(String)
  */
-public abstract class CtClass
-{
-   protected String qualifiedName;
-
-   /**
-    * The version number of this release.
-    */
-   public static final String version = "3.0 RC1";
-
-   /**
-    * Prints the version number and the copyright notice.
-    * <p/>
-    * <p>The following command invokes this method:
-    * <p/>
-    * <ul><pre>java -jar javassist.jar</pre></ul>
-    */
-   public static void main(String[] args)
-   {
-      System.out.println("Javassist version " + CtClass.version);
-      System.out.println("Copyright (C) 1999-2004 Shigeru Chiba."
-              + " All Rights Reserved.");
-   }
-
-   static final String javaLangObject = "java.lang.Object";
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>boolean</code> type.
-    */
-   public static CtClass booleanType;
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>char</code> type.
-    */
-   public static CtClass charType;
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>byte</code> type.
-    */
-   public static CtClass byteType;
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>short</code> type.
-    */
-   public static CtClass shortType;
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>int</code> type.
-    */
-   public static CtClass intType;
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>long</code> type.
-    */
-   public static CtClass longType;
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>float</code> type.
-    */
-   public static CtClass floatType;
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>double</code> type.
-    */
-   public static CtClass doubleType;
-
-   /**
-    * The <code>CtClass</code> object representing
-    * the <code>void</code> type.
-    */
-   public static CtClass voidType;
-
-   static CtClass[] primitiveTypes;
-
-   static
-   {
-      primitiveTypes = new CtClass[9];
-
-      booleanType = new CtPrimitiveType("boolean", 'Z', "java.lang.Boolean",
-              "booleanValue", "()Z", Opcode.IRETURN,
-              Opcode.T_BOOLEAN, 1);
-      primitiveTypes[0] = booleanType;
-
-      charType = new CtPrimitiveType("char", 'C', "java.lang.Character",
-              "charValue", "()C", Opcode.IRETURN,
-              Opcode.T_CHAR, 1);
-      primitiveTypes[1] = charType;
-
-      byteType = new CtPrimitiveType("byte", 'B', "java.lang.Byte",
-              "byteValue", "()B", Opcode.IRETURN,
-              Opcode.T_BYTE, 1);
-      primitiveTypes[2] = byteType;
-
-      shortType = new CtPrimitiveType("short", 'S', "java.lang.Short",
-              "shortValue", "()S", Opcode.IRETURN,
-              Opcode.T_SHORT, 1);
-      primitiveTypes[3] = shortType;
-
-      intType = new CtPrimitiveType("int", 'I', "java.lang.Integer",
-              "intValue", "()I", Opcode.IRETURN,
-              Opcode.T_INT, 1);
-      primitiveTypes[4] = intType;
-
-      longType = new CtPrimitiveType("long", 'J', "java.lang.Long",
-              "longValue", "()J", Opcode.LRETURN,
-              Opcode.T_LONG, 2);
-      primitiveTypes[5] = longType;
-
-      floatType = new CtPrimitiveType("float", 'F', "java.lang.Float",
-              "floatValue", "()F", Opcode.FRETURN,
-              Opcode.T_FLOAT, 1);
-      primitiveTypes[6] = floatType;
-
-      doubleType = new CtPrimitiveType("double", 'D', "java.lang.Double",
-              "doubleValue", "()D", Opcode.DRETURN,
-              Opcode.T_DOUBLE, 2);
-      primitiveTypes[7] = doubleType;
-
-      voidType = new CtPrimitiveType("void", 'V', "java.lang.Void",
-              null, null, Opcode.RETURN, 0, 0);
-      primitiveTypes[8] = voidType;
-   }
-
-   protected CtClass(String name)
-   {
-      qualifiedName = name;
-   }
-
-   /**
-    * Converts the object to a string.
-    */
-   public String toString()
-   {
-      StringBuffer buf = new StringBuffer(getClass().getName());
-      buf.append("@");
-      buf.append(Integer.toHexString(hashCode()));
-      buf.append("[");
-      extendToString(buf);
-      buf.append("]");
-      return buf.toString();
-   }
-
-   /**
-    * Implemented in subclasses to add to the {@link #toString()} result.
-    * Subclasses should put a space before each token added to the buffer.
-    */
-   protected void extendToString(StringBuffer buffer)
-   {
-      buffer.append(getName());
-   }
-
-   /**
-    * Returns a <code>ClassPool</code> for this class.
-    */
-   public ClassPool getClassPool()
-   {
-      return null;
-   }
-
-   /**
-    * Returns a class file for this class.
-    * <p/>
-    * <p>This method is not available if <code>isFrozen()</code>
-    * is true.
-    */
-   public ClassFile getClassFile()
-   {
-      checkModify();
-      return getClassFile2();
-   }
-
-   /**
-    * Undocumented method.  Do not use; internal-use only.
-    */
-   public ClassFile getClassFile2()
-   {
-      return null;
-   }
-
-   /**
-    * Undocumented method.  Do not use; internal-use only.
-    */
-   public javassist.compiler.AccessorMaker getAccessorMaker()
-   {
-      return null;
-   }
-
-   /**
-    * Returns the uniform resource locator (URL) of the class file.
-    */
-   public URL getURL() throws NotFoundException
-   {
-      throw new NotFoundException(getName());
-   }
-
-   /**
-    * Returns true if the definition of the class has been modified.
-    */
-   public boolean isModified()
-   {
-      return false;
-   }
-
-   /**
-    * Returns true if the class has been loaded or written out
-    * and thus it cannot be modified any more.
-    *
-    * @see #defrost()
-    */
-   public boolean isFrozen()
-   {
-      return true;
-   }
-
-   void freeze()
-   {
-   }
-
-   void checkModify() throws RuntimeException
-   {
-      if (isFrozen())
-         throw new RuntimeException(getName() + " class is frozen");
-
-      // isModified() must return true after this method is invoked.
-   }
-
-   /**
-    * Defrosts the class so that the class can be modified again.
-    * <p/>
-    * <p>To avoid changes that will be never reflected,
-    * the class is frozen to be unmodifiable if it is loaded or
-    * written out.  This method should be called only in a case
-    * that the class will be reloaded or written out later again.
-    * <p/>
-    * <p>If <code>defrost()</code> will be called later, pruning
-    * must be disallowed in advance.
-    *
-    * @see #isFrozen()
-    * @see #stopPruning(boolean)
-    */
-   public void defrost()
-   {
-      throw new RuntimeException("cannot defrost " + getName());
-   }
-
-   /**
-    * Disallows (or allows) pruning the data structure on memory
-    * when this <code>CtClass</code> object is converted into a class file.
-    * Pruning saves memory space since a <code>ClassPool</code> holds
-    * all instances of <code>CtClass</code>
-    * all the time of program execution.
-    * However, pruning discards the data representing part of the
-    * class definition, such as method bodies.
-    * Therefore, once it is pruned, <code>toBytecode()</code>,
-    * <code>writeFile()</code>, or <code>toClass()</code> cannot
-    * be called again.
-    * <p/>
-    * <p>Initially, pruning is allowed.
-    *
-    * @param stop disallow pruning if true.  Otherwise, allow.
-    * @see #detach()
-    * @see #toBytecode()
-    * @see #toClass()
-    * @see #writeFile()
-    */
-   public void stopPruning(boolean stop)
-   {
-   }
-
-   /* Called by get() in ClassPool.
-    * CtClassType overrides this method.
-    */
-   void incGetCounter()
-   {
-   }
-
-   /**
-    * Returns <code>true</code> if this object represents a primitive
-    * Java type: boolean, byte, char, short, int, long, float, double,
-    * or void.
-    */
-   public boolean isPrimitive()
-   {
-      return false;
-   }
-
-   /**
-    * Returns <code>true</code> if this object represents an array type.
-    */
-   public boolean isArray()
-   {
-      return false;
-   }
-
-   /**
-    * If this object represents an array, this method returns the component
-    * type of the array.  Otherwise, it returns <code>null</code>.
-    */
-   public CtClass getComponentType() throws NotFoundException
-   {
-      return null;
-   }
-
-   /**
-    * Returns <code>true</code> if this class extends or implements
-    * <code>clazz</code>.  It also returns <code>true</code> if
-    * this class is the same as <code>clazz</code>.
-    */
-   public boolean subtypeOf(CtClass clazz) throws NotFoundException
-   {
-      return this == clazz || getName().equals(clazz.getName());
-   }
-
-   /**
-    * Obtains the fully-qualified name of the class.
-    */
-   public String getName()
-   {
-      return qualifiedName;
-   }
-
-   /**
-    * Obtains the not-qualified class name.
-    */
-   public final String getSimpleName()
-   {
-      String qname = qualifiedName;
-      int index = qname.lastIndexOf('.');
-      if (index < 0)
-         return qname;
-      else
-         return qname.substring(index + 1);
-   }
-
-   /**
-    * Obtains the package name.  It may be <code>null</code>.
-    */
-   public final String getPackageName()
-   {
-      String qname = qualifiedName;
-      int index = qname.lastIndexOf('.');
-      if (index < 0)
-         return null;
-      else
-         return qname.substring(0, index);
-   }
-
-   /**
-    * Sets the class name
-    *
-    * @param name fully-qualified name
-    */
-   public void setName(String name)
-   {
-      checkModify();
-      if (name != null)
-         qualifiedName = name;
-   }
-
-   /**
-    * Substitutes <code>newName</code> for all occurrences of a class
-    * name <code>oldName</code> in the class file.
-    *
-    * @param oldName replaced class name
-    * @param newName substituted class name
-    */
-   public void replaceClassName(String oldName, String newName)
-   {
-      checkModify();
-   }
-
-   /**
-    * Changes class names appearing in the class file according to the
-    * given <code>map</code>.
-    * <p/>
-    * <p>All the class names appearing in the class file are tested
-    * with <code>map</code> to determine whether each class name is
-    * replaced or not.  Thus this method can be used for collecting
-    * all the class names in the class file.  To do that, first define
-    * a subclass of <code>ClassMap</code> so that <code>get()</code>
-    * records all the given parameters.  Then, make an instance of
-    * that subclass as an empty hash-table.  Finally, pass that instance
-    * to this method.  After this method finishes, that instance would
-    * contain all the class names appearing in the class file.
-    *
-    * @param map the hashtable associating replaced class names
-    *            with substituted names.
-    */
-   public void replaceClassName(ClassMap map)
-   {
-      checkModify();
-   }
-
-   /**
-    * Returns a collection of the names of all the classes
-    * referenced in this class.
-    * That collection includes the name of this class.
-    * <p/>
-    * <p>This method may return <code>null</code>.
-    */
-   public Collection getRefClasses()
-   {
-      ClassFile cf = getClassFile2();
-      if (cf != null)
-      {
-         ClassMap cm = new ClassMap()
-         {
-            public void put(String oldname, String newname)
-            {
-               put0(oldname, newname);
-            }
-
-            public Object get(Object jvmClassName)
-            {
-               String n = toJavaName((String) jvmClassName);
-               put0(n, n);
-               return null;
-            }
-
-            public void fix(String name)
-            {
-            }
-         };
-         cf.renameClass(cm);
-         return cm.values();
-      }
-      else
-         return null;
-   }
-
-   /**
-    * Determines whether this object represents a class or an interface.
-    * It returns <code>true</code> if this object represents an interface.
-    */
-   public boolean isInterface()
-   {
-      return false;
-   }
-
-   /**
-    * Returns the modifiers for this class, encoded in an integer.
-    * For decoding, use <code>javassist.Modifier</code>.
-    *
-    * @see Modifier
-    */
-   public int getModifiers()
-   {
-      return 0;
-   }
-
-   /**
-    * Sets the modifiers.
-    *
-    * @param mod modifiers encoded by
-    *            <code>javassist.Modifier</code>
-    * @see Modifier
-    */
-   public void setModifiers(int mod)
-   {
-      checkModify();
-   }
-
-   /**
-    * Determines whether the class directly or indirectly extends
-    * the given class.  If this class extends a class A and
-    * the class A extends a class B, then subclassof(B) returns true.
-    * <p/>
-    * <p>This method returns true if the given class is identical to
-    * the class represented by this object.
-    */
-   public boolean subclassOf(CtClass superclass)
-   {
-      return false;
-   }
-
-   /**
-    * Obtains the class object representing the superclass of the
-    * class.
-    * It returns null if this object represents the
-    * <code>java.lang.Object</code> class and thus it does not have
-    * the super class.
-    * <p/>
-    * <p>If this object represents an interface, this method
-    * always returns the <code>java.lang.Object</code> class.
-    * To obtain the super interfaces
-    * extended by that interface, call <code>getInterfaces()</code>.
-    */
-   public CtClass getSuperclass() throws NotFoundException
-   {
-      return null;
-   }
-
-   /**
-    * Changes a super class unless this object represents an interface.
-    * The new super class must be compatible with the old one.
-    * <p/>
-    * <p>If this object represents an interface, this method is equivalent
-    * to <code>addInterface()</code>; it appends <code>clazz</code> to
-    * the list of the super interfaces extended by that interface.
-    * Note that an interface can extend multiple super interfaces.
-    */
-   public void setSuperclass(CtClass clazz) throws CannotCompileException
-   {
-      checkModify();
-   }
-
-   /**
-    * Obtains the class objects representing the interfaces implemented
-    * by the class or, if this object represents an interface, the interfaces
-    * extended by that interface.
-    */
-   public CtClass[] getInterfaces() throws NotFoundException
-   {
-      return new CtClass[0];
-   }
-
-   /**
-    * Sets implemented interfaces.  If this object represents an interface,
-    * this method sets the interfaces extended by that interface.
-    *
-    * @param list a list of the <code>CtClass</code> objects
-    *             representing interfaces, or
-    *             <code>null</code> if the class implements
-    *             no interfaces.
-    */
-   public void setInterfaces(CtClass[] list)
-   {
-      checkModify();
-   }
-
-   /**
-    * Adds an interface.
-    *
-    * @param anInterface the added interface.
-    */
-   public void addInterface(CtClass anInterface)
-   {
-      checkModify();
-   }
-
-   /**
-    * If this class is a member class or interface of another class,
-    * then the class enclosing this class is returned.
-    *
-    * @return null if this class is a top-level class.
-    */
-   public CtClass getDeclaringClass() throws NotFoundException
-   {
-      return null;
-   }
-
-   /**
-    * Makes a new nested class.  Making a nested class modifies the
-    * data in this <code>CtClass</code>.
-    * <p/>
-    * <p>The current implementation only supports a static nested class.
-    * <code>isStatic</code> must be true.
-    *
-    * @param name     the simple name of the nested class.
-    * @param isStatic true if the nested class is static.
-    */
-   public CtClass makeNestedClass(String name, boolean isStatic)
-   {
-      throw new RuntimeException(getName() + " is not a class");
-   }
-
-   /**
-    * Returns an array containing <code>CtField</code> objects
-    * representing all the public fields of the class.
-    * That array includes public fields inherited from the
-    * superclasses.
-    */
-   public CtField[] getFields()
-   {
-      return new CtField[0];
-   }
-
-   /**
-    * Returns the field with the specified name.  The returned field
-    * may be a private field declared in a super class or interface.
-    */
-   public CtField getField(String name) throws NotFoundException
-   {
-      throw new NotFoundException(name);
-   }
-
-   /**
-    * @return null     if the specified field is not found.
-    */
-   CtField getField2(String name)
-   {
-      return null;
-   }
-
-   /**
-    * Gets all the fields declared in the class.  The inherited fields
-    * are not included.
-    * <p/>
-    * <p>Note: the result does not include inherited fields.
-    */
-   public CtField[] getDeclaredFields()
-   {
-      return new CtField[0];
-   }
-
-   /**
-    * Retrieves the field with the specified name among the fields
-    * declared in the class.
-    * <p/>
-    * <p>Note: this method does not search the superclasses.
-    */
-   public CtField getDeclaredField(String name) throws NotFoundException
-   {
-      throw new NotFoundException(name);
-   }
-
-   /**
-    * Gets all the constructors and methods declared in the class.
-    */
-   public CtBehavior[] getDeclaredBehaviors()
-   {
-      return new CtBehavior[0];
-   }
-
-   /**
-    * Returns an array containing <code>CtConstructor</code> objects
-    * representing all the public constructors of the class.
-    */
-   public CtConstructor[] getConstructors()
-   {
-      return new CtConstructor[0];
-   }
-
-   /**
-    * Returns the constructor with the given signature,
-    * which is represented by a character string
-    * called method descriptor.
-    * For details of the method descriptor, see the JVM specification
-    * or <code>javassist.bytecode.Descriptor</code>.
-    *
-    * @param desc method descriptor
-    * @see javassist.bytecode.Descriptor
-    */
-   public CtConstructor getConstructor(String desc)
-           throws NotFoundException
-   {
-      throw new NotFoundException("no such a constructor");
-   }
-
-   /**
-    * Gets all the constructors declared in the class.
-    *
-    * @see javassist.CtConstructor
-    */
-   public CtConstructor[] getDeclaredConstructors()
-   {
-      return new CtConstructor[0];
-   }
-
-   /**
-    * Returns a constructor receiving the specified parameters.
-    *
-    * @param params parameter types.
-    */
-   public CtConstructor getDeclaredConstructor(CtClass[] params)
-           throws NotFoundException
-   {
-      String desc = Descriptor.ofConstructor(params);
-      return getConstructor(desc);
-   }
-
-   /**
-    * Gets the class initializer (static constructor)
-    * declared in the class.
-    * This method returns <code>null</code> if
-    * no class initializer is not declared.
-    *
-    * @see #makeClassInitializer()
-    * @see javassist.CtConstructor
-    */
-   public CtConstructor getClassInitializer()
-   {
-      return null;
-   }
-
-   /**
-    * Returns an array containing <code>CtMethod</code> objects
-    * representing all the public methods of the class.
-    * That array includes public methods inherited from the
-    * superclasses.
-    */
-   public CtMethod[] getMethods()
-   {
-      return new CtMethod[0];
-   }
-
-   /**
-    * Returns the method with the given name and signature.
-    * The returned method may be declared in a super class.
-    * The method signature is represented by a character string
-    * called method descriptor,
-    * which is defined in the JVM specification.
-    *
-    * @param name method name
-    * @param desc method descriptor
-    * @see javassist.bytecode.Descriptor
-    */
-   public CtMethod getMethod(String name, String desc)
-           throws NotFoundException
-   {
-      throw new NotFoundException(name);
-   }
-
-   /**
-    * Gets all methods declared in the class.  The inherited methods
-    * are not included.
-    *
-    * @see javassist.CtMethod
-    */
-   public CtMethod[] getDeclaredMethods()
-   {
-      return new CtMethod[0];
-   }
-
-   /**
-    * Retrieves the method with the specified name and parameter types
-    * among the methods declared in the class.
-    * <p/>
-    * <p>Note: this method does not search the superclasses.
-    *
-    * @param name   method name
-    * @param params parameter types
-    * @see javassist.CtMethod
-    */
-   public CtMethod getDeclaredMethod(String name, CtClass[] params)
-           throws NotFoundException
-   {
-      throw new NotFoundException(name);
-   }
-
-   /**
-    * Retrieves the method with the specified name among the methods
-    * declared in the class.  If there are multiple methods with
-    * the specified name, then this method returns one of them.
-    * <p/>
-    * <p>Note: this method does not search the superclasses.
-    *
-    * @see javassist.CtMethod
-    */
-   public CtMethod getDeclaredMethod(String name) throws NotFoundException
-   {
-      throw new NotFoundException(name);
-   }
-
-   /**
-    * Makes an empty class initializer (static constructor).
-    * If the class already includes a class initializer,
-    * this method returns it.
-    *
-    * @see #getClassInitializer()
-    */
-   public CtConstructor makeClassInitializer()
-           throws CannotCompileException
-   {
-      throw new CannotCompileException("not a class");
-   }
-
-   /**
-    * Adds a constructor.  To add a class initializer (static constructor),
-    * call <code>makeClassInitializer()</code>.
-    *
-    * @see #makeClassInitializer()
-    */
-   public void addConstructor(CtConstructor c)
-           throws CannotCompileException
-   {
-      checkModify();
-   }
-
-   /**
-    * Adds a method.
-    */
-   public void addMethod(CtMethod m) throws CannotCompileException
-   {
-      checkModify();
-   }
-
-   /**
-    * Adds a field.
-    * <p/>
-    * <p>The <code>CtField</code> belonging to another
-    * <code>CtClass</code> cannot be directly added to this class.
-    * Only a field created for this class can be added.
-    *
-    * @see javassist.CtField#CtField(CtField,CtClass)
-    */
-   public void addField(CtField f) throws CannotCompileException
-   {
-      addField(f, (CtField.Initializer) null);
-   }
-
-   /**
-    * Adds a field with an initial value.
-    * <p/>
-    * <p>The <code>CtField</code> belonging to another
-    * <code>CtClass</code> cannot be directly added to this class.
-    * Only a field created for this class can be added.
-    * <p/>
-    * <p>The initial value is given as an expression written in Java.
-    * Any regular Java expression can be used for specifying the initial
-    * value.  The followings are examples.
-    * <p/>
-    * <ul><pre>
-    * cc.addField(f, "0")               // the initial value is 0.
-    * cc.addField(f, "i + 1")           // i + 1.
-    * cc.addField(f, "new Point()");    // a Point object.
-    * </pre></ul>
-    * <p/>
-    * <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>.
-    * The type of <code>f</code> is <code>CtField</code>.
-    *
-    * @param init an expression for the initial value.
-    * @see javassist.CtField.Initializer#byExpr(String)
-    * @see javassist.CtField#CtField(CtField,CtClass)
-    */
-   public void addField(CtField f, String init)
-           throws CannotCompileException
-   {
-      checkModify();
-   }
-
-   /**
-    * Adds a field with an initial value.
-    * <p/>
-    * <p>The <code>CtField</code> belonging to another
-    * <code>CtClass</code> cannot be directly added to this class.
-    * Only a field created for this class can be added.
-    * <p/>
-    * <p>For example,
-    * <p/>
-    * <ul><pre>
-    * CtClass cc = ...;
-    * addField(new CtField(CtClass.intType, "i", cc),
-    *          CtField.Initializer.constant(1));
-    * </pre></ul>
-    * <p/>
-    * <p>This code adds an <code>int</code> field named "i".  The
-    * initial value of this field is 1.
-    *
-    * @param init specifies the initial value of the field.
-    * @see javassist.CtField#CtField(CtField,CtClass)
-    */
-   public void addField(CtField f, CtField.Initializer init)
-           throws CannotCompileException
-   {
-      checkModify();
-   }
-
-   /**
-    * Obtains an attribute with the given name.
-    * If that attribute is not found in the class file, this
-    * method returns null.
-    * <p/>
-    * <p>This is a convenient method mainly for obtaining
-    * a user-defined attribute.  For dealing with attributes, see the
-    * <code>javassist.bytecode</code> package.  For example, the following
-    * expression returns all the attributes of a class file.
-    * <p/>
-    * <ul><pre>
-    * getClassFile().getAttributes()
-    * </pre></ul>
-    *
-    * @param name attribute name
-    * @see javassist.bytecode.AttributeInfo
-    */
-   public byte[] getAttribute(String name)
-   {
-      return null;
-   }
-
-   /**
-    * Adds a named attribute.
-    * An arbitrary data (smaller than 64Kb) can be saved in the class
-    * file.  Some attribute name are reserved by the JVM.
-    * The attributes with the non-reserved names are ignored when a
-    * class file is loaded into the JVM.
-    * If there is already an attribute with
-    * the same name, this method substitutes the new one for it.
-    * <p/>
-    * <p>This is a convenient method mainly for adding
-    * a user-defined attribute.  For dealing with attributes, see the
-    * <code>javassist.bytecode</code> package.  For example, the following
-    * expression adds an attribute of a class file.
-    * <p/>
-    * <ul><pre>
-    * getClassFile().addAttribute(info)
-    * </pre></ul>
-    *
-    * @param name attribute name
-    * @param data attribute value
-    * @see javassist.bytecode.AttributeInfo
-    */
-   public void setAttribute(String name, byte[] data)
-   {
-      checkModify();
-   }
-
-   /**
-    * Applies the given converter to all methods and constructors
-    * declared in the class.  This method calls <code>instrument()</code>
-    * on every <code>CtMethod</code> and <code>CtConstructor</code> object
-    * in the class.
-    *
-    * @param converter specifies how to modify.
-    */
-   public void instrument(CodeConverter converter)
-           throws CannotCompileException
-   {
-      checkModify();
-   }
-
-   /**
-    * Modifies the bodies of all methods and constructors
-    * declared in the class.  This method calls <code>instrument()</code>
-    * on every <code>CtMethod</code> and <code>CtConstructor</code> object
-    * in the class.
-    *
-    * @param editor specifies how to modify.
-    */
-   public void instrument(ExprEditor editor)
-           throws CannotCompileException
-   {
-      checkModify();
-   }
-
-   /**
-    * Converts this class to a <code>java.lang.Class</code> object.
-    * Once this method is called, further modifications are not
-    * allowed any more.
-    * To load the class, this method uses the context class loader
-    * of the current thread.  If the program is running on some application
-    * server, the context class loader might be inappropriate to load the
-    * class.
-    * <p/>
-    * <p>This method is provided for convenience.  If you need more
-    * complex functionality, you should write your own class loader.
-    *
-    * @see #toClass(java.lang.ClassLoader)
-    */
-   public Class toClass()
-           throws CannotCompileException
-   {
-      return getClassPool().toClass(this, Thread.currentThread().getContextClassLoader());
-   }
-
-   /**
-    * Converts this class to a <code>java.lang.Class</code> object.
-    * Once this method is called, further modifications are not allowed
-    * any more.
-    * <p/>
-    * <p>The class file represented by this <code>CtClass</code> is
-    * loaded by the given class loader to construct a
-    * <code>java.lang.Class</code> object.  Since a private method
-    * on the class loader is invoked through the reflection API,
-    * the caller must have permissions to do that.
-    * <p/>
-    * <p>This method is provided for convenience.  If you need more
-    * complex functionality, you should write your own class loader.
-    *
-    * @param loader the class loader used to load this class.
-    */
-   public Class toClass(ClassLoader loader)
-           throws CannotCompileException
-   {
-      return getClassPool().toClass(this, loader);
-   }
-
-   /**
-    * Removes this <code>CtClass</code> object from the
-    * <code>ClassPool</code>.
-    * After this method is called, any method cannot be called on the
-    * removed <code>CtClass</code> object.
-    * <p/>
-    * <p>If <code>get()</code> in <code>ClassPool</code> is called
-    * with the name of the removed method,
-    * the <code>ClassPool</code> will read the class file again
-    * and constructs another <code>CtClass</code> object representing
-    * the same class.
-    */
-   public void detach()
-   {
-      ClassPool cp = getClassPool();
-      CtClass obj = cp.removeCached(getName());
-      if (obj != this)
-         cp.cacheCtClass(getName(), obj);
-   }
-
-   /**
-    * Converts this class to a class file.
-    * Once this method is called, further modifications are not
-    * possible any more.
-    *
-    * @return the contents of the class file.
-    */
-   public byte[] toBytecode()
-           throws IOException, CannotCompileException
-   {
-      ByteArrayOutputStream barray = new ByteArrayOutputStream();
-      DataOutputStream out = new DataOutputStream(barray);
-      try
-      {
-         toBytecode(out);
-      }
-      finally
-      {
-         out.close();
-      }
-
-      return barray.toByteArray();
-   }
-
-   /**
-    * Writes a class file represented by this <code>CtClass</code>
-    * object in the current directory.
-    * Once this method is called, further modifications are not
-    * possible any more.
-    */
-   public void writeFile()
-           throws NotFoundException, IOException, CannotCompileException
-   {
-      writeFile(".");
-   }
-
-   /**
-    * Writes a class file represented by this <code>CtClass</code>
-    * object on a local disk.
-    * Once this method is called, further modifications are not
-    * possible any more.
-    *
-    * @param directoryName it must end without a directory separator.
-    */
-   public void writeFile(String directoryName)
-           throws NotFoundException, CannotCompileException, IOException
-   {
-      String classname = getName();
-      String filename = directoryName + File.separatorChar
-              + classname.replace('.', File.separatorChar) + ".class";
-      int pos = filename.lastIndexOf(File.separatorChar);
-      if (pos > 0)
-      {
-         String dir = filename.substring(0, pos);
-         if (!dir.equals("."))
-            new File(dir).mkdirs();
-      }
-
-      DataOutputStream out
-              = new DataOutputStream(new BufferedOutputStream(new DelayedFileOutputStream(filename)));
-      try
-      {
-         toBytecode(out);
-      }
-      finally
-      {
-         out.close();
-      }
-   }
-
-   static class DelayedFileOutputStream extends OutputStream
-   {
-      private FileOutputStream file;
-      private String filename;
-
-      DelayedFileOutputStream(String name)
-      {
-         file = null;
-         filename = name;
-      }
-
-      private void init() throws IOException
-      {
-         if (file == null)
-            file = new FileOutputStream(filename);
-      }
-
-      public void write(int b) throws IOException
-      {
-         init();
-         file.write(b);
-      }
-
-      public void write(byte[] b) throws IOException
-      {
-         init();
-         file.write(b);
-      }
-
-      public void write(byte[] b, int off, int len) throws IOException
-      {
-         init();
-         file.write(b, off, len);
-
-      }
-
-      public void flush() throws IOException
-      {
-         init();
-         file.flush();
-      }
-
-      public void close() throws IOException
-      {
-         init();
-         file.close();
-      }
-   }
-
-   /**
-    * Converts this class to a class file.
-    * Once this method is called, further modifications are not
-    * possible any more.
-    * <p/>
-    * <p>This method dose not close the output stream in the end.
-    *
-    * @param out the output stream that a class file is written to.
-    */
-   public void toBytecode(DataOutputStream out)
-           throws CannotCompileException, IOException
-   {
-      throw new CannotCompileException("not a class");
-   }
+public abstract class CtClass {
+    protected String qualifiedName;
+
+    /**
+     * The version number of this release.
+     */
+    public static final String version = "3.0 RC1";
+
+    /**
+     * Prints the version number and the copyright notice.
+     *
+     * <p>The following command invokes this method:
+     *
+     * <ul><pre>java -jar javassist.jar</pre></ul>
+     */
+    public static void main(String[] args) {
+        System.out.println("Javassist version " + CtClass.version);
+        System.out.println("Copyright (C) 1999-2004 Shigeru Chiba."
+                           + " All Rights Reserved.");
+    }
+
+    static final String javaLangObject = "java.lang.Object";
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>boolean</code> type.
+     */
+    public static CtClass booleanType;
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>char</code> type.
+     */
+    public static CtClass charType;
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>byte</code> type.
+     */
+    public static CtClass byteType;
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>short</code> type.
+     */
+    public static CtClass shortType;
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>int</code> type.
+     */
+    public static CtClass intType;
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>long</code> type.
+     */
+    public static CtClass longType;
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>float</code> type.
+     */
+    public static CtClass floatType;
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>double</code> type.
+     */
+    public static CtClass doubleType;
+
+    /**
+     * The <code>CtClass</code> object representing
+     * the <code>void</code> type.
+     */
+    public static CtClass voidType;
+
+    static CtClass[] primitiveTypes;
+
+    static {
+        primitiveTypes = new CtClass[9];
+
+        booleanType =
+            new CtPrimitiveType("boolean", 'Z', "java.lang.Boolean",
+                                "booleanValue", "()Z", Opcode.IRETURN,
+                                Opcode.T_BOOLEAN, 1);
+        primitiveTypes[0] = booleanType;
+
+        charType = new CtPrimitiveType("char", 'C', "java.lang.Character",
+                                       "charValue", "()C", Opcode.IRETURN,
+                                       Opcode.T_CHAR, 1);
+        primitiveTypes[1] = charType;
+
+        byteType = new CtPrimitiveType("byte", 'B', "java.lang.Byte",
+                                       "byteValue", "()B", Opcode.IRETURN,
+                                       Opcode.T_BYTE, 1);
+        primitiveTypes[2] = byteType;
+
+        shortType = new CtPrimitiveType("short", 'S', "java.lang.Short",
+                                        "shortValue", "()S", Opcode.IRETURN,
+                                        Opcode.T_SHORT, 1);
+        primitiveTypes[3] = shortType;
+
+        intType = new CtPrimitiveType("int", 'I', "java.lang.Integer",
+                                      "intValue", "()I", Opcode.IRETURN,
+                                      Opcode.T_INT, 1);
+        primitiveTypes[4] = intType;
+
+        longType = new CtPrimitiveType("long", 'J', "java.lang.Long",
+                                       "longValue", "()J", Opcode.LRETURN,
+                                       Opcode.T_LONG, 2);
+        primitiveTypes[5] = longType;
+
+        floatType = new CtPrimitiveType("float", 'F', "java.lang.Float",
+                                        "floatValue", "()F", Opcode.FRETURN,
+                                        Opcode.T_FLOAT, 1);
+        primitiveTypes[6] = floatType;
+
+        doubleType = new CtPrimitiveType("double", 'D', "java.lang.Double",
+                                         "doubleValue", "()D", Opcode.DRETURN,
+                                         Opcode.T_DOUBLE, 2);
+        primitiveTypes[7] = doubleType;
+
+        voidType = new CtPrimitiveType("void", 'V', "java.lang.Void",
+                                       null, null, Opcode.RETURN, 0, 0);
+        primitiveTypes[8] = voidType;
+    }
+
+    protected CtClass(String name) {
+        qualifiedName = name;
+    }
+
+    /**
+     * Converts the object to a string.
+     */
+    public String toString() {
+        StringBuffer buf = new StringBuffer(getClass().getName());
+        buf.append("@");
+        buf.append(Integer.toHexString(hashCode()));
+        buf.append("[");
+        extendToString(buf);
+        buf.append("]");
+        return buf.toString();
+    }
+
+    /**
+     * Implemented in subclasses to add to the {@link #toString()} result.
+     * Subclasses should put a space before each token added to the buffer.
+     */
+    protected void extendToString(StringBuffer buffer) {
+        buffer.append(getName());
+    }
+
+    /**
+     * Returns a <code>ClassPool</code> for this class.
+     */
+    public ClassPool getClassPool() { return null; }
+
+    /**
+     * Returns a class file for this class.
+     *
+     * <p>This method is not available if <code>isFrozen()</code>
+     * is true.
+     */
+    public ClassFile getClassFile() {
+        checkModify();
+        return getClassFile2();
+    }
+
+    /**
+     * Undocumented method.  Do not use; internal-use only.
+     */
+    public ClassFile getClassFile2() { return null; }
+
+    /**
+     * Undocumented method.  Do not use; internal-use only.
+     */
+    public javassist.compiler.AccessorMaker getAccessorMaker() {
+        return null;
+    }
+
+    /**
+     * Returns the uniform resource locator (URL) of the class file.
+     */
+    public URL getURL() throws NotFoundException {
+        throw new NotFoundException(getName());
+    }
+
+    /**
+     * Returns true if the definition of the class has been modified.
+     */
+    public boolean isModified() { return false; }
+
+    /**
+     * Returns true if the class has been loaded or written out
+     * and thus it cannot be modified any more.
+     *
+     * @see #defrost()
+     */
+    public boolean isFrozen() { return true; }
+
+    void freeze() {}
+
+    void checkModify() throws RuntimeException {
+        if (isFrozen())
+            throw new RuntimeException(getName() + " class is frozen");
+
+        // isModified() must return true after this method is invoked.
+    }
+
+    /**
+     * Defrosts the class so that the class can be modified again.
+     *
+     * <p>To avoid changes that will be never reflected,
+     * the class is frozen to be unmodifiable if it is loaded or
+     * written out.  This method should be called only in a case
+     * that the class will be reloaded or written out later again.
+     *
+     * <p>If <code>defrost()</code> will be called later, pruning
+     * must be disallowed in advance.
+     *
+     * @see #isFrozen()
+     * @see #stopPruning(boolean)
+     */
+    public void defrost() {
+        throw new RuntimeException("cannot defrost " + getName());
+    }
+
+    /**
+     * Disallows (or allows) pruning the data structure on memory
+     * when this <code>CtClass</code> object is converted into a class file.
+     * Pruning saves memory space since a <code>ClassPool</code> holds
+     * all instances of <code>CtClass</code>
+     * all the time of program execution.
+     * However, pruning discards the data representing part of the
+     * class definition, such as method bodies.
+     * Therefore, once it is pruned, <code>toBytecode()</code>,
+     * <code>writeFile()</code>, or <code>toClass()</code> cannot
+     * be called again.
+     *
+     * <p>Initially, pruning is allowed.
+     *
+     * @param stop      disallow pruning if true.  Otherwise, allow.
+     * @see #detach()
+     * @see #toBytecode()
+     * @see #toClass()
+     * @see #writeFile()
+     */
+    public void stopPruning(boolean stop) {}
+
+    /* Called by get() in ClassPool.
+     * CtClassType overrides this method.
+     */
+    void incGetCounter() {}
+
+    /**
+     * Returns <code>true</code> if this object represents a primitive
+     * Java type: boolean, byte, char, short, int, long, float, double,
+     * or void.
+     */
+    public boolean isPrimitive() { return false; }
+
+    /**
+     * Returns <code>true</code> if this object represents an array type.
+     */
+    public boolean isArray() {
+        return false;
+    }
+
+    /**
+     * If this object represents an array, this method returns the component
+     * type of the array.  Otherwise, it returns <code>null</code>.
+     */
+    public CtClass getComponentType() throws NotFoundException {
+        return null;
+    }
+
+    /**
+     * Returns <code>true</code> if this class extends or implements
+     * <code>clazz</code>.  It also returns <code>true</code> if
+     * this class is the same as <code>clazz</code>.
+     */
+    public boolean subtypeOf(CtClass clazz) throws NotFoundException {
+        return this == clazz || getName().equals(clazz.getName());
+    }
+
+    /**
+     * Obtains the fully-qualified name of the class.
+     */
+    public String getName() { return qualifiedName; }
+
+    /**
+     * Obtains the not-qualified class name.
+     */
+    public final String getSimpleName() {
+        String qname = qualifiedName;
+        int index = qname.lastIndexOf('.');
+        if (index < 0)
+            return qname;
+        else
+            return qname.substring(index + 1);
+    }
+
+    /**
+     * Obtains the package name.  It may be <code>null</code>.
+     */
+    public final String getPackageName() {
+        String qname = qualifiedName;
+        int index = qname.lastIndexOf('.');
+        if (index < 0)
+            return null;
+        else
+            return qname.substring(0, index);
+    }
+
+    /**
+     * Sets the class name
+     *
+     * @param name      fully-qualified name
+     */
+    public void setName(String name) {
+        checkModify();
+        if (name != null)
+            qualifiedName = name;
+    }
+
+    /**
+     * Substitutes <code>newName</code> for all occurrences of a class
+     * name <code>oldName</code> in the class file.
+     *
+     * @param oldName           replaced class name
+     * @param newName           substituted class name
+     */
+    public void replaceClassName(String oldName, String newName) {
+        checkModify();
+    }
+
+    /**
+     * Changes class names appearing in the class file according to the
+     * given <code>map</code>.
+     *
+     * <p>All the class names appearing in the class file are tested
+     * with <code>map</code> to determine whether each class name is
+     * replaced or not.  Thus this method can be used for collecting
+     * all the class names in the class file.  To do that, first define
+     * a subclass of <code>ClassMap</code> so that <code>get()</code>
+     * records all the given parameters.  Then, make an instance of
+     * that subclass as an empty hash-table.  Finally, pass that instance
+     * to this method.  After this method finishes, that instance would
+     * contain all the class names appearing in the class file.
+     *
+     * @param map       the hashtable associating replaced class names
+     *                  with substituted names.
+     */
+    public void replaceClassName(ClassMap map) {
+        checkModify();
+    }
+
+    /**
+     * Returns a collection of the names of all the classes
+     * referenced in this class.
+     * That collection includes the name of this class.
+     *
+     * <p>This method may return <code>null</code>.
+     */
+    public Collection getRefClasses() {
+        ClassFile cf = getClassFile2();
+        if (cf != null) {
+            ClassMap cm = new ClassMap() {
+                public void put(String oldname, String newname) {
+                    put0(oldname, newname);
+                }
+
+                public Object get(Object jvmClassName) {
+                    String n = toJavaName((String)jvmClassName);
+                    put0(n, n);
+                    return null;
+                }
+
+                public void fix(String name) {}
+            };
+            cf.renameClass(cm);
+            return cm.values();
+        }
+        else
+            return null;
+    }
+
+    /**
+     * Determines whether this object represents a class or an interface.
+     * It returns <code>true</code> if this object represents an interface.
+     */
+    public boolean isInterface() {
+        return false;
+    }
+
+    /**
+     * Returns the modifiers for this class, encoded in an integer.
+     * For decoding, use <code>javassist.Modifier</code>.
+     *
+     * @see Modifier
+     */
+    public int getModifiers() {
+        return 0;
+    }
+
+    /**
+     * Sets the modifiers.
+     *
+     * @param mod       modifiers encoded by
+     *                  <code>javassist.Modifier</code>
+     * @see Modifier
+     */
+    public void setModifiers(int mod) {
+        checkModify();
+    }
+
+    /**
+     * Determines whether the class directly or indirectly extends
+     * the given class.  If this class extends a class A and
+     * the class A extends a class B, then subclassof(B) returns true.
+     *
+     * <p>This method returns true if the given class is identical to
+     * the class represented by this object.
+     */
+    public boolean subclassOf(CtClass superclass) {
+        return false;
+    }
+
+    /**
+     * Obtains the class object representing the superclass of the
+     * class.
+     * It returns null if this object represents the
+     * <code>java.lang.Object</code> class and thus it does not have
+     * the super class.
+     *
+     * <p>If this object represents an interface, this method
+     * always returns the <code>java.lang.Object</code> class.
+     * To obtain the super interfaces
+     * extended by that interface, call <code>getInterfaces()</code>.
+     */
+    public CtClass getSuperclass() throws NotFoundException {
+        return null;
+    }
+
+    /**
+     * Changes a super class unless this object represents an interface.
+     * The new super class must be compatible with the old one.
+     *
+     * <p>If this object represents an interface, this method is equivalent
+     * to <code>addInterface()</code>; it appends <code>clazz</code> to
+     * the list of the super interfaces extended by that interface.
+     * Note that an interface can extend multiple super interfaces.
+     */
+    public void setSuperclass(CtClass clazz) throws CannotCompileException {
+        checkModify();
+    }
+
+    /**
+     * Obtains the class objects representing the interfaces implemented
+     * by the class or, if this object represents an interface, the interfaces
+     * extended by that interface.
+     */
+    public CtClass[] getInterfaces() throws NotFoundException {
+        return new CtClass[0];
+    }
+
+    /**
+     * Sets implemented interfaces.  If this object represents an interface,
+     * this method sets the interfaces extended by that interface.
+     *
+     * @param list              a list of the <code>CtClass</code> objects
+     *                          representing interfaces, or
+     *                          <code>null</code> if the class implements
+     *                          no interfaces.
+     */
+    public void setInterfaces(CtClass[] list) {
+        checkModify();
+    }
+
+    /**
+     * Adds an interface.
+     *
+     * @param anInterface       the added interface.
+     */
+    public void addInterface(CtClass anInterface) {
+        checkModify();
+    }
+
+    /**
+     * If this class is a member class or interface of another class,
+     * then the class enclosing this class is returned.
+     *
+     * @return null if this class is a top-level class.
+     */
+    public CtClass getDeclaringClass() throws NotFoundException {
+        return null;
+    }
+
+    /**
+     * Makes a new nested class.  Making a nested class modifies the
+     * data in this <code>CtClass</code>.
+     *
+     * <p>The current implementation only supports a static nested class.
+     * <code>isStatic</code> must be true.
+     *
+     * @param name          the simple name of the nested class.
+     * @param isStatic      true if the nested class is static.
+     */
+    public CtClass makeNestedClass(String name, boolean isStatic) {
+        throw new RuntimeException(getName() + " is not a class");
+    }
+
+    /**
+     * Returns an array containing <code>CtField</code> objects
+     * representing all the public fields of the class.
+     * That array includes public fields inherited from the
+     * superclasses.
+     */
+    public CtField[] getFields() { return new CtField[0]; }
+
+    /**
+     * Returns the field with the specified name.  The returned field
+     * may be a private field declared in a super class or interface.
+     */
+    public CtField getField(String name) throws NotFoundException {
+        throw new NotFoundException(name);
+    }
+
+    /**
+     * @return null     if the specified field is not found.
+     */
+    CtField getField2(String name) { return null; }
+
+    /**
+     * Gets all the fields declared in the class.  The inherited fields
+     * are not included.
+     *
+     * <p>Note: the result does not include inherited fields.
+     */
+    public CtField[] getDeclaredFields() { return new CtField[0]; }
+
+    /**
+     * Retrieves the field with the specified name among the fields
+     * declared in the class.
+     *
+     * <p>Note: this method does not search the superclasses.
+     */
+    public CtField getDeclaredField(String name) throws NotFoundException {
+        throw new NotFoundException(name);
+    }
+
+    /**
+     * Gets all the constructors and methods declared in the class.
+     */
+    public CtBehavior[] getDeclaredBehaviors() {
+        return new CtBehavior[0];
+    }
+
+    /**
+     * Returns an array containing <code>CtConstructor</code> objects
+     * representing all the public constructors of the class.
+     */
+    public CtConstructor[] getConstructors() {
+        return new CtConstructor[0];
+    }
+
+    /**
+     * Returns the constructor with the given signature,
+     * which is represented by a character string
+     * called method descriptor.
+     * For details of the method descriptor, see the JVM specification
+     * or <code>javassist.bytecode.Descriptor</code>.
+     *
+     * @param desc      method descriptor
+     * @see javassist.bytecode.Descriptor
+     */
+    public CtConstructor getConstructor(String desc)
+        throws NotFoundException
+    {
+        throw new NotFoundException("no such a constructor");
+    }
+
+    /**
+     * Gets all the constructors declared in the class.
+     *
+     * @see javassist.CtConstructor
+     */
+    public CtConstructor[] getDeclaredConstructors() {
+        return new CtConstructor[0];
+    }
+
+    /**
+     * Returns a constructor receiving the specified parameters.
+     *
+     * @param params    parameter types.
+     */
+    public CtConstructor getDeclaredConstructor(CtClass[] params)
+        throws NotFoundException
+    {
+        String desc = Descriptor.ofConstructor(params);
+        return getConstructor(desc);
+    }
+
+    /**
+     * Gets the class initializer (static constructor)
+     * declared in the class.
+     * This method returns <code>null</code> if
+     * no class initializer is not declared.
+     *
+     * @see #makeClassInitializer()
+     * @see javassist.CtConstructor
+     */
+    public CtConstructor getClassInitializer() {
+        return null;
+    }
+
+    /**
+     * Returns an array containing <code>CtMethod</code> objects
+     * representing all the public methods of the class.
+     * That array includes public methods inherited from the
+     * superclasses.
+     */
+    public CtMethod[] getMethods() {
+        return new CtMethod[0];
+    }
+
+    /**
+     * Returns the method with the given name and signature.
+     * The returned method may be declared in a super class.
+     * The method signature is represented by a character string
+     * called method descriptor,
+     * which is defined in the JVM specification.
+     *
+     * @param name      method name
+     * @param desc      method descriptor
+     * @see javassist.bytecode.Descriptor
+     */
+    public CtMethod getMethod(String name, String desc)
+        throws NotFoundException
+    {
+        throw new NotFoundException(name);
+    }
+
+    /**
+     * Gets all methods declared in the class.  The inherited methods
+     * are not included.
+     *
+     * @see javassist.CtMethod
+     */
+    public CtMethod[] getDeclaredMethods() {
+        return new CtMethod[0];
+    }
+
+    /**
+     * Retrieves the method with the specified name and parameter types
+     * among the methods declared in the class.
+     *
+     * <p>Note: this method does not search the superclasses.
+     *
+     * @param name              method name
+     * @param params            parameter types
+     * @see javassist.CtMethod
+     */
+    public CtMethod getDeclaredMethod(String name, CtClass[] params)
+        throws NotFoundException
+    {
+        throw new NotFoundException(name);
+    }
+
+    /**
+     * Retrieves the method with the specified name among the methods
+     * declared in the class.  If there are multiple methods with
+     * the specified name, then this method returns one of them.
+     *
+     * <p>Note: this method does not search the superclasses.
+     *
+     * @see javassist.CtMethod
+     */
+    public CtMethod getDeclaredMethod(String name) throws NotFoundException {
+        throw new NotFoundException(name);
+    }
+
+    /**
+     * Makes an empty class initializer (static constructor).
+     * If the class already includes a class initializer,
+     * this method returns it.
+     *
+     * @see #getClassInitializer()
+     */
+    public CtConstructor makeClassInitializer()
+        throws CannotCompileException
+    {
+        throw new CannotCompileException("not a class");
+    }
+
+    /**
+     * Adds a constructor.  To add a class initializer (static constructor),
+     * call <code>makeClassInitializer()</code>.
+     *
+     * @see #makeClassInitializer()
+     */
+    public void addConstructor(CtConstructor c)
+        throws CannotCompileException
+    {
+        checkModify();
+    }
+
+    /**
+     * Adds a method.
+     */
+    public void addMethod(CtMethod m) throws CannotCompileException {
+        checkModify();
+    }
+
+    /**
+     * Adds a field.
+     *
+     * <p>The <code>CtField</code> belonging to another
+     * <code>CtClass</code> cannot be directly added to this class.
+     * Only a field created for this class can be added.
+     *
+     * @see javassist.CtField#CtField(CtField,CtClass)
+     */
+    public void addField(CtField f) throws CannotCompileException {
+        addField(f, (CtField.Initializer)null);
+    }
+
+    /**
+     * Adds a field with an initial value.
+     *
+     * <p>The <code>CtField</code> belonging to another
+     * <code>CtClass</code> cannot be directly added to this class.
+     * Only a field created for this class can be added.
+     *
+     * <p>The initial value is given as an expression written in Java.
+     * Any regular Java expression can be used for specifying the initial
+     * value.  The followings are examples.
+     *
+     * <ul><pre>
+     * cc.addField(f, "0")               // the initial value is 0.
+     * cc.addField(f, "i + 1")           // i + 1.
+     * cc.addField(f, "new Point()");    // a Point object.
+     * </pre></ul>
+     *
+     * <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>.
+     * The type of <code>f</code> is <code>CtField</code>.
+     *
+     * @param init      an expression for the initial value.
+     *
+     * @see javassist.CtField.Initializer#byExpr(String)
+     * @see javassist.CtField#CtField(CtField,CtClass)
+     */
+    public void addField(CtField f, String init)
+        throws CannotCompileException
+    {
+        checkModify();
+    }
+
+    /**
+     * Adds a field with an initial value.
+     *
+     * <p>The <code>CtField</code> belonging to another
+     * <code>CtClass</code> cannot be directly added to this class.
+     * Only a field created for this class can be added.
+     *
+     * <p>For example,
+     *
+     * <ul><pre>
+     * CtClass cc = ...;
+     * addField(new CtField(CtClass.intType, "i", cc),
+     *          CtField.Initializer.constant(1));
+     * </pre></ul>
+     *
+     * <p>This code adds an <code>int</code> field named "i".  The
+     * initial value of this field is 1.
+     *
+     * @param init      specifies the initial value of the field.
+     *
+     * @see javassist.CtField#CtField(CtField,CtClass)
+     */
+    public void addField(CtField f, CtField.Initializer init)
+        throws CannotCompileException
+    {
+        checkModify();
+    }
+
+    /**
+     * Obtains an attribute with the given name.
+     * If that attribute is not found in the class file, this
+     * method returns null.
+     *
+     * <p>This is a convenient method mainly for obtaining
+     * a user-defined attribute.  For dealing with attributes, see the
+     * <code>javassist.bytecode</code> package.  For example, the following
+     * expression returns all the attributes of a class file.
+     *
+     * <ul><pre>
+     * getClassFile().getAttributes()
+     * </pre></ul>
+     *
+     * @param name              attribute name
+     * @see javassist.bytecode.AttributeInfo
+     */
+    public byte[] getAttribute(String name) {
+        return null;
+    }
+
+    /**
+     * Adds a named attribute.
+     * An arbitrary data (smaller than 64Kb) can be saved in the class
+     * file.  Some attribute name are reserved by the JVM.
+     * The attributes with the non-reserved names are ignored when a
+     * class file is loaded into the JVM.
+     * If there is already an attribute with
+     * the same name, this method substitutes the new one for it.
+     *
+     * <p>This is a convenient method mainly for adding
+     * a user-defined attribute.  For dealing with attributes, see the
+     * <code>javassist.bytecode</code> package.  For example, the following
+     * expression adds an attribute of a class file.
+     *
+     * <ul><pre>
+     * getClassFile().addAttribute(info)
+     * </pre></ul>
+     *
+     * @param name      attribute name
+     * @param data      attribute value
+     * @see javassist.bytecode.AttributeInfo
+     */
+    public void setAttribute(String name, byte[] data) {
+        checkModify();
+    }
+
+    /**
+     * Applies the given converter to all methods and constructors
+     * declared in the class.  This method calls <code>instrument()</code>
+     * on every <code>CtMethod</code> and <code>CtConstructor</code> object
+     * in the class.
+     *
+     * @param converter         specifies how to modify.
+     */
+    public void instrument(CodeConverter converter)
+        throws CannotCompileException
+    {
+        checkModify();
+    }
+
+    /**
+     * Modifies the bodies of all methods and constructors
+     * declared in the class.  This method calls <code>instrument()</code>
+     * on every <code>CtMethod</code> and <code>CtConstructor</code> object
+     * in the class.
+     *
+     * @param editor            specifies how to modify.
+     */
+    public void instrument(ExprEditor editor)
+        throws CannotCompileException
+    {
+        checkModify();
+    }
+
+    /**
+     * Converts this class to a <code>java.lang.Class</code> object.
+     * Once this method is called, further modifications are not
+     * allowed any more.
+     * To load the class, this method uses the context class loader
+     * of the current thread.  If the program is running on some application
+     * server, the context class loader might be inappropriate to load the
+     * class.
+     *
+     * <p>This method is provided for convenience.  If you need more
+     * complex functionality, you should write your own class loader.
+     *
+     * <p>Note: this method calls <code>toClass()</code>
+     * in <code>ClassPool</code>.
+     *
+     * @see #toClass(java.lang.ClassLoader)
+     * @see ClassPool#toClass(java.lang.ClassLoader)
+     */
+    public Class toClass() throws CannotCompileException {
+        return getClassPool().toClass(this);
+    }
+
+    /**
+     * Converts this class to a <code>java.lang.Class</code> object.
+     * Once this method is called, further modifications are not allowed
+     * any more.
+     *
+     * <p>The class file represented by this <code>CtClass</code> is
+     * loaded by the given class loader to construct a
+     * <code>java.lang.Class</code> object.  Since a private method
+     * on the class loader is invoked through the reflection API,
+     * the caller must have permissions to do that.
+     *
+     * <p>This method is provided for convenience.  If you need more
+     * complex functionality, you should write your own class loader.
+     *
+     * <p>Note: this method calls <code>toClass()</code>
+     * in <code>ClassPool</code>.
+     *
+     * @param loader        the class loader used to load this class.
+     * @see ClassPool#toClass(CtClass,java.lang.ClassLoader)
+     */
+    public Class toClass(ClassLoader loader)
+        throws CannotCompileException
+    {
+        return getClassPool().toClass(this, loader);
+    }
+
+    /**
+     * Removes this <code>CtClass</code> object from the
+     * <code>ClassPool</code>.
+     * After this method is called, any method cannot be called on the
+     * removed <code>CtClass</code> object.
+     *
+     * <p>If <code>get()</code> in <code>ClassPool</code> is called
+     * with the name of the removed method,
+     * the <code>ClassPool</code> will read the class file again
+     * and constructs another <code>CtClass</code> object representing
+     * the same class.
+     */
+    public void detach() {
+        ClassPool cp = getClassPool();
+        CtClass obj = cp.removeCached(getName());
+        if (obj != this)
+            cp.cacheCtClass(getName(), obj);
+    }
+
+    /**
+     * Converts this class to a class file.
+     * Once this method is called, further modifications are not
+     * possible any more.
+     *
+     * @return the contents of the class file.
+     */
+    public byte[] toBytecode() throws IOException, CannotCompileException {
+        ByteArrayOutputStream barray = new ByteArrayOutputStream();
+        DataOutputStream out = new DataOutputStream(barray);
+        try {
+            toBytecode(out);
+        }
+        finally {
+            out.close();
+        }
+
+        return barray.toByteArray();
+    }
+
+    /**
+     * Writes a class file represented by this <code>CtClass</code>
+     * object in the current directory.
+     * Once this method is called, further modifications are not
+     * possible any more.
+     */
+    public void writeFile()
+        throws NotFoundException, IOException, CannotCompileException
+    {
+        writeFile(".");
+    }
+
+    /**
+     * Writes a class file represented by this <code>CtClass</code>
+     * object on a local disk.
+     * Once this method is called, further modifications are not
+     * possible any more.
+     *
+     * @param directoryName     it must end without a directory separator.
+     */
+    public void writeFile(String directoryName)
+        throws NotFoundException, CannotCompileException, IOException
+    {
+        String classname = getName();
+        String filename = directoryName + File.separatorChar
+            + classname.replace('.', File.separatorChar) + ".class";
+        int pos = filename.lastIndexOf(File.separatorChar);
+        if (pos > 0) {
+            String dir = filename.substring(0, pos);
+            if (!dir.equals("."))
+                new File(dir).mkdirs();
+        }
+
+        DataOutputStream out
+            = new DataOutputStream(new BufferedOutputStream(
+                                new DelayedFileOutputStream(filename)));
+        try {
+            toBytecode(out);
+        }
+        finally {
+            out.close();
+        }
+    }
+
+    static class DelayedFileOutputStream extends OutputStream {
+        private FileOutputStream file;
+        private String filename;
+
+        DelayedFileOutputStream(String name) {
+            file = null;
+            filename = name;
+        }
+
+        private void init() throws IOException {
+            if (file == null)
+                file = new FileOutputStream(filename);
+        }
+
+        public void write(int b) throws IOException {
+            init();
+            file.write(b);
+        }
+
+        public void write(byte[] b) throws IOException {
+            init();
+            file.write(b);
+        }
+
+        public void write(byte[] b, int off, int len) throws IOException {
+            init();
+            file.write(b, off, len);
+
+        }
+
+        public void flush() throws IOException {
+            init();
+            file.flush();
+        }
+
+        public void close() throws IOException {
+            init();
+            file.close();
+        }
+    }
+
+    /**
+     * Converts this class to a class file.
+     * Once this method is called, further modifications are not
+     * possible any more.
+     *
+     * <p>This method dose not close the output stream in the end.
+     *
+     * @param out       the output stream that a class file is written to.
+     */
+    public void toBytecode(DataOutputStream out)
+        throws CannotCompileException, IOException
+    {
+        throw new CannotCompileException("not a class");
+    }
 }
index 177f772db473033966aec9bc81a7c05bf07dd1ee..5b249a42616260a3b278c875fb088e24284db5f6 100644 (file)
@@ -47,1235 +47,1067 @@ import java.util.List;
 /**
  * Class types.
  */
-class CtClassType extends CtClass
-{
-   ClassPool classPool;
-   boolean wasChanged;
-   private boolean wasFrozen;
-   boolean wasPruned;
-   ClassFile classfile;
-
-   private CtField fieldsCache;
-   private CtConstructor constructorsCache;
-   private CtConstructor classInitializerCache;
-   private CtMethod methodsCache;
-
-   private AccessorMaker accessors;
-
-   private FieldInitLink fieldInitializers;
-   private Hashtable hiddenMethods;    // must be synchronous
-   private int uniqueNumberSeed;
-
-   private boolean doPruning = false;
-   int getCounter;
-   private static int readCounter = 0;
-   private static final int READ_THRESHOLD = 100;  // see getClassFile2()
-
-   CtClassType(String name, ClassPool cp)
-   {
-      super(name);
-      classPool = cp;
-      wasChanged = wasFrozen = wasPruned = false;
-      classfile = null;
-      accessors = null;
-      fieldInitializers = null;
-      hiddenMethods = null;
-      uniqueNumberSeed = 0;
-      eraseCache();
-      getCounter = 0;
-   }
-
-   CtClassType(InputStream ins, ClassPool cp) throws IOException
-   {
-      this((String) null, cp);
-      classfile = new ClassFile(new DataInputStream(ins));
-      qualifiedName = classfile.getName();
-   }
-
-   protected void extendToString(StringBuffer buffer)
-   {
-      if (wasChanged)
-         buffer.append("changed ");
-
-      if (wasFrozen)
-         buffer.append("frozen ");
-
-      if (wasPruned)
-         buffer.append("pruned ");
-
-      buffer.append(Modifier.toString(getModifiers()));
-      buffer.append(" class ");
-      buffer.append(getName());
-
-      try
-      {
-         CtClass ext = getSuperclass();
-         if (ext != null)
-         {
-            String name = ext.getName();
-            if (!name.equals("java.lang.Object"))
-               buffer.append(" extends " + ext.getName());
-         }
-      }
-      catch (NotFoundException e)
-      {
-         buffer.append(" extends ??");
-      }
-
-      try
-      {
-         CtClass[] intf = getInterfaces();
-         if (intf.length > 0)
-            buffer.append(" implements ");
-
-         for (int i = 0; i < intf.length; ++i)
-         {
-            buffer.append(intf[i].getName());
-            buffer.append(", ");
-         }
-      }
-      catch (NotFoundException e)
-      {
-         buffer.append(" extends ??");
-      }
-
-      CtField field = getFieldsCache();
-      buffer.append(" fields=");
-      while (field != null)
-      {
-         buffer.append(field);
-         buffer.append(", ");
-         field = field.next;
-      }
-
-      CtConstructor c = getConstructorsCache();
-      buffer.append(" constructors=");
-      while (c != null)
-      {
-         buffer.append(c);
-         buffer.append(", ");
-         c = c.next;
-      }
-
-      CtMethod m = getMethodsCache();
-      buffer.append(" methods=");
-      while (m != null)
-      {
-         buffer.append(m);
-         buffer.append(", ");
-         m = m.next;
-      }
-   }
-
-   protected void eraseCache()
-   {
-      fieldsCache = null;
-      constructorsCache = null;
-      classInitializerCache = null;
-      methodsCache = null;
-   }
-
-   public AccessorMaker getAccessorMaker()
-   {
-      if (accessors == null)
-         accessors = new AccessorMaker(this);
-
-      return accessors;
-   }
-
-   public ClassFile getClassFile2()
-   {
-      if (classfile != null)
-         return classfile;
-
-      if (readCounter++ > READ_THRESHOLD)
-      {
-         doCompaction();
-         readCounter = 0;
-      }
-
-      InputStream fin = null;
-      try
-      {
-         fin = classPool.openClassfile(getName());
-         if (fin == null)
-            throw new NotFoundException(getName());
-
-         fin = new BufferedInputStream(fin);
-         classfile = new ClassFile(new DataInputStream(fin));
-         return classfile;
-      }
-      catch (NotFoundException e)
-      {
-         throw new RuntimeException(e.toString());
-      }
-      catch (IOException e)
-      {
-         throw new RuntimeException(e.toString());
-      }
-      finally
-      {
-         if (fin != null)
-            try
-            {
-               fin.close();
+class CtClassType extends CtClass {
+    ClassPool classPool;
+    boolean wasChanged;
+    private boolean wasFrozen;
+    boolean wasPruned;
+    ClassFile classfile;
+
+    private CtField fieldsCache;
+    private CtConstructor constructorsCache;
+    private CtConstructor classInitializerCache;
+    private CtMethod methodsCache;
+
+    private AccessorMaker accessors;
+
+    private FieldInitLink fieldInitializers;
+    private Hashtable hiddenMethods;    // must be synchronous
+    private int uniqueNumberSeed;
+
+    private boolean doPruning = false;
+    int getCounter;
+    private static int readCounter = 0;
+    private static final int READ_THRESHOLD = 100;  // see getClassFile2()
+
+    CtClassType(String name, ClassPool cp) {
+        super(name);
+        classPool = cp;
+        wasChanged = wasFrozen = wasPruned = false;
+        classfile = null;
+        accessors = null;
+        fieldInitializers = null;
+        hiddenMethods = null;
+        uniqueNumberSeed = 0;
+        eraseCache();
+        getCounter = 0;
+    }
+
+    CtClassType(InputStream ins, ClassPool cp) throws IOException {
+        this((String)null, cp);
+        classfile = new ClassFile(new DataInputStream(ins));
+        qualifiedName = classfile.getName();
+    }
+
+    protected void extendToString(StringBuffer buffer) {
+        if (wasChanged)
+            buffer.append("changed ");
+
+        if (wasFrozen)
+            buffer.append("frozen ");
+
+        if (wasPruned)
+            buffer.append("pruned ");
+
+        buffer.append(Modifier.toString(getModifiers()));
+        buffer.append(" class ");
+        buffer.append(getName());
+
+        try {
+            CtClass ext = getSuperclass();
+            if (ext != null) {
+                String name = ext.getName();
+                if (!name.equals("java.lang.Object"))
+                    buffer.append(" extends " + ext.getName());
             }
-            catch (IOException e)
-            {
+        }
+        catch (NotFoundException e) {
+            buffer.append(" extends ??");
+        }
+
+        try {
+            CtClass[] intf = getInterfaces();
+            if (intf.length > 0)
+                buffer.append(" implements ");
+
+            for (int i = 0; i < intf.length; ++i) {
+                buffer.append(intf[i].getName());
+                buffer.append(", ");
             }
-      }
-   }
-
-   /* Inherited from CtClass.  Called by get() in ClassPool.
-    *
-    * @see javassist.CtClass#incGetCounter()
-    */
-   void incGetCounter()
-   {
-      ++getCounter;
-   }
-
-   private void doCompaction()
-   {
-      Enumeration e = classPool.classes.elements();
-      while (e.hasMoreElements())
-      {
-         Object obj = e.nextElement();
-         if (obj instanceof CtClassType)
-         {
-            CtClassType cct = (CtClassType) obj;
-            if (cct.getCounter < 2 && !cct.isModified())
-            {
-               cct.eraseCache();
-               cct.classfile = null;
+        }
+        catch (NotFoundException e) {
+            buffer.append(" extends ??");
+        }
+
+        CtField field = getFieldsCache();
+        buffer.append(" fields=");
+        while (field != null) {
+            buffer.append(field);
+            buffer.append(", ");
+            field = field.next;
+        }
+
+        CtConstructor c = getConstructorsCache();
+        buffer.append(" constructors=");
+        while (c != null) {
+            buffer.append(c);
+            buffer.append(", ");
+            c = c.next;
+        }
+
+        CtMethod m = getMethodsCache();
+        buffer.append(" methods=");
+        while (m != null) {
+            buffer.append(m);
+            buffer.append(", ");
+            m = m.next;
+        }
+    }
+
+    protected void eraseCache() {
+        fieldsCache = null;
+        constructorsCache = null;
+        classInitializerCache = null;
+        methodsCache = null;
+    }
+
+    public AccessorMaker getAccessorMaker() {
+        if (accessors == null)
+            accessors = new AccessorMaker(this);
+
+        return accessors;
+    }
+
+    public ClassFile getClassFile2() {
+        if (classfile != null)
+            return classfile;
+
+        if (readCounter++ > READ_THRESHOLD) {
+            doCompaction();
+            readCounter = 0;
+        }
+
+        InputStream fin = null;
+        try {
+            fin = classPool.openClassfile(getName());
+            if (fin == null)
+                throw new NotFoundException(getName());
+
+            fin = new BufferedInputStream(fin);
+            classfile = new ClassFile(new DataInputStream(fin));
+            return classfile;
+        }
+        catch (NotFoundException e) {
+            throw new RuntimeException(e.toString());
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e.toString());
+        }
+        finally {
+            if (fin != null)
+                try {
+                    fin.close();
+                }
+                catch (IOException e) {}
+        }
+    }
+
+    /* Inherited from CtClass.  Called by get() in ClassPool.
+     *
+     * @see javassist.CtClass#incGetCounter()
+     */
+    void incGetCounter() { ++getCounter; }
+
+    private void doCompaction() {
+        Enumeration e = classPool.classes.elements();
+        while (e.hasMoreElements()) {
+            Object obj = e.nextElement();
+            if (obj instanceof CtClassType) {
+                CtClassType cct = (CtClassType)obj;
+                if (cct.getCounter < 2 && !cct.isModified()) {
+                    cct.eraseCache();
+                    cct.classfile = null;
+                }
+
+                cct.getCounter = 0;
             }
+        }
+    }
+
+    public ClassPool getClassPool() { return classPool; }
+
+    void setClassPool(ClassPool cp) { classPool = cp; }
+
+    public URL getURL() throws NotFoundException {
+        URL url = classPool.find(getName());
+        if (url == null)
+            throw new NotFoundException(getName());
+        else
+            return url;
+    }
+
+    public boolean isModified() { return wasChanged; }
 
-            cct.getCounter = 0;
-         }
-      }
-   }
-
-   public ClassPool getClassPool()
-   {
-      return classPool;
-   }
-
-   void setClassPool(ClassPool cp)
-   {
-      classPool = cp;
-   }
-
-   public URL getURL() throws NotFoundException
-   {
-      URL url = classPool.find(getName());
-      if (url == null)
-         throw new NotFoundException(getName());
-      else
-         return url;
-   }
-
-   public boolean isModified()
-   {
-      return wasChanged;
-   }
-
-   public boolean isFrozen()
-   {
-      return wasFrozen;
-   }
-
-   void freeze()
-   {
-      wasFrozen = true;
-   }
-
-   void checkModify() throws RuntimeException
-   {
-      super.checkModify();
-      wasChanged = true;
-   }
-
-   public void defrost()
-   {
-      checkPruned("defrost");
-      wasFrozen = false;
-   }
-
-   public boolean subtypeOf(CtClass clazz) throws NotFoundException
-   {
-      int i;
-      String cname = clazz.getName();
-      if (this == clazz || getName().equals(cname))
-         return true;
-
-      ClassFile file = getClassFile2();
-      String supername = file.getSuperclass();
-      if (supername != null && supername.equals(cname))
-         return true;
-
-      String[] ifs = file.getInterfaces();
-      int num = ifs.length;
-      for (i = 0; i < num; ++i)
-         if (ifs[i].equals(cname))
+    public boolean isFrozen() { return wasFrozen; }
+
+    void freeze() { wasFrozen = true; }
+
+    void checkModify() throws RuntimeException {
+        super.checkModify();
+        wasChanged = true;
+    }
+
+    public void defrost() {
+        checkPruned("defrost");
+        wasFrozen = false;
+    }
+
+    public boolean subtypeOf(CtClass clazz) throws NotFoundException {
+        int i;
+        String cname = clazz.getName();
+        if (this == clazz || getName().equals(cname))
+            return true;
+
+        ClassFile file = getClassFile2();
+        String supername = file.getSuperclass();
+        if (supername != null && supername.equals(cname))
             return true;
 
-      if (supername != null && classPool.get(supername).subtypeOf(clazz))
-         return true;
+        String[] ifs = file.getInterfaces();
+        int num = ifs.length;
+        for (i = 0; i < num; ++i)
+            if (ifs[i].equals(cname))
+                return true;
 
-      for (i = 0; i < num; ++i)
-         if (classPool.get(ifs[i]).subtypeOf(clazz))
+        if (supername != null && classPool.get(supername).subtypeOf(clazz))
             return true;
 
-      return false;
-   }
-
-   public void setName(String name) throws RuntimeException
-   {
-      String oldname = getName();
-      if (name.equals(oldname))
-         return;
-
-      // check this in advance although classNameChanged() below does.
-      classPool.checkNotFrozen(name);
-      ClassFile cf = getClassFile2();
-      super.setName(name);
-      cf.setName(name);
-      eraseCache();
-      classPool.classNameChanged(oldname, this);
-   }
-
-   public void replaceClassName(ClassMap classnames)
-           throws RuntimeException
-   {
-      String oldClassName = getName();
-      String newClassName
-              = (String) classnames.get(Descriptor.toJvmName(oldClassName));
-      if (newClassName != null)
-      {
-         newClassName = Descriptor.toJavaName(newClassName);
-         // check this in advance although classNameChanged() below does.
-         classPool.checkNotFrozen(newClassName);
-      }
-
-      super.replaceClassName(classnames);
-      ClassFile cf = getClassFile2();
-      cf.renameClass(classnames);
-      eraseCache();
-
-      if (newClassName != null)
-      {
-         super.setName(newClassName);
-         classPool.classNameChanged(oldClassName, this);
-      }
-   }
-
-   public void replaceClassName(String oldname, String newname)
-           throws RuntimeException
-   {
-      String thisname = getName();
-      if (thisname.equals(oldname))
-         setName(newname);
-      else
-      {
-         super.replaceClassName(oldname, newname);
-         getClassFile2().renameClass(oldname, newname);
-         eraseCache();
-      }
-   }
-
-   public boolean isInterface()
-   {
-      return Modifier.isInterface(getModifiers());
-   }
-
-   public int getModifiers()
-   {
-      int acc = getClassFile2().getAccessFlags();
-      acc = AccessFlag.clear(acc, AccessFlag.SUPER);
-      return AccessFlag.toModifier(acc);
-   }
-
-   public void setModifiers(int mod)
-   {
-      checkModify();
-      int acc = AccessFlag.of(mod) | AccessFlag.SUPER;
-      getClassFile2().setAccessFlags(acc);
-   }
-
-   public boolean subclassOf(CtClass superclass)
-   {
-      if (superclass == null)
-         return false;
-
-      String superName = superclass.getName();
-      CtClass curr = this;
-      try
-      {
-         while (curr != null)
-         {
-            if (curr.getName().equals(superName))
-               return true;
-
-            curr = curr.getSuperclass();
-         }
-      }
-      catch (Exception ignored)
-      {
-      }
-      return false;
-   }
-
-   public CtClass getSuperclass() throws NotFoundException
-   {
-      String supername = getClassFile2().getSuperclass();
-      if (supername == null)
-         return null;
-      else
-         return classPool.get(supername);
-   }
-
-   public void setSuperclass(CtClass clazz) throws CannotCompileException
-   {
-      checkModify();
-      if (isInterface())
-         addInterface(clazz);
-      else
-         getClassFile2().setSuperclass(clazz.getName());
-   }
-
-   public CtClass[] getInterfaces() throws NotFoundException
-   {
-      String[] ifs = getClassFile2().getInterfaces();
-      int num = ifs.length;
-      CtClass[] ifc = new CtClass[num];
-      for (int i = 0; i < num; ++i)
-         ifc[i] = classPool.get(ifs[i]);
-
-      return ifc;
-   }
-
-   public void setInterfaces(CtClass[] list)
-   {
-      checkModify();
-      String[] ifs;
-      if (list == null)
-         ifs = new String[0];
-      else
-      {
-         int num = list.length;
-         ifs = new String[num];
-         for (int i = 0; i < num; ++i)
-            ifs[i] = list[i].getName();
-      }
-
-      getClassFile2().setInterfaces(ifs);
-   }
-
-   public void addInterface(CtClass anInterface)
-   {
-      checkModify();
-      if (anInterface != null)
-         getClassFile2().addInterface(anInterface.getName());
-   }
-
-   public CtClass getDeclaringClass() throws NotFoundException
-   {
-      ClassFile cf = getClassFile2();
-      InnerClassesAttribute ica = (InnerClassesAttribute) cf.getAttribute(InnerClassesAttribute.tag);
-      if (ica == null)
-         return null;
-
-      String name = getName();
-      int n = ica.tableLength();
-      for (int i = 0; i < n; ++i)
-         if (name.equals(ica.innerClass(i)))
-            return classPool.get(ica.outerClass(i));
-
-      return null;
-   }
-
-   public CtClass makeNestedClass(String name, boolean isStatic)
-   {
-      if (!isStatic)
-         throw new RuntimeException("sorry, only nested static class is supported");
-
-      checkModify();
-      CtClass c = classPool.makeNestedClass(getName() + "$" + name);
-      ClassFile cf = getClassFile2();
-      InnerClassesAttribute ica = (InnerClassesAttribute) cf.getAttribute(InnerClassesAttribute.tag);
-      if (ica == null)
-      {
-         ica = new InnerClassesAttribute(cf.getConstPool());
-         cf.addAttribute(ica);
-      }
-
-      ica.append(c.getName(), this.getName(), name, AccessFlag.STATIC);
-      ClassFile cf2 = c.getClassFile2();
-      cf2.addAttribute(ica.copy(cf2.getConstPool(), null));
-      return c;
-   }
-
-   public CtField[] getFields()
-   {
-      ArrayList alist = new ArrayList();
-      getFields(alist, this);
-      return (CtField[]) alist.toArray(new CtField[alist.size()]);
-   }
-
-   private static void getFields(ArrayList alist, CtClass cc)
-   {
-      int i, num;
-      if (cc == null)
-         return;
-
-      try
-      {
-         getFields(alist, cc.getSuperclass());
-      }
-      catch (NotFoundException e)
-      {
-      }
-
-      try
-      {
-         CtClass[] ifs = cc.getInterfaces();
-         num = ifs.length;
-         for (i = 0; i < num; ++i)
-            getFields(alist, ifs[i]);
-      }
-      catch (NotFoundException e)
-      {
-      }
-
-      CtField cf = ((CtClassType) cc).getFieldsCache();
-      while (cf != null)
-      {
-         if (Modifier.isPublic(cf.getModifiers()))
-            alist.add(cf);
-
-         cf = cf.next;
-      }
-   }
-
-   public CtField getField(String name) throws NotFoundException
-   {
-      CtField f = getField2(name);
-      if (f == null)
-         throw new NotFoundException("field: " + name + " in " + getName());
-      else
-         return f;
-   }
-
-   CtField getField2(String name)
-   {
-      CtField df = getDeclaredField2(name);
-      if (df != null)
-         return df;
-
-      try
-      {
-         CtClass[] ifs = getInterfaces();
-         int num = ifs.length;
-         for (int i = 0; i < num; ++i)
-         {
-            CtField f = ifs[i].getField2(name);
-            if (f != null)
-               return f;
-         }
-
-         CtClass s = getSuperclass();
-         if (s != null)
-            return s.getField2(name);
-      }
-      catch (NotFoundException e)
-      {
-      }
-      return null;
-   }
-
-   public CtField[] getDeclaredFields()
-   {
-      CtField cf = getFieldsCache();
-      int num = CtField.count(cf);
-      CtField[] cfs = new CtField[num];
-      int i = 0;
-      while (cf != null)
-      {
-         cfs[i++] = cf;
-         cf = cf.next;
-      }
-
-      return cfs;
-   }
-
-   protected CtField getFieldsCache()
-   {
-      if (fieldsCache == null)
-      {
-         List list = getClassFile2().getFields();
-         int n = list.size();
-         for (int i = 0; i < n; ++i)
-         {
-            FieldInfo finfo = (FieldInfo) list.get(i);
-            fieldsCache = CtField.append(fieldsCache,
-                    new CtField(finfo, this));
-         }
-      }
-
-      return fieldsCache;
-   }
-
-   public CtField getDeclaredField(String name) throws NotFoundException
-   {
-      CtField f = getDeclaredField2(name);
-      if (f == null)
-         throw new NotFoundException("field: " + name + " in " + getName());
-      else
-         return f;
-   }
-
-   private CtField getDeclaredField2(String name)
-   {
-      CtField cf = getFieldsCache();
-      while (cf != null)
-      {
-         if (cf.getName().equals(name))
-            return cf;
-
-         cf = cf.next;
-      }
-
-      return null;
-   }
-
-   public CtBehavior[] getDeclaredBehaviors()
-   {
-      CtConstructor cc = getConstructorsCache();
-      CtMethod cm = getMethodsCache();
-      int num = CtMethod.count(cm) + CtConstructor.count(cc);
-      CtBehavior[] cb = new CtBehavior[num];
-      int i = 0;
-      while (cc != null)
-      {
-         cb[i++] = cc;
-         cc = cc.next;
-      }
-
-      while (cm != null)
-      {
-         cb[i++] = cm;
-         cm = cm.next;
-      }
-
-      return cb;
-   }
-
-   public CtConstructor[] getConstructors()
-   {
-      CtConstructor[] cons = getDeclaredConstructors();
-      if (cons.length == 0)
-         return cons;
-
-      int n = 0;
-      int i = cons.length;
-      while (--i >= 0)
-         if (Modifier.isPublic(cons[i].getModifiers()))
-            ++n;
-
-      CtConstructor[] result = new CtConstructor[n];
-      n = 0;
-      i = cons.length;
-      while (--i >= 0)
-      {
-         CtConstructor c = cons[i];
-         if (Modifier.isPublic(c.getModifiers()))
-            result[n++] = c;
-      }
-
-      return result;
-   }
-
-   public CtConstructor getConstructor(String desc)
-           throws NotFoundException
-   {
-      CtConstructor cc = getConstructorsCache();
-      while (cc != null)
-      {
-         if (cc.getMethodInfo2().getDescriptor().equals(desc))
-            return cc;
-
-         cc = cc.next;
-      }
-
-      return super.getConstructor(desc);
-   }
-
-   public CtConstructor[] getDeclaredConstructors()
-   {
-      CtConstructor cc = getConstructorsCache();
-      int num = CtConstructor.count(cc);
-      CtConstructor[] ccs = new CtConstructor[num];
-      int i = 0;
-      while (cc != null)
-      {
-         ccs[i++] = cc;
-         cc = cc.next;
-      }
-
-      return ccs;
-   }
-
-   protected CtConstructor getConstructorsCache()
-   {
-      if (constructorsCache == null)
-      {
-         List list = getClassFile2().getMethods();
-         int n = list.size();
-         for (int i = 0; i < n; ++i)
-         {
-            MethodInfo minfo = (MethodInfo) list.get(i);
-            if (minfo.isConstructor())
-               constructorsCache
-                       = CtConstructor.append(constructorsCache,
-                               new CtConstructor(minfo, this));
-         }
-      }
-
-      return constructorsCache;
-   }
-
-   public CtConstructor getClassInitializer()
-   {
-      if (classInitializerCache == null)
-      {
-         MethodInfo minfo = getClassFile2().getStaticInitializer();
-         if (minfo != null)
-            classInitializerCache = new CtConstructor(minfo, this);
-      }
-
-      return classInitializerCache;
-   }
-
-   public CtMethod[] getMethods()
-   {
-      HashMap h = new HashMap();
-      getMethods0(h, this);
-      return (CtMethod[]) h.values().toArray(new CtMethod[0]);
-   }
-
-   private static void getMethods0(HashMap h, CtClass cc)
-   {
-      try
-      {
-         CtClass[] ifs = cc.getInterfaces();
-         int size = ifs.length;
-         for (int i = 0; i < size; ++i)
-            getMethods0(h, ifs[i]);
-      }
-      catch (NotFoundException e)
-      {
-      }
-
-      try
-      {
-         CtClass s = cc.getSuperclass();
-         if (s != null)
-            getMethods0(h, s);
-      }
-      catch (NotFoundException e)
-      {
-      }
-
-      if (cc instanceof CtClassType)
-      {
-         CtMethod cm = ((CtClassType) cc).getMethodsCache();
-         while (cm != null)
-         {
-            if (Modifier.isPublic(cm.getModifiers()))
-               h.put(cm.getStringRep(), cm);
+        for (i = 0; i < num; ++i)
+            if (classPool.get(ifs[i]).subtypeOf(clazz))
+                return true;
+
+        return false;
+    }
+
+    public void setName(String name) throws RuntimeException {
+        String oldname = getName();
+        if (name.equals(oldname))
+            return;
+
+        // check this in advance although classNameChanged() below does.
+        classPool.checkNotFrozen(name);
+        ClassFile cf = getClassFile2();
+        super.setName(name);
+        cf.setName(name);
+        eraseCache();
+        classPool.classNameChanged(oldname, this);
+    }
+
+    public void replaceClassName(ClassMap classnames)
+        throws RuntimeException
+    {
+        String oldClassName = getName();
+        String newClassName
+            = (String)classnames.get(Descriptor.toJvmName(oldClassName));
+        if (newClassName != null) {
+            newClassName = Descriptor.toJavaName(newClassName);
+            // check this in advance although classNameChanged() below does.
+            classPool.checkNotFrozen(newClassName);
+        }
+
+        super.replaceClassName(classnames);
+        ClassFile cf = getClassFile2();
+        cf.renameClass(classnames);
+        eraseCache();
+
+        if (newClassName != null) {
+            super.setName(newClassName);
+            classPool.classNameChanged(oldClassName, this);
+        }
+    }
+
+    public void replaceClassName(String oldname, String newname)
+        throws RuntimeException
+    {
+        String thisname = getName();
+        if (thisname.equals(oldname))
+            setName(newname);
+        else {
+            super.replaceClassName(oldname, newname);
+            getClassFile2().renameClass(oldname, newname);
+            eraseCache();
+        }
+    }
+
+    public boolean isInterface() {
+        return Modifier.isInterface(getModifiers());
+    }
+
+    public int getModifiers() {
+        int acc = getClassFile2().getAccessFlags();
+        acc = AccessFlag.clear(acc, AccessFlag.SUPER);
+        return AccessFlag.toModifier(acc);
+    }
+
+    public void setModifiers(int mod) {
+        checkModify();
+        int acc = AccessFlag.of(mod) | AccessFlag.SUPER;
+        getClassFile2().setAccessFlags(acc);
+    }
+
+    public boolean subclassOf(CtClass superclass) {
+        if (superclass == null)
+            return false;
+
+        String superName = superclass.getName();
+        CtClass curr = this;
+        try {
+            while (curr != null) {
+                if (curr.getName().equals(superName))
+                    return true;
+
+                curr = curr.getSuperclass();
+            }
+        }
+        catch (Exception ignored) {}
+        return false;
+    }
+
+    public CtClass getSuperclass() throws NotFoundException {
+        String supername = getClassFile2().getSuperclass();
+        if (supername == null)
+            return null;
+        else
+            return classPool.get(supername);
+    }
+
+    public void setSuperclass(CtClass clazz) throws CannotCompileException {
+        checkModify();
+        if (isInterface())
+            addInterface(clazz);
+        else
+            getClassFile2().setSuperclass(clazz.getName());
+    }
+
+    public CtClass[] getInterfaces() throws NotFoundException {
+        String[] ifs = getClassFile2().getInterfaces();
+        int num = ifs.length;
+        CtClass[] ifc = new CtClass[num];
+        for (int i = 0; i < num; ++i)
+            ifc[i] = classPool.get(ifs[i]);
+
+        return ifc;
+    }
+
+    public void setInterfaces(CtClass[] list) {
+        checkModify();
+        String[] ifs;
+        if (list == null)
+            ifs = new String[0];
+        else {
+            int num = list.length;
+            ifs = new String[num];
+            for (int i = 0; i < num; ++i)
+                ifs[i] = list[i].getName();
+        }
+
+        getClassFile2().setInterfaces(ifs);
+    }
+
+    public void addInterface(CtClass anInterface) {
+        checkModify();
+        if (anInterface != null)
+            getClassFile2().addInterface(anInterface.getName());
+    }
+
+    public CtClass getDeclaringClass() throws NotFoundException {
+        ClassFile cf = getClassFile2();
+        InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute(
+                                                InnerClassesAttribute.tag);
+        if (ica == null)
+            return null;
+
+        String name = getName();
+        int n = ica.tableLength();
+        for (int i = 0; i < n; ++i)
+            if (name.equals(ica.innerClass(i)))
+                return classPool.get(ica.outerClass(i));
+
+        return null;
+    }
+
+    public CtClass makeNestedClass(String name, boolean isStatic) {
+        if (!isStatic)
+            throw new RuntimeException(
+                        "sorry, only nested static class is supported");
+
+        checkModify();
+        CtClass c = classPool.makeNestedClass(getName() + "$" + name);
+        ClassFile cf = getClassFile2();
+        InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute(
+                                                InnerClassesAttribute.tag);
+        if (ica == null) {
+            ica = new InnerClassesAttribute(cf.getConstPool());
+            cf.addAttribute(ica);
+        }
+
+        ica.append(c.getName(), this.getName(), name, AccessFlag.STATIC);
+        ClassFile cf2 = c.getClassFile2();
+        cf2.addAttribute(ica.copy(cf2.getConstPool(), null));
+        return c;
+    }
+
+    public CtField[] getFields() {
+        ArrayList alist = new ArrayList();
+        getFields(alist, this);
+        return (CtField[])alist.toArray(new CtField[alist.size()]);
+    }
+
+    private static void getFields(ArrayList alist, CtClass cc) {
+        int i, num;
+        if (cc == null)
+            return;
+
+        try {
+            getFields(alist, cc.getSuperclass());
+        }
+        catch (NotFoundException e) {}
+
+        try {
+            CtClass[] ifs = cc.getInterfaces();
+            num = ifs.length;
+            for (i = 0; i < num; ++i)
+                getFields(alist, ifs[i]);
+        }
+        catch (NotFoundException e) {}
+
+        CtField cf = ((CtClassType)cc).getFieldsCache();
+        while (cf != null) {
+            if (Modifier.isPublic(cf.getModifiers()))
+                alist.add(cf);
+
+            cf = cf.next;
+        }
+    }
+
+    public CtField getField(String name) throws NotFoundException {
+        CtField f = getField2(name);
+        if (f == null)
+            throw new NotFoundException("field: " + name + " in " + getName());
+        else
+            return f;
+    }
+
+    CtField getField2(String name) {
+        CtField df = getDeclaredField2(name);
+        if (df != null)
+            return df;
+
+        try {
+            CtClass[] ifs = getInterfaces();
+            int num = ifs.length;
+            for (int i = 0; i < num; ++i) {
+                CtField f = ifs[i].getField2(name);
+                if (f != null)
+                    return f;
+            }
 
+            CtClass s = getSuperclass();
+            if (s != null)
+                return s.getField2(name);
+        }
+        catch (NotFoundException e) {}
+        return null;
+    }
+
+    public CtField[] getDeclaredFields() {
+        CtField cf = getFieldsCache();
+        int num = CtField.count(cf);
+        CtField[] cfs = new CtField[num];
+        int i = 0;
+        while (cf != null) {
+            cfs[i++] = cf;
+            cf = cf.next;
+        }
+
+        return cfs;
+    }
+
+    protected CtField getFieldsCache() {
+        if (fieldsCache == null) {
+            List list = getClassFile2().getFields();
+            int n = list.size();
+            for (int i = 0; i < n; ++i) {
+                FieldInfo finfo = (FieldInfo)list.get(i);
+                fieldsCache = CtField.append(fieldsCache,
+                                             new CtField(finfo, this));
+            }
+        }
+
+        return fieldsCache;
+    }
+
+    public CtField getDeclaredField(String name) throws NotFoundException {
+        CtField f = getDeclaredField2(name);
+        if (f == null)
+            throw new NotFoundException("field: " + name + " in " + getName());
+        else
+            return f;
+    }
+
+    private CtField getDeclaredField2(String name) {
+        CtField cf = getFieldsCache();
+        while (cf != null) {
+            if (cf.getName().equals(name))
+                return cf;
+
+            cf = cf.next;
+        }
+
+        return null;
+    }
+
+    public CtBehavior[] getDeclaredBehaviors() {
+        CtConstructor cc = getConstructorsCache();
+        CtMethod cm = getMethodsCache();
+        int num = CtMethod.count(cm) + CtConstructor.count(cc);
+        CtBehavior[] cb = new CtBehavior[num];
+        int i = 0;
+        while (cc != null) {
+            cb[i++] = cc;
+            cc = cc.next;
+        }
+
+        while (cm != null) {
+            cb[i++] = cm;
             cm = cm.next;
-         }
-      }
-   }
-
-   public CtMethod getMethod(String name, String desc)
-           throws NotFoundException
-   {
-      CtMethod m = getMethod0(this, name, desc);
-      if (m != null)
-         return m;
-      else
-         throw new NotFoundException(name + "(..) is not found in "
-                 + getName());
-   }
-
-   private static CtMethod getMethod0(CtClass cc,
-                                      String name, String desc)
-   {
-      if (cc instanceof CtClassType)
-      {
-         CtMethod cm = ((CtClassType) cc).getMethodsCache();
-         while (cm != null)
-         {
-            if (cm.getName().equals(name)
+        }
+
+        return cb;
+    }
+
+    public CtConstructor[] getConstructors() {
+        CtConstructor[] cons = getDeclaredConstructors();
+        if (cons.length == 0)
+            return cons;
+
+        int n = 0;
+        int i = cons.length;
+        while (--i >= 0)
+            if (Modifier.isPublic(cons[i].getModifiers()))
+                ++n;
+
+        CtConstructor[] result = new CtConstructor[n];
+        n = 0;
+        i = cons.length;
+        while (--i >= 0) {
+            CtConstructor c = cons[i];
+            if (Modifier.isPublic(c.getModifiers()))
+                result[n++] = c;
+        }
+
+        return result;
+    }
+
+    public CtConstructor getConstructor(String desc)
+        throws NotFoundException
+    {
+        CtConstructor cc = getConstructorsCache();
+        while (cc != null) {
+            if (cc.getMethodInfo2().getDescriptor().equals(desc))
+                return cc;
+
+            cc = cc.next;
+        }
+
+        return super.getConstructor(desc);
+    }
+
+    public CtConstructor[] getDeclaredConstructors() {
+        CtConstructor cc = getConstructorsCache();
+        int num = CtConstructor.count(cc);
+        CtConstructor[] ccs = new CtConstructor[num];
+        int i = 0;
+        while (cc != null) {
+            ccs[i++] = cc;
+            cc = cc.next;
+        }
+
+        return ccs;
+    }
+
+    protected CtConstructor getConstructorsCache() {
+        if (constructorsCache == null) {
+            List list = getClassFile2().getMethods();
+            int n = list.size();
+            for (int i = 0; i < n; ++i) {
+                MethodInfo minfo = (MethodInfo)list.get(i);
+                if (minfo.isConstructor())
+                    constructorsCache
+                        = CtConstructor.append(constructorsCache,
+                                            new CtConstructor(minfo, this));
+            }
+        }
+
+        return constructorsCache;
+    }
+
+    public CtConstructor getClassInitializer() {
+        if (classInitializerCache == null) {
+            MethodInfo minfo = getClassFile2().getStaticInitializer();
+            if (minfo != null)
+                classInitializerCache = new CtConstructor(minfo, this);
+        }
+
+        return classInitializerCache;
+    }
+
+    public CtMethod[] getMethods() {
+        HashMap h = new HashMap();
+        getMethods0(h, this);
+        return (CtMethod[])h.values().toArray(new CtMethod[0]);
+    }
+
+    private static void getMethods0(HashMap h, CtClass cc) {
+        try {
+            CtClass[] ifs = cc.getInterfaces();
+            int size = ifs.length;
+            for (int i = 0; i < size; ++i)
+                getMethods0(h, ifs[i]);
+        }
+        catch (NotFoundException e) {}
+
+        try {
+            CtClass s = cc.getSuperclass();
+            if (s != null)
+                getMethods0(h, s);
+        }
+        catch (NotFoundException e) {}
+
+        if (cc instanceof CtClassType) {
+            CtMethod cm = ((CtClassType)cc).getMethodsCache();
+            while (cm != null) {
+                if (Modifier.isPublic(cm.getModifiers()))
+                    h.put(cm.getStringRep(), cm);
+
+                cm = cm.next;
+            }
+        }
+    }
+
+    public CtMethod getMethod(String name, String desc)
+        throws NotFoundException
+    {
+        CtMethod m = getMethod0(this, name, desc);
+        if (m != null)
+            return m;
+        else
+            throw new NotFoundException(name + "(..) is not found in "
+                                        + getName());
+    }
+
+    private static CtMethod getMethod0(CtClass cc,
+                                       String name, String desc) {
+        if (cc instanceof CtClassType) {
+            CtMethod cm = ((CtClassType)cc).getMethodsCache();
+            while (cm != null) {
+                if (cm.getName().equals(name)
                     && cm.getMethodInfo2().getDescriptor().equals(desc))
-               return cm;
+                    return cm;
 
+                cm = cm.next;
+            }
+        }
+
+        try {
+            CtClass s = cc.getSuperclass();
+            if (s != null) {
+                CtMethod m = getMethod0(s, name, desc);
+                if (m != null)
+                    return m;
+            }
+        }
+        catch (NotFoundException e) {}
+
+        try {
+            CtClass[] ifs = cc.getInterfaces();
+            int size = ifs.length;
+            for (int i = 0; i < size; ++i) {
+                CtMethod m = getMethod0(ifs[i], name, desc);
+                if (m != null)
+                    return m;
+            }
+        }
+        catch (NotFoundException e) {}
+        return null;
+    }
+
+    public CtMethod[] getDeclaredMethods() {
+        CtMethod cm = getMethodsCache();
+        int num = CtMethod.count(cm);
+        CtMethod[] cms = new CtMethod[num];
+        int i = 0;
+        while (cm != null) {
+            cms[i++] = cm;
             cm = cm.next;
-         }
-      }
-
-      try
-      {
-         CtClass s = cc.getSuperclass();
-         if (s != null)
-         {
-            CtMethod m = getMethod0(s, name, desc);
-            if (m != null)
-               return m;
-         }
-      }
-      catch (NotFoundException e)
-      {
-      }
-
-      try
-      {
-         CtClass[] ifs = cc.getInterfaces();
-         int size = ifs.length;
-         for (int i = 0; i < size; ++i)
-         {
-            CtMethod m = getMethod0(ifs[i], name, desc);
-            if (m != null)
-               return m;
-         }
-      }
-      catch (NotFoundException e)
-      {
-      }
-      return null;
-   }
-
-   public CtMethod[] getDeclaredMethods()
-   {
-      CtMethod cm = getMethodsCache();
-      int num = CtMethod.count(cm);
-      CtMethod[] cms = new CtMethod[num];
-      int i = 0;
-      while (cm != null)
-      {
-         cms[i++] = cm;
-         cm = cm.next;
-      }
-
-      return cms;
-   }
-
-   public CtMethod getDeclaredMethod(String name) throws NotFoundException
-   {
-      CtMethod m = getMethodsCache();
-      while (m != null)
-      {
-         if (m.getName().equals(name))
-            return m;
-
-         m = m.next;
-      }
-
-      throw new NotFoundException(name + "(..) is not found in "
-              + getName());
-   }
-
-   public CtMethod getDeclaredMethod(String name, CtClass[] params)
-           throws NotFoundException
-   {
-      String desc = Descriptor.ofParameters(params);
-      CtMethod m = getMethodsCache();
-      while (m != null)
-      {
-         if (m.getName().equals(name)
-                 && m.getMethodInfo2().getDescriptor().startsWith(desc))
-            return m;
+        }
+
+        return cms;
+    }
+
+    public CtMethod getDeclaredMethod(String name) throws NotFoundException {
+        CtMethod m = getMethodsCache();
+        while (m != null) {
+            if (m.getName().equals(name))
+                return m;
+
+            m = m.next;
+        }
+
+        throw new NotFoundException(name + "(..) is not found in "
+                                    + getName());
+    }
+
+    public CtMethod getDeclaredMethod(String name, CtClass[] params)
+        throws NotFoundException
+    {
+        String desc = Descriptor.ofParameters(params);
+        CtMethod m = getMethodsCache();
+        while (m != null) {
+            if (m.getName().equals(name)
+                && m.getMethodInfo2().getDescriptor().startsWith(desc))
+                return m;
+
+            m = m.next;
+        }
+
+        throw new NotFoundException(name + "(..) is not found in "
+                                    + getName());
+    }
+
+    protected CtMethod getMethodsCache() {
+        if (methodsCache == null) {
+            List list = getClassFile2().getMethods();
+            int n = list.size();
+            for (int i = 0; i < n; ++i) {
+                MethodInfo minfo = (MethodInfo)list.get(i);
+                if (minfo.isMethod())
+                    methodsCache = CtMethod.append(methodsCache,
+                                                new CtMethod(minfo, this));
+            }
+        }
+
+        return methodsCache;
+    }
+
+    public void addField(CtField f, String init)
+        throws CannotCompileException
+    {
+        addField(f, CtField.Initializer.byExpr(init));
+    }
+
+    public void addField(CtField f, CtField.Initializer init)
+        throws CannotCompileException
+    {
+        checkModify();
+        if (f.getDeclaringClass() != this)
+            throw new CannotCompileException("cannot add");
+
+        if (init == null)
+            init = f.getInit();
+
+        getFieldsCache();
+        fieldsCache = CtField.append(fieldsCache, f);
+        getClassFile2().addField(f.getFieldInfo2());
+
+        if (init != null) {
+            FieldInitLink fil = new FieldInitLink(f, init);
+            FieldInitLink link = fieldInitializers;
+            if (link == null)
+                fieldInitializers = fil;
+            else {
+                while (link.next != null)
+                    link = link.next;
+
+                link.next = fil;
+            }
+        }
+    }
+
+    public CtConstructor makeClassInitializer()
+        throws CannotCompileException
+    {
+        CtConstructor clinit = getClassInitializer();
+        if (clinit != null)
+            return clinit;
+
+        checkModify();
+        ClassFile cf = getClassFile2();
+        Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
+        modifyClassConstructor(cf, code, 0, 0);
+        return getClassInitializer();
+    }
+
+    public void addConstructor(CtConstructor c)
+        throws CannotCompileException
+    {
+        checkModify();
+        if (c.getDeclaringClass() != this)
+            throw new CannotCompileException("cannot add");
+
+        getConstructorsCache();
+        constructorsCache = CtConstructor.append(constructorsCache, c);
+        getClassFile2().addMethod(c.getMethodInfo2());
+    }
+
+    public void addMethod(CtMethod m) throws CannotCompileException {
+        checkModify();
+        if (m.getDeclaringClass() != this)
+            throw new CannotCompileException("cannot add");
+
+        getMethodsCache();
+        methodsCache = CtMethod.append(methodsCache, m);
+        getClassFile2().addMethod(m.getMethodInfo2());
+        if ((m.getModifiers() & Modifier.ABSTRACT) != 0)
+            setModifiers(getModifiers() | Modifier.ABSTRACT);
+    }
+
+    public byte[] getAttribute(String name) {
+        AttributeInfo ai = getClassFile2().getAttribute(name);
+        if (ai == null)
+            return null;
+        else
+            return ai.get();
+    }
+
+    public void setAttribute(String name, byte[] data) {
+        checkModify();
+        ClassFile cf = getClassFile2();
+        cf.addAttribute(new AttributeInfo(cf.getConstPool(), name, data));
+    }
+
+    public void instrument(CodeConverter converter)
+        throws CannotCompileException
+    {
+        checkModify();
+        ClassFile cf = getClassFile2();
+        ConstPool cp = cf.getConstPool();
+        List list = cf.getMethods();
+        int n = list.size();
+        for (int i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            converter.doit(this, minfo, cp);
+        }
+    }
+
+    public void instrument(ExprEditor editor)
+        throws CannotCompileException
+    {
+        checkModify();
+        ClassFile cf = getClassFile2();
+        List list = cf.getMethods();
+        int n = list.size();
+        for (int i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            editor.doit(this, minfo);
+        }
+    }
+
+    public void toBytecode(DataOutputStream out)
+        throws CannotCompileException, IOException
+    {
+        try {
+            if (isModified()) {
+                checkPruned("toBytecode");
+                ClassFile cf = getClassFile2();
+                modifyClassConstructor(cf);
+                modifyConstructors(cf);
+                cf.write(out);
+                out.flush();
+                fieldInitializers = null;
+                if (doPruning) {
+                    // to save memory
+                    cf.prune();
+                    wasPruned = true;
+                }
+            }
+            else {
+                classPool.writeClassfile(getName(), out);
+                // to save memory
+                eraseCache();
+                classfile = null;
+            }
 
-         m = m.next;
-      }
-
-      throw new NotFoundException(name + "(..) is not found in "
-              + getName());
-   }
-
-   protected CtMethod getMethodsCache()
-   {
-      if (methodsCache == null)
-      {
-         List list = getClassFile2().getMethods();
-         int n = list.size();
-         for (int i = 0; i < n; ++i)
-         {
-            MethodInfo minfo = (MethodInfo) list.get(i);
-            if (minfo.isMethod())
-               methodsCache = CtMethod.append(methodsCache,
-                       new CtMethod(minfo, this));
-         }
-      }
-
-      return methodsCache;
-   }
-
-   public void addField(CtField f, String init)
-           throws CannotCompileException
-   {
-      addField(f, CtField.Initializer.byExpr(init));
-   }
-
-   public void addField(CtField f, CtField.Initializer init)
-           throws CannotCompileException
-   {
-      checkModify();
-      if (f.getDeclaringClass() != this)
-         throw new CannotCompileException("cannot add");
-
-      if (init == null)
-         init = f.getInit();
-
-      getFieldsCache();
-      fieldsCache = CtField.append(fieldsCache, f);
-      getClassFile2().addField(f.getFieldInfo2());
-
-      if (init != null)
-      {
-         FieldInitLink fil = new FieldInitLink(f, init);
-         FieldInitLink link = fieldInitializers;
-         if (link == null)
-            fieldInitializers = fil;
-         else
-         {
-            while (link.next != null)
-               link = link.next;
-
-            link.next = fil;
-         }
-      }
-   }
-
-   public CtConstructor makeClassInitializer()
-           throws CannotCompileException
-   {
-      CtConstructor clinit = getClassInitializer();
-      if (clinit != null)
-         return clinit;
-
-      checkModify();
-      ClassFile cf = getClassFile2();
-      Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
-      modifyClassConstructor(cf, code, 0, 0);
-      return getClassInitializer();
-   }
-
-   public void addConstructor(CtConstructor c)
-           throws CannotCompileException
-   {
-      checkModify();
-      if (c.getDeclaringClass() != this)
-         throw new CannotCompileException("cannot add");
-
-      getConstructorsCache();
-      constructorsCache = CtConstructor.append(constructorsCache, c);
-      getClassFile2().addMethod(c.getMethodInfo2());
-   }
-
-   public void addMethod(CtMethod m) throws CannotCompileException
-   {
-      checkModify();
-      if (m.getDeclaringClass() != this)
-         throw new CannotCompileException("cannot add");
-
-      getMethodsCache();
-      methodsCache = CtMethod.append(methodsCache, m);
-      getClassFile2().addMethod(m.getMethodInfo2());
-      if ((m.getModifiers() & Modifier.ABSTRACT) != 0)
-         setModifiers(getModifiers() | Modifier.ABSTRACT);
-   }
-
-   public byte[] getAttribute(String name)
-   {
-      AttributeInfo ai = getClassFile2().getAttribute(name);
-      if (ai == null)
-         return null;
-      else
-         return ai.get();
-   }
-
-   public void setAttribute(String name, byte[] data)
-   {
-      checkModify();
-      ClassFile cf = getClassFile2();
-      cf.addAttribute(new AttributeInfo(cf.getConstPool(), name, data));
-   }
-
-   public void instrument(CodeConverter converter)
-           throws CannotCompileException
-   {
-      checkModify();
-      ClassFile cf = getClassFile2();
-      ConstPool cp = cf.getConstPool();
-      List list = cf.getMethods();
-      int n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         converter.doit(this, minfo, cp);
-      }
-   }
-
-   public void instrument(ExprEditor editor)
-           throws CannotCompileException
-   {
-      checkModify();
-      ClassFile cf = getClassFile2();
-      List list = cf.getMethods();
-      int n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         editor.doit(this, minfo);
-      }
-   }
-
-   public void toBytecode(DataOutputStream out)
-           throws CannotCompileException, IOException
-   {
-      try
-      {
-         if (isModified())
-         {
-            checkPruned("toBytecode");
-            ClassFile cf = getClassFile2();
-            modifyClassConstructor(cf);
-            modifyConstructors(cf);
-            cf.write(out);
-            out.flush();
-            fieldInitializers = null;
-            if (doPruning)
-            {
-               // to save memory
-               cf.prune();
-               wasPruned = true;
+            wasFrozen = true;
+        }
+        catch (NotFoundException e) {
+            throw new CannotCompileException(e);
+        }
+        catch (IOException e) {
+            throw new CannotCompileException(e);
+        }
+    }
+
+    private void checkPruned(String method) {
+        if (wasPruned)
+            throw new RuntimeException(method + "(): " + getName()
+                                       + " was pruned.");
+    }
+
+    public void stopPruning(boolean stop) {
+        doPruning = !stop;
+    }
+
+    private void modifyClassConstructor(ClassFile cf)
+        throws CannotCompileException, NotFoundException
+    {
+        if (fieldInitializers == null)
+            return;
+
+        Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
+        Javac jv = new Javac(code, this);
+        int stacksize = 0;
+        boolean doInit = false;
+        for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next) {
+            CtField f = fi.field;
+            if (Modifier.isStatic(f.getModifiers())) {
+                doInit = true;
+                int s = fi.init.compileIfStatic(f.getType(), f.getName(),
+                                                code, jv);
+                if (stacksize < s)
+                    stacksize = s;
             }
-         }
-         else
-         {
-            classPool.writeClassfile(getName(), out);
-            // to save memory
-            eraseCache();
-            classfile = null;
-         }
-
-         wasFrozen = true;
-      }
-      catch (NotFoundException e)
-      {
-         throw new CannotCompileException(e);
-      }
-      catch (IOException e)
-      {
-         throw new CannotCompileException(e);
-      }
-   }
-
-   private void checkPruned(String method)
-   {
-      if (wasPruned)
-         throw new RuntimeException(method + "(): " + getName()
-                 + " was pruned.");
-   }
-
-   public void stopPruning(boolean stop)
-   {
-      doPruning = !stop;
-   }
-
-   private void modifyClassConstructor(ClassFile cf)
-           throws CannotCompileException, NotFoundException
-   {
-      if (fieldInitializers == null)
-         return;
-
-      Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
-      Javac jv = new Javac(code, this);
-      int stacksize = 0;
-      boolean doInit = false;
-      for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next)
-      {
-         CtField f = fi.field;
-         if (Modifier.isStatic(f.getModifiers()))
-         {
-            doInit = true;
-            int s = fi.init.compileIfStatic(f.getType(), f.getName(),
-                    code, jv);
-            if (stacksize < s)
-               stacksize = s;
-         }
-      }
-
-      if (doInit)    // need an initializer for static fileds.
-         modifyClassConstructor(cf, code, stacksize, 0);
-   }
-
-   private void modifyClassConstructor(ClassFile cf, Bytecode code,
-                                       int stacksize, int localsize)
-           throws CannotCompileException
-   {
-      MethodInfo m = cf.getStaticInitializer();
-      if (m == null)
-      {
-         code.add(Bytecode.RETURN);
-         code.setMaxStack(stacksize);
-         code.setMaxLocals(localsize);
-         m = new MethodInfo(cf.getConstPool(), "<clinit>", "()V");
-         m.setAccessFlags(AccessFlag.STATIC);
-         m.setCodeAttribute(code.toCodeAttribute());
-         cf.addMethod(m);
-      }
-      else
-      {
-         CodeAttribute codeAttr = m.getCodeAttribute();
-         if (codeAttr == null)
-            throw new CannotCompileException("empty <clinit>");
-
-         try
-         {
-            CodeIterator it = codeAttr.iterator();
-            int pos = it.insertEx(code.get());
-            it.insert(code.getExceptionTable(), pos);
-            int maxstack = codeAttr.getMaxStack();
-            if (maxstack < stacksize)
-               codeAttr.setMaxStack(stacksize);
-
-            int maxlocals = codeAttr.getMaxLocals();
-            if (maxlocals < localsize)
-               codeAttr.setMaxLocals(localsize);
-         }
-         catch (BadBytecode e)
-         {
+        }
+
+        if (doInit)    // need an initializer for static fileds.
+            modifyClassConstructor(cf, code, stacksize, 0);
+    }
+
+    private void modifyClassConstructor(ClassFile cf, Bytecode code,
+                                        int stacksize, int localsize)
+        throws CannotCompileException
+    {
+        MethodInfo m = cf.getStaticInitializer();
+        if (m == null) {
+            code.add(Bytecode.RETURN);
+            code.setMaxStack(stacksize);
+            code.setMaxLocals(localsize);
+            m = new MethodInfo(cf.getConstPool(), "<clinit>", "()V");
+            m.setAccessFlags(AccessFlag.STATIC);
+            m.setCodeAttribute(code.toCodeAttribute());
+            cf.addMethod(m);
+        }
+        else {
+            CodeAttribute codeAttr = m.getCodeAttribute();
+            if (codeAttr == null)
+                throw new CannotCompileException("empty <clinit>");
+
+            try {
+                CodeIterator it = codeAttr.iterator();
+                int pos = it.insertEx(code.get());
+                it.insert(code.getExceptionTable(), pos);
+                int maxstack = codeAttr.getMaxStack();
+                if (maxstack < stacksize)
+                    codeAttr.setMaxStack(stacksize);
+
+                int maxlocals = codeAttr.getMaxLocals();
+                if (maxlocals < localsize)
+                    codeAttr.setMaxLocals(localsize);
+            }
+            catch (BadBytecode e) {
+                throw new CannotCompileException(e);
+            }
+        }
+    }
+
+    private void modifyConstructors(ClassFile cf)
+        throws CannotCompileException, NotFoundException
+    {
+        if (fieldInitializers == null)
+            return;
+
+        ConstPool cp = cf.getConstPool();
+        List list = cf.getMethods();
+        int n = list.size();
+        for (int i = 0; i < n; ++i) {
+            MethodInfo minfo = (MethodInfo)list.get(i);
+            if (minfo.isConstructor()) {
+                CodeAttribute codeAttr = minfo.getCodeAttribute();
+                if (codeAttr != null)
+                    try {
+                        Bytecode init = new Bytecode(cp, 0,
+                                                codeAttr.getMaxLocals());
+                        CtClass[] params
+                            = Descriptor.getParameterTypes(
+                                                minfo.getDescriptor(),
+                                                classPool);
+                        int stacksize = makeFieldInitializer(init, params);
+                        insertAuxInitializer(codeAttr, init, stacksize);
+                    }
+                    catch (BadBytecode e) {
+                        throw new CannotCompileException(e);
+                    }
+            }
+        }
+    }
+
+    private static void insertAuxInitializer(CodeAttribute codeAttr,
+                                             Bytecode initializer,
+                                             int stacksize)
+        throws BadBytecode
+    {
+        CodeIterator it = codeAttr.iterator();
+        int index = it.skipSuperConstructor();
+        if (index < 0) {
+            index = it.skipThisConstructor();
+            if (index >= 0)
+                return;         // this() is called.
+
+            // Neither this() or super() is called.
+        }
+
+        int pos = it.insertEx(initializer.get());
+        it.insert(initializer.getExceptionTable(), pos);
+        int maxstack = codeAttr.getMaxStack();
+        if (maxstack < stacksize)
+            codeAttr.setMaxStack(stacksize);
+    }
+
+    private int makeFieldInitializer(Bytecode code, CtClass[] parameters)
+        throws CannotCompileException, NotFoundException
+    {
+        int stacksize = 0;
+        Javac jv = new Javac(code, this);
+        try {
+            jv.recordParams(parameters, false);
+        }
+        catch (CompileError e) {
             throw new CannotCompileException(e);
-         }
-      }
-   }
-
-   private void modifyConstructors(ClassFile cf)
-           throws CannotCompileException, NotFoundException
-   {
-      if (fieldInitializers == null)
-         return;
-
-      ConstPool cp = cf.getConstPool();
-      List list = cf.getMethods();
-      int n = list.size();
-      for (int i = 0; i < n; ++i)
-      {
-         MethodInfo minfo = (MethodInfo) list.get(i);
-         if (minfo.isConstructor())
-         {
-            CodeAttribute codeAttr = minfo.getCodeAttribute();
-            if (codeAttr != null)
-               try
-               {
-                  Bytecode init = new Bytecode(cp, 0,
-                          codeAttr.getMaxLocals());
-                  CtClass[] params
-                          = Descriptor.getParameterTypes(minfo.getDescriptor(),
-                                  classPool);
-                  int stacksize = makeFieldInitializer(init, params);
-                  insertAuxInitializer(codeAttr, init, stacksize);
-               }
-               catch (BadBytecode e)
-               {
-                  throw new CannotCompileException(e);
-               }
-         }
-      }
-   }
-
-   private static void insertAuxInitializer(CodeAttribute codeAttr,
-                                            Bytecode initializer,
-                                            int stacksize)
-           throws BadBytecode
-   {
-      CodeIterator it = codeAttr.iterator();
-      int index = it.skipSuperConstructor();
-      if (index < 0)
-      {
-         index = it.skipThisConstructor();
-         if (index >= 0)
-            return;         // this() is called.
-
-         // Neither this() or super() is called.
-      }
-
-      int pos = it.insertEx(initializer.get());
-      it.insert(initializer.getExceptionTable(), pos);
-      int maxstack = codeAttr.getMaxStack();
-      if (maxstack < stacksize)
-         codeAttr.setMaxStack(stacksize);
-   }
-
-   private int makeFieldInitializer(Bytecode code, CtClass[] parameters)
-           throws CannotCompileException, NotFoundException
-   {
-      int stacksize = 0;
-      Javac jv = new Javac(code, this);
-      try
-      {
-         jv.recordParams(parameters, false);
-      }
-      catch (CompileError e)
-      {
-         throw new CannotCompileException(e);
-      }
-
-      for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next)
-      {
-         CtField f = fi.field;
-         if (!Modifier.isStatic(f.getModifiers()))
-         {
-            int s = fi.init.compile(f.getType(), f.getName(), code,
-                    parameters, jv);
-            if (stacksize < s)
-               stacksize = s;
-         }
-      }
-
-      return stacksize;
-   }
-
-   // Methods used by CtNewWrappedMethod
-
-   Hashtable getHiddenMethods()
-   {
-      if (hiddenMethods == null)
-         hiddenMethods = new Hashtable();
-
-      return hiddenMethods;
-   }
-
-   int getUniqueNumber()
-   {
-      return uniqueNumberSeed++;
-   }
+        }
+
+        for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next) {
+            CtField f = fi.field;
+            if (!Modifier.isStatic(f.getModifiers())) {
+                int s = fi.init.compile(f.getType(), f.getName(), code,
+                                        parameters, jv);
+                if (stacksize < s)
+                    stacksize = s;
+            }
+        }
+
+        return stacksize;
+    }
+
+    // Methods used by CtNewWrappedMethod
+
+    Hashtable getHiddenMethods() {
+        if (hiddenMethods == null)
+            hiddenMethods = new Hashtable();
+
+        return hiddenMethods;
+    }
+
+    int getUniqueNumber() { return uniqueNumberSeed++; }
 }
 
-class FieldInitLink
-{
-   FieldInitLink next;
-   CtField field;
-   CtField.Initializer init;
-
-   FieldInitLink(CtField f, CtField.Initializer i)
-   {
-      next = null;
-      field = f;
-      init = i;
-   }
+class FieldInitLink {
+    FieldInitLink next;
+    CtField field;
+    CtField.Initializer init;
+
+    FieldInitLink(CtField f, CtField.Initializer i) {
+        next = null;
+        field = f;
+        init = i;
+    }
 }
index 2483c01b895072a4b396b99e6bb085969ae375d9..302004a63013c157838c1c7ba9e2f2f42621a9b4 100644 (file)
 
 package javassist.bytecode;
 
-import javassist.bytecode.annotation.Annotation;
-import javassist.bytecode.annotation.AnnotationMemberValue;
-import javassist.bytecode.annotation.AnnotationsWriter;
-import javassist.bytecode.annotation.ArrayMemberValue;
-import javassist.bytecode.annotation.BooleanMemberValue;
-import javassist.bytecode.annotation.ByteMemberValue;
-import javassist.bytecode.annotation.CharMemberValue;
-import javassist.bytecode.annotation.ClassMemberValue;
-import javassist.bytecode.annotation.DoubleMemberValue;
-import javassist.bytecode.annotation.EnumMemberValue;
-import javassist.bytecode.annotation.FloatMemberValue;
-import javassist.bytecode.annotation.IntegerMemberValue;
-import javassist.bytecode.annotation.LongMemberValue;
-import javassist.bytecode.annotation.MemberValue;
-import javassist.bytecode.annotation.ShortMemberValue;
-import javassist.bytecode.annotation.StringMemberValue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.util.HashMap;
 import java.util.Map;
+import java.io.IOException;
+import java.io.DataInputStream;
+import java.io.ByteArrayOutputStream;
+import javassist.bytecode.annotation.*;
 
 /**
  * A class representing
  * <code>RuntimeVisibleAnnotations_attribute</code> and
  * <code>RuntimeInvisibleAnnotations_attribute</code>.
- * <p/>
+ *
  * <p>To obtain an AnnotationAttribute object, invoke
  * <code>getAttribute(AnnotationsAttribute.invisibleTag)</code>
  * in <code>ClassFile</code>, <code>MethodInfo</code>,
@@ -51,10 +34,10 @@ import java.util.Map;
  * If the parameter is
  * <code>AnnotationAttribute.visibleTag</code>, then the obtained
  * attribute is a runtime visible one.
- * <p/>
+ *
  * <p>If you want to record a new AnnotationAttribute object, execute the
  * following snippet:
- * <p/>
+ *
  * <ul><pre>
  * ClassFile cf = ... ;
  * ConstPool cp = cf.getConstPool();
@@ -66,571 +49,513 @@ import java.util.Map;
  * cf.addAttribute(attr);
  * </pre></ul>
  */
-public class AnnotationsAttribute extends AttributeInfo
-{
-   /**
-    * The name of the <code>RuntimeVisibleAnnotations</code> attribute.
-    */
-   public static final String visibleTag = "RuntimeVisibleAnnotations";
-
-   /**
-    * The name of the <code>RuntimeInvisibleAnnotations</code> attribute.
-    */
-   public static final String invisibleTag = "RuntimeInvisibleAnnotations";
-
-   private HashMap annotationMap;
-
-   /**
-    * Constructs a <code>Runtime(In)VisisbleAnnotations_attribute</code>.
-    *
-    * @param cp       constant pool
-    * @param attrname attribute name (<code>visibleTag</code> or
-    *                 <code>invisibleTag</code>).
-    * @param info     the contents of this attribute.  It does not
-    *                 include <code>attribute_name_index</code> or
-    *                 <code>attribute_length</code>.
-    */
-   public AnnotationsAttribute(ConstPool cp, String attrname, byte[] info)
-   {
-      super(cp, attrname, info);
-   }
-
-   /**
-    * Constructs an empty
-    * <code>Runtime(In)VisisbleAnnotations_attribute</code>.
-    * A new annotation can be later added to the created attribute
-    * by <code>setAnnotations()</code>.
-    *
-    * @param cp       constant pool
-    * @param attrname attribute name (<code>visibleTag</code> or
-    *                 <code>invisibleTag</code>).
-    * @see #setAnnotations(Annotation[])
-    */
-   public AnnotationsAttribute(ConstPool cp, String attrname)
-   {
-      this(cp, attrname, new byte[]{0, 0});
-   }
-
-   /**
-    * @param n the attribute name.
-    */
-   AnnotationsAttribute(ConstPool cp, int n, DataInputStream in)
-           throws IOException
-   {
-      super(cp, n, in);
-   }
-
-   /**
-    * Returns <code>num_annotations</code>.
-    */
-   public int numAnnotations()
-   {
-      return ByteArray.readU16bit(info, 0);
-   }
-
-   /**
-    * Copies this attribute and returns a new copy.
-    */
-   public AttributeInfo copy(ConstPool newCp, Map classnames)
-   {
-      Copier copier = new Copier(info, constPool, newCp, classnames);
-      try
-      {
-         copier.annotationArray();
-         return new AnnotationsAttribute(newCp, getName(), copier.close());
-      }
-      catch (Exception e)
-      {
-         throw new RuntimeException(e.toString());
-      }
-   }
-
-   public Annotation getAnnotation(String type)
-   {
-      Annotation[] annotations = getAnnotations();
-      for (int i = 0; i < annotations.length; i++)
-      {
-         if (annotations[i].getTypeName().equals(type)) return annotations[i];
-      }
-      return null;
-   }
-
-   public void addAnnotation(Annotation annotation)
-   {
-      String type = annotation.getTypeName();
-      Annotation[] annotations = getAnnotations();
-      for (int i = 0; i < annotations.length; i++)
-      {
-         if (annotations[i].getTypeName().equals(type))
-         {
-            annotations[i] = annotation;
-            setAnnotations(annotations);
-            return;
-         }
-      }
-      Annotation[] newlist = new Annotation[annotations.length + 1];
-      System.arraycopy(annotations, 0, newlist, 0, annotations.length);
-      newlist[annotations.length] = annotation;
-      setAnnotations(newlist);
-   }
-
-   /**
-    * Parses the annotations and returns a data structure representing
-    * that parsed annotations.  Note that changes of the node values of the
-    * returned tree are not reflected on the annotations represented by
-    * this object unless the tree is copied back to this object by
-    * <code>setAnnotations()</code>.
-    *
-    * @see #setAnnotations(Annotation[])
-    */
-   public Annotation[] getAnnotations()
-   {
-      try
-      {
-         return new Parser(info, constPool).parseAnnotations();
-      }
-      catch (Exception e)
-      {
-         throw new RuntimeException(e.toString());
-      }
-   }
-
-   /**
-    * Changes the annotations represented by this object according to
-    * the given array of <code>Annotation</code> objects.
-    *
-    * @param annotations the data structure representing the
-    *                    new annotations.
-    */
-   public void setAnnotations(Annotation[] annotations)
-   {
-      ByteArrayOutputStream output = new ByteArrayOutputStream();
-      AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
-      try
-      {
-         int n = annotations.length;
-         writer.numAnnotations(n);
-         for (int i = 0; i < n; ++i)
-            annotations[i].write(writer);
-
-         writer.close();
-      }
-      catch (IOException e)
-      {
-         throw new RuntimeException(e);      // should never reach here.
-      }
-
-      set(output.toByteArray());
-   }
-
-   /**
-    * Changes the annotations.  A call to this method is equivalent to:
-    * <ul><pre>setAnnotations(new Annotation[] { annotation })</pre></ul>
-    *
-    * @param annotation the data structure representing
-    *                   the new annotation.
-    */
-   public void setAnnotation(Annotation annotation)
-   {
-      setAnnotations(new Annotation[]{annotation});
-   }
-
-   /**
-    * Returns a string representation of this object.
-    */
-   public String toString()
-   {
-      Annotation[] a = getAnnotations();
-      StringBuffer sbuf = new StringBuffer();
-      int i = 0;
-      while (i < a.length)
-      {
-         sbuf.append(a[i++].toString());
-         if (i != a.length)
-            sbuf.append(", ");
-      }
-
-      return sbuf.toString();
-   }
-
-   static class Walker
-   {
-      byte[] info;
-
-      Walker(byte[] attrInfo)
-      {
-         info = attrInfo;
-      }
-
-      final void parameters() throws Exception
-      {
-         int numParam = info[0] & 0xff;
-         parameters(numParam, 1);
-      }
-
-      void parameters(int numParam, int pos) throws Exception
-      {
-         for (int i = 0; i < numParam; ++i)
-            pos = annotationArray(pos);
-      }
-
-      final void annotationArray() throws Exception
-      {
-         annotationArray(0);
-      }
-
-      final int annotationArray(int pos) throws Exception
-      {
-         int num = ByteArray.readU16bit(info, pos);
-         return annotationArray(pos + 2, num);
-      }
-
-      int annotationArray(int pos, int num) throws Exception
-      {
-         for (int i = 0; i < num; ++i)
-            pos = annotation(pos);
-
-         return pos;
-      }
-
-      final int annotation(int pos) throws Exception
-      {
-         int type = ByteArray.readU16bit(info, pos);
-         int numPairs = ByteArray.readU16bit(info, pos + 2);
-         return annotation(pos + 4, type, numPairs);
-      }
-
-      int annotation(int pos, int type, int numPairs) throws Exception
-      {
-         for (int j = 0; j < numPairs; ++j)
-            pos = memberValuePair(pos);
-
-         return pos;
-      }
-
-      final int memberValuePair(int pos) throws Exception
-      {
-         int nameIndex = ByteArray.readU16bit(info, pos);
-         return memberValuePair(pos + 2, nameIndex);
-      }
-
-      int memberValuePair(int pos, int nameIndex) throws Exception
-      {
-         return memberValue(pos);
-      }
-
-      final int memberValue(int pos) throws Exception
-      {
-         int tag = info[pos] & 0xff;
-         if (tag == 'e')
-         {
-            int typeNameIndex = ByteArray.readU16bit(info, pos + 1);
-            int constNameIndex = ByteArray.readU16bit(info, pos + 3);
-            enumMemberValue(typeNameIndex, constNameIndex);
-            return pos + 5;
-         }
-         else if (tag == 'c')
-         {
-            int index = ByteArray.readU16bit(info, pos + 1);
-            classMemberValue(index);
-            return pos + 3;
-         }
-         else if (tag == '@')
-            return annotationMemberValue(pos + 1);
-         else if (tag == '[')
-         {
-            int num = ByteArray.readU16bit(info, pos + 1);
-            return arrayMemberValue(pos + 3, num);
-         }
-         else
-         { // primitive types or String.
-            int index = ByteArray.readU16bit(info, pos + 1);
-            constValueMember(tag, index);
-            return pos + 3;
-         }
-      }
-
-      void constValueMember(int tag, int index) throws Exception
-      {
-      }
-
-      void enumMemberValue(int typeNameIndex, int constNameIndex)
-              throws Exception
-      {
-      }
-
-      void classMemberValue(int index) throws Exception
-      {
-      }
-
-      int annotationMemberValue(int pos) throws Exception
-      {
-         return annotation(pos);
-      }
-
-      int arrayMemberValue(int pos, int num) throws Exception
-      {
-         for (int i = 0; i < num; ++i)
-         {
-            pos = memberValue(pos);
-         }
-
-         return pos;
-      }
-   }
-
-   static class Copier extends Walker
-   {
-      ByteArrayOutputStream output;
-      AnnotationsWriter writer;
-      ConstPool srcPool, destPool;
-      Map classnames;
-
-      /**
-       * Constructs a copier.  This copier renames some class names
-       * into the new names specified by <code>map</code> when it copies
-       * an annotation attribute.
-       *
-       * @param info the source attribute.
-       * @param src  the constant pool of the source class.
-       * @param dest the constant pool of the destination class.
-       * @param map  pairs of replaced and substituted class names.
-       *             It can be null.
-       */
-      Copier(byte[] info, ConstPool src, ConstPool dest, Map map)
-      {
-         super(info);
-         output = new ByteArrayOutputStream();
-         writer = new AnnotationsWriter(output, dest);
-         srcPool = src;
-         destPool = dest;
-         classnames = map;
-      }
-
-      byte[] close() throws IOException
-      {
-         writer.close();
-         return output.toByteArray();
-      }
-
-      void parameters(int numParam, int pos) throws Exception
-      {
-         writer.numParameters(numParam);
-         super.parameters(numParam, pos);
-      }
-
-      int annotationArray(int pos, int num) throws Exception
-      {
-         writer.numAnnotations(num);
-         return super.annotationArray(pos, num);
-      }
-
-      int annotation(int pos, int type, int numPairs) throws Exception
-      {
-         writer.annotation(copy(type), numPairs);
-         return super.annotation(pos, type, numPairs);
-      }
-
-      int memberValuePair(int pos, int nameIndex) throws Exception
-      {
-         writer.memberValuePair(copy(nameIndex));
-         return super.memberValuePair(pos, nameIndex);
-      }
-
-      void constValueMember(int tag, int index) throws Exception
-      {
-         writer.constValueIndex(tag, copy(index));
-         super.constValueMember(tag, index);
-      }
-
-      void enumMemberValue(int typeNameIndex, int constNameIndex)
-              throws Exception
-      {
-         writer.enumConstValue(copy(typeNameIndex), copy(constNameIndex));
-         super.enumMemberValue(typeNameIndex, constNameIndex);
-      }
-
-      void classMemberValue(int index) throws Exception
-      {
-         writer.classInfoIndex(copy(index));
-         super.classMemberValue(index);
-      }
-
-      int annotationMemberValue(int pos) throws Exception
-      {
-         writer.annotationValue();
-         return super.annotationMemberValue(pos);
-      }
-
-      int arrayMemberValue(int pos, int num) throws Exception
-      {
-         writer.arrayValue(num);
-         return super.arrayMemberValue(pos, num);
-      }
-
-      /**
-       * Copies a constant pool entry into the destination constant pool
-       * and returns the index of the copied entry.
-       *
-       * @param srcIndex the index of the copied entry into the source
-       *                 constant pool.
-       * @return the index of the copied item into the destination
-       *         constant pool.
-       */
-      int copy(int srcIndex)
-      {
-         return srcPool.copy(srcIndex, destPool, classnames);
-      }
-   }
-
-   static class Parser extends Walker
-   {
-      ConstPool pool;
-      Annotation[][] allParams;   // all parameters
-      Annotation[] allAnno;       // all annotations
-      Annotation currentAnno;     // current annotation
-      MemberValue memberValue;
-
-      /**
-       * Constructs a parser.  This parser constructs a parse tree of
-       * the annotations.
-       *
-       * @param info the attribute.
-       * @param src  the constant pool.
-       */
-      Parser(byte[] info, ConstPool cp)
-      {
-         super(info);
-         pool = cp;
-      }
-
-      Annotation[][] parseParameters() throws Exception
-      {
-         parameters();
-         return allParams;
-      }
-
-      Annotation[] parseAnnotations() throws Exception
-      {
-         annotationArray();
-         return allAnno;
-      }
-
-      void parameters(int numParam, int pos) throws Exception
-      {
-         Annotation[][] params = new Annotation[numParam][];
-         for (int i = 0; i < numParam; ++i)
-         {
-            pos = annotationArray(pos);
-            params[i] = allAnno;
-         }
-
-         allParams = params;
-      }
-
-      int annotationArray(int pos, int num) throws Exception
-      {
-         Annotation[] array = new Annotation[num];
-         for (int i = 0; i < num; ++i)
-         {
-            pos = annotation(pos);
-            array[i] = currentAnno;
-         }
-
-         allAnno = array;
-         return pos;
-      }
-
-      int annotation(int pos, int type, int numPairs) throws Exception
-      {
-         currentAnno = new Annotation(type, pool);
-         return super.annotation(pos, type, numPairs);
-      }
-
-      int memberValuePair(int pos, int nameIndex) throws Exception
-      {
-         pos = super.memberValuePair(pos, nameIndex);
-         currentAnno.addMemberValue(nameIndex, memberValue);
-         return pos;
-      }
-
-      void constValueMember(int tag, int index) throws Exception
-      {
-         MemberValue m;
-         ConstPool cp = pool;
-         switch (tag)
-         {
-         case 'B':
-            m = new ByteMemberValue(index, cp);
-            break;
-         case 'C':
-            m = new CharMemberValue(index, cp);
-            break;
-         case 'D':
-            m = new DoubleMemberValue(index, cp);
-            break;
-         case 'F':
-            m = new FloatMemberValue(index, cp);
-            break;
-         case 'I':
-            m = new IntegerMemberValue(index, cp);
-            break;
-         case 'J':
-            m = new LongMemberValue(index, cp);
-            break;
-         case 'S':
-            m = new ShortMemberValue(index, cp);
-            break;
-         case 'Z':
-            m = new BooleanMemberValue(index, cp);
-            break;
-         case 's':
-            m = new StringMemberValue(index, cp);
-            break;
-         default :
-            throw new RuntimeException("unknown tag:" + tag);
-         }
-
-         memberValue = m;
-         super.constValueMember(tag, index);
-      }
-
-      void enumMemberValue(int typeNameIndex, int constNameIndex)
-              throws Exception
-      {
-         memberValue = new EnumMemberValue(typeNameIndex,
-                 constNameIndex, pool);
-         super.enumMemberValue(typeNameIndex, constNameIndex);
-      }
-
-      void classMemberValue(int index) throws Exception
-      {
-         memberValue = new ClassMemberValue(index, pool);
-         super.classMemberValue(index);
-      }
-
-      int annotationMemberValue(int pos) throws Exception
-      {
-         Annotation anno = currentAnno;
-         pos = super.annotationMemberValue(pos);
-         memberValue = new AnnotationMemberValue(currentAnno, pool);
-         currentAnno = anno;
-         return pos;
-      }
-
-      int arrayMemberValue(int pos, int num) throws Exception
-      {
-         ArrayMemberValue amv = new ArrayMemberValue(pool);
-         MemberValue[] elements = new MemberValue[num];
-         for (int i = 0; i < num; ++i)
-         {
-            pos = memberValue(pos);
-            elements[i] = memberValue;
-         }
-
-         amv.setValue(elements);
-         memberValue = amv;
-         return pos;
-      }
-   }
+public class AnnotationsAttribute extends AttributeInfo {
+    /**
+     * The name of the <code>RuntimeVisibleAnnotations</code> attribute.
+     */
+    public static final String visibleTag = "RuntimeVisibleAnnotations";
+
+    /**
+     * The name of the <code>RuntimeInvisibleAnnotations</code> attribute.
+     */
+    public static final String invisibleTag = "RuntimeInvisibleAnnotations";
+
+    /**
+     * Constructs a <code>Runtime(In)VisisbleAnnotations_attribute</code>.
+     *
+     * @param cp            constant pool
+     * @param attrname      attribute name (<code>visibleTag</code> or
+     *                      <code>invisibleTag</code>).
+     * @param info          the contents of this attribute.  It does not
+     *                      include <code>attribute_name_index</code> or
+     *                      <code>attribute_length</code>.
+     */
+    public AnnotationsAttribute(ConstPool cp, String attrname, byte[] info) {
+        super(cp, attrname, info);
+    }
+
+    /**
+     * Constructs an empty
+     * <code>Runtime(In)VisisbleAnnotations_attribute</code>.
+     * A new annotation can be later added to the created attribute
+     * by <code>setAnnotations()</code>.
+     *
+     * @param cp            constant pool
+     * @param attrname      attribute name (<code>visibleTag</code> or
+     *                      <code>invisibleTag</code>).
+     * @see #setAnnotations(Annotation[])
+     */
+    public AnnotationsAttribute(ConstPool cp, String attrname) {
+        this(cp, attrname, new byte[] { 0, 0 });
+    }
+
+    /**
+     * @param n     the attribute name.
+     */
+    AnnotationsAttribute(ConstPool cp, int n, DataInputStream in)
+        throws IOException
+    {
+        super(cp, n, in);
+    }
+
+    /**
+     * Returns <code>num_annotations</code>.
+     */
+    public int numAnnotations() {
+        return ByteArray.readU16bit(info, 0);
+    }
+
+    /**
+     * Copies this attribute and returns a new copy.
+     */
+    public AttributeInfo copy(ConstPool newCp, Map classnames) {
+        Copier copier = new Copier(info, constPool, newCp, classnames);
+        try {
+            copier.annotationArray();
+            return new AnnotationsAttribute(newCp, getName(), copier.close());
+        }
+        catch (Exception e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    /**
+     * Parses the annotations and returns a data structure representing
+     * the annotation with the specified type.  See also
+     * <code>getAnnotations()</code> as to the returned data structure.
+     *
+     * @param type      the annotation type.
+     * @see #getAnnotations()
+     */
+    public Annotation getAnnotation(String type) {
+        Annotation[] annotations = getAnnotations();
+        for (int i = 0; i < annotations.length; i++) {
+            if (annotations[i].getTypeName().equals(type))
+                return annotations[i];
+        }
+
+        return null;
+    }
+
+    /**
+     * Adds an annotation.  If there is an annotation with the same type,
+     * it is removed before the new annotation is added.
+     *
+     * @param annotation        the added annotation.
+     */
+    public void addAnnotation(Annotation annotation) {
+        String type = annotation.getTypeName();
+        Annotation[] annotations = getAnnotations();
+        for (int i = 0; i < annotations.length; i++) {
+            if (annotations[i].getTypeName().equals(type)) {
+                annotations[i] = annotation;
+                setAnnotations(annotations);
+                return;
+            }
+        }
+
+        Annotation[] newlist = new Annotation[annotations.length + 1];
+        System.arraycopy(annotations, 0, newlist, 0, annotations.length);
+        newlist[annotations.length] = annotation;
+        setAnnotations(newlist);
+    }
+
+    /**
+     * Parses the annotations and returns a data structure representing
+     * that parsed annotations.  Note that changes of the node values of the
+     * returned tree are not reflected on the annotations represented by
+     * this object unless the tree is copied back to this object by
+     * <code>setAnnotations()</code>.
+     *
+     * @see #setAnnotations(Annotation[])
+     */
+    public Annotation[] getAnnotations() {
+        try {
+            return new Parser(info, constPool).parseAnnotations();
+        }
+        catch (Exception e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    /**
+     * Changes the annotations represented by this object according to
+     * the given array of <code>Annotation</code> objects.
+     *
+     * @param annotations           the data structure representing the
+     *                              new annotations.
+     */
+    public void setAnnotations(Annotation[] annotations) {
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
+        try {
+            int n = annotations.length;
+            writer.numAnnotations(n);
+            for (int i = 0; i < n; ++i)
+                annotations[i].write(writer);
+
+            writer.close();
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e);      // should never reach here.
+        }
+
+        set(output.toByteArray());
+    }
+
+    /**
+     * Changes the annotations.  A call to this method is equivalent to:
+     * <ul><pre>setAnnotations(new Annotation[] { annotation })</pre></ul>
+     *
+     * @param annotation    the data structure representing
+     *                      the new annotation.
+     */
+    public void setAnnotation(Annotation annotation) {
+        setAnnotations(new Annotation[] { annotation });
+    }
+
+    /**
+     * Returns a string representation of this object.
+     */
+    public String toString() {
+        Annotation[] a = getAnnotations();
+        StringBuffer sbuf = new StringBuffer();
+        int i = 0;
+        while (i < a.length) {
+            sbuf.append(a[i++].toString());
+            if (i != a.length)
+                sbuf.append(", ");
+        }
+
+        return sbuf.toString();
+    }
+
+    static class Walker {
+        byte[] info;
+
+        Walker(byte[] attrInfo) {
+            info = attrInfo;
+        }
+
+        final void parameters() throws Exception {
+            int numParam = info[0] & 0xff;
+            parameters(numParam, 1);
+        }
+
+        void parameters(int numParam, int pos) throws Exception {
+            for (int i = 0; i < numParam; ++i)
+                pos = annotationArray(pos);
+        }
+
+        final void annotationArray() throws Exception {
+            annotationArray(0);
+        }
+
+        final int annotationArray(int pos) throws Exception {
+            int num = ByteArray.readU16bit(info, pos);
+            return annotationArray(pos + 2, num);
+        }
+
+        int annotationArray(int pos, int num) throws Exception {
+            for (int i = 0; i < num; ++i)
+                pos = annotation(pos);
+
+            return pos;
+        }
+
+        final int annotation(int pos) throws Exception {
+            int type = ByteArray.readU16bit(info, pos);
+            int numPairs = ByteArray.readU16bit(info, pos + 2);
+            return annotation(pos + 4, type, numPairs);
+        }
+
+        int annotation(int pos, int type, int numPairs) throws Exception {
+            for (int j = 0; j < numPairs; ++j)
+                pos = memberValuePair(pos);
+
+            return pos;
+        }
+
+        final int memberValuePair(int pos) throws Exception {
+            int nameIndex = ByteArray.readU16bit(info, pos);
+            return memberValuePair(pos + 2, nameIndex);
+        }
+
+        int memberValuePair(int pos, int nameIndex) throws Exception {
+            return memberValue(pos);
+        }
+
+        final int memberValue(int pos) throws Exception {
+            int tag = info[pos] & 0xff;
+            if (tag == 'e') {
+                int typeNameIndex = ByteArray.readU16bit(info, pos + 1);
+                int constNameIndex = ByteArray.readU16bit(info, pos + 3);
+                enumMemberValue(typeNameIndex, constNameIndex);
+                return pos + 5;
+            }
+            else if (tag == 'c') {
+                int index = ByteArray.readU16bit(info, pos + 1);
+                classMemberValue(index);
+                return pos + 3;
+            }
+            else if (tag == '@')
+                return annotationMemberValue(pos + 1);
+            else if (tag == '[') {
+                int num = ByteArray.readU16bit(info, pos + 1);
+                return arrayMemberValue(pos + 3, num);
+            }
+            else { // primitive types or String.
+                int index = ByteArray.readU16bit(info, pos + 1);
+                constValueMember(tag, index);
+                return pos + 3;
+            }
+        }
+
+        void constValueMember(int tag, int index) throws Exception {}
+
+        void enumMemberValue(int typeNameIndex, int constNameIndex)
+            throws Exception {
+        }
+
+        void classMemberValue(int index) throws Exception {}
+
+        int annotationMemberValue(int pos) throws Exception {
+            return annotation(pos);
+        }
+
+        int arrayMemberValue(int pos, int num) throws Exception {
+            for (int i = 0; i < num; ++i) {
+                pos = memberValue(pos);
+            }
+
+            return pos;
+        }
+    }
+
+    static class Copier extends Walker {
+        ByteArrayOutputStream output;
+        AnnotationsWriter writer;
+        ConstPool srcPool, destPool;
+        Map classnames;
+
+        /**
+         * Constructs a copier.  This copier renames some class names
+         * into the new names specified by <code>map</code> when it copies
+         * an annotation attribute.
+         *
+         * @param info      the source attribute.
+         * @param src       the constant pool of the source class.
+         * @param dest      the constant pool of the destination class.
+         * @param map       pairs of replaced and substituted class names.
+         *                  It can be null.
+         */
+        Copier(byte[] info, ConstPool src, ConstPool dest, Map map) {
+            super(info);
+            output = new ByteArrayOutputStream();
+            writer = new AnnotationsWriter(output, dest);
+            srcPool = src;
+            destPool = dest;
+            classnames = map;
+        }
+
+        byte[] close() throws IOException {
+            writer.close();
+            return output.toByteArray();
+        }
+
+        void parameters(int numParam, int pos) throws Exception {
+            writer.numParameters(numParam);
+            super.parameters(numParam, pos);
+        }
+
+        int annotationArray(int pos, int num) throws Exception {
+            writer.numAnnotations(num);
+            return super.annotationArray(pos, num);
+        }
+
+        int annotation(int pos, int type, int numPairs) throws Exception {
+            writer.annotation(copy(type), numPairs);
+            return super.annotation(pos, type, numPairs);
+        }
+
+        int memberValuePair(int pos, int nameIndex) throws Exception {
+            writer.memberValuePair(copy(nameIndex));
+            return super.memberValuePair(pos, nameIndex);
+        }
+
+        void constValueMember(int tag, int index) throws Exception {
+            writer.constValueIndex(tag, copy(index));
+            super.constValueMember(tag, index);
+        }
+
+        void enumMemberValue(int typeNameIndex, int constNameIndex)
+            throws Exception
+        {
+            writer.enumConstValue(copy(typeNameIndex), copy(constNameIndex));
+            super.enumMemberValue(typeNameIndex, constNameIndex);
+        }
+
+        void classMemberValue(int index) throws Exception {
+            writer.classInfoIndex(copy(index));
+            super.classMemberValue(index);
+        }
+
+        int annotationMemberValue(int pos) throws Exception {
+            writer.annotationValue();
+            return super.annotationMemberValue(pos);
+        }
+
+        int arrayMemberValue(int pos, int num) throws Exception {
+            writer.arrayValue(num);
+            return super.arrayMemberValue(pos, num);
+        }
+
+        /**
+         * Copies a constant pool entry into the destination constant pool
+         * and returns the index of the copied entry.
+         *
+         * @param srcIndex      the index of the copied entry into the source
+         *                      constant pool.
+         * @return the index of the copied item into the destination
+         *         constant pool.
+         */
+        int copy(int srcIndex) {
+            return srcPool.copy(srcIndex, destPool, classnames);
+        }
+    }
+
+    static class Parser extends Walker {
+        ConstPool pool;
+        Annotation[][] allParams;   // all parameters
+        Annotation[] allAnno;       // all annotations
+        Annotation currentAnno;     // current annotation
+        MemberValue memberValue;
+
+        /**
+         * Constructs a parser.  This parser constructs a parse tree of
+         * the annotations.
+         *
+         * @param info      the attribute.
+         * @param src       the constant pool.
+         */
+        Parser(byte[] info, ConstPool cp) {
+            super(info);
+            pool = cp;
+        }
+
+        Annotation[][] parseParameters() throws Exception {
+            parameters();
+            return allParams;
+        }
+
+        Annotation[] parseAnnotations() throws Exception {
+            annotationArray();
+            return allAnno;
+        }
+
+        void parameters(int numParam, int pos) throws Exception {
+            Annotation[][] params = new Annotation[numParam][];
+            for (int i = 0; i < numParam; ++i) {
+                pos = annotationArray(pos);
+                params[i] = allAnno;
+            }
+
+            allParams = params;
+        }
+
+        int annotationArray(int pos, int num) throws Exception {
+            Annotation[] array = new Annotation[num];
+            for (int i = 0; i < num; ++i) {
+                pos = annotation(pos);
+                array[i] = currentAnno;
+            }
+
+            allAnno = array;
+            return pos;
+        }
+
+        int annotation(int pos, int type, int numPairs) throws Exception {
+            currentAnno = new Annotation(type, pool);
+            return super.annotation(pos, type, numPairs);
+        }
+
+        int memberValuePair(int pos, int nameIndex) throws Exception {
+            pos = super.memberValuePair(pos, nameIndex);
+            currentAnno.addMemberValue(nameIndex, memberValue);
+            return pos;
+        }
+
+        void constValueMember(int tag, int index) throws Exception {
+            MemberValue m;
+            ConstPool cp = pool;
+            switch (tag) {
+            case 'B' :
+                m = new ByteMemberValue(index, cp);
+                break;
+            case 'C' :
+                m = new CharMemberValue(index, cp);
+                break;
+            case 'D' :
+                m = new DoubleMemberValue(index, cp);
+                break;
+            case 'F' :
+                m = new FloatMemberValue(index, cp);
+                break;
+            case 'I' :
+                m = new IntegerMemberValue(index, cp);
+                break;
+            case 'J' :
+                m = new LongMemberValue(index, cp);
+                break;
+            case 'S' :
+                m = new ShortMemberValue(index, cp);
+                break;
+            case 'Z' :
+                m = new BooleanMemberValue(index, cp);
+                break;
+            case 's' :
+                m = new StringMemberValue(index, cp);
+                break;
+            default :
+                throw new RuntimeException("unknown tag:" + tag);
+            }
+
+            memberValue = m;
+            super.constValueMember(tag, index);
+        }
+
+        void enumMemberValue(int typeNameIndex, int constNameIndex)
+            throws Exception
+        {
+            memberValue = new EnumMemberValue(typeNameIndex,
+                                              constNameIndex, pool);
+            super.enumMemberValue(typeNameIndex, constNameIndex);
+        }
+
+        void classMemberValue(int index) throws Exception {
+            memberValue = new ClassMemberValue(index, pool);
+            super.classMemberValue(index);
+        }
+
+        int annotationMemberValue(int pos) throws Exception {
+            Annotation anno = currentAnno;
+            pos = super.annotationMemberValue(pos);
+            memberValue = new AnnotationMemberValue(currentAnno, pool);
+            currentAnno = anno;
+            return pos;
+        }
+
+        int arrayMemberValue(int pos, int num) throws Exception {
+            ArrayMemberValue amv = new ArrayMemberValue(pool);
+            MemberValue[] elements = new MemberValue[num];
+            for (int i = 0; i < num; ++i) {
+                pos = memberValue(pos);
+                elements[i] = memberValue;
+            }
+
+            amv.setValue(elements);
+            memberValue = amv;
+            return pos;
+        }
+    }
 }
index b0744942307c41f4b11748217bd9f13a18580c1f..2e1e4fed1e5f91364fb01db98cba6530ebda539f 100644 (file)
@@ -28,395 +28,364 @@ import java.util.Map;
  * @see javassist.CtMethod#getMethodInfo()
  * @see javassist.CtConstructor#getMethodInfo()
  */
-public final class MethodInfo
-{
-   ConstPool constPool;
-   int accessFlags;
-   int name;
-   int descriptor;
-   LinkedList attribute;       // may be null
-
-   /**
-    * The name of constructors: <code>&lt;init&gt</code>.
-    */
-   public static final String nameInit = "<init>";
-
-   /**
-    * The name of class initializer (static initializer):
-    * <code>&lt;clinit&gt</code>.
-    */
-   public static final String nameClinit = "<clinit>";
-
-   private MethodInfo(ConstPool cp)
-   {
-      constPool = cp;
-      attribute = null;
-   }
-
-   /**
-    * Constructs a <code>method_info</code> structure.
-    * The initial value of <code>access_flags</code> is zero.
-    *
-    * @param cp         a constant pool table
-    * @param methodname method name
-    * @param desc       method descriptor
-    * @see Descriptor
-    */
-   public MethodInfo(ConstPool cp, String methodname, String desc)
-   {
-      this(cp);
-      accessFlags = 0;
-      name = cp.addUtf8Info(methodname);
-      descriptor = constPool.addUtf8Info(desc);
-   }
-
-   MethodInfo(ConstPool cp, DataInputStream in) throws IOException
-   {
-      this(cp);
-      read(in);
-   }
-
-   /**
-    * Constructs a copy of <code>method_info</code> structure.
-    * Class names appearing in the source <code>method_info</code>
-    * are renamed according to <code>classnameMap</code>.
-    * <p/>
-    * <p>Note: only <code>Code</code> and <code>Exceptions</code>
-    * attributes are copied from the source.  The other attributes
-    * are ignored.
-    *
-    * @param cp           a constant pool table
-    * @param methodname   a method name
-    * @param src          a source <code>method_info</code>
-    * @param classnameMap specifies pairs of replaced and substituted
-    *                     name.
-    * @see Descriptor
-    */
-   public MethodInfo(ConstPool cp, String methodname, MethodInfo src,
-                     Map classnameMap) throws BadBytecode
-   {
-      this(cp);
-      read(src, methodname, classnameMap);
-   }
-
-   void prune(ConstPool cp)
-   {
-      new Exception("****** pruned *****").printStackTrace();
-      attribute = null;
-      name = cp.addUtf8Info(getName());
-      descriptor = cp.addUtf8Info(getDescriptor());
-      constPool = cp;
-   }
-
-   /**
-    * Returns a method name.
-    */
-   public String getName()
-   {
-      return constPool.getUtf8Info(name);
-   }
-
-   /**
-    * Sets a method name.
-    */
-   public void setName(String newName)
-   {
-      name = constPool.addUtf8Info(newName);
-   }
-
-   /**
-    * Returns true if this is not a constructor or a class initializer
-    * (static initializer).
-    */
-   public boolean isMethod()
-   {
-      String n = getName();
-      return !n.equals(nameInit) && !n.equals(nameClinit);
-   }
-
-   /**
-    * Returns a constant pool table used by this method.
-    */
-   public ConstPool getConstPool()
-   {
-      return constPool;
-   }
-
-   /**
-    * Returns true if this is a constructor.
-    */
-   public boolean isConstructor()
-   {
-      return getName().equals(nameInit);
-   }
-
-   /**
-    * Returns true if this is a class initializer (static initializer).
-    */
-   public boolean isStaticInitializer()
-   {
-      return getName().equals(nameClinit);
-   }
-
-   /**
-    * Returns access flags.
-    *
-    * @see AccessFlag
-    */
-   public int getAccessFlags()
-   {
-      return accessFlags;
-   }
-
-   /**
-    * Sets access flags.
-    *
-    * @see AccessFlag
-    */
-   public void setAccessFlags(int acc)
-   {
-      accessFlags = acc;
-   }
-
-   /**
-    * Returns a method descriptor.
-    *
-    * @see Descriptor
-    */
-   public String getDescriptor()
-   {
-      return constPool.getUtf8Info(descriptor);
-   }
-
-   /**
-    * Sets a method descriptor.
-    *
-    * @see Descriptor
-    */
-   public void setDescriptor(String desc)
-   {
-      if (!desc.equals(getDescriptor()))
-         descriptor = constPool.addUtf8Info(desc);
-   }
-
-   /**
-    * Returns all the attributes.
-    * A new element can be added to the returned list
-    * and an existing element can be removed from the list.
-    *
-    * @return a list of <code>AttributeInfo</code> objects.
-    * @see AttributeInfo
-    */
-   public List getAttributes()
-   {
-      if (attribute == null)
-         attribute = new LinkedList();
-
-      return attribute;
-   }
-
-   /**
-    * Returns the attribute with the specified name.
-    * If it is not found, this method returns null.
-    *
-    * @param name attribute name
-    * @return an <code>AttributeInfo</code> object or null.
-    */
-   public AttributeInfo getAttribute(String name)
-   {
-      return AttributeInfo.lookup(attribute, name);
-   }
-
-   /**
-    * Appends an attribute.  If there is already an attribute with
-    * the same name, the new one substitutes for it.
-    */
-   public void addAttribute(AttributeInfo info)
-   {
-      if (attribute == null)
-         attribute = new LinkedList();
-
-      AttributeInfo.remove(attribute, info.getName());
-      attribute.add(info);
-   }
-
-   /**
-    * Returns an Exceptions attribute.
-    *
-    * @return an Exceptions attribute
-    *         or null if it is not specified.
-    */
-   public ExceptionsAttribute getExceptionsAttribute()
-   {
-      AttributeInfo info
-              = AttributeInfo.lookup(attribute, ExceptionsAttribute.tag);
-      return (ExceptionsAttribute) info;
-   }
-
-   /**
-    * Returns a Code attribute.
-    *
-    * @return a Code attribute
-    *         or null if it is not specified.
-    */
-   public CodeAttribute getCodeAttribute()
-   {
-      AttributeInfo info
-              = AttributeInfo.lookup(attribute, CodeAttribute.tag);
-      return (CodeAttribute) info;
-   }
-
-   /**
-    * Removes an Exception attribute.
-    */
-   public void removeExceptionsAttribute()
-   {
-      AttributeInfo.remove(attribute, ExceptionsAttribute.tag);
-   }
-
-   /**
-    * Adds an Exception attribute.
-    * <p/>
-    * <p>The added attribute must share the same constant pool table
-    * as this <code>method_info</code> structure.
-    */
-   public void setExceptionsAttribute(ExceptionsAttribute cattr)
-   {
-      removeExceptionsAttribute();
-      if (attribute == null)
-         attribute = new LinkedList();
-
-      attribute.add(cattr);
-   }
-
-   /**
-    * Removes a Code attribute.
-    */
-   public void removeCodeAttribute()
-   {
-      AttributeInfo.remove(attribute, CodeAttribute.tag);
-   }
-
-   /**
-    * Adds a Code attribute.
-    * <p/>
-    * <p>The added attribute must share the same constant pool table
-    * as this <code>method_info</code> structure.
-    */
-   public void setCodeAttribute(CodeAttribute cattr)
-   {
-      removeCodeAttribute();
-      if (attribute == null)
-         attribute = new LinkedList();
-
-      attribute.add(cattr);
-   }
-
-   /**
-    * Returns the line number of the source line corresponding to the
-    * specified bytecode contained in this method.
-    *
-    * @param pos the position of the bytecode (&gt;= 0).
-    *            an index into the code array.
-    * @return -1       if this information is not available.
-    */
-   public int getLineNumber(int pos)
-   {
-      CodeAttribute ca = getCodeAttribute();
-      if (ca == null)
-         return -1;
-
-      LineNumberAttribute ainfo =
-              (LineNumberAttribute) ca.getAttribute(LineNumberAttribute.tag);
-      if (ainfo == null)
-         return -1;
-
-      return ainfo.toLineNumber(pos);
-   }
-
-   /**
-    * Changes a super constructor called by this constructor.
-    * <p/>
-    * <p>This method modifies a call to <code>super()</code>,
-    * which should be at the
-    * head of a constructor body, so that a constructor in a different
-    * super class is called.  This method does not change actural
-    * parameters.  Hence the new super class must have a constructor
-    * with the same signature as the original one.
-    * <p/>
-    * <p>This method should be called when the super class
-    * of the class declaring this method is changed.
-    * <p/>
-    * <p>This method does not perform anything unless this
-    * <code>MethodInfo</code> represents a constructor.
-    *
-    * @param superclass the new super class
-    */
-   public void setSuperclass(String superclass) throws BadBytecode
-   {
-      if (!isConstructor())
-         return;
-
-      CodeAttribute ca = getCodeAttribute();
-      byte[] code = ca.getCode();
-      CodeIterator iterator = ca.iterator();
-      int pos = iterator.skipSuperConstructor();
-      if (pos >= 0)
-      { // not this()
-         ConstPool cp = constPool;
-         int mref = ByteArray.readU16bit(code, pos + 1);
-         int nt = cp.getMethodrefNameAndType(mref);
-         int sc = cp.addClassInfo(superclass);
-         int mref2 = cp.addMethodrefInfo(sc, nt);
-         ByteArray.write16bit(mref2, code, pos + 1);
-      }
-   }
-
-   private void read(MethodInfo src, String methodname, Map classnames)
-           throws BadBytecode
-   {
-      ConstPool destCp = constPool;
-      accessFlags = src.accessFlags;
-      name = destCp.addUtf8Info(methodname);
-
-      ConstPool srcCp = src.constPool;
-      String desc = srcCp.getUtf8Info(src.descriptor);
-      String desc2 = Descriptor.rename(desc, classnames);
-      descriptor = destCp.addUtf8Info(desc2);
-
-      attribute = new LinkedList();
-      ExceptionsAttribute eattr = src.getExceptionsAttribute();
-      if (eattr != null)
-         attribute.add(eattr.copy(destCp, classnames));
-
-      CodeAttribute cattr = src.getCodeAttribute();
-      if (cattr != null)
-         attribute.add(cattr.copy(destCp, classnames));
-   }
-
-   private void read(DataInputStream in) throws IOException
-   {
-      accessFlags = in.readUnsignedShort();
-      name = in.readUnsignedShort();
-      descriptor = in.readUnsignedShort();
-      int n = in.readUnsignedShort();
-      attribute = new LinkedList();
-      for (int i = 0; i < n; ++i)
-         attribute.add(AttributeInfo.read(constPool, in));
-   }
-
-   void write(DataOutputStream out) throws IOException
-   {
-      out.writeShort(accessFlags);
-      out.writeShort(name);
-      out.writeShort(descriptor);
-
-      if (attribute == null)
-         out.writeShort(0);
-      else
-      {
-         out.writeShort(attribute.size());
-         AttributeInfo.writeAll(attribute, out);
-      }
-   }
+public final class MethodInfo {
+    ConstPool constPool;
+    int accessFlags;
+    int name;
+    int descriptor;
+    LinkedList attribute;       // may be null
+
+    /**
+     * The name of constructors: <code>&lt;init&gt</code>.
+     */
+    public static final String nameInit = "<init>";
+
+    /**
+     * The name of class initializer (static initializer):
+     * <code>&lt;clinit&gt</code>.
+     */
+    public static final String nameClinit = "<clinit>";
+
+    private MethodInfo(ConstPool cp) {
+        constPool = cp;
+        attribute = null;
+    }
+
+    /**
+     * Constructs a <code>method_info</code> structure.
+     * The initial value of <code>access_flags</code> is zero.
+     *
+     * @param cp                a constant pool table
+     * @param methodname        method name
+     * @param desc              method descriptor
+     * @see Descriptor
+     */
+    public MethodInfo(ConstPool cp, String methodname, String desc) {
+        this(cp);
+        accessFlags = 0;
+        name = cp.addUtf8Info(methodname);
+        descriptor = constPool.addUtf8Info(desc);
+    }
+
+    MethodInfo(ConstPool cp, DataInputStream in) throws IOException {
+        this(cp);
+        read(in);
+    }
+
+    /**
+     * Constructs a copy of <code>method_info</code> structure.
+     * Class names appearing in the source <code>method_info</code>
+     * are renamed according to <code>classnameMap</code>.
+     *
+     * <p>Note: only <code>Code</code> and <code>Exceptions</code>
+     * attributes are copied from the source.  The other attributes
+     * are ignored.
+     *
+     * @param cp                a constant pool table
+     * @param methodname        a method name
+     * @param src               a source <code>method_info</code>
+     * @param classnameMap      specifies pairs of replaced and substituted
+     *                          name.
+     * @see Descriptor
+     */
+    public MethodInfo(ConstPool cp, String methodname, MethodInfo src,
+                      Map classnameMap) throws BadBytecode
+    {
+        this(cp);
+        read(src, methodname, classnameMap);
+    }
+
+    void prune(ConstPool cp) {
+        attribute = null;
+        name = cp.addUtf8Info(getName());
+        descriptor = cp.addUtf8Info(getDescriptor());
+        constPool = cp;
+    }
+
+    /**
+     * Returns a method name.
+     */
+    public String getName() {
+        return constPool.getUtf8Info(name);
+    }
+
+    /**
+     * Sets a method name.
+     */
+    public void setName(String newName) {
+        name = constPool.addUtf8Info(newName);
+    }
+
+    /**
+     * Returns true if this is not a constructor or a class initializer
+     * (static initializer).
+     */
+    public boolean isMethod() {
+        String n = getName();
+        return !n.equals(nameInit) && !n.equals(nameClinit);
+    }
+
+    /**
+     * Returns a constant pool table used by this method.
+     */
+    public ConstPool getConstPool() {
+        return constPool;
+    }
+
+    /**
+     * Returns true if this is a constructor.
+     */
+    public boolean isConstructor() {
+        return getName().equals(nameInit);
+    }
+
+    /**
+     * Returns true if this is a class initializer (static initializer).
+     */
+    public boolean isStaticInitializer() {
+        return getName().equals(nameClinit);
+    }
+
+    /**
+     * Returns access flags.
+     *
+     * @see AccessFlag
+     */
+    public int getAccessFlags() {
+        return accessFlags;
+    }
+
+    /**
+     * Sets access flags.
+     *
+     * @see AccessFlag
+     */
+    public void setAccessFlags(int acc) {
+        accessFlags = acc;
+    }
+
+    /**
+     * Returns a method descriptor.
+     *
+     * @see Descriptor
+     */
+    public String getDescriptor() {
+        return constPool.getUtf8Info(descriptor);
+    }
+
+    /**
+     * Sets a method descriptor.
+     *
+     * @see Descriptor
+     */
+    public void setDescriptor(String desc) {
+        if (!desc.equals(getDescriptor()))
+            descriptor = constPool.addUtf8Info(desc);
+    }
+
+    /**
+     * Returns all the attributes.
+     * A new element can be added to the returned list
+     * and an existing element can be removed from the list.
+     *
+     * @return a list of <code>AttributeInfo</code> objects.
+     * @see AttributeInfo
+     */
+    public List getAttributes() {
+        if (attribute == null)
+            attribute = new LinkedList();
+
+        return attribute;
+    }
+
+    /**
+     * Returns the attribute with the specified name.
+     * If it is not found, this method returns null.
+     *
+     * @param name      attribute name
+     * @return an <code>AttributeInfo</code> object or null.
+     */
+    public AttributeInfo getAttribute(String name) {
+        return AttributeInfo.lookup(attribute, name);
+    }
+
+    /**
+     * Appends an attribute.  If there is already an attribute with
+     * the same name, the new one substitutes for it.
+     */
+    public void addAttribute(AttributeInfo info) {
+        if (attribute == null)
+            attribute = new LinkedList();
+
+        AttributeInfo.remove(attribute, info.getName());
+        attribute.add(info);
+    }
+
+    /**
+     * Returns an Exceptions attribute.
+     *
+     * @return an Exceptions attribute
+     *         or null if it is not specified.
+     */
+    public ExceptionsAttribute getExceptionsAttribute() {
+        AttributeInfo info
+            = AttributeInfo.lookup(attribute, ExceptionsAttribute.tag);
+        return (ExceptionsAttribute)info;
+    }
+
+    /**
+     * Returns a Code attribute.
+     *
+     * @return a Code attribute
+     *         or null if it is not specified.
+     */
+    public CodeAttribute getCodeAttribute() {
+        AttributeInfo info
+            = AttributeInfo.lookup(attribute, CodeAttribute.tag);
+        return (CodeAttribute)info;
+    }
+
+    /**
+     * Removes an Exception attribute.
+     */
+    public void removeExceptionsAttribute() {
+        AttributeInfo.remove(attribute, ExceptionsAttribute.tag);
+    }
+
+    /**
+     * Adds an Exception attribute.
+     *
+     * <p>The added attribute must share the same constant pool table
+     * as this <code>method_info</code> structure.
+     */
+    public void setExceptionsAttribute(ExceptionsAttribute cattr) {
+        removeExceptionsAttribute();
+        if (attribute == null)
+            attribute = new LinkedList();
+
+        attribute.add(cattr);
+    }
+
+    /**
+     * Removes a Code attribute.
+     */
+    public void removeCodeAttribute() {
+        AttributeInfo.remove(attribute, CodeAttribute.tag);
+    }
+
+    /**
+     * Adds a Code attribute.
+     *
+     * <p>The added attribute must share the same constant pool table
+     * as this <code>method_info</code> structure.
+     */
+    public void setCodeAttribute(CodeAttribute cattr) {
+        removeCodeAttribute();
+        if (attribute == null)
+            attribute = new LinkedList();
+
+        attribute.add(cattr);
+    }
+
+    /**
+     * Returns the line number of the source line corresponding to the
+     * specified bytecode contained in this method.
+     *
+     * @param pos       the position of the bytecode (&gt;= 0).
+     *                  an index into the code array.
+     * @return -1       if this information is not available.
+     */
+    public int getLineNumber(int pos) {
+        CodeAttribute ca = getCodeAttribute();
+        if (ca == null)
+            return -1;
+
+        LineNumberAttribute ainfo =
+            (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
+        if (ainfo == null)
+            return -1;
+
+        return ainfo.toLineNumber(pos);
+    }
+
+    /**
+     * Changes a super constructor called by this constructor.
+     *
+     * <p>This method modifies a call to <code>super()</code>,
+     * which should be at the
+     * head of a constructor body, so that a constructor in a different
+     * super class is called.  This method does not change actural
+     * parameters.  Hence the new super class must have a constructor
+     * with the same signature as the original one.
+     *
+     * <p>This method should be called when the super class
+     * of the class declaring this method is changed.
+     *
+     * <p>This method does not perform anything unless this
+     * <code>MethodInfo</code> represents a constructor.
+     *
+     * @param superclass        the new super class
+     */
+    public void setSuperclass(String superclass) throws BadBytecode {
+        if (!isConstructor())
+            return;
+
+        CodeAttribute ca = getCodeAttribute();
+        byte[] code = ca.getCode();
+        CodeIterator iterator = ca.iterator();
+        int pos = iterator.skipSuperConstructor();
+        if (pos >= 0) { // not this()
+            ConstPool cp = constPool;
+            int mref = ByteArray.readU16bit(code, pos + 1);
+            int nt = cp.getMethodrefNameAndType(mref);
+            int sc = cp.addClassInfo(superclass);
+            int mref2 = cp.addMethodrefInfo(sc, nt);
+            ByteArray.write16bit(mref2, code, pos + 1);
+        }
+    }
+
+    private void read(MethodInfo src, String methodname, Map classnames)
+        throws BadBytecode
+    {
+        ConstPool destCp = constPool;
+        accessFlags = src.accessFlags;
+        name = destCp.addUtf8Info(methodname);
+
+        ConstPool srcCp = src.constPool;
+        String desc = srcCp.getUtf8Info(src.descriptor);
+        String desc2 = Descriptor.rename(desc, classnames);
+        descriptor = destCp.addUtf8Info(desc2);
+
+        attribute = new LinkedList();
+        ExceptionsAttribute eattr = src.getExceptionsAttribute();
+        if (eattr != null)
+            attribute.add(eattr.copy(destCp, classnames));
+
+        CodeAttribute cattr = src.getCodeAttribute();
+        if (cattr != null)
+            attribute.add(cattr.copy(destCp, classnames));
+    }
+
+    private void read(DataInputStream in) throws IOException {
+        accessFlags = in.readUnsignedShort();
+        name = in.readUnsignedShort();
+        descriptor = in.readUnsignedShort();
+        int n = in.readUnsignedShort();
+        attribute = new LinkedList();
+        for (int i = 0; i < n; ++i)
+            attribute.add(AttributeInfo.read(constPool, in));
+    }
+
+    void write(DataOutputStream out) throws IOException {
+        out.writeShort(accessFlags);
+        out.writeShort(name);
+        out.writeShort(descriptor);
+
+        if (attribute == null)
+            out.writeShort(0);
+        else {
+            out.writeShort(attribute.size());
+            AttributeInfo.writeAll(attribute, out);
+        }
+    }
 }
index 09a1075bc7d58169dab2c95bc1dc6a11760f6393..0be36b24ce857b54cbf7cee5545e18fee59e0312 100644 (file)
@@ -17,7 +17,6 @@ package javassist.bytecode.annotation;
 
 import javassist.bytecode.ConstPool;
 import javassist.bytecode.Descriptor;
-
 import java.io.IOException;
 
 /**
@@ -26,83 +25,74 @@ import java.io.IOException;
  * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
  * @author Shigeru Chiba
  */
-public class ClassMemberValue extends MemberValue
-{
-   int valueIndex;
+public class ClassMemberValue extends MemberValue {
+    int valueIndex;
 
-   /**
-    * Constructs a string constant value.  The initial value is specified
-    * by the constant pool entry at the given index.
-    *
-    * @param index the index of a CONSTANT_Utf8_info structure.
-    */
-   public ClassMemberValue(int index, ConstPool cp)
-   {
-      super('c', cp);
-      this.valueIndex = index;
-   }
+    /**
+     * Constructs a string constant value.  The initial value is specified
+     * by the constant pool entry at the given index.
+     *
+     * @param index the index of a CONSTANT_Utf8_info structure.
+     */
+    public ClassMemberValue(int index, ConstPool cp) {
+        super('c', cp);
+        this.valueIndex = index;
+    }
 
-   /**
-    * Constructs a string constant value.
-    *
-    * @param className the initial value.
-    */
-   public ClassMemberValue(String className, ConstPool cp)
-   {
-      super('c', cp);
-      setValue(className);
-   }
+    /**
+     * Constructs a string constant value.
+     *
+     * @param className         the initial value.
+     */
+    public ClassMemberValue(String className, ConstPool cp) {
+        super('c', cp);
+        setValue(className);
+    }
 
-   /**
-    * Constructs a string constant value.
-    * The initial value is java.lang.Class.
-    */
-   public ClassMemberValue(ConstPool cp)
-   {
-      super('c', cp);
-      setValue("java.lang.Class");
-   }
+    /**
+     * Constructs a string constant value.
+     * The initial value is java.lang.Class.
+     */
+    public ClassMemberValue(ConstPool cp) {
+        super('c', cp);
+        setValue("java.lang.Class");
+    }
 
-   /**
-    * Obtains the value of the member.
-    *
-    * @return fully-qualified class name.
-    */
-   public String getValue()
-   {
-      String v = cp.getUtf8Info(valueIndex);
-      return Descriptor.toClassName(v);
-   }
+    /**
+     * Obtains the value of the member.
+     *
+     * @return fully-qualified class name.
+     */
+    public String getValue() {
+        String v = cp.getUtf8Info(valueIndex);
+        return Descriptor.toClassName(v);
+    }
 
-   /**
-    * Sets the value of the member.
-    *
-    * @param newClassName fully-qualified class name.
-    */
-   public void setValue(String newClassName)
-   {
-      String setTo = Descriptor.of(newClassName);
-      valueIndex = cp.addUtf8Info(setTo);
-   }
+    /**
+     * Sets the value of the member.
+     *
+     * @param newClassName      fully-qualified class name.
+     */
+    public void setValue(String newClassName) {
+        String setTo = Descriptor.of(newClassName);
+        valueIndex = cp.addUtf8Info(setTo);
+    }
 
-   /**
-    * Obtains the string representation of this object.
-    */
-   public String toString()
-   {
-      return "<" + getValue() + " class>";
-   }
+    /**
+     * Obtains the string representation of this object.
+     */
+    public String toString() {
+        return "<" + getValue() + " class>";
+    }
 
-   void write(AnnotationsWriter writer) throws IOException
-   {
-      writer.classInfoIndex(valueIndex);
-   }
+    void write(AnnotationsWriter writer) throws IOException {
+        writer.classInfoIndex(valueIndex);
+    }
 
-   /**
-    * Accepts a visitor.
-    */
-   public void accept(MemberValueVisitor visitor)
-   {
-      visitor.visitClassMemberValue(this);
-   }
+    /**
+     * Accepts a visitor.
+     */
+    public void accept(MemberValueVisitor visitor) {
+        visitor.visitClassMemberValue(this);
+    }
 }