source: trunk/src/gcc/libjava/java/io/ObjectInputStream.java@ 2171

Last change on this file since 2171 was 1392, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 45.5 KB
Line 
1/* ObjectInputStream.java -- Class used to read serialized objects
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3
4This file is part of GNU Classpath.
5
6GNU Classpath is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Classpath is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Classpath; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1902111-1307 USA.
20
21Linking this library statically or dynamically with other modules is
22making a combined work based on this library. Thus, the terms and
23conditions of the GNU General Public License cover the whole
24combination.
25
26As a special exception, the copyright holders of this library give you
27permission to link this library with independent modules to produce an
28executable, regardless of the license terms of these independent
29modules, and to copy and distribute the resulting executable under
30terms of your choice, provided that you also meet, for each linked
31independent module, the terms and conditions of the license of that
32module. An independent module is a module which is not derived from
33or based on this library. If you modify this library, you may extend
34this exception to your version of the library, but you are not
35obligated to do so. If you do not wish to do so, delete this
36exception statement from your version. */
37
38
39package java.io;
40
41import java.lang.reflect.Array;
42import java.lang.reflect.Modifier;
43import java.lang.reflect.Proxy;
44import java.util.Arrays;
45import java.util.Hashtable;
46import java.util.Vector;
47
48import gnu.java.io.ObjectIdentityWrapper;
49import gnu.java.lang.reflect.TypeSignature;
50import java.lang.reflect.Field;
51import java.lang.reflect.Method;
52import java.lang.reflect.InvocationTargetException;
53
54import gnu.classpath.Configuration;
55
56public class ObjectInputStream extends InputStream
57 implements ObjectInput, ObjectStreamConstants
58{
59 /**
60 Creates a new <code>ObjectInputStream</code> that will do all of
61 its reading from <code>in</code>. This method also checks
62 the stream by reading the header information (stream magic number
63 and stream version).
64
65 @exception IOException Reading stream header from underlying
66 stream cannot be completed.
67
68 @exception StreamCorruptedException An invalid stream magic
69 number or stream version was read from the stream.
70
71 @see readStreamHeader ()
72 */
73 public ObjectInputStream (InputStream in)
74 throws IOException, StreamCorruptedException
75 {
76 if (Configuration.DEBUG)
77 {
78 String val = System.getProperty("gcj.dumpobjects");
79 if (dump == false && val != null && !val.equals(""))
80 {
81 dump = true;
82 System.out.println ("Serialization debugging enabled");
83 }
84 else if (dump == true && (val == null || val.equals("")))
85 {
86 dump = false;
87 System.out.println ("Serialization debugging disabled");
88 }
89 }
90
91 this.resolveEnabled = false;
92 this.isDeserializing = false;
93 this.blockDataPosition = 0;
94 this.blockDataBytes = 0;
95 this.blockData = new byte[BUFFER_SIZE];
96 this.blockDataInput = new DataInputStream (this);
97 this.realInputStream = new DataInputStream (in);
98 this.nextOID = baseWireHandle;
99 this.objectLookupTable = new Hashtable ();
100 this.validators = new Vector ();
101 setBlockDataMode (true);
102 readStreamHeader ();
103 }
104
105
106 /**
107 Returns the next deserialized object read from the underlying stream.
108
109 This method can be overriden by a class by implementing
110 <code>private void readObject (ObjectInputStream)</code>.
111
112 If an exception is thrown from this method, the stream is left in
113 an undefined state.
114
115 @exception ClassNotFoundException The class that an object being
116 read in belongs to cannot be found.
117
118 @exception IOException Exception from underlying
119 <code>InputStream</code>.
120 */
121 public final Object readObject () throws ClassNotFoundException, IOException
122 {
123 if (this.useSubclassMethod)
124 return readObjectOverride ();
125
126 boolean was_deserializing;
127
128 Object ret_val;
129 was_deserializing = this.isDeserializing;
130
131 boolean is_consumed = false;
132 boolean old_mode = setBlockDataMode (false);
133
134 this.isDeserializing = true;
135
136 byte marker = this.realInputStream.readByte ();
137 dumpElement ("MARKER: 0x" + Integer.toHexString(marker) + " ");
138
139 try
140 {
141 switch (marker)
142 {
143 case TC_ENDBLOCKDATA:
144 {
145 ret_val = null;
146 is_consumed = true;
147 break;
148 }
149
150 case TC_BLOCKDATA:
151 case TC_BLOCKDATALONG:
152 {
153 if (marker == TC_BLOCKDATALONG)
154 dumpElementln ("BLOCKDATALONG");
155 else
156 dumpElementln ("BLOCKDATA");
157 readNextBlock (marker);
158 throw new StreamCorruptedException ("Unexpected blockData");
159 }
160
161 case TC_NULL:
162 {
163 dumpElementln ("NULL");
164 ret_val = null;
165 break;
166 }
167
168 case TC_REFERENCE:
169 {
170 dumpElement ("REFERENCE ");
171 Integer oid = new Integer (this.realInputStream.readInt ());
172 dumpElementln (Integer.toHexString(oid.intValue()));
173 ret_val = ((ObjectIdentityWrapper)
174 this.objectLookupTable.get (oid)).object;
175 break;
176 }
177
178 case TC_CLASS:
179 {
180 dumpElementln ("CLASS");
181 ObjectStreamClass osc = (ObjectStreamClass)readObject ();
182 Class clazz = osc.forClass ();
183 assignNewHandle (clazz);
184 ret_val = clazz;
185 break;
186 }
187
188 case TC_PROXYCLASSDESC:
189 {
190 dumpElementln ("PROXYCLASS");
191 int n_intf = this.realInputStream.readInt();
192 String[] intfs = new String[n_intf];
193 for (int i = 0; i < n_intf; i++)
194 {
195 intfs[i] = this.realInputStream.readUTF();
196 System.out.println(intfs[i]);
197 }
198
199 boolean oldmode = setBlockDataMode (true);
200 Class cl = resolveProxyClass(intfs);
201 setBlockDataMode(oldmode);
202
203 ObjectStreamClass osc = ObjectStreamClass.lookup(cl);
204 assignNewHandle (osc);
205
206 if (!is_consumed)
207 {
208 byte b = this.realInputStream.readByte ();
209 if (b != TC_ENDBLOCKDATA)
210 throw new IOException ("Data annotated to class was not consumed." + b);
211 }
212 else
213 is_consumed = false;
214 ObjectStreamClass superosc = (ObjectStreamClass)readObject ();
215 osc.setSuperclass (superosc);
216 ret_val = osc;
217 break;
218 }
219
220 case TC_CLASSDESC:
221 {
222 dumpElement ("CLASSDESC NAME=");
223 String name = this.realInputStream.readUTF ();
224 dumpElement (name + "; UID=");
225 long uid = this.realInputStream.readLong ();
226 dumpElement (Long.toHexString(uid) + "; FLAGS=");
227 byte flags = this.realInputStream.readByte ();
228 dumpElement (Integer.toHexString(flags) + "; FIELD COUNT=");
229 short field_count = this.realInputStream.readShort ();
230 dumpElementln (Short.toString(field_count));
231 ObjectStreamField[] fields = new ObjectStreamField[field_count];
232 ObjectStreamClass osc = new ObjectStreamClass (name, uid,
233 flags, fields);
234 assignNewHandle (osc);
235
236 for (int i=0; i < field_count; i++)
237 {
238 dumpElement (" TYPE CODE=");
239 char type_code = (char)this.realInputStream.readByte ();
240 dumpElement (type_code + "; FIELD NAME=");
241 String field_name = this.realInputStream.readUTF ();
242 dumpElementln (field_name);
243 String class_name;
244
245 if (type_code == 'L' || type_code == '[')
246 class_name = (String)readObject ();
247 else
248 class_name = String.valueOf (type_code);
249
250 // There're many cases you can't get java.lang.Class from
251 // typename if your context class loader can't load it,
252 // then use typename to construct the field
253 fields[i] =
254 new ObjectStreamField (field_name, class_name);
255 }
256
257 boolean oldmode = setBlockDataMode (true);
258 osc.setClass (resolveClass (osc));
259 setBlockDataMode (oldmode);
260
261 if (!is_consumed)
262 {
263 byte b = this.realInputStream.readByte ();
264 if (b != TC_ENDBLOCKDATA)
265 throw new IOException ("Data annotated to class was not consumed." + b);
266 }
267 else
268 is_consumed = false;
269
270 osc.setSuperclass ((ObjectStreamClass)readObject ());
271 ret_val = osc;
272 break;
273 }
274
275 case TC_STRING:
276 case TC_LONGSTRING:
277 {
278 dumpElement ("STRING=");
279 String s = this.realInputStream.readUTF ();
280 dumpElementln (s);
281 ret_val = processResolution (s, assignNewHandle (s));
282 break;
283 }
284
285 case TC_ARRAY:
286 {
287 dumpElementln ("ARRAY");
288 ObjectStreamClass osc = (ObjectStreamClass)readObject ();
289 Class componentType = osc.forClass ().getComponentType ();
290 dumpElement ("ARRAY LENGTH=");
291 int length = this.realInputStream.readInt ();
292 dumpElementln (length + "; COMPONENT TYPE=" + componentType);
293 Object array = Array.newInstance (componentType, length);
294 int handle = assignNewHandle (array);
295 readArrayElements (array, componentType);
296 for (int i=0, len=Array.getLength(array); i < len; i++)
297 dumpElementln (" ELEMENT[" + i + "]=" + Array.get(array, i));
298 ret_val = processResolution (array, handle);
299 break;
300 }
301
302 case TC_OBJECT:
303 {
304 dumpElementln ("OBJECT");
305 ObjectStreamClass osc = (ObjectStreamClass)readObject ();
306 Class clazz = osc.forClass ();
307
308 if (!Serializable.class.isAssignableFrom (clazz))
309 throw new NotSerializableException (clazz + " is not Serializable, and thus cannot be deserialized.");
310
311 if (Externalizable.class.isAssignableFrom (clazz))
312 {
313 Externalizable obj = null;
314
315 try
316 {
317 obj = (Externalizable)clazz.newInstance ();
318 }
319 catch (InstantiationException e)
320 {
321 throw new ClassNotFoundException ("Instance of " + clazz
322 + " could not be created");
323 }
324 catch (IllegalAccessException e)
325 {
326 throw new ClassNotFoundException ("Instance of " + clazz
327 + " could not be created because class or zero-argument constructor is not accessible");
328 }
329 catch (NoSuchMethodError e)
330 {
331 throw new ClassNotFoundException ("Instance of " + clazz
332 + " could not be created because zero-argument constructor is not defined");
333 }
334
335 int handle = assignNewHandle (obj);
336
337 boolean read_from_blocks = ((osc.getFlags () & SC_BLOCK_DATA) != 0);
338
339 boolean oldmode = this.readDataFromBlock;
340 if (read_from_blocks)
341 setBlockDataMode (true);
342
343 obj.readExternal (this);
344
345 if (read_from_blocks)
346 setBlockDataMode (oldmode);
347
348 ret_val = processResolution (obj, handle);
349 break;
350 } // end if (Externalizable.class.isAssignableFrom (clazz))
351
352 // find the first non-serializable, non-abstract
353 // class in clazz's inheritance hierarchy
354 Class first_nonserial = clazz.getSuperclass ();
355 while (Serializable.class.isAssignableFrom (first_nonserial)
356 || Modifier.isAbstract (first_nonserial.getModifiers ()))
357 first_nonserial = first_nonserial.getSuperclass ();
358
359 Object obj = null;
360 obj = newObject (clazz, first_nonserial);
361
362 if (obj == null)
363 throw new ClassNotFoundException ("Instance of " + clazz +
364 " could not be created");
365
366 int handle = assignNewHandle (obj);
367 this.currentObject = obj;
368 ObjectStreamClass[] hierarchy =
369 ObjectStreamClass.getObjectStreamClasses (clazz);
370
371 for (int i=0; i < hierarchy.length; i++)
372 {
373 this.currentObjectStreamClass = hierarchy[i];
374
375 dumpElementln ("Reading fields of "
376 + this.currentObjectStreamClass.getName ());
377
378 // XXX: should initialize fields in classes in the hierarchy
379 // that aren't in the stream
380 // should skip over classes in the stream that aren't in the
381 // real classes hierarchy
382
383 if (this.currentObjectStreamClass.hasReadMethod())
384 {
385 fieldsAlreadyRead = false;
386 boolean oldmode = setBlockDataMode (true);
387 callReadMethod (obj, this.currentObjectStreamClass);
388 setBlockDataMode (oldmode);
389 dumpElement ("ENDBLOCKDATA? ");
390 try
391 {
392 // FIXME: XXX: This try block is to catch EOF which is
393 // thrown for some objects. That indicates a bug in the logic.
394 if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
395 throw new IOException ("No end of block data seen for class with readObject (ObjectInputStream) method.");
396 dumpElementln ("yes");
397 }
398 catch (EOFException e)
399 {
400 dumpElementln ("no, got EOFException");
401 }
402 catch (IOException e)
403 {
404 dumpElementln ("no, got IOException");
405 }
406 }
407 else
408 {
409 readFields (obj, currentObjectStreamClass);
410 }
411 }
412
413 this.currentObject = null;
414 this.currentObjectStreamClass = null;
415 ret_val = processResolution (obj, handle);
416 break;
417 }
418
419 case TC_RESET:
420 dumpElementln ("RESET");
421 clearHandles ();
422 ret_val = readObject ();
423 break;
424
425 case TC_EXCEPTION:
426 {
427 dumpElement ("EXCEPTION=");
428 Exception e = (Exception)readObject ();
429 dumpElementln (e.toString());
430 clearHandles ();
431 throw new WriteAbortedException ("Exception thrown during writing of stream", e);
432 }
433
434 default:
435 throw new IOException ("Unknown marker on stream: " + marker);
436 }
437 }
438 finally
439 {
440 setBlockDataMode (old_mode);
441
442 this.isDeserializing = was_deserializing;
443
444 if (! was_deserializing)
445 {
446 if (validators.size () > 0)
447 invokeValidators ();
448 }
449 }
450
451 return ret_val;
452 }
453
454 /**
455 Reads the current objects non-transient, non-static fields from
456 the current class from the underlying output stream.
457
458 This method is intended to be called from within a object's
459 <code>private void readObject (ObjectInputStream)</code>
460 method.
461
462 @exception ClassNotFoundException The class that an object being
463 read in belongs to cannot be found.
464
465 @exception NotActiveException This method was called from a
466 context other than from the current object's and current class's
467 <code>private void readObject (ObjectInputStream)</code>
468 method.
469
470 @exception IOException Exception from underlying
471 <code>OutputStream</code>.
472 */
473 public void defaultReadObject ()
474 throws ClassNotFoundException, IOException, NotActiveException
475 {
476 if (this.currentObject == null || this.currentObjectStreamClass == null)
477 throw new NotActiveException ("defaultReadObject called by non-active class and/or object");
478
479 if (fieldsAlreadyRead)
480 throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");
481
482 boolean oldmode = setBlockDataMode(false);
483 readFields (this.currentObject, this.currentObjectStreamClass);
484 setBlockDataMode(oldmode);
485
486 fieldsAlreadyRead = true;
487 }
488
489
490 /**
491 Registers a <code>ObjectInputValidation</code> to be carried out
492 on the object graph currently being deserialized before it is
493 returned to the original caller of <code>readObject ()</code>.
494 The order of validation for multiple
495 <code>ObjectInputValidation</code>s can be controled using
496 <code>priority</code>. Validators with higher priorities are
497 called first.
498
499 @see java.io.ObjectInputValidation
500
501 @exception InvalidObjectException <code>validator</code> is
502 <code>null</code>
503
504 @exception NotActiveException an attempt was made to add a
505 validator outside of the <code>readObject</code> method of the
506 object currently being deserialized
507 */
508 public void registerValidation (ObjectInputValidation validator,
509 int priority)
510 throws InvalidObjectException, NotActiveException
511 {
512 if (this.currentObject == null || this.currentObjectStreamClass == null)
513 throw new NotActiveException ("registerValidation called by non-active class and/or object");
514
515 if (validator == null)
516 throw new InvalidObjectException ("attempt to add a null ObjectInputValidation object");
517
518 this.validators.addElement (new ValidatorAndPriority (validator,
519 priority));
520 }
521
522
523 /**
524 Called when a class is being deserialized. This is a hook to
525 allow subclasses to read in information written by the
526 <code>annotateClass (Class)</code> method of an
527 <code>ObjectOutputStream</code>.
528
529 This implementation looks up the active call stack for a
530 <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,
531 it is used to load the class associated with <code>osc</code>,
532 otherwise, the default system <code>ClassLoader</code> is used.
533
534 @exception IOException Exception from underlying
535 <code>OutputStream</code>.
536
537 @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
538 */
539 protected Class resolveClass (ObjectStreamClass osc)
540 throws ClassNotFoundException, IOException
541 {
542 SecurityManager sm = System.getSecurityManager ();
543 if (sm == null)
544 sm = new SecurityManager () {};
545
546 // FIXME: currentClassLoader doesn't yet do anything useful. We need
547 // to call forName() with the classloader of the class which called
548 // readObject(). See SecurityManager.getClassContext().
549 ClassLoader cl = currentClassLoader (sm);
550
551 if (cl == null)
552 return Class.forName (osc.getName ());
553 else
554 return cl.loadClass (osc.getName ());
555 }
556
557 /**
558 Allows subclasses to resolve objects that are read from the
559 stream with other objects to be returned in their place. This
560 method is called the first time each object is encountered.
561
562 This method must be enabled before it will be called in the
563 serialization process.
564
565 @exception IOException Exception from underlying
566 <code>OutputStream</code>.
567
568 @see enableResolveObject (boolean)
569 */
570 protected Object resolveObject (Object obj) throws IOException
571 {
572 return obj;
573 }
574
575
576 protected Class resolveProxyClass (String[] intfs)
577 throws IOException, ClassNotFoundException
578 {
579 SecurityManager sm = System.getSecurityManager ();
580
581 if (sm == null)
582 sm = new SecurityManager () {};
583
584 ClassLoader cl = currentClassLoader (sm);
585
586 Class[] clss = new Class[intfs.length];
587 if(cl == null){
588 for (int i = 0; i < intfs.length; i++)
589 clss[i] = Class.forName(intfs[i]);
590 cl = ClassLoader.getSystemClassLoader();
591 }
592 else
593 for (int i = 0; i < intfs.length; i++)
594 clss[i] = cl.loadClass(intfs[i]);
595 try {
596 return Proxy.getProxyClass(cl, clss);
597 } catch (IllegalArgumentException e) {
598 throw new ClassNotFoundException(null, e);
599 }
600 }
601
602 /**
603 If <code>enable</code> is <code>true</code> and this object is
604 trusted, then <code>resolveObject (Object)</code> will be called
605 in subsequent calls to <code>readObject (Object)</code>.
606 Otherwise, <code>resolveObject (Object)</code> will not be called.
607
608 @exception SecurityException This class is not trusted.
609 */
610 protected boolean enableResolveObject (boolean enable)
611 throws SecurityException
612 {
613 if (enable)
614 {
615 SecurityManager sm = System.getSecurityManager ();
616 if (sm != null)
617 sm.checkPermission (new SerializablePermission ("enableSubstitution"));
618 }
619
620 boolean old_val = this.resolveEnabled;
621 this.resolveEnabled = enable;
622 return old_val;
623 }
624
625
626 /**
627 Reads stream magic and stream version information from the
628 underlying stream.
629
630 @exception IOException Exception from underlying stream.
631
632 @exception StreamCorruptedException An invalid stream magic
633 number or stream version was read from the stream.
634 */
635 protected void readStreamHeader ()
636 throws IOException, StreamCorruptedException
637 {
638 dumpElement ("STREAM MAGIC ");
639 if (this.realInputStream.readShort () != STREAM_MAGIC)
640 throw new StreamCorruptedException ("Invalid stream magic number");
641
642 dumpElementln ("STREAM VERSION ");
643 if (this.realInputStream.readShort () != STREAM_VERSION)
644 throw new StreamCorruptedException ("Invalid stream version number");
645 }
646
647
648 public int read () throws IOException
649 {
650 if (this.readDataFromBlock)
651 {
652 if (this.blockDataPosition >= this.blockDataBytes)
653 readNextBlock ();
654 return (this.blockData[this.blockDataPosition++] & 0xff);
655 }
656 else
657 return this.realInputStream.read ();
658 }
659
660 public int read (byte[] data, int offset, int length) throws IOException
661 {
662 if (this.readDataFromBlock)
663 {
664 if (this.blockDataPosition + length > this.blockDataBytes)
665 {
666 int remain = this.blockDataBytes - this.blockDataPosition;
667 if (remain != 0)
668 {
669 System.arraycopy (this.blockData, this.blockDataPosition,
670 data, offset, remain);
671 offset += remain;
672 length -= remain;
673 }
674 readNextBlock ();
675 }
676
677 System.arraycopy (this.blockData, this.blockDataPosition,
678 data, offset, length);
679 this.blockDataPosition += length;
680
681 return length;
682 }
683 else
684 return this.realInputStream.read (data, offset, length);
685 }
686
687 public int available () throws IOException
688 {
689 if (this.readDataFromBlock)
690 {
691 if (this.blockDataPosition >= this.blockDataBytes)
692 readNextBlock ();
693
694 return this.blockDataBytes - this.blockDataPosition;
695 }
696 else
697 return this.realInputStream.available ();
698 }
699
700 public void close () throws IOException
701 {
702 this.realInputStream.close ();
703 }
704
705 public boolean readBoolean () throws IOException
706 {
707 return this.dataInputStream.readBoolean ();
708 }
709
710 public byte readByte () throws IOException
711 {
712 return this.dataInputStream.readByte ();
713 }
714
715 public int readUnsignedByte () throws IOException
716 {
717 return this.dataInputStream.readUnsignedByte ();
718 }
719
720 public short readShort () throws IOException
721 {
722 return this.dataInputStream.readShort ();
723 }
724
725 public int readUnsignedShort () throws IOException
726 {
727 return this.dataInputStream.readUnsignedShort ();
728 }
729
730 public char readChar () throws IOException
731 {
732 return this.dataInputStream.readChar ();
733 }
734
735 public int readInt () throws IOException
736 {
737 return this.dataInputStream.readInt ();
738 }
739
740 public long readLong () throws IOException
741 {
742 return this.dataInputStream.readLong ();
743 }
744
745 public float readFloat () throws IOException
746 {
747 return this.dataInputStream.readFloat ();
748 }
749
750 public double readDouble () throws IOException
751 {
752 return this.dataInputStream.readDouble ();
753 }
754
755 public void readFully (byte data[]) throws IOException
756 {
757 this.dataInputStream.readFully (data);
758 }
759
760 public void readFully (byte data[], int offset, int size)
761 throws IOException
762 {
763 this.dataInputStream.readFully (data, offset, size);
764 }
765
766 public int skipBytes (int len) throws IOException
767 {
768 return this.dataInputStream.skipBytes (len);
769 }
770
771 /**
772 @deprecated
773 @see java.io.DataInputStream#readLine ()
774 */
775 public String readLine () throws IOException
776 {
777 return this.dataInputStream.readLine ();
778 }
779
780 public String readUTF () throws IOException
781 {
782 return this.dataInputStream.readUTF ();
783 }
784
785
786 /**
787 This class allows a class to specify exactly which fields should
788 be read, and what values should be read for these fields.
789
790 XXX: finish up comments
791 */
792 public static abstract class GetField
793 {
794 public abstract ObjectStreamClass getObjectStreamClass ();
795
796 public abstract boolean defaulted (String name)
797 throws IOException, IllegalArgumentException;
798
799 public abstract boolean get (String name, boolean defvalue)
800 throws IOException, IllegalArgumentException;
801
802 public abstract char get (String name, char defvalue)
803 throws IOException, IllegalArgumentException;
804
805 public abstract byte get (String name, byte defvalue)
806 throws IOException, IllegalArgumentException;
807
808 public abstract short get (String name, short defvalue)
809 throws IOException, IllegalArgumentException;
810
811 public abstract int get (String name, int defvalue)
812 throws IOException, IllegalArgumentException;
813
814 public abstract long get (String name, long defvalue)
815 throws IOException, IllegalArgumentException;
816
817 public abstract float get (String name, float defvalue)
818 throws IOException, IllegalArgumentException;
819
820 public abstract double get (String name, double defvalue)
821 throws IOException, IllegalArgumentException;
822
823 public abstract Object get (String name, Object defvalue)
824 throws IOException, IllegalArgumentException;
825 }
826
827 public GetField readFields ()
828 throws IOException, ClassNotFoundException, NotActiveException
829 {
830 if (this.currentObject == null || this.currentObjectStreamClass == null)
831 throw new NotActiveException ("readFields called by non-active class and/or object");
832
833 if (fieldsAlreadyRead)
834 throw new NotActiveException ("readFields called but fields already read from stream (by defaultReadObject or readFields)");
835
836 final ObjectStreamClass clazz = this.currentObjectStreamClass;
837 final byte[] prim_field_data = new byte[clazz.primFieldSize];
838 final Object[] objs = new Object[clazz.objectFieldCount];
839
840 // Apparently Block data is not used with GetField as per
841 // empirical evidence against JDK 1.2. Also see Mauve test
842 // java.io.ObjectInputOutput.Test.GetPutField.
843 boolean oldmode = setBlockDataMode (false);
844 readFully (prim_field_data);
845 for (int i = 0; i < objs.length; ++ i)
846 objs[i] = readObject ();
847 setBlockDataMode (oldmode);
848
849 return new GetField ()
850 {
851 public ObjectStreamClass getObjectStreamClass ()
852 {
853 return clazz;
854 }
855
856 public boolean defaulted (String name)
857 throws IOException, IllegalArgumentException
858 {
859 return clazz.getField (name) == null;
860 }
861
862 public boolean get (String name, boolean defvalue)
863 throws IOException, IllegalArgumentException
864 {
865 ObjectStreamField field = getField (name, Boolean.TYPE);
866
867 if (field == null)
868 return defvalue;
869
870 return prim_field_data[field.getOffset ()] == 0 ? false : true;
871 }
872
873 public char get (String name, char defvalue)
874 throws IOException, IllegalArgumentException
875 {
876 ObjectStreamField field = getField (name, Character.TYPE);
877
878 if (field == null)
879 return defvalue;
880
881 int off = field.getOffset ();
882
883 return (char)(((prim_field_data[off++] & 0xFF) << 8)
884 | (prim_field_data[off] & 0xFF));
885 }
886
887 public byte get (String name, byte defvalue)
888 throws IOException, IllegalArgumentException
889 {
890 ObjectStreamField field = getField (name, Byte.TYPE);
891
892 if (field == null)
893 return defvalue;
894
895 return prim_field_data[field.getOffset ()];
896 }
897
898 public short get (String name, short defvalue)
899 throws IOException, IllegalArgumentException
900 {
901 ObjectStreamField field = getField (name, Short.TYPE);
902
903 if (field == null)
904 return defvalue;
905
906 int off = field.getOffset ();
907
908 return (short)(((prim_field_data[off++] & 0xFF) << 8)
909 | (prim_field_data[off] & 0xFF));
910 }
911
912 public int get (String name, int defvalue)
913 throws IOException, IllegalArgumentException
914 {
915 ObjectStreamField field = getField (name, Integer.TYPE);
916
917 if (field == null)
918 return defvalue;
919
920 int off = field.getOffset ();
921
922 return ((prim_field_data[off++] & 0xFF) << 24)
923 | ((prim_field_data[off++] & 0xFF) << 16)
924 | ((prim_field_data[off++] & 0xFF) << 8)
925 | (prim_field_data[off] & 0xFF);
926 }
927
928 public long get (String name, long defvalue)
929 throws IOException, IllegalArgumentException
930 {
931 ObjectStreamField field = getField (name, Long.TYPE);
932
933 if (field == null)
934 return defvalue;
935
936 int off = field.getOffset ();
937
938 return (long)(((prim_field_data[off++] & 0xFF) << 56)
939 | ((prim_field_data[off++] & 0xFF) << 48)
940 | ((prim_field_data[off++] & 0xFF) << 40)
941 | ((prim_field_data[off++] & 0xFF) << 32)
942 | ((prim_field_data[off++] & 0xFF) << 24)
943 | ((prim_field_data[off++] & 0xFF) << 16)
944 | ((prim_field_data[off++] & 0xFF) << 8)
945 | (prim_field_data[off] & 0xFF));
946 }
947
948 public float get (String name, float defvalue)
949 throws IOException, IllegalArgumentException
950 {
951 ObjectStreamField field = getField (name, Float.TYPE);
952
953 if (field == null)
954 return defvalue;
955
956 int off = field.getOffset ();
957
958 return Float.intBitsToFloat (((prim_field_data[off++] & 0xFF) << 24)
959 | ((prim_field_data[off++] & 0xFF) << 16)
960 | ((prim_field_data[off++] & 0xFF) << 8)
961 | (prim_field_data[off] & 0xFF));
962 }
963
964 public double get (String name, double defvalue)
965 throws IOException, IllegalArgumentException
966 {
967 ObjectStreamField field = getField (name, Double.TYPE);
968
969 if (field == null)
970 return defvalue;
971
972 int off = field.getOffset ();
973
974 return Double.longBitsToDouble
975 ( (long) (((prim_field_data[off++] & 0xFF) << 56)
976 | ((prim_field_data[off++] & 0xFF) << 48)
977 | ((prim_field_data[off++] & 0xFF) << 40)
978 | ((prim_field_data[off++] & 0xFF) << 32)
979 | ((prim_field_data[off++] & 0xFF) << 24)
980 | ((prim_field_data[off++] & 0xFF) << 16)
981 | ((prim_field_data[off++] & 0xFF) << 8)
982 | (prim_field_data[off] & 0xFF)));
983 }
984
985 public Object get (String name, Object defvalue)
986 throws IOException, IllegalArgumentException
987 {
988 ObjectStreamField field =
989 getField (name, defvalue == null ? null : defvalue.getClass ());
990
991 if (field == null)
992 return defvalue;
993
994 return objs[field.getOffset ()];
995 }
996
997 private ObjectStreamField getField (String name, Class type)
998 throws IllegalArgumentException
999 {
1000 ObjectStreamField field = clazz.getField (name);
1001
1002 if (field == null)
1003 return null;
1004
1005 Class field_type = field.getType ();
1006
1007 if (type == field_type ||
1008 (type == null && ! field_type.isPrimitive ()))
1009 return field;
1010
1011 throw new IllegalArgumentException ("Field requested is of type "
1012 + field_type.getName ()
1013 + ", but requested type was "
1014 + (type == null ?
1015 "Object" : type.getName ()));
1016 }
1017 };
1018
1019 }
1020
1021
1022 /**
1023 Protected constructor that allows subclasses to override
1024 deserialization. This constructor should be called by subclasses
1025 that wish to override <code>readObject (Object)</code>. This
1026 method does a security check <i>NOTE: currently not
1027 implemented</i>, then sets a flag that informs
1028 <code>readObject (Object)</code> to call the subclasses
1029 <code>readObjectOverride (Object)</code> method.
1030
1031 @see readObjectOverride (Object)
1032 */
1033 protected ObjectInputStream ()
1034 throws IOException, SecurityException
1035 {
1036 SecurityManager sec_man = System.getSecurityManager ();
1037 if (sec_man != null)
1038 sec_man.checkPermission (SUBCLASS_IMPLEMENTATION_PERMISSION);
1039 this.useSubclassMethod = true;
1040 }
1041
1042
1043 /**
1044 This method allows subclasses to override the default
1045 de serialization mechanism provided by
1046 <code>ObjectInputStream</code>. To make this method be used for
1047 writing objects, subclasses must invoke the 0-argument
1048 constructor on this class from their constructor.
1049
1050 @see ObjectInputStream ()
1051 */
1052 protected Object readObjectOverride ()
1053 throws ClassNotFoundException, IOException, OptionalDataException
1054 {
1055 throw new IOException ("Subclass of ObjectInputStream must implement readObjectOverride");
1056 }
1057
1058
1059 // assigns the next availible handle to OBJ
1060 private int assignNewHandle (Object obj)
1061 {
1062 this.objectLookupTable.put (new Integer (this.nextOID),
1063 new ObjectIdentityWrapper (obj));
1064 return this.nextOID++;
1065 }
1066
1067
1068 private Object processResolution (Object obj, int handle)
1069 throws IOException
1070 {
1071 if (obj instanceof Serializable)
1072 {
1073 Method m = null;
1074 try
1075 {
1076 Class classArgs[] = {};
1077 m = obj.getClass ().getDeclaredMethod ("readResolve", classArgs);
1078 // m can't be null by definition since an exception would
1079 // have been thrown so a check for null is not needed.
1080 obj = m.invoke (obj, new Object[] {});
1081 }
1082 catch (NoSuchMethodException ignore)
1083 {
1084 }
1085 catch (IllegalAccessException ignore)
1086 {
1087 }
1088 catch (InvocationTargetException ignore)
1089 {
1090 }
1091 }
1092
1093 if (this.resolveEnabled)
1094 obj = resolveObject (obj);
1095
1096 this.objectLookupTable.put (new Integer (handle),
1097 new ObjectIdentityWrapper (obj));
1098
1099 return obj;
1100 }
1101
1102
1103 private void clearHandles ()
1104 {
1105 this.objectLookupTable.clear ();
1106 this.nextOID = baseWireHandle;
1107 }
1108
1109
1110 private void readNextBlock () throws IOException
1111 {
1112 readNextBlock (this.realInputStream.readByte ());
1113 }
1114
1115
1116 private void readNextBlock (byte marker) throws IOException
1117 {
1118 if (marker == TC_BLOCKDATA)
1119 {
1120 dumpElement ("BLOCK DATA SIZE=");
1121 this.blockDataBytes = this.realInputStream.readUnsignedByte ();
1122 dumpElementln (Integer.toString(this.blockDataBytes));
1123 }
1124 else if (marker == TC_BLOCKDATALONG)
1125 {
1126 dumpElement ("BLOCK DATA LONG SIZE=");
1127 this.blockDataBytes = this.realInputStream.readInt ();
1128 dumpElementln (Integer.toString(this.blockDataBytes));
1129 }
1130 else
1131 {
1132 throw new EOFException ("Attempt to read primitive data, but no data block is active.");
1133 }
1134
1135 if (this.blockData.length < this.blockDataBytes)
1136 this.blockData = new byte[this.blockDataBytes];
1137
1138 this.realInputStream.readFully (this.blockData, 0, this.blockDataBytes);
1139 this.blockDataPosition = 0;
1140 }
1141
1142
1143 private void readArrayElements (Object array, Class clazz)
1144 throws ClassNotFoundException, IOException
1145 {
1146 if (clazz.isPrimitive ())
1147 {
1148 if (clazz == Boolean.TYPE)
1149 {
1150 boolean[] cast_array = (boolean[])array;
1151 for (int i=0; i < cast_array.length; i++)
1152 cast_array[i] = this.realInputStream.readBoolean ();
1153 return;
1154 }
1155 if (clazz == Byte.TYPE)
1156 {
1157 byte[] cast_array = (byte[])array;
1158 for (int i=0; i < cast_array.length; i++)
1159 cast_array[i] = this.realInputStream.readByte ();
1160 return;
1161 }
1162 if (clazz == Character.TYPE)
1163 {
1164 char[] cast_array = (char[])array;
1165 for (int i=0; i < cast_array.length; i++)
1166 cast_array[i] = this.realInputStream.readChar ();
1167 return;
1168 }
1169 if (clazz == Double.TYPE)
1170 {
1171 double[] cast_array = (double[])array;
1172 for (int i=0; i < cast_array.length; i++)
1173 cast_array[i] = this.realInputStream.readDouble ();
1174 return;
1175 }
1176 if (clazz == Float.TYPE)
1177 {
1178 float[] cast_array = (float[])array;
1179 for (int i=0; i < cast_array.length; i++)
1180 cast_array[i] = this.realInputStream.readFloat ();
1181 return;
1182 }
1183 if (clazz == Integer.TYPE)
1184 {
1185 int[] cast_array = (int[])array;
1186 for (int i=0; i < cast_array.length; i++)
1187 cast_array[i] = this.realInputStream.readInt ();
1188 return;
1189 }
1190 if (clazz == Long.TYPE)
1191 {
1192 long[] cast_array = (long[])array;
1193 for (int i=0; i < cast_array.length; i++)
1194 cast_array[i] = this.realInputStream.readLong ();
1195 return;
1196 }
1197 if (clazz == Short.TYPE)
1198 {
1199 short[] cast_array = (short[])array;
1200 for (int i=0; i < cast_array.length; i++)
1201 cast_array[i] = this.realInputStream.readShort ();
1202 return;
1203 }
1204 }
1205 else
1206 {
1207 Object[] cast_array = (Object[])array;
1208 for (int i=0; i < cast_array.length; i++)
1209 cast_array[i] = readObject ();
1210 }
1211 }
1212
1213
1214 private void readFields (Object obj, ObjectStreamClass stream_osc)
1215 throws ClassNotFoundException, IOException
1216 {
1217 ObjectStreamField[] stream_fields = stream_osc.fields;
1218 ObjectStreamField[] real_fields =
1219 ObjectStreamClass.lookup (stream_osc.forClass ()).fields;
1220
1221 boolean default_initialize, set_value;
1222 String field_name = null;
1223 Class type = null;
1224 ObjectStreamField stream_field = null;
1225 ObjectStreamField real_field = null;
1226 int stream_idx = 0;
1227 int real_idx = 0;
1228
1229 while (stream_idx < stream_fields.length
1230 && real_idx < real_fields.length)
1231 {
1232 default_initialize = false;
1233 set_value = true;
1234
1235 if (stream_idx == stream_fields.length)
1236 default_initialize = true;
1237 else
1238 {
1239 stream_field = stream_fields[stream_idx];
1240 type = stream_field.getType ();
1241 }
1242
1243 if (real_idx == real_fields.length)
1244 set_value = false;
1245 else
1246 {
1247 real_field = real_fields[real_idx];
1248 type = real_field.getType ();
1249 field_name = real_field.getName ();
1250 }
1251
1252 if (set_value && !default_initialize)
1253 {
1254 int comp_val =
1255 real_field.compareTo (stream_field);
1256
1257 if (comp_val < 0)
1258 {
1259 default_initialize = true;
1260 real_idx++;
1261 }
1262 else if (comp_val > 0)
1263 {
1264 set_value = false;
1265 stream_idx++;
1266 }
1267 else
1268 {
1269 real_idx++;
1270 stream_idx++;
1271 }
1272 }
1273
1274 try
1275 {
1276 if (type == Boolean.TYPE)
1277 {
1278 boolean value =
1279 default_initialize ? false : this.realInputStream.readBoolean ();
1280 if (!default_initialize && set_value)
1281 dumpElementln (" " + field_name + ": " + value);
1282 if (set_value)
1283 setBooleanField (obj, stream_osc.forClass (), field_name, value);
1284 }
1285 else if (type == Byte.TYPE)
1286 {
1287 byte value =
1288 default_initialize ? 0 : this.realInputStream.readByte ();
1289 if (!default_initialize && set_value)
1290 dumpElementln (" " + field_name + ": " + value);
1291 if (set_value)
1292 setByteField (obj, stream_osc.forClass (), field_name, value);
1293 }
1294 else if (type == Character.TYPE)
1295 {
1296 char value =
1297 default_initialize ? (char)0 : this.realInputStream.readChar ();
1298 if (!default_initialize && set_value)
1299 dumpElementln (" " + field_name + ": " + value);
1300 if (set_value)
1301 setCharField (obj, stream_osc.forClass (), field_name, value);
1302 }
1303 else if (type == Double.TYPE)
1304 {
1305 double value =
1306 default_initialize ? 0 : this.realInputStream.readDouble ();
1307 if (!default_initialize && set_value)
1308 dumpElementln (" " + field_name + ": " + value);
1309 if (set_value)
1310 setDoubleField (obj, stream_osc.forClass (), field_name, value);
1311 }
1312 else if (type == Float.TYPE)
1313 {
1314 float value =
1315 default_initialize ? 0 : this.realInputStream.readFloat ();
1316 if (!default_initialize && set_value)
1317 dumpElementln (" " + field_name + ": " + value);
1318 if (set_value)
1319 setFloatField (obj, stream_osc.forClass (), field_name, value);
1320 }
1321 else if (type == Integer.TYPE)
1322 {
1323 int value =
1324 default_initialize ? 0 : this.realInputStream.readInt ();
1325 if (!default_initialize && set_value)
1326 dumpElementln (" " + field_name + ": " + value);
1327 if (set_value)
1328 setIntField (obj, stream_osc.forClass (), field_name, value);
1329 }
1330 else if (type == Long.TYPE)
1331 {
1332 long value =
1333 default_initialize ? 0 : this.realInputStream.readLong ();
1334 if (!default_initialize && set_value)
1335 dumpElementln (" " + field_name + ": " + value);
1336 if (set_value)
1337 setLongField (obj, stream_osc.forClass (), field_name, value);
1338 }
1339 else if (type == Short.TYPE)
1340 {
1341 short value =
1342 default_initialize ? (short)0 : this.realInputStream.readShort ();
1343 if (!default_initialize && set_value)
1344 dumpElementln (" " + field_name + ": " + value);
1345 if (set_value)
1346 setShortField (obj, stream_osc.forClass (), field_name, value);
1347 }
1348 else
1349 {
1350 Object value =
1351 default_initialize ? null : readObject ();
1352 if (set_value)
1353 setObjectField (obj, stream_osc.forClass (), field_name,
1354 real_field.getTypeString (), value);
1355 }
1356 }
1357 catch (NoSuchFieldError e)
1358 {
1359 dumpElementln("XXXX " + field_name + " does not exist.");
1360 }
1361 }
1362 }
1363
1364 // Toggles writing primitive data to block-data buffer.
1365 private boolean setBlockDataMode (boolean on)
1366 {
1367 boolean oldmode = this.readDataFromBlock;
1368 this.readDataFromBlock = on;
1369
1370 if (on)
1371 this.dataInputStream = this.blockDataInput;
1372 else
1373 this.dataInputStream = this.realInputStream;
1374 return oldmode;
1375 }
1376
1377
1378 // returns a new instance of REAL_CLASS that has been constructed
1379 // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
1380 private Object newObject (Class real_class, Class constructor_class)
1381 {
1382 try
1383 {
1384 Object obj = allocateObject (real_class);
1385 callConstructor (constructor_class, obj);
1386 return obj;
1387 }
1388 catch (InstantiationException e)
1389 {
1390 return null;
1391 }
1392 }
1393
1394
1395 // runs all registered ObjectInputValidations in prioritized order
1396 // on OBJ
1397 private void invokeValidators () throws InvalidObjectException
1398 {
1399 Object[] validators = new Object[this.validators.size ()];
1400 this.validators.copyInto (validators);
1401 Arrays.sort (validators);
1402
1403 try
1404 {
1405 for (int i=0; i < validators.length; i++)
1406 ((ObjectInputValidation)validators[i]).validateObject ();
1407 }
1408 finally
1409 {
1410 this.validators.removeAllElements ();
1411 }
1412 }
1413
1414
1415 // this native method is used to get access to the protected method
1416 // of the same name in SecurityManger
1417 private static ClassLoader currentClassLoader (SecurityManager sm)
1418 {
1419 // FIXME: This is too simple.
1420 return ClassLoader.getSystemClassLoader ();
1421 }
1422
1423 private static Field getField (Class klass, String name)
1424 throws java.lang.NoSuchFieldException
1425 {
1426 return klass.getDeclaredField(name);
1427 }
1428
1429 private static Method getMethod (Class klass, String name, Class args[])
1430 throws java.lang.NoSuchMethodException
1431 {
1432 return klass.getDeclaredMethod(name, args);
1433 }
1434
1435 private void callReadMethod (Object obj, ObjectStreamClass osc) throws IOException
1436 {
1437 Class klass = osc.forClass();
1438 try
1439 {
1440 Class classArgs[] = {ObjectInputStream.class};
1441 Method m = getMethod (klass, "readObject", classArgs);
1442 if (m == null)
1443 return;
1444 Object args[] = {this};
1445 m.invoke (obj, args);
1446 }
1447 catch (InvocationTargetException x)
1448 {
1449 /* Rethrow if possible. */
1450 Throwable exception = x.getTargetException();
1451 if (exception instanceof RuntimeException)
1452 throw (RuntimeException) exception;
1453 if (exception instanceof IOException)
1454 throw (IOException) exception;
1455
1456 throw new IOException ("Exception thrown from readObject() on " +
1457 klass + ": " + exception.getClass().getName());
1458 }
1459 catch (Exception x)
1460 {
1461 throw new IOException ("Failure invoking readObject() on " +
1462 klass + ": " + x.getClass().getName());
1463 }
1464 }
1465
1466 private native Object allocateObject (Class clazz)
1467 throws InstantiationException;
1468
1469 private native void callConstructor (Class clazz, Object obj);
1470
1471 private void setBooleanField (Object obj, Class klass, String field_name,
1472 boolean val)
1473 {
1474 try
1475 {
1476 Field f = getField (klass, field_name);
1477 f.setAccessible(true);
1478 f.setBoolean (obj, val);
1479 }
1480 catch (Exception _)
1481 {
1482 }
1483 }
1484
1485 private void setByteField (Object obj, Class klass, String field_name,
1486 byte val)
1487 {
1488 try
1489 {
1490 Field f = getField (klass, field_name);
1491 f.setAccessible(true);
1492 f.setByte (obj, val);
1493 }
1494 catch (Exception _)
1495 {
1496 }
1497 }
1498
1499 private void setCharField (Object obj, Class klass, String field_name,
1500 char val)
1501 {
1502 try
1503 {
1504 Field f = getField (klass, field_name);
1505 f.setAccessible(true);
1506 f.setChar (obj, val);
1507 }
1508 catch (Exception _)
1509 {
1510 }
1511 }
1512
1513 private void setDoubleField (Object obj, Class klass, String field_name,
1514 double val)
1515 {
1516 try
1517 {
1518 Field f = getField (klass, field_name);
1519 f.setAccessible(true);
1520 f.setDouble (obj, val);
1521 }
1522 catch (Exception _)
1523 {
1524 }
1525 }
1526
1527 private void setFloatField (Object obj, Class klass, String field_name,
1528 float val)
1529 {
1530 try
1531 {
1532 Field f = getField (klass, field_name);
1533 f.setAccessible(true);
1534 f.setFloat (obj, val);
1535 }
1536 catch (Exception _)
1537 {
1538 }
1539 }
1540
1541 private void setIntField (Object obj, Class klass, String field_name,
1542 int val)
1543 {
1544 try
1545 {
1546 Field f = getField (klass, field_name);
1547 f.setAccessible(true);
1548 f.setInt (obj, val);
1549 }
1550 catch (Exception _)
1551 {
1552 }
1553 }
1554
1555
1556 private void setLongField (Object obj, Class klass, String field_name,
1557 long val)
1558 {
1559 try
1560 {
1561 Field f = getField (klass, field_name);
1562 f.setAccessible(true);
1563 f.setLong (obj, val);
1564 }
1565 catch (Exception _)
1566 {
1567 }
1568 }
1569
1570
1571 private void setShortField (Object obj, Class klass, String field_name,
1572 short val)
1573 {
1574 try
1575 {
1576 Field f = getField (klass, field_name);
1577 f.setAccessible(true);
1578 f.setShort (obj, val);
1579 }
1580 catch (Exception _)
1581 {
1582 }
1583 }
1584
1585
1586 private void setObjectField (Object obj, Class klass, String field_name, String type_code,
1587 Object val)
1588 {
1589 try
1590 {
1591 Field f = getField (klass, field_name);
1592 f.setAccessible(true);
1593 // FIXME: We should check the type_code here
1594 f.set (obj, val);
1595 }
1596 catch (Exception _)
1597 {
1598 }
1599 }
1600
1601 private static final int BUFFER_SIZE = 1024;
1602 private static final Class[] readObjectParams = { ObjectInputStream.class };
1603
1604 private DataInputStream realInputStream;
1605 private DataInputStream dataInputStream;
1606 private DataInputStream blockDataInput;
1607 private int blockDataPosition;
1608 private int blockDataBytes;
1609 private byte[] blockData;
1610 private boolean useSubclassMethod;
1611 private int nextOID;
1612 private boolean resolveEnabled;
1613 private Hashtable objectLookupTable;
1614 private Object currentObject;
1615 private ObjectStreamClass currentObjectStreamClass;
1616 private boolean readDataFromBlock;
1617 private boolean isDeserializing;
1618 private boolean fieldsAlreadyRead;
1619 private Vector validators;
1620
1621 private static boolean dump;
1622
1623 private void dumpElement (String msg)
1624 {
1625 if (Configuration.DEBUG && dump)
1626 System.out.print(msg);
1627 }
1628
1629 private void dumpElementln (String msg)
1630 {
1631 if (Configuration.DEBUG && dump)
1632 System.out.println(msg);
1633 }
1634
1635 static
1636 {
1637 if (Configuration.INIT_LOAD_LIBRARY)
1638 {
1639 System.loadLibrary ("javaio");
1640 }
1641 }
1642}
1643
1644
1645// used to keep a prioritized list of object validators
1646class ValidatorAndPriority implements Comparable
1647{
1648 int priority;
1649 ObjectInputValidation validator;
1650
1651 ValidatorAndPriority (ObjectInputValidation validator, int priority)
1652 {
1653 this.priority = priority;
1654 this.validator = validator;
1655 }
1656
1657 public int compareTo (Object o)
1658 {
1659 ValidatorAndPriority vap = (ValidatorAndPriority)o;
1660 return this.priority - vap.priority;
1661 }
1662}
Note: See TracBrowser for help on using the repository browser.