/* ObjectInputStream.java -- Class used to read serialized objects
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

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

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

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

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

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


package java.io;

import gnu.java.io.ObjectIdentityWrapper;

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.Hashtable;
import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;

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;
    this.objectLookupTable = new Hashtable();
    this.classLookupTable = new Hashtable();
    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
  {
    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);
      }
    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.
    * @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)
     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 ");
 	  Integer oid = new Integer(this.realInputStream.readInt());
 	  if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
 	  ret_val = ((ObjectIdentityWrapper)
 		     this.objectLookupTable.get(oid)).object;
 	  break;
 	}
 	
       case TC_CLASS:
 	{
 	  if(dump) dumpElementln("CLASS");
 	  ObjectStreamClass osc = (ObjectStreamClass)readObject();
 	  Class clazz = osc.forClass();
 	  assignNewHandle(clazz);
 	  ret_val = clazz;
 	  break;
 	}
 	
       case TC_PROXYCLASSDESC:
 	{
 	  if(dump) dumpElementln("PROXYCLASS");
 	  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);
                }
            }
 	  assignNewHandle(osc);
 	  
 	  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:
       case TC_LONGSTRING:
 	{
 	  if(dump) dumpElement("STRING=");
 	  String s = this.realInputStream.readUTF();
 	  if(dump) dumpElementln(s);
 	  ret_val = processResolution(null, s, assignNewHandle(s));
 	  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);
 	  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);
 	  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);
	      
 	      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);
              break;
	      
 	    } // end if (osc.realClassIsExternalizable)
 	  
 	  Object obj = newObject(clazz, osc.firstNonSerializableParentConstructor);
 	  
 	  int handle = assignNewHandle(obj);
 	  Object prevObject = this.currentObject;
 	  ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
	  TreeSet prevObjectValidators = this.currentObjectValidators;
 	  
 	  this.currentObject = obj;
	  this.currentObjectValidators = null;
 	  ObjectStreamClass[] hierarchy =
 	    inputGetObjectStreamClasses(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);
 			  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);
	  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);
	   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);

    ClassLoader callersClassLoader = currentLoader();
	      
    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, callersClassLoader);
      }
	      
    /* Now that fields have been read we may resolve the class
     * (and read annotation if needed). */
    Class clazz = resolveClass(osc);
    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();
    
    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 VMObjectInputStream.currentClassLoader();
  }

  /**
   * 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 = (ObjectStreamClass)classLookupTable.get(clazz);
    if (oclazz == null)
      return ObjectStreamClass.lookup(clazz);
    else
      return oclazz;
  }

  /**
   * Reconstruct class hierarchy the same way
   * {@link java.io.ObjectStreamClass#getObjectStreamClasses(Class)} does
   * but using lookupClass instead of ObjectStreamClass.lookup. This
   * dup is necessary localize the lookup table. Hopefully some future
   * rewritings will be able to prevent this.
   *
   * @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[] inputGetObjectStreamClasses(Class clazz)
  {
    ObjectStreamClass osc = lookupClass(clazz);

    if (osc == null)
      return new ObjectStreamClass[0];
    else
      {
        Vector oscs = new Vector();

        while (osc != null)
          {
            oscs.addElement(osc);
            osc = osc.getSuper();
	  }

        int count = oscs.size();
	ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[count];

        for (int i = count - 1; i >= 0; i--)
          sorted_oscs[count - i - 1] = (ObjectStreamClass) oscs.elementAt(i);

        return sorted_oscs;
      }
  }

  /**
   * 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.
   * @return A valid handle for the specified object.
   */
  private int assignNewHandle(Object obj)
  {
    this.objectLookupTable.put(new Integer(this.nextOID),
			       new ObjectIdentityWrapper(obj));
    return this.nextOID++;
  }

  private Object processResolution(ObjectStreamClass osc, Object obj, int handle)
    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);

    this.objectLookupTable.put(new Integer(handle),
			       new ObjectIdentityWrapper(obj));

    return obj;
  }

  private void clearHandles()
  {
    this.objectLookupTable.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 it = currentObjectValidators.iterator();
	while(it.hasNext())
	  {
	    ValidatorAndPriority vap = (ValidatorAndPriority) 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 Hashtable objectLookupTable;
  private Object currentObject;
  private ObjectStreamClass currentObjectStreamClass;
  private TreeSet currentObjectValidators;
  private boolean readDataFromBlock;
  private boolean fieldsAlreadyRead;
  private Hashtable 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() + ": ");
  }

  // 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;
    }
  }
}

