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

This file is part of GNU Classpath.

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

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

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

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

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


package java.io;

import gnu.java.io.ObjectIdentityWrapper;
import 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 (osc.isEnum())
	      {
		/* TC_ENUM classDesc newHandle enumConstantName */
		realOutput.writeByte(TC_ENUM);
		writeObject(osc);
		assignNewHandle(obj);
		writeObject(((Enum) obj).name());
		break;
	      }

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

        assignNewHandle(osc);
    
        boolean oldmode = setBlockDataMode(true);
        annotateProxyClass(osc.forClass());
        setBlockDataMode(oldmode);
        realOutput.writeByte(TC_ENDBLOCKDATA);
      }
    else
      {
        realOutput.writeByte(TC_CLASSDESC);
        realOutput.writeUTF(osc.getName());
	if (osc.isEnum())
	  realOutput.writeLong(0L);
	else
	  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;

	if (fields == ObjectStreamClass.INVALID_FIELDS)
	  throw new InvalidClassException
		  (osc.getName(), "serialPersistentFields is invalid");

        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
   * since the JDK 1.2.
   * <p>
   * For an explanation of the differences between the two protocols
   * see the Java Object Serialization Specification.
   * </p>
   * 
   * @param version the version to use.
   * 
   * @throws IllegalArgumentException if <code>version</code> is not a valid 
   * protocol.
   * @throws IllegalStateException if called after the first the first object
   * was serialized.
   * @throws IOException if an I/O error occurs.
   * 
   * @see ObjectStreamConstants#PROTOCOL_VERSION_1
   * @see ObjectStreamConstants#PROTOCOL_VERSION_2
   * 
   * @since 1.2
   */
  public void useProtocolVersion(int version) throws IOException
  {
    if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
      throw new IllegalArgumentException("Invalid protocol version requested.");
    
    if (nextOID != baseWireHandle)
      throw new IllegalStateException("Protocol version cannot be changed " 
                                      + "after serialization started.");
    
    protocolVersion = 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;
}
