/* ObjectStreamClass.java -- Class used to write class information
   about serialized objects.
   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005  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.io;

import gnu.java.io.NullOutputStream;
import gnu.java.lang.reflect.TypeSignature;
import gnu.java.security.action.SetAccessibleAction;
import gnu.java.security.provider.Gnu;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessController;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.security.Security;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Hashtable;

/**
 * @author Tom Tromey (tromey@redhat.com)
 * @author Jeroen Frijters (jeroen@frijters.net)
 * @author Guilhem Lavaux (guilhem@kaffe.org)
 * @author Michael Koch (konqueror@gmx.de)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 */
public class ObjectStreamClass implements Serializable
{
  static final ObjectStreamField[] INVALID_FIELDS = new ObjectStreamField[0];

  /**
   * Returns the <code>ObjectStreamClass</code> for <code>cl</code>.
   * If <code>cl</code> is null, or is not <code>Serializable</code>,
   * null is returned.  <code>ObjectStreamClass</code>'s are memorized;
   * later calls to this method with the same class will return the
   * same <code>ObjectStreamClass</code> object and no recalculation
   * will be done.
   *
   * Warning: If this class contains an invalid serialPersistentField arrays
   * lookup will not throw anything. However {@link #getFields()} will return
   * an empty array and {@link java.io.ObjectOutputStream#writeObject} will throw an
   * {@link java.io.InvalidClassException}.
   *
   * @see java.io.Serializable
   */
  public static ObjectStreamClass lookup(Class<?> cl)
  {
    if (cl == null)
      return null;
    if (! (Serializable.class).isAssignableFrom(cl))
      return null;

    return lookupForClassObject(cl);
  }

  /**
   * This lookup for internal use by ObjectOutputStream.  Suppose
   * we have a java.lang.Class object C for class A, though A is not
   * serializable, but it's okay to serialize C.
   */
  static ObjectStreamClass lookupForClassObject(Class cl)
  {
    if (cl == null)
      return null;

    ObjectStreamClass osc = classLookupTable.get(cl);

    if (osc != null)
      return osc;
    else
      {
        osc = new ObjectStreamClass(cl);
        classLookupTable.put(cl, osc);
        return osc;
      }
  }

  /**
   * Returns the name of the class that this
   * <code>ObjectStreamClass</code> represents.
   *
   * @return the name of the class.
   */
  public String getName()
  {
    return name;
  }

  /**
   * Returns the class that this <code>ObjectStreamClass</code>
   * represents.  Null could be returned if this
   * <code>ObjectStreamClass</code> was read from an
   * <code>ObjectInputStream</code> and the class it represents cannot
   * be found or loaded.
   *
   * @see java.io.ObjectInputStream
   */
  public Class<?> forClass()
  {
    return clazz;
  }

  /**
   * Returns the serial version stream-unique identifier for the class
   * represented by this <code>ObjectStreamClass</code>.  This SUID is
   * either defined by the class as <code>static final long
   * serialVersionUID</code> or is calculated as specified in
   * Javasoft's "Object Serialization Specification" XXX: add reference
   *
   * @return the serial version UID.
   */
  public long getSerialVersionUID()
  {
    return uid;
  }

  /**
   * Returns the serializable (non-static and non-transient) Fields
   * of the class represented by this ObjectStreamClass.  The Fields
   * are sorted by name.
   * If fields were obtained using serialPersistentFields and this array
   * is faulty then the returned array of this method will be empty.
   *
   * @return the fields.
   */
  public ObjectStreamField[] getFields()
  {
    ObjectStreamField[] copy = new ObjectStreamField[ fields.length ];
    System.arraycopy(fields, 0, copy, 0, fields.length);
    return copy;
  }

  // XXX doc
  // Can't do binary search since fields is sorted by name and
  // primitiveness.
  public ObjectStreamField getField (String name)
  {
    for (int i = 0; i < fields.length; i++)
      if (fields[i].getName().equals(name))
        return fields[i];
    return null;
  }

  /**
   * Returns a textual representation of this
   * <code>ObjectStreamClass</code> object including the name of the
   * class it represents as well as that class's serial version
   * stream-unique identifier.
   *
   * @see #getSerialVersionUID()
   * @see #getName()
   */
  public String toString()
  {
    return "java.io.ObjectStreamClass< " + name + ", " + uid + " >";
  }

  // Returns true iff the class that this ObjectStreamClass represents
  // has the following method:
  //
  // private void writeObject (ObjectOutputStream)
  //
  // This method is used by the class to override default
  // serialization behavior.
  boolean hasWriteMethod()
  {
    return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0;
  }

  // Returns true iff the class that this ObjectStreamClass represents
  // implements Serializable but does *not* implement Externalizable.
  boolean isSerializable()
  {
    return (flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0;
  }


  // Returns true iff the class that this ObjectStreamClass represents
  // implements Externalizable.
  boolean isExternalizable()
  {
    return (flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0;
  }

  // Returns true iff the class that this ObjectStreamClass represents
  // implements Externalizable.
  boolean isEnum()
  {
    return (flags & ObjectStreamConstants.SC_ENUM) != 0;
  }

  // Returns the <code>ObjectStreamClass</code> that represents the
  // class that is the superclass of the class this
  // <code>ObjectStreamClass</code> represents.  If the superclass is
  // not Serializable, null is returned.
  ObjectStreamClass getSuper()
  {
    return superClass;
  }

  /**
   * returns an array of ObjectStreamClasses that represent the super
   * classes of the class represented by this and the class
   * represented by this itself in order from most super to this.
   * ObjectStreamClass[0] is the highest superclass of this that is
   * serializable.
   *
   * The result of consecutive calls this hierarchy() will be the same
   * array instance.
   *
   * @return an array of ObjectStreamClass representing the
   * super-class hierarchy of serializable classes.
   */
  ObjectStreamClass[] hierarchy()
  {
    ObjectStreamClass[] result = hierarchy;
    if (result == null)
        {
        int d = 0;

        for(ObjectStreamClass osc = this; osc != null; osc = osc.getSuper())
          d++;

        result = new ObjectStreamClass[d];

        for (ObjectStreamClass osc = this; osc != null; osc = osc.getSuper())
          {
            result[--d] = osc;
          }

        hierarchy = result;
      }
    return result;
  }

  /**
   * Cache for hierarchy() result.
   */
  private ObjectStreamClass[] hierarchy = null;

  // Returns an integer that consists of bit-flags that indicate
  // properties of the class represented by this ObjectStreamClass.
  // The bit-flags that could be present are those defined in
  // ObjectStreamConstants that begin with `SC_'
  int getFlags()
  {
    return flags;
  }


  ObjectStreamClass(String name, long uid, byte flags,
                    ObjectStreamField[] fields)
  {
    this.name = name;
    this.uid = uid;
    this.flags = flags;
    this.fields = fields;
  }

  /**
   * This method builds the internal description corresponding to a Java Class.
   * As the constructor only assign a name to the current ObjectStreamClass instance,
   * that method sets the serial UID, chose the fields which will be serialized,
   * and compute the position of the fields in the serialized stream.
   *
   * @param cl The Java class which is used as a reference for building the descriptor.
   * @param superClass The descriptor of the super class for this class descriptor.
   * @throws InvalidClassException if an incompatibility between computed UID and
   * already set UID is found.
   */
  void setClass(Class cl, ObjectStreamClass superClass) throws InvalidClassException
  {hierarchy = null;
    this.clazz = cl;

    cacheMethods();

    long class_uid = getClassUID(cl);
    if (uid == 0)
      uid = class_uid;
    else
      {
        // Check that the actual UID of the resolved class matches the UID from
        // the stream. Mismatches for array classes are ignored.
        if (!cl.isArray() && uid != class_uid)
          {
            String msg = cl +
              ": Local class not compatible: stream serialVersionUID="
              + uid + ", local serialVersionUID=" + class_uid;
            throw new InvalidClassException (msg);
          }
      }

    isProxyClass = clazz != null && Proxy.isProxyClass(clazz);
    this.superClass = superClass;
    calculateOffsets();

    try
      {
        ObjectStreamField[] exportedFields = getSerialPersistentFields (clazz);

        if (exportedFields == null)
          return;

        ObjectStreamField[] newFieldList = new ObjectStreamField[exportedFields.length + fields.length];
        int i, j, k;

        /* We now check the import fields against the exported fields.
         * There should not be contradiction (e.g. int x and String x)
         * but extra virtual fields can be added to the class.
         */

        Arrays.sort(exportedFields);

        i = 0; j = 0; k = 0;
        while (i < fields.length && j < exportedFields.length)
          {
            int comp = fields[i].compareTo(exportedFields[j]);

            if (comp < 0)
              {
                newFieldList[k] = fields[i];
                fields[i].setPersistent(false);
                fields[i].setToSet(false);
                i++;
              }
            else if (comp > 0)
              {
                /* field not found in imported fields. We add it
                 * in the list of supported fields.
                 */
                newFieldList[k] = exportedFields[j];
                newFieldList[k].setPersistent(true);
                newFieldList[k].setToSet(false);
                try
                  {
                    newFieldList[k].lookupField(clazz);
                    newFieldList[k].checkFieldType();
                  }
                catch (NoSuchFieldException _)
                  {
                  }
                j++;
              }
            else
              {
                try
                  {
                    exportedFields[j].lookupField(clazz);
                    exportedFields[j].checkFieldType();
                  }
                catch (NoSuchFieldException _)
                  {
                  }

                if (!fields[i].getType().equals(exportedFields[j].getType()))
                  throw new InvalidClassException
                    ("serialPersistentFields must be compatible with" +
                     " imported fields (about " + fields[i].getName() + ")");
                newFieldList[k] = fields[i];
                fields[i].setPersistent(true);
                i++;
                j++;
              }
            k++;
          }

        if (i < fields.length)
          for (;i<fields.length;i++,k++)
            {
              fields[i].setPersistent(false);
              fields[i].setToSet(false);
              newFieldList[k] = fields[i];
            }
        else
          if (j < exportedFields.length)
            for (;j<exportedFields.length;j++,k++)
              {
                exportedFields[j].setPersistent(true);
                exportedFields[j].setToSet(false);
                newFieldList[k] = exportedFields[j];
              }

        fields = new ObjectStreamField[k];
        System.arraycopy(newFieldList, 0, fields, 0, k);
      }
    catch (NoSuchFieldException ignore)
      {
        return;
      }
    catch (IllegalAccessException ignore)
      {
        return;
      }
  }

  void setSuperclass (ObjectStreamClass osc)
  {
    superClass = osc;
    hierarchy = null;
  }

  void calculateOffsets()
  {
    int i;
    ObjectStreamField field;
    primFieldSize = 0;
    int fcount = fields.length;
    for (i = 0; i < fcount; ++ i)
      {
        field = fields[i];

        if (! field.isPrimitive())
          break;

        field.setOffset(primFieldSize);
        switch (field.getTypeCode())
          {
          case 'B':
          case 'Z':
            ++ primFieldSize;
            break;
          case 'C':
          case 'S':
            primFieldSize += 2;
            break;
          case 'I':
          case 'F':
            primFieldSize += 4;
            break;
          case 'D':
          case 'J':
            primFieldSize += 8;
            break;
          }
      }

    for (objectFieldCount = 0; i < fcount; ++ i)
      fields[i].setOffset(objectFieldCount++);
  }

  private Method findMethod(Method[] methods, String name, Class[] params,
                            Class returnType, boolean mustBePrivate)
  {
outer:
    for (int i = 0; i < methods.length; i++)
    {
        final Method m = methods[i];
        int mods = m.getModifiers();
        if (Modifier.isStatic(mods)
            || (mustBePrivate && !Modifier.isPrivate(mods)))
        {
            continue;
        }

        if (m.getName().equals(name)
           && m.getReturnType() == returnType)
        {
            Class[] mp = m.getParameterTypes();
            if (mp.length == params.length)
            {
                for (int j = 0; j < mp.length; j++)
                {
                    if (mp[j] != params[j])
                    {
                        continue outer;
                    }
                }
                AccessController.doPrivileged(new SetAccessibleAction(m));
                return m;
            }
        }
    }
    return null;
  }

  private static boolean inSamePackage(Class c1, Class c2)
  {
    String name1 = c1.getName();
    String name2 = c2.getName();

    int id1 = name1.lastIndexOf('.');
    int id2 = name2.lastIndexOf('.');

    // Handle the default package
    if (id1 == -1 || id2 == -1)
      return id1 == id2;

    String package1 = name1.substring(0, id1);
    String package2 = name2.substring(0, id2);

    return package1.equals(package2);
  }

  final static Class[] noArgs = new Class[0];

  private static Method findAccessibleMethod(String name, Class from)
  {
    for (Class c = from; c != null; c = c.getSuperclass())
      {
        try
          {
            Method res = c.getDeclaredMethod(name, noArgs);
            int mods = res.getModifiers();

            if (c == from
                || Modifier.isProtected(mods)
                || Modifier.isPublic(mods)
                || (! Modifier.isPrivate(mods) && inSamePackage(c, from)))
              {
                AccessController.doPrivileged(new SetAccessibleAction(res));
                return res;
              }
          }
        catch (NoSuchMethodException e)
          {
          }
      }

    return null;
  }

  /**
   * Helper routine to check if a class was loaded by boot or
   * application class loader.  Classes for which this is not the case
   * should not be cached since caching prevent class file garbage
   * collection.
   *
   * @param cl a class
   *
   * @return true if cl was loaded by boot or application class loader,
   *         false if cl was loaded by a user class loader.
   */
  private static boolean loadedByBootOrApplicationClassLoader(Class cl)
  {
    ClassLoader l = cl.getClassLoader();
    return
      (   l == null                             /* boot loader */       )
      || (l == ClassLoader.getSystemClassLoader() /* application loader */);
  }

  static Hashtable methodCache = new Hashtable();

  static final Class[] readObjectSignature  = { ObjectInputStream.class };
  static final Class[] writeObjectSignature = { ObjectOutputStream.class };

  private void cacheMethods()
  {
    Class cl = forClass();
    Method[] cached = (Method[]) methodCache.get(cl);
    if (cached == null)
      {
        cached = new Method[4];
        Method[] methods = cl.getDeclaredMethods();

        cached[0] = findMethod(methods, "readObject",
                               readObjectSignature,
                               Void.TYPE, true);
        cached[1] = findMethod(methods, "writeObject",
                               writeObjectSignature,
                               Void.TYPE, true);

        // readResolve and writeReplace can be in parent classes, as long as they
        // are accessible from this class.
        cached[2] = findAccessibleMethod("readResolve", cl);
        cached[3] = findAccessibleMethod("writeReplace", cl);

        /* put in cache if classes not loaded by user class loader.
         * For a user class loader, the cache may otherwise grow
         * without limit.
         */
        if (loadedByBootOrApplicationClassLoader(cl))
          methodCache.put(cl,cached);
      }
    readObjectMethod   = cached[0];
    writeObjectMethod  = cached[1];
    readResolveMethod  = cached[2];
    writeReplaceMethod = cached[3];
  }

  private ObjectStreamClass(Class cl)
  {
    uid = 0;
    flags = 0;
    isProxyClass = Proxy.isProxyClass(cl);

    clazz = cl;
    cacheMethods();
    name = cl.getName();
    setFlags(cl);
    setFields(cl);
    // to those class nonserializable, its uid field is 0
    if ( (Serializable.class).isAssignableFrom(cl) && !isProxyClass)
      uid = getClassUID(cl);
    superClass = lookup(cl.getSuperclass());
  }


  // Sets bits in flags according to features of CL.
  private void setFlags(Class cl)
  {
    if ((java.io.Externalizable.class).isAssignableFrom(cl))
      flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
    else if ((java.io.Serializable.class).isAssignableFrom(cl))
      // only set this bit if CL is NOT Externalizable
      flags |= ObjectStreamConstants.SC_SERIALIZABLE;

    if (writeObjectMethod != null)
      flags |= ObjectStreamConstants.SC_WRITE_METHOD;

    if (cl.isEnum() || cl == Enum.class)
      flags |= ObjectStreamConstants.SC_ENUM;
  }

/* GCJ LOCAL */
  // FIXME: This is a workaround for a fairly obscure bug that happens
  // when reading a Proxy and then writing it back out again.  The
  // result is that the ObjectStreamClass doesn't have its fields set,
  // generating a NullPointerException.  Rather than this kludge we
  // should probably fix the real bug, but it would require a fairly
  // radical reorganization to do so.
  final void ensureFieldsSet(Class cl)
  {
    if (! fieldsSet)
      setFields(cl);
  }
/* END GCJ LOCAL */


  // Sets fields to be a sorted array of the serializable fields of
  // clazz.
  private void setFields(Class cl)
  {
/* GCJ LOCAL */
    fieldsSet = true;
/* END GCJ LOCAL */

    SetAccessibleAction setAccessible = new SetAccessibleAction();

    if (!isSerializable() || isExternalizable() || isEnum())
      {
        fields = NO_FIELDS;
        return;
      }

    try
      {
        final Field f =
          cl.getDeclaredField("serialPersistentFields");
        setAccessible.setMember(f);
        AccessController.doPrivileged(setAccessible);
        int modifiers = f.getModifiers();

        if (Modifier.isStatic(modifiers)
            && Modifier.isFinal(modifiers)
            && Modifier.isPrivate(modifiers))
          {
            fields = getSerialPersistentFields(cl);
            if (fields != null)
              {
                ObjectStreamField[] fieldsName = new ObjectStreamField[fields.length];
                System.arraycopy(fields, 0, fieldsName, 0, fields.length);

                Arrays.sort (fieldsName, new Comparator() {
                        public int compare(Object o1, Object o2)
                        {
                          ObjectStreamField f1 = (ObjectStreamField)o1;
                          ObjectStreamField f2 = (ObjectStreamField)o2;

                          return f1.getName().compareTo(f2.getName());
                        }
                    });

                for (int i=1; i < fields.length; i++)
                  {
                    if (fieldsName[i-1].getName().equals(fieldsName[i].getName()))
                        {
                            fields = INVALID_FIELDS;
                            return;
                        }
                  }

                Arrays.sort (fields);
                // Retrieve field reference.
                for (int i=0; i < fields.length; i++)
                  {
                    try
                      {
                        fields[i].lookupField(cl);
                      }
                    catch (NoSuchFieldException _)
                      {
                        fields[i].setToSet(false);
                      }
                  }

                calculateOffsets();
                return;
              }
          }
      }
    catch (NoSuchFieldException ignore)
      {
      }
    catch (IllegalAccessException ignore)
      {
      }

    int num_good_fields = 0;
    Field[] all_fields = cl.getDeclaredFields();

    int modifiers;
    // set non-serializable fields to null in all_fields
    for (int i = 0; i < all_fields.length; i++)
      {
        modifiers = all_fields[i].getModifiers();
        if (Modifier.isTransient(modifiers)
            || Modifier.isStatic(modifiers))
          all_fields[i] = null;
        else
          num_good_fields++;
      }

    // make a copy of serializable (non-null) fields
    fields = new ObjectStreamField[ num_good_fields ];
    for (int from = 0, to = 0; from < all_fields.length; from++)
      if (all_fields[from] != null)
        {
          final Field f = all_fields[from];
          setAccessible.setMember(f);
          AccessController.doPrivileged(setAccessible);
          fields[to] = new ObjectStreamField(all_fields[from]);
          to++;
        }

    Arrays.sort(fields);
    // Make sure we don't have any duplicate field names
    // (Sun JDK 1.4.1. throws an Internal Error as well)
    for (int i = 1; i < fields.length; i++)
      {
        if(fields[i - 1].getName().equals(fields[i].getName()))
            throw new InternalError("Duplicate field " +
                        fields[i].getName() + " in class " + cl.getName());
      }
    calculateOffsets();
  }

  static Hashtable uidCache = new Hashtable();

  // Returns the serial version UID defined by class, or if that
  // isn't present, calculates value of serial version UID.
  private long getClassUID(Class cl)
  {
    long result = 0;
    Long cache = (Long) uidCache.get(cl);
    if (cache != null)
      result = cache.longValue();
    else
      {
        // Note that we can't use Class.isEnum() here, because that returns
        // false for java.lang.Enum and enum value sub classes.
        if (Enum.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl))
          {
            // Spec says that enums and dynamic proxies have
            // a serialVersionUID of 0L.
            return 0L;
          }
        try
          {
            result = getClassUIDFromField(cl);
          }
        catch (NoSuchFieldException ignore)
          {
            try
              {
                result = calculateClassUID(cl);
              }
            catch (NoSuchAlgorithmException e)
              {
                throw new RuntimeException
                  ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
                   + cl.getName(), e);
              }
            catch (IOException ioe)
              {
                throw new RuntimeException(ioe);
              }
          }

        if (loadedByBootOrApplicationClassLoader(cl))
          uidCache.put(cl,Long.valueOf(result));
      }
    return result;
  }

  /**
   * Search for a serialVersionUID field in the given class and read
   * its value.
   *
   * @return the contents of the serialVersionUID field
   *
   * @throws NoSuchFieldException if such a field does not exist or is
   * not static, not final, not of type Long or not accessible.
   */
  long getClassUIDFromField(Class cl)
    throws NoSuchFieldException
  {
    long result;

    try
      {
        // Use getDeclaredField rather than getField, since serialVersionUID
        // may not be public AND we only want the serialVersionUID of this
        // class, not a superclass or interface.
        final Field suid = cl.getDeclaredField("serialVersionUID");
        SetAccessibleAction setAccessible = new SetAccessibleAction(suid);
        AccessController.doPrivileged(setAccessible);
        int modifiers = suid.getModifiers();

        if (Modifier.isStatic(modifiers)
            && Modifier.isFinal(modifiers)
            && suid.getType() == Long.TYPE)
          result = suid.getLong(null);
        else
          throw new NoSuchFieldException();
      }
    catch (IllegalAccessException ignore)
      {
        throw new NoSuchFieldException();
      }

    return result;
  }

  /**
   * Calculate class serial version UID for a class that does not
   * define serialVersionUID:
   *
   * @param cl a class
   *
   * @return the calculated serial varsion UID.
   *
   * @throws NoSuchAlgorithmException if SHA algorithm not found
   *
   * @throws IOException if writing to the DigestOutputStream causes
   * an IOException.
   */
  long calculateClassUID(Class cl)
    throws NoSuchAlgorithmException, IOException
  {
    long result;
    MessageDigest md;
    try
      {
        md = MessageDigest.getInstance("SHA");
      }
    catch (NoSuchAlgorithmException e)
      {
        // If a provider already provides SHA, use it; otherwise, use this.
        Gnu gnuProvider = new Gnu();
        Security.addProvider(gnuProvider);
        md = MessageDigest.getInstance("SHA");
      }

    DigestOutputStream digest_out =
      new DigestOutputStream(nullOutputStream, md);
    DataOutputStream data_out = new DataOutputStream(digest_out);

    data_out.writeUTF(cl.getName());

    int modifiers = cl.getModifiers();
    // just look at interesting bits
    modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
                             | Modifier.INTERFACE | Modifier.PUBLIC);
    data_out.writeInt(modifiers);

    // Pretend that an array has no interfaces, because when array
    // serialization was defined (JDK 1.1), arrays didn't have it.
    if (! cl.isArray())
      {
        Class[] interfaces = cl.getInterfaces();
        Arrays.sort(interfaces, interfaceComparator);
        for (int i = 0; i < interfaces.length; i++)
          data_out.writeUTF(interfaces[i].getName());
      }

    Field field;
    Field[] fields = cl.getDeclaredFields();
    Arrays.sort(fields, memberComparator);
    for (int i = 0; i < fields.length; i++)
      {
        field = fields[i];
        modifiers = field.getModifiers();
        if (Modifier.isPrivate(modifiers)
            && (Modifier.isStatic(modifiers)
                || Modifier.isTransient(modifiers)))
          continue;

        data_out.writeUTF(field.getName());
        data_out.writeInt(modifiers);
        data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
      }

    // write class initializer method if present
    if (VMObjectStreamClass.hasClassInitializer(cl))
      {
        data_out.writeUTF("<clinit>");
        data_out.writeInt(Modifier.STATIC);
        data_out.writeUTF("()V");
      }

    Constructor constructor;
    Constructor[] constructors = cl.getDeclaredConstructors();
    Arrays.sort (constructors, memberComparator);
    for (int i = 0; i < constructors.length; i++)
      {
        constructor = constructors[i];
        modifiers = constructor.getModifiers();
        if (Modifier.isPrivate(modifiers))
          continue;

        data_out.writeUTF("<init>");
        data_out.writeInt(modifiers);

        // the replacement of '/' with '.' was needed to make computed
        // SUID's agree with those computed by JDK
        data_out.writeUTF
          (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
      }

    Method method;
    Method[] methods = cl.getDeclaredMethods();
    Arrays.sort(methods, memberComparator);
    for (int i = 0; i < methods.length; i++)
      {
        method = methods[i];
        modifiers = method.getModifiers();
        if (Modifier.isPrivate(modifiers))
          continue;

        data_out.writeUTF(method.getName());
        data_out.writeInt(modifiers);

        // the replacement of '/' with '.' was needed to make computed
        // SUID's agree with those computed by JDK
        data_out.writeUTF
          (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
      }

    data_out.close();
    byte[] sha = md.digest();
    result = 0;
    int len = sha.length < 8 ? sha.length : 8;
    for (int i = 0; i < len; i++)
      result += (long) (sha[i] & 0xFF) << (8 * i);

    return result;
  }

  /**
   * Returns the value of CLAZZ's private static final field named
   * `serialPersistentFields'. It performs some sanity checks before
   * returning the real array. Besides, the returned array is a clean
   * copy of the original. So it can be modified.
   *
   * @param clazz Class to retrieve 'serialPersistentFields' from.
   * @return The content of 'serialPersistentFields'.
   */
  private ObjectStreamField[] getSerialPersistentFields(Class clazz)
    throws NoSuchFieldException, IllegalAccessException
  {
    ObjectStreamField[] fieldsArray = null;
    ObjectStreamField[] o;

    // Use getDeclaredField rather than getField for the same reason
    // as above in getDefinedSUID.
    Field f = clazz.getDeclaredField("serialPersistentFields");
    f.setAccessible(true);

    int modifiers = f.getModifiers();
    if (!(Modifier.isStatic(modifiers) &&
          Modifier.isFinal(modifiers) &&
          Modifier.isPrivate(modifiers)))
      return null;

    o = (ObjectStreamField[]) f.get(null);

    if (o == null)
      return null;

    fieldsArray = new ObjectStreamField[ o.length ];
    System.arraycopy(o, 0, fieldsArray, 0, o.length);

    return fieldsArray;
  }

  /**
   * Returns a new instance of the Class this ObjectStreamClass corresponds
   * to.
   * Note that this should only be used for Externalizable classes.
   *
   * @return A new instance.
   */
  Externalizable newInstance() throws InvalidClassException
  {
    synchronized(this)
    {
        if (constructor == null)
        {
            try
            {
                final Constructor c = clazz.getConstructor(new Class[0]);

                AccessController.doPrivileged(new PrivilegedAction()
                {
                    public Object run()
                    {
                        c.setAccessible(true);
                        return null;
                    }
                });

                constructor = c;
            }
            catch(NoSuchMethodException x)
            {
                throw new InvalidClassException(clazz.getName(),
                    "No public zero-argument constructor");
            }
        }
    }

    try
    {
        return (Externalizable)constructor.newInstance();
    }
    catch(Exception x)
    {
        throw (InvalidClassException)
            new InvalidClassException(clazz.getName(),
                     "Unable to instantiate").initCause(x);
    }
  }

  public static final ObjectStreamField[] NO_FIELDS = {};

  private static Hashtable<Class,ObjectStreamClass> classLookupTable
    = new Hashtable<Class,ObjectStreamClass>();
  private static final NullOutputStream nullOutputStream = new NullOutputStream();
  private static final Comparator interfaceComparator = new InterfaceComparator();
  private static final Comparator memberComparator = new MemberComparator();
  private static final
    Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };

  private ObjectStreamClass superClass;
  private Class<?> clazz;
  private String name;
  private long uid;
  private byte flags;

  // this field is package protected so that ObjectInputStream and
  // ObjectOutputStream can access it directly
  ObjectStreamField[] fields;

  // these are accessed by ObjectIn/OutputStream
  int primFieldSize = -1;  // -1 if not yet calculated
  int objectFieldCount;

  Method readObjectMethod;
  Method readResolveMethod;
  Method writeReplaceMethod;
  Method writeObjectMethod;
  boolean realClassIsSerializable;
  boolean realClassIsExternalizable;
  ObjectStreamField[] fieldMapping;
  Constructor firstNonSerializableParentConstructor;
  private Constructor constructor;  // default constructor for Externalizable

  boolean isProxyClass = false;

/* GCJ LOCAL */
  // True after setFields() has been called
  private boolean fieldsSet = false;
/* END GCJ LOCAL */

  // This is probably not necessary because this class is special cased already
  // but it will avoid showing up as a discrepancy when comparing SUIDs.
  private static final long serialVersionUID = -6120832682080437368L;


  // interfaces are compared only by name
  private static final class InterfaceComparator implements Comparator
  {
    public int compare(Object o1, Object o2)
    {
      return ((Class) o1).getName().compareTo(((Class) o2).getName());
    }
  }


  // Members (Methods and Constructors) are compared first by name,
  // conflicts are resolved by comparing type signatures
  private static final class MemberComparator implements Comparator
  {
    public int compare(Object o1, Object o2)
    {
      Member m1 = (Member) o1;
      Member m2 = (Member) o2;

      int comp = m1.getName().compareTo(m2.getName());

      if (comp == 0)
        return TypeSignature.getEncodingOfMember(m1).
          compareTo(TypeSignature.getEncodingOfMember(m2));
      else
        return comp;
    }
  }
}
