Index: java/io/ObjectInputStream.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/ObjectInputStream.java,v
retrieving revision 1.64
diff -u -3 -p -u -r1.64 ObjectInputStream.java
--- java/io/ObjectInputStream.java 9 Sep 2005 12:12:03 -0000 1.64
+++ java/io/ObjectInputStream.java 12 Sep 2005 14:14:21 -0000
@@ -120,7 +120,8 @@ public class ObjectInputStream extends I
* @exception IOException Exception from underlying
* InputStream
.
*/
- public final Object readObject() throws ClassNotFoundException, IOException
+ public final Object readObject()
+ throws ClassNotFoundException, IOException
{
if (this.useSubclassMethod)
return readObjectOverride();
@@ -130,7 +131,6 @@ public class ObjectInputStream extends I
Object ret_val;
was_deserializing = this.isDeserializing;
- boolean is_consumed = false;
boolean old_mode = setBlockDataMode(false);
this.isDeserializing = true;
@@ -143,271 +143,285 @@ public class ObjectInputStream extends I
try
{
- switch (marker)
+ ret_val = parseContent(marker);
+ }
+ finally
+ {
+ setBlockDataMode(old_mode);
+
+ this.isDeserializing = was_deserializing;
+
+ depth -= 2;
+
+ if (! was_deserializing)
{
- case TC_ENDBLOCKDATA:
+ if (validators.size() > 0)
+ invokeValidators();
+ }
+ }
+
+ return ret_val;
+ }
+
+ /**
+ * Handles a content block within the stream, which begins with a marker
+ * byte indicating its type.
+ *
+ * @param byte the byte marker.
+ * @return an object which represents the parsed content.
+ * @throws ClassNotFoundException if the class of an object being
+ * read in cannot be found.
+ * @throws IOException if invalid data occurs or one is thrown by the
+ * underlying InputStream
.
+ */
+ private Object parseContent(byte marker)
+ throws ClassNotFoundException, IOException
+ {
+ Object ret_val;
+ boolean is_consumed = false;
+
+ switch (marker)
+ {
+ case TC_ENDBLOCKDATA:
+ {
+ ret_val = null;
+ is_consumed = true;
+ break;
+ }
+
+ case TC_BLOCKDATA:
+ case TC_BLOCKDATALONG:
+ {
+ if (marker == TC_BLOCKDATALONG)
+ { if(dump) dumpElementln("BLOCKDATALONG"); }
+ else
+ { if(dump) dumpElementln("BLOCKDATA"); }
+ readNextBlock(marker);
+ throw new StreamCorruptedException("Unexpected blockData");
+ }
+
+ case TC_NULL:
+ {
+ if(dump) dumpElementln("NULL");
+ ret_val = null;
+ break;
+ }
+
+ case TC_REFERENCE:
+ {
+ if(dump) dumpElement("REFERENCE ");
+ Integer oid = new Integer(this.realInputStream.readInt());
+ if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
+ ret_val = ((ObjectIdentityWrapper)
+ this.objectLookupTable.get(oid)).object;
+ break;
+ }
+
+ case TC_CLASS:
+ {
+ if(dump) dumpElementln("CLASS");
+ ObjectStreamClass osc = (ObjectStreamClass)readObject();
+ Class clazz = osc.forClass();
+ assignNewHandle(clazz);
+ ret_val = clazz;
+ break;
+ }
+
+ case TC_PROXYCLASSDESC:
+ {
+ if(dump) 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 = lookupClass(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:
+ {
+ ObjectStreamClass osc = readClassDescriptor();
+
+ 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:
+ {
+ if(dump) dumpElement("STRING=");
+ String s = this.realInputStream.readUTF();
+ if(dump) dumpElementln(s);
+ ret_val = processResolution(null, s, assignNewHandle(s));
+ break;
+ }
+
+ case TC_ARRAY:
+ {
+ if(dump) dumpElementln("ARRAY");
+ ObjectStreamClass osc = (ObjectStreamClass)readObject();
+ Class componentType = osc.forClass().getComponentType();
+ if(dump) dumpElement("ARRAY LENGTH=");
+ int length = this.realInputStream.readInt();
+ if(dump) dumpElementln (length + "; COMPONENT TYPE=" + componentType);
+ Object array = Array.newInstance(componentType, length);
+ int handle = assignNewHandle(array);
+ readArrayElements(array, componentType);
+ if(dump)
+ for (int i = 0, len = Array.getLength(array); i < len; i++)
+ dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i));
+ ret_val = processResolution(null, array, handle);
+ break;
+ }
+
+ case TC_OBJECT:
+ {
+ if(dump) dumpElementln("OBJECT");
+ ObjectStreamClass osc = (ObjectStreamClass)readObject();
+ Class clazz = osc.forClass();
+
+ if (!osc.realClassIsSerializable)
+ throw new NotSerializableException
+ (clazz + " is not Serializable, and thus cannot be deserialized.");
+
+ if (osc.realClassIsExternalizable)
{
- ret_val = null;
- is_consumed = true;
- break;
- }
-
- case TC_BLOCKDATA:
- case TC_BLOCKDATALONG:
- {
- if (marker == TC_BLOCKDATALONG)
- { if(dump) dumpElementln("BLOCKDATALONG"); }
- else
- { if(dump) dumpElementln("BLOCKDATA"); }
- readNextBlock(marker);
- throw new StreamCorruptedException("Unexpected blockData");
- }
-
- case TC_NULL:
- {
- if(dump) dumpElementln("NULL");
- ret_val = null;
- break;
- }
-
- case TC_REFERENCE:
- {
- if(dump) dumpElement("REFERENCE ");
- Integer oid = new Integer(this.realInputStream.readInt());
- if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
- ret_val = ((ObjectIdentityWrapper)
- this.objectLookupTable.get(oid)).object;
- break;
- }
-
- case TC_CLASS:
- {
- if(dump) dumpElementln("CLASS");
- ObjectStreamClass osc = (ObjectStreamClass)readObject();
- Class clazz = osc.forClass();
- assignNewHandle(clazz);
- ret_val = clazz;
- break;
- }
-
- case TC_PROXYCLASSDESC:
- {
- if(dump) 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();
- }
+ Externalizable obj = osc.newInstance();
- boolean oldmode = setBlockDataMode(true);
- Class cl = resolveProxyClass(intfs);
- setBlockDataMode(oldmode);
+ int handle = assignNewHandle(obj);
- ObjectStreamClass osc = lookupClass(cl);
- assignNewHandle(osc);
+ boolean read_from_blocks = ((osc.getFlags() & SC_BLOCK_DATA) != 0);
- 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);
- osc.firstNonSerializableParentConstructor =
- superosc.firstNonSerializableParentConstructor;
- osc.fieldMapping = new ObjectStreamField[0];
- osc.realClassIsSerializable = true;
- ret_val = osc;
- break;
- }
-
- case TC_CLASSDESC:
- {
- ObjectStreamClass osc = readClassDescriptor();
+ boolean oldmode = this.readDataFromBlock;
+ if (read_from_blocks)
+ setBlockDataMode(true);
- if (!is_consumed)
- {
- byte b = this.realInputStream.readByte();
- if (b != TC_ENDBLOCKDATA)
- throw new IOException("Data annotated to class was not consumed." + b);
+ obj.readExternal(this);
+
+ if (read_from_blocks)
+ {
+ setBlockDataMode(oldmode);
+ if (!oldmode)
+ if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
+ throw new IOException("No end of block data seen for class with readExternal (ObjectInputStream) method.");
}
- else
- is_consumed = false;
-
- osc.setSuperclass ((ObjectStreamClass)readObject());
- ret_val = osc;
- break;
- }
- case TC_STRING:
- case TC_LONGSTRING:
- {
- if(dump) dumpElement("STRING=");
- String s = this.realInputStream.readUTF();
- if(dump) dumpElementln(s);
- ret_val = processResolution(null, s, assignNewHandle(s));
- break;
- }
-
- case TC_ARRAY:
- {
- if(dump) dumpElementln("ARRAY");
- ObjectStreamClass osc = (ObjectStreamClass)readObject();
- Class componentType = osc.forClass().getComponentType();
- if(dump) dumpElement("ARRAY LENGTH=");
- int length = this.realInputStream.readInt();
- if(dump) dumpElementln (length + "; COMPONENT TYPE=" + componentType);
- Object array = Array.newInstance(componentType, length);
- int handle = assignNewHandle(array);
- readArrayElements(array, componentType);
- if(dump)
- for (int i = 0, len = Array.getLength(array); i < len; i++)
- dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i));
- ret_val = processResolution(null, array, handle);
- break;
- }
-
- case TC_OBJECT:
- {
- if(dump) dumpElementln("OBJECT");
- ObjectStreamClass osc = (ObjectStreamClass)readObject();
- Class clazz = osc.forClass();
-
- if (!osc.realClassIsSerializable)
- throw new NotSerializableException
- (clazz + " is not Serializable, and thus cannot be deserialized.");
+ ret_val = processResolution(osc, obj, handle);
+ break;
- if (osc.realClassIsExternalizable)
- {
- Externalizable obj = osc.newInstance();
-
- 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);
- if (!oldmode)
- if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
- throw new IOException("No end of block data seen for class with readExternal (ObjectInputStream) method.");
- }
-
- ret_val = processResolution(osc, obj, handle);
- break;
- } // end if (osc.realClassIsExternalizable)
-
- Object obj = newObject(clazz, osc.firstNonSerializableParentConstructor);
-
- int handle = assignNewHandle(obj);
- Object prevObject = this.currentObject;
- ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
-
- this.currentObject = obj;
- ObjectStreamClass[] hierarchy =
- inputGetObjectStreamClasses(clazz);
-
- for (int i = 0; i < hierarchy.length; i++)
- {
- this.currentObjectStreamClass = hierarchy[i];
-
- if(dump) dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ());
-
- // 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
-
- Method readObjectMethod = this.currentObjectStreamClass.readObjectMethod;
- if (readObjectMethod != null)
- {
- fieldsAlreadyRead = false;
- boolean oldmode = setBlockDataMode(true);
- callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
- setBlockDataMode(oldmode);
- }
- else
- {
- readFields(obj, currentObjectStreamClass);
- }
-
- if (this.currentObjectStreamClass.hasWriteMethod())
- {
- if(dump) 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.");
- if(dump) dumpElementln("yes");
- }
-// catch (EOFException e)
-// {
-// if(dump) dumpElementln("no, got EOFException");
-// }
- catch (IOException e)
- {
- if(dump) dumpElementln("no, got IOException");
+ } // end if (osc.realClassIsExternalizable)
+
+ Object obj = newObject(clazz, osc.firstNonSerializableParentConstructor);
+
+ int handle = assignNewHandle(obj);
+ Object prevObject = this.currentObject;
+ ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
+
+ this.currentObject = obj;
+ ObjectStreamClass[] hierarchy =
+ inputGetObjectStreamClasses(clazz);
+
+ for (int i = 0; i < hierarchy.length; i++)
+ {
+ this.currentObjectStreamClass = hierarchy[i];
+ if(dump) dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ());
+
+ // 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
+
+ Method readObjectMethod = this.currentObjectStreamClass.readObjectMethod;
+ if (readObjectMethod != null)
+ {
+ fieldsAlreadyRead = false;
+ boolean oldmode = setBlockDataMode(true);
+ callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
+ setBlockDataMode(oldmode);
+ }
+ else
+ {
+ readFields(obj, currentObjectStreamClass);
+ }
+
+ if (this.currentObjectStreamClass.hasWriteMethod())
+ {
+ if(dump) dumpElement("ENDBLOCKDATA? ");
+ try
+ {
+ /* Read blocks until an end marker */
+ byte writeMarker = this.realInputStream.readByte();
+ while (writeMarker != TC_ENDBLOCKDATA)
+ {
+ parseContent(writeMarker);
+ writeMarker = this.realInputStream.readByte();
}
+ if(dump) dumpElementln("yes");
+ }
+ catch (EOFException e)
+ {
+ throw (IOException) new IOException
+ ("No end of block data seen for class with readObject (ObjectInputStream) method.").initCause(e);
}
}
-
- this.currentObject = prevObject;
- this.currentObjectStreamClass = prevObjectStreamClass;
- ret_val = processResolution(osc, obj, handle);
-
- break;
}
-
- case TC_RESET:
- if(dump) dumpElementln("RESET");
- clearHandles();
- ret_val = readObject();
- break;
-
- case TC_EXCEPTION:
- {
- if(dump) dumpElement("EXCEPTION=");
- Exception e = (Exception)readObject();
- if(dump) dumpElementln(e.toString());
- clearHandles();
- throw new WriteAbortedException("Exception thrown during writing of stream", e);
- }
-
- default:
- throw new IOException("Unknown marker on stream: " + marker);
- }
- }
- finally
- {
- setBlockDataMode(old_mode);
+
+ this.currentObject = prevObject;
+ this.currentObjectStreamClass = prevObjectStreamClass;
+ ret_val = processResolution(osc, obj, handle);
+
+ break;
+ }
- this.isDeserializing = was_deserializing;
+ case TC_RESET:
+ if(dump) dumpElementln("RESET");
+ clearHandles();
+ ret_val = readObject();
+ break;
- depth -= 2;
+ case TC_EXCEPTION:
+ {
+ if(dump) dumpElement("EXCEPTION=");
+ Exception e = (Exception)readObject();
+ if(dump) dumpElementln(e.toString());
+ 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: " + marker);
}
-
return ret_val;
}