Commit 4480b3dc by Mark Wielaard Committed by Mark Wielaard

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
parent 28727f1f
2003-02-28 Mark Wielaard <mark@klomp.org>
* 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.
2003-02-27 Michael Koch <konqueror@gmx.de> 2003-02-27 Michael Koch <konqueror@gmx.de>
* java/beans/Beans.java, * java/beans/Beans.java,
......
...@@ -2496,7 +2496,6 @@ gnu/java/nio/natSocketChannelImpl.cc \ ...@@ -2496,7 +2496,6 @@ gnu/java/nio/natSocketChannelImpl.cc \
java/io/natFile.cc \ java/io/natFile.cc \
java/io/natFileDescriptor.cc \ java/io/natFileDescriptor.cc \
java/io/natObjectInputStream.cc \ java/io/natObjectInputStream.cc \
java/io/natObjectOutputStream.cc \
java/io/natVMObjectStreamClass.cc \ java/io/natVMObjectStreamClass.cc \
java/lang/natCharacter.cc \ java/lang/natCharacter.cc \
java/lang/natClass.cc \ java/lang/natClass.cc \
......
...@@ -2257,7 +2257,6 @@ gnu/java/nio/natSocketChannelImpl.cc \ ...@@ -2257,7 +2257,6 @@ gnu/java/nio/natSocketChannelImpl.cc \
java/io/natFile.cc \ java/io/natFile.cc \
java/io/natFileDescriptor.cc \ java/io/natFileDescriptor.cc \
java/io/natObjectInputStream.cc \ java/io/natObjectInputStream.cc \
java/io/natObjectOutputStream.cc \
java/io/natVMObjectStreamClass.cc \ java/io/natVMObjectStreamClass.cc \
java/lang/natCharacter.cc \ java/lang/natCharacter.cc \
java/lang/natClass.cc \ java/lang/natClass.cc \
...@@ -2432,11 +2431,11 @@ gnu/java/nio/natIntBufferImpl.lo gnu/java/nio/natLongBufferImpl.lo \ ...@@ -2432,11 +2431,11 @@ gnu/java/nio/natIntBufferImpl.lo gnu/java/nio/natLongBufferImpl.lo \
gnu/java/nio/natSelectorImpl.lo gnu/java/nio/natShortBufferImpl.lo \ gnu/java/nio/natSelectorImpl.lo gnu/java/nio/natShortBufferImpl.lo \
gnu/java/nio/natSocketChannelImpl.lo java/io/natFile.lo \ gnu/java/nio/natSocketChannelImpl.lo java/io/natFile.lo \
java/io/natFileDescriptor.lo java/io/natObjectInputStream.lo \ java/io/natFileDescriptor.lo java/io/natObjectInputStream.lo \
java/io/natObjectOutputStream.lo java/io/natVMObjectStreamClass.lo \ java/io/natVMObjectStreamClass.lo java/lang/natCharacter.lo \
java/lang/natCharacter.lo java/lang/natClass.lo \ java/lang/natClass.lo java/lang/natClassLoader.lo \
java/lang/natClassLoader.lo java/lang/natConcreteProcess.lo \ java/lang/natConcreteProcess.lo java/lang/natDouble.lo \
java/lang/natDouble.lo java/lang/natFloat.lo java/lang/natMath.lo \ java/lang/natFloat.lo java/lang/natMath.lo java/lang/natObject.lo \
java/lang/natObject.lo java/lang/natRuntime.lo java/lang/natString.lo \ java/lang/natRuntime.lo java/lang/natString.lo \
java/lang/natStringBuffer.lo java/lang/natSystem.lo \ java/lang/natStringBuffer.lo java/lang/natSystem.lo \
java/lang/natThread.lo java/lang/natVMSecurityManager.lo \ java/lang/natThread.lo java/lang/natVMSecurityManager.lo \
java/lang/ref/natReference.lo java/lang/reflect/natArray.lo \ java/lang/ref/natReference.lo java/lang/reflect/natArray.lo \
...@@ -2599,7 +2598,7 @@ libgcj-test.spec.in libgcj.spec.in ...@@ -2599,7 +2598,7 @@ libgcj-test.spec.in libgcj.spec.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar TAR = tar
GZIP_ENV = --best GZIP_ENV = --best
DIST_SUBDIRS = @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include DIST_SUBDIRS = @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include
DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
...@@ -3270,7 +3269,6 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ ...@@ -3270,7 +3269,6 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/java/io/WriteAbortedException.P .deps/java/io/Writer.P \ .deps/java/io/WriteAbortedException.P .deps/java/io/Writer.P \
.deps/java/io/natFile.P .deps/java/io/natFileDescriptor.P \ .deps/java/io/natFile.P .deps/java/io/natFileDescriptor.P \
.deps/java/io/natObjectInputStream.P \ .deps/java/io/natObjectInputStream.P \
.deps/java/io/natObjectOutputStream.P \
.deps/java/io/natVMObjectStreamClass.P \ .deps/java/io/natVMObjectStreamClass.P \
.deps/java/lang/AbstractMethodError.P \ .deps/java/lang/AbstractMethodError.P \
.deps/java/lang/ArithmeticException.P \ .deps/java/lang/ArithmeticException.P \
......
/* ObjectInputStream.java -- Class used to read serialized objects /* ObjectInputStream.java -- Class used to read serialized objects
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
...@@ -38,8 +38,6 @@ exception statement from your version. */ ...@@ -38,8 +38,6 @@ exception statement from your version. */
package java.io; package java.io;
import gnu.classpath.Configuration;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
...@@ -53,7 +51,7 @@ import java.lang.reflect.Field; ...@@ -53,7 +51,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import gnu.classpath.Configuration;
public class ObjectInputStream extends InputStream public class ObjectInputStream extends InputStream
implements ObjectInput, ObjectStreamConstants implements ObjectInput, ObjectStreamConstants
...@@ -130,286 +128,343 @@ public class ObjectInputStream extends InputStream ...@@ -130,286 +128,343 @@ public class ObjectInputStream extends InputStream
Object ret_val; Object ret_val;
was_deserializing = this.isDeserializing; was_deserializing = this.isDeserializing;
if (! was_deserializing) boolean is_consumed = false;
setBlockDataMode (false); boolean old_mode = setBlockDataMode (false);
this.isDeserializing = true; this.isDeserializing = true;
byte marker = this.realInputStream.readByte (); byte marker = this.realInputStream.readByte ();
dumpElement ("MARKER: 0x" + Integer.toHexString(marker) + " "); dumpElement ("MARKER: 0x" + Integer.toHexString(marker) + " ");
switch (marker) try
{
case TC_BLOCKDATA:
case TC_BLOCKDATALONG:
if (marker == TC_BLOCKDATALONG)
dumpElementln ("BLOCKDATALONG");
else
dumpElementln ("BLOCKDATA");
readNextBlock (marker);
throw new StreamCorruptedException ("Unexpected blockData");
case TC_NULL:
dumpElementln ("NULL");
ret_val = null;
break;
case TC_REFERENCE:
{
dumpElement ("REFERENCE ");
Integer oid = new Integer (this.realInputStream.readInt ());
dumpElementln (Integer.toHexString(oid.intValue()));
ret_val = ((ObjectIdentityWrapper)
this.objectLookupTable.get (oid)).object;
break;
}
case TC_CLASS:
{
dumpElementln ("CLASS");
ObjectStreamClass osc = (ObjectStreamClass)readObject ();
Class clazz = osc.forClass ();
assignNewHandle (clazz);
ret_val = clazz;
break;
}
case TC_CLASSDESC:
{
dumpElement ("CLASSDESC NAME=");
String name = this.realInputStream.readUTF ();
dumpElement (name + "; UID=");
long uid = this.realInputStream.readLong ();
dumpElement (Long.toHexString(uid) + "; FLAGS=");
byte flags = this.realInputStream.readByte ();
dumpElement (Integer.toHexString(flags) + "; FIELD COUNT=");
short field_count = this.realInputStream.readShort ();
dumpElementln (Short.toString(field_count));
ObjectStreamField[] fields = new ObjectStreamField[field_count];
ObjectStreamClass osc = new ObjectStreamClass (name, uid,
flags, fields);
assignNewHandle (osc);
for (int i=0; i < field_count; i++)
{
dumpElement (" TYPE CODE=");
char type_code = (char)this.realInputStream.readByte ();
dumpElement (type_code + "; FIELD NAME=");
String field_name = this.realInputStream.readUTF ();
dumpElementln (field_name);
String class_name;
if (type_code == 'L' || type_code == '[')
class_name = (String)readObject ();
else
class_name = String.valueOf (type_code);
fields[i] =
new ObjectStreamField (field_name,
TypeSignature.getClassForEncoding
(class_name));
}
Class cl = resolveClass (osc);
osc.setClass (cl);
setBlockDataMode (false);
if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
throw new IOException ("Data annotated to class was not consumed.");
dumpElementln ("ENDBLOCKDATA ");
osc.setSuperclass ((ObjectStreamClass)readObject ());
ret_val = osc;
break;
}
case TC_STRING:
{
dumpElement ("STRING=");
String s = this.realInputStream.readUTF ();
dumpElementln (s);
ret_val = processResolution (s, assignNewHandle (s));
break;
}
case TC_ARRAY:
{
dumpElementln ("ARRAY");
ObjectStreamClass osc = (ObjectStreamClass)readObject ();
Class componentType = osc.forClass ().getComponentType ();
dumpElement ("ARRAY LENGTH=");
int length = this.realInputStream.readInt ();
dumpElementln (length + "; COMPONENT TYPE=" + componentType);
Object array = Array.newInstance (componentType, length);
int handle = assignNewHandle (array);
readArrayElements (array, componentType);
for (int i=0, len=Array.getLength(array); i < len; i++)
dumpElementln (" ELEMENT[" + i + "]=" + Array.get(array, i));
ret_val = processResolution (array, handle);
break;
}
case TC_OBJECT:
{ {
dumpElementln ("OBJECT"); switch (marker)
ObjectStreamClass osc = (ObjectStreamClass)readObject ();
Class clazz = osc.forClass ();
if (!Serializable.class.isAssignableFrom (clazz))
throw new NotSerializableException (clazz + " is not Serializable, and thus cannot be deserialized.");
if (Externalizable.class.isAssignableFrom (clazz))
{
Externalizable obj = null;
try
{
obj = (Externalizable)clazz.newInstance ();
}
catch (InstantiationException e)
{
throw new ClassNotFoundException ("Instance of " + clazz
+ " could not be created");
}
catch (IllegalAccessException e)
{
throw new ClassNotFoundException ("Instance of " + clazz
+ " could not be created because class or zero-argument constructor is not accessible");
}
catch (NoSuchMethodError e)
{ {
throw new ClassNotFoundException ("Instance of " + clazz case TC_ENDBLOCKDATA:
+ " could not be created because zero-argument constructor is not defined"); {
} ret_val = null;
is_consumed = true;
int handle = assignNewHandle (obj); break;
}
boolean read_from_blocks = ((osc.getFlags () & SC_BLOCK_DATA) != 0);
case TC_BLOCKDATA:
if (read_from_blocks) case TC_BLOCKDATALONG:
setBlockDataMode (true); {
if (marker == TC_BLOCKDATALONG)
obj.readExternal (this); dumpElementln ("BLOCKDATALONG");
else
if (read_from_blocks) dumpElementln ("BLOCKDATA");
setBlockDataMode (false); readNextBlock (marker);
throw new StreamCorruptedException ("Unexpected blockData");
ret_val = processResolution (obj, handle); }
break;
} // end if (Externalizable.class.isAssignableFrom (clazz)) case TC_NULL:
{
dumpElementln ("NULL");
ret_val = null;
break;
}
case TC_REFERENCE:
{
dumpElement ("REFERENCE ");
Integer oid = new Integer (this.realInputStream.readInt ());
dumpElementln (Integer.toHexString(oid.intValue()));
ret_val = ((ObjectIdentityWrapper)
this.objectLookupTable.get (oid)).object;
break;
}
case TC_CLASS:
{
dumpElementln ("CLASS");
ObjectStreamClass osc = (ObjectStreamClass)readObject ();
Class clazz = osc.forClass ();
assignNewHandle (clazz);
ret_val = clazz;
break;
}
case TC_PROXYCLASSDESC:
{
dumpElementln ("PROXYCLASS");
int n_intf = this.realInputStream.readInt();
String[] intfs = new String[n_intf];
for (int i = 0; i < n_intf; i++)
{
intfs[i] = this.realInputStream.readUTF();
System.out.println(intfs[i]);
}
boolean oldmode = setBlockDataMode (true);
Class cl = resolveProxyClass(intfs);
setBlockDataMode(oldmode);
ObjectStreamClass osc = ObjectStreamClass.lookup(cl);
assignNewHandle (osc);
if (!is_consumed)
{
byte b = this.realInputStream.readByte ();
if (b != TC_ENDBLOCKDATA)
throw new IOException ("Data annotated to class was not consumed." + b);
}
else
is_consumed = false;
ObjectStreamClass superosc = (ObjectStreamClass)readObject ();
osc.setSuperclass (superosc);
ret_val = osc;
break;
}
case TC_CLASSDESC:
{
dumpElement ("CLASSDESC NAME=");
String name = this.realInputStream.readUTF ();
dumpElement (name + "; UID=");
long uid = this.realInputStream.readLong ();
dumpElement (Long.toHexString(uid) + "; FLAGS=");
byte flags = this.realInputStream.readByte ();
dumpElement (Integer.toHexString(flags) + "; FIELD COUNT=");
short field_count = this.realInputStream.readShort ();
dumpElementln (Short.toString(field_count));
ObjectStreamField[] fields = new ObjectStreamField[field_count];
ObjectStreamClass osc = new ObjectStreamClass (name, uid,
flags, fields);
assignNewHandle (osc);
for (int i=0; i < field_count; i++)
{
dumpElement (" TYPE CODE=");
char type_code = (char)this.realInputStream.readByte ();
dumpElement (type_code + "; FIELD NAME=");
String field_name = this.realInputStream.readUTF ();
dumpElementln (field_name);
String class_name;
if (type_code == 'L' || type_code == '[')
class_name = (String)readObject ();
else
class_name = String.valueOf (type_code);
// There're many cases you can't get java.lang.Class from
// typename if your context class loader can't load it,
// then use typename to construct the field
fields[i] =
new ObjectStreamField (field_name, class_name);
}
boolean oldmode = setBlockDataMode (true);
osc.setClass (resolveClass (osc));
setBlockDataMode (oldmode);
if (!is_consumed)
{
byte b = this.realInputStream.readByte ();
if (b != TC_ENDBLOCKDATA)
throw new IOException ("Data annotated to class was not consumed." + b);
}
else
is_consumed = false;
osc.setSuperclass ((ObjectStreamClass)readObject ());
ret_val = osc;
break;
}
case TC_STRING:
case TC_LONGSTRING:
{
dumpElement ("STRING=");
String s = this.realInputStream.readUTF ();
dumpElementln (s);
ret_val = processResolution (s, assignNewHandle (s));
break;
}
case TC_ARRAY:
{
dumpElementln ("ARRAY");
ObjectStreamClass osc = (ObjectStreamClass)readObject ();
Class componentType = osc.forClass ().getComponentType ();
dumpElement ("ARRAY LENGTH=");
int length = this.realInputStream.readInt ();
dumpElementln (length + "; COMPONENT TYPE=" + componentType);
Object array = Array.newInstance (componentType, length);
int handle = assignNewHandle (array);
readArrayElements (array, componentType);
for (int i=0, len=Array.getLength(array); i < len; i++)
dumpElementln (" ELEMENT[" + i + "]=" + Array.get(array, i));
ret_val = processResolution (array, handle);
break;
}
case TC_OBJECT:
{
dumpElementln ("OBJECT");
ObjectStreamClass osc = (ObjectStreamClass)readObject ();
Class clazz = osc.forClass ();
if (!Serializable.class.isAssignableFrom (clazz))
throw new NotSerializableException (clazz + " is not Serializable, and thus cannot be deserialized.");
if (Externalizable.class.isAssignableFrom (clazz))
{
Externalizable obj = null;
try
{
obj = (Externalizable)clazz.newInstance ();
}
catch (InstantiationException e)
{
throw new ClassNotFoundException ("Instance of " + clazz
+ " could not be created");
}
catch (IllegalAccessException e)
{
throw new ClassNotFoundException ("Instance of " + clazz
+ " could not be created because class or zero-argument constructor is not accessible");
}
catch (NoSuchMethodError e)
{
throw new ClassNotFoundException ("Instance of " + clazz
+ " could not be created because zero-argument constructor is not defined");
}
int handle = assignNewHandle (obj);
boolean read_from_blocks = ((osc.getFlags () & SC_BLOCK_DATA) != 0);
boolean oldmode = this.readDataFromBlock;
if (read_from_blocks)
setBlockDataMode (true);
obj.readExternal (this);
if (read_from_blocks)
setBlockDataMode (oldmode);
ret_val = processResolution (obj, handle);
break;
} // end if (Externalizable.class.isAssignableFrom (clazz))
// find the first non-serializable, non-abstract
// class in clazz's inheritance hierarchy
Class first_nonserial = clazz.getSuperclass ();
while (Serializable.class.isAssignableFrom (first_nonserial)
|| Modifier.isAbstract (first_nonserial.getModifiers ()))
first_nonserial = first_nonserial.getSuperclass ();
// DEBUGln ("Using " + first_nonserial
// + " as starting point for constructing " + clazz);
Object obj = null;
obj = newObject (clazz, first_nonserial);
if (obj == null)
throw new ClassNotFoundException ("Instance of " + clazz +
" could not be created");
int handle = assignNewHandle (obj);
this.currentObject = obj;
ObjectStreamClass[] hierarchy =
ObjectStreamClass.getObjectStreamClasses (clazz);
// DEBUGln ("Got class hierarchy of depth " + hierarchy.length);
boolean has_read;
for (int i=0; i < hierarchy.length; i++)
{
this.currentObjectStreamClass = hierarchy[i];
dumpElementln ("Reading fields of "
+ this.currentObjectStreamClass.getName ());
has_read = true;
try
{
this.currentObjectStreamClass.forClass ().
getDeclaredMethod ("readObject", readObjectParams);
}
catch (NoSuchMethodException e)
{
has_read = false;
}
// XXX: should initialize fields in classes in the hierarchy
// that aren't in the stream
// should skip over classes in the stream that aren't in the
// real classes hierarchy
readFields (obj, this.currentObjectStreamClass.fields,
has_read, this.currentObjectStreamClass);
if (has_read)
{
dumpElement ("ENDBLOCKDATA? ");
try
{
// FIXME: XXX: This try block is to catch EOF which is
// thrown for some objects. That indicates a bug in the logic.
if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
throw new IOException ("No end of block data seen for class with readObject (ObjectInputStream) method.");
dumpElementln ("yes");
}
catch (EOFException e)
{
dumpElementln ("no, got EOFException");
}
catch (IOException e)
{
dumpElementln ("no, got IOException");
}
}
}
this.currentObject = null;
this.currentObjectStreamClass = null;
ret_val = processResolution (obj, handle);
break;
}
case TC_RESET:
dumpElementln ("RESET");
clearHandles ();
ret_val = readObject ();
break;
case TC_EXCEPTION:
{
dumpElement ("EXCEPTION=");
Exception e = (Exception)readObject ();
dumpElementln (e.toString());
clearHandles ();
throw new WriteAbortedException ("Exception thrown during writing of stream", e);
}
default:
throw new IOException ("Unknown marker on stream: " + marker);
// find the first non-serializable, non-abstract
// class in clazz's inheritance hierarchy
Class first_nonserial = clazz.getSuperclass ();
while (Serializable.class.isAssignableFrom (first_nonserial)
|| Modifier.isAbstract (first_nonserial.getModifiers ()))
first_nonserial = first_nonserial.getSuperclass ();
// DEBUGln ("Using " + first_nonserial
// + " as starting point for constructing " + clazz);
Object obj = null;
obj = newObject (clazz, first_nonserial);
if (obj == null)
throw new ClassNotFoundException ("Instance of " + clazz +
" could not be created");
int handle = assignNewHandle (obj);
this.currentObject = obj;
ObjectStreamClass[] hierarchy =
ObjectStreamClass.getObjectStreamClasses (clazz);
// DEBUGln ("Got class hierarchy of depth " + hierarchy.length);
boolean has_read;
for (int i=0; i < hierarchy.length; i++)
{
this.currentObjectStreamClass = hierarchy[i];
dumpElementln ("Reading fields of "
+ this.currentObjectStreamClass.getName ());
has_read = true;
try
{
this.currentObjectStreamClass.forClass ().
getDeclaredMethod ("readObject", readObjectParams);
} }
catch (NoSuchMethodException e)
{
has_read = false;
}
// XXX: should initialize fields in classes in the hierarchy
// that aren't in the stream
// should skip over classes in the stream that aren't in the
// real classes hierarchy
readFields (obj, this.currentObjectStreamClass.fields,
has_read, this.currentObjectStreamClass);
if (has_read)
{
dumpElement ("ENDBLOCKDATA? ");
try
{
// FIXME: XXX: This try block is to catch EOF which is
// thrown for some objects. That indicates a bug in the logic.
if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
throw new IOException ("No end of block data seen for class with readObject (ObjectInputStream) method.");
dumpElementln ("yes");
}
catch (EOFException e)
{
dumpElementln ("no, got EOFException");
}
catch (IOException e)
{
dumpElementln ("no, got IOException");
}
}
}
this.currentObject = null;
this.currentObjectStreamClass = null;
ret_val = processResolution (obj, handle);
break;
} }
finally
case TC_RESET:
dumpElementln ("RESET");
clearHandles ();
ret_val = readObject ();
break;
case TC_EXCEPTION:
{ {
dumpElement ("EXCEPTION="); setBlockDataMode (old_mode);
Exception e = (Exception)readObject ();
dumpElementln (e.toString()); this.isDeserializing = was_deserializing;
clearHandles ();
throw new WriteAbortedException ("Exception thrown during writing of stream", e); if (! was_deserializing)
{
if (validators.size () > 0)
invokeValidators ();
}
} }
default:
throw new IOException ("Unknown marker on stream");
}
this.isDeserializing = was_deserializing;
if (! was_deserializing)
{
setBlockDataMode (true);
if (validators.size () > 0)
invokeValidators ();
}
return ret_val; return ret_val;
} }
/** /**
Reads the current objects non-transient, non-static fields from Reads the current objects non-transient, non-static fields from
...@@ -439,9 +494,11 @@ public class ObjectInputStream extends InputStream ...@@ -439,9 +494,11 @@ public class ObjectInputStream extends InputStream
if (fieldsAlreadyRead) if (fieldsAlreadyRead)
throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)"); throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");
boolean oldmode = setBlockDataMode(false);
readFields (this.currentObject, readFields (this.currentObject,
this.currentObjectStreamClass.fields, this.currentObjectStreamClass.fields,
false, this.currentObjectStreamClass); false, this.currentObjectStreamClass);
setBlockDataMode(oldmode);
fieldsAlreadyRead = true; fieldsAlreadyRead = true;
} }
...@@ -500,13 +557,18 @@ public class ObjectInputStream extends InputStream ...@@ -500,13 +557,18 @@ public class ObjectInputStream extends InputStream
throws ClassNotFoundException, IOException throws ClassNotFoundException, IOException
{ {
SecurityManager sm = System.getSecurityManager (); SecurityManager sm = System.getSecurityManager ();
if (sm == null)
sm = new SecurityManager () {};
// FIXME: currentClassLoader doesn't yet do anything useful. We need // FIXME: currentClassLoader doesn't yet do anything useful. We need
// to call forName() with the classloader of the class which called // to call forName() with the classloader of the class which called
// readObject(). See SecurityManager.getClassContext(). // readObject(). See SecurityManager.getClassContext().
ClassLoader cl = currentClassLoader (sm); ClassLoader cl = currentClassLoader (sm);
return Class.forName (osc.getName (), true, cl); if (cl == null)
return Class.forName (osc.getName ());
else
return cl.loadClass (osc.getName ());
} }
/** /**
...@@ -617,7 +679,17 @@ public class ObjectInputStream extends InputStream ...@@ -617,7 +679,17 @@ public class ObjectInputStream extends InputStream
if (this.readDataFromBlock) if (this.readDataFromBlock)
{ {
if (this.blockDataPosition + length > this.blockDataBytes) if (this.blockDataPosition + length > this.blockDataBytes)
readNextBlock (); {
int remain = this.blockDataBytes - this.blockDataPosition;
if (remain != 0)
{
System.arraycopy (this.blockData, this.blockDataPosition,
data, offset, remain);
offset += remain;
length -= remain;
}
readNextBlock ();
}
System.arraycopy (this.blockData, this.blockDataPosition, System.arraycopy (this.blockData, this.blockDataPosition,
data, offset, length); data, offset, length);
...@@ -785,11 +857,11 @@ public class ObjectInputStream extends InputStream ...@@ -785,11 +857,11 @@ public class ObjectInputStream extends InputStream
// Apparently Block data is not used with GetField as per // Apparently Block data is not used with GetField as per
// empirical evidence against JDK 1.2. Also see Mauve test // empirical evidence against JDK 1.2. Also see Mauve test
// java.io.ObjectInputOutput.Test.GetPutField. // java.io.ObjectInputOutput.Test.GetPutField.
setBlockDataMode (false); boolean oldmode = setBlockDataMode (false);
readFully (prim_field_data); readFully (prim_field_data);
for (int i = 0; i < objs.length; ++ i) for (int i = 0; i < objs.length; ++ i)
objs[i] = readObject (); objs[i] = readObject ();
setBlockDataMode (true); setBlockDataMode (oldmode);
return new GetField () return new GetField ()
{ {
...@@ -990,7 +1062,7 @@ public class ObjectInputStream extends InputStream ...@@ -990,7 +1062,7 @@ public class ObjectInputStream extends InputStream
de serialization mechanism provided by de serialization mechanism provided by
<code>ObjectInputStream</code>. To make this method be used for <code>ObjectInputStream</code>. To make this method be used for
writing objects, subclasses must invoke the 0-argument writing objects, subclasses must invoke the 0-argument
constructor on this class from there constructor. constructor on this class from their constructor.
@see ObjectInputStream () @see ObjectInputStream ()
*/ */
...@@ -1175,9 +1247,9 @@ public class ObjectInputStream extends InputStream ...@@ -1175,9 +1247,9 @@ public class ObjectInputStream extends InputStream
{ {
// DEBUGln (" call_read_method is true"); // DEBUGln (" call_read_method is true");
fieldsAlreadyRead = false; fieldsAlreadyRead = false;
setBlockDataMode (true); boolean oldmode = setBlockDataMode (true);
callReadMethod (obj, stream_osc.forClass ()); callReadMethod (obj, stream_osc.forClass ());
setBlockDataMode (false); setBlockDataMode (oldmode);
return; return;
} }
...@@ -1237,101 +1309,109 @@ public class ObjectInputStream extends InputStream ...@@ -1237,101 +1309,109 @@ public class ObjectInputStream extends InputStream
} }
} }
if (type == Boolean.TYPE) try
{ {
boolean value = if (type == Boolean.TYPE)
default_initialize ? false : this.realInputStream.readBoolean (); {
if (!default_initialize && set_value) boolean value =
dumpElementln (" " + field_name + ": " + value); default_initialize ? false : this.realInputStream.readBoolean ();
if (set_value) if (!default_initialize && set_value)
setBooleanField (obj, field_name, value); dumpElementln (" " + field_name + ": " + value);
} if (set_value)
else if (type == Byte.TYPE) setBooleanField (obj, field_name, value);
{ }
byte value = else if (type == Byte.TYPE)
default_initialize ? 0 : this.realInputStream.readByte (); {
if (!default_initialize && set_value) byte value =
dumpElementln (" " + field_name + ": " + value); default_initialize ? 0 : this.realInputStream.readByte ();
if (set_value) if (!default_initialize && set_value)
setByteField (obj, field_name, value); dumpElementln (" " + field_name + ": " + value);
} if (set_value)
else if (type == Character.TYPE) setByteField (obj, field_name, value);
{ }
char value = else if (type == Character.TYPE)
default_initialize ? (char)0 : this.realInputStream.readChar (); {
if (!default_initialize && set_value) char value =
dumpElementln (" " + field_name + ": " + value); default_initialize ? (char)0 : this.realInputStream.readChar ();
if (set_value) if (!default_initialize && set_value)
setCharField (obj, field_name, value); dumpElementln (" " + field_name + ": " + value);
} if (set_value)
else if (type == Double.TYPE) setCharField (obj, field_name, value);
{ }
double value = else if (type == Double.TYPE)
default_initialize ? 0 : this.realInputStream.readDouble (); {
if (!default_initialize && set_value) double value =
dumpElementln (" " + field_name + ": " + value); default_initialize ? 0 : this.realInputStream.readDouble ();
if (set_value) if (!default_initialize && set_value)
setDoubleField (obj, field_name, value); dumpElementln (" " + field_name + ": " + value);
} if (set_value)
else if (type == Float.TYPE) setDoubleField (obj, field_name, value);
{ }
float value = else if (type == Float.TYPE)
default_initialize ? 0 : this.realInputStream.readFloat (); {
if (!default_initialize && set_value) float value =
dumpElementln (" " + field_name + ": " + value); default_initialize ? 0 : this.realInputStream.readFloat ();
if (set_value) if (!default_initialize && set_value)
setFloatField (obj, field_name, value); dumpElementln (" " + field_name + ": " + value);
} if (set_value)
else if (type == Integer.TYPE) setFloatField (obj, field_name, value);
{ }
int value = else if (type == Integer.TYPE)
default_initialize ? 0 : this.realInputStream.readInt (); {
if (!default_initialize && set_value) int value =
dumpElementln (" " + field_name + ": " + value); default_initialize ? 0 : this.realInputStream.readInt ();
if (set_value) if (!default_initialize && set_value)
setIntField (obj, field_name, value); dumpElementln (" " + field_name + ": " + value);
} if (set_value)
else if (type == Long.TYPE) setIntField (obj, field_name, value);
{ }
long value = else if (type == Long.TYPE)
default_initialize ? 0 : this.realInputStream.readLong (); {
if (!default_initialize && set_value) long value =
dumpElementln (" " + field_name + ": " + value); default_initialize ? 0 : this.realInputStream.readLong ();
if (set_value) if (!default_initialize && set_value)
setLongField (obj, field_name, value); dumpElementln (" " + field_name + ": " + value);
} if (set_value)
else if (type == Short.TYPE) setLongField (obj, field_name, value);
{ }
short value = else if (type == Short.TYPE)
default_initialize ? (short)0 : this.realInputStream.readShort (); {
if (!default_initialize && set_value) short value =
dumpElementln (" " + field_name + ": " + value); default_initialize ? (short)0 : this.realInputStream.readShort ();
if (set_value) if (!default_initialize && set_value)
setShortField (obj, field_name, value); dumpElementln (" " + field_name + ": " + value);
} if (set_value)
else setShortField (obj, field_name, value);
{ }
Object value = else
default_initialize ? null : readObject (); {
if (set_value) Object value =
setObjectField (obj, field_name, default_initialize ? null : readObject ();
real_field.getTypeString (), value); if (set_value)
} setObjectField (obj, field_name,
real_field.getTypeString (), value);
}
}
catch (NoSuchFieldError e)
{
dumpElementln("XXXX " + field_name + " does not exist.");
}
} }
} }
// Toggles writing primitive data to block-data buffer. // Toggles writing primitive data to block-data buffer.
private void setBlockDataMode (boolean on) private boolean setBlockDataMode (boolean on)
{ {
// DEBUGln ("Setting block data mode to " + on); // DEBUGln ("Setting block data mode to " + on);
boolean oldmode = this.readDataFromBlock;
this.readDataFromBlock = on; this.readDataFromBlock = on;
if (on) if (on)
this.dataInputStream = this.blockDataInput; this.dataInputStream = this.blockDataInput;
else else
this.dataInputStream = this.realInputStream; this.dataInputStream = this.realInputStream;
return oldmode;
} }
...@@ -1380,12 +1460,18 @@ public class ObjectInputStream extends InputStream ...@@ -1380,12 +1460,18 @@ public class ObjectInputStream extends InputStream
return ClassLoader.getSystemClassLoader (); return ClassLoader.getSystemClassLoader ();
} }
private static native Field getField (Class klass, String name) private static Field getField (Class klass, String name)
throws java.lang.NoSuchFieldException; throws java.lang.NoSuchFieldException
{
private static native Method getMethod (Class klass, String name, Class args[]) return klass.getDeclaredField(name);
throws java.lang.NoSuchMethodException; }
private static Method getMethod (Class klass, String name, Class args[])
throws java.lang.NoSuchMethodException
{
return klass.getDeclaredMethod(name, args);
}
private void callReadMethod (Object obj, Class klass) throws IOException private void callReadMethod (Object obj, Class klass) throws IOException
{ {
try try
...@@ -1593,6 +1679,14 @@ public class ObjectInputStream extends InputStream ...@@ -1593,6 +1679,14 @@ public class ObjectInputStream extends InputStream
if (Configuration.DEBUG && dump) if (Configuration.DEBUG && dump)
System.out.println(msg); System.out.println(msg);
} }
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary ("javaio");
}
}
} }
......
/* ObjectOutputStream.java -- Class used to write serialized objects /* 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. This file is part of GNU Classpath.
...@@ -46,6 +46,7 @@ import java.util.Hashtable; ...@@ -46,6 +46,7 @@ import java.util.Hashtable;
import gnu.java.io.ObjectIdentityWrapper; import gnu.java.io.ObjectIdentityWrapper;
import gnu.java.lang.reflect.TypeSignature; import gnu.java.lang.reflect.TypeSignature;
import gnu.classpath.Configuration;
/** /**
An <code>ObjectOutputStream</code> can be used to write objects An <code>ObjectOutputStream</code> can be used to write objects
...@@ -167,229 +168,242 @@ public class ObjectOutputStream extends OutputStream ...@@ -167,229 +168,242 @@ public class ObjectOutputStream extends OutputStream
public final void writeObject (Object obj) throws IOException public final void writeObject (Object obj) throws IOException
{ {
if (useSubclassMethod) if (useSubclassMethod)
{ {
writeObjectOverride (obj); writeObjectOverride (obj);
return; return;
} }
boolean was_serializing = isSerializing; boolean was_serializing = isSerializing;
boolean old_mode = setBlockDataMode (false);
if (! was_serializing)
setBlockDataMode (false);
try try
{
isSerializing = true;
boolean replaceDone = false;
drain ();
while (true)
{ {
if (obj == null) isSerializing = true;
{ boolean replaceDone = false;
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; Object replacedObject = null;
if ((replacementEnabled || obj instanceof Serializable) while (true)
&& ! replaceDone) {
{ if (obj == null)
replacedObject = obj; {
realOutput.writeByte (TC_NULL);
if (obj instanceof Serializable) break;
{ }
Method m = null;
try 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)
{ {
Class classArgs[] = {}; replacedObject = obj;
m = obj.getClass ().getDeclaredMethod ("writeReplace",
classArgs); if (obj instanceof Serializable)
// m can't be null by definition since an exception would {
// have been thrown so a check for null is not needed. Method m = null;
obj = m.invoke (obj, new Object[] {}); 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;
} }
catch (NoSuchMethodException ignore)
if (obj instanceof String)
{ {
realOutput.writeByte (TC_STRING);
assignNewHandle (obj);
realOutput.writeUTF ((String)obj);
break;
} }
catch (IllegalAccessException ignore)
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;
} }
catch (InvocationTargetException ignore)
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)
if (replacementEnabled) {
obj = replaceObject (obj); currentObject = obj;
ObjectStreamClass[] hierarchy =
replaceDone = true; ObjectStreamClass.getObjectStreamClasses (clazz);
continue;
} boolean has_write;
for (int i=0; i < hierarchy.length; i++)
if (obj instanceof String) {
{ currentObjectStreamClass = hierarchy[i];
realOutput.writeByte (TC_STRING);
assignNewHandle (obj); fieldsAlreadyWritten = false;
realOutput.writeUTF ((String)obj); has_write = currentObjectStreamClass.hasWriteMethod ();
break;
} writeFields (obj, currentObjectStreamClass.fields,
has_write);
Class clazz = obj.getClass ();
ObjectStreamClass osc = ObjectStreamClass.lookup (clazz); }
if (osc == null)
throw new NotSerializableException (clazz.getName ()); currentObject = null;
currentObjectStreamClass = null;
if (clazz.isArray ()) currentPutField = null;
{ break;
realOutput.writeByte (TC_ARRAY); }
writeObject (osc);
assignNewHandle (obj); throw new NotSerializableException (clazz.getName ());
writeArraySizeAndElements (obj, clazz.getComponentType ()); } // end pseudo-loop
break; }
} catch (ObjectStreamException ose)
{
realOutput.writeByte (TC_OBJECT); // Rethrow these are fatal.
writeObject (osc); throw ose;
}
if (replaceDone) catch (IOException e)
assignNewHandle (replacedObject); {
else realOutput.writeByte (TC_EXCEPTION);
assignNewHandle (obj); reset (true);
if (obj instanceof Externalizable) setBlockDataMode (false);
{ try
if (protocolVersion == PROTOCOL_VERSION_2)
setBlockDataMode (true);
((Externalizable)obj).writeExternal (this);
if (protocolVersion == PROTOCOL_VERSION_2)
{ {
setBlockDataMode (false); writeObject (e);
drain ();
} }
catch (IOException ioe)
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]; throw new StreamCorruptedException ("Exception " + ioe + " thrown while exception was being written to stream.");
fieldsAlreadyWritten = false;
has_write = currentObjectStreamClass.hasWriteMethod ();
writeFields (obj, currentObjectStreamClass.fields,
has_write);
if (has_write)
{
drain ();
realOutput.writeByte (TC_ENDBLOCKDATA);
}
} }
currentObject = null; reset (true);
currentObjectStreamClass = null;
currentPutField = null;
break;
}
throw new NotSerializableException (clazz.getName ());
} // 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 finally
{ {
isSerializing = was_serializing; isSerializing = was_serializing;
if (! was_serializing) setBlockDataMode (old_mode);
setBlockDataMode (true); }
}
} }
...@@ -466,8 +480,8 @@ public class ObjectOutputStream extends OutputStream ...@@ -466,8 +480,8 @@ public class ObjectOutputStream extends OutputStream
according to the specified protocol. There are currently two according to the specified protocol. There are currently two
different protocols, specified by <code>PROTOCOL_VERSION_1</code> different protocols, specified by <code>PROTOCOL_VERSION_1</code>
and <code>PROTOCOL_VERSION_2</code>. This implementation writes and <code>PROTOCOL_VERSION_2</code>. This implementation writes
data using <code>PROTOCOL_VERSION_1</code> by default, as is done data using <code>PROTOCOL_VERSION_2</code> by default, as is done
by the JDK 1.1. by the JDK 1.2.
A non-portable method, <code>setDefaultProtocolVersion (int A non-portable method, <code>setDefaultProtocolVersion (int
version)</code> is provided to change the default protocol version)</code> is provided to change the default protocol
...@@ -528,6 +542,8 @@ public class ObjectOutputStream extends OutputStream ...@@ -528,6 +542,8 @@ public class ObjectOutputStream extends OutputStream
protected void annotateClass (Class cl) throws IOException protected void annotateClass (Class cl) throws IOException
{} {}
protected void annotateProxyClass(Class cl) throws IOException
{}
/** /**
Allows subclasses to replace objects that are written to the Allows subclasses to replace objects that are written to the
...@@ -702,7 +718,8 @@ public class ObjectOutputStream extends OutputStream ...@@ -702,7 +718,8 @@ public class ObjectOutputStream extends OutputStream
if (blockDataCount == 0) if (blockDataCount == 0)
return; return;
writeBlockDataHeader (blockDataCount); if (writeDataAsBlocks)
writeBlockDataHeader (blockDataCount);
realOutput.write (blockData, 0, blockDataCount); realOutput.write (blockData, 0, blockDataCount);
blockDataCount = 0; blockDataCount = 0;
} }
...@@ -713,7 +730,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -713,7 +730,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void close () throws IOException public void close () throws IOException
{ {
drain (); flush ();
realOutput.close (); realOutput.close ();
} }
...@@ -723,7 +740,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -723,7 +740,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeBoolean (boolean data) throws IOException public void writeBoolean (boolean data) throws IOException
{ {
dataOutput.writeBoolean (data); blockDataOutput.writeBoolean (data);
} }
...@@ -732,7 +749,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -732,7 +749,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeByte (int data) throws IOException public void writeByte (int data) throws IOException
{ {
dataOutput.writeByte (data); blockDataOutput.writeByte (data);
} }
...@@ -741,7 +758,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -741,7 +758,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeShort (int data) throws IOException public void writeShort (int data) throws IOException
{ {
dataOutput.writeShort (data); blockDataOutput.writeShort (data);
} }
...@@ -750,7 +767,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -750,7 +767,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeChar (int data) throws IOException public void writeChar (int data) throws IOException
{ {
dataOutput.writeChar (data); blockDataOutput.writeChar (data);
} }
...@@ -759,7 +776,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -759,7 +776,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeInt (int data) throws IOException public void writeInt (int data) throws IOException
{ {
dataOutput.writeInt (data); blockDataOutput.writeInt (data);
} }
...@@ -768,7 +785,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -768,7 +785,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeLong (long data) throws IOException public void writeLong (long data) throws IOException
{ {
dataOutput.writeLong (data); blockDataOutput.writeLong (data);
} }
...@@ -777,7 +794,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -777,7 +794,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeFloat (float data) throws IOException public void writeFloat (float data) throws IOException
{ {
dataOutput.writeFloat (data); blockDataOutput.writeFloat (data);
} }
...@@ -786,7 +803,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -786,7 +803,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeDouble (double data) throws IOException public void writeDouble (double data) throws IOException
{ {
dataOutput.writeDouble (data); blockDataOutput.writeDouble (data);
} }
...@@ -795,7 +812,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -795,7 +812,7 @@ public class ObjectOutputStream extends OutputStream
*/ */
public void writeBytes (String data) throws IOException public void writeBytes (String data) throws IOException
{ {
dataOutput.writeBytes (data); blockDataOutput.writeBytes (data);
} }
...@@ -965,6 +982,8 @@ public class ObjectOutputStream extends OutputStream ...@@ -965,6 +982,8 @@ public class ObjectOutputStream extends OutputStream
{ {
ObjectStreamField field ObjectStreamField field
= currentObjectStreamClass.getField (name); = currentObjectStreamClass.getField (name);
if (field == null)
throw new IllegalArgumentException ();
if (value != null && if (value != null &&
! field.getType ().isAssignableFrom (value.getClass ())) ! field.getType ().isAssignableFrom (value.getClass ()))
throw new IllegalArgumentException (); throw new IllegalArgumentException ();
...@@ -976,11 +995,11 @@ public class ObjectOutputStream extends OutputStream ...@@ -976,11 +995,11 @@ public class ObjectOutputStream extends OutputStream
// Apparently Block data is not used with PutField as per // Apparently Block data is not used with PutField as per
// empirical evidence against JDK 1.2. Also see Mauve test // empirical evidence against JDK 1.2. Also see Mauve test
// java.io.ObjectInputOutput.Test.GetPutField. // java.io.ObjectInputOutput.Test.GetPutField.
setBlockDataMode (false); boolean oldmode = setBlockDataMode (false);
out.write (prim_field_data); out.write (prim_field_data);
for (int i = 0; i < objs.length; ++ i) for (int i = 0; i < objs.length; ++ i)
out.writeObject (objs[i]); out.writeObject (objs[i]);
setBlockDataMode (true); setBlockDataMode (oldmode);
} }
private void checkType (ObjectStreamField field, char type) private void checkType (ObjectStreamField field, char type)
...@@ -1067,8 +1086,7 @@ public class ObjectOutputStream extends OutputStream ...@@ -1067,8 +1086,7 @@ public class ObjectOutputStream extends OutputStream
{ {
byte[] cast_array = (byte[])array; byte[] cast_array = (byte[])array;
realOutput.writeInt (length); realOutput.writeInt (length);
for (int i=0; i < length; i++) realOutput.write(cast_array, 0, length);
realOutput.writeByte (cast_array[i]);
return; return;
} }
if (clazz == Character.TYPE) if (clazz == Character.TYPE)
...@@ -1142,9 +1160,11 @@ public class ObjectOutputStream extends OutputStream ...@@ -1142,9 +1160,11 @@ public class ObjectOutputStream extends OutputStream
setBlockDataMode (true); setBlockDataMode (true);
callWriteMethod (obj); callWriteMethod (obj);
setBlockDataMode (false); setBlockDataMode (false);
realOutput.writeByte (TC_ENDBLOCKDATA);
return; return;
} }
boolean oldmode = setBlockDataMode (false);
String field_name; String field_name;
Class type; Class type;
for (int i=0; i < fields.length; i++) for (int i=0; i < fields.length; i++)
...@@ -1170,20 +1190,28 @@ public class ObjectOutputStream extends OutputStream ...@@ -1170,20 +1190,28 @@ public class ObjectOutputStream extends OutputStream
realOutput.writeShort (getShortField (obj, field_name)); realOutput.writeShort (getShortField (obj, field_name));
else else
writeObject (getObjectField (obj, field_name, writeObject (getObjectField (obj, field_name,
TypeSignature.getEncodingOfClass (type))); fields[i].getTypeString ()));
} }
setBlockDataMode(oldmode);
} }
// Toggles writing primitive data to block-data buffer. // 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; writeDataAsBlocks = on;
if (on) if (on)
dataOutput = blockDataOutput; dataOutput = blockDataOutput;
else else
dataOutput = realOutput; dataOutput = realOutput;
return oldmode;
} }
...@@ -1355,16 +1383,22 @@ public class ObjectOutputStream extends OutputStream ...@@ -1355,16 +1383,22 @@ public class ObjectOutputStream extends OutputStream
} }
} }
private static native Field getField (Class klass, String name) private static Field getField (Class klass, String name)
throws java.lang.NoSuchFieldException; throws java.lang.NoSuchFieldException
{
private static native Method getMethod (Class klass, String name, Class[] args) return klass.getDeclaredField(name);
throws java.lang.NoSuchMethodException; }
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 // this value comes from 1.2 spec, but is used in 1.1 as well
private final static int BUFFER_SIZE = 1024; 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 DataOutputStream dataOutput;
private boolean writeDataAsBlocks; private boolean writeDataAsBlocks;
...@@ -1382,4 +1416,12 @@ public class ObjectOutputStream extends OutputStream ...@@ -1382,4 +1416,12 @@ public class ObjectOutputStream extends OutputStream
private Hashtable OIDLookupTable; private Hashtable OIDLookupTable;
private int protocolVersion; private int protocolVersion;
private boolean useSubclassMethod; private boolean useSubclassMethod;
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary ("javaio");
}
}
} }
...@@ -47,8 +47,23 @@ public class ObjectStreamField implements java.lang.Comparable ...@@ -47,8 +47,23 @@ public class ObjectStreamField implements java.lang.Comparable
{ {
this.name = name; this.name = name;
this.type = type; this.type = type;
this.typename = TypeSignature.getEncodingOfClass(type);
} }
/**
* There're many cases you can't get java.lang.Class from typename if your context
* class loader can't load it, then use typename to construct the field
*/
ObjectStreamField (String name, String typename){
this.name = name;
this.typename = typename;
try{
type = TypeSignature.getClassForEncoding(typename);
}catch(ClassNotFoundException e){
type = Object.class; //??
}
}
public String getName () public String getName ()
{ {
return name; return name;
...@@ -61,12 +76,13 @@ public class ObjectStreamField implements java.lang.Comparable ...@@ -61,12 +76,13 @@ public class ObjectStreamField implements java.lang.Comparable
public char getTypeCode () public char getTypeCode ()
{ {
return TypeSignature.getEncodingOfClass (type).charAt (0); return typename.charAt (0);
} }
public String getTypeString () public String getTypeString ()
{ {
return TypeSignature.getEncodingOfClass (type); // use intern()
return typename.intern();
} }
public int getOffset () public int getOffset ()
...@@ -106,5 +122,6 @@ public class ObjectStreamField implements java.lang.Comparable ...@@ -106,5 +122,6 @@ public class ObjectStreamField implements java.lang.Comparable
private String name; private String name;
private Class type; private Class type;
private String typename;
private int offset = -1; // XXX make sure this is correct private int offset = -1; // XXX make sure this is correct
} }
...@@ -69,16 +69,3 @@ java::io::ObjectInputStream::callConstructor (jclass klass, jobject obj) ...@@ -69,16 +69,3 @@ java::io::ObjectInputStream::callConstructor (jclass klass, jobject obj)
+ m->offset); + m->offset);
_Jv_CallAnyMethodA (obj, JvPrimClass (void), meth, false, arg_types, NULL); _Jv_CallAnyMethodA (obj, JvPrimClass (void), meth, false, arg_types, NULL);
} }
java::lang::reflect::Field *
java::io::ObjectInputStream::getField (jclass klass, jstring name)
{
return klass->getPrivateField (name);
}
java::lang::reflect::Method *
java::io::ObjectInputStream::getMethod (jclass klass, jstring name,
JArray<jclass> *arg_types)
{
return klass->getPrivateMethod (name, arg_types);
}
// natObjectOutputStream.cc - Native part of ObjectOutputStream class.
/* Copyright (C) 1998, 1999 Free Software Foundation
This ObjectOutputStream is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the ObjectOutputStream "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <java/io/ObjectOutputStream$PutField.h>
#include <java/io/ObjectOutputStream.h>
#include <java/io/IOException.h>
#include <java/lang/Class.h>
java::lang::reflect::Field *
java::io::ObjectOutputStream::getField (jclass klass, jstring name)
{
return klass->getPrivateField (name);
}
java::lang::reflect::Method *
java::io::ObjectOutputStream::getMethod (jclass klass, jstring name,
JArray<jclass> *arg_types)
{
return klass->getPrivateMethod (name, arg_types);
}
...@@ -15,7 +15,6 @@ JDBC2.0 ...@@ -15,7 +15,6 @@ JDBC2.0
# The following tests seem to hang or crash the testsuite. # The following tests seem to hang or crash the testsuite.
# This a problem when running Mauve "standalone". # This a problem when running Mauve "standalone".
!java.io.ObjectInputOutput
!java.lang.reflect.Array.newInstance !java.lang.reflect.Array.newInstance
# Character.unicode seems to be very broken (the test) # Character.unicode seems to be very broken (the test)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment