aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/io/ObjectStreamClass.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/io/ObjectStreamClass.java')
-rw-r--r--libjava/java/io/ObjectStreamClass.java819
1 files changed, 466 insertions, 353 deletions
diff --git a/libjava/java/io/ObjectStreamClass.java b/libjava/java/io/ObjectStreamClass.java
index 3a2ccfb8e99..5bd0e686625 100644
--- a/libjava/java/io/ObjectStreamClass.java
+++ b/libjava/java/io/ObjectStreamClass.java
@@ -2,39 +2,39 @@
about serialized objects.
Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
-This file is part of GNU Classpath.
+ This file is part of GNU Classpath.
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
package java.io;
@@ -61,23 +61,23 @@ import gnu.java.security.provider.Gnu;
public class ObjectStreamClass implements Serializable
{
/**
- Returns the <code>ObjectStreamClass</code> for <code>cl</code>.
- If <code>cl</code> is null, or is not <code>Serializable</code>,
- null is returned. <code>ObjectStreamClass</code>'s are memorized;
- later calls to this method with the same class will return the
- same <code>ObjectStreamClass</code> object and no recalculation
- will be done.
-
- @see java.io.Serializable
- */
- public static ObjectStreamClass lookup (Class cl)
+ * Returns the <code>ObjectStreamClass</code> for <code>cl</code>.
+ * If <code>cl</code> is null, or is not <code>Serializable</code>,
+ * null is returned. <code>ObjectStreamClass</code>'s are memorized;
+ * later calls to this method with the same class will return the
+ * same <code>ObjectStreamClass</code> object and no recalculation
+ * will be done.
+ *
+ * @see java.io.Serializable
+ */
+ public static ObjectStreamClass lookup(Class cl)
{
if (cl == null)
return null;
- if (! (Serializable.class).isAssignableFrom (cl))
+ if (! (Serializable.class).isAssignableFrom(cl))
return null;
- return lookupForClassObject (cl);
+ return lookupForClassObject(cl);
}
/**
@@ -85,57 +85,57 @@ public class ObjectStreamClass implements Serializable
* we have a java.lang.Class object C for class A, though A is not
* serializable, but it's okay to serialize C.
*/
- static ObjectStreamClass lookupForClassObject (Class cl)
+ static ObjectStreamClass lookupForClassObject(Class cl)
{
if (cl == null)
return null;
- ObjectStreamClass osc = (ObjectStreamClass)classLookupTable.get (cl);
+ ObjectStreamClass osc = (ObjectStreamClass) classLookupTable.get(cl);
if (osc != null)
return osc;
else
- {
- osc = new ObjectStreamClass (cl);
- classLookupTable.put (cl, osc);
- return osc;
- }
+ {
+ osc = new ObjectStreamClass(cl);
+ classLookupTable.put(cl, osc);
+ return osc;
+ }
}
/**
- Returns the name of the class that this
- <code>ObjectStreamClass</code> represents.
- */
- public String getName ()
+ * Returns the name of the class that this
+ * <code>ObjectStreamClass</code> represents.
+ */
+ public String getName()
{
return name;
}
/**
- Returns the class that this <code>ObjectStreamClass</code>
- represents. Null could be returned if this
- <code>ObjectStreamClass</code> was read from an
- <code>ObjectInputStream</code> and the class it represents cannot
- be found or loaded.
-
- @see java.io.ObjectInputStream
- */
- public Class forClass ()
+ * Returns the class that this <code>ObjectStreamClass</code>
+ * represents. Null could be returned if this
+ * <code>ObjectStreamClass</code> was read from an
+ * <code>ObjectInputStream</code> and the class it represents cannot
+ * be found or loaded.
+ *
+ * @see java.io.ObjectInputStream
+ */
+ public Class forClass()
{
return clazz;
}
/**
- Returns the serial version stream-unique identifier for the class
- represented by this <code>ObjectStreamClass</code>. This SUID is
- either defined by the class as <code>static final long
- serialVersionUID</code> or is calculated as specified in
- Javasoft's "Object Serialization Specification" XXX: add reference
- */
- public long getSerialVersionUID ()
+ * Returns the serial version stream-unique identifier for the class
+ * represented by this <code>ObjectStreamClass</code>. This SUID is
+ * either defined by the class as <code>static final long
+ * serialVersionUID</code> or is calculated as specified in
+ * Javasoft's "Object Serialization Specification" XXX: add reference
+ */
+ public long getSerialVersionUID()
{
return uid;
}
@@ -145,10 +145,10 @@ public class ObjectStreamClass implements Serializable
// of the class represented by this ObjectStreamClass. The Fields
// are sorted by name.
// XXX doc
- public ObjectStreamField[] getFields ()
+ public ObjectStreamField[] getFields()
{
ObjectStreamField[] copy = new ObjectStreamField[ fields.length ];
- System.arraycopy (fields, 0, copy, 0, fields.length);
+ System.arraycopy(fields, 0, copy, 0, fields.length);
return copy;
}
@@ -158,8 +158,8 @@ public class ObjectStreamClass implements Serializable
// primitiveness.
public ObjectStreamField getField (String name)
{
- for (int i=0; i < fields.length; i++)
- if (fields[i].getName ().equals (name))
+ for (int i = 0; i < fields.length; i++)
+ if (fields[i].getName().equals(name))
return fields[i];
return null;
}
@@ -174,7 +174,7 @@ public class ObjectStreamClass implements Serializable
* @see #getSerialVersionUID()
* @see #getName()
*/
- public String toString ()
+ public String toString()
{
return "java.io.ObjectStreamClass< " + name + ", " + uid + " >";
}
@@ -187,7 +187,7 @@ public class ObjectStreamClass implements Serializable
//
// This method is used by the class to override default
// serialization behavior.
- boolean hasWriteMethod ()
+ boolean hasWriteMethod()
{
return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0;
}
@@ -200,24 +200,24 @@ public class ObjectStreamClass implements Serializable
//
// This method is used by the class to override default
// serialization behavior.
- boolean hasReadMethod ()
+ boolean hasReadMethod()
{
- try
+ try
{
- Class[] readObjectParams = { ObjectInputStream.class };
- forClass ().getDeclaredMethod ("readObject", readObjectParams);
- return true;
+ Class[] readObjectParams = { ObjectInputStream.class };
+ forClass().getDeclaredMethod("readObject", readObjectParams);
+ return true;
}
- catch (NoSuchMethodException e)
+ catch (NoSuchMethodException e)
{
- return false;
+ return false;
}
}
// Returns true iff the class that this ObjectStreamClass represents
// implements Serializable but does *not* implement Externalizable.
- boolean isSerializable ()
+ boolean isSerializable()
{
return (flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0;
}
@@ -225,7 +225,7 @@ public class ObjectStreamClass implements Serializable
// Returns true iff the class that this ObjectStreamClass represents
// implements Externalizable.
- boolean isExternalizable ()
+ boolean isExternalizable()
{
return (flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0;
}
@@ -235,7 +235,7 @@ public class ObjectStreamClass implements Serializable
// class that is the superclass of the class this
// <code>ObjectStreamClass</code> represents. If the superclass is
// not Serializable, null is returned.
- ObjectStreamClass getSuper ()
+ ObjectStreamClass getSuper()
{
return superClass;
}
@@ -245,30 +245,30 @@ public class ObjectStreamClass implements Serializable
// classes of CLAZZ and CLAZZ itself in order from most super to
// CLAZZ. ObjectStreamClass[0] is the highest superclass of CLAZZ
// that is serializable.
- static ObjectStreamClass[] getObjectStreamClasses (Class clazz)
+ static ObjectStreamClass[] getObjectStreamClasses(Class clazz)
{
- ObjectStreamClass osc = ObjectStreamClass.lookup (clazz);
+ ObjectStreamClass osc = ObjectStreamClass.lookup(clazz);
if (osc == null)
return new ObjectStreamClass[0];
else
- {
- Vector oscs = new Vector ();
-
- while (osc != null)
{
- oscs.addElement (osc);
- osc = osc.getSuper ();
- }
+ Vector oscs = new Vector();
- int count = oscs.size ();
- ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[ count ];
+ while (osc != null)
+ {
+ oscs.addElement (osc);
+ osc = osc.getSuper();
+ }
- for (int i = count - 1; i >= 0; i--)
- sorted_oscs[ count - i - 1 ] = (ObjectStreamClass)oscs.elementAt (i);
+ int count = oscs.size();
+ ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[ count ];
- return sorted_oscs;
- }
+ for (int i = count - 1; i >= 0; i--)
+ sorted_oscs[ count - i - 1 ] = (ObjectStreamClass) oscs.elementAt(i);
+
+ return sorted_oscs;
+ }
}
@@ -276,14 +276,14 @@ public class ObjectStreamClass implements Serializable
// properties of the class represented by this ObjectStreamClass.
// The bit-flags that could be present are those defined in
// ObjectStreamConstants that begin with `SC_'
- int getFlags ()
+ int getFlags()
{
return flags;
}
- ObjectStreamClass (String name, long uid, byte flags,
- ObjectStreamField[] fields)
+ ObjectStreamClass(String name, long uid, byte flags,
+ ObjectStreamField[] fields)
{
this.name = name;
this.uid = uid;
@@ -291,11 +291,22 @@ public class ObjectStreamClass implements Serializable
this.fields = fields;
}
- void setClass (Class cl) throws InvalidClassException
+ /**
+ * This method builds the internal description corresponding to a Java Class.
+ * As the constructor only assign a name to the current ObjectStreamClass instance,
+ * that method sets the serial UID, chose the fields which will be serialized,
+ * and compute the position of the fields in the serialized stream.
+ *
+ * @param cl The Java class which is used as a reference for building the descriptor.
+ * @param superClass The descriptor of the super class for this class descriptor.
+ * @throws InvalidClassException if an incompatibility between computed UID and
+ * already set UID is found.
+ */
+ void setClass(Class cl, ObjectStreamClass superClass) throws InvalidClassException
{
this.clazz = cl;
- long class_uid = getClassUID (cl);
+ long class_uid = getClassUID(cl);
if (uid == 0)
uid = class_uid;
else
@@ -311,12 +322,90 @@ public class ObjectStreamClass implements Serializable
}
}
- isProxyClass = clazz != null && Proxy.isProxyClass (clazz);
- ObjectStreamClass osc = (ObjectStreamClass)classLookupTable.get (clazz);
- if (osc == null)
- classLookupTable.put (clazz, this);
- superClass = lookupForClassObject (clazz.getSuperclass ());
- calculateOffsets ();
+ isProxyClass = clazz != null && Proxy.isProxyClass(clazz);
+ this.superClass = superClass;
+ calculateOffsets();
+
+ try
+ {
+ ObjectStreamField[] exportedFields = getSerialPersistentFields (clazz);
+
+ if (exportedFields == null)
+ return;
+
+ ObjectStreamField[] newFieldList = new ObjectStreamField[exportedFields.length + fields.length];
+ int i, j, k;
+
+ /* We now check the import fields against the exported fields.
+ * There should not be contradiction (e.g. int x and String x)
+ * but extra virtual fields can be added to the class.
+ */
+
+ Arrays.sort(exportedFields);
+
+ i = 0; j = 0; k = 0;
+ while (i < fields.length && j < exportedFields.length)
+ {
+ int comp = fields[i].getName().compareTo(exportedFields[j].getName());
+
+ if (comp < 0)
+ {
+ newFieldList[k] = fields[i];
+ fields[i].setPersistent(false);
+ fields[i].setToSet(false);
+ i++;
+ }
+ else if (comp > 0)
+ {
+ /* field not found in imported fields. We add it
+ * in the list of supported fields.
+ */
+ newFieldList[k] = exportedFields[j];
+ newFieldList[k].setPersistent(true);
+ newFieldList[k].setToSet(false);
+ j++;
+ }
+ else
+ {
+ if (!fields[i].getType().equals(exportedFields[j].getType()))
+ throw new InvalidClassException
+ ("serialPersistentFields must be compatible with" +
+ " imported fields (about " + fields[i].getName() + ")");
+ newFieldList[k] = fields[i];
+ fields[i].setPersistent(true);
+ i++;
+ j++;
+ }
+ k++;
+ }
+
+ if (i < fields.length)
+ for (;i<fields.length;i++,k++)
+ {
+ fields[i].setPersistent(false);
+ fields[i].setToSet(false);
+ newFieldList[k] = fields[i];
+ }
+ else
+ if (j < exportedFields.length)
+ for (;j<exportedFields.length;j++,k++)
+ {
+ exportedFields[j].setPersistent(true);
+ exportedFields[j].setToSet(false);
+ newFieldList[k] = exportedFields[j];
+ }
+
+ fields = new ObjectStreamField[k];
+ System.arraycopy(newFieldList, 0, fields, 0, k);
+ }
+ catch (NoSuchFieldException ignore)
+ {
+ return;
+ }
+ catch (IllegalAccessException ignore)
+ {
+ return;
+ }
}
void setSuperclass (ObjectStreamClass osc)
@@ -324,321 +413,345 @@ public class ObjectStreamClass implements Serializable
superClass = osc;
}
-
- void calculateOffsets ()
+ void calculateOffsets()
{
int i;
ObjectStreamField field;
primFieldSize = 0;
int fcount = fields.length;
for (i = 0; i < fcount; ++ i)
- {
- field = fields[i];
-
- if (! field.isPrimitive ())
- break;
-
- field.setOffset (primFieldSize);
- switch (field.getTypeCode ())
{
- case 'B':
- case 'Z':
- ++ primFieldSize;
- break;
- case 'C':
- case 'S':
- primFieldSize += 2;
- break;
- case 'I':
- case 'F':
- primFieldSize += 4;
- break;
- case 'D':
- case 'J':
- primFieldSize += 8;
+ field = fields[i];
+
+ if (! field.isPrimitive())
break;
+
+ field.setOffset(primFieldSize);
+ switch (field.getTypeCode())
+ {
+ case 'B':
+ case 'Z':
+ ++ primFieldSize;
+ break;
+ case 'C':
+ case 'S':
+ primFieldSize += 2;
+ break;
+ case 'I':
+ case 'F':
+ primFieldSize += 4;
+ break;
+ case 'D':
+ case 'J':
+ primFieldSize += 8;
+ break;
+ }
}
- }
for (objectFieldCount = 0; i < fcount; ++ i)
- fields[i].setOffset (objectFieldCount++);
+ fields[i].setOffset(objectFieldCount++);
}
- private ObjectStreamClass (Class cl)
+ private ObjectStreamClass(Class cl)
{
uid = 0;
flags = 0;
- isProxyClass = Proxy.isProxyClass (cl);
+ isProxyClass = Proxy.isProxyClass(cl);
clazz = cl;
- name = cl.getName ();
- setFlags (cl);
- setFields (cl);
+ name = cl.getName();
+ setFlags(cl);
+ setFields(cl);
// to those class nonserializable, its uid field is 0
- if ( (Serializable.class).isAssignableFrom (cl) && !isProxyClass)
- uid = getClassUID (cl);
- superClass = lookup (cl.getSuperclass ());
+ if ( (Serializable.class).isAssignableFrom(cl) && !isProxyClass)
+ uid = getClassUID(cl);
+ superClass = lookup(cl.getSuperclass());
}
// Sets bits in flags according to features of CL.
- private void setFlags (Class cl)
+ private void setFlags(Class cl)
{
- if ((java.io.Externalizable.class).isAssignableFrom (cl))
+ if ((java.io.Externalizable.class).isAssignableFrom(cl))
flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
- else if ((java.io.Serializable.class).isAssignableFrom (cl))
+ else if ((java.io.Serializable.class).isAssignableFrom(cl))
// only set this bit if CL is NOT Externalizable
flags |= ObjectStreamConstants.SC_SERIALIZABLE;
try
- {
- Method writeMethod = cl.getDeclaredMethod ("writeObject",
- writeMethodArgTypes);
- int modifiers = writeMethod.getModifiers ();
-
- if (writeMethod.getReturnType () == Void.TYPE
- && Modifier.isPrivate (modifiers)
- && !Modifier.isStatic (modifiers))
- flags |= ObjectStreamConstants.SC_WRITE_METHOD;
- }
- catch (NoSuchMethodException oh_well)
- {}
+ {
+ Method writeMethod = cl.getDeclaredMethod("writeObject",
+ writeMethodArgTypes);
+ int modifiers = writeMethod.getModifiers();
+
+ if (writeMethod.getReturnType() == Void.TYPE
+ && Modifier.isPrivate(modifiers)
+ && !Modifier.isStatic(modifiers))
+ flags |= ObjectStreamConstants.SC_WRITE_METHOD;
+ }
+ catch(NoSuchMethodException oh_well)
+ {
+ }
}
// Sets fields to be a sorted array of the serializable fields of
// clazz.
- private void setFields (Class cl)
+ private void setFields(Class cl)
{
- if (! isSerializable () || isExternalizable ())
- {
- fields = NO_FIELDS;
- return;
- }
+ if (!isSerializable() || isExternalizable())
+ {
+ fields = NO_FIELDS;
+ return;
+ }
try
- {
- Field serialPersistentFields
- = cl.getDeclaredField ("serialPersistentFields");
- serialPersistentFields.setAccessible(true);
- int modifiers = serialPersistentFields.getModifiers ();
-
- if (Modifier.isStatic (modifiers)
- && Modifier.isFinal (modifiers)
- && Modifier.isPrivate (modifiers))
{
- fields = getSerialPersistentFields (cl);
- Arrays.sort (fields);
- calculateOffsets ();
- return;
+ Field serialPersistentFields =
+ cl.getDeclaredField("serialPersistentFields");
+ serialPersistentFields.setAccessible(true);
+ int modifiers = serialPersistentFields.getModifiers();
+
+ if (Modifier.isStatic(modifiers)
+ && Modifier.isFinal(modifiers)
+ && Modifier.isPrivate(modifiers))
+ {
+ fields = getSerialPersistentFields(cl);
+ if (fields != null)
+ {
+ Arrays.sort (fields);
+ calculateOffsets();
+ return;
+ }
+ }
}
- }
catch (NoSuchFieldException ignore)
- {}
+ {
+ }
+ catch (IllegalAccessException ignore)
+ {
+ }
int num_good_fields = 0;
- Field[] all_fields = cl.getDeclaredFields ();
+ Field[] all_fields = cl.getDeclaredFields();
int modifiers;
// set non-serializable fields to null in all_fields
- for (int i=0; i < all_fields.length; i++)
- {
- modifiers = all_fields[i].getModifiers ();
- if (Modifier.isTransient (modifiers)
- || Modifier.isStatic (modifiers))
- all_fields[i] = null;
- else
- num_good_fields++;
- }
+ for (int i = 0; i < all_fields.length; i++)
+ {
+ modifiers = all_fields[i].getModifiers();
+ if (Modifier.isTransient(modifiers)
+ || Modifier.isStatic(modifiers))
+ all_fields[i] = null;
+ else
+ num_good_fields++;
+ }
// make a copy of serializable (non-null) fields
fields = new ObjectStreamField[ num_good_fields ];
- for (int from=0, to=0; from < all_fields.length; from++)
+ for (int from = 0, to = 0; from < all_fields.length; from++)
if (all_fields[from] != null)
- {
- Field f = all_fields[from];
- fields[to] = new ObjectStreamField (f.getName (), f.getType ());
- to++;
- }
+ {
+ Field f = all_fields[from];
+ fields[to] = new ObjectStreamField(f.getName(), f.getType());
+ to++;
+ }
- Arrays.sort (fields);
- calculateOffsets ();
+ Arrays.sort(fields);
+ calculateOffsets();
}
// Returns the serial version UID defined by class, or if that
// isn't present, calculates value of serial version UID.
- private long getClassUID (Class cl)
+ private long getClassUID(Class cl)
{
try
- {
- // Use getDeclaredField rather than getField, since serialVersionUID
- // may not be public AND we only want the serialVersionUID of this
- // class, not a superclass or interface.
- Field suid = cl.getDeclaredField ("serialVersionUID");
- suid.setAccessible(true);
- int modifiers = suid.getModifiers ();
-
- if (Modifier.isStatic (modifiers)
- && Modifier.isFinal (modifiers)
- && suid.getType() == Long.TYPE)
- return suid.getLong (null);
- }
+ {
+ // Use getDeclaredField rather than getField, since serialVersionUID
+ // may not be public AND we only want the serialVersionUID of this
+ // class, not a superclass or interface.
+ Field suid = cl.getDeclaredField("serialVersionUID");
+ suid.setAccessible(true);
+ int modifiers = suid.getModifiers();
+
+ if (Modifier.isStatic(modifiers)
+ && Modifier.isFinal(modifiers)
+ && suid.getType() == Long.TYPE)
+ return suid.getLong(null);
+ }
catch (NoSuchFieldException ignore)
- {}
+ {
+ }
catch (IllegalAccessException ignore)
- {}
+ {
+ }
// cl didn't define serialVersionUID, so we have to compute it
try
- {
- MessageDigest md;
- try
- {
- md = MessageDigest.getInstance ("SHA");
- }
- catch (NoSuchAlgorithmException e)
- {
- // If a provider already provides SHA, use it; otherwise, use this.
- Gnu gnuProvider = new Gnu();
- Security.addProvider(gnuProvider);
- md = MessageDigest.getInstance ("SHA");
- }
-
- DigestOutputStream digest_out =
- new DigestOutputStream (nullOutputStream, md);
- DataOutputStream data_out = new DataOutputStream (digest_out);
+ {
+ MessageDigest md;
+ try
+ {
+ md = MessageDigest.getInstance("SHA");
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // If a provider already provides SHA, use it; otherwise, use this.
+ Gnu gnuProvider = new Gnu();
+ Security.addProvider(gnuProvider);
+ md = MessageDigest.getInstance("SHA");
+ }
- data_out.writeUTF (cl.getName ());
+ DigestOutputStream digest_out =
+ new DigestOutputStream(nullOutputStream, md);
+ DataOutputStream data_out = new DataOutputStream(digest_out);
- int modifiers = cl.getModifiers ();
- // just look at interesting bits
- modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
- | Modifier.INTERFACE | Modifier.PUBLIC);
- data_out.writeInt (modifiers);
+ data_out.writeUTF(cl.getName());
- // Pretend that an array has no interfaces, because when array
- // serialization was defined (JDK 1.1), arrays didn't have it.
- if (! cl.isArray ())
- {
- Class[] interfaces = cl.getInterfaces ();
- Arrays.sort (interfaces, interfaceComparator);
- for (int i=0; i < interfaces.length; i++)
- data_out.writeUTF (interfaces[i].getName ());
- }
+ int modifiers = cl.getModifiers();
+ // just look at interesting bits
+ modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
+ | Modifier.INTERFACE | Modifier.PUBLIC);
+ data_out.writeInt(modifiers);
- Field field;
- Field[] fields = cl.getDeclaredFields ();
- Arrays.sort (fields, memberComparator);
- for (int i=0; i < fields.length; i++)
- {
- field = fields[i];
- modifiers = field.getModifiers ();
- if (Modifier.isPrivate (modifiers)
- && (Modifier.isStatic (modifiers)
- || Modifier.isTransient (modifiers)))
- continue;
-
- data_out.writeUTF (field.getName ());
- data_out.writeInt (modifiers);
- data_out.writeUTF (TypeSignature.getEncodingOfClass (field.getType ()));
- }
+ // Pretend that an array has no interfaces, because when array
+ // serialization was defined (JDK 1.1), arrays didn't have it.
+ if (! cl.isArray())
+ {
+ Class[] interfaces = cl.getInterfaces();
+ Arrays.sort(interfaces, interfaceComparator);
+ for (int i = 0; i < interfaces.length; i++)
+ data_out.writeUTF(interfaces[i].getName());
+ }
- // write class initializer method if present
- if (VMObjectStreamClass.hasClassInitializer (cl))
- {
- data_out.writeUTF ("<clinit>");
- data_out.writeInt (Modifier.STATIC);
- data_out.writeUTF ("()V");
- }
+ Field field;
+ Field[] fields = cl.getDeclaredFields();
+ Arrays.sort(fields, memberComparator);
+ for (int i = 0; i < fields.length; i++)
+ {
+ field = fields[i];
+ modifiers = field.getModifiers();
+ if (Modifier.isPrivate(modifiers)
+ && (Modifier.isStatic(modifiers)
+ || Modifier.isTransient(modifiers)))
+ continue;
+
+ data_out.writeUTF(field.getName());
+ data_out.writeInt(modifiers);
+ data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
+ }
- Constructor constructor;
- Constructor[] constructors = cl.getDeclaredConstructors ();
- Arrays.sort (constructors, memberComparator);
- for (int i=0; i < constructors.length; i++)
- {
- constructor = constructors[i];
- modifiers = constructor.getModifiers ();
- if (Modifier.isPrivate (modifiers))
- continue;
-
- data_out.writeUTF ("<init>");
- data_out.writeInt (modifiers);
-
- // the replacement of '/' with '.' was needed to make computed
- // SUID's agree with those computed by JDK
- data_out.writeUTF (
- TypeSignature.getEncodingOfConstructor (constructor).replace ('/','.'));
- }
+ // write class initializer method if present
+ if (VMObjectStreamClass.hasClassInitializer(cl))
+ {
+ data_out.writeUTF("<clinit>");
+ data_out.writeInt(Modifier.STATIC);
+ data_out.writeUTF("()V");
+ }
- Method method;
- Method[] methods = cl.getDeclaredMethods ();
- Arrays.sort (methods, memberComparator);
- for (int i=0; i < methods.length; i++)
- {
- method = methods[i];
- modifiers = method.getModifiers ();
- if (Modifier.isPrivate (modifiers))
- continue;
-
- data_out.writeUTF (method.getName ());
- data_out.writeInt (modifiers);
-
- // the replacement of '/' with '.' was needed to make computed
- // SUID's agree with those computed by JDK
- data_out.writeUTF (
- TypeSignature.getEncodingOfMethod (method).replace ('/', '.'));
- }
+ Constructor constructor;
+ Constructor[] constructors = cl.getDeclaredConstructors();
+ Arrays.sort (constructors, memberComparator);
+ for (int i = 0; i < constructors.length; i++)
+ {
+ constructor = constructors[i];
+ modifiers = constructor.getModifiers();
+ if (Modifier.isPrivate(modifiers))
+ continue;
+
+ data_out.writeUTF("<init>");
+ data_out.writeInt(modifiers);
+
+ // the replacement of '/' with '.' was needed to make computed
+ // SUID's agree with those computed by JDK
+ data_out.writeUTF
+ (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
+ }
- data_out.close ();
- byte[] sha = md.digest ();
- long result = 0;
- int len = sha.length < 8 ? sha.length : 8;
- for (int i=0; i < len; i++)
- result += (long)(sha[i] & 0xFF) << (8 * i);
+ Method method;
+ Method[] methods = cl.getDeclaredMethods();
+ Arrays.sort(methods, memberComparator);
+ for (int i = 0; i < methods.length; i++)
+ {
+ method = methods[i];
+ modifiers = method.getModifiers();
+ if (Modifier.isPrivate(modifiers))
+ continue;
+
+ data_out.writeUTF(method.getName());
+ data_out.writeInt(modifiers);
+
+ // the replacement of '/' with '.' was needed to make computed
+ // SUID's agree with those computed by JDK
+ data_out.writeUTF
+ (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
+ }
- return result;
- }
- catch (NoSuchAlgorithmException e)
- {
- throw new RuntimeException ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
- + cl.getName (), e);
- }
- catch (IOException ioe)
- {
- throw new RuntimeException (ioe);
- }
- }
+ data_out.close();
+ byte[] sha = md.digest();
+ long result = 0;
+ int len = sha.length < 8 ? sha.length : 8;
+ for (int i = 0; i < len; i++)
+ result += (long) (sha[i] & 0xFF) << (8 * i);
- // Returns the value of CLAZZ's private static final field named
- // `serialPersistentFields'.
- private ObjectStreamField[] getSerialPersistentFields (Class clazz)
- {
- ObjectStreamField[] o = null;
- try
- {
- // Use getDeclaredField rather than getField for the same reason
- // as above in getDefinedSUID.
- Field f = clazz.getDeclaredField ("serialPersistentFields");
- f.setAccessible(true);
- o = (ObjectStreamField[])f.get (null);
+ return result;
}
- catch (java.lang.NoSuchFieldException e)
+ catch (NoSuchAlgorithmException e)
{
+ throw new RuntimeException
+ ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
+ + cl.getName(), e);
}
- catch (java.lang.IllegalAccessException e)
+ catch (IOException ioe)
{
+ throw new RuntimeException(ioe);
}
+ }
+
+ /**
+ * 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)
+ throws NoSuchFieldException, IllegalAccessException
+ {
+ ObjectStreamField[] fieldsArray = null;
+ ObjectStreamField[] o;
+
+ // Use getDeclaredField rather than getField for the same reason
+ // as above in getDefinedSUID.
+ Field f = clazz.getDeclaredField("serialPersistentFields");
+ f.setAccessible(true);
+
+ 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;
- return o;
+ fieldsArray = new ObjectStreamField[ o.length ];
+ System.arraycopy(o, 0, fieldsArray, 0, o.length);
+
+ return fieldsArray;
}
public static final ObjectStreamField[] NO_FIELDS = {};
- private static Hashtable classLookupTable = new Hashtable ();
- private static final NullOutputStream nullOutputStream = new NullOutputStream ();
- private static final Comparator interfaceComparator = new InterfaceComparator ();
- private static final Comparator memberComparator = new MemberComparator ();
+ private static Hashtable classLookupTable = new Hashtable();
+ private static final NullOutputStream nullOutputStream = new NullOutputStream();
+ private static final Comparator interfaceComparator = new InterfaceComparator();
+ private static final Comparator memberComparator = new MemberComparator();
private static final
Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };
@@ -668,9 +781,9 @@ public class ObjectStreamClass implements Serializable
// interfaces are compared only by name
class InterfaceComparator implements Comparator
{
- public int compare (Object o1, Object o2)
+ public int compare(Object o1, Object o2)
{
- return ((Class)o1).getName ().compareTo (((Class)o2).getName ());
+ return ((Class) o1).getName().compareTo(((Class) o2).getName());
}
}
@@ -679,16 +792,16 @@ class InterfaceComparator implements Comparator
// conflicts are resolved by comparing type signatures
class MemberComparator implements Comparator
{
- public int compare (Object o1, Object o2)
+ public int compare(Object o1, Object o2)
{
- Member m1 = (Member)o1;
- Member m2 = (Member)o2;
+ Member m1 = (Member) o1;
+ Member m2 = (Member) o2;
- int comp = m1.getName ().compareTo (m2.getName ());
+ int comp = m1.getName().compareTo(m2.getName());
if (comp == 0)
- return TypeSignature.getEncodingOfMember (m1).
- compareTo (TypeSignature.getEncodingOfMember (m2));
+ return TypeSignature.getEncodingOfMember(m1).
+ compareTo(TypeSignature.getEncodingOfMember(m2));
else
return comp;
}