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/] [ObjectOutputStream.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* ObjectOutputStream.java -- Class used to write serialized objects
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3
   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.ObjectIdentityWrapper;
43
import gnu.java.lang.reflect.TypeSignature;
44
import gnu.java.security.action.SetAccessibleAction;
45
 
46
import java.lang.reflect.Array;
47
import java.lang.reflect.Field;
48
import java.lang.reflect.InvocationTargetException;
49
import java.lang.reflect.Method;
50
import java.security.AccessController;
51
import java.util.Hashtable;
52
 
53
/**
54
 * An <code>ObjectOutputStream</code> can be used to write objects
55
 * as well as primitive data in a platform-independent manner to an
56
 * <code>OutputStream</code>.
57
 *
58
 * The data produced by an <code>ObjectOutputStream</code> can be read
59
 * and reconstituted by an <code>ObjectInputStream</code>.
60
 *
61
 * <code>writeObject (Object)</code> is used to write Objects, the
62
 * <code>write&lt;type&gt;</code> methods are used to write primitive
63
 * data (as in <code>DataOutputStream</code>). Strings can be written
64
 * as objects or as primitive data.
65
 *
66
 * Not all objects can be written out using an
67
 * <code>ObjectOutputStream</code>.  Only those objects that are an
68
 * instance of <code>java.io.Serializable</code> can be written.
69
 *
70
 * Using default serialization, information about the class of an
71
 * object is written, all of the non-transient, non-static fields of
72
 * the object are written, if any of these fields are objects, they are
73
 * written out in the same manner.
74
 *
75
 * An object is only written out the first time it is encountered.  If
76
 * the object is encountered later, a reference to it is written to
77
 * the underlying stream.  Thus writing circular object graphs
78
 * does not present a problem, nor are relationships between objects
79
 * in a graph lost.
80
 *
81
 * Example usage:
82
 * <pre>
83
 * Hashtable map = new Hashtable ();
84
 * map.put ("one", new Integer (1));
85
 * map.put ("two", new Integer (2));
86
 *
87
 * ObjectOutputStream oos =
88
 * new ObjectOutputStream (new FileOutputStream ("numbers"));
89
 * oos.writeObject (map);
90
 * oos.close ();
91
 *
92
 * ObjectInputStream ois =
93
 * new ObjectInputStream (new FileInputStream ("numbers"));
94
 * Hashtable newmap = (Hashtable)ois.readObject ();
95
 *
96
 * System.out.println (newmap);
97
 * </pre>
98
 *
99
 * The default serialization can be overriden in two ways.
100
 *
101
 * By defining a method <code>private void
102
 * writeObject (ObjectOutputStream)</code>, a class can dictate exactly
103
 * how information about itself is written.
104
 * <code>defaultWriteObject ()</code> may be called from this method to
105
 * carry out default serialization.  This method is not
106
 * responsible for dealing with fields of super-classes or subclasses.
107
 *
108
 * By implementing <code>java.io.Externalizable</code>.  This gives
109
 * the class complete control over the way it is written to the
110
 * stream.  If this approach is used the burden of writing superclass
111
 * and subclass data is transfered to the class implementing
112
 * <code>java.io.Externalizable</code>.
113
 *
114
 * @see java.io.DataOutputStream
115
 * @see java.io.Externalizable
116
 * @see java.io.ObjectInputStream
117
 * @see java.io.Serializable
118
 */
119
public class ObjectOutputStream extends OutputStream
120
  implements ObjectOutput, ObjectStreamConstants
121
{
122
  /**
123
   * Creates a new <code>ObjectOutputStream</code> that will do all of
124
   * its writing onto <code>out</code>.  This method also initializes
125
   * the stream by writing the header information (stream magic number
126
   * and stream version).
127
   *
128
   * @exception IOException Writing stream header to underlying
129
   * stream cannot be completed.
130
   *
131
   * @see #writeStreamHeader()
132
   */
133
  public ObjectOutputStream (OutputStream out) throws IOException
134
  {
135
    realOutput = new DataOutputStream(out);
136
    blockData = new byte[ BUFFER_SIZE ];
137
    blockDataCount = 0;
138
    blockDataOutput = new DataOutputStream(this);
139
    setBlockDataMode(true);
140
    replacementEnabled = false;
141
    isSerializing = false;
142
    nextOID = baseWireHandle;
143
    OIDLookupTable = new Hashtable();
144
    protocolVersion = defaultProtocolVersion;
145
    useSubclassMethod = false;
146
    writeStreamHeader();
147
 
148
    if (DEBUG)
149
      {
150
        String val = System.getProperty("gcj.dumpobjects");
151
        if (val != null && !val.equals(""))
152
          dump = true;
153
      }
154
  }
155
 
156
  /**
157
   * Writes a representation of <code>obj</code> to the underlying
158
   * output stream by writing out information about its class, then
159
   * writing out each of the objects non-transient, non-static
160
   * fields.  If any of these fields are other objects,
161
   * they are written out in the same manner.
162
   *
163
   * This method can be overriden by a class by implementing
164
   * <code>private void writeObject (ObjectOutputStream)</code>.
165
   *
166
   * If an exception is thrown from this method, the stream is left in
167
   * an undefined state.
168
   *
169
   * @exception NotSerializableException An attempt was made to
170
   * serialize an <code>Object</code> that is not serializable.
171
   *
172
   * @exception InvalidClassException Somebody tried to serialize
173
   * an object which is wrongly formatted.
174
   *
175
   * @exception IOException Exception from underlying
176
   * <code>OutputStream</code>.
177
   */
178
  public final void writeObject(Object obj) throws IOException
179
  {
180
    if (useSubclassMethod)
181
      {
182
        if (dump)
183
          dumpElementln ("WRITE OVERRIDE: " + obj);
184
 
185
        writeObjectOverride(obj);
186
        return;
187
      }
188
 
189
    if (dump)
190
      dumpElementln ("WRITE: " + obj);
191
 
192
    depth += 2;
193
 
194
    boolean was_serializing = isSerializing;
195
    boolean old_mode = setBlockDataMode(false);
196
    try
197
      {
198
        isSerializing = true;
199
        boolean replaceDone = false;
200
        Object replacedObject = null;
201
 
202
        while (true)
203
          {
204
            if (obj == null)
205
              {
206
                realOutput.writeByte(TC_NULL);
207
                break;
208
              }
209
 
210
            Integer handle = findHandle(obj);
211
            if (handle != null)
212
              {
213
                realOutput.writeByte(TC_REFERENCE);
214
                realOutput.writeInt(handle.intValue());
215
                break;
216
              }
217
 
218
            if (obj instanceof Class)
219
              {
220
                Class cl = (Class)obj;
221
                ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(cl);
222
                realOutput.writeByte(TC_CLASS);
223
                if (!osc.isProxyClass)
224
                  {
225
                    writeObject (osc);
226
                  }
227
                else
228
                  {
229
                    realOutput.writeByte(TC_PROXYCLASSDESC);
230
                    Class[] intfs = cl.getInterfaces();
231
                    realOutput.writeInt(intfs.length);
232
                    for (int i = 0; i < intfs.length; i++)
233
                      realOutput.writeUTF(intfs[i].getName());
234
 
235
                    boolean oldmode = setBlockDataMode(true);
236
                    annotateProxyClass(cl);
237
                    setBlockDataMode(oldmode);
238
                    realOutput.writeByte(TC_ENDBLOCKDATA);
239
 
240
                    writeObject(osc.getSuper());
241
                  }
242
                assignNewHandle(obj);
243
                break;
244
              }
245
 
246
            if (obj instanceof ObjectStreamClass)
247
              {
248
                writeClassDescriptor((ObjectStreamClass) obj);
249
                break;
250
              }
251
 
252
            Class clazz = obj.getClass();
253
            ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz);
254
            if (osc == null)
255
              throw new NotSerializableException(clazz.getName());
256
 
257
            if ((replacementEnabled || obj instanceof Serializable)
258
                && ! replaceDone)
259
              {
260
                replacedObject = obj;
261
 
262
                if (obj instanceof Serializable)
263
                  {
264
                    try
265
                      {
266
                        Method m = osc.writeReplaceMethod;
267
                        if (m != null)
268
                            obj = m.invoke(obj, new Object[0]);
269
                      }
270
                    catch (IllegalAccessException ignore)
271
                      {
272
                      }
273
                    catch (InvocationTargetException ignore)
274
                      {
275
                      }
276
                  }
277
 
278
                if (replacementEnabled)
279
                  obj = replaceObject(obj);
280
 
281
                replaceDone = true;
282
                continue;
283
              }
284
 
285
            if (obj instanceof String)
286
              {
287
                realOutput.writeByte(TC_STRING);
288
                assignNewHandle(obj);
289
                realOutput.writeUTF((String)obj);
290
                break;
291
              }
292
 
293
            if (clazz.isArray ())
294
              {
295
                realOutput.writeByte(TC_ARRAY);
296
                writeObject(osc);
297
                assignNewHandle(obj);
298
                writeArraySizeAndElements(obj, clazz.getComponentType());
299
                break;
300
              }
301
 
302
            realOutput.writeByte(TC_OBJECT);
303
            writeObject(osc);
304
 
305
            if (replaceDone)
306
              assignNewHandle(replacedObject);
307
            else
308
              assignNewHandle(obj);
309
 
310
            if (obj instanceof Externalizable)
311
              {
312
                if (protocolVersion == PROTOCOL_VERSION_2)
313
                  setBlockDataMode(true);
314
 
315
                ((Externalizable)obj).writeExternal(this);
316
 
317
                if (protocolVersion == PROTOCOL_VERSION_2)
318
                  {
319
                    setBlockDataMode(false);
320
                    realOutput.writeByte(TC_ENDBLOCKDATA);
321
                  }
322
 
323
                break;
324
              }
325
 
326
            if (obj instanceof Serializable)
327
              {
328
                Object prevObject = this.currentObject;
329
                ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
330
                currentObject = obj;
331
                ObjectStreamClass[] hierarchy =
332
                  ObjectStreamClass.getObjectStreamClasses(clazz);
333
 
334
                for (int i = 0; i < hierarchy.length; i++)
335
                  {
336
                    currentObjectStreamClass = hierarchy[i];
337
 
338
                    fieldsAlreadyWritten = false;
339
                    if (currentObjectStreamClass.hasWriteMethod())
340
                      {
341
                        if (dump)
342
                          dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
343
                        setBlockDataMode(true);
344
                        callWriteMethod(obj, currentObjectStreamClass);
345
                        setBlockDataMode(false);
346
                        realOutput.writeByte(TC_ENDBLOCKDATA);
347
                        if (dump)
348
                          dumpElementln ("WRITE ENDBLOCKDATA FOR: " + obj);
349
                      }
350
                    else
351
                      {
352
                        if (dump)
353
                          dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
354
                        writeFields(obj, currentObjectStreamClass);
355
                      }
356
                  }
357
 
358
                this.currentObject = prevObject;
359
                this.currentObjectStreamClass = prevObjectStreamClass;
360
                currentPutField = null;
361
                break;
362
              }
363
 
364
            throw new NotSerializableException(clazz.getName()
365
                                               + " in "
366
                                               + obj.getClass());
367
          } // end pseudo-loop
368
      }
369
    catch (ObjectStreamException ose)
370
      {
371
        // Rethrow these are fatal.
372
        throw ose;
373
      }
374
    catch (IOException e)
375
      {
376
        realOutput.writeByte(TC_EXCEPTION);
377
        reset(true);
378
 
379
        setBlockDataMode(false);
380
        try
381
          {
382
            if (DEBUG)
383
              {
384
                e.printStackTrace(System.out);
385
              }
386
            writeObject(e);
387
          }
388
        catch (IOException ioe)
389
          {
390
            StreamCorruptedException ex =
391
              new StreamCorruptedException
392
              (ioe + " thrown while exception was being written to stream.");
393
            if (DEBUG)
394
              {
395
                ex.printStackTrace(System.out);
396
              }
397
            throw ex;
398
          }
399
 
400
        reset (true);
401
 
402
      }
403
    finally
404
      {
405
        isSerializing = was_serializing;
406
        setBlockDataMode(old_mode);
407
        depth -= 2;
408
 
409
        if (dump)
410
          dumpElementln ("END: " + obj);
411
      }
412
  }
413
 
414
  protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException
415
  {
416
    if (osc.isProxyClass)
417
      {
418
        realOutput.writeByte(TC_PROXYCLASSDESC);
419
        Class[] intfs = osc.forClass().getInterfaces();
420
        realOutput.writeInt(intfs.length);
421
        for (int i = 0; i < intfs.length; i++)
422
          realOutput.writeUTF(intfs[i].getName());
423
 
424
        boolean oldmode = setBlockDataMode(true);
425
        annotateProxyClass(osc.forClass());
426
        setBlockDataMode(oldmode);
427
        realOutput.writeByte(TC_ENDBLOCKDATA);
428
      }
429
    else
430
      {
431
        realOutput.writeByte(TC_CLASSDESC);
432
        realOutput.writeUTF(osc.getName());
433
        realOutput.writeLong(osc.getSerialVersionUID());
434
        assignNewHandle(osc);
435
 
436
        int flags = osc.getFlags();
437
 
438
        if (protocolVersion == PROTOCOL_VERSION_2
439
            && osc.isExternalizable())
440
        flags |= SC_BLOCK_DATA;
441
 
442
        realOutput.writeByte(flags);
443
 
444
        ObjectStreamField[] fields = osc.fields;
445
        realOutput.writeShort(fields.length);
446
 
447
        ObjectStreamField field;
448
        for (int i = 0; i < fields.length; i++)
449
          {
450
            field = fields[i];
451
            realOutput.writeByte(field.getTypeCode ());
452
            realOutput.writeUTF(field.getName ());
453
 
454
            if (! field.isPrimitive())
455
              writeObject(field.getTypeString());
456
          }
457
 
458
        boolean oldmode = setBlockDataMode(true);
459
        annotateClass(osc.forClass());
460
        setBlockDataMode(oldmode);
461
        realOutput.writeByte(TC_ENDBLOCKDATA);
462
      }
463
 
464
    if (osc.isSerializable() || osc.isExternalizable())
465
      writeObject(osc.getSuper());
466
    else
467
      writeObject(null);
468
  }
469
 
470
  /**
471
   * Writes the current objects non-transient, non-static fields from
472
   * the current class to the underlying output stream.
473
   *
474
   * This method is intended to be called from within a object's
475
   * <code>private void writeObject (ObjectOutputStream)</code>
476
   * method.
477
   *
478
   * @exception NotActiveException This method was called from a
479
   * context other than from the current object's and current class's
480
   * <code>private void writeObject (ObjectOutputStream)</code>
481
   * method.
482
   *
483
   * @exception IOException Exception from underlying
484
   * <code>OutputStream</code>.
485
   */
486
  public void defaultWriteObject()
487
    throws IOException, NotActiveException
488
  {
489
    markFieldsWritten();
490
    writeFields(currentObject, currentObjectStreamClass);
491
  }
492
 
493
 
494
  private void markFieldsWritten() throws IOException
495
  {
496
    if (currentObject == null || currentObjectStreamClass == null)
497
      throw new NotActiveException
498
        ("defaultWriteObject called by non-active class and/or object");
499
 
500
    if (fieldsAlreadyWritten)
501
      throw new IOException
502
        ("Only one of writeFields and defaultWriteObject may be called, and it may only be called once");
503
 
504
    fieldsAlreadyWritten = true;
505
  }
506
 
507
  /**
508
   * Resets stream to state equivalent to the state just after it was
509
   * constructed.
510
   *
511
   * Causes all objects previously written to the stream to be
512
   * forgotten.  A notification of this reset is also written to the
513
   * underlying stream.
514
   *
515
   * @exception IOException Exception from underlying
516
   * <code>OutputStream</code> or reset called while serialization is
517
   * in progress.
518
   */
519
  public void reset() throws IOException
520
  {
521
    reset(false);
522
  }
523
 
524
 
525
  private void reset(boolean internal) throws IOException
526
  {
527
    if (!internal)
528
      {
529
        if (isSerializing)
530
          throw new IOException("Reset called while serialization in progress");
531
 
532
        realOutput.writeByte(TC_RESET);
533
      }
534
 
535
    clearHandles();
536
  }
537
 
538
 
539
  /**
540
   * Informs this <code>ObjectOutputStream</code> to write data
541
   * according to the specified protocol.  There are currently two
542
   * different protocols, specified by <code>PROTOCOL_VERSION_1</code>
543
   * and <code>PROTOCOL_VERSION_2</code>.  This implementation writes
544
   * data using <code>PROTOCOL_VERSION_2</code> by default, as is done
545
   * by the JDK 1.2.
546
   *
547
   * A non-portable method, <code>setDefaultProtocolVersion (int
548
   * version)</code> is provided to change the default protocol
549
   * version.
550
   *
551
   * For an explanation of the differences between the two protocols
552
   * see XXX: the Java ObjectSerialization Specification.
553
   *
554
   * @exception IOException if <code>version</code> is not a valid
555
   * protocol
556
   *
557
   * @see #setDefaultProtocolVersion(int)
558
   */
559
  public void useProtocolVersion(int version) throws IOException
560
  {
561
    if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
562
      throw new IOException("Invalid protocol version requested.");
563
 
564
    protocolVersion = version;
565
  }
566
 
567
 
568
  /**
569
   * <em>GNU $classpath specific</em>
570
   *
571
   * Changes the default stream protocol used by all
572
   * <code>ObjectOutputStream</code>s.  There are currently two
573
   * different protocols, specified by <code>PROTOCOL_VERSION_1</code>
574
   * and <code>PROTOCOL_VERSION_2</code>.  The default default is
575
   * <code>PROTOCOL_VERSION_1</code>.
576
   *
577
   * @exception IOException if <code>version</code> is not a valid
578
   * protocol
579
   *
580
   * @see #useProtocolVersion(int)
581
   */
582
  public static void setDefaultProtocolVersion(int version)
583
    throws IOException
584
  {
585
    if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
586
      throw new IOException("Invalid protocol version requested.");
587
 
588
    defaultProtocolVersion = version;
589
  }
590
 
591
 
592
  /**
593
   * An empty hook that allows subclasses to write extra information
594
   * about classes to the stream.  This method is called the first
595
   * time each class is seen, and after all of the standard
596
   * information about the class has been written.
597
   *
598
   * @exception IOException Exception from underlying
599
   * <code>OutputStream</code>.
600
   *
601
   * @see ObjectInputStream#resolveClass(java.io.ObjectStreamClass)
602
   */
603
  protected void annotateClass(Class cl) throws IOException
604
  {
605
  }
606
 
607
  protected void annotateProxyClass(Class cl) throws IOException
608
  {
609
  }
610
 
611
  /**
612
   * Allows subclasses to replace objects that are written to the
613
   * stream with other objects to be written in their place.  This
614
   * method is called the first time each object is encountered
615
   * (modulo reseting of the stream).
616
   *
617
   * This method must be enabled before it will be called in the
618
   * serialization process.
619
   *
620
   * @exception IOException Exception from underlying
621
   * <code>OutputStream</code>.
622
   *
623
   * @see #enableReplaceObject(boolean)
624
   */
625
  protected Object replaceObject(Object obj) throws IOException
626
  {
627
    return obj;
628
  }
629
 
630
 
631
  /**
632
   * If <code>enable</code> is <code>true</code> and this object is
633
   * trusted, then <code>replaceObject (Object)</code> will be called
634
   * in subsequent calls to <code>writeObject (Object)</code>.
635
   * Otherwise, <code>replaceObject (Object)</code> will not be called.
636
   *
637
   * @exception SecurityException This class is not trusted.
638
   */
639
  protected boolean enableReplaceObject(boolean enable)
640
    throws SecurityException
641
  {
642
    if (enable)
643
      {
644
        SecurityManager sm = System.getSecurityManager();
645
        if (sm != null)
646
          sm.checkPermission(new SerializablePermission("enableSubstitution"));
647
      }
648
 
649
    boolean old_val = replacementEnabled;
650
    replacementEnabled = enable;
651
    return old_val;
652
  }
653
 
654
 
655
  /**
656
   * Writes stream magic and stream version information to the
657
   * underlying stream.
658
   *
659
   * @exception IOException Exception from underlying
660
   * <code>OutputStream</code>.
661
   */
662
  protected void writeStreamHeader() throws IOException
663
  {
664
    realOutput.writeShort(STREAM_MAGIC);
665
    realOutput.writeShort(STREAM_VERSION);
666
  }
667
 
668
  /**
669
   * Protected constructor that allows subclasses to override
670
   * serialization.  This constructor should be called by subclasses
671
   * that wish to override <code>writeObject (Object)</code>.  This
672
   * method does a security check <i>NOTE: currently not
673
   * implemented</i>, then sets a flag that informs
674
   * <code>writeObject (Object)</code> to call the subclasses
675
   * <code>writeObjectOverride (Object)</code> method.
676
   *
677
   * @see #writeObjectOverride(Object)
678
   */
679
  protected ObjectOutputStream() throws IOException, SecurityException
680
  {
681
    SecurityManager sec_man = System.getSecurityManager ();
682
    if (sec_man != null)
683
      sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
684
    useSubclassMethod = true;
685
  }
686
 
687
 
688
  /**
689
   * This method allows subclasses to override the default
690
   * serialization mechanism provided by
691
   * <code>ObjectOutputStream</code>.  To make this method be used for
692
   * writing objects, subclasses must invoke the 0-argument
693
   * constructor on this class from there constructor.
694
   *
695
   * @see #ObjectOutputStream()
696
   *
697
   * @exception NotActiveException Subclass has arranged for this
698
   * method to be called, but did not implement this method.
699
   */
700
  protected void writeObjectOverride(Object obj) throws NotActiveException,
701
    IOException
702
  {
703
    throw new NotActiveException
704
      ("Subclass of ObjectOutputStream must implement writeObjectOverride");
705
  }
706
 
707
 
708
  /**
709
   * @see DataOutputStream#write(int)
710
   */
711
  public void write (int data) throws IOException
712
  {
713
    if (writeDataAsBlocks)
714
      {
715
        if (blockDataCount == BUFFER_SIZE)
716
          drain();
717
 
718
        blockData[ blockDataCount++ ] = (byte)data;
719
      }
720
    else
721
      realOutput.write(data);
722
  }
723
 
724
 
725
  /**
726
   * @see DataOutputStream#write(byte[])
727
   */
728
  public void write(byte[] b) throws IOException
729
  {
730
    write(b, 0, b.length);
731
  }
732
 
733
 
734
  /**
735
   * @see DataOutputStream#write(byte[],int,int)
736
   */
737
  public void write(byte[] b, int off, int len) throws IOException
738
  {
739
    if (writeDataAsBlocks)
740
      {
741
        if (len < 0)
742
          throw new IndexOutOfBoundsException();
743
 
744
        if (blockDataCount + len < BUFFER_SIZE)
745
          {
746
            System.arraycopy(b, off, blockData, blockDataCount, len);
747
            blockDataCount += len;
748
          }
749
        else
750
          {
751
            drain();
752
            writeBlockDataHeader(len);
753
            realOutput.write(b, off, len);
754
          }
755
      }
756
    else
757
      realOutput.write(b, off, len);
758
  }
759
 
760
 
761
  /**
762
   * @see DataOutputStream#flush()
763
   */
764
  public void flush () throws IOException
765
  {
766
    drain();
767
    realOutput.flush();
768
  }
769
 
770
 
771
  /**
772
   * Causes the block-data buffer to be written to the underlying
773
   * stream, but does not flush underlying stream.
774
   *
775
   * @exception IOException Exception from underlying
776
   * <code>OutputStream</code>.
777
   */
778
  protected void drain() throws IOException
779
  {
780
    if (blockDataCount == 0)
781
      return;
782
 
783
    if (writeDataAsBlocks)
784
      writeBlockDataHeader(blockDataCount);
785
    realOutput.write(blockData, 0, blockDataCount);
786
    blockDataCount = 0;
787
  }
788
 
789
 
790
  /**
791
   * @see java.io.DataOutputStream#close ()
792
   */
793
  public void close() throws IOException
794
  {
795
    flush();
796
    realOutput.close();
797
  }
798
 
799
 
800
  /**
801
   * @see java.io.DataOutputStream#writeBoolean (boolean)
802
   */
803
  public void writeBoolean(boolean data) throws IOException
804
  {
805
    blockDataOutput.writeBoolean(data);
806
  }
807
 
808
 
809
  /**
810
   * @see java.io.DataOutputStream#writeByte (int)
811
   */
812
  public void writeByte(int data) throws IOException
813
  {
814
    blockDataOutput.writeByte(data);
815
  }
816
 
817
 
818
  /**
819
   * @see java.io.DataOutputStream#writeShort (int)
820
   */
821
  public void writeShort (int data) throws IOException
822
  {
823
    blockDataOutput.writeShort(data);
824
  }
825
 
826
 
827
  /**
828
   * @see java.io.DataOutputStream#writeChar (int)
829
   */
830
  public void writeChar(int data) throws IOException
831
  {
832
    blockDataOutput.writeChar(data);
833
  }
834
 
835
 
836
  /**
837
   * @see java.io.DataOutputStream#writeInt (int)
838
   */
839
  public void writeInt(int data) throws IOException
840
  {
841
    blockDataOutput.writeInt(data);
842
  }
843
 
844
 
845
  /**
846
   * @see java.io.DataOutputStream#writeLong (long)
847
   */
848
  public void writeLong(long data) throws IOException
849
  {
850
    blockDataOutput.writeLong(data);
851
  }
852
 
853
 
854
  /**
855
   * @see java.io.DataOutputStream#writeFloat (float)
856
   */
857
  public void writeFloat(float data) throws IOException
858
  {
859
    blockDataOutput.writeFloat(data);
860
  }
861
 
862
 
863
  /**
864
   * @see java.io.DataOutputStream#writeDouble (double)
865
   */
866
  public void writeDouble(double data) throws IOException
867
  {
868
    blockDataOutput.writeDouble(data);
869
  }
870
 
871
 
872
  /**
873
   * @see java.io.DataOutputStream#writeBytes (java.lang.String)
874
   */
875
  public void writeBytes(String data) throws IOException
876
  {
877
    blockDataOutput.writeBytes(data);
878
  }
879
 
880
 
881
  /**
882
   * @see java.io.DataOutputStream#writeChars (java.lang.String)
883
   */
884
  public void writeChars(String data) throws IOException
885
  {
886
    dataOutput.writeChars(data);
887
  }
888
 
889
 
890
  /**
891
   * @see java.io.DataOutputStream#writeUTF (java.lang.String)
892
   */
893
  public void writeUTF(String data) throws IOException
894
  {
895
    dataOutput.writeUTF(data);
896
  }
897
 
898
 
899
  /**
900
   * This class allows a class to specify exactly which fields should
901
   * be written, and what values should be written for these fields.
902
   *
903
   * XXX: finish up comments
904
   */
905
  public abstract static class PutField
906
  {
907
    public abstract void put (String name, boolean value);
908
    public abstract void put (String name, byte value);
909
    public abstract void put (String name, char value);
910
    public abstract void put (String name, double value);
911
    public abstract void put (String name, float value);
912
    public abstract void put (String name, int value);
913
    public abstract void put (String name, long value);
914
    public abstract void put (String name, short value);
915
    public abstract void put (String name, Object value);
916
 
917
    /**
918
     * @deprecated
919
     */
920
    public abstract void write (ObjectOutput out) throws IOException;
921
  }
922
 
923
  public PutField putFields() throws IOException
924
  {
925
    if (currentPutField != null)
926
      return currentPutField;
927
 
928
    currentPutField = new PutField()
929
      {
930
        private byte[] prim_field_data
931
          = new byte[currentObjectStreamClass.primFieldSize];
932
        private Object[] objs
933
          = new Object[currentObjectStreamClass.objectFieldCount];
934
 
935
        private ObjectStreamField getField (String name)
936
        {
937
          ObjectStreamField field
938
            = currentObjectStreamClass.getField(name);
939
 
940
          if (field == null)
941
            throw new IllegalArgumentException("no such serializable field " + name);
942
 
943
          return field;
944
        }
945
 
946
        public void put(String name, boolean value)
947
        {
948
          ObjectStreamField field = getField(name);
949
 
950
          checkType(field, 'Z');
951
          prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
952
        }
953
 
954
        public void put(String name, byte value)
955
        {
956
          ObjectStreamField field = getField(name);
957
 
958
          checkType(field, 'B');
959
          prim_field_data[field.getOffset()] = value;
960
        }
961
 
962
        public void put(String name, char value)
963
        {
964
          ObjectStreamField field = getField(name);
965
 
966
          checkType(field, 'C');
967
          int off = field.getOffset();
968
          prim_field_data[off++] = (byte)(value >>> 8);
969
          prim_field_data[off] = (byte)value;
970
        }
971
 
972
        public void put(String name, double value)
973
        {
974
          ObjectStreamField field = getField (name);
975
 
976
          checkType(field, 'D');
977
          int off = field.getOffset();
978
          long l_value = Double.doubleToLongBits (value);
979
          prim_field_data[off++] = (byte)(l_value >>> 52);
980
          prim_field_data[off++] = (byte)(l_value >>> 48);
981
          prim_field_data[off++] = (byte)(l_value >>> 40);
982
          prim_field_data[off++] = (byte)(l_value >>> 32);
983
          prim_field_data[off++] = (byte)(l_value >>> 24);
984
          prim_field_data[off++] = (byte)(l_value >>> 16);
985
          prim_field_data[off++] = (byte)(l_value >>> 8);
986
          prim_field_data[off] = (byte)l_value;
987
        }
988
 
989
        public void put(String name, float value)
990
        {
991
          ObjectStreamField field = getField(name);
992
 
993
          checkType(field, 'F');
994
          int off = field.getOffset();
995
          int i_value = Float.floatToIntBits(value);
996
          prim_field_data[off++] = (byte)(i_value >>> 24);
997
          prim_field_data[off++] = (byte)(i_value >>> 16);
998
          prim_field_data[off++] = (byte)(i_value >>> 8);
999
          prim_field_data[off] = (byte)i_value;
1000
        }
1001
 
1002
        public void put(String name, int value)
1003
        {
1004
          ObjectStreamField field = getField(name);
1005
          checkType(field, 'I');
1006
          int off = field.getOffset();
1007
          prim_field_data[off++] = (byte)(value >>> 24);
1008
          prim_field_data[off++] = (byte)(value >>> 16);
1009
          prim_field_data[off++] = (byte)(value >>> 8);
1010
          prim_field_data[off] = (byte)value;
1011
        }
1012
 
1013
        public void put(String name, long value)
1014
        {
1015
          ObjectStreamField field = getField(name);
1016
          checkType(field, 'J');
1017
          int off = field.getOffset();
1018
          prim_field_data[off++] = (byte)(value >>> 52);
1019
          prim_field_data[off++] = (byte)(value >>> 48);
1020
          prim_field_data[off++] = (byte)(value >>> 40);
1021
          prim_field_data[off++] = (byte)(value >>> 32);
1022
          prim_field_data[off++] = (byte)(value >>> 24);
1023
          prim_field_data[off++] = (byte)(value >>> 16);
1024
          prim_field_data[off++] = (byte)(value >>> 8);
1025
          prim_field_data[off] = (byte)value;
1026
        }
1027
 
1028
        public void put(String name, short value)
1029
        {
1030
          ObjectStreamField field = getField(name);
1031
          checkType(field, 'S');
1032
          int off = field.getOffset();
1033
          prim_field_data[off++] = (byte)(value >>> 8);
1034
          prim_field_data[off] = (byte)value;
1035
        }
1036
 
1037
        public void put(String name, Object value)
1038
        {
1039
          ObjectStreamField field = getField(name);
1040
 
1041
          if (value != null &&
1042
              ! field.getType().isAssignableFrom(value.getClass ()))
1043
            throw new IllegalArgumentException("Class " + value.getClass() +
1044
                                               " cannot be cast to " + field.getType());
1045
          objs[field.getOffset()] = value;
1046
        }
1047
 
1048
        public void write(ObjectOutput out) throws IOException
1049
        {
1050
          // Apparently Block data is not used with PutField as per
1051
          // empirical evidence against JDK 1.2.  Also see Mauve test
1052
          // java.io.ObjectInputOutput.Test.GetPutField.
1053
          boolean oldmode = setBlockDataMode(false);
1054
          out.write(prim_field_data);
1055
          for (int i = 0; i < objs.length; ++ i)
1056
            out.writeObject(objs[i]);
1057
          setBlockDataMode(oldmode);
1058
        }
1059
 
1060
        private void checkType(ObjectStreamField field, char type)
1061
          throws IllegalArgumentException
1062
        {
1063
          if (TypeSignature.getEncodingOfClass(field.getType()).charAt(0)
1064
              != type)
1065
            throw new IllegalArgumentException();
1066
        }
1067
      };
1068
    // end PutFieldImpl
1069
 
1070
    return currentPutField;
1071
  }
1072
 
1073
 
1074
  public void writeFields() throws IOException
1075
  {
1076
    if (currentPutField == null)
1077
      throw new NotActiveException("writeFields can only be called after putFields has been called");
1078
 
1079
    markFieldsWritten();
1080
    currentPutField.write(this);
1081
  }
1082
 
1083
 
1084
  // write out the block-data buffer, picking the correct header
1085
  // depending on the size of the buffer
1086
  private void writeBlockDataHeader(int size) throws IOException
1087
  {
1088
    if (size < 256)
1089
      {
1090
        realOutput.writeByte(TC_BLOCKDATA);
1091
        realOutput.write(size);
1092
      }
1093
    else
1094
      {
1095
        realOutput.writeByte(TC_BLOCKDATALONG);
1096
        realOutput.writeInt(size);
1097
      }
1098
  }
1099
 
1100
 
1101
  // lookup the handle for OBJ, return null if OBJ doesn't have a
1102
  // handle yet
1103
  private Integer findHandle(Object obj)
1104
  {
1105
    return (Integer)OIDLookupTable.get(new ObjectIdentityWrapper(obj));
1106
  }
1107
 
1108
 
1109
  // assigns the next availible handle to OBJ
1110
  private int assignNewHandle(Object obj)
1111
  {
1112
    OIDLookupTable.put(new ObjectIdentityWrapper(obj),
1113
                       new Integer(nextOID));
1114
    return nextOID++;
1115
  }
1116
 
1117
 
1118
  // resets mapping from objects to handles
1119
  private void clearHandles()
1120
  {
1121
    nextOID = baseWireHandle;
1122
    OIDLookupTable.clear();
1123
  }
1124
 
1125
 
1126
  // write out array size followed by each element of the array
1127
  private void writeArraySizeAndElements(Object array, Class clazz)
1128
    throws IOException
1129
  {
1130
    int length = Array.getLength(array);
1131
 
1132
    if (clazz.isPrimitive())
1133
      {
1134
        if (clazz == Boolean.TYPE)
1135
          {
1136
            boolean[] cast_array = (boolean[])array;
1137
            realOutput.writeInt (length);
1138
            for (int i = 0; i < length; i++)
1139
              realOutput.writeBoolean(cast_array[i]);
1140
            return;
1141
          }
1142
        if (clazz == Byte.TYPE)
1143
          {
1144
            byte[] cast_array = (byte[])array;
1145
            realOutput.writeInt(length);
1146
            realOutput.write(cast_array, 0, length);
1147
            return;
1148
          }
1149
        if (clazz == Character.TYPE)
1150
          {
1151
            char[] cast_array = (char[])array;
1152
            realOutput.writeInt(length);
1153
            for (int i = 0; i < length; i++)
1154
              realOutput.writeChar(cast_array[i]);
1155
            return;
1156
          }
1157
        if (clazz == Double.TYPE)
1158
          {
1159
            double[] cast_array = (double[])array;
1160
            realOutput.writeInt(length);
1161
            for (int i = 0; i < length; i++)
1162
              realOutput.writeDouble(cast_array[i]);
1163
            return;
1164
          }
1165
        if (clazz == Float.TYPE)
1166
          {
1167
            float[] cast_array = (float[])array;
1168
            realOutput.writeInt(length);
1169
            for (int i = 0; i < length; i++)
1170
              realOutput.writeFloat(cast_array[i]);
1171
            return;
1172
          }
1173
        if (clazz == Integer.TYPE)
1174
          {
1175
            int[] cast_array = (int[])array;
1176
            realOutput.writeInt(length);
1177
            for (int i = 0; i < length; i++)
1178
              realOutput.writeInt(cast_array[i]);
1179
            return;
1180
          }
1181
        if (clazz == Long.TYPE)
1182
          {
1183
            long[] cast_array = (long[])array;
1184
            realOutput.writeInt (length);
1185
            for (int i = 0; i < length; i++)
1186
              realOutput.writeLong(cast_array[i]);
1187
            return;
1188
          }
1189
        if (clazz == Short.TYPE)
1190
          {
1191
            short[] cast_array = (short[])array;
1192
            realOutput.writeInt (length);
1193
            for (int i = 0; i < length; i++)
1194
              realOutput.writeShort(cast_array[i]);
1195
            return;
1196
          }
1197
      }
1198
    else
1199
      {
1200
        Object[] cast_array = (Object[])array;
1201
        realOutput.writeInt(length);
1202
        for (int i = 0; i < length; i++)
1203
          writeObject(cast_array[i]);
1204
      }
1205
  }
1206
 
1207
 
1208
  // writes out FIELDS of OBJECT for the specified ObjectStreamClass.
1209
  // FIELDS are already in canonical order.
1210
  private void writeFields(Object obj, ObjectStreamClass osc)
1211
    throws IOException
1212
  {
1213
    ObjectStreamField[] fields = osc.fields;
1214
    boolean oldmode = setBlockDataMode(false);
1215
    String field_name;
1216
    Class type;
1217
 
1218
    for (int i = 0; i < fields.length; i++)
1219
      {
1220
        field_name = fields[i].getName();
1221
        type = fields[i].getType();
1222
 
1223
        if (dump)
1224
          dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);
1225
 
1226
        if (type == Boolean.TYPE)
1227
          realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
1228
        else if (type == Byte.TYPE)
1229
          realOutput.writeByte(getByteField(obj, osc.forClass(), field_name));
1230
        else if (type == Character.TYPE)
1231
          realOutput.writeChar(getCharField(obj, osc.forClass(), field_name));
1232
        else if (type == Double.TYPE)
1233
          realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name));
1234
        else if (type == Float.TYPE)
1235
          realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name));
1236
        else if (type == Integer.TYPE)
1237
          realOutput.writeInt(getIntField(obj, osc.forClass(), field_name));
1238
        else if (type == Long.TYPE)
1239
          realOutput.writeLong(getLongField(obj, osc.forClass(), field_name));
1240
        else if (type == Short.TYPE)
1241
          realOutput.writeShort(getShortField(obj, osc.forClass(), field_name));
1242
        else
1243
          writeObject(getObjectField(obj, osc.forClass(), field_name,
1244
                                     fields[i].getTypeString ()));
1245
      }
1246
    setBlockDataMode(oldmode);
1247
  }
1248
 
1249
 
1250
  // Toggles writing primitive data to block-data buffer.
1251
  // Package-private to avoid a trampoline constructor.
1252
  boolean setBlockDataMode(boolean on) throws IOException
1253
  {
1254
    if (on == writeDataAsBlocks)
1255
      return on;
1256
 
1257
    drain();
1258
    boolean oldmode = writeDataAsBlocks;
1259
    writeDataAsBlocks = on;
1260
 
1261
    if (on)
1262
      dataOutput = blockDataOutput;
1263
    else
1264
      dataOutput = realOutput;
1265
 
1266
    return oldmode;
1267
  }
1268
 
1269
 
1270
  private void callWriteMethod(Object obj, ObjectStreamClass osc)
1271
    throws IOException
1272
  {
1273
    currentPutField = null;
1274
    try
1275
      {
1276
        Object args[] = {this};
1277
        osc.writeObjectMethod.invoke(obj, args);
1278
      }
1279
    catch (InvocationTargetException x)
1280
      {
1281
        /* Rethrow if possible. */
1282
        Throwable exception = x.getTargetException();
1283
        if (exception instanceof RuntimeException)
1284
          throw (RuntimeException) exception;
1285
        if (exception instanceof IOException)
1286
          throw (IOException) exception;
1287
 
1288
        IOException ioe
1289
          = new IOException("Exception thrown from writeObject() on " +
1290
                            osc.forClass().getName() + ": " +
1291
                            exception.getClass().getName());
1292
        ioe.initCause(exception);
1293
        throw ioe;
1294
      }
1295
    catch (Exception x)
1296
      {
1297
        IOException ioe
1298
          = new IOException("Failure invoking writeObject() on " +
1299
                            osc.forClass().getName() + ": " +
1300
                            x.getClass().getName());
1301
        ioe.initCause(x);
1302
        throw ioe;
1303
      }
1304
  }
1305
 
1306
  private boolean getBooleanField(Object obj, Class klass, String field_name)
1307
    throws IOException
1308
  {
1309
    try
1310
      {
1311
        Field f = getField(klass, field_name);
1312
        boolean b = f.getBoolean(obj);
1313
        return b;
1314
      }
1315
    catch (IllegalArgumentException _)
1316
      {
1317
        throw new InvalidClassException
1318
          ("invalid requested type for field " + field_name + " in class " + klass.getName());
1319
      }
1320
    catch (IOException e)
1321
      {
1322
        throw e;
1323
      }
1324
    catch (Exception _)
1325
      {
1326
        throw new IOException("Unexpected exception " + _);
1327
      }
1328
  }
1329
 
1330
  private byte getByteField (Object obj, Class klass, String field_name)
1331
    throws IOException
1332
  {
1333
    try
1334
      {
1335
        Field f = getField (klass, field_name);
1336
        byte b = f.getByte (obj);
1337
        return b;
1338
      }
1339
    catch (IllegalArgumentException _)
1340
      {
1341
        throw new InvalidClassException
1342
          ("invalid requested type for field " + field_name + " in class " + klass.getName());
1343
      }
1344
    catch (IOException e)
1345
      {
1346
        throw e;
1347
      }
1348
    catch (Exception _)
1349
      {
1350
        throw new IOException("Unexpected exception " + _);
1351
      }
1352
  }
1353
 
1354
  private char getCharField (Object obj, Class klass, String field_name)
1355
    throws IOException
1356
  {
1357
    try
1358
      {
1359
        Field f = getField (klass, field_name);
1360
        char b = f.getChar (obj);
1361
        return b;
1362
      }
1363
    catch (IllegalArgumentException _)
1364
      {
1365
        throw new InvalidClassException
1366
          ("invalid requested type for field " + field_name + " in class " + klass.getName());
1367
      }
1368
    catch (IOException e)
1369
      {
1370
        throw e;
1371
      }
1372
    catch (Exception _)
1373
      {
1374
        throw new IOException("Unexpected exception " + _);
1375
      }
1376
  }
1377
 
1378
  private double getDoubleField (Object obj, Class klass, String field_name)
1379
    throws IOException
1380
  {
1381
    try
1382
      {
1383
        Field f = getField (klass, field_name);
1384
        double b = f.getDouble (obj);
1385
        return b;
1386
      }
1387
    catch (IllegalArgumentException _)
1388
      {
1389
        throw new InvalidClassException
1390
          ("invalid requested type for field " + field_name + " in class " + klass.getName());
1391
      }
1392
    catch (IOException e)
1393
      {
1394
        throw e;
1395
      }
1396
    catch (Exception _)
1397
      {
1398
        throw new IOException("Unexpected exception " + _);
1399
      }
1400
  }
1401
 
1402
  private float getFloatField (Object obj, Class klass, String field_name)
1403
    throws IOException
1404
  {
1405
    try
1406
      {
1407
        Field f = getField (klass, field_name);
1408
        float b = f.getFloat (obj);
1409
        return b;
1410
      }
1411
    catch (IllegalArgumentException _)
1412
      {
1413
        throw new InvalidClassException
1414
          ("invalid requested type for field " + field_name + " in class " + klass.getName());
1415
      }
1416
    catch (IOException e)
1417
      {
1418
        throw e;
1419
      }
1420
    catch (Exception _)
1421
      {
1422
        throw new IOException("Unexpected exception " + _);
1423
      }
1424
  }
1425
 
1426
  private int getIntField (Object obj, Class klass, String field_name)
1427
    throws IOException
1428
  {
1429
    try
1430
      {
1431
        Field f = getField (klass, field_name);
1432
        int b = f.getInt (obj);
1433
        return b;
1434
      }
1435
    catch (IllegalArgumentException _)
1436
      {
1437
        throw new InvalidClassException
1438
          ("invalid requested type for field " + field_name + " in class " + klass.getName());
1439
      }
1440
    catch (IOException e)
1441
      {
1442
        throw e;
1443
      }
1444
    catch (Exception _)
1445
      {
1446
        throw new IOException("Unexpected exception " + _);
1447
      }
1448
  }
1449
 
1450
  private long getLongField (Object obj, Class klass, String field_name)
1451
    throws IOException
1452
  {
1453
    try
1454
      {
1455
        Field f = getField (klass, field_name);
1456
        long b = f.getLong (obj);
1457
        return b;
1458
      }
1459
    catch (IllegalArgumentException _)
1460
      {
1461
        throw new InvalidClassException
1462
          ("invalid requested type for field " + field_name + " in class " + klass.getName());
1463
      }
1464
    catch (IOException e)
1465
      {
1466
        throw e;
1467
      }
1468
    catch (Exception _)
1469
      {
1470
        throw new IOException("Unexpected exception " + _);
1471
      }
1472
  }
1473
 
1474
  private short getShortField (Object obj, Class klass, String field_name)
1475
    throws IOException
1476
  {
1477
    try
1478
      {
1479
        Field f = getField (klass, field_name);
1480
        short b = f.getShort (obj);
1481
        return b;
1482
      }
1483
    catch (IllegalArgumentException _)
1484
      {
1485
        throw new InvalidClassException
1486
          ("invalid requested type for field " + field_name + " in class " + klass.getName());
1487
      }
1488
    catch (IOException e)
1489
      {
1490
       throw e;
1491
      }
1492
    catch (Exception _)
1493
      {
1494
        throw new IOException("Unexpected exception " + _);
1495
      }
1496
  }
1497
 
1498
  private Object getObjectField (Object obj, Class klass, String field_name,
1499
                                 String type_code) throws IOException
1500
  {
1501
    try
1502
      {
1503
        Field f = getField (klass, field_name);
1504
        ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType());
1505
 
1506
        /* if of is primitive something went wrong
1507
         * in the check for primitive classes in writeFields.
1508
         */
1509
        if (of.isPrimitive())
1510
          throw new InvalidClassException
1511
            ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field is primitive");
1512
 
1513
        if (!of.getTypeString().equals(type_code))
1514
            throw new InvalidClassException
1515
                ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field " + of + " has type string " + of.getTypeString() + " instead of " + type_code);
1516
 
1517
        Object o = f.get (obj);
1518
        // FIXME: We should check the type_code here
1519
        return o;
1520
      }
1521
    catch (IOException e)
1522
      {
1523
        throw e;
1524
      }
1525
    catch (Exception e)
1526
      {
1527
        throw new IOException ();
1528
      }
1529
  }
1530
 
1531
  private Field getField (Class klass, String name)
1532
    throws java.io.InvalidClassException
1533
  {
1534
    try
1535
      {
1536
        final Field f = klass.getDeclaredField(name);
1537
        setAccessible.setMember(f);
1538
        AccessController.doPrivileged(setAccessible);
1539
        return f;
1540
      }
1541
    catch (java.lang.NoSuchFieldException e)
1542
      {
1543
        throw new InvalidClassException
1544
          ("no field called " + name + " in class " + klass.getName());
1545
      }
1546
  }
1547
 
1548
  private void dumpElementln (String msg)
1549
  {
1550
    for (int i = 0; i < depth; i++)
1551
      System.out.print (" ");
1552
    System.out.print (Thread.currentThread() + ": ");
1553
    System.out.println(msg);
1554
  }
1555
 
1556
  // this value comes from 1.2 spec, but is used in 1.1 as well
1557
  private static final int BUFFER_SIZE = 1024;
1558
 
1559
  private static int defaultProtocolVersion = PROTOCOL_VERSION_2;
1560
 
1561
  private DataOutputStream dataOutput;
1562
  private boolean writeDataAsBlocks;
1563
  private DataOutputStream realOutput;
1564
  private DataOutputStream blockDataOutput;
1565
  private byte[] blockData;
1566
  private int blockDataCount;
1567
  private Object currentObject;
1568
  // Package-private to avoid a trampoline.
1569
  ObjectStreamClass currentObjectStreamClass;
1570
  private PutField currentPutField;
1571
  private boolean fieldsAlreadyWritten;
1572
  private boolean replacementEnabled;
1573
  private boolean isSerializing;
1574
  private int nextOID;
1575
  private Hashtable OIDLookupTable;
1576
  private int protocolVersion;
1577
  private boolean useSubclassMethod;
1578
  private SetAccessibleAction setAccessible = new SetAccessibleAction();
1579
 
1580
  // The nesting depth for debugging output
1581
  private int depth = 0;
1582
 
1583
  // Set if we're generating debugging dumps
1584
  private boolean dump = false;
1585
 
1586
  private static final boolean DEBUG = false;
1587
}

powered by: WebSVN 2.1.0

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