2003-12-23 Guilhem Lavaux <guilhem@kaffe.org>
* java/io/ObjectInputStream.java (getField): Handle transient and non persistent fields. (readClassDescriptor): Better error handling, use the right class loader. (readFields): Fields marked as not present in the stream or not to be set are not read and set. * java/io/ObjectInputStream.java (readFields): Changed implementation of GetField. (readClassDescriptor): Documented. * java/io/ObjectOutputStream.java (writeClassDescriptor): Added condition when to write class super class information. From-SVN: r74985
This commit is contained in:
parent
f2073745a8
commit
692fb023ef
|
@ -1,3 +1,18 @@
|
||||||
|
2003-12-23 Guilhem Lavaux <guilhem@kaffe.org>
|
||||||
|
|
||||||
|
* java/io/ObjectInputStream.java
|
||||||
|
(getField): Handle transient and non persistent fields.
|
||||||
|
(readClassDescriptor): Better error handling, use the right
|
||||||
|
class loader.
|
||||||
|
(readFields): Fields marked as not present in the stream
|
||||||
|
or not to be set are not read and set.
|
||||||
|
* java/io/ObjectInputStream.java
|
||||||
|
(readFields): Changed implementation of GetField.
|
||||||
|
(readClassDescriptor): Documented.
|
||||||
|
* java/io/ObjectOutputStream.java
|
||||||
|
(writeClassDescriptor): Added condition when to write class super
|
||||||
|
class information.
|
||||||
|
|
||||||
2003-12-22 Fernando Nasser <fnasser@redhat.com>
|
2003-12-22 Fernando Nasser <fnasser@redhat.com>
|
||||||
|
|
||||||
* gnu/java/awt/peer/gtk/GtkChoicePeer.java (postItemEvent): Rename to...
|
* gnu/java/awt/peer/gtk/GtkChoicePeer.java (postItemEvent): Rename to...
|
||||||
|
|
|
@ -101,6 +101,7 @@ public class ObjectInputStream extends InputStream
|
||||||
this.nextOID = baseWireHandle;
|
this.nextOID = baseWireHandle;
|
||||||
this.objectLookupTable = new Hashtable ();
|
this.objectLookupTable = new Hashtable ();
|
||||||
this.validators = new Vector ();
|
this.validators = new Vector ();
|
||||||
|
this.classLookupTable = new Hashtable();
|
||||||
setBlockDataMode (true);
|
setBlockDataMode (true);
|
||||||
readStreamHeader ();
|
readStreamHeader ();
|
||||||
}
|
}
|
||||||
|
@ -417,6 +418,22 @@ public class ObjectInputStream extends InputStream
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method reads a class descriptor from the real input stream
|
||||||
|
* and use these data to create a new instance of ObjectStreamClass.
|
||||||
|
* Fields are sorted and ordered for the real read which occurs for
|
||||||
|
* each instance of the described class. Be aware that if you call that
|
||||||
|
* method you must ensure that the stream is synchronized, in the other
|
||||||
|
* case it may be completely desynchronized.
|
||||||
|
*
|
||||||
|
* @return A new instance of ObjectStreamClass containing the freshly
|
||||||
|
* created descriptor.
|
||||||
|
* @throws ClassNotFoundException if the required class to build the
|
||||||
|
* descriptor has not been found in the system.
|
||||||
|
* @throws IOException An input/output error occured.
|
||||||
|
* @throws InvalidClassException If there was a compatibility problem
|
||||||
|
* between the class present in the system and the serialized class.
|
||||||
|
*/
|
||||||
protected ObjectStreamClass readClassDescriptor ()
|
protected ObjectStreamClass readClassDescriptor ()
|
||||||
throws ClassNotFoundException, IOException
|
throws ClassNotFoundException, IOException
|
||||||
{
|
{
|
||||||
|
@ -443,19 +460,41 @@ public class ObjectInputStream extends InputStream
|
||||||
dumpElementln (field_name);
|
dumpElementln (field_name);
|
||||||
String class_name;
|
String class_name;
|
||||||
|
|
||||||
|
// If the type code is an array or an object we must
|
||||||
|
// decode a String here. In the other case we convert
|
||||||
|
// the type code and pass it to ObjectStreamField.
|
||||||
|
// Type codes are decoded by gnu.java.lang.reflect.TypeSignature.
|
||||||
if (type_code == 'L' || type_code == '[')
|
if (type_code == 'L' || type_code == '[')
|
||||||
class_name = (String)readObject ();
|
class_name = (String)readObject ();
|
||||||
else
|
else
|
||||||
class_name = String.valueOf (type_code);
|
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] =
|
fields[i] =
|
||||||
new ObjectStreamField (field_name, class_name);
|
new ObjectStreamField(field_name, class_name, currentLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now that fields have been read we may resolve the class
|
||||||
|
* (and read annotation if needed). */
|
||||||
Class clazz = resolveClass(osc);
|
Class clazz = resolveClass(osc);
|
||||||
|
|
||||||
|
for (int i = 0; i < field_count; i++)
|
||||||
|
{
|
||||||
|
Field f;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
f = clazz.getDeclaredField(fields[i].getName());
|
||||||
|
if (f != null && !f.getType().equals(fields[i].getType()))
|
||||||
|
throw new InvalidClassException
|
||||||
|
("invalid field type for " + fields[i].getName() + " in class "
|
||||||
|
+ name + " (requested was \"" + fields[i].getType()
|
||||||
|
+ " and found \"" + f.getType() + "\")");
|
||||||
|
}
|
||||||
|
catch (NoSuchFieldException _)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean oldmode = setBlockDataMode (true);
|
boolean oldmode = setBlockDataMode (true);
|
||||||
osc.setClass (clazz, lookupClass(clazz.getSuperclass()));
|
osc.setClass (clazz, lookupClass(clazz.getSuperclass()));
|
||||||
classLookupTable.put(clazz, osc);
|
classLookupTable.put(clazz, osc);
|
||||||
|
@ -487,10 +526,13 @@ public class ObjectInputStream extends InputStream
|
||||||
throws ClassNotFoundException, IOException, NotActiveException
|
throws ClassNotFoundException, IOException, NotActiveException
|
||||||
{
|
{
|
||||||
if (this.currentObject == null || this.currentObjectStreamClass == null)
|
if (this.currentObject == null || this.currentObjectStreamClass == null)
|
||||||
throw new NotActiveException ("defaultReadObject called by non-active class and/or object");
|
throw new NotActiveException("defaultReadObject called by non-active"
|
||||||
|
+ " class and/or object");
|
||||||
|
|
||||||
if (fieldsAlreadyRead)
|
if (fieldsAlreadyRead)
|
||||||
throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");
|
throw new NotActiveException("defaultReadObject called but fields "
|
||||||
|
+ "already read from stream (by "
|
||||||
|
+ "defaultReadObject or readFields)");
|
||||||
|
|
||||||
boolean oldmode = setBlockDataMode(false);
|
boolean oldmode = setBlockDataMode(false);
|
||||||
readFields (this.currentObject, this.currentObjectStreamClass);
|
readFields (this.currentObject, this.currentObjectStreamClass);
|
||||||
|
@ -523,10 +565,12 @@ public class ObjectInputStream extends InputStream
|
||||||
throws InvalidObjectException, NotActiveException
|
throws InvalidObjectException, NotActiveException
|
||||||
{
|
{
|
||||||
if (this.currentObject == null || this.currentObjectStreamClass == null)
|
if (this.currentObject == null || this.currentObjectStreamClass == null)
|
||||||
throw new NotActiveException ("registerValidation called by non-active class and/or object");
|
throw new NotActiveException ("registerValidation called by non-active "
|
||||||
|
+"class and/or object");
|
||||||
|
|
||||||
if (validator == null)
|
if (validator == null)
|
||||||
throw new InvalidObjectException ("attempt to add a null ObjectInputValidation object");
|
throw new InvalidObjectException ("attempt to add a null "
|
||||||
|
+"ObjectInputValidation object");
|
||||||
|
|
||||||
this.validators.addElement (new ValidatorAndPriority (validator,
|
this.validators.addElement (new ValidatorAndPriority (validator,
|
||||||
priority));
|
priority));
|
||||||
|
@ -555,6 +599,14 @@ public class ObjectInputStream extends InputStream
|
||||||
return Class.forName(osc.getName(), true, currentLoader());
|
return Class.forName(osc.getName(), true, currentLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method invokes the method currentClassLoader for the
|
||||||
|
* current security manager (or build an empty one if it is not
|
||||||
|
* present).
|
||||||
|
*
|
||||||
|
* @return The most recent non-system ClassLoader on the execution stack.
|
||||||
|
* @see java.lang.SecurityManager#currentClassLoader()
|
||||||
|
*/
|
||||||
private ClassLoader currentLoader()
|
private ClassLoader currentLoader()
|
||||||
{
|
{
|
||||||
SecurityManager sm = System.getSecurityManager ();
|
SecurityManager sm = System.getSecurityManager ();
|
||||||
|
@ -590,8 +642,8 @@ public class ObjectInputStream extends InputStream
|
||||||
* Reconstruct class hierarchy the same way
|
* Reconstruct class hierarchy the same way
|
||||||
* {@link java.io.ObjectStreamClass.getObjectStreamClasses(java.lang.Class)} does
|
* {@link java.io.ObjectStreamClass.getObjectStreamClasses(java.lang.Class)} does
|
||||||
* but using lookupClass instead of ObjectStreamClass.lookup. This
|
* but using lookupClass instead of ObjectStreamClass.lookup. This
|
||||||
* dup is necessary localize the lookup table. Hopefully some future rewritings will
|
* dup is necessary localize the lookup table. Hopefully some future
|
||||||
* be able to prevent this.
|
* rewritings will be able to prevent this.
|
||||||
*
|
*
|
||||||
* @param clazz This is the class for which we want the hierarchy.
|
* @param clazz This is the class for which we want the hierarchy.
|
||||||
*
|
*
|
||||||
|
@ -774,52 +826,142 @@ public class ObjectInputStream extends InputStream
|
||||||
|
|
||||||
public boolean readBoolean () throws IOException
|
public boolean readBoolean () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readBoolean ();
|
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
|
public byte readByte () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readByte ();
|
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
|
public int readUnsignedByte () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readUnsignedByte ();
|
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
|
public short readShort () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readShort ();
|
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
|
public int readUnsignedShort () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readUnsignedShort ();
|
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
|
public char readChar () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readChar ();
|
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
|
public int readInt () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readInt ();
|
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
|
public long readLong () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readLong ();
|
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
|
public float readFloat () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readFloat ();
|
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
|
public double readDouble () throws IOException
|
||||||
{
|
{
|
||||||
return this.dataInputStream.readDouble ();
|
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
|
public void readFully (byte data[]) throws IOException
|
||||||
|
@ -893,14 +1035,31 @@ public class ObjectInputStream extends InputStream
|
||||||
throws IOException, IllegalArgumentException;
|
throws IOException, IllegalArgumentException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should be called by a method called 'readObject' in the
|
||||||
|
* deserializing class (if present). It cannot (and should not)be called
|
||||||
|
* outside of it. Its goal is to read all fields in the real input stream
|
||||||
|
* and keep them accessible through the {@link #GetField} class. Calling
|
||||||
|
* this method will not alterate the deserializing object.
|
||||||
|
*
|
||||||
|
* @return A valid freshly created 'GetField' instance to get access to
|
||||||
|
* the deserialized stream.
|
||||||
|
* @throws IOException An input/output exception occured.
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws NotActiveException
|
||||||
|
*/
|
||||||
public GetField readFields ()
|
public GetField readFields ()
|
||||||
throws IOException, ClassNotFoundException, NotActiveException
|
throws IOException, ClassNotFoundException, NotActiveException
|
||||||
{
|
{
|
||||||
if (this.currentObject == null || this.currentObjectStreamClass == null)
|
if (this.currentObject == null || this.currentObjectStreamClass == null)
|
||||||
throw new NotActiveException ("readFields called by non-active class and/or object");
|
throw new NotActiveException ("readFields called by non-active class and/or object");
|
||||||
|
|
||||||
|
if (prereadFields != null)
|
||||||
|
return prereadFields;
|
||||||
|
|
||||||
if (fieldsAlreadyRead)
|
if (fieldsAlreadyRead)
|
||||||
throw new NotActiveException ("readFields called but fields already read from stream (by defaultReadObject or readFields)");
|
throw new NotActiveException ("readFields called but fields already read from"
|
||||||
|
+ " stream (by defaultReadObject or readFields)");
|
||||||
|
|
||||||
final ObjectStreamClass clazz = this.currentObjectStreamClass;
|
final ObjectStreamClass clazz = this.currentObjectStreamClass;
|
||||||
final byte[] prim_field_data = new byte[clazz.primFieldSize];
|
final byte[] prim_field_data = new byte[clazz.primFieldSize];
|
||||||
|
@ -915,7 +1074,7 @@ public class ObjectInputStream extends InputStream
|
||||||
objs[i] = readObject ();
|
objs[i] = readObject ();
|
||||||
setBlockDataMode (oldmode);
|
setBlockDataMode (oldmode);
|
||||||
|
|
||||||
return new GetField ()
|
prereadFields = new GetField()
|
||||||
{
|
{
|
||||||
public ObjectStreamClass getObjectStreamClass ()
|
public ObjectStreamClass getObjectStreamClass ()
|
||||||
{
|
{
|
||||||
|
@ -925,7 +1084,31 @@ public class ObjectInputStream extends InputStream
|
||||||
public boolean defaulted (String name)
|
public boolean defaulted (String name)
|
||||||
throws IOException, IllegalArgumentException
|
throws IOException, IllegalArgumentException
|
||||||
{
|
{
|
||||||
return clazz.getField (name) == null;
|
ObjectStreamField f = clazz.getField(name);
|
||||||
|
|
||||||
|
/* First if we have a serialized field use the descriptor */
|
||||||
|
if (f != null)
|
||||||
|
{
|
||||||
|
/* It is in serialPersistentFields but setClass tells us
|
||||||
|
* it should not be set. This value is defaulted.
|
||||||
|
*/
|
||||||
|
if (f.isPersistent() && !f.isToSet())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is not a serialized field. There should be
|
||||||
|
* a default value only if the field really exists.
|
||||||
|
*/
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (clazz.forClass().getDeclaredField (name) != null);
|
||||||
|
}
|
||||||
|
catch (NoSuchFieldException e)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException (e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean get (String name, boolean defvalue)
|
public boolean get (String name, boolean defvalue)
|
||||||
|
@ -1067,24 +1250,76 @@ public class ObjectInputStream extends InputStream
|
||||||
throws IllegalArgumentException
|
throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
ObjectStreamField field = clazz.getField (name);
|
ObjectStreamField field = clazz.getField (name);
|
||||||
|
boolean illegal = false;
|
||||||
|
|
||||||
if (field == null)
|
try
|
||||||
return null;
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
Class field_type = field.getType();
|
Class field_type = field.getType();
|
||||||
|
|
||||||
if (type == field_type ||
|
if (type == field_type ||
|
||||||
(type == null && !field_type.isPrimitive()))
|
(type == null && !field_type.isPrimitive()))
|
||||||
|
{
|
||||||
|
/* See defaulted */
|
||||||
return field;
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException ("Field requested is of type "
|
illegal = true;
|
||||||
|
throw new IllegalArgumentException
|
||||||
|
("Field requested is of type "
|
||||||
+ field_type.getName()
|
+ field_type.getName()
|
||||||
+ ", but requested type was "
|
+ ", but requested type was "
|
||||||
+ (type == null ?
|
+ (type == null ? "Object" : type.getName()));
|
||||||
"Object" : type.getName ()));
|
}
|
||||||
|
catch (NullPointerException _)
|
||||||
|
{
|
||||||
|
/* Here we catch NullPointerException, because it may
|
||||||
|
only come from the call 'field.getType()'. If field
|
||||||
|
is null, we have to return null and classpath ethic
|
||||||
|
say we must try to avoid 'if (xxx == null)'.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
/* If this is an unassigned field we should return
|
||||||
|
* the default value.
|
||||||
|
*/
|
||||||
|
if (!illegal && field != null && !field.isToSet() && field.isPersistent())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
/* We do not want to modify transient fields. They should
|
||||||
|
* be left to 0.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1334,6 +1569,15 @@ public class ObjectInputStream extends InputStream
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream_field.getOffset() < 0)
|
||||||
|
{
|
||||||
|
default_initialize = true;
|
||||||
|
set_value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream_field.isToSet())
|
||||||
|
set_value = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (type == Boolean.TYPE)
|
if (type == Boolean.TYPE)
|
||||||
|
@ -1485,10 +1729,24 @@ public class ObjectInputStream extends InputStream
|
||||||
return ClassLoader.getSystemClassLoader ();
|
return ClassLoader.getSystemClassLoader ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Field getField (Class klass, String name)
|
/**
|
||||||
|
* This method tries to access a precise field called in the
|
||||||
|
* specified class. Before accessing the field, it tries to
|
||||||
|
* gain control on this field. If the field is either declared as
|
||||||
|
* not persistent or transient then it returns null
|
||||||
|
* immediately.
|
||||||
|
*
|
||||||
|
* @param klass Class to get the field from.
|
||||||
|
* @param name Name of the field to access.
|
||||||
|
* @return Field instance representing the requested field.
|
||||||
|
* @throws NoSuchFieldException if the field does not exist.
|
||||||
|
*/
|
||||||
|
private Field getField(Class klass, String name)
|
||||||
throws java.lang.NoSuchFieldException
|
throws java.lang.NoSuchFieldException
|
||||||
{
|
{
|
||||||
final Field f = klass.getDeclaredField(name);
|
final Field f = klass.getDeclaredField(name);
|
||||||
|
ObjectStreamField sf = lookupClass(klass).getField(name);
|
||||||
|
|
||||||
AccessController.doPrivileged(new PrivilegedAction()
|
AccessController.doPrivileged(new PrivilegedAction()
|
||||||
{
|
{
|
||||||
public Object run()
|
public Object run()
|
||||||
|
@ -1497,6 +1755,14 @@ public class ObjectInputStream extends InputStream
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* We do not want to modify transient fields. They should
|
||||||
|
* be left to 0.
|
||||||
|
* N.B.: Not valid if the field is in serialPersistentFields.
|
||||||
|
*/
|
||||||
|
if (Modifier.isTransient(f.getModifiers()) && !sf.isPersistent())
|
||||||
|
return null;
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1546,6 +1812,9 @@ public class ObjectInputStream extends InputStream
|
||||||
throw new IOException ("Failure invoking readObject() on " +
|
throw new IOException ("Failure invoking readObject() on " +
|
||||||
klass + ": " + x.getClass().getName());
|
klass + ": " + x.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invalidate fields which has been read through readFields.
|
||||||
|
prereadFields = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private native Object allocateObject (Class clazz)
|
private native Object allocateObject (Class clazz)
|
||||||
|
@ -1829,6 +2098,7 @@ public class ObjectInputStream extends InputStream
|
||||||
private boolean fieldsAlreadyRead;
|
private boolean fieldsAlreadyRead;
|
||||||
private Vector validators;
|
private Vector validators;
|
||||||
private Hashtable classLookupTable;
|
private Hashtable classLookupTable;
|
||||||
|
private GetField prereadFields;
|
||||||
|
|
||||||
private static boolean dump;
|
private static boolean dump;
|
||||||
|
|
||||||
|
|
|
@ -407,7 +407,8 @@ public class ObjectOutputStream extends OutputStream
|
||||||
setBlockDataMode (oldmode);
|
setBlockDataMode (oldmode);
|
||||||
realOutput.writeByte (TC_ENDBLOCKDATA);
|
realOutput.writeByte (TC_ENDBLOCKDATA);
|
||||||
|
|
||||||
if (osc.isSerializable ())
|
if (osc.isSerializable()
|
||||||
|
|| osc.isExternalizable())
|
||||||
writeObject (osc.getSuper ());
|
writeObject (osc.getSuper ());
|
||||||
else
|
else
|
||||||
writeObject (null);
|
writeObject (null);
|
||||||
|
|
|
@ -516,11 +516,14 @@ public class ObjectStreamClass implements Serializable
|
||||||
&& Modifier.isPrivate (modifiers))
|
&& Modifier.isPrivate (modifiers))
|
||||||
{
|
{
|
||||||
fields = getSerialPersistentFields (cl);
|
fields = getSerialPersistentFields (cl);
|
||||||
|
if (fields != null)
|
||||||
|
{
|
||||||
Arrays.sort(fields);
|
Arrays.sort(fields);
|
||||||
calculateOffsets();
|
calculateOffsets();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (NoSuchFieldException ignore)
|
catch (NoSuchFieldException ignore)
|
||||||
{}
|
{}
|
||||||
catch (IllegalAccessException ignore)
|
catch (IllegalAccessException ignore)
|
||||||
|
@ -700,16 +703,41 @@ public class ObjectStreamClass implements Serializable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the value of CLAZZ's private static final field named
|
/**
|
||||||
// `serialPersistentFields'.
|
* Returns the value of CLAZZ's private static final field named
|
||||||
|
* `serialPersistentFields'. It performs some sanity checks before
|
||||||
|
* returning the real array. Besides, the returned array is a clean
|
||||||
|
* copy of the original. So it can be modified.
|
||||||
|
*
|
||||||
|
* @param clazz Class to retrieve 'serialPersistentFields' from.
|
||||||
|
* @return The content of 'serialPersistentFields'.
|
||||||
|
*/
|
||||||
private ObjectStreamField[] getSerialPersistentFields (Class clazz)
|
private ObjectStreamField[] getSerialPersistentFields (Class clazz)
|
||||||
throws NoSuchFieldException, IllegalAccessException
|
throws NoSuchFieldException, IllegalAccessException
|
||||||
{
|
{
|
||||||
|
ObjectStreamField[] fieldsArray = null;
|
||||||
|
ObjectStreamField[] o;
|
||||||
|
|
||||||
// Use getDeclaredField rather than getField for the same reason
|
// Use getDeclaredField rather than getField for the same reason
|
||||||
// as above in getDefinedSUID.
|
// as above in getDefinedSUID.
|
||||||
Field f = clazz.getDeclaredField("serialPersistentFields");
|
Field f = clazz.getDeclaredField("serialPersistentFields");
|
||||||
f.setAccessible(true);
|
f.setAccessible(true);
|
||||||
return (ObjectStreamField[]) f.get(null);
|
|
||||||
|
int modifiers = f.getModifiers();
|
||||||
|
if (!(Modifier.isStatic(modifiers)
|
||||||
|
&& Modifier.isFinal(modifiers)
|
||||||
|
&& Modifier.isPrivate(modifiers)))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
o = (ObjectStreamField[]) f.get(null);
|
||||||
|
|
||||||
|
if (o == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
fieldsArray = new ObjectStreamField[o.length];
|
||||||
|
System.arraycopy(o, 0, fieldsArray, 0, o.length);
|
||||||
|
|
||||||
|
return fieldsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final ObjectStreamField[] NO_FIELDS = {};
|
public static final ObjectStreamField[] NO_FIELDS = {};
|
||||||
|
|
Loading…
Reference in New Issue