/* ObjectOutputStream.java -- Class used to write serialized objects
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008
   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.ObjectIdentityMap2Int;
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.security.PrivilegedAction;

/**
 * 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
 * @author Tom Tromey (tromey@redhat.com)
 * @author Jeroen Frijters (jeroen@frijters.net)
 * @author Guilhem Lavaux (guilhem@kaffe.org)
 * @author Michael Koch (konqueror@gmx.de)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 */
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
  {
    SecurityManager secMan = System.getSecurityManager();
    if (secMan != null && overridesMethods(getClass()))
      secMan.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);

    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 ObjectIdentityMap2Int();
    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.
   *
   * @param obj the object to serialize.
   * @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>.
   * @see #writeUnshared(Object)
   */
  public final void writeObject(Object obj) throws IOException
  {
    writeObject(obj, true);
  }

  /**
   * Writes an object to the stream in the same manner as
   * {@link #writeObject(Object)}, but without the use of
   * references.  As a result, the object is always written
   * to the stream in full.  Likewise, if an object is written
   * by this method and is then later written again by
   * {@link #writeObject(Object)}, both calls will write out
   * the object in full, as the later call to
   * {@link #writeObject(Object)} will know nothing of the
   * earlier use of {@link #writeUnshared(Object)}.
   *
   * @param obj the object to serialize.
   * @throws NotSerializableException if the object being
   *                                  serialized does not implement
   *                                  {@link Serializable}.
   * @throws InvalidClassException if a problem occurs with
   *                               the class of the object being
   *                               serialized.
   * @throws IOException if an I/O error occurs on the underlying
   *                     <code>OutputStream</code>.
   * @since 1.4
   * @see #writeObject(Object)
   */
  public void writeUnshared(Object obj)
    throws IOException
  {
    writeObject(obj, false);
  }

  /**
   * 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.
   *
   * @param obj the object to serialize.
   * @param shared true if the serialized object should be
   *               shared with later calls.
   * @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>.
   * @see #writeUnshared(Object)
   */
  private final void writeObject(Object obj, boolean shared)
    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;
              }

            int handle = findHandle(obj);
            if (handle >= 0 && shared)
              {
                realOutput.writeByte(TC_REFERENCE);
                realOutput.writeInt(handle);
                break;
              }

            if (obj instanceof Class)
              {
                Class cl = (Class)obj;
                ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(cl);
                realOutput.writeByte(TC_CLASS);
                if (!osc.isProxyClass)
                  {
                    writeObject (osc);
                  }
                else
                  {System.err.println("1");
                    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());
                  }
                if (shared)
                  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);
                if (shared)
                  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)
              {
                String s = (String)obj;
                long l = realOutput.getUTFlength(s, 0, 0);
                if (l <= 65535)
                  {
                    realOutput.writeByte(TC_STRING);
                    if (shared)
                      assignNewHandle(obj);
                    realOutput.writeUTFShort(s, (int)l);
                  }
                else
                  {
                    realOutput.writeByte(TC_LONGSTRING);
                    if (shared)
                      assignNewHandle(obj);
                    realOutput.writeUTFLong(s, l);
                  }
                break;
              }

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

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

            if (shared)
              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 = osc.hierarchy();

                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 int findHandle(Object obj)
  {
    return OIDLookupTable.get(obj);
  }


  // assigns the next availible handle to OBJ
  private int assignNewHandle(Object obj)
  {
    OIDLookupTable.put(obj, 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]);
      }
  }


/* GCJ LOCAL */
  // writes out FIELDS of OBJECT for the specified ObjectStreamClass.
  // FIELDS are already supposed already to be in canonical order, but
  // under some circumstances (to do with Proxies) this isn't the
  // case, so we call ensureFieldsSet().
  private void writeFields(Object obj, ObjectStreamClass osc)
    throws IOException
  {
    osc.ensureFieldsSet(osc.forClass());
/* END GCJ LOCAL */

    ObjectStreamField[] fields = osc.fields;
    boolean oldmode = setBlockDataMode(false);

    try
      {
        writeFields(obj,fields);
      }
    catch (IllegalArgumentException _)
      {
        InvalidClassException e = new InvalidClassException
          ("writing fields of class " + osc.forClass().getName());
        e.initCause(_);
        throw e;
      }
    catch (IOException e)
      {
        throw e;
      }
    catch (Exception _)
      {
        IOException e = new IOException("Unexpected exception " + _);
        e.initCause(_);
        throw(e);
      }

    setBlockDataMode(oldmode);
  }


  /**
   * Helper function for writeFields(Object,ObjectStreamClass): write
   * fields from given fields array.  Pass exception on.
   *
   * @param obj the object to be written
   *
   * @param fields the fields of obj to be written.
   */
  private void writeFields(Object obj, ObjectStreamField[] fields)
    throws
      IllegalArgumentException, IllegalAccessException, IOException
  {
    for (int i = 0; i < fields.length; i++)
      {
        ObjectStreamField osf = fields[i];
        Field field = osf.field;

        if (DEBUG && dump)
          dumpElementln ("WRITE FIELD: " + osf.getName() + " type=" + osf.getType());

        switch (osf.getTypeCode())
          {
          case 'Z': realOutput.writeBoolean(field.getBoolean(obj)); break;
          case 'B': realOutput.writeByte   (field.getByte   (obj)); break;
          case 'S': realOutput.writeShort  (field.getShort  (obj)); break;
          case 'C': realOutput.writeChar   (field.getChar   (obj)); break;
          case 'I': realOutput.writeInt    (field.getInt    (obj)); break;
          case 'F': realOutput.writeFloat  (field.getFloat  (obj)); break;
          case 'J': realOutput.writeLong   (field.getLong   (obj)); break;
          case 'D': realOutput.writeDouble (field.getDouble (obj)); break;
          case 'L':
          case '[':            writeObject (field.get       (obj)); break;
          default:
            throw new IOException("Unexpected type code " + osf.getTypeCode());
          }
      }
  }


  // 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 void dumpElementln (String msg, Object obj)
  {
    try
      {
        for (int i = 0; i < depth; i++)
          System.out.print (" ");
        System.out.print (Thread.currentThread() + ": ");
        System.out.print (msg);
        if (java.lang.reflect.Proxy.isProxyClass(obj.getClass()))
          System.out.print (obj.getClass());
        else
          System.out.print (obj);
      }
    catch (Exception _)
      {
      }
    finally
      {
        System.out.println ();
      }
  }

  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 ObjectIdentityMap2Int 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;

  /**
   * Returns true if the given class overrides either of the
   * methods <code>putFields</code> or <code>writeUnshared</code>.
   *
   * @param clazz the class to check.
   * @return true if the class overrides one of the methods.
   */
  private static boolean overridesMethods(final Class<?> clazz)
  {
    if (clazz == ObjectOutputStream.class)
      return false;

    return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
        public Boolean run()
        {
          Method[] methods = clazz.getDeclaredMethods();
          for (int a = 0; a < methods.length; ++a)
            {
              String name = methods[a].getName();
              if (name.equals("writeUnshared"))
                {
                  Class<?>[] paramTypes = methods[a].getParameterTypes();
                  if (paramTypes.length == 1 &&
                      paramTypes[0] == Object.class &&
                      methods[a].getReturnType() == Void.class)
                    return true;
                }
              else if (name.equals("putFields"))
                {
                  if (methods[a].getParameterTypes().length == 0 &&
                      methods[a].getReturnType() == PutField.class)
                    return true;
                }
            }
          return false;
        }
      });
  }

}
