Makefile.am (nat_source_files): Remove java/io/natObjectOutputStream.cc.

* Makefile.am (nat_source_files): Remove
        java/io/natObjectOutputStream.cc.
        * Makefile.in: Regenerated.
        * mauve-libgcj: Don't exclude java.io.ObjectInputOutput tests.
        * java/io/ObjectStreamField.java (typename): New field.
        (ObjectStreamField(String, Class)): Initialize new field.
        (ObjectStreamField(String, String)): New Constructor.
        (getTypeCode): Use new field.
        (getTypeString): Use new field.
        * java/io/ObjectOutputStream.java (writeObject): Rethrow fatal
        ObjectStreamExceptions. Remember and reset old BlockDataMode.
        Handle reading of Proxy classes. Never drain(), just write
        TC_ENDBLOCKDATA. Rethrow ObjectStreamExceptions.
        (drain): Check writeDataAsBlocks before calling writeBlockDataHeader.
        (flush): Call flush(), not just drain().
        (writeBoolean): Always use blockDataOutput.
        (writeByte): Likewise.
        (writeShort): Likewise.
        (writeChar): Likewise.
        (writeInt): Likewise.
        (writeLong): Likewise.
        (writeFloat): Likewise.
        (writeDouble): Likewise.
        (writeBytes): Likewise.
        (putfield (put(String,Object))): Throw IllegalArgumentException if
        field cannot be found.
        (putfield (write(ObjectOutput))): Remember old BlockDataMode.
        (writeArraySizeAndElements): Write byte[] in one go.
        (writeFields): Write TC_ENDBLOCKDATA when call_write_method, otherwise
        set BlockDataMode to false.
        (annotateProxyClass): New method.
        (defaultProtocolVersion): Now defaults to PROTOCOL_VERSION_2
        (getField): No longer native.
        (getMethod): Likewise.
        (setBlockDataMode): Always drain() on switch, return old mode.
        (static): New static code block.
        * java/io/natObjectOutputStream.cc: Removed.
        * java/io/ObjectInputStream.java (getField): No longer native.
        (getMethod): Likewise.
        (readObject): Remember and reset old BlockDataMode. Track whether
        object is consumed. Handle TC_ENDBLOCKDATA, TC_PROXYCLASSDESC and
        TC_LONGSTRING.
        (defaultReadObject): Set BlockDataMode to false during readFields.
        (resolveClass): Create new SecurityManager if necessary.
        Use Class.forName() if null ClassLoader found.
        (read(byte[],int,int): Copy remaining bytes to data before calling
        readNextBlock().
        (readFields): Set and reset BlockDataMode on call_read_method.
        Catch NoSuchFieldErrors.
        (setBlockDataMode): Return old mode.
        (static): New static code block.
        * java/io/natObjectInputStream.cc (getField): Removed.
        (getMethod): Likewise.

From-SVN: r63556
This commit is contained in:
Mark Wielaard 2003-02-28 11:38:56 +00:00 committed by Mark Wielaard
parent 28727f1fb3
commit 4480b3dcf6
9 changed files with 824 additions and 665 deletions

View file

@ -1,5 +1,5 @@
/* ObjectOutputStream.java -- Class used to write serialized objects
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@ -46,6 +46,7 @@ import java.util.Hashtable;
import gnu.java.io.ObjectIdentityWrapper;
import gnu.java.lang.reflect.TypeSignature;
import gnu.classpath.Configuration;
/**
An <code>ObjectOutputStream</code> can be used to write objects
@ -167,229 +168,242 @@ public class ObjectOutputStream extends OutputStream
public final void writeObject (Object obj) throws IOException
{
if (useSubclassMethod)
{
writeObjectOverride (obj);
return;
}
{
writeObjectOverride (obj);
return;
}
boolean was_serializing = isSerializing;
if (! was_serializing)
setBlockDataMode (false);
boolean old_mode = 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;
}
isSerializing = true;
boolean replaceDone = false;
Object replacedObject = null;
if ((replacementEnabled || obj instanceof Serializable)
&& ! replaceDone)
{
replacedObject = obj;
if (obj instanceof Serializable)
{
Method m = null;
try
{
Class classArgs[] = {};
m = obj.getClass ().getDeclaredMethod ("writeReplace",
classArgs);
// m can't be null by definition since an exception would
// have been thrown so a check for null is not needed.
obj = m.invoke (obj, new Object[] {});
}
catch (NoSuchMethodException ignore)
{
}
catch (IllegalAccessException ignore)
{
}
catch (InvocationTargetException ignore)
{
}
}
if (replacementEnabled)
obj = replaceObject (obj);
replaceDone = true;
continue;
}
if (obj instanceof String)
{
realOutput.writeByte (TC_STRING);
assignNewHandle (obj);
realOutput.writeUTF ((String)obj);
break;
}
Class clazz = obj.getClass ();
ObjectStreamClass osc = ObjectStreamClass.lookup (clazz);
if (osc == null)
throw new NotSerializableException (clazz.getName ());
if (clazz.isArray ())
{
realOutput.writeByte (TC_ARRAY);
writeObject (osc);
assignNewHandle (obj);
writeArraySizeAndElements (obj, clazz.getComponentType ());
break;
}
realOutput.writeByte (TC_OBJECT);
writeObject (osc);
if (replaceDone)
assignNewHandle (replacedObject);
else
assignNewHandle (obj);
if (obj instanceof Externalizable)
{
if (protocolVersion == PROTOCOL_VERSION_2)
setBlockDataMode (true);
((Externalizable)obj).writeExternal (this);
if (protocolVersion == PROTOCOL_VERSION_2)
while (true)
{
setBlockDataMode (false);
drain ();
}
break;
}
if (obj instanceof Serializable)
{
currentObject = obj;
ObjectStreamClass[] hierarchy =
ObjectStreamClass.getObjectStreamClasses (clazz);
boolean has_write;
for (int i=0; i < hierarchy.length; i++)
{
currentObjectStreamClass = hierarchy[i];
fieldsAlreadyWritten = false;
has_write = currentObjectStreamClass.hasWriteMethod ();
writeFields (obj, currentObjectStreamClass.fields,
has_write);
if (has_write)
{
drain ();
realOutput.writeByte (TC_ENDBLOCKDATA);
}
}
currentObject = null;
currentObjectStreamClass = null;
currentPutField = null;
break;
}
throw new NotSerializableException (clazz.getName ());
} // end pseudo-loop
}
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);
assignNewHandle (obj);
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());
}
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 ());
}
boolean oldmode = setBlockDataMode (true);
annotateClass (osc.forClass ());
setBlockDataMode (oldmode);
realOutput.writeByte (TC_ENDBLOCKDATA);
if (osc.isSerializable ())
writeObject (osc.getSuper ());
else
writeObject (null);
break;
}
if ((replacementEnabled || obj instanceof Serializable)
&& ! replaceDone)
{
replacedObject = obj;
if (obj instanceof Serializable)
{
Method m = null;
try
{
Class classArgs[] = {};
m = obj.getClass ().getDeclaredMethod ("writeReplace",
classArgs);
// m can't be null by definition since an exception would
// have been thrown so a check for null is not needed.
obj = m.invoke (obj, new Object[] {});
}
catch (NoSuchMethodException ignore)
{
}
catch (IllegalAccessException ignore)
{
}
catch (InvocationTargetException ignore)
{
}
}
if (replacementEnabled)
obj = replaceObject (obj);
replaceDone = true;
continue;
}
if (obj instanceof String)
{
realOutput.writeByte (TC_STRING);
assignNewHandle (obj);
realOutput.writeUTF ((String)obj);
break;
}
Class clazz = obj.getClass ();
ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject (clazz);
if (osc == null)
throw new NotSerializableException (clazz.getName ());
if (clazz.isArray ())
{
realOutput.writeByte (TC_ARRAY);
writeObject (osc);
assignNewHandle (obj);
writeArraySizeAndElements (obj, clazz.getComponentType ());
break;
}
realOutput.writeByte (TC_OBJECT);
writeObject (osc);
if (replaceDone)
assignNewHandle (replacedObject);
else
assignNewHandle (obj);
if (obj instanceof Externalizable)
{
if (protocolVersion == PROTOCOL_VERSION_2)
setBlockDataMode (true);
((Externalizable)obj).writeExternal (this);
if (protocolVersion == PROTOCOL_VERSION_2)
{
setBlockDataMode (false);
realOutput.writeByte (TC_ENDBLOCKDATA);
}
break;
}
if (obj instanceof Serializable)
{
currentObject = obj;
ObjectStreamClass[] hierarchy =
ObjectStreamClass.getObjectStreamClasses (clazz);
boolean has_write;
for (int i=0; i < hierarchy.length; i++)
{
currentObjectStreamClass = hierarchy[i];
fieldsAlreadyWritten = false;
has_write = currentObjectStreamClass.hasWriteMethod ();
writeFields (obj, currentObjectStreamClass.fields,
has_write);
}
currentObject = null;
currentObjectStreamClass = null;
currentPutField = null;
break;
}
throw new NotSerializableException (clazz.getName ());
} // end pseudo-loop
}
catch (ObjectStreamException ose)
{
// Rethrow these are fatal.
throw ose;
}
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.");
}
realOutput.writeByte (TC_EXCEPTION);
reset (true);
reset (true);
}
setBlockDataMode (false);
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;
{
isSerializing = was_serializing;
if (! was_serializing)
setBlockDataMode (true);
}
setBlockDataMode (old_mode);
}
}
@ -466,8 +480,8 @@ public class ObjectOutputStream extends OutputStream
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.
data using <code>PROTOCOL_VERSION_2</code> by default, as is done
by the JDK 1.2.
A non-portable method, <code>setDefaultProtocolVersion (int
version)</code> is provided to change the default protocol
@ -528,6 +542,8 @@ public class ObjectOutputStream extends OutputStream
protected void annotateClass (Class cl) throws IOException
{}
protected void annotateProxyClass(Class cl) throws IOException
{}
/**
Allows subclasses to replace objects that are written to the
@ -702,7 +718,8 @@ public class ObjectOutputStream extends OutputStream
if (blockDataCount == 0)
return;
writeBlockDataHeader (blockDataCount);
if (writeDataAsBlocks)
writeBlockDataHeader (blockDataCount);
realOutput.write (blockData, 0, blockDataCount);
blockDataCount = 0;
}
@ -713,7 +730,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void close () throws IOException
{
drain ();
flush ();
realOutput.close ();
}
@ -723,7 +740,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeBoolean (boolean data) throws IOException
{
dataOutput.writeBoolean (data);
blockDataOutput.writeBoolean (data);
}
@ -732,7 +749,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeByte (int data) throws IOException
{
dataOutput.writeByte (data);
blockDataOutput.writeByte (data);
}
@ -741,7 +758,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeShort (int data) throws IOException
{
dataOutput.writeShort (data);
blockDataOutput.writeShort (data);
}
@ -750,7 +767,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeChar (int data) throws IOException
{
dataOutput.writeChar (data);
blockDataOutput.writeChar (data);
}
@ -759,7 +776,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeInt (int data) throws IOException
{
dataOutput.writeInt (data);
blockDataOutput.writeInt (data);
}
@ -768,7 +785,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeLong (long data) throws IOException
{
dataOutput.writeLong (data);
blockDataOutput.writeLong (data);
}
@ -777,7 +794,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeFloat (float data) throws IOException
{
dataOutput.writeFloat (data);
blockDataOutput.writeFloat (data);
}
@ -786,7 +803,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeDouble (double data) throws IOException
{
dataOutput.writeDouble (data);
blockDataOutput.writeDouble (data);
}
@ -795,7 +812,7 @@ public class ObjectOutputStream extends OutputStream
*/
public void writeBytes (String data) throws IOException
{
dataOutput.writeBytes (data);
blockDataOutput.writeBytes (data);
}
@ -965,6 +982,8 @@ public class ObjectOutputStream extends OutputStream
{
ObjectStreamField field
= currentObjectStreamClass.getField (name);
if (field == null)
throw new IllegalArgumentException ();
if (value != null &&
! field.getType ().isAssignableFrom (value.getClass ()))
throw new IllegalArgumentException ();
@ -976,11 +995,11 @@ public class ObjectOutputStream extends OutputStream
// Apparently Block data is not used with PutField as per
// empirical evidence against JDK 1.2. Also see Mauve test
// java.io.ObjectInputOutput.Test.GetPutField.
setBlockDataMode (false);
boolean oldmode = setBlockDataMode (false);
out.write (prim_field_data);
for (int i = 0; i < objs.length; ++ i)
out.writeObject (objs[i]);
setBlockDataMode (true);
setBlockDataMode (oldmode);
}
private void checkType (ObjectStreamField field, char type)
@ -1067,8 +1086,7 @@ public class ObjectOutputStream extends OutputStream
{
byte[] cast_array = (byte[])array;
realOutput.writeInt (length);
for (int i=0; i < length; i++)
realOutput.writeByte (cast_array[i]);
realOutput.write(cast_array, 0, length);
return;
}
if (clazz == Character.TYPE)
@ -1142,9 +1160,11 @@ public class ObjectOutputStream extends OutputStream
setBlockDataMode (true);
callWriteMethod (obj);
setBlockDataMode (false);
realOutput.writeByte (TC_ENDBLOCKDATA);
return;
}
boolean oldmode = setBlockDataMode (false);
String field_name;
Class type;
for (int i=0; i < fields.length; i++)
@ -1170,20 +1190,28 @@ public class ObjectOutputStream extends OutputStream
realOutput.writeShort (getShortField (obj, field_name));
else
writeObject (getObjectField (obj, field_name,
TypeSignature.getEncodingOfClass (type)));
fields[i].getTypeString ()));
}
setBlockDataMode(oldmode);
}
// Toggles writing primitive data to block-data buffer.
private void setBlockDataMode (boolean on)
private 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;
}
@ -1355,16 +1383,22 @@ public class ObjectOutputStream extends OutputStream
}
}
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;
private static Field getField (Class klass, String name)
throws java.lang.NoSuchFieldException
{
return klass.getDeclaredField(name);
}
private static Method getMethod (Class klass, String name, Class[] args)
throws java.lang.NoSuchMethodException
{
return klass.getDeclaredMethod(name, args);
}
// 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 static int defaultProtocolVersion = PROTOCOL_VERSION_2;
private DataOutputStream dataOutput;
private boolean writeDataAsBlocks;
@ -1382,4 +1416,12 @@ public class ObjectOutputStream extends OutputStream
private Hashtable OIDLookupTable;
private int protocolVersion;
private boolean useSubclassMethod;
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary ("javaio");
}
}
}