ObjectInputStream.java [plain text]
package java.io;
import gnu.classpath.Configuration;
import gnu.java.io.ObjectIdentityWrapper;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Vector;
public class ObjectInputStream extends InputStream
implements ObjectInput, ObjectStreamConstants
{
public ObjectInputStream(InputStream in)
throws IOException, StreamCorruptedException
{
if (Configuration.DEBUG)
{
String val = System.getProperty("gcj.dumpobjects");
if (dump == false && val != null && !val.equals(""))
{
dump = true;
System.out.println ("Serialization debugging enabled");
}
else if (dump == true && (val == null || val.equals("")))
{
dump = false;
System.out.println ("Serialization debugging disabled");
}
}
this.resolveEnabled = false;
this.isDeserializing = false;
this.blockDataPosition = 0;
this.blockDataBytes = 0;
this.blockData = new byte[BUFFER_SIZE];
this.blockDataInput = new DataInputStream(this);
this.realInputStream = new DataInputStream(in);
this.nextOID = baseWireHandle;
this.objectLookupTable = new Hashtable();
this.validators = new Vector();
this.classLookupTable = new Hashtable();
setBlockDataMode(true);
readStreamHeader();
}
public final Object readObject() throws ClassNotFoundException, IOException
{
if (this.useSubclassMethod)
return readObjectOverride();
boolean was_deserializing;
Object ret_val;
was_deserializing = this.isDeserializing;
boolean is_consumed = false;
boolean old_mode = setBlockDataMode(false);
this.isDeserializing = true;
byte marker = this.realInputStream.readByte();
if(dump) dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");
try
{
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)
{
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(osc, obj, handle);
break;
}
Object obj = newObject(clazz, osc.firstNonSerializableParent);
int handle = assignNewHandle(obj);
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 ());
Method readObjectMethod = this.currentObjectStreamClass.readObjectMethod;
if (readObjectMethod != null)
{
fieldsAlreadyRead = false;
boolean oldmode = setBlockDataMode(true);
callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
setBlockDataMode(oldmode);
if(dump) dumpElement("ENDBLOCKDATA? ");
try
{
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");
}
}
else
{
readFields(obj, currentObjectStreamClass);
}
}
this.currentObject = null;
this.currentObjectStreamClass = null;
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.isDeserializing = was_deserializing;
if (! was_deserializing)
{
if (validators.size() > 0)
invokeValidators();
}
}
return ret_val;
}
private void checkTypeConsistency(String name, ObjectStreamField[] fields1, ObjectStreamField[] fields2)
throws InvalidClassException
{
int nonPrimitive = 0;
for (nonPrimitive = 0;
nonPrimitive < fields1.length
&& fields1[nonPrimitive].isPrimitive(); nonPrimitive++)
{
}
if (nonPrimitive == fields1.length)
return;
int i = 0;
ObjectStreamField f1;
ObjectStreamField f2;
while (i < fields2.length
&& nonPrimitive < fields1.length)
{
f1 = fields1[nonPrimitive];
f2 = fields2[i];
if (!f2.isPrimitive())
break;
int compVal = f1.getName().compareTo (f2.getName());
if (compVal < 0)
{
nonPrimitive++;
}
else if (compVal > 0)
{
i++;
}
else
{
throw new InvalidClassException
("invalid field type for " + f2.getName() +
" in class " + name);
}
}
}
protected ObjectStreamClass readClassDescriptor()
throws ClassNotFoundException, IOException
{
if(dump) dumpElement("CLASSDESC NAME=");
String name = this.realInputStream.readUTF();
if(dump) dumpElement(name + "; UID=");
long uid = this.realInputStream.readLong ();
if(dump) dumpElement(Long.toHexString(uid) + "; FLAGS=");
byte flags = this.realInputStream.readByte ();
if(dump) dumpElement(Integer.toHexString(flags) + "; FIELD COUNT=");
short field_count = this.realInputStream.readShort();
if(dump) dumpElementln(Short.toString(field_count));
ObjectStreamField[] fields = new ObjectStreamField[field_count];
ObjectStreamClass osc = new ObjectStreamClass(name, uid,
flags, fields);
assignNewHandle(osc);
ClassLoader currentLoader = currentLoader();
for (int i = 0; i < field_count; i++)
{
if(dump) dumpElement(" TYPE CODE=");
char type_code = (char)this.realInputStream.readByte();
if(dump) dumpElement(type_code + "; FIELD NAME=");
String field_name = this.realInputStream.readUTF();
if(dump) 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, class_name, currentLoader);
}
Class clazz = resolveClass(osc);
boolean oldmode = setBlockDataMode(true);
osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
classLookupTable.put(clazz, osc);
setBlockDataMode(oldmode);
Class first_nonserial = clazz.getSuperclass();
while (Serializable.class.isAssignableFrom(first_nonserial)
|| Modifier.isAbstract(first_nonserial.getModifiers()))
first_nonserial = first_nonserial.getSuperclass();
osc.firstNonSerializableParent = first_nonserial;
osc.realClassIsSerializable = Serializable.class.isAssignableFrom(clazz);
osc.realClassIsExternalizable = Externalizable.class.isAssignableFrom(clazz);
ObjectStreamField[] stream_fields = osc.fields;
ObjectStreamField[] real_fields = ObjectStreamClass.lookup(clazz).fields;
ObjectStreamField[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)];
int stream_idx = 0;
int real_idx = 0;
int map_idx = 0;
checkTypeConsistency(name, real_fields, stream_fields);
checkTypeConsistency(name, stream_fields, real_fields);
while (stream_idx < stream_fields.length
|| real_idx < real_fields.length)
{
ObjectStreamField stream_field = null;
ObjectStreamField real_field = null;
if (stream_idx == stream_fields.length)
{
real_field = real_fields[real_idx++];
}
else if (real_idx == real_fields.length)
{
stream_field = stream_fields[stream_idx++];
}
else
{
int comp_val =
real_fields[real_idx].compareTo (stream_fields[stream_idx]);
if (comp_val < 0)
{
real_field = real_fields[real_idx++];
}
else if (comp_val > 0)
{
stream_field = stream_fields[stream_idx++];
}
else
{
stream_field = stream_fields[stream_idx++];
real_field = real_fields[real_idx++];
if (stream_field.getType() != real_field.getType())
throw new InvalidClassException
("invalid field type for " + real_field.getName() +
" in class " + name);
}
}
if (map_idx == fieldmapping.length)
{
ObjectStreamField[] newfieldmapping =
new ObjectStreamField[fieldmapping.length + 2];
System.arraycopy(fieldmapping, 0,
newfieldmapping, 0, fieldmapping.length);
fieldmapping = newfieldmapping;
}
fieldmapping[map_idx++] = stream_field;
fieldmapping[map_idx++] = real_field;
}
osc.fieldMapping = fieldmapping;
return osc;
}
public void defaultReadObject()
throws ClassNotFoundException, IOException, NotActiveException
{
if (this.currentObject == null || this.currentObjectStreamClass == null)
throw new NotActiveException("defaultReadObject called by non-active"
+ " class and/or object");
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);
setBlockDataMode(oldmode);
fieldsAlreadyRead = true;
}
public void registerValidation(ObjectInputValidation validator,
int priority)
throws InvalidObjectException, NotActiveException
{
if (this.currentObject == null || this.currentObjectStreamClass == null)
throw new NotActiveException("registerValidation called by non-active "
+ "class and/or object");
if (validator == null)
throw new InvalidObjectException("attempt to add a null "
+ "ObjectInputValidation object");
this.validators.addElement(new ValidatorAndPriority (validator,
priority));
}
protected Class resolveClass(ObjectStreamClass osc)
throws ClassNotFoundException, IOException
{
return Class.forName(osc.getName(), true, currentLoader());
}
private ClassLoader currentLoader()
{
SecurityManager sm = System.getSecurityManager();
if (sm == null)
sm = new SecurityManager () {};
return currentClassLoader(sm);
}
private ObjectStreamClass lookupClass(Class clazz)
{
ObjectStreamClass oclazz;
oclazz = (ObjectStreamClass)classLookupTable.get(clazz);
if (oclazz == null)
return ObjectStreamClass.lookup(clazz);
else
return oclazz;
}
private ObjectStreamClass[] inputGetObjectStreamClasses(Class clazz)
{
ObjectStreamClass osc = lookupClass(clazz);
if (osc == null)
return new ObjectStreamClass[0];
else
{
Vector oscs = new Vector();
while (osc != null)
{
oscs.addElement(osc);
osc = osc.getSuper();
}
int count = oscs.size();
ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[count];
for (int i = count - 1; i >= 0; i--)
sorted_oscs[count - i - 1] = (ObjectStreamClass) oscs.elementAt(i);
return sorted_oscs;
}
}
protected Object resolveObject(Object obj) throws IOException
{
return obj;
}
protected Class resolveProxyClass(String[] intfs)
throws IOException, ClassNotFoundException
{
SecurityManager sm = System.getSecurityManager();
if (sm == null)
sm = new SecurityManager() {};
ClassLoader cl = currentClassLoader(sm);
Class[] clss = new Class[intfs.length];
if(cl == null)
{
for (int i = 0; i < intfs.length; i++)
clss[i] = Class.forName(intfs[i]);
cl = ClassLoader.getSystemClassLoader();
}
else
for (int i = 0; i < intfs.length; i++)
clss[i] = cl.loadClass(intfs[i]);
try
{
return Proxy.getProxyClass(cl, clss);
}
catch (IllegalArgumentException e)
{
throw new ClassNotFoundException(null, e);
}
}
protected boolean enableResolveObject (boolean enable)
throws SecurityException
{
if (enable)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new SerializablePermission("enableSubstitution"));
}
boolean old_val = this.resolveEnabled;
this.resolveEnabled = enable;
return old_val;
}
protected void readStreamHeader()
throws IOException, StreamCorruptedException
{
if(dump) dumpElement("STREAM MAGIC ");
if (this.realInputStream.readShort() != STREAM_MAGIC)
throw new StreamCorruptedException("Invalid stream magic number");
if(dump) dumpElementln("STREAM VERSION ");
if (this.realInputStream.readShort() != STREAM_VERSION)
throw new StreamCorruptedException("Invalid stream version number");
}
public int read() throws IOException
{
if (this.readDataFromBlock)
{
if (this.blockDataPosition >= this.blockDataBytes)
readNextBlock();
return (this.blockData[this.blockDataPosition++] & 0xff);
}
else
return this.realInputStream.read();
}
public int read(byte[] data, int offset, int length) throws IOException
{
if (this.readDataFromBlock)
{
if (this.blockDataPosition + length > this.blockDataBytes)
{
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);
this.blockDataPosition += length;
return length;
}
else
return this.realInputStream.read(data, offset, length);
}
public int available() throws IOException
{
if (this.readDataFromBlock)
{
if (this.blockDataPosition >= this.blockDataBytes)
readNextBlock ();
return this.blockDataBytes - this.blockDataPosition;
}
else
return this.realInputStream.available();
}
public void close() throws IOException
{
this.realInputStream.close();
}
public boolean readBoolean() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode (true);
boolean value = this.dataInputStream.readBoolean ();
if (switchmode)
setBlockDataMode (oldmode);
return value;
}
public byte readByte() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
byte value = this.dataInputStream.readByte();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public int readUnsignedByte() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
int value = this.dataInputStream.readUnsignedByte();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public short readShort() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
short value = this.dataInputStream.readShort();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public int readUnsignedShort() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
int value = this.dataInputStream.readUnsignedShort();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public char readChar() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
char value = this.dataInputStream.readChar();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public int readInt() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
int value = this.dataInputStream.readInt();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public long readLong() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
long value = this.dataInputStream.readLong();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public float readFloat() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
float value = this.dataInputStream.readFloat();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public double readDouble() throws IOException
{
boolean switchmode = true;
boolean oldmode = this.readDataFromBlock;
if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
switchmode = false;
if (switchmode)
oldmode = setBlockDataMode(true);
double value = this.dataInputStream.readDouble();
if (switchmode)
setBlockDataMode(oldmode);
return value;
}
public void readFully(byte data[]) throws IOException
{
this.dataInputStream.readFully(data);
}
public void readFully(byte data[], int offset, int size)
throws IOException
{
this.dataInputStream.readFully(data, offset, size);
}
public int skipBytes(int len) throws IOException
{
return this.dataInputStream.skipBytes(len);
}
public String readLine() throws IOException
{
return this.dataInputStream.readLine();
}
public String readUTF() throws IOException
{
return this.dataInputStream.readUTF();
}
public static abstract class GetField
{
public abstract ObjectStreamClass getObjectStreamClass();
public abstract boolean defaulted(String name)
throws IOException, IllegalArgumentException;
public abstract boolean get(String name, boolean defvalue)
throws IOException, IllegalArgumentException;
public abstract char get(String name, char defvalue)
throws IOException, IllegalArgumentException;
public abstract byte get(String name, byte defvalue)
throws IOException, IllegalArgumentException;
public abstract short get(String name, short defvalue)
throws IOException, IllegalArgumentException;
public abstract int get(String name, int defvalue)
throws IOException, IllegalArgumentException;
public abstract long get(String name, long defvalue)
throws IOException, IllegalArgumentException;
public abstract float get(String name, float defvalue)
throws IOException, IllegalArgumentException;
public abstract double get(String name, double defvalue)
throws IOException, IllegalArgumentException;
public abstract Object get(String name, Object defvalue)
throws IOException, IllegalArgumentException;
}
public GetField readFields()
throws IOException, ClassNotFoundException, NotActiveException
{
if (this.currentObject == null || this.currentObjectStreamClass == null)
throw new NotActiveException("readFields called by non-active class and/or object");
if (prereadFields != null)
return prereadFields;
if (fieldsAlreadyRead)
throw new NotActiveException("readFields called but fields already read from"
+ " stream (by defaultReadObject or readFields)");
final ObjectStreamClass clazz = this.currentObjectStreamClass;
final byte[] prim_field_data = new byte[clazz.primFieldSize];
final Object[] objs = new Object[clazz.objectFieldCount];
boolean oldmode = setBlockDataMode(false);
readFully(prim_field_data);
for (int i = 0; i < objs.length; ++ i)
objs[i] = readObject();
setBlockDataMode(oldmode);
prereadFields = new GetField()
{
public ObjectStreamClass getObjectStreamClass()
{
return clazz;
}
public boolean defaulted(String name)
throws IOException, IllegalArgumentException
{
ObjectStreamField f = clazz.getField(name);
if (f != null)
{
if (f.isPersistent() && !f.isToSet())
return true;
return false;
}
try
{
return (clazz.forClass().getDeclaredField (name) != null);
}
catch (NoSuchFieldException e)
{
throw new IllegalArgumentException(e.getMessage());
}
}
public boolean get(String name, boolean defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field = getField(name, Boolean.TYPE);
if (field == null)
return defvalue;
return prim_field_data[field.getOffset()] == 0 ? false : true;
}
public char get(String name, char defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field = getField(name, Character.TYPE);
if (field == null)
return defvalue;
int off = field.getOffset();
return (char)(((prim_field_data[off++] & 0xFF) << 8)
| (prim_field_data[off] & 0xFF));
}
public byte get(String name, byte defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field = getField(name, Byte.TYPE);
if (field == null)
return defvalue;
return prim_field_data[field.getOffset()];
}
public short get(String name, short defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field = getField(name, Short.TYPE);
if (field == null)
return defvalue;
int off = field.getOffset();
return (short)(((prim_field_data[off++] & 0xFF) << 8)
| (prim_field_data[off] & 0xFF));
}
public int get(String name, int defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field = getField(name, Integer.TYPE);
if (field == null)
return defvalue;
int off = field.getOffset();
return ((prim_field_data[off++] & 0xFF) << 24)
| ((prim_field_data[off++] & 0xFF) << 16)
| ((prim_field_data[off++] & 0xFF) << 8)
| (prim_field_data[off] & 0xFF);
}
public long get(String name, long defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field = getField(name, Long.TYPE);
if (field == null)
return defvalue;
int off = field.getOffset();
return (long)(((prim_field_data[off++] & 0xFF) << 56)
| ((prim_field_data[off++] & 0xFF) << 48)
| ((prim_field_data[off++] & 0xFF) << 40)
| ((prim_field_data[off++] & 0xFF) << 32)
| ((prim_field_data[off++] & 0xFF) << 24)
| ((prim_field_data[off++] & 0xFF) << 16)
| ((prim_field_data[off++] & 0xFF) << 8)
| (prim_field_data[off] & 0xFF));
}
public float get(String name, float defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field = getField(name, Float.TYPE);
if (field == null)
return defvalue;
int off = field.getOffset();
return Float.intBitsToFloat(((prim_field_data[off++] & 0xFF) << 24)
| ((prim_field_data[off++] & 0xFF) << 16)
| ((prim_field_data[off++] & 0xFF) << 8)
| (prim_field_data[off] & 0xFF));
}
public double get(String name, double defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field = getField(name, Double.TYPE);
if (field == null)
return defvalue;
int off = field.getOffset();
return Double.longBitsToDouble
( (long) (((prim_field_data[off++] & 0xFF) << 56)
| ((prim_field_data[off++] & 0xFF) << 48)
| ((prim_field_data[off++] & 0xFF) << 40)
| ((prim_field_data[off++] & 0xFF) << 32)
| ((prim_field_data[off++] & 0xFF) << 24)
| ((prim_field_data[off++] & 0xFF) << 16)
| ((prim_field_data[off++] & 0xFF) << 8)
| (prim_field_data[off] & 0xFF)));
}
public Object get(String name, Object defvalue)
throws IOException, IllegalArgumentException
{
ObjectStreamField field =
getField(name, defvalue == null ? null : defvalue.getClass ());
if (field == null)
return defvalue;
return objs[field.getOffset()];
}
private ObjectStreamField getField(String name, Class type)
throws IllegalArgumentException
{
ObjectStreamField field = clazz.getField(name);
boolean illegal = false;
try
{
try
{
Class field_type = field.getType();
if (type == field_type ||
(type == null && !field_type.isPrimitive()))
{
return field;
}
illegal = true;
throw new IllegalArgumentException
("Field requested is of type "
+ field_type.getName()
+ ", but requested type was "
+ (type == null ? "Object" : type.getName()));
}
catch (NullPointerException _)
{
}
catch (IllegalArgumentException e)
{
throw e;
}
return null;
}
finally
{
if (!illegal && field != null && !field.isToSet() && field.isPersistent())
return null;
try
{
Field f = clazz.forClass().getDeclaredField(name);
if (Modifier.isTransient(f.getModifiers()))
throw new IllegalArgumentException
("no such field (non transient) " + name);
if (field == null && f.getType() != type)
throw new IllegalArgumentException
("Invalid requested type for field " + name);
}
catch (NoSuchFieldException e)
{
if (field == null)
throw new IllegalArgumentException(e.getMessage());
}
}
}
};
fieldsAlreadyRead = true;
return prereadFields;
}
protected ObjectInputStream()
throws IOException, SecurityException
{
SecurityManager sec_man = System.getSecurityManager();
if (sec_man != null)
sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
this.useSubclassMethod = true;
}
protected Object readObjectOverride()
throws ClassNotFoundException, IOException, OptionalDataException
{
throw new IOException("Subclass of ObjectInputStream must implement readObjectOverride");
}
private int assignNewHandle(Object obj)
{
this.objectLookupTable.put(new Integer(this.nextOID),
new ObjectIdentityWrapper(obj));
return this.nextOID++;
}
private Object processResolution(ObjectStreamClass osc, Object obj, int handle)
throws IOException
{
if (osc != null && obj instanceof Serializable)
{
try
{
Method m = osc.readResolveMethod;
if(m != null)
{
obj = m.invoke(obj, new Object[] {});
}
}
catch (IllegalAccessException ignore)
{
}
catch (InvocationTargetException ignore)
{
}
}
if (this.resolveEnabled)
obj = resolveObject(obj);
this.objectLookupTable.put(new Integer(handle),
new ObjectIdentityWrapper(obj));
return obj;
}
private void clearHandles()
{
this.objectLookupTable.clear();
this.nextOID = baseWireHandle;
}
private void readNextBlock() throws IOException
{
readNextBlock(this.realInputStream.readByte());
}
private void readNextBlock(byte marker) throws IOException
{
if (marker == TC_BLOCKDATA)
{
if(dump) dumpElement("BLOCK DATA SIZE=");
this.blockDataBytes = this.realInputStream.readUnsignedByte();
if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
}
else if (marker == TC_BLOCKDATALONG)
{
if(dump) dumpElement("BLOCK DATA LONG SIZE=");
this.blockDataBytes = this.realInputStream.readInt();
if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
}
else
{
throw new EOFException("Attempt to read primitive data, but no data block is active.");
}
if (this.blockData.length < this.blockDataBytes)
this.blockData = new byte[this.blockDataBytes];
this.realInputStream.readFully (this.blockData, 0, this.blockDataBytes);
this.blockDataPosition = 0;
}
private void readArrayElements (Object array, Class clazz)
throws ClassNotFoundException, IOException
{
if (clazz.isPrimitive())
{
if (clazz == Boolean.TYPE)
{
boolean[] cast_array = (boolean[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = this.realInputStream.readBoolean();
return;
}
if (clazz == Byte.TYPE)
{
byte[] cast_array = (byte[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = this.realInputStream.readByte();
return;
}
if (clazz == Character.TYPE)
{
char[] cast_array = (char[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = this.realInputStream.readChar();
return;
}
if (clazz == Double.TYPE)
{
double[] cast_array = (double[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = this.realInputStream.readDouble();
return;
}
if (clazz == Float.TYPE)
{
float[] cast_array = (float[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = this.realInputStream.readFloat();
return;
}
if (clazz == Integer.TYPE)
{
int[] cast_array = (int[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = this.realInputStream.readInt();
return;
}
if (clazz == Long.TYPE)
{
long[] cast_array = (long[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = this.realInputStream.readLong();
return;
}
if (clazz == Short.TYPE)
{
short[] cast_array = (short[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = this.realInputStream.readShort();
return;
}
}
else
{
Object[] cast_array = (Object[])array;
for (int i=0; i < cast_array.length; i++)
cast_array[i] = readObject();
}
}
private void readFields (Object obj, ObjectStreamClass stream_osc)
throws ClassNotFoundException, IOException
{
ObjectStreamField[] fields = stream_osc.fieldMapping;
for (int i = 0; i < fields.length; i += 2)
{
ObjectStreamField stream_field = fields[i];
ObjectStreamField real_field = fields[i + 1];
boolean read_value = (stream_field != null && stream_field.getOffset() >= 0 && stream_field.isToSet());
boolean set_value = (real_field != null && real_field.isToSet());
String field_name;
char type;
if (stream_field != null)
{
field_name = stream_field.getName();
type = stream_field.getTypeCode();
}
else
{
field_name = real_field.getName();
type = real_field.getTypeCode();
}
switch(type)
{
case 'Z':
{
boolean value =
read_value ? this.realInputStream.readBoolean() : false;
if (dump && read_value && set_value)
dumpElementln(" " + field_name + ": " + value);
if (set_value)
real_field.setBooleanField(obj, value);
break;
}
case 'B':
{
byte value =
read_value ? this.realInputStream.readByte() : 0;
if (dump && read_value && set_value)
dumpElementln(" " + field_name + ": " + value);
if (set_value)
real_field.setByteField(obj, value);
break;
}
case 'C':
{
char value =
read_value ? this.realInputStream.readChar(): 0;
if (dump && read_value && set_value)
dumpElementln(" " + field_name + ": " + value);
if (set_value)
real_field.setCharField(obj, value);
break;
}
case 'D':
{
double value =
read_value ? this.realInputStream.readDouble() : 0;
if (dump && read_value && set_value)
dumpElementln(" " + field_name + ": " + value);
if (set_value)
real_field.setDoubleField(obj, value);
break;
}
case 'F':
{
float value =
read_value ? this.realInputStream.readFloat() : 0;
if (dump && read_value && set_value)
dumpElementln(" " + field_name + ": " + value);
if (set_value)
real_field.setFloatField(obj, value);
break;
}
case 'I':
{
int value =
read_value ? this.realInputStream.readInt() : 0;
if (dump && read_value && set_value)
dumpElementln(" " + field_name + ": " + value);
if (set_value)
real_field.setIntField(obj, value);
break;
}
case 'J':
{
long value =
read_value ? this.realInputStream.readLong() : 0;
if (dump && read_value && set_value)
dumpElementln(" " + field_name + ": " + value);
if (set_value)
real_field.setLongField(obj, value);
break;
}
case 'S':
{
short value =
read_value ? this.realInputStream.readShort() : 0;
if (dump && read_value && set_value)
dumpElementln(" " + field_name + ": " + value);
if (set_value)
real_field.setShortField(obj, value);
break;
}
case 'L':
case '[':
{
Object value =
read_value ? readObject() : null;
if (set_value)
real_field.setObjectField(obj, value);
break;
}
default:
throw new InternalError("Invalid type code: " + type);
}
}
}
private boolean setBlockDataMode (boolean on)
{
boolean oldmode = this.readDataFromBlock;
this.readDataFromBlock = on;
if (on)
this.dataInputStream = this.blockDataInput;
else
this.dataInputStream = this.realInputStream;
return oldmode;
}
private Object newObject (Class real_class, Class constructor_class)
throws ClassNotFoundException
{
try
{
Object obj = allocateObject (real_class);
callConstructor (constructor_class, obj);
return obj;
}
catch (InstantiationException e)
{
throw new ClassNotFoundException
("Instance of " + real_class + " could not be created");
}
}
private void invokeValidators() throws InvalidObjectException
{
Object[] validators = new Object[this.validators.size()];
this.validators.copyInto (validators);
Arrays.sort (validators);
try
{
for (int i=0; i < validators.length; i++)
((ObjectInputValidation)validators[i]).validateObject();
}
finally
{
this.validators.removeAllElements();
}
}
private static ClassLoader currentClassLoader (SecurityManager sm)
{
return ClassLoader.getSystemClassLoader ();
}
private void callReadMethod (Method readObject, Class klass, Object obj) throws IOException
{
try
{
readObject.invoke(obj, new Object[] { this });
}
catch (InvocationTargetException x)
{
Throwable exception = x.getTargetException();
if (exception instanceof RuntimeException)
throw (RuntimeException) exception;
if (exception instanceof IOException)
throw (IOException) exception;
throw new IOException("Exception thrown from readObject() on " +
klass + ": " + exception.getClass().getName());
}
catch (Exception x)
{
throw new IOException("Failure invoking readObject() on " +
klass + ": " + x.getClass().getName());
}
prereadFields = null;
}
private native Object allocateObject (Class clazz)
throws InstantiationException;
private native void callConstructor (Class clazz, Object obj);
private static final int BUFFER_SIZE = 1024;
private DataInputStream realInputStream;
private DataInputStream dataInputStream;
private DataInputStream blockDataInput;
private int blockDataPosition;
private int blockDataBytes;
private byte[] blockData;
private boolean useSubclassMethod;
private int nextOID;
private boolean resolveEnabled;
private Hashtable objectLookupTable;
private Object currentObject;
private ObjectStreamClass currentObjectStreamClass;
private boolean readDataFromBlock;
private boolean isDeserializing;
private boolean fieldsAlreadyRead;
private Vector validators;
private Hashtable classLookupTable;
private GetField prereadFields;
private static boolean dump = false && Configuration.DEBUG;
private void dumpElement (String msg)
{
System.out.print(msg);
}
private void dumpElementln (String msg)
{
System.out.println(msg);
}
static
{
if (Configuration.INIT_LOAD_LIBRARY)
{
System.loadLibrary ("javaio");
}
}
}
class ValidatorAndPriority implements Comparable
{
int priority;
ObjectInputValidation validator;
ValidatorAndPriority (ObjectInputValidation validator, int priority)
{
this.priority = priority;
this.validator = validator;
}
public int compareTo (Object o)
{
ValidatorAndPriority vap = (ValidatorAndPriority)o;
return this.priority - vap.priority;
}
}