/* ObjectInputStream.java -- Class used to read serialized objects
   Copyright (C) 1998, 1999, 2000, 2001 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

As a special exception, if you link this library with other files to
produce an executable, this library does not by itself cause the
resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */


package java.io;

import gnu.classpath.Configuration;

import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Vector;

import gnu.java.io.ObjectIdentityWrapper;
import gnu.java.lang.reflect.TypeSignature;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;



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 (Configuration.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.isDeserializing = 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.validators = new Vector ();
    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.

     @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 ();

    boolean was_deserializing;

    Object ret_val;
    was_deserializing = this.isDeserializing;

    if (! was_deserializing)
      setBlockDataMode (false);

    this.isDeserializing = true;

    byte marker = this.realInputStream.readByte ();
    dumpElement ("MARKER: 0x" + Integer.toHexString(marker) + " ");

    switch (marker)
    {
      case TC_BLOCKDATA:
      case TC_BLOCKDATALONG:
	if (marker == TC_BLOCKDATALONG) 
	  dumpElementln ("BLOCKDATALONG");
	else
	  dumpElementln ("BLOCKDATA");
	readNextBlock (marker);
	throw new StreamCorruptedException ("Unexpected blockData");

      case TC_NULL:
	dumpElementln ("NULL");
	ret_val = null;
	break;

      case TC_REFERENCE:
      {
	dumpElement ("REFERENCE ");
	Integer oid = new Integer (this.realInputStream.readInt ());
	dumpElementln (Integer.toHexString(oid.intValue()));
	ret_val = ((ObjectIdentityWrapper)
		   this.objectLookupTable.get (oid)).object;
	break;
      }

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

      case TC_CLASSDESC:
      {
	dumpElement ("CLASSDESC NAME=");
	String name = this.realInputStream.readUTF ();
	dumpElement (name + "; UID=");
	long uid = this.realInputStream.readLong ();
	dumpElement (Long.toHexString(uid) + "; FLAGS=");
	byte flags = this.realInputStream.readByte ();
	dumpElement (Integer.toHexString(flags) + "; FIELD COUNT=");
	short field_count = this.realInputStream.readShort ();
	dumpElementln (Short.toString(field_count));
	ObjectStreamField[] fields = new ObjectStreamField[field_count];

	ObjectStreamClass osc = new ObjectStreamClass (name, uid,
						       flags, fields);
	assignNewHandle (osc);

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

	  if (type_code == 'L' || type_code == '[')
	    class_name = (String)readObject ();
	  else
	    class_name = String.valueOf (type_code);

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

	Class cl = resolveClass (osc);
	osc.setClass (cl);
	setBlockDataMode (false);

	if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
	  throw new IOException ("Data annotated to class was not consumed.");
	dumpElementln ("ENDBLOCKDATA ");

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

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

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

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

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

	if (Externalizable.class.isAssignableFrom (clazz))
	{
	  Externalizable obj = null;

	  try
	  {
	    obj = (Externalizable)clazz.newInstance ();
	  }
	  catch (InstantiationException e)
	  {
	    throw new ClassNotFoundException ("Instance of " + clazz
					      + " could not be created");
	  }
	  catch (IllegalAccessException e)
	  {
	    throw new ClassNotFoundException ("Instance of " + clazz
					      + " could not be created because class or zero-argument constructor is not accessible");
	  }
	  catch (NoSuchMethodError e)
	  {
	    throw new ClassNotFoundException ("Instance of " + clazz
					      + " could not be created because zero-argument constructor is not defined");
	  }

	  int handle = assignNewHandle (obj);

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

	  if (read_from_blocks)
	    setBlockDataMode (true);

	  obj.readExternal (this);

	  if (read_from_blocks)
	    setBlockDataMode (false);

	  ret_val = processResolution (obj, handle);
	  break;
	} // end if (Externalizable.class.isAssignableFrom (clazz))

	// find the first non-serializable, non-abstract
	// class in clazz's inheritance hierarchy
	Class first_nonserial = clazz.getSuperclass ();
	while (Serializable.class.isAssignableFrom (first_nonserial)
	       || Modifier.isAbstract (first_nonserial.getModifiers ()))
	  first_nonserial = first_nonserial.getSuperclass ();

//	DEBUGln ("Using " + first_nonserial
//		 + " as starting point for constructing " + clazz);

	Object obj = null;
	obj = newObject (clazz, first_nonserial);

	if (obj == null)
	  throw new ClassNotFoundException ("Instance of " + clazz +
					    " could not be created");

	int handle = assignNewHandle (obj);
	this.currentObject = obj;
	ObjectStreamClass[] hierarchy =
	  ObjectStreamClass.getObjectStreamClasses (clazz);

//	DEBUGln ("Got class hierarchy of depth " + hierarchy.length);

	boolean has_read;
	for (int i=0; i < hierarchy.length; i++)
	{
	  this.currentObjectStreamClass = hierarchy[i];

	  dumpElementln ("Reading fields of "
		   + this.currentObjectStreamClass.getName ());

	  has_read = true;

	  try
	  {
	    this.currentObjectStreamClass.forClass ().
	      getDeclaredMethod ("readObject", readObjectParams);
	  }
	  catch (NoSuchMethodException e)
	  {
	    has_read = false;
	  }

	  // 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
	  readFields (obj, this.currentObjectStreamClass.fields,
		      has_read, this.currentObjectStreamClass);

	  if (has_read)
	  {
	    dumpElement ("ENDBLOCKDATA? ");
	    try
	      {
		// FIXME: XXX: This try block is to catch EOF which is
		// thrown for some objects.  That indicates a bug in the logic.
	        if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
		  throw new IOException ("No end of block data seen for class with readObject (ObjectInputStream) method.");
	        dumpElementln ("yes");
	      }
	    catch (EOFException e)
	      {
	        dumpElementln ("no, got EOFException");
	      }
	    catch (IOException e)
	      {
	        dumpElementln ("no, got IOException");
	      }
	  }
	}

	this.currentObject = null;
	this.currentObjectStreamClass = null;
	ret_val = processResolution (obj, handle);
	break;
      }

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

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

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

    this.isDeserializing = was_deserializing;

    if (! was_deserializing)
    {
      setBlockDataMode (true);

      if (validators.size () > 0)
	invokeValidators ();
    }

    return ret_val;
  }


  /**
     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)");

    readFields (this.currentObject,
		this.currentObjectStreamClass.fields,
		false, this.currentObjectStreamClass);

    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");

    this.validators.addElement (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
  {
    SecurityManager sm = System.getSecurityManager ();

    // FIXME: currentClassLoader doesn't yet do anything useful. We need
    // to call forName() with the classloader of the class which called 
    // readObject(). See SecurityManager.getClassContext().
    ClassLoader cl = currentClassLoader (sm);

    return Class.forName (osc.getName (), true, cl);
  }

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


  /**
     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)
      if (getClass ().getClassLoader () != null)
	throw new SecurityException ("Untrusted ObjectInputStream subclass attempted to enable object resolution");

    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
  {
    dumpElement ("STREAM MAGIC ");
    if (this.realInputStream.readShort () != STREAM_MAGIC)
      throw new StreamCorruptedException ("Invalid stream magic number");

    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)
    {
      if (this.blockDataPosition + length > this.blockDataBytes)
	readNextBlock ();

      System.arraycopy (this.blockData, this.blockDataPosition,
			data, offset, length);
      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
  {
    return this.dataInputStream.readBoolean ();
  }

  public byte readByte () throws IOException
  {
    return this.dataInputStream.readByte ();
  }

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

  public short readShort () throws IOException
  {
    return this.dataInputStream.readShort ();
  }

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

  public char readChar () throws IOException
  {
    return this.dataInputStream.readChar ();
  }

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

  public long readLong () throws IOException
  {
    return this.dataInputStream.readLong ();
  }

  public float readFloat () throws IOException
  {
    return this.dataInputStream.readFloat ();
  }

  public double readDouble () throws IOException
  {
    return this.dataInputStream.readDouble ();
  }

  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 static abstract 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;
  }

  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 (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.
    setBlockDataMode (false);
    readFully (prim_field_data);
    for (int i = 0; i < objs.length; ++ i)
      objs[i] = readObject ();
    setBlockDataMode (true);

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

      public boolean defaulted (String name)
	throws IOException, IllegalArgumentException
      {
	return clazz.getField (name) == null;
      }

      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++] & 0xFF) << 56)
		      | ((prim_field_data[off++] & 0xFF) << 48)
		      | ((prim_field_data[off++] & 0xFF) << 40)
		      | ((prim_field_data[off++] & 0xFF) << 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++] & 0xFF) << 56)
		 | ((prim_field_data[off++] & 0xFF) << 48)
		 | ((prim_field_data[off++] & 0xFF) << 40)
		 | ((prim_field_data[off++] & 0xFF) << 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);

	if (field == null)
	  return null;

	Class field_type = field.getType ();

	if (type == field_type ||
	    (type == null && ! field_type.isPrimitive ()))
	  return field;

	throw new IllegalArgumentException ("Field requested is of type "
					    + field_type.getName ()
					    + ", but requested type was "
					    + (type == null ?
					       "Object" : type.getName ()));
      }
    };

  }


  /**
     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 (Object)
  */
  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 there constructor.

     @see ObjectInputStream ()
  */
  protected Object readObjectOverride ()
    throws ClassNotFoundException, IOException, OptionalDataException
  {
    throw new IOException ("Subclass of ObjectInputStream must implement readObjectOverride");
  }


  // assigns the next availible handle to OBJ
  private int assignNewHandle (Object obj)
  {
    this.objectLookupTable.put (new Integer (this.nextOID),
			     new ObjectIdentityWrapper (obj));

//    try
//    {
//      DEBUG ("Assigning handle " + this.nextOID);
//      DEBUGln (" to " + obj);
//    }
//    catch (Throwable t) {}

    return this.nextOID++;
  }


  private Object processResolution (Object obj, int handle)
    throws IOException
  {
    if (obj instanceof Serializable)
      {
        Method m = null; 
	try
	{
	  Class classArgs[] = {};
	  m = obj.getClass ().getDeclaredMethod ("readResolve", classArgs);
	  // m can't be null by definition since an exception would
	  // have been thrown so a check for null is not needed.
	  obj = m.invoke (obj, new Object[] {});	
	}
	catch (NoSuchMethodException ignore)
	{
	}
	catch (IllegalAccessException ignore)
	{
	}
	catch (InvocationTargetException ignore)
	{
	}
      }

    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
  {
//  DEBUGln ("In readNextBlock ");
    readNextBlock (this.realInputStream.readByte ());
  }


  private void readNextBlock (byte marker) throws IOException
  {
    if (marker == TC_BLOCKDATA)
    {
      dumpElement ("BLOCK DATA SIZE=");
      this.blockDataBytes = this.realInputStream.readUnsignedByte ();
      dumpElementln (Integer.toString(this.blockDataBytes));
    }
    else if (marker == TC_BLOCKDATALONG)
    {
      dumpElement ("BLOCK DATA LONG SIZE=");
      this.blockDataBytes = this.realInputStream.readInt ();
      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, ObjectStreamField[] stream_fields,
			   boolean call_read_method,
			   ObjectStreamClass stream_osc)
    throws ClassNotFoundException, IOException
  {
//  DEBUGln ("In readFields");
    if (call_read_method)
    {
//    DEBUGln ("  call_read_method is true");
      fieldsAlreadyRead = false;
      setBlockDataMode (true);
      callReadMethod (obj, stream_osc.forClass ());
      setBlockDataMode (false);
      return;
    }

    ObjectStreamField[] real_fields =
      ObjectStreamClass.lookup (stream_osc.forClass ()).fields;

    boolean default_initialize, set_value;
    String field_name = null;
    Class type = null;
    ObjectStreamField stream_field = null;
    ObjectStreamField real_field = null;
    int stream_idx = 0;
    int real_idx = 0;

    while (stream_idx < stream_fields.length
	   && real_idx < real_fields.length)
    {
      default_initialize = false;
      set_value = true;

      if (stream_idx == stream_fields.length)
	default_initialize = true;
      else
      {
	stream_field = stream_fields[stream_idx];
	type = stream_field.getType ();
      }

      if (real_idx == real_fields.length)
	set_value = false;
      else
      {
	real_field = real_fields[real_idx];
	type = real_field.getType ();
	field_name = real_field.getName ();
      }

      if (set_value && !default_initialize)
      {
	int comp_val =
	  real_field.compareTo (stream_field);

	if (comp_val < 0)
	{
	  default_initialize = true;
	  real_idx++;
	}
	else if (comp_val > 0)
	{
	  set_value = false;
	  stream_idx++;
	}
	else
	{
	  real_idx++;
	  stream_idx++;
	}
      }

      if (type == Boolean.TYPE)
      {
	boolean value =
	  default_initialize ? false : this.realInputStream.readBoolean ();
	if (!default_initialize && set_value)
	  dumpElementln ("  " + field_name + ": " + value);
	if (set_value)
	  setBooleanField (obj, field_name, value);
      }
      else if (type == Byte.TYPE)
      {
	byte value =
	  default_initialize ? 0 : this.realInputStream.readByte ();
	if (!default_initialize && set_value)
	  dumpElementln ("  " + field_name + ": " + value);
	if (set_value)
	  setByteField (obj, field_name, value);
      }
      else if (type == Character.TYPE)
      {
	char value =
	  default_initialize ? (char)0 : this.realInputStream.readChar ();
	if (!default_initialize && set_value)
	  dumpElementln ("  " + field_name + ": " + value);
	if (set_value)
	  setCharField (obj, field_name, value);
      }
      else if (type == Double.TYPE)
      {
	double value =
	  default_initialize ? 0 : this.realInputStream.readDouble ();
	if (!default_initialize && set_value)
	  dumpElementln ("  " + field_name + ": " + value);
	if (set_value)
	  setDoubleField (obj, field_name, value);
      }
      else if (type == Float.TYPE)
      {
	float value =
	  default_initialize ? 0 : this.realInputStream.readFloat ();
	if (!default_initialize && set_value)
	  dumpElementln ("  " + field_name + ": " + value);
	if (set_value)
	  setFloatField (obj, field_name, value);
      }
      else if (type == Integer.TYPE)
      {
	int value =
	  default_initialize ? 0 : this.realInputStream.readInt ();
	if (!default_initialize && set_value)
	  dumpElementln ("  " + field_name + ": " + value);
	if (set_value)
	  setIntField (obj, field_name, value);
      }
      else if (type == Long.TYPE)
      {
	long value =
	  default_initialize ? 0 : this.realInputStream.readLong ();
	if (!default_initialize && set_value)
	  dumpElementln ("  " + field_name + ": " + value);
	if (set_value)
	  setLongField (obj, field_name, value);
      }
      else if (type == Short.TYPE)
      {
	short value =
	  default_initialize ? (short)0 : this.realInputStream.readShort ();
	if (!default_initialize && set_value)
	  dumpElementln ("  " + field_name + ": " + value);
	if (set_value)
	  setShortField (obj, field_name, value);
      }
      else
      {
	Object value =
	  default_initialize ? null : readObject ();
	if (set_value)
	  setObjectField (obj, field_name,
			  real_field.getTypeString (), value);
      }
    }
  }


  // Toggles writing primitive data to block-data buffer.
  private void setBlockDataMode (boolean on)
  {
//    DEBUGln ("Setting block data mode to " + on);

    this.readDataFromBlock = on;

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


  // 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, Class constructor_class)
  {
    try
    {
      Object obj = allocateObject (real_class);
      callConstructor (constructor_class, obj);
      return obj;
    }
    catch (InstantiationException e)
    {
      return null;
    }
  }


  // runs all registered ObjectInputValidations in prioritized order
  // on OBJ
  private void invokeValidators () throws InvalidObjectException
  {
    Object[] validators = new Object[this.validators.size ()];
    this.validators.copyInto (validators);
    Arrays.sort (validators);

    try
    {
      for (int i=0; i < validators.length; i++)
	((ObjectInputValidation)validators[i]).validateObject ();
    }
    finally
    {
      this.validators.removeAllElements ();
    }
  }


  // this native method is used to get access to the protected method
  // of the same name in SecurityManger
  private static ClassLoader currentClassLoader (SecurityManager sm)
  {
    // FIXME: This is too simple.
    return ClassLoader.getSystemClassLoader ();
  }

  private static native Field getField (Class klass, String name)
    throws java.lang.NoSuchFieldException;

  private static native Method getMethod (Class klass, String name, Class args[])
    throws java.lang.NoSuchMethodException;

  private void callReadMethod (Object obj, Class klass) throws IOException
  {
    try
      {
	Class classArgs[] = {ObjectInputStream.class};
	Method m = getMethod (klass, "readObject", classArgs);
	if (m == null)
	  return;
	Object args[] = {this};
	m.invoke (obj, args);
      }
    catch (InvocationTargetException x)
      {
        /* Rethrow if possible. */
	Throwable exception = x.getTargetException();
	if (exception instanceof RuntimeException)
	  throw (RuntimeException) exception;
	if (exception instanceof IOException)
	  throw (IOException) exception;

	throw new IOException ("Exception thrown from readObject() on " +
			       klass + ": " + exception.getClass().getName());
      }
    catch (Exception x)
      {
	throw new IOException ("Failure invoking readObject() on " +
			       klass + ": " + x.getClass().getName());
      }
  }
    
  private native Object allocateObject (Class clazz)
    throws InstantiationException;

  private native void callConstructor (Class clazz, Object obj);

  private void setBooleanField (Object obj, String field_name,
				boolean val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	f.setBoolean (obj, val);
      }
    catch (Exception _)
      {
      }    
  }

  private void setByteField (Object obj, String field_name,
				byte val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	f.setByte (obj, val);
      }
    catch (Exception _)
      {
      }    
  }

  private void setCharField (Object obj, String field_name,
			     char val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	f.setChar (obj, val);
      }
    catch (Exception _)
      {
      }    
  }

  private void setDoubleField (Object obj, String field_name,
			       double val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	f.setDouble (obj, val);
      }
    catch (Exception _)
      {
      }    
  }

  private void setFloatField (Object obj, String field_name,
			      float val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	f.setFloat (obj, val);
      }
    catch (Exception _)
      {
      }    
  }

  private void setIntField (Object obj, String field_name,
			      int val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	f.setInt (obj, val);
      }
    catch (Exception _)
      {
      }    
  }


  private void setLongField (Object obj, String field_name,
			      long val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	f.setLong (obj, val);
      }
    catch (Exception _)
      {
      }    
  }


  private void setShortField (Object obj, String field_name,
			      short val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	f.setShort (obj, val);
      }
    catch (Exception _)
      {
      }    
  }


  private void setObjectField (Object obj, String field_name, String type_code,
			       Object val)
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	// FIXME: We should check the type_code here
	f.set (obj, val);
      }
    catch (Exception _)
      {
      }    
  }

  private static final int BUFFER_SIZE = 1024;
  private static final Class[] readObjectParams = { ObjectInputStream.class };

  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 boolean readDataFromBlock;
  private boolean isDeserializing;
  private boolean fieldsAlreadyRead;
  private Vector validators;

  private static boolean dump;  

  private void dumpElement (String msg)
  {
    if (Configuration.DEBUG && dump)  
      System.out.print(msg);
  }
  
  private void dumpElementln (String msg)
  {
    if (Configuration.DEBUG && dump)
      System.out.println(msg);
  }
}


// used to keep a prioritized list of object validators
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;
  }
}
