OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [io/] [ObjectStreamClass.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* ObjectStreamClass.java -- Class used to write class information
2
   about serialized objects.
3
   Copyright (C) 1998, 1999, 2000, 2001, 2003  Free Software Foundation, Inc.
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
GNU Classpath is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module.  An independent module is a module which is not derived from
34
or based on this library.  If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so.  If you do not wish to do so, delete this
37
exception statement from your version. */
38
 
39
 
40
package java.io;
41
 
42
import gnu.java.io.NullOutputStream;
43
import gnu.java.lang.reflect.TypeSignature;
44
import gnu.java.security.action.SetAccessibleAction;
45
import gnu.java.security.provider.Gnu;
46
 
47
import java.lang.reflect.Constructor;
48
import java.lang.reflect.Field;
49
import java.lang.reflect.Member;
50
import java.lang.reflect.Method;
51
import java.lang.reflect.Modifier;
52
import java.lang.reflect.Proxy;
53
import java.security.AccessController;
54
import java.security.DigestOutputStream;
55
import java.security.MessageDigest;
56
import java.security.NoSuchAlgorithmException;
57
import java.security.PrivilegedAction;
58
import java.security.Security;
59
import java.util.Arrays;
60
import java.util.Comparator;
61
import java.util.Hashtable;
62
import java.util.Vector;
63
 
64
public class ObjectStreamClass implements Serializable
65
{
66
  /**
67
   * Returns the <code>ObjectStreamClass</code> for <code>cl</code>.
68
   * If <code>cl</code> is null, or is not <code>Serializable</code>,
69
   * null is returned.  <code>ObjectStreamClass</code>'s are memorized;
70
   * later calls to this method with the same class will return the
71
   * same <code>ObjectStreamClass</code> object and no recalculation
72
   * will be done.
73
   *
74
   * @see java.io.Serializable
75
   */
76
  public static ObjectStreamClass lookup(Class cl)
77
  {
78
    if (cl == null)
79
      return null;
80
    if (! (Serializable.class).isAssignableFrom(cl))
81
      return null;
82
 
83
    return lookupForClassObject(cl);
84
  }
85
 
86
  /**
87
   * This lookup for internal use by ObjectOutputStream.  Suppose
88
   * we have a java.lang.Class object C for class A, though A is not
89
   * serializable, but it's okay to serialize C.
90
   */
91
  static ObjectStreamClass lookupForClassObject(Class cl)
92
  {
93
    if (cl == null)
94
      return null;
95
 
96
    ObjectStreamClass osc = (ObjectStreamClass) classLookupTable.get(cl);
97
 
98
    if (osc != null)
99
      return osc;
100
    else
101
      {
102
        osc = new ObjectStreamClass(cl);
103
        classLookupTable.put(cl, osc);
104
        return osc;
105
      }
106
  }
107
 
108
  /**
109
   * Returns the name of the class that this
110
   * <code>ObjectStreamClass</code> represents.
111
   *
112
   * @return the name of the class.
113
   */
114
  public String getName()
115
  {
116
    return name;
117
  }
118
 
119
  /**
120
   * Returns the class that this <code>ObjectStreamClass</code>
121
   * represents.  Null could be returned if this
122
   * <code>ObjectStreamClass</code> was read from an
123
   * <code>ObjectInputStream</code> and the class it represents cannot
124
   * be found or loaded.
125
   *
126
   * @see java.io.ObjectInputStream
127
   */
128
  public Class forClass()
129
  {
130
    return clazz;
131
  }
132
 
133
  /**
134
   * Returns the serial version stream-unique identifier for the class
135
   * represented by this <code>ObjectStreamClass</code>.  This SUID is
136
   * either defined by the class as <code>static final long
137
   * serialVersionUID</code> or is calculated as specified in
138
   * Javasoft's "Object Serialization Specification" XXX: add reference
139
   *
140
   * @return the serial version UID.
141
   */
142
  public long getSerialVersionUID()
143
  {
144
    return uid;
145
  }
146
 
147
  /**
148
   * Returns the serializable (non-static and non-transient) Fields
149
   * of the class represented by this ObjectStreamClass.  The Fields
150
   * are sorted by name.
151
   *
152
   * @return the fields.
153
   */
154
  public ObjectStreamField[] getFields()
155
  {
156
    ObjectStreamField[] copy = new ObjectStreamField[ fields.length ];
157
    System.arraycopy(fields, 0, copy, 0, fields.length);
158
    return copy;
159
  }
160
 
161
  // XXX doc
162
  // Can't do binary search since fields is sorted by name and
163
  // primitiveness.
164
  public ObjectStreamField getField (String name)
165
  {
166
    for (int i = 0; i < fields.length; i++)
167
      if (fields[i].getName().equals(name))
168
        return fields[i];
169
    return null;
170
  }
171
 
172
  /**
173
   * Returns a textual representation of this
174
   * <code>ObjectStreamClass</code> object including the name of the
175
   * class it represents as well as that class's serial version
176
   * stream-unique identifier.
177
   *
178
   * @see #getSerialVersionUID()
179
   * @see #getName()
180
   */
181
  public String toString()
182
  {
183
    return "java.io.ObjectStreamClass< " + name + ", " + uid + " >";
184
  }
185
 
186
  // Returns true iff the class that this ObjectStreamClass represents
187
  // has the following method:
188
  //
189
  // private void writeObject (ObjectOutputStream)
190
  //
191
  // This method is used by the class to override default
192
  // serialization behavior.
193
  boolean hasWriteMethod()
194
  {
195
    return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0;
196
  }
197
 
198
  // Returns true iff the class that this ObjectStreamClass represents
199
  // implements Serializable but does *not* implement Externalizable.
200
  boolean isSerializable()
201
  {
202
    return (flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0;
203
  }
204
 
205
 
206
  // Returns true iff the class that this ObjectStreamClass represents
207
  // implements Externalizable.
208
  boolean isExternalizable()
209
  {
210
    return (flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0;
211
  }
212
 
213
 
214
  // Returns the <code>ObjectStreamClass</code> that represents the
215
  // class that is the superclass of the class this
216
  // <code>ObjectStreamClass</code> represents.  If the superclass is
217
  // not Serializable, null is returned.
218
  ObjectStreamClass getSuper()
219
  {
220
    return superClass;
221
  }
222
 
223
 
224
  // returns an array of ObjectStreamClasses that represent the super
225
  // classes of CLAZZ and CLAZZ itself in order from most super to
226
  // CLAZZ.  ObjectStreamClass[0] is the highest superclass of CLAZZ
227
  // that is serializable.
228
  static ObjectStreamClass[] getObjectStreamClasses(Class clazz)
229
  {
230
    ObjectStreamClass osc = ObjectStreamClass.lookup(clazz);
231
 
232
    if (osc == null)
233
      return new ObjectStreamClass[0];
234
    else
235
      {
236
        Vector oscs = new Vector();
237
 
238
        while (osc != null)
239
          {
240
            oscs.addElement (osc);
241
            osc = osc.getSuper();
242
          }
243
 
244
        int count = oscs.size();
245
        ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[ count ];
246
 
247
        for (int i = count - 1; i >= 0; i--)
248
          sorted_oscs[ count - i - 1 ] = (ObjectStreamClass) oscs.elementAt(i);
249
 
250
        return sorted_oscs;
251
      }
252
  }
253
 
254
 
255
  // Returns an integer that consists of bit-flags that indicate
256
  // properties of the class represented by this ObjectStreamClass.
257
  // The bit-flags that could be present are those defined in
258
  // ObjectStreamConstants that begin with `SC_'
259
  int getFlags()
260
  {
261
    return flags;
262
  }
263
 
264
 
265
  ObjectStreamClass(String name, long uid, byte flags,
266
                    ObjectStreamField[] fields)
267
  {
268
    this.name = name;
269
    this.uid = uid;
270
    this.flags = flags;
271
    this.fields = fields;
272
  }
273
 
274
  /**
275
   * This method builds the internal description corresponding to a Java Class.
276
   * As the constructor only assign a name to the current ObjectStreamClass instance,
277
   * that method sets the serial UID, chose the fields which will be serialized,
278
   * and compute the position of the fields in the serialized stream.
279
   *
280
   * @param cl The Java class which is used as a reference for building the descriptor.
281
   * @param superClass The descriptor of the super class for this class descriptor.
282
   * @throws InvalidClassException if an incompatibility between computed UID and
283
   * already set UID is found.
284
   */
285
  void setClass(Class cl, ObjectStreamClass superClass) throws InvalidClassException
286
  {
287
    this.clazz = cl;
288
 
289
    cacheMethods();
290
 
291
    long class_uid = getClassUID(cl);
292
    if (uid == 0)
293
      uid = class_uid;
294
    else
295
      {
296
        // Check that the actual UID of the resolved class matches the UID from 
297
        // the stream.    
298
        if (uid != class_uid)
299
          {
300
            String msg = cl +
301
              ": Local class not compatible: stream serialVersionUID="
302
              + uid + ", local serialVersionUID=" + class_uid;
303
            throw new InvalidClassException (msg);
304
          }
305
      }
306
 
307
    isProxyClass = clazz != null && Proxy.isProxyClass(clazz);
308
    this.superClass = superClass;
309
    calculateOffsets();
310
 
311
    try
312
      {
313
        ObjectStreamField[] exportedFields = getSerialPersistentFields (clazz);
314
 
315
        if (exportedFields == null)
316
          return;
317
 
318
        ObjectStreamField[] newFieldList = new ObjectStreamField[exportedFields.length + fields.length];
319
        int i, j, k;
320
 
321
        /* We now check the import fields against the exported fields.
322
         * There should not be contradiction (e.g. int x and String x)
323
         * but extra virtual fields can be added to the class.
324
         */
325
 
326
        Arrays.sort(exportedFields);
327
 
328
        i = 0; j = 0; k = 0;
329
        while (i < fields.length && j < exportedFields.length)
330
          {
331
            int comp = fields[i].compareTo(exportedFields[j]);
332
 
333
            if (comp < 0)
334
              {
335
                newFieldList[k] = fields[i];
336
                fields[i].setPersistent(false);
337
                fields[i].setToSet(false);
338
                i++;
339
              }
340
            else if (comp > 0)
341
              {
342
                /* field not found in imported fields. We add it
343
                 * in the list of supported fields.
344
                 */
345
                newFieldList[k] = exportedFields[j];
346
                newFieldList[k].setPersistent(true);
347
                newFieldList[k].setToSet(false);
348
                try
349
                  {
350
                    newFieldList[k].lookupField(clazz);
351
                    newFieldList[k].checkFieldType();
352
                  }
353
                catch (NoSuchFieldException _)
354
                  {
355
                  }
356
                j++;
357
              }
358
            else
359
              {
360
                try
361
                  {
362
                    exportedFields[j].lookupField(clazz);
363
                    exportedFields[j].checkFieldType();
364
                  }
365
                catch (NoSuchFieldException _)
366
                  {
367
                  }
368
 
369
                if (!fields[i].getType().equals(exportedFields[j].getType()))
370
                  throw new InvalidClassException
371
                    ("serialPersistentFields must be compatible with" +
372
                     " imported fields (about " + fields[i].getName() + ")");
373
                newFieldList[k] = fields[i];
374
                fields[i].setPersistent(true);
375
                i++;
376
                j++;
377
              }
378
            k++;
379
          }
380
 
381
        if (i < fields.length)
382
          for (;i<fields.length;i++,k++)
383
            {
384
              fields[i].setPersistent(false);
385
              fields[i].setToSet(false);
386
              newFieldList[k] = fields[i];
387
            }
388
        else
389
          if (j < exportedFields.length)
390
            for (;j<exportedFields.length;j++,k++)
391
              {
392
                exportedFields[j].setPersistent(true);
393
                exportedFields[j].setToSet(false);
394
                newFieldList[k] = exportedFields[j];
395
              }
396
 
397
        fields = new ObjectStreamField[k];
398
        System.arraycopy(newFieldList, 0, fields, 0, k);
399
      }
400
    catch (NoSuchFieldException ignore)
401
      {
402
        return;
403
      }
404
    catch (IllegalAccessException ignore)
405
      {
406
        return;
407
      }
408
  }
409
 
410
  void setSuperclass (ObjectStreamClass osc)
411
  {
412
    superClass = osc;
413
  }
414
 
415
  void calculateOffsets()
416
  {
417
    int i;
418
    ObjectStreamField field;
419
    primFieldSize = 0;
420
    int fcount = fields.length;
421
    for (i = 0; i < fcount; ++ i)
422
      {
423
        field = fields[i];
424
 
425
        if (! field.isPrimitive())
426
          break;
427
 
428
        field.setOffset(primFieldSize);
429
        switch (field.getTypeCode())
430
          {
431
          case 'B':
432
          case 'Z':
433
            ++ primFieldSize;
434
            break;
435
          case 'C':
436
          case 'S':
437
            primFieldSize += 2;
438
            break;
439
          case 'I':
440
          case 'F':
441
            primFieldSize += 4;
442
            break;
443
          case 'D':
444
          case 'J':
445
            primFieldSize += 8;
446
            break;
447
          }
448
      }
449
 
450
    for (objectFieldCount = 0; i < fcount; ++ i)
451
      fields[i].setOffset(objectFieldCount++);
452
  }
453
 
454
  private Method findMethod(Method[] methods, String name, Class[] params,
455
                            Class returnType, boolean mustBePrivate)
456
  {
457
outer:
458
    for (int i = 0; i < methods.length; i++)
459
    {
460
        final Method m = methods[i];
461
        int mods = m.getModifiers();
462
        if (Modifier.isStatic(mods)
463
            || (mustBePrivate && !Modifier.isPrivate(mods)))
464
        {
465
            continue;
466
        }
467
 
468
        if (m.getName().equals(name)
469
           && m.getReturnType() == returnType)
470
        {
471
            Class[] mp = m.getParameterTypes();
472
            if (mp.length == params.length)
473
            {
474
                for (int j = 0; j < mp.length; j++)
475
                {
476
                    if (mp[j] != params[j])
477
                    {
478
                        continue outer;
479
                    }
480
                }
481
                AccessController.doPrivileged(new SetAccessibleAction(m));
482
                return m;
483
            }
484
        }
485
    }
486
    return null;
487
  }
488
 
489
  private static boolean inSamePackage(Class c1, Class c2)
490
  {
491
    String name1 = c1.getName();
492
    String name2 = c2.getName();
493
 
494
    int id1 = name1.lastIndexOf('.');
495
    int id2 = name2.lastIndexOf('.');
496
 
497
    // Handle the default package
498
    if (id1 == -1 || id2 == -1)
499
      return id1 == id2;
500
 
501
    String package1 = name1.substring(0, id1);
502
    String package2 = name2.substring(0, id2);
503
 
504
    return package1.equals(package2);
505
  }
506
 
507
  final static Class[] noArgs = new Class[0];
508
 
509
  private static Method findAccessibleMethod(String name, Class from)
510
  {
511
    for (Class c = from; c != null; c = c.getSuperclass())
512
      {
513
        try
514
          {
515
            Method res = c.getDeclaredMethod(name, noArgs);
516
            int mods = res.getModifiers();
517
 
518
            if (c == from
519
                || Modifier.isProtected(mods)
520
                || Modifier.isPublic(mods)
521
                || (! Modifier.isPrivate(mods) && inSamePackage(c, from)))
522
              {
523
                AccessController.doPrivileged(new SetAccessibleAction(res));
524
                return res;
525
              }
526
          }
527
        catch (NoSuchMethodException e)
528
          {
529
          }
530
      }
531
 
532
    return null;
533
  }
534
 
535
  private void cacheMethods()
536
  {
537
    Method[] methods = forClass().getDeclaredMethods();
538
 
539
    readObjectMethod = findMethod(methods, "readObject",
540
                                  new Class[] { ObjectInputStream.class },
541
                                  Void.TYPE, true);
542
    writeObjectMethod = findMethod(methods, "writeObject",
543
                                   new Class[] { ObjectOutputStream.class },
544
                                   Void.TYPE, true);
545
 
546
    // readResolve and writeReplace can be in parent classes, as long as they
547
    // are accessible from this class.
548
    readResolveMethod = findAccessibleMethod("readResolve", forClass());
549
    writeReplaceMethod = findAccessibleMethod("writeReplace", forClass());
550
  }
551
 
552
  private ObjectStreamClass(Class cl)
553
  {
554
    uid = 0;
555
    flags = 0;
556
    isProxyClass = Proxy.isProxyClass(cl);
557
 
558
    clazz = cl;
559
    cacheMethods();
560
    name = cl.getName();
561
    setFlags(cl);
562
    setFields(cl);
563
    // to those class nonserializable, its uid field is 0
564
    if ( (Serializable.class).isAssignableFrom(cl) && !isProxyClass)
565
      uid = getClassUID(cl);
566
    superClass = lookup(cl.getSuperclass());
567
  }
568
 
569
 
570
  // Sets bits in flags according to features of CL.
571
  private void setFlags(Class cl)
572
  {
573
    if ((java.io.Externalizable.class).isAssignableFrom(cl))
574
      flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
575
    else if ((java.io.Serializable.class).isAssignableFrom(cl))
576
      // only set this bit if CL is NOT Externalizable
577
      flags |= ObjectStreamConstants.SC_SERIALIZABLE;
578
 
579
    if (writeObjectMethod != null)
580
      flags |= ObjectStreamConstants.SC_WRITE_METHOD;
581
  }
582
 
583
 
584
  // Sets fields to be a sorted array of the serializable fields of
585
  // clazz.
586
  private void setFields(Class cl)
587
  {
588
    SetAccessibleAction setAccessible = new SetAccessibleAction();
589
 
590
    if (!isSerializable() || isExternalizable())
591
      {
592
        fields = NO_FIELDS;
593
        return;
594
      }
595
 
596
    try
597
      {
598
        final Field f =
599
          cl.getDeclaredField("serialPersistentFields");
600
        setAccessible.setMember(f);
601
        AccessController.doPrivileged(setAccessible);
602
        int modifiers = f.getModifiers();
603
 
604
        if (Modifier.isStatic(modifiers)
605
            && Modifier.isFinal(modifiers)
606
            && Modifier.isPrivate(modifiers))
607
          {
608
            fields = getSerialPersistentFields(cl);
609
            if (fields != null)
610
              {
611
                Arrays.sort (fields);
612
                // Retrieve field reference.
613
                for (int i=0; i < fields.length; i++)
614
                  {
615
                    try
616
                      {
617
                        fields[i].lookupField(cl);
618
                      }
619
                    catch (NoSuchFieldException _)
620
                      {
621
                        fields[i].setToSet(false);
622
                      }
623
                  }
624
 
625
                calculateOffsets();
626
                return;
627
              }
628
          }
629
      }
630
    catch (NoSuchFieldException ignore)
631
      {
632
      }
633
    catch (IllegalAccessException ignore)
634
      {
635
      }
636
 
637
    int num_good_fields = 0;
638
    Field[] all_fields = cl.getDeclaredFields();
639
 
640
    int modifiers;
641
    // set non-serializable fields to null in all_fields
642
    for (int i = 0; i < all_fields.length; i++)
643
      {
644
        modifiers = all_fields[i].getModifiers();
645
        if (Modifier.isTransient(modifiers)
646
            || Modifier.isStatic(modifiers))
647
          all_fields[i] = null;
648
        else
649
          num_good_fields++;
650
      }
651
 
652
    // make a copy of serializable (non-null) fields
653
    fields = new ObjectStreamField[ num_good_fields ];
654
    for (int from = 0, to = 0; from < all_fields.length; from++)
655
      if (all_fields[from] != null)
656
        {
657
          final Field f = all_fields[from];
658
          setAccessible.setMember(f);
659
          AccessController.doPrivileged(setAccessible);
660
          fields[to] = new ObjectStreamField(all_fields[from]);
661
          to++;
662
        }
663
 
664
    Arrays.sort(fields);
665
    // Make sure we don't have any duplicate field names
666
    // (Sun JDK 1.4.1. throws an Internal Error as well)
667
    for (int i = 1; i < fields.length; i++)
668
      {
669
        if(fields[i - 1].getName().equals(fields[i].getName()))
670
            throw new InternalError("Duplicate field " +
671
                        fields[i].getName() + " in class " + cl.getName());
672
      }
673
    calculateOffsets();
674
  }
675
 
676
  // Returns the serial version UID defined by class, or if that
677
  // isn't present, calculates value of serial version UID.
678
  private long getClassUID(Class cl)
679
  {
680
    try
681
      {
682
        // Use getDeclaredField rather than getField, since serialVersionUID
683
        // may not be public AND we only want the serialVersionUID of this
684
        // class, not a superclass or interface.
685
        final Field suid = cl.getDeclaredField("serialVersionUID");
686
        SetAccessibleAction setAccessible = new SetAccessibleAction(suid);
687
        AccessController.doPrivileged(setAccessible);
688
        int modifiers = suid.getModifiers();
689
 
690
        if (Modifier.isStatic(modifiers)
691
            && Modifier.isFinal(modifiers)
692
            && suid.getType() == Long.TYPE)
693
          return suid.getLong(null);
694
      }
695
    catch (NoSuchFieldException ignore)
696
      {
697
      }
698
    catch (IllegalAccessException ignore)
699
      {
700
      }
701
 
702
    // cl didn't define serialVersionUID, so we have to compute it
703
    try
704
      {
705
        MessageDigest md;
706
        try
707
          {
708
            md = MessageDigest.getInstance("SHA");
709
          }
710
        catch (NoSuchAlgorithmException e)
711
          {
712
            // If a provider already provides SHA, use it; otherwise, use this.
713
            Gnu gnuProvider = new Gnu();
714
            Security.addProvider(gnuProvider);
715
            md = MessageDigest.getInstance("SHA");
716
          }
717
 
718
        DigestOutputStream digest_out =
719
          new DigestOutputStream(nullOutputStream, md);
720
        DataOutputStream data_out = new DataOutputStream(digest_out);
721
 
722
        data_out.writeUTF(cl.getName());
723
 
724
        int modifiers = cl.getModifiers();
725
        // just look at interesting bits
726
        modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
727
                                 | Modifier.INTERFACE | Modifier.PUBLIC);
728
        data_out.writeInt(modifiers);
729
 
730
        // Pretend that an array has no interfaces, because when array
731
        // serialization was defined (JDK 1.1), arrays didn't have it.
732
        if (! cl.isArray())
733
          {
734
            Class[] interfaces = cl.getInterfaces();
735
            Arrays.sort(interfaces, interfaceComparator);
736
            for (int i = 0; i < interfaces.length; i++)
737
              data_out.writeUTF(interfaces[i].getName());
738
          }
739
 
740
        Field field;
741
        Field[] fields = cl.getDeclaredFields();
742
        Arrays.sort(fields, memberComparator);
743
        for (int i = 0; i < fields.length; i++)
744
          {
745
            field = fields[i];
746
            modifiers = field.getModifiers();
747
            if (Modifier.isPrivate(modifiers)
748
                && (Modifier.isStatic(modifiers)
749
                    || Modifier.isTransient(modifiers)))
750
              continue;
751
 
752
            data_out.writeUTF(field.getName());
753
            data_out.writeInt(modifiers);
754
            data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
755
          }
756
 
757
        // write class initializer method if present
758
        if (VMObjectStreamClass.hasClassInitializer(cl))
759
          {
760
            data_out.writeUTF("<clinit>");
761
            data_out.writeInt(Modifier.STATIC);
762
            data_out.writeUTF("()V");
763
          }
764
 
765
        Constructor constructor;
766
        Constructor[] constructors = cl.getDeclaredConstructors();
767
        Arrays.sort (constructors, memberComparator);
768
        for (int i = 0; i < constructors.length; i++)
769
          {
770
            constructor = constructors[i];
771
            modifiers = constructor.getModifiers();
772
            if (Modifier.isPrivate(modifiers))
773
              continue;
774
 
775
            data_out.writeUTF("<init>");
776
            data_out.writeInt(modifiers);
777
 
778
            // the replacement of '/' with '.' was needed to make computed
779
            // SUID's agree with those computed by JDK
780
            data_out.writeUTF
781
              (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
782
          }
783
 
784
        Method method;
785
        Method[] methods = cl.getDeclaredMethods();
786
        Arrays.sort(methods, memberComparator);
787
        for (int i = 0; i < methods.length; i++)
788
          {
789
            method = methods[i];
790
            modifiers = method.getModifiers();
791
            if (Modifier.isPrivate(modifiers))
792
              continue;
793
 
794
            data_out.writeUTF(method.getName());
795
            data_out.writeInt(modifiers);
796
 
797
            // the replacement of '/' with '.' was needed to make computed
798
            // SUID's agree with those computed by JDK
799
            data_out.writeUTF
800
              (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
801
          }
802
 
803
        data_out.close();
804
        byte[] sha = md.digest();
805
        long result = 0;
806
        int len = sha.length < 8 ? sha.length : 8;
807
        for (int i = 0; i < len; i++)
808
          result += (long) (sha[i] & 0xFF) << (8 * i);
809
 
810
        return result;
811
      }
812
    catch (NoSuchAlgorithmException e)
813
      {
814
        throw new RuntimeException
815
          ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
816
           + cl.getName(), e);
817
      }
818
    catch (IOException ioe)
819
      {
820
        throw new RuntimeException(ioe);
821
      }
822
  }
823
 
824
  /**
825
   * Returns the value of CLAZZ's private static final field named
826
   * `serialPersistentFields'. It performs some sanity checks before
827
   * returning the real array. Besides, the returned array is a clean
828
   * copy of the original. So it can be modified.
829
   *
830
   * @param clazz Class to retrieve 'serialPersistentFields' from.
831
   * @return The content of 'serialPersistentFields'.
832
   */
833
  private ObjectStreamField[] getSerialPersistentFields(Class clazz)
834
    throws NoSuchFieldException, IllegalAccessException
835
  {
836
    ObjectStreamField[] fieldsArray = null;
837
    ObjectStreamField[] o;
838
 
839
    // Use getDeclaredField rather than getField for the same reason
840
    // as above in getDefinedSUID.
841
    Field f = clazz.getDeclaredField("serialPersistentFields");
842
    f.setAccessible(true);
843
 
844
    int modifiers = f.getModifiers();
845
    if (!(Modifier.isStatic(modifiers) &&
846
          Modifier.isFinal(modifiers) &&
847
          Modifier.isPrivate(modifiers)))
848
      return null;
849
 
850
    o = (ObjectStreamField[]) f.get(null);
851
 
852
    if (o == null)
853
      return null;
854
 
855
    fieldsArray = new ObjectStreamField[ o.length ];
856
    System.arraycopy(o, 0, fieldsArray, 0, o.length);
857
 
858
    return fieldsArray;
859
  }
860
 
861
  /**
862
   * Returns a new instance of the Class this ObjectStreamClass corresponds
863
   * to.
864
   * Note that this should only be used for Externalizable classes.
865
   *
866
   * @return A new instance.
867
   */
868
  Externalizable newInstance() throws InvalidClassException
869
  {
870
    synchronized(this)
871
    {
872
        if (constructor == null)
873
        {
874
            try
875
            {
876
                final Constructor c = clazz.getConstructor(new Class[0]);
877
 
878
                AccessController.doPrivileged(new PrivilegedAction()
879
                {
880
                    public Object run()
881
                    {
882
                        c.setAccessible(true);
883
                        return null;
884
                    }
885
                });
886
 
887
                constructor = c;
888
            }
889
            catch(NoSuchMethodException x)
890
            {
891
                throw new InvalidClassException(clazz.getName(),
892
                    "No public zero-argument constructor");
893
            }
894
        }
895
    }
896
 
897
    try
898
    {
899
        return (Externalizable)constructor.newInstance(null);
900
    }
901
    catch(Exception x)
902
    {
903
        throw (InvalidClassException)
904
            new InvalidClassException(clazz.getName(),
905
                     "Unable to instantiate").initCause(x);
906
    }
907
  }
908
 
909
  public static final ObjectStreamField[] NO_FIELDS = {};
910
 
911
  private static Hashtable classLookupTable = new Hashtable();
912
  private static final NullOutputStream nullOutputStream = new NullOutputStream();
913
  private static final Comparator interfaceComparator = new InterfaceComparator();
914
  private static final Comparator memberComparator = new MemberComparator();
915
  private static final
916
    Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };
917
 
918
  private ObjectStreamClass superClass;
919
  private Class clazz;
920
  private String name;
921
  private long uid;
922
  private byte flags;
923
 
924
  // this field is package protected so that ObjectInputStream and
925
  // ObjectOutputStream can access it directly
926
  ObjectStreamField[] fields;
927
 
928
  // these are accessed by ObjectIn/OutputStream
929
  int primFieldSize = -1;  // -1 if not yet calculated
930
  int objectFieldCount;
931
 
932
  Method readObjectMethod;
933
  Method readResolveMethod;
934
  Method writeReplaceMethod;
935
  Method writeObjectMethod;
936
  boolean realClassIsSerializable;
937
  boolean realClassIsExternalizable;
938
  ObjectStreamField[] fieldMapping;
939
  Constructor firstNonSerializableParentConstructor;
940
  private Constructor constructor;  // default constructor for Externalizable
941
 
942
  boolean isProxyClass = false;
943
 
944
  // This is probably not necessary because this class is special cased already
945
  // but it will avoid showing up as a discrepancy when comparing SUIDs.
946
  private static final long serialVersionUID = -6120832682080437368L;
947
 
948
 
949
  // interfaces are compared only by name
950
  private static final class InterfaceComparator implements Comparator
951
  {
952
    public int compare(Object o1, Object o2)
953
    {
954
      return ((Class) o1).getName().compareTo(((Class) o2).getName());
955
    }
956
  }
957
 
958
 
959
  // Members (Methods and Constructors) are compared first by name,
960
  // conflicts are resolved by comparing type signatures
961
  private static final class MemberComparator implements Comparator
962
  {
963
    public int compare(Object o1, Object o2)
964
    {
965
      Member m1 = (Member) o1;
966
      Member m2 = (Member) o2;
967
 
968
      int comp = m1.getName().compareTo(m2.getName());
969
 
970
      if (comp == 0)
971
        return TypeSignature.getEncodingOfMember(m1).
972
          compareTo(TypeSignature.getEncodingOfMember(m2));
973
      else
974
        return comp;
975
    }
976
  }
977
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.