/* Proxy.java -- build a proxy class that implements reflected interfaces
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.lang.reflect;

import gnu.java.lang.reflect.TypeSignature;

import java.io.Serializable;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * This class allows you to dynamically create an instance of any (or
 * even multiple) interfaces by reflection, and decide at runtime
 * how that instance will behave by giving it an appropriate
 * {@link InvocationHandler}.  Proxy classes serialize specially, so
 * that the proxy object can be reused between VMs, without requiring
 * a persistent copy of the generated class code.
 *
 * <h3>Creation</h3>
 * To create a proxy for some interface Foo:
 *
 * <pre>
 *   InvocationHandler handler = new MyInvocationHandler(...);
 *   Class proxyClass = Proxy.getProxyClass(
 *       Foo.class.getClassLoader(), new Class[] { Foo.class });
 *   Foo f = (Foo) proxyClass
 *       .getConstructor(new Class[] { InvocationHandler.class })
 *       .newInstance(new Object[] { handler });
 * </pre>
 * or more simply:
 * <pre>
 *   Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
 *                                        new Class[] { Foo.class },
 *                                        handler);
 * </pre>
 *
 * <h3>Dynamic Proxy Classes</h3>
 * A dynamic proxy class is created at runtime, and has the following
 * properties:
 * <ul>
 *  <li>The class is <code>public</code> and <code>final</code>,
 *      and is neither <code>abstract</code> nor an inner class.</li>
 *  <li>The class has no canonical name (there is no formula you can use
 *      to determine or generate its name), but begins with the
 *      sequence "$Proxy".  Abuse this knowledge at your own peril.
 *      (For now, '$' in user identifiers is legal, but it may not
 *      be that way forever. You weren't using '$' in your
 *      identifiers, were you?)</li>
 *  <li>The class extends Proxy, and explicitly implements all the
 *      interfaces specified at creation, in order (this is important
 *      for determining how method invocation is resolved).  Note that
 *      a proxy class implements {@link Serializable}, at least
 *      implicitly, since Proxy does, but true serial behavior
 *      depends on using a serializable invocation handler as well.</li>
 *  <li>If at least one interface is non-public, the proxy class
 *      will be in the same package.  Otherwise, the package is
 *      unspecified.  This will work even if the package is sealed
 *      from user-generated classes, because Proxy classes are
 *      generated by a trusted source.  Meanwhile, the proxy class
 *      belongs to the classloader you designated.</li>
 *  <li>Reflection works as expected: {@link Class#getInterfaces()} and
 *      {@link Class#getMethods()} work as they do on normal classes.</li>
 *  <li>The method {@link #isProxyClass(Class)} will distinguish between
 *      true proxy classes and user extensions of this class.  It only
 *      returns true for classes created by {@link #getProxyClass}.</li>
 *  <li>The {@link ProtectionDomain} of a proxy class is the same as for
 *      bootstrap classes, such as Object or Proxy, since it is created by
 *      a trusted source.  This protection domain will typically be granted
 *      {@link java.security.AllPermission}. But this is not a security
 *      risk, since there are adequate permissions on reflection, which is
 *      the only way to create an instance of the proxy class.</li>
 *  <li>The proxy class contains a single constructor, which takes as
 *      its only argument an {@link InvocationHandler}.  The method
 *      {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
 *      is shorthand to do the necessary reflection.</li>
 * </ul>
 *
 * <h3>Proxy Instances</h3>
 * A proxy instance is an instance of a proxy class.  It has the
 * following properties, many of which follow from the properties of a
 * proxy class listed above:
 * <ul>
 *  <li>For a proxy class with Foo listed as one of its interfaces, the
 *      expression <code>proxy instanceof Foo</code> will return true,
 *      and the expression <code>(Foo) proxy</code> will succeed without
 *      a {@link ClassCastException}.</li>
 *  <li>Each proxy instance has an invocation handler, which can be
 *      accessed by {@link #getInvocationHandler(Object)}.  Any call
 *      to an interface method, including {@link Object#hashCode()},
 *      {@link Object#equals(Object)}, or {@link Object#toString()},
 *      but excluding the public final methods of Object, will be
 *      encoded and passed to the {@link InvocationHandler#invoke}
 *      method of this handler.</li>
 * </ul>
 *
 * <h3>Inheritance Issues</h3>
 * A proxy class may inherit a method from more than one interface.
 * The order in which interfaces are listed matters, because it determines
 * which reflected {@link Method} object will be passed to the invocation
 * handler.  This means that the dynamically generated class cannot
 * determine through which interface a method is being invoked.<p>
 *
 * In short, if a method is declared in Object (namely, hashCode,
 * equals, or toString), then Object will be used; otherwise, the
 * leftmost interface that inherits or declares a method will be used,
 * even if it has a more permissive throws clause than what the proxy
 * class is allowed. Thus, in the invocation handler, it is not always
 * safe to assume that every class listed in the throws clause of the
 * passed Method object can safely be thrown; fortunately, the Proxy
 * instance is robust enough to wrap all illegal checked exceptions in
 * {@link UndeclaredThrowableException}.
 *
 * @see InvocationHandler
 * @see UndeclaredThrowableException
 * @see Class
 * @author Eric Blake (ebb9@email.byu.edu)
 * @since 1.3
 * @status updated to 1.4, except for the use of ProtectionDomain
 */
public class Proxy implements Serializable
{
  /**
   * Compatible with JDK 1.3+.
   */
  private static final long serialVersionUID = -2222568056686623797L;

  /**
   * Map of ProxyType to proxy class.
   *
   * @XXX This prevents proxy classes from being garbage collected.
   * java.util.WeakHashSet is not appropriate, because that collects the
   * keys, but we are interested in collecting the elements.
   */
  private static final Map proxyClasses = new HashMap();

  /**
   * The invocation handler for this proxy instance.  For Proxy, this
   * field is unused, but it appears here in order to be serialized in all
   * proxy classes.
   *
   * <em>NOTE</em>: This implementation is more secure for proxy classes
   * than what Sun specifies. Sun does not require h to be immutable, but
   * this means you could change h after the fact by reflection.  However,
   * by making h immutable, we may break non-proxy classes which extend
   * Proxy.
   * @serial invocation handler associated with this proxy instance
   */
  protected InvocationHandler h;

  /**
   * Constructs a new Proxy from a subclass (usually a proxy class),
   * with the specified invocation handler.
   *
   * <em>NOTE</em>: This throws a NullPointerException if you attempt
   * to create a proxy instance with a null handler using reflection.
   * This behavior is not yet specified by Sun; see Sun Bug 4487672.
   *
   * @param handler the invocation handler, may be null if the subclass
   *        is not a proxy class
   * @throws NullPointerException if handler is null and this is a proxy
   *         instance
   */
  protected Proxy(InvocationHandler handler)
  {
    if (handler == null && isProxyClass(getClass()))
      throw new NullPointerException("invalid handler");
    h = handler;
  }

  /**
   * Returns the proxy {@link Class} for the given ClassLoader and array
   * of interfaces, dynamically generating it if necessary.
   *
   * <p>There are several restrictions on this method, the violation of
   * which will result in an IllegalArgumentException or
   * NullPointerException:</p>
   * 
   * <ul>
   * <li>All objects in `interfaces' must represent distinct interfaces.
   *     Classes, primitive types, null, and duplicates are forbidden.</li>
   * <li>The interfaces must be visible in the specified ClassLoader.
   *     In other words, for each interface i:
   *     <code>Class.forName(i.getName(), false, loader) == i</code>
   *     must be true.</li>
   * <li>All non-public interfaces (if any) must reside in the same
   *     package, or the proxy class would be non-instantiable.  If
   *     there are no non-public interfaces, the package of the proxy
   *     class is unspecified.</li>
   * <li>All interfaces must be compatible - if two declare a method
   *     with the same name and parameters, the return type must be
   *     the same and the throws clause of the proxy class will be
   *     the maximal subset of subclasses of the throws clauses for
   *     each method that is overridden.</li>
   * <li>VM constraints limit the number of interfaces a proxy class
   *     may directly implement (however, the indirect inheritance
   *     of {@link Serializable} does not count against this limit).
   *     Even though most VMs can theoretically have 65535
   *     superinterfaces for a class, the actual limit is smaller
   *     because a class's constant pool is limited to 65535 entries,
   *     and not all entries can be interfaces.</li>
   * </ul>
   *
   * <p>Note that different orders of interfaces produce distinct classes.</p>
   *
   * @param loader the class loader to define the proxy class in; null
   *        implies the bootstrap class loader
   * @param interfaces the array of interfaces the proxy class implements,
   *        may be empty, but not null
   * @return the Class object of the proxy class
   * @throws IllegalArgumentException if the constraints above were
   *         violated, except for problems with null
   * @throws NullPointerException if `interfaces' is null or contains
   *         a null entry
   */
  // synchronized so that we aren't trying to build the same class
  // simultaneously in two threads
  public static synchronized Class getProxyClass(ClassLoader loader,
                                                 Class[] interfaces)
  {
    interfaces = (Class[]) interfaces.clone();
    ProxyType pt = new ProxyType(loader, interfaces);
    Class clazz = (Class) proxyClasses.get(pt);
    if (clazz == null)
      {
        if (VMProxy.HAVE_NATIVE_GET_PROXY_CLASS)
          clazz = VMProxy.getProxyClass(loader, interfaces);
        else
          {
            ProxyData data = (VMProxy.HAVE_NATIVE_GET_PROXY_DATA
                              ? VMProxy.getProxyData(loader, interfaces)
                              : ProxyData.getProxyData(pt));

            clazz = (VMProxy.HAVE_NATIVE_GENERATE_PROXY_CLASS
		     ? VMProxy.generateProxyClass(loader, data)
                     : new ClassFactory(data).generate(loader));
          }

        Object check = proxyClasses.put(pt, clazz);
        // assert check == null && clazz != null;
        if (check != null || clazz == null)
          throw new InternalError(/*"Fatal flaw in getProxyClass"*/);
      }
    return clazz;
  }

  /**
   * Combines several methods into one.  This is equivalent to:
   * <pre>
   *   Proxy.getProxyClass(loader, interfaces)
   *       .getConstructor(new Class[] {InvocationHandler.class})
   *       .newInstance(new Object[] {handler});
   * </pre>
   * except that it will not fail with the normal problems caused
   * by reflection.  It can still fail for the same reasons documented
   * in getProxyClass, or if handler is null.
   *
   * @param loader the class loader to define the proxy class in; null
   *        implies the bootstrap class loader
   * @param interfaces the array of interfaces the proxy class implements,
   *        may be empty, but not null
   * @param handler the invocation handler, may not be null
   * @return a proxy instance implementing the specified interfaces
   * @throws IllegalArgumentException if the constraints for getProxyClass
   *         were violated, except for problems with null
   * @throws NullPointerException if `interfaces' is null or contains
   *         a null entry, or if handler is null
   * @see #getProxyClass(ClassLoader, Class[])
   * @see Class#getConstructor(Class[])
   * @see Constructor#newInstance(Object[])
   */
  public static Object newProxyInstance(ClassLoader loader,
                                        Class[] interfaces,
                                        InvocationHandler handler)
  {
    try
      {
        // getProxyClass() and Proxy() throw the necessary exceptions
        return getProxyClass(loader, interfaces)
          .getConstructor(new Class[] {InvocationHandler.class})
          .newInstance(new Object[] {handler});
      }
    catch (RuntimeException e)
      {
        // Let IllegalArgumentException, NullPointerException escape.
        // assert e instanceof IllegalArgumentException
        //   || e instanceof NullPointerException;
        throw e;
      }
    catch (InvocationTargetException e)
      {
        // Let wrapped NullPointerException escape.
        // assert e.getTargetException() instanceof NullPointerException
        throw (NullPointerException) e.getCause();
      }
    catch (Exception e)
      {
        // Covers InstantiationException, IllegalAccessException,
        // NoSuchMethodException, none of which should be generated
        // if the proxy class was generated correctly.
        // assert false;
        throw (Error) new InternalError("Unexpected: " + e).initCause(e);
      }
  }

  /**
   * Returns true if and only if the Class object is a dynamically created
   * proxy class (created by <code>getProxyClass</code> or by the
   * syntactic sugar of <code>newProxyInstance</code>).
   *
   * <p>This check is secure (in other words, it is not simply
   * <code>clazz.getSuperclass() == Proxy.class</code>), it will not
   * be spoofed by non-proxy classes that extend Proxy.
   *
   * @param clazz the class to check, must not be null
   * @return true if the class represents a proxy class
   * @throws NullPointerException if clazz is null
   */
  // This is synchronized on the off chance that another thread is
  // trying to add a class to the map at the same time we read it.
  public static synchronized boolean isProxyClass(Class clazz)
  {
    if (! Proxy.class.isAssignableFrom(clazz))
      return false;
    // This is a linear search, even though we could do an O(1) search
    // using new ProxyType(clazz.getClassLoader(), clazz.getInterfaces()).
    return proxyClasses.containsValue(clazz);
  }

  /**
   * Returns the invocation handler for the given proxy instance.<p>
   *
   * <em>NOTE</em>: We guarantee a non-null result if successful,
   * but Sun allows the creation of a proxy instance with a null
   * handler.  See the comments for {@link #Proxy(InvocationHandler)}.
   *
   * @param proxy the proxy instance, must not be null
   * @return the invocation handler, guaranteed non-null.
   * @throws IllegalArgumentException if
   *         <code>Proxy.isProxyClass(proxy.getClass())</code> returns false.
   * @throws NullPointerException if proxy is null
   */
  public static InvocationHandler getInvocationHandler(Object proxy)
  {
    if (! isProxyClass(proxy.getClass()))
      throw new IllegalArgumentException("not a proxy instance");
    return ((Proxy) proxy).h;
  }

  /**
   * Helper class for mapping unique ClassLoader and interface combinations
   * to proxy classes.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class ProxyType
  {
    /**
     * Store the class loader (may be null)
     */
    final ClassLoader loader;

    /**
     * Store the interfaces (never null, all elements are interfaces)
     */
    final Class[] interfaces;

    /**
     * Construct the helper object.
     *
     * @param loader the class loader to define the proxy class in; null
     *        implies the bootstrap class loader
     * @param interfaces an array of interfaces
     */
    ProxyType(ClassLoader loader, Class[] interfaces)
    {
      this.loader = loader;
      this.interfaces = interfaces;
    }

    /**
     * Calculates the hash code.
     *
     * @return a combination of the classloader and interfaces hashcodes.
     */
    public int hashCode()
    {
      int hash = loader == null ? 0 : loader.hashCode();
      for (int i = 0; i < interfaces.length; i++)
        hash = hash * 31 + interfaces[i].hashCode();
      return hash;
    }

    /**
     * Calculates equality.
     *
     * @param other object to compare to
     * @return true if it is a ProxyType with same data
     */
    public boolean equals(Object other)
    {
      ProxyType pt = (ProxyType) other;
      if (loader != pt.loader || interfaces.length != pt.interfaces.length)
        return false;
      for (int i = 0; i < interfaces.length; i++)
        if (interfaces[i] != pt.interfaces[i])
          return false;
      return true;
    }
  } // class ProxyType

  /**
   * Helper class which allows hashing of a method name and signature
   * without worrying about return type, declaring class, or throws clause,
   * and which reduces the maximally common throws clause between two methods
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class ProxySignature
  {
    /**
     * The core signatures which all Proxy instances handle.
     */
    static final HashMap coreMethods = new HashMap();
    static
    {
      try
        {
          ProxySignature sig
            = new ProxySignature(Object.class
                                 .getMethod("equals",
                                            new Class[] {Object.class}));
          coreMethods.put(sig, sig);
          sig = new ProxySignature(Object.class.getMethod("hashCode", null));
          coreMethods.put(sig, sig);
          sig = new ProxySignature(Object.class.getMethod("toString", null));
          coreMethods.put(sig, sig);
        }
      catch (Exception e)
        {
          // assert false;
          throw (Error) new InternalError("Unexpected: " + e).initCause(e);
        }
    }

    /**
     * The underlying Method object, never null
     */
    final Method method;

    /**
     * The set of compatible thrown exceptions, may be empty
     */
    final Set exceptions = new HashSet();

    /**
     * Construct a signature
     *
     * @param method the Method this signature is based on, never null
     */
    ProxySignature(Method method)
    {
      this.method = method;
      Class[] exc = method.getExceptionTypes();
      int i = exc.length;
      while (--i >= 0)
        {
          // discard unchecked exceptions
          if (Error.class.isAssignableFrom(exc[i])
              || RuntimeException.class.isAssignableFrom(exc[i]))
            continue;
          exceptions.add(exc[i]);
        }
    }

    /**
     * Given a method, make sure it's return type is identical
     * to this, and adjust this signature's throws clause appropriately
     *
     * @param other the signature to merge in
     * @throws IllegalArgumentException if the return types conflict
     */
    void checkCompatibility(ProxySignature other)
    {
      if (method.getReturnType() != other.method.getReturnType())
        throw new IllegalArgumentException("incompatible return types: "
                                           + method + ", " + other.method);

      // if you can think of a more efficient way than this O(n^2) search,
      // implement it!
      int size1 = exceptions.size();
      int size2 = other.exceptions.size();
      boolean[] valid1 = new boolean[size1];
      boolean[] valid2 = new boolean[size2];
      Iterator itr = exceptions.iterator();
      int pos = size1;
      while (--pos >= 0)
        {
          Class c1 = (Class) itr.next();
          Iterator itr2 = other.exceptions.iterator();
          int pos2 = size2;
          while (--pos2 >= 0)
            {
              Class c2 = (Class) itr2.next();
              if (c2.isAssignableFrom(c1))
                valid1[pos] = true;
              if (c1.isAssignableFrom(c2))
                valid2[pos2] = true;
            }
        }
      pos = size1;
      itr = exceptions.iterator();
      while (--pos >= 0)
        {
          itr.next();
          if (! valid1[pos])
            itr.remove();
        }
      pos = size2;
      itr = other.exceptions.iterator();
      while (--pos >= 0)
        {
          itr.next();
          if (! valid2[pos])
            itr.remove();
        }
      exceptions.addAll(other.exceptions);
    }

    /**
     * Calculates the hash code.
     *
     * @return a combination of name and parameter types
     */
    public int hashCode()
    {
      int hash = method.getName().hashCode();
      Class[] types = method.getParameterTypes();
      for (int i = 0; i < types.length; i++)
        hash = hash * 31 + types[i].hashCode();
      return hash;
    }

    /**
     * Calculates equality.
     *
     * @param other object to compare to
     * @return true if it is a ProxySignature with same data
     */
    public boolean equals(Object other)
    {
      ProxySignature ps = (ProxySignature) other;
      Class[] types1 = method.getParameterTypes();
      Class[] types2 = ps.method.getParameterTypes();
      if (! method.getName().equals(ps.method.getName())
          || types1.length != types2.length)
        return false;
      int i = types1.length;
      while (--i >= 0)
        if (types1[i] != types2[i])
          return false;
      return true;
    }
  } // class ProxySignature

  /**
   * A flat representation of all data needed to generate bytecode/instantiate
   * a proxy class.  This is basically a struct.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  static final class ProxyData
  {
    /**
     * The package this class is in <b>including the trailing dot</b>
     * or an empty string for the unnamed (aka default) package.
     */
    String pack = "";

    /**
     * The interfaces this class implements.  Non-null, but possibly empty.
     */
    Class[] interfaces;

    /**
     * The Method objects this class must pass as the second argument to
     * invoke (also useful for determining what methods this class has).
     * Non-null, non-empty (includes at least Object.hashCode, Object.equals,
     * and Object.toString).
     */
    Method[] methods;

    /**
     * The exceptions that do not need to be wrapped in
     * UndeclaredThrowableException. exceptions[i] is the same as, or a
     * subset of subclasses, of methods[i].getExceptionTypes(), depending on
     * compatible throws clauses with multiple inheritance. It is unspecified
     * if these lists include or exclude subclasses of Error and
     * RuntimeException, but excluding them is harmless and generates a
     * smaller class.
     */
    Class[][] exceptions;

    /**
     * For unique id's
     */
    private static int count;

    /**
     * The id of this proxy class
     */
    final int id = count++;

    /**
     * Construct a ProxyData with uninitialized data members.
     */
    ProxyData()
    {
    }

    /**
     * Return the name of a package (including the trailing dot)
     * given the name of a class.
     * Returns an empty string if no package.  We use this in preference to
     * using Class.getPackage() to avoid problems with ClassLoaders
     * that don't set the package.
     */
    private static String getPackage(Class k)
    {
      String name = k.getName();
      int idx = name.lastIndexOf('.');
      return name.substring(0, idx + 1);
    }

    /**
     * Verifies that the arguments are legal, and sets up remaining data
     * This should only be called when a class must be generated, as
     * it is expensive.
     *
     * @param pt the ProxyType to convert to ProxyData
     * @return the flattened, verified ProxyData structure for use in
     *         class generation
     * @throws IllegalArgumentException if `interfaces' contains
     *         non-interfaces or incompatible combinations, and verify is true
     * @throws NullPointerException if interfaces is null or contains null
     */
    static ProxyData getProxyData(ProxyType pt)
    {
      Map method_set = (Map) ProxySignature.coreMethods.clone();
      boolean in_package = false; // true if we encounter non-public interface

      ProxyData data = new ProxyData();
      data.interfaces = pt.interfaces;

      // if interfaces is too large, we croak later on when the constant
      // pool overflows
      int i = data.interfaces.length;
      while (--i >= 0)
        {
          Class inter = data.interfaces[i];
          if (! inter.isInterface())
            throw new IllegalArgumentException("not an interface: " + inter);
          try
            {
              if (Class.forName(inter.getName(), false, pt.loader) != inter)
                throw new IllegalArgumentException("not accessible in "
                                                   + "classloader: " + inter);
            }
          catch (ClassNotFoundException e)
            {
              throw new IllegalArgumentException("not accessible in "
                                                 + "classloader: " + inter);
            }
          if (! Modifier.isPublic(inter.getModifiers()))
            if (in_package)
              {
		String p = getPackage(inter);
                if (! data.pack.equals(p))
                  throw new IllegalArgumentException("non-public interfaces "
                                                     + "from different "
                                                     + "packages");
              }
            else
              {
                in_package = true;
                data.pack = getPackage(inter);
              }
          for (int j = i-1; j >= 0; j--)
            if (data.interfaces[j] == inter)
              throw new IllegalArgumentException("duplicate interface: "
                                                 + inter);
          Method[] methods = inter.getMethods();
          int j = methods.length;
          while (--j >= 0)
            {
              if (isCoreObjectMethod(methods[j]))
                {
                  // In the case of an attempt to redefine a public non-final
                  // method of Object, we must skip it
                  continue;
                }
              ProxySignature sig = new ProxySignature(methods[j]);
              ProxySignature old = (ProxySignature) method_set.put(sig, sig);
              if (old != null)
                sig.checkCompatibility(old);
            }
        }

      i = method_set.size();
      data.methods = new Method[i];
      data.exceptions = new Class[i][];
      Iterator itr = method_set.values().iterator();
      while (--i >= 0)
        {
          ProxySignature sig = (ProxySignature) itr.next();
          data.methods[i] = sig.method;
          data.exceptions[i] = (Class[]) sig.exceptions
            .toArray(new Class[sig.exceptions.size()]);
        }
      return data;
    }

    /**
     * Checks whether the method is similar to a public non-final method of
     * Object or not (i.e. with the same name and parameter types). Note that we
     * can't rely, directly or indirectly (via Collection.contains) on
     * Method.equals as it would also check the declaring class, what we do not
     * want. We only want to check that the given method have the same signature
     * as a core method (same name and parameter types)
     * 
     * @param method the method to check
     * @return whether the method has the same name and parameter types as
     *         Object.equals, Object.hashCode or Object.toString
     * @see java.lang.Object#equals(Object)
     * @see java.lang.Object#hashCode()
     * @see java.lang.Object#toString()
     */
    private static boolean isCoreObjectMethod(Method method)
    {
      String methodName = method.getName();
      if (methodName.equals("equals"))
        {
          return Arrays.equals(method.getParameterTypes(),
                               new Class[] { Object.class });
        }
      if (methodName.equals("hashCode"))
        {
          return method.getParameterTypes().length == 0;
        }
      if (methodName.equals("toString"))
        {
          return method.getParameterTypes().length == 0;
        }
      return false;
    }
    
  } // class ProxyData

  /**
   * Does all the work of building a class. By making this a nested class,
   * this code is not loaded in memory if the VM has a native
   * implementation instead.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class ClassFactory
  {
    /** Constants for assisting the compilation */
    private static final byte FIELD = 1;
    private static final byte METHOD = 2;
    private static final byte INTERFACE = 3;
    private static final String CTOR_SIG
      = "(Ljava/lang/reflect/InvocationHandler;)V";
    private static final String INVOKE_SIG = "(Ljava/lang/Object;"
      + "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";

    /** Bytecodes for insertion in the class definition byte[] */
    private static final char ACONST_NULL = 1;
    private static final char ICONST_0 = 3;
    private static final char BIPUSH = 16;
    private static final char SIPUSH = 17;
    private static final char ILOAD = 21;
    private static final char ILOAD_0 = 26;
    private static final char ALOAD_0 = 42;
    private static final char ALOAD_1 = 43;
    private static final char AALOAD = 50;
    private static final char AASTORE = 83;
    private static final char DUP = 89;
    private static final char DUP_X1 = 90;
    private static final char SWAP = 95;
    private static final char IRETURN = 172;
    private static final char LRETURN = 173;
    private static final char FRETURN = 174;
    private static final char DRETURN = 175;
    private static final char ARETURN = 176;
    private static final char RETURN = 177;
    private static final char GETSTATIC = 178;
    private static final char GETFIELD = 180;
    private static final char INVOKEVIRTUAL = 182;
    private static final char INVOKESPECIAL = 183;
    private static final char INVOKEINTERFACE = 185;
    private static final char NEW = 187;
    private static final char ANEWARRAY = 189;
    private static final char ATHROW = 191;
    private static final char CHECKCAST = 192;

    // Implementation note: we use StringBuffers to hold the byte data, since
    // they automatically grow.  However, we only use the low 8 bits of
    // every char in the array, so we are using twice the necessary memory
    // for the ease StringBuffer provides.

    /** The constant pool. */
    private final StringBuffer pool = new StringBuffer();
    /** The rest of the class data. */
    private final StringBuffer stream = new StringBuffer();

    /** Map of strings to byte sequences, to minimize size of pool. */
    private final Map poolEntries = new HashMap();

    /** The VM name of this proxy class. */
    private final String qualName;

    /**
     * The Method objects the proxy class refers to when calling the
     * invocation handler.
     */
    private final Method[] methods;

    /**
     * Initializes the buffers with the bytecode contents for a proxy class.
     *
     * @param data the remainder of the class data
     * @throws IllegalArgumentException if anything else goes wrong this
     *         late in the game; as far as I can tell, this will only happen
     *         if the constant pool overflows, which is possible even when
     *         the user doesn't exceed the 65535 interface limit
     */
    ClassFactory(ProxyData data)
    {
      methods = data.methods;

      // magic = 0xcafebabe
      // minor_version = 0
      // major_version = 46
      // constant_pool_count: place-holder for now
      pool.append("\u00ca\u00fe\u00ba\u00be\0\0\0\56\0\0");
      // constant_pool[], filled in as we go

      // access_flags
      putU2(Modifier.SUPER | Modifier.FINAL | Modifier.PUBLIC);
      // this_class
      qualName = (data.pack + "$Proxy" + data.id);
      putU2(classInfo(TypeSignature.getEncodingOfClass(qualName, false)));
      // super_class
      putU2(classInfo("java/lang/reflect/Proxy"));

      // interfaces_count
      putU2(data.interfaces.length);
      // interfaces[]
      for (int i = 0; i < data.interfaces.length; i++)
        putU2(classInfo(data.interfaces[i]));

      // Recall that Proxy classes serialize specially, so we do not need
      // to worry about a <clinit> method for this field.  Instead, we
      // just assign it by reflection after the class is successfully loaded.
      // fields_count - private static Method[] m;
      putU2(1);
      // fields[]
      // m.access_flags
      putU2(Modifier.PRIVATE | Modifier.STATIC);
      // m.name_index
      putU2(utf8Info("m"));
      // m.descriptor_index
      putU2(utf8Info("[Ljava/lang/reflect/Method;"));
      // m.attributes_count
      putU2(0);
      // m.attributes[]

      // methods_count - # handler methods, plus <init>
      putU2(methods.length + 1);
      // methods[]
      // <init>.access_flags
      putU2(Modifier.PUBLIC);
      // <init>.name_index
      putU2(utf8Info("<init>"));
      // <init>.descriptor_index
      putU2(utf8Info(CTOR_SIG));
      // <init>.attributes_count - only Code is needed
      putU2(1);
      // <init>.Code.attribute_name_index
      putU2(utf8Info("Code"));
      // <init>.Code.attribute_length = 18
      // <init>.Code.info:
      //   $Proxynn(InvocationHandler h) { super(h); }
      // <init>.Code.max_stack = 2
      // <init>.Code.max_locals = 2
      // <init>.Code.code_length = 6
      // <init>.Code.code[]
      stream.append("\0\0\0\22\0\2\0\2\0\0\0\6" + ALOAD_0 + ALOAD_1
                    + INVOKESPECIAL);
      putU2(refInfo(METHOD, "java/lang/reflect/Proxy", "<init>", CTOR_SIG));
      // <init>.Code.exception_table_length = 0
      // <init>.Code.exception_table[]
      // <init>.Code.attributes_count = 0
      // <init>.Code.attributes[]
      stream.append(RETURN + "\0\0\0\0");

      for (int i = methods.length - 1; i >= 0; i--)
        emitMethod(i, data.exceptions[i]);

      // attributes_count
      putU2(0);
      // attributes[] - empty; omit SourceFile attribute
      // XXX should we mark this with a Synthetic attribute?
    }

    /**
     * Produce the bytecode for a single method.
     *
     * @param i the index of the method we are building
     * @param e the exceptions possible for the method
     */
    private void emitMethod(int i, Class[] e)
    {
      // First, we precalculate the method length and other information.

      Method m = methods[i];
      Class[] paramtypes = m.getParameterTypes();
      int wrap_overhead = 0; // max words taken by wrapped primitive
      int param_count = 1; // 1 for this
      int code_length = 16; // aload_0, getfield, aload_0, getstatic, const,
      // aaload, const/aconst_null, invokeinterface
      if (i > 5)
        {
          if (i > Byte.MAX_VALUE)
            code_length += 2; // sipush
          else
            code_length++; // bipush
        }
      if (paramtypes.length > 0)
        {
          code_length += 3; // anewarray
          if (paramtypes.length > Byte.MAX_VALUE)
            code_length += 2; // sipush
          else if (paramtypes.length > 5)
            code_length++; // bipush
          for (int j = 0; j < paramtypes.length; j++)
            {
              code_length += 4; // dup, const, load, store
              Class type = paramtypes[j];
              if (j > 5)
                {
                  if (j > Byte.MAX_VALUE)
                    code_length += 2; // sipush
                  else
                    code_length++; // bipush
                }
              if (param_count >= 4)
                code_length++; // 2-byte load
              param_count++;
              if (type.isPrimitive())
                {
                  code_length += 7; // new, dup, invokespecial
                  if (type == long.class || type == double.class)
                    {
                      wrap_overhead = 3;
                      param_count++;
                    }
                  else if (wrap_overhead < 2)
                    wrap_overhead = 2;
                }
            }
        }
      int end_pc = code_length;
      Class ret_type = m.getReturnType();
      if (ret_type == void.class)
        code_length++; // return
      else if (ret_type.isPrimitive())
        code_length += 7; // cast, invokevirtual, return
      else
        code_length += 4; // cast, return
      int exception_count = 0;
      boolean throws_throwable = false;
      for (int j = 0; j < e.length; j++)
        if (e[j] == Throwable.class)
          {
            throws_throwable = true;
            break;
          }
      if (! throws_throwable)
        {
          exception_count = e.length + 3; // Throwable, Error, RuntimeException
          code_length += 9; // new, dup_x1, swap, invokespecial, athrow
        }
      int handler_pc = code_length - 1;
      StringBuffer signature = new StringBuffer("(");
      for (int j = 0; j < paramtypes.length; j++)
        signature.append(TypeSignature.getEncodingOfClass(paramtypes[j]));
      signature.append(")").append(TypeSignature.getEncodingOfClass(ret_type));

      // Now we have enough information to emit the method.

      // handler.access_flags
      putU2(Modifier.PUBLIC | Modifier.FINAL);
      // handler.name_index
      putU2(utf8Info(m.getName()));
      // handler.descriptor_index
      putU2(utf8Info(signature.toString()));
      // handler.attributes_count - Code is necessary, Exceptions possible
      putU2(e.length > 0 ? 2 : 1);

      // handler.Code.info:
      //   type name(args) {
      //     try {
      //       return (type) h.invoke(this, methods[i], new Object[] {args});
      //     } catch (<declared Exceptions> e) {
      //       throw e;
      //     } catch (Throwable t) {
      //       throw new UndeclaredThrowableException(t);
      //     }
      //   }
      // Special cases:
      //  if arg_n is primitive, wrap it
      //  if method throws Throwable, try-catch is not needed
      //  if method returns void, return statement not needed
      //  if method returns primitive, unwrap it
      //  save space by sharing code for all the declared handlers

      // handler.Code.attribute_name_index
      putU2(utf8Info("Code"));
      // handler.Code.attribute_length
      putU4(12 + code_length + 8 * exception_count);
      // handler.Code.max_stack
      putU2(param_count == 1 ? 4 : 7 + wrap_overhead);
      // handler.Code.max_locals
      putU2(param_count);
      // handler.Code.code_length
      putU4(code_length);
      // handler.Code.code[]
      putU1(ALOAD_0);
      putU1(GETFIELD);
      putU2(refInfo(FIELD, "java/lang/reflect/Proxy", "h",
                    "Ljava/lang/reflect/InvocationHandler;"));
      putU1(ALOAD_0);
      putU1(GETSTATIC);
      putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName, false),
                    "m", "[Ljava/lang/reflect/Method;"));
      putConst(i);
      putU1(AALOAD);
      if (paramtypes.length > 0)
        {
          putConst(paramtypes.length);
          putU1(ANEWARRAY);
          putU2(classInfo("java/lang/Object"));
          param_count = 1;
          for (int j = 0; j < paramtypes.length; j++, param_count++)
            {
              putU1(DUP);
              putConst(j);
              if (paramtypes[j].isPrimitive())
                {
                  putU1(NEW);
                  putU2(classInfo(wrapper(paramtypes[j])));
                  putU1(DUP);
                }
              putLoad(param_count, paramtypes[j]);
              if (paramtypes[j].isPrimitive())
                {
                  putU1(INVOKESPECIAL);
                  putU2(refInfo(METHOD, wrapper(paramtypes[j]), "<init>",
                                '(' + (TypeSignature
                                       .getEncodingOfClass(paramtypes[j])
                                       + ")V")));
                  if (paramtypes[j] == long.class
                      || paramtypes[j] == double.class)
                    param_count++;
                }
              putU1(AASTORE);
            }
        }
      else
        putU1(ACONST_NULL);
      putU1(INVOKEINTERFACE);
      putU2(refInfo(INTERFACE, "java/lang/reflect/InvocationHandler",
                    "invoke", INVOKE_SIG));
      putU1(4); // InvocationHandler, this, Method, Object[]
      putU1(0);
      if (ret_type == void.class)
        putU1(RETURN);
      else if (ret_type.isPrimitive())
        {
          putU1(CHECKCAST);
          putU2(classInfo(wrapper(ret_type)));
          putU1(INVOKEVIRTUAL);
          putU2(refInfo(METHOD, wrapper(ret_type),
                        ret_type.getName() + "Value",
                        "()" + TypeSignature.getEncodingOfClass(ret_type)));
          if (ret_type == long.class)
            putU1(LRETURN);
          else if (ret_type == float.class)
            putU1(FRETURN);
          else if (ret_type == double.class)
            putU1(DRETURN);
          else
            putU1(IRETURN);
        }
      else
        {
          putU1(CHECKCAST);
          putU2(classInfo(ret_type));
          putU1(ARETURN);
        }
      if (! throws_throwable)
        {
          putU1(NEW);
          putU2(classInfo("java/lang/reflect/UndeclaredThrowableException"));
          putU1(DUP_X1);
          putU1(SWAP);
          putU1(INVOKESPECIAL);
          putU2(refInfo(METHOD,
                        "java/lang/reflect/UndeclaredThrowableException",
                        "<init>", "(Ljava/lang/Throwable;)V"));
          putU1(ATHROW);
        }

      // handler.Code.exception_table_length
      putU2(exception_count);
      // handler.Code.exception_table[]
      if (! throws_throwable)
        {
          // handler.Code.exception_table.start_pc
          putU2(0);
          // handler.Code.exception_table.end_pc
          putU2(end_pc);
          // handler.Code.exception_table.handler_pc
          putU2(handler_pc);
          // handler.Code.exception_table.catch_type
          putU2(classInfo("java/lang/Error"));
          // handler.Code.exception_table.start_pc
          putU2(0);
          // handler.Code.exception_table.end_pc
          putU2(end_pc);
          // handler.Code.exception_table.handler_pc
          putU2(handler_pc);
          // handler.Code.exception_table.catch_type
          putU2(classInfo("java/lang/RuntimeException"));
          for (int j = 0; j < e.length; j++)
            {
              // handler.Code.exception_table.start_pc
              putU2(0);
              // handler.Code.exception_table.end_pc
              putU2(end_pc);
              // handler.Code.exception_table.handler_pc
              putU2(handler_pc);
              // handler.Code.exception_table.catch_type
              putU2(classInfo(e[j]));
            }
          // handler.Code.exception_table.start_pc
          putU2(0);
          // handler.Code.exception_table.end_pc
          putU2(end_pc);
          // handler.Code.exception_table.handler_pc -
          //   -8 for undeclared handler, which falls thru to normal one
          putU2(handler_pc - 8);
          // handler.Code.exception_table.catch_type
          putU2(0);
        }
      // handler.Code.attributes_count
      putU2(0);
      // handler.Code.attributes[]

      if (e.length > 0)
        {
          // handler.Exceptions.attribute_name_index
          putU2(utf8Info("Exceptions"));
          // handler.Exceptions.attribute_length
          putU4(2 * e.length + 2);
          // handler.Exceptions.number_of_exceptions
          putU2(e.length);
          // handler.Exceptions.exception_index_table[]
          for (int j = 0; j < e.length; j++)
            putU2(classInfo(e[j]));
        }
    }

    /**
     * Creates the Class object that corresponds to the bytecode buffers
     * built when this object was constructed.
     *
     * @param loader the class loader to define the proxy class in; null
     *        implies the bootstrap class loader
     * @return the proxy class Class object
     */
    Class generate(ClassLoader loader)
    {
      byte[] bytecode = new byte[pool.length() + stream.length()];
      // More efficient to bypass calling charAt() repetitively.
      char[] c = pool.toString().toCharArray();
      int i = c.length;
      while (--i >= 0)
        bytecode[i] = (byte) c[i];
      c = stream.toString().toCharArray();
      i = c.length;
      int j = bytecode.length;
      while (i > 0)
        bytecode[--j] = (byte) c[--i];

      // Patch the constant pool size, which we left at 0 earlier.
      int count = poolEntries.size() + 1;
      bytecode[8] = (byte) (count >> 8);
      bytecode[9] = (byte) count;

      try
        {
          Class vmClassLoader = Class.forName("java.lang.VMClassLoader");
          Class[] types = {ClassLoader.class, String.class,
                           byte[].class, int.class, int.class,
                           ProtectionDomain.class };
          Method m = vmClassLoader.getDeclaredMethod("defineClass", types);
          // We can bypass the security check of setAccessible(true), since
	  // we're in the same package.
          m.flag = true;

          Object[] args = {loader, qualName, bytecode, new Integer(0),
                           new Integer(bytecode.length),
                           Object.class.getProtectionDomain() };
          Class clazz = (Class) m.invoke(null, args);

          // Finally, initialize the m field of the proxy class, before
          // returning it.
          Field f = clazz.getDeclaredField("m");
          f.flag = true;
          // we can share the array, because it is not publicized
          f.set(null, methods);

          return clazz;
        }
      catch (Exception e)
        {
          // assert false;
          throw (Error) new InternalError("Unexpected: " + e).initCause(e);
        }
    }

    /**
     * Put a single byte on the stream.
     *
     * @param i the information to add (only lowest 8 bits are used)
     */
    private void putU1(int i)
    {
      stream.append((char) i);
    }

    /**
     * Put two bytes on the stream.
     *
     * @param i the information to add (only lowest 16 bits are used)
     */
    private void putU2(int i)
    {
      stream.append((char) (i >> 8)).append((char) i);
    }

    /**
     * Put four bytes on the stream.
     *
     * @param i the information to add (treated as unsigned)
     */
    private void putU4(int i)
    {
      stream.append((char) (i >> 24)).append((char) (i >> 16));
      stream.append((char) (i >> 8)).append((char) i);
    }

    /**
     * Put bytecode to load a constant integer on the stream. This only
     * needs to work for values less than Short.MAX_VALUE.
     *
     * @param i the int to add
     */
    private void putConst(int i)
    {
      if (i >= -1 && i <= 5)
        putU1(ICONST_0 + i);
      else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE)
        {
          putU1(BIPUSH);
          putU1(i);
        }
      else
        {
          putU1(SIPUSH);
          putU2(i);
        }
    }

    /**
     * Put bytecode to load a given local variable on the stream.
     *
     * @param i the slot to load
     * @param type the base type of the load
     */
    private void putLoad(int i, Class type)
    {
      int offset = 0;
      if (type == long.class)
        offset = 1;
      else if (type == float.class)
        offset = 2;
      else if (type == double.class)
        offset = 3;
      else if (! type.isPrimitive())
        offset = 4;
      if (i < 4)
        putU1(ILOAD_0 + 4 * offset + i);
      else
        {
          putU1(ILOAD + offset);
          putU1(i);
        }
    }

    /**
     * Given a primitive type, return its wrapper class name.
     *
     * @param clazz the primitive type (but not void.class)
     * @return the internal form of the wrapper class name
     */
    private String wrapper(Class clazz)
    {
      if (clazz == boolean.class)
        return "java/lang/Boolean";
      if (clazz == byte.class)
        return "java/lang/Byte";
      if (clazz == short.class)
        return "java/lang/Short";
      if (clazz == char.class)
        return "java/lang/Character";
      if (clazz == int.class)
        return "java/lang/Integer";
      if (clazz == long.class)
        return "java/lang/Long";
      if (clazz == float.class)
        return "java/lang/Float";
      if (clazz == double.class)
        return "java/lang/Double";
      // assert false;
      return null;
    }

    /**
     * Returns the entry of this String in the Constant pool, adding it
     * if necessary.
     *
     * @param str the String to resolve
     * @return the index of the String in the constant pool
     */
    private char utf8Info(String str)
    {
      String utf8 = toUtf8(str);
      int len = utf8.length();
      return poolIndex("\1" + (char) (len >> 8) + (char) (len & 0xff) + utf8);
    }

    /**
     * Returns the entry of the appropriate class info structure in the
     * Constant pool, adding it if necessary.
     *
     * @param name the class name, in internal form
     * @return the index of the ClassInfo in the constant pool
     */
    private char classInfo(String name)
    {
      char index = utf8Info(name);
      char[] c = {7, (char) (index >> 8), (char) (index & 0xff)};
      return poolIndex(new String(c));
    }

    /**
     * Returns the entry of the appropriate class info structure in the
     * Constant pool, adding it if necessary.
     *
     * @param clazz the class type
     * @return the index of the ClassInfo in the constant pool
     */
    private char classInfo(Class clazz)
    {
      return classInfo(TypeSignature.getEncodingOfClass(clazz.getName(),
                                                        false));
    }

    /**
     * Returns the entry of the appropriate fieldref, methodref, or
     * interfacemethodref info structure in the Constant pool, adding it
     * if necessary.
     *
     * @param structure FIELD, METHOD, or INTERFACE
     * @param clazz the class name, in internal form
     * @param name the simple reference name
     * @param type the type of the reference
     * @return the index of the appropriate Info structure in the constant pool
     */
    private char refInfo(byte structure, String clazz, String name,
                         String type)
    {
      char cindex = classInfo(clazz);
      char ntindex = nameAndTypeInfo(name, type);
      // relies on FIELD == 1, METHOD == 2, INTERFACE == 3
      char[] c = {(char) (structure + 8),
                  (char) (cindex >> 8), (char) (cindex & 0xff),
                  (char) (ntindex >> 8), (char) (ntindex & 0xff)};
      return poolIndex(new String(c));
    }

    /**
     * Returns the entry of the appropriate nameAndTyperef info structure
     * in the Constant pool, adding it if necessary.
     *
     * @param name the simple name
     * @param type the reference type
     * @return the index of the NameAndTypeInfo structure in the constant pool
     */
    private char nameAndTypeInfo(String name, String type)
    {
      char nindex = utf8Info(name);
      char tindex = utf8Info(type);
      char[] c = {12, (char) (nindex >> 8), (char) (nindex & 0xff),
                  (char) (tindex >> 8), (char) (tindex & 0xff)};
      return poolIndex(new String(c));
    }

    /**
     * Converts a regular string to a UTF8 string, where the upper byte
     * of every char is 0, and '\\u0000' is not in the string.  This is
     * basically to use a String as a fancy byte[], and while it is less
     * efficient in memory use, it is easier for hashing.
     *
     * @param str the original, in straight unicode
     * @return a modified string, in UTF8 format in the low bytes
     */
    private String toUtf8(String str)
    {
      final char[] ca = str.toCharArray();
      final int len = ca.length;

      // Avoid object creation, if str is already fits UTF8.
      int i;
      for (i = 0; i < len; i++)
        if (ca[i] == 0 || ca[i] > '\u007f')
          break;
      if (i == len)
        return str;

      final StringBuffer sb = new StringBuffer(str);
      sb.setLength(i);
      for ( ; i < len; i++)
        {
          final char c = ca[i];
          if (c > 0 && c <= '\u007f')
            sb.append(c);
          else if (c <= '\u07ff') // includes '\0'
            {
              sb.append((char) (0xc0 | (c >> 6)));
              sb.append((char) (0x80 | (c & 0x6f)));
            }
          else
            {
              sb.append((char) (0xe0 | (c >> 12)));
              sb.append((char) (0x80 | ((c >> 6) & 0x6f)));
              sb.append((char) (0x80 | (c & 0x6f)));
            }
        }
      return sb.toString();
    }

    /**
     * Returns the location of a byte sequence (conveniently wrapped in
     * a String with all characters between \u0001 and \u00ff inclusive)
     * in the constant pool, adding it if necessary.
     *
     * @param sequence the byte sequence to look for
     * @return the index of the sequence
     * @throws IllegalArgumentException if this would make the constant
     *         pool overflow
     */
    private char poolIndex(String sequence)
    {
      Integer i = (Integer) poolEntries.get(sequence);
      if (i == null)
        {
          // pool starts at index 1
          int size = poolEntries.size() + 1;
          if (size >= 65535)
            throw new IllegalArgumentException("exceeds VM limitations");
          i = new Integer(size);
          poolEntries.put(sequence, i);
          pool.append(sequence);
        }
      return (char) i.intValue();
    }
  } // class ClassFactory
}
