/* 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.CPStringBuilder;

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.5, 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"));
          coreMethods.put(sig, sig);
          sig = new ProxySignature(Object.class.getMethod("toString"));
          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;
      CPStringBuilder signature = new CPStringBuilder("(");
      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, Integer.valueOf(0),
                           Integer.valueOf(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 CPStringBuilder sb = new CPStringBuilder(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 = Integer.valueOf(size);
          poolEntries.put(sequence, i);
          pool.append(sequence);
        }
      return (char) i.intValue();
    }
  } // class ClassFactory
}
