/* ObjectInputStream.java -- Class used to read serialized objects
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008
   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.classpath.Pair;
import gnu.classpath.VMStackWalker;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;

/**
 * @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 ObjectInputStream extends InputStream
  implements ObjectInput, ObjectStreamConstants
{
  /**
   * Creates a new <code>ObjectInputStream</code> that will do all of
   * its reading from <code>in</code>.  This method also checks
   * the stream by reading the header information (stream magic number
   * and stream version).
   *
   * @exception IOException Reading stream header from underlying
   * stream cannot be completed.
   *
   * @exception StreamCorruptedException An invalid stream magic
   * number or stream version was read from the stream.
   *
   * @see #readStreamHeader()
   */
  public ObjectInputStream(InputStream in)
    throws IOException, StreamCorruptedException
  {
    if (DEBUG)
      {
        String val = System.getProperty("gcj.dumpobjects");
        if (dump == false && val != null && !val.equals(""))
          {
            dump = true;
            System.out.println ("Serialization debugging enabled");
          }
        else if (dump == true && (val == null || val.equals("")))
          {
            dump = false;
            System.out.println ("Serialization debugging disabled");
          }
      }

    this.resolveEnabled = false;
    this.blockDataPosition = 0;
    this.blockDataBytes = 0;
    this.blockData = new byte[BUFFER_SIZE];
    this.blockDataInput = new DataInputStream(this);
    this.realInputStream = new DataInputStream(in);
    this.nextOID = baseWireHandle;
    handles = new HashMap<Integer,Pair<Boolean,Object>>();
    this.classLookupTable = new Hashtable<Class,ObjectStreamClass>();
    setBlockDataMode(true);
    readStreamHeader();
  }


  /**
   * Returns the next deserialized object read from the underlying stream.
   *
   * This method can be overriden by a class by implementing
   * <code>private void readObject (ObjectInputStream)</code>.
   *
   * If an exception is thrown from this method, the stream is left in
   * an undefined state. This method can also throw Errors and
   * RuntimeExceptions if caused by existing readResolve() user code.
   *
   * @return The object read from the underlying stream.
   *
   * @exception ClassNotFoundException The class that an object being
   * read in belongs to cannot be found.
   *
   * @exception IOException Exception from underlying
   * <code>InputStream</code>.
   */
  public final Object readObject()
    throws ClassNotFoundException, IOException
  {
    return readObject(true);
  }

  /**
   * <p>
   * Returns the next deserialized object read from the
   * underlying stream in an unshared manner.  Any object
   * returned by this method will not be returned by
   * subsequent calls to either this method or {@link #readObject()}.
   * </p>
   * <p>
   * This behaviour is achieved by:
   * </p>
   * <ul>
   * <li>Marking the handles created by successful calls to this
   * method, so that future calls to {@link #readObject()} or
   * {@link #readUnshared()} will throw an {@link ObjectStreamException}
   * rather than returning the same object reference.</li>
   * <li>Throwing an {@link ObjectStreamException} if the next
   * element in the stream is a reference to an earlier object.</li>
   * </ul>
   *
   * @return a reference to the deserialized object.
   * @throws ClassNotFoundException if the class of the object being
   *                                deserialized can not be found.
   * @throws StreamCorruptedException if information in the stream
   *                                  is inconsistent.
   * @throws ObjectStreamException if the next object has already been
   *                               returned by an earlier call to this
   *                               method or {@link #readObject()}.
   * @throws OptionalDataException if primitive data occurs next in the stream.
   * @throws IOException if an I/O error occurs from the stream.
   * @since 1.4
   * @see #readObject()
   */
  public Object readUnshared()
    throws IOException, ClassNotFoundException
  {
    return readObject(false);
  }

  /**
   * Returns the next deserialized object read from the underlying stream.
   *
   * This method can be overriden by a class by implementing
   * <code>private void readObject (ObjectInputStream)</code>.
   *
   * If an exception is thrown from this method, the stream is left in
   * an undefined state. This method can also throw Errors and
   * RuntimeExceptions if caused by existing readResolve() user code.
   *
   * @param shared true if handles created by this call should be shared
   *               with later calls.
   * @return The object read from the underlying stream.
   *
   * @exception ClassNotFoundException The class that an object being
   * read in belongs to cannot be found.
   *
   * @exception IOException Exception from underlying
   * <code>InputStream</code>.
   */
  private final Object readObject(boolean shared)
    throws ClassNotFoundException, IOException
  {
    if (this.useSubclassMethod)
      return readObjectOverride();

    Object ret_val;
    boolean old_mode = setBlockDataMode(false);
    byte marker = this.realInputStream.readByte();

    if (DEBUG)
      depth += 2;

    if(dump) dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");

    try
      {
        ret_val = parseContent(marker, shared);
      }
    finally
      {
        setBlockDataMode(old_mode);
        if (DEBUG)
          depth -= 2;
      }

    return ret_val;
  }

   /**
    * Handles a content block within the stream, which begins with a marker
    * byte indicating its type.
    *
    * @param marker the byte marker.
    * @param shared true if handles created by this call should be shared
    *               with later calls.
    * @return an object which represents the parsed content.
    * @throws ClassNotFoundException if the class of an object being
    *                                read in cannot be found.
    * @throws IOException if invalid data occurs or one is thrown by the
    *                     underlying <code>InputStream</code>.
    */
   private Object parseContent(byte marker, boolean shared)
     throws ClassNotFoundException, IOException
   {
     Object ret_val;
     boolean is_consumed = false;

     switch (marker)
       {
       case TC_ENDBLOCKDATA:
        {
          ret_val = null;
          is_consumed = true;
          break;
        }

       case TC_BLOCKDATA:
       case TC_BLOCKDATALONG:
        {
          if (marker == TC_BLOCKDATALONG)
            { if(dump) dumpElementln("BLOCKDATALONG"); }
          else
            { if(dump) dumpElementln("BLOCKDATA"); }
          readNextBlock(marker);
        }

       case TC_NULL:
        {
          if(dump) dumpElementln("NULL");
          ret_val = null;
          break;
        }

       case TC_REFERENCE:
        {
          if(dump) dumpElement("REFERENCE ");
          int oid = realInputStream.readInt();
          if(dump) dumpElementln(Integer.toHexString(oid));
          ret_val = lookupHandle(oid);
          if (!shared)
            throw new
              InvalidObjectException("References can not be read unshared.");
          break;
        }

       case TC_CLASS:
        {
          if(dump) dumpElementln("CLASS");
          ObjectStreamClass osc = (ObjectStreamClass)readObject();
          Class clazz = osc.forClass();
          assignNewHandle(clazz,shared);
          ret_val = clazz;
          break;
        }

       case TC_PROXYCLASSDESC:
        {
          if(dump) dumpElementln("PROXYCLASS");

/* GCJ LOCAL */
          // The grammar at this point is
          //   TC_PROXYCLASSDESC newHandle proxyClassDescInfo
          // i.e. we have to assign the handle immediately after
          // reading the marker.
          int handle = assignNewHandle("Dummy proxy",shared);
/* END GCJ LOCAL */

          int n_intf = this.realInputStream.readInt();
          String[] intfs = new String[n_intf];
          for (int i = 0; i < n_intf; i++)
            {
              intfs[i] = this.realInputStream.readUTF();
            }

          boolean oldmode = setBlockDataMode(true);
          Class cl = resolveProxyClass(intfs);
          setBlockDataMode(oldmode);

          ObjectStreamClass osc = lookupClass(cl);
          if (osc.firstNonSerializableParentConstructor == null)
            {
              osc.realClassIsSerializable = true;
              osc.fields = osc.fieldMapping = new ObjectStreamField[0];
              try
                {
                  osc.firstNonSerializableParentConstructor =
                    Object.class.getConstructor(new Class[0]);
                }
              catch (NoSuchMethodException x)
                {
                  throw (InternalError)
                    new InternalError("Object ctor missing").initCause(x);
                }
            }
/* GCJ LOCAL */
          rememberHandle(osc,shared,handle);
/* END GCJ LOCAL */

          if (!is_consumed)
            {
              byte b = this.realInputStream.readByte();
              if (b != TC_ENDBLOCKDATA)
                throw new IOException("Data annotated to class was not consumed." + b);
            }
          else
            is_consumed = false;
          ObjectStreamClass superosc = (ObjectStreamClass)readObject();
          osc.setSuperclass(superosc);
          ret_val = osc;
          break;
        }

       case TC_CLASSDESC:
        {
          ObjectStreamClass osc = readClassDescriptor();

          if (!is_consumed)
            {
              byte b = this.realInputStream.readByte();
              if (b != TC_ENDBLOCKDATA)
                throw new IOException("Data annotated to class was not consumed." + b);
            }
          else
            is_consumed = false;

          osc.setSuperclass ((ObjectStreamClass)readObject());
          ret_val = osc;
          break;
        }

       case TC_STRING:
        {
          if(dump) dumpElement("STRING=");
          String s = this.realInputStream.readUTF();
          if(dump) dumpElementln(s);
          ret_val = processResolution(null, s, assignNewHandle(s,shared),
                                      shared);
          break;
        }

       case TC_LONGSTRING:
        {
          if(dump) dumpElement("STRING=");
          String s = this.realInputStream.readUTFLong();
          if(dump) dumpElementln(s);
          ret_val = processResolution(null, s, assignNewHandle(s,shared),
                                      shared);
          break;
        }

       case TC_ARRAY:
        {
          if(dump) dumpElementln("ARRAY");
          ObjectStreamClass osc = (ObjectStreamClass)readObject();
          Class componentType = osc.forClass().getComponentType();
          if(dump) dumpElement("ARRAY LENGTH=");
          int length = this.realInputStream.readInt();
          if(dump) dumpElementln (length + "; COMPONENT TYPE=" + componentType);
          Object array = Array.newInstance(componentType, length);
          int handle = assignNewHandle(array,shared);
          readArrayElements(array, componentType);
          if(dump)
            for (int i = 0, len = Array.getLength(array); i < len; i++)
              dumpElementln("  ELEMENT[" + i + "]=", Array.get(array, i));
          ret_val = processResolution(null, array, handle, shared);
          break;
        }

       case TC_OBJECT:
        {
          if(dump) dumpElementln("OBJECT");
          ObjectStreamClass osc = (ObjectStreamClass)readObject();
          Class clazz = osc.forClass();

          if (!osc.realClassIsSerializable)
            throw new NotSerializableException
              (clazz + " is not Serializable, and thus cannot be deserialized.");

          if (osc.realClassIsExternalizable)
            {
              Externalizable obj = osc.newInstance();

              int handle = assignNewHandle(obj,shared);

              boolean read_from_blocks = ((osc.getFlags() & SC_BLOCK_DATA) != 0);

              boolean oldmode = this.readDataFromBlock;
              if (read_from_blocks)
                setBlockDataMode(true);

              obj.readExternal(this);

              if (read_from_blocks)
                {
                  setBlockDataMode(oldmode);
                  if (!oldmode)
                    if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
                      throw new IOException("No end of block data seen for class with readExternal (ObjectInputStream) method.");
                }

              ret_val = processResolution(osc, obj, handle,shared);
              break;

            } // end if (osc.realClassIsExternalizable)

          Object obj = newObject(clazz, osc.firstNonSerializableParentConstructor);

          int handle = assignNewHandle(obj,shared);
          Object prevObject = this.currentObject;
          ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
          TreeSet<ValidatorAndPriority> prevObjectValidators =
            this.currentObjectValidators;

          this.currentObject = obj;
          this.currentObjectValidators = null;
          ObjectStreamClass[] hierarchy = hierarchy(clazz);

          for (int i = 0; i < hierarchy.length; i++)
          {
              this.currentObjectStreamClass = hierarchy[i];
              if(dump) dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ());

              // XXX: should initialize fields in classes in the hierarchy
              // that aren't in the stream
              // should skip over classes in the stream that aren't in the
              // real classes hierarchy

              Method readObjectMethod = this.currentObjectStreamClass.readObjectMethod;
              if (readObjectMethod != null)
                {
                  fieldsAlreadyRead = false;
                  boolean oldmode = setBlockDataMode(true);
                  callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
                  setBlockDataMode(oldmode);
                }
              else
                {
                  readFields(obj, currentObjectStreamClass);
                }

              if (this.currentObjectStreamClass.hasWriteMethod())
                {
                  if(dump) dumpElement("ENDBLOCKDATA? ");
                  try
                    {
                      /* Read blocks until an end marker */
                      byte writeMarker = this.realInputStream.readByte();
                      while (writeMarker != TC_ENDBLOCKDATA)
                        {
                          parseContent(writeMarker, shared);
                          writeMarker = this.realInputStream.readByte();
                        }
                      if(dump) dumpElementln("yes");
                    }
                  catch (EOFException e)
                    {
                      throw (IOException) new IOException
                        ("No end of block data seen for class with readObject (ObjectInputStream) method.").initCause(e);
                    }
                }
            }

          this.currentObject = prevObject;
          this.currentObjectStreamClass = prevObjectStreamClass;
          ret_val = processResolution(osc, obj, handle, shared);
          if (currentObjectValidators != null)
            invokeValidators();
          this.currentObjectValidators = prevObjectValidators;

          break;
        }

       case TC_RESET:
        if(dump) dumpElementln("RESET");
        clearHandles();
        ret_val = readObject();
        break;

       case TC_EXCEPTION:
        {
          if(dump) dumpElement("EXCEPTION=");
          Exception e = (Exception)readObject();
          if(dump) dumpElementln(e.toString());
          clearHandles();
          throw new WriteAbortedException("Exception thrown during writing of stream", e);
        }

       case TC_ENUM:
         {
           /* TC_ENUM classDesc newHandle enumConstantName */
           if (dump)
             dumpElementln("ENUM=");
           ObjectStreamClass osc = (ObjectStreamClass) readObject();
	   int enumHandle = assignNewHandle(null, shared);
           String constantName = (String) readObject();
           if (dump)
             dumpElementln("CONSTANT NAME = " + constantName);
           Class clazz = osc.forClass();
           Enum instance = Enum.valueOf(clazz, constantName);
	   rememberHandle(instance, shared, enumHandle);
           ret_val = instance;
           break;
         }

       default:
        throw new IOException("Unknown marker on stream: " + marker);
      }
    return ret_val;
  }

  /**
   * This method makes a partial check of types for the fields
   * contained given in arguments. It checks primitive types of
   * fields1 against non primitive types of fields2. This method
   * assumes the two lists has already been sorted according to
   * the Java specification.
   *
   * @param name Name of the class owning the given fields.
   * @param fields1 First list to check.
   * @param fields2 Second list to check.
   * @throws InvalidClassException if a field in fields1, which has a primitive type, is a present
   * in the non primitive part in fields2.
   */
  private void checkTypeConsistency(String name, ObjectStreamField[] fields1, ObjectStreamField[] fields2)
    throws InvalidClassException
  {
    int nonPrimitive = 0;

    for (nonPrimitive = 0;
         nonPrimitive < fields1.length
           && fields1[nonPrimitive].isPrimitive(); nonPrimitive++)
      {
      }

    if (nonPrimitive == fields1.length)
      return;

    int i = 0;
    ObjectStreamField f1;
    ObjectStreamField f2;

    while (i < fields2.length
           && nonPrimitive < fields1.length)
      {
        f1 = fields1[nonPrimitive];
        f2 = fields2[i];

        if (!f2.isPrimitive())
          break;

        int compVal = f1.getName().compareTo (f2.getName());

        if (compVal < 0)
          {
            nonPrimitive++;
          }
        else if (compVal > 0)
          {
            i++;
          }
        else
          {
            throw new InvalidClassException
              ("invalid field type for " + f2.getName() +
               " in class " + name);
          }
      }
  }

  /**
   * This method reads a class descriptor from the real input stream
   * and use these data to create a new instance of ObjectStreamClass.
   * Fields are sorted and ordered for the real read which occurs for
   * each instance of the described class. Be aware that if you call that
   * method you must ensure that the stream is synchronized, in the other
   * case it may be completely desynchronized.
   *
   * @return A new instance of ObjectStreamClass containing the freshly
   * created descriptor.
   * @throws ClassNotFoundException if the required class to build the
   * descriptor has not been found in the system.
   * @throws IOException An input/output error occured.
   * @throws InvalidClassException If there was a compatibility problem
   * between the class present in the system and the serialized class.
   */
  protected ObjectStreamClass readClassDescriptor()
    throws ClassNotFoundException, IOException
  {
    if(dump) dumpElement("CLASSDESC NAME=");
    String name = this.realInputStream.readUTF();
    if(dump) dumpElement(name + "; UID=");
    long uid = this.realInputStream.readLong ();
    if(dump) dumpElement(Long.toHexString(uid) + "; FLAGS=");
    byte flags = this.realInputStream.readByte ();
    if(dump) dumpElement(Integer.toHexString(flags) + "; FIELD COUNT=");
    short field_count = this.realInputStream.readShort();
    if(dump) dumpElementln(Short.toString(field_count));
    ObjectStreamField[] fields = new ObjectStreamField[field_count];
    ObjectStreamClass osc = new ObjectStreamClass(name, uid,
                                                  flags, fields);
    assignNewHandle(osc,true);

    for (int i = 0; i < field_count; i++)
      {
        if(dump) dumpElement("  TYPE CODE=");
        char type_code = (char)this.realInputStream.readByte();
        if(dump) dumpElement(type_code + "; FIELD NAME=");
        String field_name = this.realInputStream.readUTF();
        if(dump) dumpElementln(field_name);
        String class_name;

        // If the type code is an array or an object we must
        // decode a String here. In the other case we convert
        // the type code and pass it to ObjectStreamField.
        // Type codes are decoded by gnu.java.lang.reflect.TypeSignature.
        if (type_code == 'L' || type_code == '[')
          class_name = (String)readObject();
        else
          class_name = String.valueOf(type_code);

        fields[i] =
          new ObjectStreamField(field_name, class_name);
      }

    /* Now that fields have been read we may resolve the class
     * (and read annotation if needed). */
    Class clazz = resolveClass(osc);
    ClassLoader loader = clazz.getClassLoader();
    for (int i = 0; i < field_count; i++)
      {
        fields[i].resolveType(loader);
      }
    boolean oldmode = setBlockDataMode(true);
    osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
    classLookupTable.put(clazz, osc);
    setBlockDataMode(oldmode);

    // find the first non-serializable class in clazz's inheritance hierarchy
    Class first_nonserial = clazz.getSuperclass();
    // Maybe it is a primitive class, those don't have a super class,
    // or Object itself.  Otherwise we can keep getting the superclass
    // till we hit the Object class, or some other non-serializable class.

    if (first_nonserial == null)
      first_nonserial = clazz;
    else
      while (Serializable.class.isAssignableFrom(first_nonserial))
        first_nonserial = first_nonserial.getSuperclass();

    final Class local_constructor_class = first_nonserial;

    osc.firstNonSerializableParentConstructor =
        (Constructor)AccessController.doPrivileged(new PrivilegedAction()
          {
            public Object run()
            {
              try
                {
                  Constructor c = local_constructor_class.
                                    getDeclaredConstructor(new Class[0]);
                  if (Modifier.isPrivate(c.getModifiers()))
                    return null;
                  return c;
                }
              catch (NoSuchMethodException e)
                {
                  // error will be reported later, in newObject()
                  return null;
                }
            }
          });

    osc.realClassIsSerializable = Serializable.class.isAssignableFrom(clazz);
    osc.realClassIsExternalizable = Externalizable.class.isAssignableFrom(clazz);

    ObjectStreamField[] stream_fields = osc.fields;
    ObjectStreamField[] real_fields = ObjectStreamClass.lookupForClassObject(clazz).fields;
    ObjectStreamField[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)];

    int stream_idx = 0;
    int real_idx = 0;
    int map_idx = 0;

    /*
     * Check that there is no type inconsistencies between the lists.
     * A special checking must be done for the two groups: primitive types and
     * not primitive types.
     */
    checkTypeConsistency(name, real_fields, stream_fields);
    checkTypeConsistency(name, stream_fields, real_fields);


    while (stream_idx < stream_fields.length
           || real_idx < real_fields.length)
      {
        ObjectStreamField stream_field = null;
        ObjectStreamField real_field = null;

        if (stream_idx == stream_fields.length)
          {
            real_field = real_fields[real_idx++];
          }
        else if (real_idx == real_fields.length)
          {
            stream_field = stream_fields[stream_idx++];
          }
        else
          {
            int comp_val =
              real_fields[real_idx].compareTo (stream_fields[stream_idx]);

            if (comp_val < 0)
              {
                real_field = real_fields[real_idx++];
              }
            else if (comp_val > 0)
              {
                stream_field = stream_fields[stream_idx++];
              }
            else
              {
                stream_field = stream_fields[stream_idx++];
                real_field = real_fields[real_idx++];
                if (stream_field.getType() != real_field.getType())
                  throw new InvalidClassException
                    ("invalid field type for " + real_field.getName() +
                     " in class " + name);
              }
          }

        /* If some of stream_fields does not correspond to any of real_fields,
         * or the opposite, then fieldmapping will go short.
         */
        if (map_idx == fieldmapping.length)
          {
            ObjectStreamField[] newfieldmapping =
              new ObjectStreamField[fieldmapping.length + 2];
            System.arraycopy(fieldmapping, 0,
                             newfieldmapping, 0, fieldmapping.length);
            fieldmapping = newfieldmapping;
          }
        fieldmapping[map_idx++] = stream_field;
        fieldmapping[map_idx++] = real_field;
      }
    osc.fieldMapping = fieldmapping;

    return osc;
  }

  /**
   * Reads the current objects non-transient, non-static fields from
   * the current class from the underlying output stream.
   *
   * This method is intended to be called from within a object's
   * <code>private void readObject (ObjectInputStream)</code>
   * method.
   *
   * @exception ClassNotFoundException The class that an object being
   * read in belongs to cannot be found.
   *
   * @exception NotActiveException This method was called from a
   * context other than from the current object's and current class's
   * <code>private void readObject (ObjectInputStream)</code>
   * method.
   *
   * @exception IOException Exception from underlying
   * <code>OutputStream</code>.
   */
  public void defaultReadObject()
    throws ClassNotFoundException, IOException, NotActiveException
  {
    if (this.currentObject == null || this.currentObjectStreamClass == null)
      throw new NotActiveException("defaultReadObject called by non-active"
                                   + " class and/or object");

    if (fieldsAlreadyRead)
      throw new NotActiveException("defaultReadObject called but fields "
                                   + "already read from stream (by "
                                   + "defaultReadObject or readFields)");

    boolean oldmode = setBlockDataMode(false);
    readFields(this.currentObject, this.currentObjectStreamClass);
    setBlockDataMode(oldmode);

    fieldsAlreadyRead = true;
  }


  /**
   * Registers a <code>ObjectInputValidation</code> to be carried out
   * on the object graph currently being deserialized before it is
   * returned to the original caller of <code>readObject ()</code>.
   * The order of validation for multiple
   * <code>ObjectInputValidation</code>s can be controled using
   * <code>priority</code>.  Validators with higher priorities are
   * called first.
   *
   * @see java.io.ObjectInputValidation
   *
   * @exception InvalidObjectException <code>validator</code> is
   * <code>null</code>
   *
   * @exception NotActiveException an attempt was made to add a
   * validator outside of the <code>readObject</code> method of the
   * object currently being deserialized
   */
  public void registerValidation(ObjectInputValidation validator,
                                 int priority)
    throws InvalidObjectException, NotActiveException
  {
    if (this.currentObject == null || this.currentObjectStreamClass == null)
      throw new NotActiveException("registerValidation called by non-active "
                                   + "class and/or object");

    if (validator == null)
      throw new InvalidObjectException("attempt to add a null "
                                       + "ObjectInputValidation object");

    if (currentObjectValidators == null)
      currentObjectValidators = new TreeSet<ValidatorAndPriority>();

    currentObjectValidators.add(new ValidatorAndPriority(validator, priority));
  }


  /**
   * Called when a class is being deserialized.  This is a hook to
   * allow subclasses to read in information written by the
   * <code>annotateClass (Class)</code> method of an
   * <code>ObjectOutputStream</code>.
   *
   * This implementation looks up the active call stack for a
   * <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,
   * it is used to load the class associated with <code>osc</code>,
   * otherwise, the default system <code>ClassLoader</code> is used.
   *
   * @exception IOException Exception from underlying
   * <code>OutputStream</code>.
   *
   * @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
   */
  protected Class<?> resolveClass(ObjectStreamClass osc)
    throws ClassNotFoundException, IOException
  {
    String name = osc.getName();
    try
      {
        return Class.forName(name, true, currentLoader());
      }
    catch(ClassNotFoundException x)
      {
        if (name.equals("void"))
          return Void.TYPE;
        else if (name.equals("boolean"))
          return Boolean.TYPE;
        else if (name.equals("byte"))
          return Byte.TYPE;
        else if (name.equals("char"))
          return Character.TYPE;
        else if (name.equals("short"))
          return Short.TYPE;
        else if (name.equals("int"))
          return Integer.TYPE;
        else if (name.equals("long"))
          return Long.TYPE;
        else if (name.equals("float"))
          return Float.TYPE;
        else if (name.equals("double"))
          return Double.TYPE;
        else
          throw x;
      }
  }

  /**
   * Returns the most recent user defined ClassLoader on the execution stack
   * or null if none is found.
   */
  private ClassLoader currentLoader()
  {
    return VMStackWalker.firstNonNullClassLoader();
  }

  /**
   * Lookup a class stored in the local hashtable. If it is not
   * use the global lookup function in ObjectStreamClass to build
   * the ObjectStreamClass. This method is requested according to
   * the behaviour detected in the JDK by Kaffe's team.
   *
   * @param clazz Class to lookup in the hash table or for which
   * we must build a descriptor.
   * @return A valid instance of ObjectStreamClass corresponding
   * to the specified class.
   */
  private ObjectStreamClass lookupClass(Class clazz)
  {
    if (clazz == null)
      return null;

    ObjectStreamClass oclazz;
    oclazz = classLookupTable.get(clazz);
    if (oclazz == null)
      return ObjectStreamClass.lookup(clazz);
    else
      return oclazz;
  }

  /**
   * Reconstruct class hierarchy the same way {@link
   * java.io.ObjectStreamClass#hierarchy} does but using lookupClass
   * instead of ObjectStreamClass.lookup.
   *
   * @param clazz This is the class for which we want the hierarchy.
   *
   * @return An array of valid {@link java.io.ObjectStreamClass} instances which
   * represent the class hierarchy for clazz.
   */
  private ObjectStreamClass[] hierarchy(Class clazz)
  {
    ObjectStreamClass osc = lookupClass(clazz);

    return osc == null ? new ObjectStreamClass[0] : osc.hierarchy();
  }

  /**
   * Allows subclasses to resolve objects that are read from the
   * stream with other objects to be returned in their place.  This
   * method is called the first time each object is encountered.
   *
   * This method must be enabled before it will be called in the
   * serialization process.
   *
   * @exception IOException Exception from underlying
   * <code>OutputStream</code>.
   *
   * @see #enableResolveObject(boolean)
   */
  protected Object resolveObject(Object obj) throws IOException
  {
    return obj;
  }


  protected Class<?> resolveProxyClass(String[] intfs)
    throws IOException, ClassNotFoundException
  {
    ClassLoader cl = currentLoader();

    Class<?>[] clss = new Class<?>[intfs.length];
    if(cl == null)
      {
        for (int i = 0; i < intfs.length; i++)
          clss[i] = Class.forName(intfs[i]);
        cl = ClassLoader.getSystemClassLoader();
      }
    else
      for (int i = 0; i < intfs.length; i++)
        clss[i] = Class.forName(intfs[i], false, cl);
    try
      {
        return Proxy.getProxyClass(cl, clss);
      }
    catch (IllegalArgumentException e)
      {
        throw new ClassNotFoundException(null, e);
      }
  }

  /**
   * If <code>enable</code> is <code>true</code> and this object is
   * trusted, then <code>resolveObject (Object)</code> will be called
   * in subsequent calls to <code>readObject (Object)</code>.
   * Otherwise, <code>resolveObject (Object)</code> will not be called.
   *
   * @exception SecurityException This class is not trusted.
   */
  protected boolean enableResolveObject (boolean enable)
    throws SecurityException
  {
    if (enable)
      {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null)
          sm.checkPermission(new SerializablePermission("enableSubstitution"));
      }

    boolean old_val = this.resolveEnabled;
    this.resolveEnabled = enable;
    return old_val;
  }

  /**
   * Reads stream magic and stream version information from the
   * underlying stream.
   *
   * @exception IOException Exception from underlying stream.
   *
   * @exception StreamCorruptedException An invalid stream magic
   * number or stream version was read from the stream.
   */
  protected void readStreamHeader()
    throws IOException, StreamCorruptedException
  {
    if(dump) dumpElement("STREAM MAGIC ");
    if (this.realInputStream.readShort() != STREAM_MAGIC)
      throw new StreamCorruptedException("Invalid stream magic number");

    if(dump) dumpElementln("STREAM VERSION ");
    if (this.realInputStream.readShort() != STREAM_VERSION)
      throw new StreamCorruptedException("Invalid stream version number");
  }

  public int read() throws IOException
  {
    if (this.readDataFromBlock)
      {
        if (this.blockDataPosition >= this.blockDataBytes)
          readNextBlock();
        return (this.blockData[this.blockDataPosition++] & 0xff);
      }
    else
      return this.realInputStream.read();
  }

  public int read(byte[] data, int offset, int length) throws IOException
  {
    if (this.readDataFromBlock)
      {
        int remain = this.blockDataBytes - this.blockDataPosition;
        if (remain == 0)
          {
            readNextBlock();
            remain = this.blockDataBytes - this.blockDataPosition;
          }
        length = Math.min(length, remain);
        System.arraycopy(this.blockData, this.blockDataPosition,
                         data, offset, length);
        this.blockDataPosition += length;

        return length;
      }
    else
      return this.realInputStream.read(data, offset, length);
  }

  public int available() throws IOException
  {
    if (this.readDataFromBlock)
      {
        if (this.blockDataPosition >= this.blockDataBytes)
          readNextBlock ();

        return this.blockDataBytes - this.blockDataPosition;
      }
    else
      return this.realInputStream.available();
  }

  public void close() throws IOException
  {
    this.realInputStream.close();
  }

  public boolean readBoolean() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode (true);
    boolean value = this.dataInputStream.readBoolean ();
    if (switchmode)
      setBlockDataMode (oldmode);
    return value;
  }

  public byte readByte() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    byte value = this.dataInputStream.readByte();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public int readUnsignedByte() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    int value = this.dataInputStream.readUnsignedByte();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public short readShort() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    short value = this.dataInputStream.readShort();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public int readUnsignedShort() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    int value = this.dataInputStream.readUnsignedShort();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public char readChar() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    char value = this.dataInputStream.readChar();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public int readInt() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    int value = this.dataInputStream.readInt();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public long readLong() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    long value = this.dataInputStream.readLong();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public float readFloat() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    float value = this.dataInputStream.readFloat();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public double readDouble() throws IOException
  {
    boolean switchmode = true;
    boolean oldmode = this.readDataFromBlock;
    if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
      switchmode = false;
    if (switchmode)
      oldmode = setBlockDataMode(true);
    double value = this.dataInputStream.readDouble();
    if (switchmode)
      setBlockDataMode(oldmode);
    return value;
  }

  public void readFully(byte data[]) throws IOException
  {
    this.dataInputStream.readFully(data);
  }

  public void readFully(byte data[], int offset, int size)
    throws IOException
  {
    this.dataInputStream.readFully(data, offset, size);
  }

  public int skipBytes(int len) throws IOException
  {
    return this.dataInputStream.skipBytes(len);
  }

  /**
   * @deprecated
   * @see java.io.DataInputStream#readLine ()
   */
  public String readLine() throws IOException
  {
    return this.dataInputStream.readLine();
  }

  public String readUTF() throws IOException
  {
    return this.dataInputStream.readUTF();
  }

  /**
   * This class allows a class to specify exactly which fields should
   * be read, and what values should be read for these fields.
   *
   * XXX: finish up comments
   */
  public abstract static class GetField
  {
    public abstract ObjectStreamClass getObjectStreamClass();

    public abstract boolean defaulted(String name)
      throws IOException, IllegalArgumentException;

    public abstract boolean get(String name, boolean defvalue)
      throws IOException, IllegalArgumentException;

    public abstract char get(String name, char defvalue)
      throws IOException, IllegalArgumentException;

    public abstract byte get(String name, byte defvalue)
      throws IOException, IllegalArgumentException;

    public abstract short get(String name, short defvalue)
      throws IOException, IllegalArgumentException;

    public abstract int get(String name, int defvalue)
      throws IOException, IllegalArgumentException;

    public abstract long get(String name, long defvalue)
      throws IOException, IllegalArgumentException;

    public abstract float get(String name, float defvalue)
      throws IOException, IllegalArgumentException;

    public abstract double get(String name, double defvalue)
      throws IOException, IllegalArgumentException;

    public abstract Object get(String name, Object defvalue)
      throws IOException, IllegalArgumentException;
  }

  /**
   * This method should be called by a method called 'readObject' in the
   * deserializing class (if present). It cannot (and should not)be called
   * outside of it. Its goal is to read all fields in the real input stream
   * and keep them accessible through the {@link GetField} class. Calling
   * this method will not alter the deserializing object.
   *
   * @return A valid freshly created 'GetField' instance to get access to
   * the deserialized stream.
   * @throws IOException An input/output exception occured.
   * @throws ClassNotFoundException
   * @throws NotActiveException
   */
  public GetField readFields()
    throws IOException, ClassNotFoundException, NotActiveException
  {
    if (this.currentObject == null || this.currentObjectStreamClass == null)
      throw new NotActiveException("readFields called by non-active class and/or object");

    if (prereadFields != null)
      return prereadFields;

    if (fieldsAlreadyRead)
      throw new NotActiveException("readFields called but fields already read from"
                                   + " stream (by defaultReadObject or readFields)");

    final ObjectStreamClass clazz = this.currentObjectStreamClass;
    final byte[] prim_field_data = new byte[clazz.primFieldSize];
    final Object[] objs = new Object[clazz.objectFieldCount];

    // Apparently Block data is not used with GetField as per
    // empirical evidence against JDK 1.2.  Also see Mauve test
    // java.io.ObjectInputOutput.Test.GetPutField.
    boolean oldmode = setBlockDataMode(false);
    readFully(prim_field_data);
    for (int i = 0; i < objs.length; ++ i)
      objs[i] = readObject();
    setBlockDataMode(oldmode);

    prereadFields = new GetField()
      {
        public ObjectStreamClass getObjectStreamClass()
        {
          return clazz;
        }

        public boolean defaulted(String name)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField f = clazz.getField(name);

          /* First if we have a serialized field use the descriptor */
          if (f != null)
            {
              /* It is in serialPersistentFields but setClass tells us
               * it should not be set. This value is defaulted.
               */
              if (f.isPersistent() && !f.isToSet())
                return true;

              return false;
            }

          /* This is not a serialized field. There should be
           * a default value only if the field really exists.
           */
          try
            {
              return (clazz.forClass().getDeclaredField (name) != null);
            }
          catch (NoSuchFieldException e)
            {
              throw new IllegalArgumentException(e);
            }
        }

        public boolean get(String name, boolean defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field = getField(name, Boolean.TYPE);

          if (field == null)
            return defvalue;

          return prim_field_data[field.getOffset()] == 0 ? false : true;
        }

        public char get(String name, char defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field = getField(name, Character.TYPE);

          if (field == null)
            return defvalue;

          int off = field.getOffset();

          return (char)(((prim_field_data[off++] & 0xFF) << 8)
                        | (prim_field_data[off] & 0xFF));
        }

        public byte get(String name, byte defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field = getField(name, Byte.TYPE);

          if (field == null)
            return defvalue;

          return prim_field_data[field.getOffset()];
        }

        public short get(String name, short defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field = getField(name, Short.TYPE);

          if (field == null)
            return defvalue;

          int off = field.getOffset();

          return (short)(((prim_field_data[off++] & 0xFF) << 8)
                         | (prim_field_data[off] & 0xFF));
        }

        public int get(String name, int defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field = getField(name, Integer.TYPE);

          if (field == null)
            return defvalue;

          int off = field.getOffset();

          return ((prim_field_data[off++] & 0xFF) << 24)
            | ((prim_field_data[off++] & 0xFF) << 16)
            | ((prim_field_data[off++] & 0xFF) << 8)
            | (prim_field_data[off] & 0xFF);
        }

        public long get(String name, long defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field = getField(name, Long.TYPE);

          if (field == null)
            return defvalue;

          int off = field.getOffset();

          return (long)(((prim_field_data[off++] & 0xFFL) << 56)
                        | ((prim_field_data[off++] & 0xFFL) << 48)
                        | ((prim_field_data[off++] & 0xFFL) << 40)
                        | ((prim_field_data[off++] & 0xFFL) << 32)
                        | ((prim_field_data[off++] & 0xFF) << 24)
                        | ((prim_field_data[off++] & 0xFF) << 16)
                        | ((prim_field_data[off++] & 0xFF) << 8)
                        | (prim_field_data[off] & 0xFF));
        }

        public float get(String name, float defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field = getField(name, Float.TYPE);

          if (field == null)
            return defvalue;

          int off = field.getOffset();

          return Float.intBitsToFloat(((prim_field_data[off++] & 0xFF) << 24)
                                      | ((prim_field_data[off++] & 0xFF) << 16)
                                      | ((prim_field_data[off++] & 0xFF) << 8)
                                      | (prim_field_data[off] & 0xFF));
        }

        public double get(String name, double defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field = getField(name, Double.TYPE);

          if (field == null)
            return defvalue;

          int off = field.getOffset();

          return Double.longBitsToDouble
            ( (long) (((prim_field_data[off++] & 0xFFL) << 56)
                      | ((prim_field_data[off++] & 0xFFL) << 48)
                      | ((prim_field_data[off++] & 0xFFL) << 40)
                      | ((prim_field_data[off++] & 0xFFL) << 32)
                      | ((prim_field_data[off++] & 0xFF) << 24)
                      | ((prim_field_data[off++] & 0xFF) << 16)
                      | ((prim_field_data[off++] & 0xFF) << 8)
                      | (prim_field_data[off] & 0xFF)));
        }

        public Object get(String name, Object defvalue)
          throws IOException, IllegalArgumentException
        {
          ObjectStreamField field =
            getField(name, defvalue == null ? null : defvalue.getClass ());

          if (field == null)
            return defvalue;

          return objs[field.getOffset()];
        }

        private ObjectStreamField getField(String name, Class type)
          throws IllegalArgumentException
        {
          ObjectStreamField field = clazz.getField(name);
          boolean illegal = false;

          // XXX This code is horrible and needs to be rewritten!
          try
            {
              try
                {
                  Class field_type = field.getType();

                  if (type == field_type ||
                      (type == null && !field_type.isPrimitive()))
                    {
                      /* See defaulted */
                      return field;
                    }

                  illegal = true;
                  throw new IllegalArgumentException
                    ("Field requested is of type "
                     + field_type.getName()
                     + ", but requested type was "
                     + (type == null ?  "Object" : type.getName()));
                }
              catch (NullPointerException _)
                {
                  /* Here we catch NullPointerException, because it may
                     only come from the call 'field.getType()'. If field
                     is null, we have to return null and classpath ethic
                     say we must try to avoid 'if (xxx == null)'.
                  */
                }
              catch (IllegalArgumentException e)
                {
                  throw e;
                }

              return null;
            }
          finally
            {
              /* If this is an unassigned field we should return
               * the default value.
               */
              if (!illegal && field != null && !field.isToSet() && field.isPersistent())
                return null;

              /* We do not want to modify transient fields. They should
               * be left to 0.
               */
              try
                {
                  Field f = clazz.forClass().getDeclaredField(name);
                  if (Modifier.isTransient(f.getModifiers()))
                    throw new IllegalArgumentException
                      ("no such field (non transient) " + name);
                  if (field == null && f.getType() != type)
                    throw new IllegalArgumentException
                      ("Invalid requested type for field " + name);
                }
              catch (NoSuchFieldException e)
                {
                  if (field == null)
                    throw new IllegalArgumentException(e);
                }

            }
        }
      };

    fieldsAlreadyRead = true;
    return prereadFields;
  }

  /**
   * Protected constructor that allows subclasses to override
   * deserialization.  This constructor should be called by subclasses
   * that wish to override <code>readObject (Object)</code>.  This
   * method does a security check <i>NOTE: currently not
   * implemented</i>, then sets a flag that informs
   * <code>readObject (Object)</code> to call the subclasses
   * <code>readObjectOverride (Object)</code> method.
   *
   * @see #readObjectOverride()
   */
  protected ObjectInputStream()
    throws IOException, SecurityException
  {
    SecurityManager sec_man = System.getSecurityManager();
    if (sec_man != null)
      sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
    this.useSubclassMethod = true;
  }

  /**
   * This method allows subclasses to override the default
   * de serialization mechanism provided by
   * <code>ObjectInputStream</code>.  To make this method be used for
   * writing objects, subclasses must invoke the 0-argument
   * constructor on this class from their constructor.
   *
   * @see #ObjectInputStream()
   */
  protected Object readObjectOverride()
    throws ClassNotFoundException, IOException, OptionalDataException
  {
    throw new IOException("Subclass of ObjectInputStream must implement readObjectOverride");
  }

  /**
   * Assigns the next available handle to <code>obj</code>.
   *
   * @param obj The object for which we want a new handle.
   * @param shared True if the handle should be shared
   *               with later calls.
   * @return A valid handle for the specified object.
   */
  private int assignNewHandle(Object obj, boolean shared)
  {
    int handle = this.nextOID;
    this.nextOID = handle + 1;
    rememberHandle(obj,shared,handle);
    return handle;
  }

  /**
   * Remember the object associated with the given handle.
   *
   * @param obj an object
   * @param shared true if the reference should be shared
   *               with later calls.
   * @param handle a handle, must be >= baseWireHandle
   *
   * @see #lookupHandle
   */
  private void rememberHandle(Object obj, boolean shared,
                              int handle)
  {
    handles.put(handle, new Pair<Boolean,Object>(shared, obj));
  }

  /**
   * Look up the object associated with a given handle.
   *
   * @param handle a handle, must be >= baseWireHandle
   * @return the object remembered for handle or null if none.
   * @throws StreamCorruptedException if the handle is invalid.
   * @throws InvalidObjectException if the reference is not shared.
   * @see #rememberHandle
   */
  private Object lookupHandle(int handle)
    throws ObjectStreamException
  {
    Pair<Boolean,Object> result = handles.get(handle);
    if (result == null)
      throw new StreamCorruptedException("The handle, " +
                                         Integer.toHexString(handle) +
                                         ", is invalid.");
    if (!result.getLeft())
      throw new InvalidObjectException("The handle, " +
                                       Integer.toHexString(handle) +
                                       ", is not shared.");
    return result.getRight();
  }

  private Object processResolution(ObjectStreamClass osc, Object obj, int handle,
                                   boolean shared)
    throws IOException
  {
    if (osc != null && obj instanceof Serializable)
      {
        try
          {
            Method m = osc.readResolveMethod;
            if(m != null)
            {
                obj = m.invoke(obj, new Object[] {});
            }
          }
        catch (IllegalAccessException ignore)
          {
          }
        catch (InvocationTargetException exception)
          {
            Throwable cause = exception.getCause();
            if (cause instanceof ObjectStreamException)
              throw (ObjectStreamException) cause;
            else if (cause instanceof RuntimeException)
              throw (RuntimeException) cause;
            else if (cause instanceof Error)
              throw (Error) cause;
          }
      }

    if (this.resolveEnabled)
      obj = resolveObject(obj);

    rememberHandle(obj, shared, handle);
    if (!shared)
      {
        if (obj instanceof byte[])
          return ((byte[]) obj).clone();
        if (obj instanceof short[])
          return ((short[]) obj).clone();
        if (obj instanceof int[])
          return ((int[]) obj).clone();
        if (obj instanceof long[])
          return ((long[]) obj).clone();
        if (obj instanceof char[])
          return ((char[]) obj).clone();
        if (obj instanceof boolean[])
          return ((boolean[]) obj).clone();
        if (obj instanceof float[])
          return ((float[]) obj).clone();
        if (obj instanceof double[])
          return ((double[]) obj).clone();
        if (obj instanceof Object[])
          return ((Object[]) obj).clone();
      }
    return obj;
  }

  private void clearHandles()
  {
    handles.clear();
    this.nextOID = baseWireHandle;
  }

  private void readNextBlock() throws IOException
  {
    byte marker = this.realInputStream.readByte();
    while (marker == TC_RESET)
      {
        if(dump) dumpElementln("RESET");
        clearHandles();
        marker = this.realInputStream.readByte();
      }
    readNextBlock(marker);
  }

  private void readNextBlock(byte marker) throws IOException
  {
    if (marker == TC_BLOCKDATA)
      {
        if(dump) dumpElement("BLOCK DATA SIZE=");
        this.blockDataBytes = this.realInputStream.readUnsignedByte();
        if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
      }
    else if (marker == TC_BLOCKDATALONG)
      {
        if(dump) dumpElement("BLOCK DATA LONG SIZE=");
        this.blockDataBytes = this.realInputStream.readInt();
        if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
      }
    else
      {
        throw new EOFException("Attempt to read primitive data, but no data block is active.");
      }

    if (this.blockData.length < this.blockDataBytes)
      this.blockData = new byte[this.blockDataBytes];

    this.realInputStream.readFully (this.blockData, 0, this.blockDataBytes);
    this.blockDataPosition = 0;
  }

  private void readArrayElements (Object array, Class clazz)
    throws ClassNotFoundException, IOException
  {
    if (clazz.isPrimitive())
      {
        if (clazz == Boolean.TYPE)
          {
            boolean[] cast_array = (boolean[])array;
            for (int i=0; i < cast_array.length; i++)
              cast_array[i] = this.realInputStream.readBoolean();
            return;
          }
        if (clazz == Byte.TYPE)
          {
            byte[] cast_array = (byte[])array;
            for (int i=0; i < cast_array.length; i++)
              cast_array[i] = this.realInputStream.readByte();
            return;
          }
        if (clazz == Character.TYPE)
          {
            char[] cast_array = (char[])array;
            for (int i=0; i < cast_array.length; i++)
              cast_array[i] = this.realInputStream.readChar();
            return;
          }
        if (clazz == Double.TYPE)
          {
            double[] cast_array = (double[])array;
            for (int i=0; i < cast_array.length; i++)
              cast_array[i] = this.realInputStream.readDouble();
            return;
          }
        if (clazz == Float.TYPE)
          {
            float[] cast_array = (float[])array;
            for (int i=0; i < cast_array.length; i++)
              cast_array[i] = this.realInputStream.readFloat();
            return;
          }
        if (clazz == Integer.TYPE)
          {
            int[] cast_array = (int[])array;
            for (int i=0; i < cast_array.length; i++)
              cast_array[i] = this.realInputStream.readInt();
            return;
          }
        if (clazz == Long.TYPE)
          {
            long[] cast_array = (long[])array;
            for (int i=0; i < cast_array.length; i++)
              cast_array[i] = this.realInputStream.readLong();
            return;
          }
        if (clazz == Short.TYPE)
          {
            short[] cast_array = (short[])array;
            for (int i=0; i < cast_array.length; i++)
              cast_array[i] = this.realInputStream.readShort();
            return;
          }
      }
    else
      {
        Object[] cast_array = (Object[])array;
        for (int i=0; i < cast_array.length; i++)
          cast_array[i] = readObject();
      }
  }

  private void readFields (Object obj, ObjectStreamClass stream_osc)
    throws ClassNotFoundException, IOException
  {
    ObjectStreamField[] fields = stream_osc.fieldMapping;

    for (int i = 0; i < fields.length; i += 2)
      {
        ObjectStreamField stream_field = fields[i];
        ObjectStreamField real_field = fields[i + 1];
        boolean read_value = (stream_field != null && stream_field.getOffset() >= 0 && stream_field.isToSet());
        boolean set_value = (real_field != null && real_field.isToSet());
        String field_name;
        char type;

        if (stream_field != null)
          {
            field_name = stream_field.getName();
            type = stream_field.getTypeCode();
          }
        else
          {
            field_name = real_field.getName();
            type = real_field.getTypeCode();
          }

        switch(type)
          {
          case 'Z':
            {
              boolean value =
                read_value ? this.realInputStream.readBoolean() : false;
              if (dump && read_value && set_value)
                dumpElementln("  " + field_name + ": " + value);
              if (set_value)
                real_field.setBooleanField(obj, value);
              break;
            }
          case 'B':
            {
              byte value =
                read_value ? this.realInputStream.readByte() : 0;
              if (dump && read_value && set_value)
                dumpElementln("  " + field_name + ": " + value);
              if (set_value)
                real_field.setByteField(obj, value);
              break;
            }
          case 'C':
            {
              char value =
                read_value ? this.realInputStream.readChar(): 0;
              if (dump && read_value && set_value)
                dumpElementln("  " + field_name + ": " + value);
              if (set_value)
                real_field.setCharField(obj, value);
              break;
            }
          case 'D':
            {
              double value =
                read_value ? this.realInputStream.readDouble() : 0;
              if (dump && read_value && set_value)
                dumpElementln("  " + field_name + ": " + value);
              if (set_value)
                real_field.setDoubleField(obj, value);
              break;
            }
          case 'F':
            {
              float value =
                read_value ? this.realInputStream.readFloat() : 0;
              if (dump && read_value && set_value)
                dumpElementln("  " + field_name + ": " + value);
              if (set_value)
                real_field.setFloatField(obj, value);
              break;
            }
          case 'I':
            {
              int value =
                read_value ? this.realInputStream.readInt() : 0;
              if (dump && read_value && set_value)
                dumpElementln("  " + field_name + ": " + value);
              if (set_value)
                real_field.setIntField(obj, value);
              break;
            }
          case 'J':
            {
              long value =
                read_value ? this.realInputStream.readLong() : 0;
              if (dump && read_value && set_value)
                dumpElementln("  " + field_name + ": " + value);
              if (set_value)
                real_field.setLongField(obj, value);
              break;
            }
          case 'S':
            {
              short value =
                read_value ? this.realInputStream.readShort() : 0;
              if (dump && read_value && set_value)
                dumpElementln("  " + field_name + ": " + value);
              if (set_value)
                real_field.setShortField(obj, value);
              break;
            }
          case 'L':
          case '[':
            {
              Object value =
                read_value ? readObject() : null;
              if (set_value)
                real_field.setObjectField(obj, value);
              break;
            }
          default:
            throw new InternalError("Invalid type code: " + type);
          }
      }
  }

  // Toggles writing primitive data to block-data buffer.
  private boolean setBlockDataMode (boolean on)
  {
    boolean oldmode = this.readDataFromBlock;
    this.readDataFromBlock = on;

    if (on)
      this.dataInputStream = this.blockDataInput;
    else
      this.dataInputStream = this.realInputStream;
    return oldmode;
  }

  // returns a new instance of REAL_CLASS that has been constructed
  // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
  private Object newObject (Class real_class, Constructor constructor)
    throws ClassNotFoundException, IOException
  {
    if (constructor == null)
        throw new InvalidClassException("Missing accessible no-arg base class constructor for " + real_class.getName());
    try
      {
        return VMObjectInputStream.allocateObject(real_class, constructor.getDeclaringClass(), constructor);
      }
    catch (InstantiationException e)
      {
        throw (ClassNotFoundException) new ClassNotFoundException
          ("Instance of " + real_class + " could not be created").initCause(e);
      }
  }

  // runs all registered ObjectInputValidations in prioritized order
  // on OBJ
  private void invokeValidators() throws InvalidObjectException
  {
    try
      {
        Iterator<ValidatorAndPriority> it = currentObjectValidators.iterator();
        while(it.hasNext())
          {
            ValidatorAndPriority vap = it.next();
            ObjectInputValidation validator = vap.validator;
            validator.validateObject();
          }
      }
    finally
      {
        currentObjectValidators = null;
      }
  }

  private void callReadMethod (Method readObject, Class klass, Object obj)
    throws ClassNotFoundException, IOException
  {
    try
      {
        readObject.invoke(obj, new Object[] { this });
      }
    catch (InvocationTargetException x)
      {
        /* Rethrow if possible. */
        Throwable exception = x.getTargetException();
        if (exception instanceof RuntimeException)
          throw (RuntimeException) exception;
        if (exception instanceof IOException)
          throw (IOException) exception;
        if (exception instanceof ClassNotFoundException)
          throw (ClassNotFoundException) exception;

        throw (IOException) new IOException(
          "Exception thrown from readObject() on " + klass).initCause(x);
      }
    catch (Exception x)
      {
        throw (IOException) new IOException(
          "Failure invoking readObject() on " + klass).initCause(x);
      }

    // Invalidate fields which has been read through readFields.
    prereadFields = null;
  }

  private static final int BUFFER_SIZE = 1024;

  private DataInputStream realInputStream;
  private DataInputStream dataInputStream;
  private DataInputStream blockDataInput;
  private int blockDataPosition;
  private int blockDataBytes;
  private byte[] blockData;
  private boolean useSubclassMethod;
  private int nextOID;
  private boolean resolveEnabled;
  private Map<Integer,Pair<Boolean,Object>> handles;
  private Object currentObject;
  private ObjectStreamClass currentObjectStreamClass;
  private TreeSet<ValidatorAndPriority> currentObjectValidators;
  private boolean readDataFromBlock;
  private boolean fieldsAlreadyRead;
  private Hashtable<Class,ObjectStreamClass> classLookupTable;
  private GetField prereadFields;

  private static boolean dump;

  // The nesting depth for debugging output
  private int depth = 0;

  private static final boolean DEBUG = false;

  private void dumpElement (String msg)
  {
    System.out.print(msg);
  }

  private void dumpElementln (String msg)
  {
    System.out.println(msg);
    for (int i = 0; i < depth; i++)
      System.out.print (" ");
    System.out.print (Thread.currentThread() + ": ");
  }

  private void dumpElementln (String msg, Object obj)
  {
    try
      {
        System.out.print(msg);
        if (java.lang.reflect.Proxy.isProxyClass(obj.getClass()))
          System.out.println(obj.getClass());
        else
        System.out.println(obj);
      }
    catch (Exception _)
      {
      }
    for (int i = 0; i < depth; i++)
      System.out.print (" ");
    System.out.print (Thread.currentThread() + ": ");
  }

  // used to keep a prioritized list of object validators
  private static final class ValidatorAndPriority implements Comparable
  {
    int priority;
    ObjectInputValidation validator;

    ValidatorAndPriority (ObjectInputValidation validator, int priority)
    {
      this.priority = priority;
      this.validator = validator;
    }

    public int compareTo (Object o)
    {
      ValidatorAndPriority vap = (ValidatorAndPriority)o;
      return this.priority - vap.priority;
    }
  }
}
