/[classpath]/classpath/java/io/ObjectStreamClass.java
ViewVC logotype

Diff of /classpath/java/io/ObjectStreamClass.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.18 by cbj, Mon Mar 25 05:12:18 2002 UTC revision 1.19 by mark, Fri Jan 3 23:46:17 2003 UTC
# Line 1  Line 1 
1  /* ObjectStreamClass.java -- Class used to write class information  /* ObjectStreamClass.java -- Class used to write class information
2     about serialized objects.     about serialized objects.
3     Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation, Inc.     Copyright (C) 1998, 1999, 2000, 2001, 2003  Free Software Foundation, Inc.
4    
5  This file is part of GNU Classpath.  This file is part of GNU Classpath.
6    
# Line 48  import java.lang.reflect.Proxy; Line 48  import java.lang.reflect.Proxy;
48  import java.security.DigestOutputStream;  import java.security.DigestOutputStream;
49  import java.security.MessageDigest;  import java.security.MessageDigest;
50  import java.security.NoSuchAlgorithmException;  import java.security.NoSuchAlgorithmException;
51    import java.security.Security;
52  import java.util.Arrays;  import java.util.Arrays;
53  import java.util.Comparator;  import java.util.Comparator;
54  import java.util.Hashtable;  import java.util.Hashtable;
55  import java.util.Vector;  import java.util.Vector;
56  import gnu.java.io.NullOutputStream;  import gnu.java.io.NullOutputStream;
57  import gnu.java.lang.reflect.TypeSignature;  import gnu.java.lang.reflect.TypeSignature;
58  import gnu.classpath.Configuration;  import gnu.java.security.provider.Gnu;
59    
60    
61  public class ObjectStreamClass implements Serializable  public class ObjectStreamClass implements Serializable
62  {  {
# Line 260  public class ObjectStreamClass implement Line 262  public class ObjectStreamClass implement
262    }    }
263    
264    
   final boolean isProxyClass()  
   {  
     return _isProxyClass;  
   }  
   
   
265    ObjectStreamClass (String name, long uid, byte flags,    ObjectStreamClass (String name, long uid, byte flags,
266                       ObjectStreamField[] fields)                       ObjectStreamField[] fields)
267    {    {
# Line 275  public class ObjectStreamClass implement Line 271  public class ObjectStreamClass implement
271      this.fields = fields;      this.fields = fields;
272    }    }
273    
274      void setClass (Class cl) throws InvalidClassException
   void setClass (Class clazz)  
275    {    {
276      _isProxyClass = Proxy.isProxyClass(clazz);      this.clazz = cl;
277      this.clazz = clazz;  
278        long class_uid = getClassUID (cl);
279        if (uid == 0)
280          uid = class_uid;
281        else
282          {
283            // Check that the actual UID of the resolved class matches the UID from
284            // the stream.    
285            if (uid != class_uid)
286              {
287                String msg = cl +
288                  ": Local class not compatible: stream serialVersionUID="
289                  + uid + ", local serialVersionUID=" + class_uid;
290                throw new InvalidClassException (msg);
291              }
292          }
293    
294        isProxyClass = clazz != null && Proxy.isProxyClass (clazz);
295      ObjectStreamClass osc = (ObjectStreamClass)classLookupTable.get (clazz);      ObjectStreamClass osc = (ObjectStreamClass)classLookupTable.get (clazz);
296      if (osc == null)      if (osc == null)
297        classLookupTable.put (clazz, this);        classLookupTable.put (clazz, this);
# Line 287  public class ObjectStreamClass implement Line 299  public class ObjectStreamClass implement
299      calculateOffsets ();      calculateOffsets ();
300    }    }
301    
   
302    void setSuperclass (ObjectStreamClass osc)    void setSuperclass (ObjectStreamClass osc)
303    {    {
304      superClass = osc;      superClass = osc;
# Line 338  public class ObjectStreamClass implement Line 349  public class ObjectStreamClass implement
349    {    {
350      uid = 0;      uid = 0;
351      flags = 0;      flags = 0;
352      _isProxyClass = Proxy.isProxyClass (cl);      isProxyClass = Proxy.isProxyClass (cl);
353    
354      clazz = cl;      clazz = cl;
355      name = cl.getName ();      name = cl.getName ();
356      setFlags (cl);      setFlags (cl);
357      setFields (cl);      setFields (cl);
358      // to those class nonserializable, its uid field is 0      // to those class nonserializable, its uid field is 0
359      if ( (Serializable.class).isAssignableFrom (cl) )      if ( (Serializable.class).isAssignableFrom (cl) && !isProxyClass)
360        setUID (cl);        uid = getClassUID (cl);
361      superClass = lookup (cl.getSuperclass ());      superClass = lookup (cl.getSuperclass ());
362    }    }
363    
# Line 390  public class ObjectStreamClass implement Line 401  public class ObjectStreamClass implement
401      {      {
402        Field serialPersistentFields        Field serialPersistentFields
403          = cl.getDeclaredField ("serialPersistentFields");          = cl.getDeclaredField ("serialPersistentFields");
404          serialPersistentFields.setAccessible(true);
405        int modifiers = serialPersistentFields.getModifiers ();        int modifiers = serialPersistentFields.getModifiers ();
406    
407        if (Modifier.isStatic (modifiers)        if (Modifier.isStatic (modifiers)
# Line 426  public class ObjectStreamClass implement Line 438  public class ObjectStreamClass implement
438        if (all_fields[from] != null)        if (all_fields[from] != null)
439        {        {
440          Field f = all_fields[from];          Field f = all_fields[from];
441          String name = f.getName();          fields[to] = new ObjectStreamField (f.getName (), f.getType ());
         // here is a hack to interoperate with JDK  
         /* if Throwable is not align with serialized form of Java API spec,  
            you should uncomment the following two line.  
            if (name.equals("message") && getName().equals("java.lang.Throwable"))  
            name = "detailMessage";  
         */  
         fields[to] = new ObjectStreamField (name, f.getType ());  
442          to++;          to++;
443        }        }
444    
# Line 441  public class ObjectStreamClass implement Line 446  public class ObjectStreamClass implement
446      calculateOffsets ();      calculateOffsets ();
447    }    }
448    
449    // Sets uid to be serial version UID defined by class, or if that    // Returns the serial version UID defined by class, or if that
450    // isn't present, calculates value of serial version UID.    // isn't present, calculates value of serial version UID.
451    private void setUID (Class cl)    private long getClassUID (Class cl)
452    {    {
453      try      try
454      {      {
455          // Use getDeclaredField rather than getField, since serialVersionUID
456          // may not be public AND we only want the serialVersionUID of this
457          // class, not a superclass or interface.
458        Field suid = cl.getDeclaredField ("serialVersionUID");        Field suid = cl.getDeclaredField ("serialVersionUID");
459          suid.setAccessible(true);
460        int modifiers = suid.getModifiers ();        int modifiers = suid.getModifiers ();
461    
462        if (Modifier.isStatic (modifiers)        if (Modifier.isStatic (modifiers)
463            && Modifier.isFinal (modifiers))            && Modifier.isFinal (modifiers)
464        {            && suid.getType() == Long.TYPE)
465          uid = getDefinedSUID (cl);          return suid.getLong (null);
         return;  
       }  
466      }      }
467      catch (NoSuchFieldException ignore)      catch (NoSuchFieldException ignore)
468      {}      {}
469        catch (IllegalAccessException ignore)
470        {}
471    
472      // cl didn't define serialVersionUID, so we have to compute it      // cl didn't define serialVersionUID, so we have to compute it
473      try      try
474      {      {
475        MessageDigest md = MessageDigest.getInstance ("SHA");        MessageDigest md;
476          try
477            {
478              md = MessageDigest.getInstance ("SHA");
479            }
480          catch (NoSuchAlgorithmException e)
481            {
482              // If a provider already provides SHA, use it; otherwise, use this.
483              Gnu gnuProvider = new Gnu();
484              Security.addProvider(gnuProvider);
485              md = MessageDigest.getInstance ("SHA");
486            }
487    
488        DigestOutputStream digest_out =        DigestOutputStream digest_out =
489          new DigestOutputStream (nullOutputStream, md);          new DigestOutputStream (nullOutputStream, md);
490        DataOutputStream data_out = new DataOutputStream (digest_out);        DataOutputStream data_out = new DataOutputStream (digest_out);
# Line 504  public class ObjectStreamClass implement Line 525  public class ObjectStreamClass implement
525        }        }
526    
527        // write class initializer method if present        // write class initializer method if present
528        boolean has_init;        if (hasClassInitializer (cl))
       try  
       {  
         has_init = hasClassInitializer (cl);  
       }  
       catch (NoSuchMethodError e)  
       {  
         has_init = false;  
       }  
   
       if (has_init)  
529        {        {
530          data_out.writeUTF ("<clinit>");          data_out.writeUTF ("<clinit>");
531          data_out.writeInt (Modifier.STATIC);          data_out.writeInt (Modifier.STATIC);
# Line 566  public class ObjectStreamClass implement Line 577  public class ObjectStreamClass implement
577        for (int i=0; i < len; i++)        for (int i=0; i < len; i++)
578          result += (long)(sha[i] & 0xFF) << (8 * i);          result += (long)(sha[i] & 0xFF) << (8 * i);
579    
580        uid = result;        return result;
581      }      }
582      catch (NoSuchAlgorithmException e)      catch (NoSuchAlgorithmException e)
583      {      {
584        throw new RuntimeException ("The SHA algorithm was not found to use in computing the Serial Version UID for class "        throw new RuntimeException ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
585                                    + cl.getName ());                                    + cl.getName (), e);
586      }      }
587      catch (IOException ioe)      catch (IOException ioe)
588      {      {
589        throw new RuntimeException (ioe.getMessage ());        throw new RuntimeException (ioe);
590      }      }
591    }    }
592    
   
   // 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;  
   }  
   
593    // Returns the value of CLAZZ's private static final field named    // Returns the value of CLAZZ's private static final field named
594    // `serialPersistentFields'.    // `serialPersistentFields'.
595    private ObjectStreamField[] getSerialPersistentFields (Class clazz)    private ObjectStreamField[] getSerialPersistentFields (Class clazz)
# Line 614  public class ObjectStreamClass implement Line 600  public class ObjectStreamClass implement
600          // Use getDeclaredField rather than getField for the same reason          // Use getDeclaredField rather than getField for the same reason
601          // as above in getDefinedSUID.          // as above in getDefinedSUID.
602          Field f = clazz.getDeclaredField ("getSerialPersistentFields");          Field f = clazz.getDeclaredField ("getSerialPersistentFields");
603            f.setAccessible(true);
604          o = (ObjectStreamField[])f.get (null);          o = (ObjectStreamField[])f.get (null);
605        }        }
606      catch (java.lang.NoSuchFieldException e)      catch (java.lang.NoSuchFieldException e)
# Line 629  public class ObjectStreamClass implement Line 616  public class ObjectStreamClass implement
616    
617    // Returns true if CLAZZ has a static class initializer    // Returns true if CLAZZ has a static class initializer
618    // (a.k.a. <clinit>).    // (a.k.a. <clinit>).
   //  
   // A NoSuchMethodError is raised if CLAZZ has no such method.  
619    private static boolean hasClassInitializer (Class clazz)    private static boolean hasClassInitializer (Class clazz)
     throws java.lang.NoSuchMethodError  
620    {    {
621      Method m = null;      Method m = null;
622    
623      try      try
624        {        {
625          /*          /*
626           * There exists a problem here, JDK run of           * There exists a problem here, according to the spec
627           * clazz.getDeclaredMethod ("<clinit>", classArgs);           * clazz.getDeclaredMethod ("<clinit>", classArgs);
628           * will always throw NoSuchMethodException, even the static           * will always throw NoSuchMethodException, even if the static
629           * intializer does exist.           * intializer does exist.
630           */           */
631          Class classArgs[] = {};          Class classArgs[] = {};
# Line 649  public class ObjectStreamClass implement Line 633  public class ObjectStreamClass implement
633        }        }
634      catch (java.lang.NoSuchMethodException e)      catch (java.lang.NoSuchMethodException e)
635        {        {
         throw new java.lang.NoSuchMethodError ();  
636        }        }
637    
638      return m != null;      return m != null;
# Line 678  public class ObjectStreamClass implement Line 661  public class ObjectStreamClass implement
661    int primFieldSize = -1;  // -1 if not yet calculated    int primFieldSize = -1;  // -1 if not yet calculated
662    int objectFieldCount;    int objectFieldCount;
663    
664    boolean _isProxyClass = false;    boolean isProxyClass = false;
665    
666    // This is probably not necessary because this class is special cased already    // This is probably not necessary because this class is special cased already
667    // but it will avoid showing up as a discrepancy when comparing SUIDs.    // but it will avoid showing up as a discrepancy when comparing SUIDs.
668    private static final long serialVersionUID = -6120832682080437368L;    private static final long serialVersionUID = -6120832682080437368L;
669    
   static  
   {  
     if (Configuration.INIT_LOAD_LIBRARY)  
       {  
         System.loadLibrary ("javaio");  
       }  
   }  
670  }  }
671    
672    

Legend:
Removed from v.1.18  
changed lines
  Added in v.1.19

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26