/* ObjectOutputStream.java -- Class used to write serialized objects
   Copyright (C) 1998, 1999, 2000 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 java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.Hashtable;

import gnu.java.io.ObjectIdentityWrapper;
import gnu.java.lang.reflect.TypeSignature;

/**
   An <code>ObjectOutputStream</code> can be used to write objects
   as well as primitive data in a platform-independent manner to an
   <code>OutputStream</code>.

   The data produced by an <code>ObjectOutputStream</code> can be read
   and reconstituted by an <code>ObjectInputStream</code>.

   <code>writeObject (Object)</code> is used to write Objects, the
   <code>write&lt;type&gt;</code> methods are used to write primitive
   data (as in <code>DataOutputStream</code>). Strings can be written
   as objects or as primitive data.

   Not all objects can be written out using an
   <code>ObjectOutputStream</code>.  Only those objects that are an
   instance of <code>java.io.Serializable</code> can be written.

   Using default serialization, information about the class of an
   object is written, all of the non-transient, non-static fields of
   the object are written, if any of these fields are objects, they are
   written out in the same manner.

   An object is only written out the first time it is encountered.  If
   the object is encountered later, a reference to it is written to
   the underlying stream.  Thus writing circular object graphs
   does not present a problem, nor are relationships between objects
   in a graph lost.

   Example usage:
     <pre>
     Hashtable map = new Hashtable ();
     map.put ("one", new Integer (1));
     map.put ("two", new Integer (2));

     ObjectOutputStream oos =
       new ObjectOutputStream (new FileOutputStream ("numbers"));
     oos.writeObject (map);
     oos.close ();

     ObjectInputStream ois =
       new ObjectInputStream (new FileInputStream ("numbers"));
     Hashtable newmap = (Hashtable)ois.readObject ();

     System.out.println (newmap);
     </pre>

   The default serialization can be overriden in two ways.

   By defining a method <code>private void
   writeObject (ObjectOutputStream)</code>, a class can dictate exactly
   how information about itself is written.
   <code>defaultWriteObject ()</code> may be called from this method to
   carry out default serialization.  This method is not
   responsible for dealing with fields of super-classes or subclasses.

   By implementing <code>java.io.Externalizable</code>.  This gives
   the class complete control over the way it is written to the
   stream.  If this approach is used the burden of writing superclass
   and subclass data is transfered to the class implementing
   <code>java.io.Externalizable</code>.

   @see java.io.DataOutputStream
   @see java.io.Externalizable
   @see java.io.ObjectInputStream
   @see java.io.Serializable
   @see XXX: java serialization spec
*/
public class ObjectOutputStream extends OutputStream
  implements ObjectOutput, ObjectStreamConstants
{
  /**
     Creates a new <code>ObjectOutputStream</code> that will do all of
     its writing onto <code>out</code>.  This method also initializes
     the stream by writing the header information (stream magic number
     and stream version).

     @exception IOException Writing stream header to underlying
     stream cannot be completed.

     @see writeStreamHeader ()
  */
  public ObjectOutputStream (OutputStream out) throws IOException
  {
    realOutput = new DataOutputStream (out);
    blockData = new byte[ BUFFER_SIZE ];
    blockDataCount = 0;
    blockDataOutput = new DataOutputStream (this);
    setBlockDataMode (true);
    replacementEnabled = false;
    isSerializing = false;
    nextOID = baseWireHandle;
    OIDLookupTable = new Hashtable ();
    protocolVersion = defaultProtocolVersion;
    useSubclassMethod = false;
    writeStreamHeader ();
  }


  /**
     Writes a representation of <code>obj</code> to the underlying
     output stream by writing out information about its class, then
     writing out each of the objects non-transient, non-static
     fields.  If any of these fields are other objects,
     they are written out in the same manner.

     This method can be overriden by a class by implementing
     <code>private void writeObject (ObjectOutputStream)</code>.

     If an exception is thrown from this method, the stream is left in
     an undefined state.

     @exception NotSerializableException An attempt was made to
     serialize an <code>Object</code> that is not serializable.

     @exception IOException Exception from underlying
     <code>OutputStream</code>.
  */
  public final void writeObject (Object obj) throws IOException
  {
    if (useSubclassMethod)
    {
      writeObjectOverride (obj);
      return;
    }

    boolean was_serializing = isSerializing;

    if (! was_serializing)
      setBlockDataMode (false);

    try
    {
      isSerializing = true;
      boolean replaceDone = false;

      drain ();

      while (true)
      {
	if (obj == null)
	{
	  realOutput.writeByte (TC_NULL);
	  break;
	}

	Integer handle = findHandle (obj);
	if (handle != null)
	{
	  realOutput.writeByte (TC_REFERENCE);
	  realOutput.writeInt (handle.intValue ());
	  break;
	}

	if (obj instanceof Class)
	{
	  realOutput.writeByte (TC_CLASS);
	  writeObject (ObjectStreamClass.lookup ((Class)obj));
	  assignNewHandle (obj);
	  break;
	}

	if (obj instanceof ObjectStreamClass)
	{
	  ObjectStreamClass osc = (ObjectStreamClass)obj;
	  realOutput.writeByte (TC_CLASSDESC);
	  realOutput.writeUTF (osc.getName ());
	  realOutput.writeLong (osc.getSerialVersionUID ());
	  assignNewHandle (obj);

	  int flags = osc.getFlags ();

	  if (protocolVersion == PROTOCOL_VERSION_2
	      && osc.isExternalizable ())
	    flags |= SC_BLOCK_DATA;

	  realOutput.writeByte (flags);

	  ObjectStreamField[] fields = osc.fields;
	  realOutput.writeShort (fields.length);

	  ObjectStreamField field;
	  for (int i=0; i < fields.length; i++)
	  {
	    field = fields[i];
	    realOutput.writeByte (field.getTypeCode ());
	    realOutput.writeUTF (field.getName ());

	    if (! field.isPrimitive ())
	      writeObject (field.getTypeString ());
	  }

	  setBlockDataMode (true);
	  annotateClass (osc.forClass ());
	  setBlockDataMode (false);
	  realOutput.writeByte (TC_ENDBLOCKDATA);

	  if (osc.isSerializable ())
	    writeObject (osc.getSuper ());
	  else
	    writeObject (null);
	  break;
	}


	Object replacedObject = null;

	if ((replacementEnabled || obj instanceof Serializable)
	    && ! replaceDone)
	{
	  replacedObject = obj;

	  if (obj instanceof Serializable)
	    {
	      Method m = null;
	      try
	      {
	        Class classArgs[] = {};
		m = obj.getClass ().getDeclaredMethod ("writeReplace",
						       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 (replacementEnabled)
	    obj = replaceObject (obj);

	  replaceDone = true;
	  continue;
	}

	if (obj instanceof String)
	{
	  realOutput.writeByte (TC_STRING);
	  assignNewHandle (obj);
	  realOutput.writeUTF ((String)obj);
	  break;
	}

	Class clazz = obj.getClass ();
	ObjectStreamClass osc = ObjectStreamClass.lookup (clazz);
	if (osc == null)
	  throw new NotSerializableException (clazz.getName ());

	if (clazz.isArray ())
	{
	  realOutput.writeByte (TC_ARRAY);
	  writeObject (osc);
	  assignNewHandle (obj);
	  writeArraySizeAndElements (obj, clazz.getComponentType ());
	  break;
	}

	realOutput.writeByte (TC_OBJECT);
	writeObject (osc);

	if (replaceDone)
	  assignNewHandle (replacedObject);
	else
	  assignNewHandle (obj);

	if (obj instanceof Externalizable)
	{
	  if (protocolVersion == PROTOCOL_VERSION_2)
	    setBlockDataMode (true);

	  ((Externalizable)obj).writeExternal (this);

	  if (protocolVersion == PROTOCOL_VERSION_2)
	  {
	    setBlockDataMode (false);
	    drain ();
	  }

	  break;
	}

	if (obj instanceof Serializable)
	{
	  currentObject = obj;
	  ObjectStreamClass[] hierarchy =
	    ObjectStreamClass.getObjectStreamClasses (clazz);

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

	    fieldsAlreadyWritten = false;
	    has_write = currentObjectStreamClass.hasWriteMethod ();

	    writeFields (obj, currentObjectStreamClass.fields,
			 has_write);

	    if (has_write)
	    {
	      drain ();
	      realOutput.writeByte (TC_ENDBLOCKDATA);
	    }
	  }

	  currentObject = null;
	  currentObjectStreamClass = null;
	  currentPutField = null;
	  break;
	}

	throw new NotSerializableException (clazz.getName ());
      } // end pseudo-loop
    }
    catch (IOException e)
    {
      realOutput.writeByte (TC_EXCEPTION);
      reset (true);

      try
      {
	writeObject (e);
      }
      catch (IOException ioe)
      {
	throw new StreamCorruptedException ("Exception " + ioe + " thrown while exception was being written to stream.");
      }

      reset (true);
    }
    finally
    {
      isSerializing = was_serializing;

      if (! was_serializing)
	setBlockDataMode (true);
    }
  }


  /**
     Writes the current objects non-transient, non-static fields from
     the current class to the underlying output stream.

     This method is intended to be called from within a object's
     <code>private void writeObject (ObjectOutputStream)</code>
     method.

     @exception NotActiveException This method was called from a
     context other than from the current object's and current class's
     <code>private void writeObject (ObjectOutputStream)</code>
     method.

     @exception IOException Exception from underlying
     <code>OutputStream</code>.
  */
  public void defaultWriteObject ()
    throws IOException, NotActiveException
  {
    markFieldsWritten ();
    writeFields (currentObject, currentObjectStreamClass.fields, false);
  }


  private void markFieldsWritten () throws IOException
  {
    if (currentObject == null || currentObjectStreamClass == null)
      throw new NotActiveException ("defaultWriteObject called by non-active class and/or object");

    if (fieldsAlreadyWritten)
      throw new IOException ("Only one of putFields and defaultWriteObject may be called, and it may only be called once");

    fieldsAlreadyWritten = true;
  }


  /**
     Resets stream to state equivalent to the state just after it was
     constructed.

     Causes all objects previously written to the stream to be
     forgotten.  A notification of this reset is also written to the
     underlying stream.

     @exception IOException Exception from underlying
     <code>OutputStream</code> or reset called while serialization is
     in progress.
  */
  public void reset () throws IOException
  {
    reset (false);
  }


  private void reset (boolean internal) throws IOException
  {
    if (!internal)
    {
      if (isSerializing)
	throw new IOException ("Reset called while serialization in progress");

      realOutput.writeByte (TC_RESET);
    }

    clearHandles ();
  }


  /**
     Informs this <code>ObjectOutputStream</code> to write data
     according to the specified protocol.  There are currently two
     different protocols, specified by <code>PROTOCOL_VERSION_1</code>
     and <code>PROTOCOL_VERSION_2</code>.  This implementation writes
     data using <code>PROTOCOL_VERSION_1</code> by default, as is done
     by the JDK 1.1.

     A non-portable method, <code>setDefaultProtocolVersion (int
     version)</code> is provided to change the default protocol
     version.

     For an explination of the differences beween the two protocols
     see XXX: the Java ObjectSerialization Specification.

     @exception IOException if <code>version</code> is not a valid
     protocol

     @see setDefaultProtocolVersion (int)
  */
  public void useProtocolVersion (int version) throws IOException
  {
    if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
      throw new IOException ("Invalid protocol version requested.");

    protocolVersion = version;
  }


  /**
     <em>GNU $classpath specific</em>

     Changes the default stream protocol used by all
     <code>ObjectOutputStream</code>s.  There are currently two
     different protocols, specified by <code>PROTOCOL_VERSION_1</code>
     and <code>PROTOCOL_VERSION_2</code>.  The default default is
     <code>PROTOCOL_VERSION_1</code>.

     @exception IOException if <code>version</code> is not a valid
     protocol

     @see useProtocolVersion (int)
  */
  public static void setDefaultProtocolVersion (int version)
    throws IOException
  {
    if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
      throw new IOException ("Invalid protocol version requested.");

    defaultProtocolVersion = version;
  }


  /**
     An empty hook that allows subclasses to write extra information
     about classes to the stream.  This method is called the first
     time each class is seen, and after all of the standard
     information about the class has been written.

     @exception IOException Exception from underlying
     <code>OutputStream</code>.

     @see java.io.ObjectInputStream#resolveClass (java.io.ObjectStreamClass)
  */
  protected void annotateClass (Class cl) throws IOException
  {}


  /**
     Allows subclasses to replace objects that are written to the
     stream with other objects to be written in their place.  This
     method is called the first time each object is encountered
     (modulo reseting of the stream).

     This method must be enabled before it will be called in the
     serialization process.

     @exception IOException Exception from underlying
     <code>OutputStream</code>.

     @see enableReplaceObject (boolean)
  */
  protected Object replaceObject (Object obj) throws IOException
  {
    return obj;
  }


  /**
     If <code>enable</code> is <code>true</code> and this object is
     trusted, then <code>replaceObject (Object)</code> will be called
     in subsequent calls to <code>writeObject (Object)</code>.
     Otherwise, <code>replaceObject (Object)</code> will not be called.

     @exception SecurityException This class is not trusted.
  */
  protected boolean enableReplaceObject (boolean enable)
    throws SecurityException
  {
    if (enable)
      if (getClass ().getClassLoader () != null)
	throw new SecurityException ("Untrusted ObjectOutputStream subclass attempted to enable object replacement");

    boolean old_val = replacementEnabled;
    replacementEnabled = enable;
    return old_val;
  }


  /**
     Writes stream magic and stream version information to the
     underlying stream.

     @exception IOException Exception from underlying
     <code>OutputStream</code>.
  */
  protected void writeStreamHeader () throws IOException
  {
    realOutput.writeShort (STREAM_MAGIC);
    realOutput.writeShort (STREAM_VERSION);
  }



  /**
     Protected constructor that allows subclasses to override
     serialization.  This constructor should be called by subclasses
     that wish to override <code>writeObject (Object)</code>.  This
     method does a security check <i>NOTE: currently not
     implemented</i>, then sets a flag that informs
     <code>writeObject (Object)</code> to call the subclasses
     <code>writeObjectOverride (Object)</code> method.

     @see writeObjectOverride (Object)
  */
  protected ObjectOutputStream () throws IOException, SecurityException
  {
    SecurityManager sec_man = System.getSecurityManager ();
    if (sec_man != null)
      sec_man.checkPermission (SUBCLASS_IMPLEMENTATION_PERMISSION);
    useSubclassMethod = true;
  }


  /**
     This method allows subclasses to override the default
     serialization mechanism provided by
     <code>ObjectOutputStream</code>.  To make this method be used for
     writing objects, subclasses must invoke the 0-argument
     constructor on this class from there constructor.

     @see ObjectOutputStream ()

     @exception NotActiveException Subclass has arranged for this
     method to be called, but did not implement this method.
  */
  protected void writeObjectOverride (Object obj) throws NotActiveException,
    IOException
  {
    throw new NotActiveException ("Subclass of ObjectOutputStream must implement writeObjectOverride");
  }


  /**
     @see java.io.DataOutputStream#write (int)
  */
  public void write (int data) throws IOException
  {
    if (writeDataAsBlocks)
    {
      if (blockDataCount == BUFFER_SIZE)
	drain ();

      blockData[ blockDataCount++ ] = (byte)data;
    }
    else
      realOutput.write (data);
  }


  /**
     @see java.io.DataOutputStream#write (byte[])
  */
  public void write (byte[] b) throws IOException
  {
    write (b, 0, b.length);
  }


  /**
     @see java.io.DataOutputStream#write (byte[],int,int)
  */
  public void write (byte[] b, int off, int len) throws IOException
  {
    if (writeDataAsBlocks)
    {
      if (len < 0)
	throw new IndexOutOfBoundsException ();

      if (blockDataCount + len < BUFFER_SIZE)
      {
	System.arraycopy (b, off, blockData, blockDataCount, len);
	blockDataCount += len;
      }
      else
      {
	drain ();
	writeBlockDataHeader (len);
	realOutput.write (b, off, len);
      }
    }
    else
      realOutput.write (b, off, len);
  }


  /**
     @see java.io.DataOutputStream#flush ()
  */
  public void flush () throws IOException
  {
    drain ();
    realOutput.flush ();
  }


  /**
     Causes the block-data buffer to be written to the underlying
     stream, but does not flush underlying stream.

     @exception IOException Exception from underlying
     <code>OutputStream</code>.
  */
  protected void drain () throws IOException
  {
    if (blockDataCount == 0)
      return;

    writeBlockDataHeader (blockDataCount);
    realOutput.write (blockData, 0, blockDataCount);
    blockDataCount = 0;
  }


  /**
     @see java.io.DataOutputStream#close ()
  */
  public void close () throws IOException
  {
    drain ();
    realOutput.close ();
  }


  /**
     @see java.io.DataOutputStream#writeBoolean (boolean)
  */
  public void writeBoolean (boolean data) throws IOException
  {
    dataOutput.writeBoolean (data);
  }


  /**
     @see java.io.DataOutputStream#writeByte (int)
  */
  public void writeByte (int data) throws IOException
  {
    dataOutput.writeByte (data);
  }


  /**
     @see java.io.DataOutputStream#writeShort (int)
  */
  public void writeShort (int data) throws IOException
  {
    dataOutput.writeShort (data);
  }


  /**
     @see java.io.DataOutputStream#writeChar (int)
  */
  public void writeChar (int data) throws IOException
  {
    dataOutput.writeChar (data);
  }


  /**
     @see java.io.DataOutputStream#writeInt (int)
  */
  public void writeInt (int data) throws IOException
  {
    dataOutput.writeInt (data);
  }


  /**
     @see java.io.DataOutputStream#writeLong (long)
  */
  public void writeLong (long data) throws IOException
  {
    dataOutput.writeLong (data);
  }


  /**
     @see java.io.DataOutputStream#writeFloat (float)
  */
  public void writeFloat (float data) throws IOException
  {
    dataOutput.writeFloat (data);
  }


  /**
     @see java.io.DataOutputStream#writeDouble (double)
  */
  public void writeDouble (double data) throws IOException
  {
    dataOutput.writeDouble (data);
  }


  /**
     @see java.io.DataOutputStream#writeBytes (java.lang.String)
  */
  public void writeBytes (String data) throws IOException
  {
    dataOutput.writeBytes (data);
  }


  /**
     @see java.io.DataOutputStream#writeChars (java.lang.String)
  */
  public void writeChars (String data) throws IOException
  {
    dataOutput.writeChars (data);
  }


  /**
     @see java.io.DataOutputStream#writeUTF (java.lang.String)
  */
  public void writeUTF (String data) throws IOException
  {
    dataOutput.writeUTF (data);
  }


  /**
     This class allows a class to specify exactly which fields should
     be written, and what values should be written for these fields.

     XXX: finish up comments
  */
  public static abstract class PutField
  {
    public abstract void put (String name, boolean value)
      throws IOException, IllegalArgumentException;
    public abstract void put (String name, byte value)
      throws IOException, IllegalArgumentException;
    public abstract void put (String name, char value)
      throws IOException, IllegalArgumentException;
    public abstract void put (String name, double value)
      throws IOException, IllegalArgumentException;
    public abstract void put (String name, float value)
      throws IOException, IllegalArgumentException;
    public abstract void put (String name, int value)
      throws IOException, IllegalArgumentException;
    public abstract void put (String name, long value)
      throws IOException, IllegalArgumentException;
    public abstract void put (String name, short value)
      throws IOException, IllegalArgumentException;
    public abstract void put (String name, Object value)
      throws IOException, IllegalArgumentException;
    public abstract void write (ObjectOutput out) throws IOException;
  }


  public PutField putFields () throws IOException
  {
    markFieldsWritten ();

    currentPutField = new PutField ()
      {
	private byte[] prim_field_data
	  = new byte[currentObjectStreamClass.primFieldSize];
	private Object[] objs
	  = new Object[currentObjectStreamClass.objectFieldCount];

	public void put (String name, boolean value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    checkType (field, 'Z');
	    prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
	  }

	public void put (String name, byte value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    checkType (field, 'B');
	    prim_field_data[field.getOffset ()] = value;
	  }

	public void put (String name, char value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    checkType (field, 'C');
	    int off = field.getOffset ();
	    prim_field_data[off++] = (byte)(value >>> 8);
	    prim_field_data[off] = (byte)value;
	  }

	public void put (String name, double value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    checkType (field, 'D');
	    int off = field.getOffset ();
	    long l_value = Double.doubleToLongBits (value);
	    prim_field_data[off++] = (byte)(l_value >>> 52);
	    prim_field_data[off++] = (byte)(l_value >>> 48);
	    prim_field_data[off++] = (byte)(l_value >>> 40);
	    prim_field_data[off++] = (byte)(l_value >>> 32);
	    prim_field_data[off++] = (byte)(l_value >>> 24);
	    prim_field_data[off++] = (byte)(l_value >>> 16);
	    prim_field_data[off++] = (byte)(l_value >>> 8);
	    prim_field_data[off] = (byte)l_value;
	  }

	public void put (String name, float value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    checkType (field, 'F');
	    int off = field.getOffset ();
	    int i_value = Float.floatToIntBits (value);
	    prim_field_data[off++] = (byte)(i_value >>> 24);
	    prim_field_data[off++] = (byte)(i_value >>> 16);
	    prim_field_data[off++] = (byte)(i_value >>> 8);
	    prim_field_data[off] = (byte)i_value;
	  }

	public void put (String name, int value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    checkType (field, 'I');
	    int off = field.getOffset ();
	    prim_field_data[off++] = (byte)(value >>> 24);
	    prim_field_data[off++] = (byte)(value >>> 16);
	    prim_field_data[off++] = (byte)(value >>> 8);
	    prim_field_data[off] = (byte)value;
	  }

	public void put (String name, long value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    checkType (field, 'J');
	    int off = field.getOffset ();
	    prim_field_data[off++] = (byte)(value >>> 52);
	    prim_field_data[off++] = (byte)(value >>> 48);
	    prim_field_data[off++] = (byte)(value >>> 40);
	    prim_field_data[off++] = (byte)(value >>> 32);
	    prim_field_data[off++] = (byte)(value >>> 24);
	    prim_field_data[off++] = (byte)(value >>> 16);
	    prim_field_data[off++] = (byte)(value >>> 8);
	    prim_field_data[off] = (byte)value;
	  }

	public void put (String name, short value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    checkType (field, 'S');
	    int off = field.getOffset ();
	    prim_field_data[off++] = (byte)(value >>> 8);
	    prim_field_data[off] = (byte)value;
	  }

	public void put (String name, Object value)
	  throws IOException, IllegalArgumentException
	  {
	    ObjectStreamField field
	      = currentObjectStreamClass.getField (name);
	    if (value != null &&
	    	! field.getType ().isAssignableFrom (value.getClass ()))
	      throw new IllegalArgumentException ();
	    objs[field.getOffset ()] = value;
	  }

	public void write (ObjectOutput out) throws IOException
	  {
	    // Apparently Block data is not used with PutField as per
	    // empirical evidence against JDK 1.2.  Also see Mauve test
	    // java.io.ObjectInputOutput.Test.GetPutField.
	    setBlockDataMode (false);
	    out.write (prim_field_data);
	    for (int i = 0; i < objs.length; ++ i)
	      out.writeObject (objs[i]);
	    setBlockDataMode (true);
	  }

	private void checkType (ObjectStreamField field, char type)
	  throws IllegalArgumentException
	  {
	    if (TypeSignature.getEncodingOfClass (field.getType ()).charAt (0) != type)
	      throw new IllegalArgumentException ();
	  }
      };
    // end PutFieldImpl

    return currentPutField;
  }


  public void writeFields () throws IOException
  {
    if (currentPutField == null)
      throw new NotActiveException ("writeFields can only be called after putFields has been called");

    currentPutField.write (this);
  }


  // write out the block-data buffer, picking the correct header
  // depending on the size of the buffer
  private void writeBlockDataHeader (int size) throws IOException
  {
    if (size < 256)
    {
      realOutput.writeByte (TC_BLOCKDATA);
      realOutput.write (size);
    }
    else
    {
      realOutput.writeByte (TC_BLOCKDATALONG);
      realOutput.writeInt (size);
    }
  }


  // lookup the handle for OBJ, return null if OBJ doesn't have a
  // handle yet
  private Integer findHandle (Object obj)
  {
    return (Integer)OIDLookupTable.get (new ObjectIdentityWrapper (obj));
  }


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


  // resets mapping from objects to handles
  private void clearHandles ()
  {
    nextOID = baseWireHandle;
    OIDLookupTable.clear ();
  }


  // write out array size followed by each element of the array
  private void writeArraySizeAndElements (Object array, Class clazz)
    throws IOException
  {
    int length = Array.getLength (array);

    if (clazz.isPrimitive ())
    {
      if (clazz == Boolean.TYPE)
      {
	boolean[] cast_array = (boolean[])array;
	realOutput.writeInt (length);
	for (int i=0; i < length; i++)
	  realOutput.writeBoolean (cast_array[i]);
	return;
      }
      if (clazz == Byte.TYPE)
      {
	byte[] cast_array = (byte[])array;
	realOutput.writeInt (length);
	for (int i=0; i < length; i++)
	  realOutput.writeByte (cast_array[i]);
	return;
      }
      if (clazz == Character.TYPE)
      {
	char[] cast_array = (char[])array;
	realOutput.writeInt (length);
	for (int i=0; i < length; i++)
	  realOutput.writeChar (cast_array[i]);
	return;
      }
      if (clazz == Double.TYPE)
      {
	double[] cast_array = (double[])array;
	realOutput.writeInt (length);
	for (int i=0; i < length; i++)
	  realOutput.writeDouble (cast_array[i]);
	return;
      }
      if (clazz == Float.TYPE)
      {
	float[] cast_array = (float[])array;
	realOutput.writeInt (length);
	for (int i=0; i < length; i++)
	  realOutput.writeFloat (cast_array[i]);
	return;
      }
      if (clazz == Integer.TYPE)
      {
	int[] cast_array = (int[])array;
	realOutput.writeInt (length);
	for (int i=0; i < length; i++)
	  realOutput.writeInt (cast_array[i]);
	return;
      }
      if (clazz == Long.TYPE)
      {
	long[] cast_array = (long[])array;
	realOutput.writeInt (length);
	for (int i=0; i < length; i++)
	  realOutput.writeLong (cast_array[i]);
	return;
      }
      if (clazz == Short.TYPE)
      {
	short[] cast_array = (short[])array;
	realOutput.writeInt (length);
	for (int i=0; i < length; i++)
	  realOutput.writeShort (cast_array[i]);
	return;
      }
    }
    else
    {
      Object[] cast_array = (Object[])array;
      realOutput.writeInt (length);
      for (int i=0; i < length; i++)
	writeObject (cast_array[i]);
    }
  }


  // writes out FIELDS of OBJECT.  If CALL_WRITE_METHOD is true, use
  // object's writeObject (ObjectOutputStream), otherwise use default
  // serialization.  FIELDS are already in canonical order.
  private void writeFields (Object obj,
			    ObjectStreamField[] fields,
			    boolean call_write_method) throws IOException
  {
    if (call_write_method)
    {
      setBlockDataMode (true);
      callWriteMethod (obj);
      setBlockDataMode (false);
      return;
    }

    String field_name;
    Class type;
    for (int i=0; i < fields.length; i++)
    {
      field_name = fields[i].getName ();
      type = fields[i].getType ();

      if (type == Boolean.TYPE)
	realOutput.writeBoolean (getBooleanField (obj, field_name));
      else if (type == Byte.TYPE)
	realOutput.writeByte (getByteField (obj, field_name));
      else if (type == Character.TYPE)
	realOutput.writeChar (getCharField (obj, field_name));
      else if (type == Double.TYPE)
	realOutput.writeDouble (getDoubleField (obj, field_name));
      else if (type == Float.TYPE)
	realOutput.writeFloat (getFloatField (obj, field_name));
      else if (type == Integer.TYPE)
	realOutput.writeInt (getIntField (obj, field_name));
      else if (type == Long.TYPE)
	realOutput.writeLong (getLongField (obj, field_name));
      else if (type == Short.TYPE)
	realOutput.writeShort (getShortField (obj, field_name));
      else
	writeObject (getObjectField (obj, field_name,
				     TypeSignature.getEncodingOfClass (type)));
    }
  }


  // Toggles writing primitive data to block-data buffer.
  private void setBlockDataMode (boolean on)
  {
    writeDataAsBlocks = on;

    if (on)
      dataOutput = blockDataOutput;
    else
      dataOutput = realOutput;
  }


  private void callWriteMethod (Object obj) throws IOException
  {
    Class klass = obj.getClass ();
    try
      {
	Class classArgs[] = {ObjectOutputStream.class};
	Method m = getMethod (klass, "writeObject", 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 writeObject() on " +
			       klass + ": " + exception.getClass().getName());
      }
    catch (Exception x)
      {
	throw new IOException ("Failure invoking writeObject() on " +
			       klass + ": " + x.getClass().getName());
      }
  }

  private boolean getBooleanField (Object obj, String field_name) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	boolean b = f.getBoolean (obj);
	return b;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  private byte getByteField (Object obj, String field_name) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	byte b = f.getByte (obj);
	return b;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  private char getCharField (Object obj, String field_name) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	char b = f.getChar (obj);
	return b;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  private double getDoubleField (Object obj, String field_name) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	double b = f.getDouble (obj);
	return b;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  private float getFloatField (Object obj, String field_name) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	float b = f.getFloat (obj);
	return b;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  private int getIntField (Object obj, String field_name) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	int b = f.getInt (obj);
	return b;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  private long getLongField (Object obj, String field_name) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	long b = f.getLong (obj);
	return b;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  private short getShortField (Object obj, String field_name) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	short b = f.getShort (obj);
	return b;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  private Object getObjectField (Object obj, String field_name,
				 String type_code) throws IOException
  {
    try
      {
	Class klass = obj.getClass ();
	Field f = getField (klass, field_name);
	Object o = f.get (obj);
	// FIXME: We should check the type_code here
	return o;
      }
    catch (Exception _)
      {
	throw new IOException ();
      }    
  }

  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;

  // this value comes from 1.2 spec, but is used in 1.1 as well
  private final static int BUFFER_SIZE = 1024;

  private static int defaultProtocolVersion = PROTOCOL_VERSION_1;

  private DataOutputStream dataOutput;
  private boolean writeDataAsBlocks;
  private DataOutputStream realOutput;
  private DataOutputStream blockDataOutput;
  private byte[] blockData;
  private int blockDataCount;
  private Object currentObject;
  private ObjectStreamClass currentObjectStreamClass;
  private PutField currentPutField;
  private boolean fieldsAlreadyWritten;
  private boolean replacementEnabled;
  private boolean isSerializing;
  private int nextOID;
  private Hashtable OIDLookupTable;
  private int protocolVersion;
  private boolean useSubclassMethod;
}
