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,3 +1,59 @@
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>
* java/beans/Beans.java,

View File

@ -2496,7 +2496,6 @@ gnu/java/nio/natSocketChannelImpl.cc \
java/io/natFile.cc \
java/io/natFileDescriptor.cc \
java/io/natObjectInputStream.cc \
java/io/natObjectOutputStream.cc \
java/io/natVMObjectStreamClass.cc \
java/lang/natCharacter.cc \
java/lang/natClass.cc \

View File

@ -2257,7 +2257,6 @@ gnu/java/nio/natSocketChannelImpl.cc \
java/io/natFile.cc \
java/io/natFileDescriptor.cc \
java/io/natObjectInputStream.cc \
java/io/natObjectOutputStream.cc \
java/io/natVMObjectStreamClass.cc \
java/lang/natCharacter.cc \
java/lang/natClass.cc \
@ -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/natSocketChannelImpl.lo java/io/natFile.lo \
java/io/natFileDescriptor.lo java/io/natObjectInputStream.lo \
java/io/natObjectOutputStream.lo java/io/natVMObjectStreamClass.lo \
java/lang/natCharacter.lo java/lang/natClass.lo \
java/lang/natClassLoader.lo java/lang/natConcreteProcess.lo \
java/lang/natDouble.lo java/lang/natFloat.lo java/lang/natMath.lo \
java/lang/natObject.lo java/lang/natRuntime.lo java/lang/natString.lo \
java/io/natVMObjectStreamClass.lo java/lang/natCharacter.lo \
java/lang/natClass.lo java/lang/natClassLoader.lo \
java/lang/natConcreteProcess.lo java/lang/natDouble.lo \
java/lang/natFloat.lo java/lang/natMath.lo java/lang/natObject.lo \
java/lang/natRuntime.lo java/lang/natString.lo \
java/lang/natStringBuffer.lo java/lang/natSystem.lo \
java/lang/natThread.lo java/lang/natVMSecurityManager.lo \
java/lang/ref/natReference.lo java/lang/reflect/natArray.lo \
@ -2599,7 +2598,7 @@ libgcj-test.spec.in libgcj.spec.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
TAR = tar
GZIP_ENV = --best
DIST_SUBDIRS = @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include
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/natFile.P .deps/java/io/natFileDescriptor.P \
.deps/java/io/natObjectInputStream.P \
.deps/java/io/natObjectOutputStream.P \
.deps/java/io/natVMObjectStreamClass.P \
.deps/java/lang/AbstractMethodError.P \
.deps/java/lang/ArithmeticException.P \

View File

@ -1,5 +1,5 @@
/* 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.
@ -38,8 +38,6 @@ exception statement from your version. */
package java.io;
import gnu.classpath.Configuration;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
@ -53,7 +51,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import gnu.classpath.Configuration;
public class ObjectInputStream extends InputStream
implements ObjectInput, ObjectStreamConstants
@ -130,286 +128,343 @@ public class ObjectInputStream extends InputStream
Object ret_val;
was_deserializing = this.isDeserializing;
if (! was_deserializing)
setBlockDataMode (false);
boolean is_consumed = false;
boolean old_mode = setBlockDataMode (false);
this.isDeserializing = true;
byte marker = this.realInputStream.readByte ();
dumpElement ("MARKER: 0x" + Integer.toHexString(marker) + " ");
switch (marker)
{
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:
try
{
dumpElement ("REFERENCE ");
Integer oid = new Integer (this.realInputStream.readInt ());
dumpElementln (Integer.toHexString(oid.intValue()));
ret_val = ((ObjectIdentityWrapper)
this.objectLookupTable.get (oid)).object;
break;
}
switch (marker)
{
case TC_ENDBLOCKDATA:
{
ret_val = null;
is_consumed = true;
break;
}
case TC_BLOCKDATA:
case TC_BLOCKDATALONG:
{
if (marker == TC_BLOCKDATALONG)
dumpElementln ("BLOCKDATALONG");
else
dumpElementln ("BLOCKDATA");
readNextBlock (marker);
throw new StreamCorruptedException ("Unexpected blockData");
}
case TC_CLASS:
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);
}
}
finally
{
dumpElementln ("CLASS");
ObjectStreamClass osc = (ObjectStreamClass)readObject ();
Class clazz = osc.forClass ();
assignNewHandle (clazz);
ret_val = clazz;
break;
setBlockDataMode (old_mode);
this.isDeserializing = was_deserializing;
if (! was_deserializing)
{
if (validators.size () > 0)
invokeValidators ();
}
}
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");
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);
if (read_from_blocks)
setBlockDataMode (true);
obj.readExternal (this);
if (read_from_blocks)
setBlockDataMode (false);
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");
}
this.isDeserializing = was_deserializing;
if (! was_deserializing)
{
setBlockDataMode (true);
if (validators.size () > 0)
invokeValidators ();
}
return ret_val;
}
/**
Reads the current objects non-transient, non-static fields from
@ -439,9 +494,11 @@ public class ObjectInputStream extends InputStream
if (fieldsAlreadyRead)
throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");
boolean oldmode = setBlockDataMode(false);
readFields (this.currentObject,
this.currentObjectStreamClass.fields,
false, this.currentObjectStreamClass);
setBlockDataMode(oldmode);
fieldsAlreadyRead = true;
}
@ -500,13 +557,18 @@ public class ObjectInputStream extends InputStream
throws ClassNotFoundException, IOException
{
SecurityManager sm = System.getSecurityManager ();
if (sm == null)
sm = new SecurityManager () {};
// FIXME: currentClassLoader doesn't yet do anything useful. We need
// to call forName() with the classloader of the class which called
// readObject(). See SecurityManager.getClassContext().
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
if (this.readDataFromBlock)
{
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,
data, offset, length);
@ -785,11 +857,11 @@ public class ObjectInputStream extends InputStream
// Apparently Block data is not used with GetField as per
// empirical evidence against JDK 1.2. Also see Mauve test
// java.io.ObjectInputOutput.Test.GetPutField.
setBlockDataMode (false);
boolean oldmode = setBlockDataMode (false);
readFully (prim_field_data);
for (int i = 0; i < objs.length; ++ i)
objs[i] = readObject ();
setBlockDataMode (true);
setBlockDataMode (oldmode);
return new GetField ()
{
@ -990,7 +1062,7 @@ public class ObjectInputStream extends InputStream
de serialization mechanism provided by
<code>ObjectInputStream</code>. To make this method be used for
writing objects, subclasses must invoke the 0-argument
constructor on this class from there constructor.
constructor on this class from their constructor.
@see ObjectInputStream ()
*/
@ -1175,9 +1247,9 @@ public class ObjectInputStream extends InputStream
{
// DEBUGln (" call_read_method is true");
fieldsAlreadyRead = false;
setBlockDataMode (true);
boolean oldmode = setBlockDataMode (true);
callReadMethod (obj, stream_osc.forClass ());
setBlockDataMode (false);
setBlockDataMode (oldmode);
return;
}
@ -1237,101 +1309,109 @@ public class ObjectInputStream extends InputStream
}
}
if (type == Boolean.TYPE)
{
boolean value =
default_initialize ? false : this.realInputStream.readBoolean ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setBooleanField (obj, field_name, value);
}
else if (type == Byte.TYPE)
{
byte value =
default_initialize ? 0 : this.realInputStream.readByte ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setByteField (obj, field_name, value);
}
else if (type == Character.TYPE)
{
char value =
default_initialize ? (char)0 : this.realInputStream.readChar ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setCharField (obj, field_name, value);
}
else if (type == Double.TYPE)
{
double value =
default_initialize ? 0 : this.realInputStream.readDouble ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setDoubleField (obj, field_name, value);
}
else if (type == Float.TYPE)
{
float value =
default_initialize ? 0 : this.realInputStream.readFloat ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setFloatField (obj, field_name, value);
}
else if (type == Integer.TYPE)
{
int value =
default_initialize ? 0 : this.realInputStream.readInt ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setIntField (obj, field_name, value);
}
else if (type == Long.TYPE)
{
long value =
default_initialize ? 0 : this.realInputStream.readLong ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setLongField (obj, field_name, value);
}
else if (type == Short.TYPE)
{
short value =
default_initialize ? (short)0 : this.realInputStream.readShort ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setShortField (obj, field_name, value);
}
else
{
Object value =
default_initialize ? null : readObject ();
if (set_value)
setObjectField (obj, field_name,
real_field.getTypeString (), value);
}
try
{
if (type == Boolean.TYPE)
{
boolean value =
default_initialize ? false : this.realInputStream.readBoolean ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setBooleanField (obj, field_name, value);
}
else if (type == Byte.TYPE)
{
byte value =
default_initialize ? 0 : this.realInputStream.readByte ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setByteField (obj, field_name, value);
}
else if (type == Character.TYPE)
{
char value =
default_initialize ? (char)0 : this.realInputStream.readChar ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setCharField (obj, field_name, value);
}
else if (type == Double.TYPE)
{
double value =
default_initialize ? 0 : this.realInputStream.readDouble ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setDoubleField (obj, field_name, value);
}
else if (type == Float.TYPE)
{
float value =
default_initialize ? 0 : this.realInputStream.readFloat ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setFloatField (obj, field_name, value);
}
else if (type == Integer.TYPE)
{
int value =
default_initialize ? 0 : this.realInputStream.readInt ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setIntField (obj, field_name, value);
}
else if (type == Long.TYPE)
{
long value =
default_initialize ? 0 : this.realInputStream.readLong ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setLongField (obj, field_name, value);
}
else if (type == Short.TYPE)
{
short value =
default_initialize ? (short)0 : this.realInputStream.readShort ();
if (!default_initialize && set_value)
dumpElementln (" " + field_name + ": " + value);
if (set_value)
setShortField (obj, field_name, value);
}
else
{
Object value =
default_initialize ? null : readObject ();
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.
private void setBlockDataMode (boolean on)
private boolean setBlockDataMode (boolean on)
{
// DEBUGln ("Setting block data mode to " + on);
boolean oldmode = this.readDataFromBlock;
this.readDataFromBlock = on;
if (on)
this.dataInputStream = this.blockDataInput;
else
this.dataInputStream = this.realInputStream;
return oldmode;
}
@ -1380,12 +1460,18 @@ public class ObjectInputStream extends InputStream
return ClassLoader.getSystemClassLoader ();
}
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);
}
private void callReadMethod (Object obj, Class klass) throws IOException
{
try
@ -1593,6 +1679,14 @@ public class ObjectInputStream extends InputStream
if (Configuration.DEBUG && dump)
System.out.println(msg);
}
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary ("javaio");
}
}
}

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");
}
}
}

View File

@ -47,8 +47,23 @@ public class ObjectStreamField implements java.lang.Comparable
{
this.name = name;
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 ()
{
return name;
@ -61,12 +76,13 @@ public class ObjectStreamField implements java.lang.Comparable
public char getTypeCode ()
{
return TypeSignature.getEncodingOfClass (type).charAt (0);
return typename.charAt (0);
}
public String getTypeString ()
{
return TypeSignature.getEncodingOfClass (type);
// use intern()
return typename.intern();
}
public int getOffset ()
@ -106,5 +122,6 @@ public class ObjectStreamField implements java.lang.Comparable
private String name;
private Class type;
private String typename;
private int offset = -1; // XXX make sure this is correct
}

View File

@ -69,16 +69,3 @@ java::io::ObjectInputStream::callConstructor (jclass klass, jobject obj)
+ m->offset);
_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);
}

View File

@ -1,33 +0,0 @@
// 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);
}

View File

@ -15,7 +15,6 @@ JDBC2.0
# The following tests seem to hang or crash the testsuite.
# This a problem when running Mauve "standalone".
!java.io.ObjectInputOutput
!java.lang.reflect.Array.newInstance
# Character.unicode seems to be very broken (the test)