/* ObjectOutputStream.java -- Class used to write serialized objects
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
   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 gnu.java.lang.reflect.TypeSignature;
import gnu.java.security.action.SetAccessibleAction;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.util.Hashtable;

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

    if (DEBUG)
      {
	String val = System.getProperty("gcj.dumpobjects");
	if (val != null && !val.equals(""))
	  dump = true;
      }
  }

  /**
   * 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 InvalidClassException Somebody tried to serialize
   * an object which is wrongly formatted.
   *
   * @exception IOException Exception from underlying
   * <code>OutputStream</code>.
   */
  public final void writeObject(Object obj) throws IOException
  {
    if (useSubclassMethod)
      {
	if (dump)
	  dumpElementln ("WRITE OVERRIDE: " + obj);
	  
	writeObjectOverride(obj);
	return;
      }

    if (dump)
      dumpElementln ("WRITE: " + obj);
    
    depth += 2;    

    boolean was_serializing = isSerializing;
    boolean old_mode = setBlockDataMode(false);
    try
      {
	isSerializing = true;
	boolean replaceDone = false;
	Object replacedObject = null;
	
	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)
	      {
		Class cl = (Class)obj;
		ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(cl);
		realOutput.writeByte(TC_CLASS);
		if (!osc.isProxyClass)
		  {
		    writeObject (osc);
		  }
		else
		  {
		    realOutput.writeByte(TC_PROXYCLASSDESC);
		    Class[] intfs = cl.getInterfaces();
		    realOutput.writeInt(intfs.length);
		    for (int i = 0; i < intfs.length; i++)
		      realOutput.writeUTF(intfs[i].getName());
		    
		    boolean oldmode = setBlockDataMode(true);
		    annotateProxyClass(cl);
		    setBlockDataMode(oldmode);
		    realOutput.writeByte(TC_ENDBLOCKDATA);
		    
		    writeObject(osc.getSuper());
		  }
		assignNewHandle(obj);
		break;
	      }

	    if (obj instanceof ObjectStreamClass)
	      {
		writeClassDescriptor((ObjectStreamClass) obj);
		break;
	      }

	    Class clazz = obj.getClass();
	    ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz);
	    if (osc == null)
	      throw new NotSerializableException(clazz.getName());
	    
	    if ((replacementEnabled || obj instanceof Serializable)
		&& ! replaceDone)
	      {
		replacedObject = obj;
		
		if (obj instanceof Serializable)
		  {
		    try
		      {
                        Method m = osc.writeReplaceMethod;
                        if (m != null)
                            obj = m.invoke(obj, new Object[0]);
		      }
		    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;
	      }

	    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);
		    realOutput.writeByte(TC_ENDBLOCKDATA);
		  }

		break;
	      }

	    if (obj instanceof Serializable)
	      {
		Object prevObject = this.currentObject;
		ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
		currentObject = obj;
		ObjectStreamClass[] hierarchy =
		  ObjectStreamClass.getObjectStreamClasses(clazz);
		
		for (int i = 0; i < hierarchy.length; i++)
		  {
		    currentObjectStreamClass = hierarchy[i];
		    
		    fieldsAlreadyWritten = false;
		    if (currentObjectStreamClass.hasWriteMethod())
		      {
			if (dump)
			  dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
			setBlockDataMode(true);
			callWriteMethod(obj, currentObjectStreamClass);
			setBlockDataMode(false);
			realOutput.writeByte(TC_ENDBLOCKDATA);
			if (dump)
			  dumpElementln ("WRITE ENDBLOCKDATA FOR: " + obj);
		      }
		    else
		      {
			if (dump)
			  dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
			writeFields(obj, currentObjectStreamClass);
		      }
		  }

		this.currentObject = prevObject;
		this.currentObjectStreamClass = prevObjectStreamClass;
		currentPutField = null;
		break;
	      }

	    throw new NotSerializableException(clazz.getName()
					       + " in "
					       + obj.getClass());
	  } // end pseudo-loop
      }
    catch (ObjectStreamException ose)
      {
	// Rethrow these are fatal.
	throw ose;
      }
    catch (IOException e)
      {
	realOutput.writeByte(TC_EXCEPTION);
	reset(true);

	setBlockDataMode(false);
	try
	  {
	    if (DEBUG)
	      {
		e.printStackTrace(System.out);
	      }
	    writeObject(e);
	  }
	catch (IOException ioe)
	  {
	    StreamCorruptedException ex = 
	      new StreamCorruptedException
	      (ioe + " thrown while exception was being written to stream.");
	    if (DEBUG)
	      {
		ex.printStackTrace(System.out);
	      }
	    throw ex;
	  }

	reset (true);
	
      }
    finally
      {
	isSerializing = was_serializing;
	setBlockDataMode(old_mode);
	depth -= 2;

	if (dump)
	  dumpElementln ("END: " + obj);
      }
  }

  protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException
  {
    if (osc.isProxyClass)
      {
        realOutput.writeByte(TC_PROXYCLASSDESC);
	Class[] intfs = osc.forClass().getInterfaces();
	realOutput.writeInt(intfs.length);
	for (int i = 0; i < intfs.length; i++)
	  realOutput.writeUTF(intfs[i].getName());

        boolean oldmode = setBlockDataMode(true);
        annotateProxyClass(osc.forClass());
        setBlockDataMode(oldmode);
        realOutput.writeByte(TC_ENDBLOCKDATA);
      }
    else
      {
        realOutput.writeByte(TC_CLASSDESC);
        realOutput.writeUTF(osc.getName());
        realOutput.writeLong(osc.getSerialVersionUID());
        assignNewHandle(osc);

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

        boolean oldmode = setBlockDataMode(true);
        annotateClass(osc.forClass());
        setBlockDataMode(oldmode);
        realOutput.writeByte(TC_ENDBLOCKDATA);
      }

    if (osc.isSerializable() || osc.isExternalizable())
      writeObject(osc.getSuper());
    else
      writeObject(null);
  }
  
  /**
   * 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);
  }


  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 writeFields 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_2</code> by default, as is done
   * by the JDK 1.2.
   *
   * A non-portable method, <code>setDefaultProtocolVersion (int
   * version)</code> is provided to change the default protocol
   * version.
   *
   * For an explanation of the differences between 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 ObjectInputStream#resolveClass(java.io.ObjectStreamClass)
   */
  protected void annotateClass(Class cl) throws IOException
  {
  }

  protected void annotateProxyClass(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)
      {
	SecurityManager sm = System.getSecurityManager();
	if (sm != null)
	  sm.checkPermission(new SerializablePermission("enableSubstitution"));
      }

    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 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 DataOutputStream#write(byte[])
   */
  public void write(byte[] b) throws IOException
  {
    write(b, 0, b.length);
  }


  /**
   * @see 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 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;

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


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


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


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


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


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


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


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


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


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


  /**
   * @see java.io.DataOutputStream#writeBytes (java.lang.String)
   */
  public void writeBytes(String data) throws IOException
  {
    blockDataOutput.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 abstract static class PutField
  {
    public abstract void put (String name, boolean value);
    public abstract void put (String name, byte value);
    public abstract void put (String name, char value);
    public abstract void put (String name, double value);
    public abstract void put (String name, float value);
    public abstract void put (String name, int value);
    public abstract void put (String name, long value);
    public abstract void put (String name, short value);
    public abstract void put (String name, Object value);

    /**
     * @deprecated
     */
    public abstract void write (ObjectOutput out) throws IOException;
  }

  public PutField putFields() throws IOException
  {
    if (currentPutField != null)
      return currentPutField;

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

	private ObjectStreamField getField (String name)
	{
	  ObjectStreamField field
	    = currentObjectStreamClass.getField(name);
	  
	  if (field == null)
	    throw new IllegalArgumentException("no such serializable field " + name);
	  
	  return field;
	}
	
	public void put(String name, boolean value)
	{
	  ObjectStreamField field = getField(name);

	  checkType(field, 'Z');
	  prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
	}

	public void put(String name, byte value)
	{
	  ObjectStreamField field = getField(name);

	  checkType(field, 'B');
	  prim_field_data[field.getOffset()] = value;
	}

	public void put(String name, char value)
	{
	  ObjectStreamField field = 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)
	{
	  ObjectStreamField field = 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)
	{
	  ObjectStreamField field = 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)
	{
	  ObjectStreamField field = 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)
	{
	  ObjectStreamField field = 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)
	{
	  ObjectStreamField field = 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)
	{
	  ObjectStreamField field = getField(name);

	  if (value != null &&
	      ! field.getType().isAssignableFrom(value.getClass ()))	    
	    throw new IllegalArgumentException("Class " + value.getClass() +
					       " cannot be cast to " + field.getType());
	  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.
	  boolean oldmode = setBlockDataMode(false);
	  out.write(prim_field_data);
	  for (int i = 0; i < objs.length; ++ i)
	    out.writeObject(objs[i]);
	  setBlockDataMode(oldmode);
	}

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

    markFieldsWritten();
    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);
	    realOutput.write(cast_array, 0, length);
	    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 for the specified ObjectStreamClass.
  // FIELDS are already in canonical order.
  private void writeFields(Object obj, ObjectStreamClass osc)
    throws IOException
  {
    ObjectStreamField[] fields = osc.fields;
    boolean oldmode = setBlockDataMode(false);
    String field_name;
    Class type;

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

	if (dump)
	  dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);

	if (type == Boolean.TYPE)
	  realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
	else if (type == Byte.TYPE)
	  realOutput.writeByte(getByteField(obj, osc.forClass(), field_name));
	else if (type == Character.TYPE)
	  realOutput.writeChar(getCharField(obj, osc.forClass(), field_name));
	else if (type == Double.TYPE)
	  realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name));
	else if (type == Float.TYPE)
	  realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name));
	else if (type == Integer.TYPE)
	  realOutput.writeInt(getIntField(obj, osc.forClass(), field_name));
	else if (type == Long.TYPE)
	  realOutput.writeLong(getLongField(obj, osc.forClass(), field_name));
	else if (type == Short.TYPE)
	  realOutput.writeShort(getShortField(obj, osc.forClass(), field_name));
	else
	  writeObject(getObjectField(obj, osc.forClass(), field_name,
				     fields[i].getTypeString ()));
      }
    setBlockDataMode(oldmode);
  }


  // Toggles writing primitive data to block-data buffer.
  // Package-private to avoid a trampoline constructor.
  boolean setBlockDataMode(boolean on) throws IOException
  {
    if (on == writeDataAsBlocks)
      return on;

    drain();
    boolean oldmode = writeDataAsBlocks;
    writeDataAsBlocks = on;

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

    return oldmode;
  }


  private void callWriteMethod(Object obj, ObjectStreamClass osc)
    throws IOException
  {
    currentPutField = null;
    try
      {
        Object args[] = {this};
        osc.writeObjectMethod.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;

	IOException ioe
	  = new IOException("Exception thrown from writeObject() on " +
			    osc.forClass().getName() + ": " +
                            exception.getClass().getName());
	ioe.initCause(exception);
	throw ioe;
      }
    catch (Exception x)
      {
	IOException ioe
	  = new IOException("Failure invoking writeObject() on " +
			    osc.forClass().getName() + ": " +
			    x.getClass().getName());
	ioe.initCause(x);
	throw ioe;
      }
  }

  private boolean getBooleanField(Object obj, Class klass, String field_name)
    throws IOException
  {
    try
      {
	Field f = getField(klass, field_name);
	boolean b = f.getBoolean(obj);
	return b;
      }
    catch (IllegalArgumentException _)
      {
	throw new InvalidClassException
	  ("invalid requested type for field " + field_name + " in class " + klass.getName());
      }
    catch (IOException e)
      {
	throw e;
      }
    catch (Exception _)
      {
	throw new IOException("Unexpected exception " + _);
      }
  }

  private byte getByteField (Object obj, Class klass, String field_name)
    throws IOException
  {
    try
      {
	Field f = getField (klass, field_name);
	byte b = f.getByte (obj);
	return b;
      }
    catch (IllegalArgumentException _)
      {
	throw new InvalidClassException
	  ("invalid requested type for field " + field_name + " in class " + klass.getName());
      }
    catch (IOException e)
      {
	throw e;
      }
    catch (Exception _)
      {
	throw new IOException("Unexpected exception " + _);
      }    
  }

  private char getCharField (Object obj, Class klass, String field_name)
    throws IOException
  {
    try
      {
	Field f = getField (klass, field_name);
	char b = f.getChar (obj);
	return b;
      }
    catch (IllegalArgumentException _)
      {
	throw new InvalidClassException
	  ("invalid requested type for field " + field_name + " in class " + klass.getName());
      }
    catch (IOException e)
      {
	throw e;
      }
    catch (Exception _)
      {
	throw new IOException("Unexpected exception " + _);
      }    
  }

  private double getDoubleField (Object obj, Class klass, String field_name)
    throws IOException
  {
    try
      {
	Field f = getField (klass, field_name);
	double b = f.getDouble (obj);
	return b;
      }
    catch (IllegalArgumentException _)
      {
	throw new InvalidClassException
	  ("invalid requested type for field " + field_name + " in class " + klass.getName());
      }
    catch (IOException e)
      {
	throw e;
      }
    catch (Exception _)
      {
	throw new IOException("Unexpected exception " + _);
      }    
  }

  private float getFloatField (Object obj, Class klass, String field_name)
    throws IOException
  {
    try
      {
	Field f = getField (klass, field_name);
	float b = f.getFloat (obj);
	return b;
      }
    catch (IllegalArgumentException _)
      {
	throw new InvalidClassException
	  ("invalid requested type for field " + field_name + " in class " + klass.getName());
      }
    catch (IOException e)
      {
	throw e;
      }
    catch (Exception _)
      {
	throw new IOException("Unexpected exception " + _);
      }
  }

  private int getIntField (Object obj, Class klass, String field_name)
    throws IOException
  {
    try
      {
	Field f = getField (klass, field_name);
	int b = f.getInt (obj);
	return b;
      }
    catch (IllegalArgumentException _)
      {
	throw new InvalidClassException
	  ("invalid requested type for field " + field_name + " in class " + klass.getName());
      }
    catch (IOException e)
      {
	throw e;
      }
    catch (Exception _)
      {
	throw new IOException("Unexpected exception " + _);
      }
  }

  private long getLongField (Object obj, Class klass, String field_name)
    throws IOException
  {
    try
      {
	Field f = getField (klass, field_name);
	long b = f.getLong (obj);
	return b;
      }
    catch (IllegalArgumentException _)
      {
	throw new InvalidClassException
	  ("invalid requested type for field " + field_name + " in class " + klass.getName());
      }
    catch (IOException e)
      {
	throw e;
      }
    catch (Exception _)
      {
	throw new IOException("Unexpected exception " + _);
      }    
  }

  private short getShortField (Object obj, Class klass, String field_name)
    throws IOException
  {
    try
      {
	Field f = getField (klass, field_name);
	short b = f.getShort (obj);
	return b;
      }
    catch (IllegalArgumentException _)
      {
	throw new InvalidClassException
	  ("invalid requested type for field " + field_name + " in class " + klass.getName());
      }
    catch (IOException e)
      {
       throw e;
      }
    catch (Exception _)
      {
	throw new IOException("Unexpected exception " + _);
      }
  }

  private Object getObjectField (Object obj, Class klass, String field_name,
				 String type_code) throws IOException
  {
    try
      {
	Field f = getField (klass, field_name);
	ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType());

	/* if of is primitive something went wrong
	 * in the check for primitive classes in writeFields.
	 */
	if (of.isPrimitive())
	  throw new InvalidClassException
	    ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field is primitive");

	if (!of.getTypeString().equals(type_code))
	    throw new InvalidClassException
		("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field " + of + " has type string " + of.getTypeString() + " instead of " + type_code);

	Object o = f.get (obj);
	// FIXME: We should check the type_code here
	return o;
      }
    catch (IOException e)
      {
	throw e;
      }
    catch (Exception e)
      {
	throw new IOException ();
      }    
  }

  private Field getField (Class klass, String name)
    throws java.io.InvalidClassException
  {
    try
      {
	final Field f = klass.getDeclaredField(name);
	setAccessible.setMember(f);
	AccessController.doPrivileged(setAccessible);
	return f;
      }
    catch (java.lang.NoSuchFieldException e)
      {
	throw new InvalidClassException
	  ("no field called " + name + " in class " + klass.getName());
      }
  }

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

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

  private static int defaultProtocolVersion = PROTOCOL_VERSION_2;

  private DataOutputStream dataOutput;
  private boolean writeDataAsBlocks;
  private DataOutputStream realOutput;
  private DataOutputStream blockDataOutput;
  private byte[] blockData;
  private int blockDataCount;
  private Object currentObject;
  // Package-private to avoid a trampoline.
  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;
  private SetAccessibleAction setAccessible = new SetAccessibleAction();

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

  // Set if we're generating debugging dumps
  private boolean dump = false;

  private static final boolean DEBUG = false;
}
