/* 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();
	   String constantName = (String) readObject();
	   if (dump)
	     dumpElementln("CONSTANT NAME = " + constantName);
	   Class clazz = osc.forClass();
	   Enum instance = Enum.valueOf(clazz, constantName);
	   assignNewHandle(instance,shared);
	   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;
    }
  }
}

