mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			673 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			673 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
	
/* ObjectStreamClass.java -- Class used to write class information
 | 
						|
   about serialized objects.
 | 
						|
   Copyright (C) 1998, 1999, 2000  Free Software Foundation, Inc.
 | 
						|
 | 
						|
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 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.
 | 
						|
 | 
						|
As a special exception, if you link this library with other files to
 | 
						|
produce an executable, this library does not by itself cause the
 | 
						|
resulting executable to be covered by the GNU General Public License.
 | 
						|
This exception does not however invalidate any other reasons why the
 | 
						|
executable file might be covered by the GNU General Public License. */
 | 
						|
 | 
						|
 | 
						|
package java.io;
 | 
						|
 | 
						|
import java.lang.reflect.Constructor;
 | 
						|
import java.lang.reflect.Field;
 | 
						|
import java.lang.reflect.Member;
 | 
						|
import java.lang.reflect.Method;
 | 
						|
import java.lang.reflect.Modifier;
 | 
						|
import java.security.DigestOutputStream;
 | 
						|
import java.security.MessageDigest;
 | 
						|
import java.security.NoSuchAlgorithmException;
 | 
						|
import java.security.Security;
 | 
						|
import java.util.Arrays;
 | 
						|
import java.util.Comparator;
 | 
						|
import java.util.Hashtable;
 | 
						|
import java.util.Vector;
 | 
						|
import gnu.java.io.NullOutputStream;
 | 
						|
import gnu.java.lang.reflect.TypeSignature;
 | 
						|
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)
 | 
						|
  {
 | 
						|
    if (cl == null)
 | 
						|
      return null;
 | 
						|
    if (! (Serializable.class).isAssignableFrom (cl))
 | 
						|
      return null;
 | 
						|
 | 
						|
    ObjectStreamClass osc = (ObjectStreamClass)classLookupTable.get (cl);
 | 
						|
 | 
						|
    if (osc != null)
 | 
						|
      return osc;
 | 
						|
    else
 | 
						|
    {
 | 
						|
      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 ()
 | 
						|
  {
 | 
						|
    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 ()
 | 
						|
  {
 | 
						|
    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 ()
 | 
						|
  {
 | 
						|
    return uid;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Returns the serializable (non-static and non-transient) Fields
 | 
						|
  // of the class represented by this ObjectStreamClass.  The Fields
 | 
						|
  // are sorted by name.
 | 
						|
  // XXX doc
 | 
						|
  public ObjectStreamField[] getFields ()
 | 
						|
  {
 | 
						|
    ObjectStreamField[] copy = new ObjectStreamField[ fields.length ];
 | 
						|
    System.arraycopy (fields, 0, copy, 0, fields.length);
 | 
						|
    return copy;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // XXX doc
 | 
						|
  // Can't do binary search since fields is sorted by name and
 | 
						|
  // primitiveness.
 | 
						|
  public ObjectStreamField getField (String name)
 | 
						|
  {
 | 
						|
    for (int i=0; i < fields.length; i++)
 | 
						|
      if (fields[i].getName ().equals (name))
 | 
						|
	return fields[i];
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
     Returns a textual representation of this
 | 
						|
     <code>ObjectStreamClass</code> object including the name of the
 | 
						|
     class it represents as well as that class's serial version
 | 
						|
     stream-unique identifier.
 | 
						|
 | 
						|
     @see getSerialVersionUID ()
 | 
						|
     @see getName ()
 | 
						|
  */
 | 
						|
  public String toString ()
 | 
						|
  {
 | 
						|
    return "java.io.ObjectStreamClass< " + name + ", " + uid + " >";
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Returns true iff the class that this ObjectStreamClass represents
 | 
						|
  // has the following method:
 | 
						|
  //
 | 
						|
  // private void writeObject (ObjectOutputStream)
 | 
						|
  //
 | 
						|
  // This method is used by the class to override default
 | 
						|
  // serialization behavior.
 | 
						|
  boolean hasWriteMethod ()
 | 
						|
  {
 | 
						|
    return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Returns true iff the class that this ObjectStreamClass represents
 | 
						|
  // implements Serializable but does *not* implement Externalizable.
 | 
						|
  boolean isSerializable ()
 | 
						|
  {
 | 
						|
    return (flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Returns true iff the class that this ObjectStreamClass represents
 | 
						|
  // implements Externalizable.
 | 
						|
  boolean isExternalizable ()
 | 
						|
  {
 | 
						|
    return (flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Returns the <code>ObjectStreamClass</code> that represents the
 | 
						|
  // class that is the superclass of the class this
 | 
						|
  // <code>ObjectStreamClass</cdoe> represents.  If the superclass is
 | 
						|
  // not Serializable, null is returned.
 | 
						|
  ObjectStreamClass getSuper ()
 | 
						|
  {
 | 
						|
    return superClass;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // returns an array of ObjectStreamClasses that represent the super
 | 
						|
  // 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)
 | 
						|
  {
 | 
						|
    ObjectStreamClass osc = ObjectStreamClass.lookup (clazz);
 | 
						|
 | 
						|
    ObjectStreamClass[] ret_val;
 | 
						|
 | 
						|
    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;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Returns an integer that consists of bit-flags that indicate
 | 
						|
  // 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 ()
 | 
						|
  {
 | 
						|
    return flags;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  ObjectStreamClass (String name, long uid, byte flags,
 | 
						|
		     ObjectStreamField[] fields)
 | 
						|
  {
 | 
						|
    this.name = name;
 | 
						|
    this.uid = uid;
 | 
						|
    this.flags = flags;
 | 
						|
    this.fields = fields;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  void setClass (Class clazz)
 | 
						|
  {
 | 
						|
    this.clazz = clazz;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  void setSuperclass (ObjectStreamClass osc)
 | 
						|
  {
 | 
						|
    superClass = osc;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  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;
 | 
						|
	  break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    for (objectFieldCount = 0; i < fcount; ++ i)
 | 
						|
      fields[i].setOffset (objectFieldCount++);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  private ObjectStreamClass (Class cl)
 | 
						|
  {
 | 
						|
    uid = 0;
 | 
						|
    flags = 0;
 | 
						|
 | 
						|
    clazz = cl;
 | 
						|
    name = cl.getName ();
 | 
						|
    setFlags (cl);
 | 
						|
    setFields (cl);
 | 
						|
    setUID (cl);
 | 
						|
    superClass = lookup (cl.getSuperclass ());
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Sets bits in flags according to features of CL.
 | 
						|
  private void setFlags (Class cl)
 | 
						|
  {
 | 
						|
    if ((java.io.Externalizable.class).isAssignableFrom (cl))
 | 
						|
      flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
 | 
						|
    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)
 | 
						|
    {}
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Sets fields to be a sorted array of the serializable fields of
 | 
						|
  // clazz.
 | 
						|
  private void setFields (Class cl)
 | 
						|
  {
 | 
						|
    if (! isSerializable () || isExternalizable ())
 | 
						|
    {
 | 
						|
      fields = NO_FIELDS;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      Field serialPersistentFields
 | 
						|
	= cl.getDeclaredField ("serialPersistentFields");
 | 
						|
      int modifiers = serialPersistentFields.getModifiers ();
 | 
						|
 | 
						|
      if (Modifier.isStatic (modifiers)
 | 
						|
	  && Modifier.isFinal (modifiers)
 | 
						|
	  && Modifier.isPrivate (modifiers))
 | 
						|
      {
 | 
						|
	fields = getSerialPersistentFields (cl);
 | 
						|
	Arrays.sort (fields);
 | 
						|
	calculateOffsets ();
 | 
						|
	return;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    catch (NoSuchFieldException ignore)
 | 
						|
    {}
 | 
						|
 | 
						|
    int num_good_fields = 0;
 | 
						|
    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++;
 | 
						|
    }
 | 
						|
 | 
						|
    // 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++)
 | 
						|
      if (all_fields[from] != null)
 | 
						|
      {
 | 
						|
	Field f = all_fields[from];
 | 
						|
	fields[to] = new ObjectStreamField (f.getName (), f.getType ());
 | 
						|
	to++;
 | 
						|
      }
 | 
						|
 | 
						|
    Arrays.sort (fields);
 | 
						|
    calculateOffsets ();
 | 
						|
  }
 | 
						|
 | 
						|
  // Sets uid to be serial version UID defined by class, or if that
 | 
						|
  // isn't present, calculates value of serial version UID.
 | 
						|
  private void setUID (Class cl)
 | 
						|
  {
 | 
						|
    try
 | 
						|
    {
 | 
						|
      Field suid = cl.getDeclaredField ("serialVersionUID");
 | 
						|
      int modifiers = suid.getModifiers ();
 | 
						|
 | 
						|
      if (Modifier.isStatic (modifiers)
 | 
						|
	  && Modifier.isFinal (modifiers))
 | 
						|
      {
 | 
						|
	uid = getDefinedSUID (cl);
 | 
						|
	return;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    catch (NoSuchFieldException ignore)
 | 
						|
    {}
 | 
						|
 | 
						|
    // cl didn't define serialVersionUID, so we have to compute it
 | 
						|
    try
 | 
						|
    {
 | 
						|
      MessageDigest md = null;
 | 
						|
      DigestOutputStream digest_out = null;
 | 
						|
      DataOutputStream data_out = null;
 | 
						|
 | 
						|
      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");
 | 
						|
	}
 | 
						|
 | 
						|
      digest_out = new DigestOutputStream (nullOutputStream, md);
 | 
						|
      data_out = new DataOutputStream (digest_out);
 | 
						|
      data_out.writeUTF (cl.getName ());
 | 
						|
 | 
						|
      int modifiers = cl.getModifiers ();
 | 
						|
      // just look at interesting bits
 | 
						|
      modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
 | 
						|
  				| Modifier.INTERFACE | Modifier.PUBLIC);
 | 
						|
      data_out.writeInt (modifiers);
 | 
						|
 | 
						|
      Class[] interfaces = cl.getInterfaces ();
 | 
						|
      Arrays.sort (interfaces, interfaceComparator);
 | 
						|
      for (int i=0; i < interfaces.length; i++)
 | 
						|
	data_out.writeUTF (interfaces[i].getName ());
 | 
						|
 | 
						|
 | 
						|
      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 ()));
 | 
						|
      }
 | 
						|
 | 
						|
      // write class initializer method if present
 | 
						|
      boolean has_init;
 | 
						|
      try
 | 
						|
      {
 | 
						|
	has_init = hasClassInitializer (cl);
 | 
						|
      }
 | 
						|
      catch (NoSuchMethodError e)
 | 
						|
      {
 | 
						|
	has_init = false;
 | 
						|
      }
 | 
						|
 | 
						|
      if (has_init)
 | 
						|
      {
 | 
						|
	data_out.writeUTF ("<clinit>");
 | 
						|
	data_out.writeInt (Modifier.STATIC);
 | 
						|
	data_out.writeUTF ("()V");
 | 
						|
      }
 | 
						|
 | 
						|
      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 ('/','.'));
 | 
						|
      }
 | 
						|
 | 
						|
      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 ('/', '.'));
 | 
						|
      }
 | 
						|
 | 
						|
      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);
 | 
						|
 | 
						|
      uid = 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 ());
 | 
						|
    }
 | 
						|
    catch (IOException ioe)
 | 
						|
    {
 | 
						|
      throw new RuntimeException (ioe.getMessage ());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Returns the value of CLAZZ's final static long field named
 | 
						|
  // `serialVersionUID'.
 | 
						|
  private long getDefinedSUID (Class clazz)
 | 
						|
  {
 | 
						|
    long l = 0;
 | 
						|
    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 f = clazz.getDeclaredField ("serialVersionUID");
 | 
						|
	l = f.getLong (null);
 | 
						|
      }
 | 
						|
    catch (java.lang.NoSuchFieldException e)
 | 
						|
      {
 | 
						|
      }
 | 
						|
 | 
						|
    catch (java.lang.IllegalAccessException e)
 | 
						|
      {
 | 
						|
      }
 | 
						|
 | 
						|
    return l;
 | 
						|
  }
 | 
						|
 | 
						|
  // 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 ("getSerialPersistentFields");
 | 
						|
	o = (ObjectStreamField[])f.get (null);
 | 
						|
      }
 | 
						|
    catch (java.lang.NoSuchFieldException e)
 | 
						|
      {
 | 
						|
      }
 | 
						|
    catch (java.lang.IllegalAccessException e)
 | 
						|
      {
 | 
						|
      }
 | 
						|
 | 
						|
    return o;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  // Returns true if CLAZZ has a static class initializer
 | 
						|
  // (a.k.a. <clinit>).
 | 
						|
  //
 | 
						|
  // A NoSuchMethodError is raised if CLAZZ has no such method.
 | 
						|
  private static boolean hasClassInitializer (Class clazz)
 | 
						|
    throws java.lang.NoSuchMethodError
 | 
						|
  {
 | 
						|
    Method m = null;
 | 
						|
 | 
						|
    try
 | 
						|
      {
 | 
						|
	Class classArgs[] = {};
 | 
						|
	m = clazz.getDeclaredMethod ("<clinit>", classArgs);
 | 
						|
      }
 | 
						|
    catch (java.lang.NoSuchMethodException e)
 | 
						|
      {
 | 
						|
	throw new java.lang.NoSuchMethodError ();
 | 
						|
      }
 | 
						|
 | 
						|
    return m != null;
 | 
						|
  }
 | 
						|
 | 
						|
  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 final
 | 
						|
    Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };
 | 
						|
 | 
						|
  private ObjectStreamClass superClass;
 | 
						|
  private Class clazz;
 | 
						|
  private String name;
 | 
						|
  private long uid;
 | 
						|
  private byte flags;
 | 
						|
 | 
						|
  // this field is package protected so that ObjectInputStream and
 | 
						|
  // ObjectOutputStream can access it directly
 | 
						|
  ObjectStreamField[] fields;
 | 
						|
 | 
						|
  // these are accessed by ObjectIn/OutputStream
 | 
						|
  int primFieldSize = -1;  // -1 if not yet calculated
 | 
						|
  int objectFieldCount;
 | 
						|
 | 
						|
  // This is probably not necessary because this class is special cased already
 | 
						|
  // but it will avoid showing up as a discrepancy when comparing SUIDs.
 | 
						|
  private static final long serialVersionUID = -6120832682080437368L;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// interfaces are compared only by name
 | 
						|
class InterfaceComparator implements Comparator
 | 
						|
{
 | 
						|
  public int compare (Object o1, Object o2)
 | 
						|
  {
 | 
						|
    return ((Class)o1).getName ().compareTo (((Class)o2).getName ());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Members (Methods and Constructors) are compared first by name,
 | 
						|
// conflicts are resolved by comparing type signatures
 | 
						|
class MemberComparator implements Comparator
 | 
						|
{
 | 
						|
  public int compare (Object o1, Object o2)
 | 
						|
  {
 | 
						|
    Member m1 = (Member)o1;
 | 
						|
    Member m2 = (Member)o2;
 | 
						|
 | 
						|
    int comp = m1.getName ().compareTo (m2.getName ());
 | 
						|
 | 
						|
    if (comp == 0)
 | 
						|
      return TypeSignature.getEncodingOfMember (m1).
 | 
						|
	compareTo (TypeSignature.getEncodingOfMember (m2));
 | 
						|
    else
 | 
						|
      return comp;
 | 
						|
  }
 | 
						|
}
 |