diff options
Diffstat (limited to 'libjava/java/io/ObjectOutputStream.java')
-rw-r--r-- | libjava/java/io/ObjectOutputStream.java | 1335 |
1 files changed, 0 insertions, 1335 deletions
diff --git a/libjava/java/io/ObjectOutputStream.java b/libjava/java/io/ObjectOutputStream.java deleted file mode 100644 index 23bcce49d76..00000000000 --- a/libjava/java/io/ObjectOutputStream.java +++ /dev/null @@ -1,1335 +0,0 @@ -/* ObjectOutputStream.java -- Class used to write serialized objects - Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -As a special exception, if you link this library with other files to -produce an executable, this library does not by itself cause the -resulting executable to be covered by the GNU General Public License. -This exception does not however invalidate any other reasons why the -executable file might be covered by the GNU General Public License. */ - - -package java.io; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Hashtable; - -import gnu.java.io.ObjectIdentityWrapper; -import gnu.java.lang.reflect.TypeSignature; - -/** - An <code>ObjectOutputStream</code> can be used to write objects - as well as primitive data in a platform-independent manner to an - <code>OutputStream</code>. - - The data produced by an <code>ObjectOutputStream</code> can be read - and reconstituted by an <code>ObjectInputStream</code>. - - <code>writeObject (Object)</code> is used to write Objects, the - <code>write<type></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, the are - written out in the same manner. - - An object is only written out the first time it is encountered. If - the object is encountered later, a reference to it is written to - the underlying stream. Thus writing circular object graphs - does not present a problem, nor are relationships between objects - in a graph lost. - - Example usage: - <pre> - Hashtable map = new Hashtable (); - map.put ("one", new Integer (1)); - map.put ("two", new Integer (2)); - - ObjectOutputStream oos = - new ObjectOutputStream (new FileOutputStream ("numbers")); - oos.writeObject (map); - oos.close (); - - ObjectInputStream ois = - new ObjectInputStream (new FileInputStream ("numbers")); - Hashtable newmap = (Hashtable)ois.readObject (); - - System.out.println (newmap); - </pre> - - The default serialization can be overriden in two ways. - - By defining a method <code>private void - writeObject (ObjectOutputStream)</code>, a class can dictate exactly - how information about itself is written. - <code>defaultWriteObject ()</code> may be called from this method to - carry out default serialization. This method is not - responsible for dealing with fields of super-classes or subclasses. - - By implementing <code>java.io.Externalizable</code>. This gives - the class complete control over the way it is written to the - stream. If this approach is used the burden of writing superclass - and subclass data is transfered to the class implementing - <code>java.io.Externalizable</code>. - - @see java.io.DataOutputStream - @see java.io.Externalizable - @see java.io.ObjectInputStream - @see java.io.Serializable - @see XXX: java serialization spec -*/ -public class ObjectOutputStream extends OutputStream - implements ObjectOutput, ObjectStreamConstants -{ - /** - Creates a new <code>ObjectOutputStream</code> that will do all of - its writing onto <code>out</code>. This method also initializes - the stream by writing the header information (stream magic number - and stream version). - - @exception IOException Writing stream header to underlying - stream cannot be completed. - - @see writeStreamHeader () - */ - public ObjectOutputStream (OutputStream out) throws IOException - { - realOutput = new DataOutputStream (out); - blockData = new byte[ BUFFER_SIZE ]; - blockDataCount = 0; - blockDataOutput = new DataOutputStream (this); - setBlockDataMode (true); - replacementEnabled = false; - isSerializing = false; - nextOID = baseWireHandle; - OIDLookupTable = new Hashtable (); - protocolVersion = defaultProtocolVersion; - useSubclassMethod = false; - writeStreamHeader (); - } - - - /** - Writes a representation of <code>obj</code> to the underlying - output stream by writing out information about its class, then - writing out each of the objects non-transient, non-static - fields. If any of these fields are other objects, - the are written out in the same manner. - - This method can be overriden by a class by implementing - <code>private void writeObject (ObjectOutputStream)</code>. - - If an exception is thrown from this method, the stream is left in - an undefined state. - - @exception NotSerializableException An attempt was made to - serialize an <code>Object</code> that is not serializable. - - @exception IOException Exception from underlying - <code>OutputStream</code>. - */ - public final void writeObject (Object obj) throws IOException - { - if (useSubclassMethod) - { - writeObjectOverride (obj); - return; - } - - boolean was_serializing = isSerializing; - - if (! was_serializing) - setBlockDataMode (false); - - try - { - isSerializing = true; - boolean replaceDone = false; - - drain (); - - while (true) - { - if (obj == null) - { - realOutput.writeByte (TC_NULL); - break; - } - - Integer handle = findHandle (obj); - if (handle != null) - { - realOutput.writeByte (TC_REFERENCE); - realOutput.writeInt (handle.intValue ()); - break; - } - - if (obj instanceof Class) - { - realOutput.writeByte (TC_CLASS); - writeObject (ObjectStreamClass.lookup ((Class)obj)); - assignNewHandle (obj); - break; - } - - if (obj instanceof ObjectStreamClass) - { - ObjectStreamClass osc = (ObjectStreamClass)obj; - realOutput.writeByte (TC_CLASSDESC); - realOutput.writeUTF (osc.getName ()); - realOutput.writeLong (osc.getSerialVersionUID ()); - assignNewHandle (obj); - - int flags = osc.getFlags (); - - if (protocolVersion == PROTOCOL_VERSION_2 - && osc.isExternalizable ()) - flags |= SC_BLOCK_DATA; - - realOutput.writeByte (flags); - - ObjectStreamField[] fields = osc.fields; - realOutput.writeShort (fields.length); - - ObjectStreamField field; - for (int i=0; i < fields.length; i++) - { - field = fields[i]; - realOutput.writeByte (field.getTypeCode ()); - realOutput.writeUTF (field.getName ()); - - if (! field.isPrimitive ()) - writeObject (field.getTypeString ()); - } - - setBlockDataMode (true); - annotateClass (osc.forClass ()); - setBlockDataMode (false); - realOutput.writeByte (TC_ENDBLOCKDATA); - - if (osc.isSerializable ()) - writeObject (osc.getSuper ()); - else - writeObject (null); - break; - } - - - Object replacedObject = null; - - if ((replacementEnabled || obj instanceof Replaceable) - && ! replaceDone) - { - replacedObject = obj; - - if (obj instanceof Replaceable) - obj = ((Replaceable)obj).writeReplace (); - - if (replacementEnabled) - obj = replaceObject (obj); - - replaceDone = true; - continue; - } - - if (obj instanceof String) - { - realOutput.writeByte (TC_STRING); - assignNewHandle (obj); - realOutput.writeUTF ((String)obj); - break; - } - - Class clazz = obj.getClass (); - ObjectStreamClass osc = ObjectStreamClass.lookup (clazz); - if (osc == null) - throw new NotSerializableException ("The class " - + clazz.getName () - + " is not Serializable"); - - if (clazz.isArray ()) - { - realOutput.writeByte (TC_ARRAY); - writeObject (osc); - assignNewHandle (obj); - writeArraySizeAndElements (obj, clazz.getComponentType ()); - break; - } - - realOutput.writeByte (TC_OBJECT); - writeObject (osc); - - if (replaceDone) - assignNewHandle (replacedObject); - else - assignNewHandle (obj); - - if (obj instanceof Externalizable) - { - if (protocolVersion == PROTOCOL_VERSION_2) - setBlockDataMode (true); - - ((Externalizable)obj).writeExternal (this); - - if (protocolVersion == PROTOCOL_VERSION_2) - { - setBlockDataMode (false); - drain (); - } - - break; - } - - if (obj instanceof Serializable) - { - currentObject = obj; - ObjectStreamClass[] hierarchy = - ObjectStreamClass.getObjectStreamClasses (clazz); - - boolean has_write; - for (int i=0; i < hierarchy.length; i++) - { - currentObjectStreamClass = hierarchy[i]; - - has_write = currentObjectStreamClass.hasWriteMethod (); - writeFields (obj, currentObjectStreamClass.fields, - has_write); - - fieldsAlreadyWritten = false; - - if (has_write) - { - drain (); - realOutput.writeByte (TC_ENDBLOCKDATA); - } - } - - currentObject = null; - currentObjectStreamClass = null; - currentPutField = null; - break; - } - - throw new NotSerializableException ("Instances of the class " - + clazz.getName () - + " are not Serializable"); - } // end pseudo-loop - } - catch (IOException e) - { - realOutput.writeByte (TC_EXCEPTION); - reset (true); - - try - { - writeObject (e); - } - catch (IOException ioe) - { - throw new StreamCorruptedException ("Exception " + ioe + " thrown while exception was being written to stream."); - } - - reset (true); - } - finally - { - isSerializing = was_serializing; - - if (! was_serializing) - setBlockDataMode (true); - } - } - - - /** - Writes the current objects non-transient, non-static fields from - the current class to the underlying output stream. - - This method is intended to be called from within a object's - <code>private void writeObject (ObjectOutputStream)</code> - method. - - @exception NotActiveException This method was called from a - context other than from the current object's and current class's - <code>private void writeObject (ObjectOutputStream)</code> - method. - - @exception IOException Exception from underlying - <code>OutputStream</code>. - */ - public void defaultWriteObject () - throws IOException, NotActiveException - { - markFieldsWritten (); - writeFields (currentObject, currentObjectStreamClass.fields, false); - } - - - private void markFieldsWritten () throws IOException - { - if (currentObject == null || currentObjectStreamClass == null) - throw new NotActiveException ("defaultWriteObject called by non-active class and/or object"); - - if (fieldsAlreadyWritten) - throw new IOException ("Only one of putFields and defaultWriteObject may be called, and it may only be called once"); - - fieldsAlreadyWritten = true; - } - - - /** - Resets stream to state equivalent to the state just after it was - constructed. - - Causes all objects previously written to the stream to be - forgotten. A notification of this reset is also written to the - underlying stream. - - @exception IOException Exception from underlying - <code>OutputStream</code> or reset called while serialization is - in progress. - */ - public void reset () throws IOException - { - reset (false); - } - - - private void reset (boolean internal) throws IOException - { - if (!internal) - { - if (isSerializing) - throw new IOException ("Reset called while serialization in progress"); - - realOutput.writeByte (TC_RESET); - } - - clearHandles (); - } - - - /** - Informs this <code>ObjectOutputStream</code> to write data - according to the specified protocol. There are currently two - different protocols, specified by <code>PROTOCOL_VERSION_1</code> - and <code>PROTOCOL_VERSION_2</code>. This implementation writes - data using <code>PROTOCOL_VERSION_1</code> by default, as is done - by the JDK 1.1. - - A non-portable method, <code>setDefaultProtocolVersion (int - version)</code> is provided to change the default protocol - version. - - For an explination of the differences beween the two protocols - see XXX: the Java ObjectSerialization Specification. - - @exception IOException if <code>version</code> is not a valid - protocol - - @see setDefaultProtocolVersion (int) - */ - public void useProtocolVersion (int version) throws IOException - { - if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2) - throw new IOException ("Invalid protocol version requested."); - - protocolVersion = version; - } - - - /** - <em>GNU $classpath specific</em> - - Changes the default stream protocol used by all - <code>ObjectOutputStream</code>s. There are currently two - different protocols, specified by <code>PROTOCOL_VERSION_1</code> - and <code>PROTOCOL_VERSION_2</code>. The default default is - <code>PROTOCOL_VERSION_1</code>. - - @exception IOException if <code>version</code> is not a valid - protocol - - @see useProtocolVersion (int) - */ - public static void setDefaultProtocolVersion (int version) - throws IOException - { - if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2) - throw new IOException ("Invalid protocol version requested."); - - defaultProtocolVersion = version; - } - - - /** - An empty hook that allows subclasses to write extra information - about classes to the stream. This method is called the first - time each class is seen, and after all of the standard - information about the class has been written. - - @exception IOException Exception from underlying - <code>OutputStream</code>. - - @see java.io.ObjectInputStream#resolveClass (java.io.ObjectStreamClass) - */ - protected void annotateClass (Class cl) throws IOException - {} - - - /** - Allows subclasses to replace objects that are written to the - stream with other objects to be written in their place. This - method is called the first time each object is encountered - (modulo reseting of the stream). - - This method must be enabled before it will be called in the - serialization process. - - @exception IOException Exception from underlying - <code>OutputStream</code>. - - @see enableReplaceObject (boolean) - */ - protected Object replaceObject (Object obj) throws IOException - { - return obj; - } - - - /** - If <code>enable</code> is <code>true</code> and this object is - trusted, then <code>replaceObject (Object)</code> will be called - in subsequent calls to <code>writeObject (Object)</code>. - Otherwise, <code>replaceObject (Object)</code> will not be called. - - @exception SecurityException This class is not trusted. - */ - protected boolean enableReplaceObject (boolean enable) - throws SecurityException - { - if (enable) - if (getClass ().getClassLoader () != null) - throw new SecurityException ("Untrusted ObjectOutputStream subclass attempted to enable object replacement"); - - boolean old_val = replacementEnabled; - replacementEnabled = enable; - return old_val; - } - - - /** - Writes stream magic and stream version information to the - underlying stream. - - @exception IOException Exception from underlying - <code>OutputStream</code>. - */ - protected void writeStreamHeader () throws IOException - { - realOutput.writeShort (STREAM_MAGIC); - realOutput.writeShort (STREAM_VERSION); - } - - - - /** - Protected constructor that allows subclasses to override - serialization. This constructor should be called by subclasses - that wish to override <code>writeObject (Object)</code>. This - method does a security check <i>NOTE: currently not - implemented</i>, then sets a flag that informs - <code>writeObject (Object)</code> to call the subclasses - <code>writeObjectOverride (Object)</code> method. - - @see writeObjectOverride (Object) - */ - protected ObjectOutputStream () throws IOException, SecurityException - { - SecurityManager sec_man = System.getSecurityManager (); - if (sec_man != null) - sec_man.checkPermission (SUBCLASS_IMPLEMENTATION_PERMISSION); - useSubclassMethod = true; - } - - - /** - This method allows subclasses to override the default - serialization mechanism provided by - <code>ObjectOutputStream</code>. To make this method be used for - writing objects, subclasses must invoke the 0-argument - constructor on this class from there constructor. - - @see ObjectOutputStream () - - @exception NotActiveException Subclass has arranged for this - method to be called, but did not implement this method. - */ - protected void writeObjectOverride (Object obj) throws NotActiveException, - IOException - { - throw new NotActiveException ("Subclass of ObjectOutputStream must implement writeObjectOverride"); - } - - - /** - @see java.io.DataOutputStream#write (int) - */ - public void write (int data) throws IOException - { - if (writeDataAsBlocks) - { - if (blockDataCount == BUFFER_SIZE) - drain (); - - blockData[ blockDataCount++ ] = (byte)data; - } - else - realOutput.write (data); - } - - - /** - @see java.io.DataOutputStream#write (byte[]) - */ - public void write (byte b[]) throws IOException - { - write (b, 0, b.length); - } - - - /** - @see java.io.DataOutputStream#write (byte[],int,int) - */ - public void write (byte b[], int off, int len) throws IOException - { - if (writeDataAsBlocks) - { - if (len < 0) - throw new IndexOutOfBoundsException (); - - if (blockDataCount + len < BUFFER_SIZE) - { - System.arraycopy (b, off, blockData, blockDataCount, len); - blockDataCount += len; - } - else - { - drain (); - writeBlockDataHeader (len); - realOutput.write (b, off, len); - } - } - else - realOutput.write (b, off, len); - } - - - /** - @see java.io.DataOutputStream#flush () - */ - public void flush () throws IOException - { - drain (); - realOutput.flush (); - } - - - /** - Causes the block-data buffer to be written to the underlying - stream, but does not flush underlying stream. - - @exception IOException Exception from underlying - <code>OutputStream</code>. - */ - protected void drain () throws IOException - { - if (blockDataCount == 0) - return; - - writeBlockDataHeader (blockDataCount); - realOutput.write (blockData, 0, blockDataCount); - blockDataCount = 0; - } - - - /** - @see java.io.DataOutputStream#close () - */ - public void close () throws IOException - { - drain (); - realOutput.close (); - } - - - /** - @see java.io.DataOutputStream#writeBoolean (boolean) - */ - public void writeBoolean (boolean data) throws IOException - { - dataOutput.writeBoolean (data); - } - - - /** - @see java.io.DataOutputStream#writeByte (int) - */ - public void writeByte (int data) throws IOException - { - dataOutput.writeByte (data); - } - - - /** - @see java.io.DataOutputStream#writeShort (int) - */ - public void writeShort (int data) throws IOException - { - dataOutput.writeShort (data); - } - - - /** - @see java.io.DataOutputStream#writeChar (int) - */ - public void writeChar (int data) throws IOException - { - dataOutput.writeChar (data); - } - - - /** - @see java.io.DataOutputStream#writeInt (int) - */ - public void writeInt (int data) throws IOException - { - dataOutput.writeInt (data); - } - - - /** - @see java.io.DataOutputStream#writeLong (long) - */ - public void writeLong (long data) throws IOException - { - dataOutput.writeLong (data); - } - - - /** - @see java.io.DataOutputStream#writeFloat (float) - */ - public void writeFloat (float data) throws IOException - { - dataOutput.writeFloat (data); - } - - - /** - @see java.io.DataOutputStream#writeDouble (double) - */ - public void writeDouble (double data) throws IOException - { - dataOutput.writeDouble (data); - } - - - /** - @see java.io.DataOutputStream#writeBytes (java.lang.String) - */ - public void writeBytes (String data) throws IOException - { - dataOutput.writeBytes (data); - } - - - /** - @see java.io.DataOutputStream#writeChars (java.lang.String) - */ - public void writeChars (String data) throws IOException - { - dataOutput.writeChars (data); - } - - - /** - @see java.io.DataOutputStream#writeUTF (java.lang.String) - */ - public void writeUTF (String data) throws IOException - { - dataOutput.writeUTF (data); - } - - - /** - This class allows a class to specify exactly which fields should - be written, and what values should be written for these fields. - - XXX: finish up comments - */ - public static abstract class PutField - { - public abstract void put (String name, boolean value) - throws IOException, IllegalArgumentException; - public abstract void put (String name, byte value) - throws IOException, IllegalArgumentException; - public abstract void put (String name, char value) - throws IOException, IllegalArgumentException; - public abstract void put (String name, double value) - throws IOException, IllegalArgumentException; - public abstract void put (String name, float value) - throws IOException, IllegalArgumentException; - public abstract void put (String name, int value) - throws IOException, IllegalArgumentException; - public abstract void put (String name, long value) - throws IOException, IllegalArgumentException; - public abstract void put (String name, short value) - throws IOException, IllegalArgumentException; - public abstract void put (String name, Object value) - throws IOException, IllegalArgumentException; - public abstract void write (ObjectOutput out) throws IOException; - } - - - public PutField putFields () throws IOException - { - markFieldsWritten (); - - currentPutField = new PutField () - { - private byte[] prim_field_data - = new byte[currentObjectStreamClass.primFieldSize]; - private Object[] objs - = new Object[currentObjectStreamClass.objectFieldCount]; - - public void put (String name, boolean value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - checkType (field, 'Z'); - prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0); - } - - public void put (String name, byte value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - checkType (field, 'B'); - prim_field_data[field.getOffset ()] = value; - } - - public void put (String name, char value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - checkType (field, 'B'); - int off = field.getOffset (); - prim_field_data[off++] = (byte)(value >>> 8); - prim_field_data[off] = (byte)value; - } - - public void put (String name, double value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - checkType (field, 'B'); - int off = field.getOffset (); - long l_value = Double.doubleToLongBits (value); - prim_field_data[off++] = (byte)(l_value >>> 52); - prim_field_data[off++] = (byte)(l_value >>> 48); - prim_field_data[off++] = (byte)(l_value >>> 40); - prim_field_data[off++] = (byte)(l_value >>> 32); - prim_field_data[off++] = (byte)(l_value >>> 24); - prim_field_data[off++] = (byte)(l_value >>> 16); - prim_field_data[off++] = (byte)(l_value >>> 8); - prim_field_data[off] = (byte)l_value; - } - - public void put (String name, float value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - checkType (field, 'B'); - int off = field.getOffset (); - int i_value = Float.floatToIntBits (value); - prim_field_data[off++] = (byte)(i_value >>> 24); - prim_field_data[off++] = (byte)(i_value >>> 16); - prim_field_data[off++] = (byte)(i_value >>> 8); - prim_field_data[off] = (byte)i_value; - } - - public void put (String name, int value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - checkType (field, 'B'); - int off = field.getOffset (); - prim_field_data[off++] = (byte)(value >>> 24); - prim_field_data[off++] = (byte)(value >>> 16); - prim_field_data[off++] = (byte)(value >>> 8); - prim_field_data[off] = (byte)value; - } - - public void put (String name, long value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - checkType (field, 'B'); - int off = field.getOffset (); - prim_field_data[off++] = (byte)(value >>> 52); - prim_field_data[off++] = (byte)(value >>> 48); - prim_field_data[off++] = (byte)(value >>> 40); - prim_field_data[off++] = (byte)(value >>> 32); - prim_field_data[off++] = (byte)(value >>> 24); - prim_field_data[off++] = (byte)(value >>> 16); - prim_field_data[off++] = (byte)(value >>> 8); - prim_field_data[off] = (byte)value; - } - - public void put (String name, short value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - checkType (field, 'B'); - int off = field.getOffset (); - prim_field_data[off++] = (byte)(value >>> 8); - prim_field_data[off] = (byte)value; - } - - public void put (String name, Object value) - throws IOException, IllegalArgumentException - { - ObjectStreamField field - = currentObjectStreamClass.getField (name); - if (! field.getType ().isAssignableFrom (value.getClass ())) - throw new IllegalArgumentException (); - objs[field.getOffset ()] = value; - } - - public void write (ObjectOutput out) throws IOException - { - out.write (prim_field_data); - for (int i = 0; i < objs.length; ++ i) - out.writeObject (objs[i]); - } - - private void checkType (ObjectStreamField field, char type) - throws IllegalArgumentException - { - if (TypeSignature.getEncodingOfClass (field.getType ()).charAt (0) != type) - throw new IllegalArgumentException (); - } - }; - // end PutFieldImpl - - return currentPutField; - } - - - public void writeFields () throws IOException - { - if (currentPutField == null) - throw new NotActiveException ("writeFields can only be called after putFields has been called"); - - currentPutField.write (this); - } - - - // write out the block-data buffer, picking the correct header - // depending on the size of the buffer - private void writeBlockDataHeader (int size) throws IOException - { - if (size < 256) - { - realOutput.writeByte (TC_BLOCKDATA); - realOutput.write (size); - } - else - { - realOutput.writeByte (TC_BLOCKDATALONG); - realOutput.writeInt (size); - } - } - - - // lookup the handle for OBJ, return null if OBJ doesn't have a - // handle yet - private Integer findHandle (Object obj) - { - return (Integer)OIDLookupTable.get (new ObjectIdentityWrapper (obj)); - } - - - // assigns the next availible handle to OBJ - private int assignNewHandle (Object obj) - { - OIDLookupTable.put (new ObjectIdentityWrapper (obj), - new Integer (nextOID)); - return nextOID++; - } - - - // resets mapping from objects to handles - private void clearHandles () - { - nextOID = baseWireHandle; - OIDLookupTable.clear (); - } - - - // write out array size followed by each element of the array - private void writeArraySizeAndElements (Object array, Class clazz) - throws IOException - { - int length = Array.getLength (array); - - if (clazz.isPrimitive ()) - { - if (clazz == Boolean.TYPE) - { - boolean[] cast_array = (boolean[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - realOutput.writeBoolean (cast_array[i]); - return; - } - if (clazz == Byte.TYPE) - { - byte[] cast_array = (byte[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - realOutput.writeByte (cast_array[i]); - return; - } - if (clazz == Character.TYPE) - { - char[] cast_array = (char[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - realOutput.writeChar (cast_array[i]); - return; - } - if (clazz == Double.TYPE) - { - double[] cast_array = (double[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - realOutput.writeDouble (cast_array[i]); - return; - } - if (clazz == Float.TYPE) - { - float[] cast_array = (float[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - realOutput.writeFloat (cast_array[i]); - return; - } - if (clazz == Integer.TYPE) - { - int[] cast_array = (int[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - realOutput.writeInt (cast_array[i]); - return; - } - if (clazz == Long.TYPE) - { - long[] cast_array = (long[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - realOutput.writeLong (cast_array[i]); - return; - } - if (clazz == Short.TYPE) - { - short[] cast_array = (short[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - realOutput.writeShort (cast_array[i]); - return; - } - } - else - { - Object[] cast_array = (Object[])array; - realOutput.writeInt (length); - for (int i=0; i < length; i++) - writeObject (cast_array[i]); - } - } - - - // writes out FIELDS of OBJECT. If CALL_WRITE_METHOD is true, use - // object's writeObject (ObjectOutputStream), otherwise use default - // serialization. FIELDS are already in canonical order. - private void writeFields (Object obj, - ObjectStreamField[] fields, - boolean call_write_method) throws IOException - { - if (call_write_method) - { - setBlockDataMode (true); - callWriteMethod (obj); - setBlockDataMode (false); - return; - } - - String field_name; - Class type; - for (int i=0; i < fields.length; i++) - { - field_name = fields[i].getName (); - type = fields[i].getType (); - - if (type == Boolean.TYPE) - realOutput.writeBoolean (getBooleanField (obj, field_name)); - else if (type == Byte.TYPE) - realOutput.writeByte (getByteField (obj, field_name)); - else if (type == Character.TYPE) - realOutput.writeChar (getCharField (obj, field_name)); - else if (type == Double.TYPE) - realOutput.writeDouble (getDoubleField (obj, field_name)); - else if (type == Float.TYPE) - realOutput.writeFloat (getFloatField (obj, field_name)); - else if (type == Integer.TYPE) - realOutput.writeInt (getIntField (obj, field_name)); - else if (type == Long.TYPE) - realOutput.writeLong (getLongField (obj, field_name)); - else if (type == Short.TYPE) - realOutput.writeShort (getShortField (obj, field_name)); - else - writeObject (getObjectField (obj, field_name, - TypeSignature.getEncodingOfClass (type))); - } - } - - - // Toggles writing primitive data to block-data buffer. - private void setBlockDataMode (boolean on) - { - writeDataAsBlocks = on; - - if (on) - dataOutput = blockDataOutput; - else - dataOutput = realOutput; - } - - - private void callWriteMethod (Object obj) throws IOException - { - try - { - Class classArgs[] = {Class.forName ("java.io.ObjectOutputStream")}; - Class klass = obj.getClass (); - Method m = getMethod (klass, "writeObject", classArgs); - if (m == null) - return; - Object args[] = {this}; - m.invoke (obj, args); - } - catch (Exception _) - { - throw new IOException (); - } - } - - private boolean getBooleanField (Object obj, String field_name) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - boolean b = f.getBoolean (obj); - return b; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private byte getByteField (Object obj, String field_name) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - byte b = f.getByte (obj); - return b; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private char getCharField (Object obj, String field_name) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - char b = f.getChar (obj); - return b; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private double getDoubleField (Object obj, String field_name) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - double b = f.getDouble (obj); - return b; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private float getFloatField (Object obj, String field_name) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - float b = f.getFloat (obj); - return b; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private int getIntField (Object obj, String field_name) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - int b = f.getInt (obj); - return b; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private long getLongField (Object obj, String field_name) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - long b = f.getLong (obj); - return b; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private short getShortField (Object obj, String field_name) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - short b = f.getShort (obj); - return b; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private Object getObjectField (Object obj, String field_name, - String type_code) throws IOException - { - try - { - Class klass = obj.getClass (); - Field f = getField (klass, field_name); - Object o = f.get (obj); - // FIXME: We should check the type_code here - return o; - } - catch (Exception _) - { - throw new IOException (); - } - } - - private static native Field getField (Class klass, String name) - throws java.lang.NoSuchFieldException; - - private static native Method getMethod (Class klass, String name, Class args[]) - throws java.lang.NoSuchMethodException; - - // this value comes from 1.2 spec, but is used in 1.1 as well - private final static int BUFFER_SIZE = 1024; - - private static int defaultProtocolVersion = PROTOCOL_VERSION_1; - - private DataOutputStream dataOutput; - private boolean writeDataAsBlocks; - private DataOutputStream realOutput; - private DataOutputStream blockDataOutput; - private byte[] blockData; - private int blockDataCount; - private Object currentObject; - private ObjectStreamClass currentObjectStreamClass; - private PutField currentPutField; - private boolean fieldsAlreadyWritten; - private boolean replacementEnabled; - private boolean isSerializing; - private int nextOID; - private Hashtable OIDLookupTable; - private int protocolVersion; - private boolean useSubclassMethod; -} |