1 /* ObjectInputStream.java -- Class used to read serialized objects
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java
.lang
.reflect
.Array
;
42 import java
.lang
.reflect
.Modifier
;
43 import java
.lang
.reflect
.Proxy
;
44 import java
.security
.PrivilegedAction
;
45 import java
.security
.AccessController
;
46 import java
.util
.Arrays
;
47 import java
.util
.Hashtable
;
48 import java
.util
.Vector
;
51 import gnu
.java
.io
.ObjectIdentityWrapper
;
52 import gnu
.java
.lang
.reflect
.TypeSignature
;
53 import java
.lang
.reflect
.Field
;
54 import java
.lang
.reflect
.Method
;
55 import java
.lang
.reflect
.InvocationTargetException
;
57 import gnu
.classpath
.Configuration
;
59 public class ObjectInputStream
extends InputStream
60 implements ObjectInput
, ObjectStreamConstants
63 * Creates a new <code>ObjectInputStream</code> that will do all of
64 * its reading from <code>in</code>. This method also checks
65 * the stream by reading the header information (stream magic number
66 * and stream version).
68 * @exception IOException Reading stream header from underlying
69 * stream cannot be completed.
71 * @exception StreamCorruptedException An invalid stream magic
72 * number or stream version was read from the stream.
74 * @see #readStreamHeader()
76 public ObjectInputStream(InputStream in
)
77 throws IOException
, StreamCorruptedException
79 if (Configuration
.DEBUG
)
81 String val
= System
.getProperty("gcj.dumpobjects");
82 if (dump
== false && val
!= null && !val
.equals(""))
85 System
.out
.println ("Serialization debugging enabled");
87 else if (dump
== true && (val
== null || val
.equals("")))
90 System
.out
.println ("Serialization debugging disabled");
94 this.resolveEnabled
= false;
95 this.isDeserializing
= false;
96 this.blockDataPosition
= 0;
97 this.blockDataBytes
= 0;
98 this.blockData
= new byte[BUFFER_SIZE
];
99 this.blockDataInput
= new DataInputStream(this);
100 this.realInputStream
= new DataInputStream(in
);
101 this.nextOID
= baseWireHandle
;
102 this.objectLookupTable
= new Hashtable();
103 this.validators
= new Vector();
104 this.classLookupTable
= new Hashtable();
105 setBlockDataMode(true);
111 * Returns the next deserialized object read from the underlying stream.
113 * This method can be overriden by a class by implementing
114 * <code>private void readObject (ObjectInputStream)</code>.
116 * If an exception is thrown from this method, the stream is left in
117 * an undefined state.
119 * @exception ClassNotFoundException The class that an object being
120 * read in belongs to cannot be found.
122 * @exception IOException Exception from underlying
123 * <code>InputStream</code>.
125 public final Object
readObject() throws ClassNotFoundException
, IOException
127 if (this.useSubclassMethod
)
128 return readObjectOverride();
130 boolean was_deserializing
;
133 was_deserializing
= this.isDeserializing
;
135 boolean is_consumed
= false;
136 boolean old_mode
= setBlockDataMode(false);
138 this.isDeserializing
= true;
140 byte marker
= this.realInputStream
.readByte();
141 if(dump
) dumpElement("MARKER: 0x" + Integer
.toHexString(marker
) + " ");
147 case TC_ENDBLOCKDATA
:
155 case TC_BLOCKDATALONG
:
157 if (marker
== TC_BLOCKDATALONG
)
158 if(dump
) dumpElementln("BLOCKDATALONG");
160 if(dump
) dumpElementln("BLOCKDATA");
161 readNextBlock(marker
);
162 throw new StreamCorruptedException("Unexpected blockData");
167 if(dump
) dumpElementln("NULL");
174 if(dump
) dumpElement("REFERENCE ");
175 Integer oid
= new Integer(this.realInputStream
.readInt());
176 if(dump
) dumpElementln(Integer
.toHexString(oid
.intValue()));
177 ret_val
= ((ObjectIdentityWrapper
)
178 this.objectLookupTable
.get(oid
)).object
;
184 if(dump
) dumpElementln("CLASS");
185 ObjectStreamClass osc
= (ObjectStreamClass
)readObject();
186 Class clazz
= osc
.forClass();
187 assignNewHandle(clazz
);
192 case TC_PROXYCLASSDESC
:
194 if(dump
) dumpElementln("PROXYCLASS");
195 int n_intf
= this.realInputStream
.readInt();
196 String
[] intfs
= new String
[n_intf
];
197 for (int i
= 0; i
< n_intf
; i
++)
199 intfs
[i
] = this.realInputStream
.readUTF();
200 System
.out
.println(intfs
[i
]);
203 boolean oldmode
= setBlockDataMode(true);
204 Class cl
= resolveProxyClass(intfs
);
205 setBlockDataMode(oldmode
);
207 ObjectStreamClass osc
= lookupClass(cl
);
208 assignNewHandle(osc
);
212 byte b
= this.realInputStream
.readByte();
213 if (b
!= TC_ENDBLOCKDATA
)
214 throw new IOException("Data annotated to class was not consumed." + b
);
218 ObjectStreamClass superosc
= (ObjectStreamClass
)readObject();
219 osc
.setSuperclass(superosc
);
226 ObjectStreamClass osc
= readClassDescriptor();
230 byte b
= this.realInputStream
.readByte();
231 if (b
!= TC_ENDBLOCKDATA
)
232 throw new IOException("Data annotated to class was not consumed." + b
);
237 osc
.setSuperclass ((ObjectStreamClass
)readObject());
245 if(dump
) dumpElement("STRING=");
246 String s
= this.realInputStream
.readUTF();
247 if(dump
) dumpElementln(s
);
248 ret_val
= processResolution(null, s
, assignNewHandle(s
));
254 if(dump
) dumpElementln("ARRAY");
255 ObjectStreamClass osc
= (ObjectStreamClass
)readObject();
256 Class componentType
= osc
.forClass().getComponentType();
257 if(dump
) dumpElement("ARRAY LENGTH=");
258 int length
= this.realInputStream
.readInt();
259 if(dump
) dumpElementln (length
+ "; COMPONENT TYPE=" + componentType
);
260 Object array
= Array
.newInstance(componentType
, length
);
261 int handle
= assignNewHandle(array
);
262 readArrayElements(array
, componentType
);
264 for (int i
= 0, len
= Array
.getLength(array
); i
< len
; i
++)
265 dumpElementln(" ELEMENT[" + i
+ "]=" + Array
.get(array
, i
));
266 ret_val
= processResolution(null, array
, handle
);
272 if(dump
) dumpElementln("OBJECT");
273 ObjectStreamClass osc
= (ObjectStreamClass
)readObject();
274 Class clazz
= osc
.forClass();
276 if (!osc
.realClassIsSerializable
)
277 throw new NotSerializableException
278 (clazz
+ " is not Serializable, and thus cannot be deserialized.");
280 if (osc
.realClassIsExternalizable
)
282 Externalizable obj
= null;
286 obj
= (Externalizable
)clazz
.newInstance();
288 catch (InstantiationException e
)
290 throw new ClassNotFoundException
291 ("Instance of " + clazz
+ " could not be created");
293 catch (IllegalAccessException e
)
295 throw new ClassNotFoundException
296 ("Instance of " + clazz
+ " could not be created because class or "
297 + "zero-argument constructor is not accessible");
299 catch (NoSuchMethodError e
)
301 throw new ClassNotFoundException
302 ("Instance of " + clazz
303 + " could not be created because zero-argument constructor is not defined");
306 int handle
= assignNewHandle(obj
);
308 boolean read_from_blocks
= ((osc
.getFlags() & SC_BLOCK_DATA
) != 0);
310 boolean oldmode
= this.readDataFromBlock
;
311 if (read_from_blocks
)
312 setBlockDataMode(true);
314 obj
.readExternal(this);
316 if (read_from_blocks
)
317 setBlockDataMode(oldmode
);
319 ret_val
= processResolution(osc
, obj
, handle
);
321 } // end if (osc.realClassIsExternalizable)
323 Object obj
= newObject(clazz
, osc
.firstNonSerializableParent
);
325 int handle
= assignNewHandle(obj
);
326 this.currentObject
= obj
;
327 ObjectStreamClass
[] hierarchy
=
328 inputGetObjectStreamClasses(clazz
);
330 for (int i
= 0; i
< hierarchy
.length
; i
++)
332 this.currentObjectStreamClass
= hierarchy
[i
];
334 if(dump
) dumpElementln("Reading fields of " + this.currentObjectStreamClass
.getName ());
336 // XXX: should initialize fields in classes in the hierarchy
337 // that aren't in the stream
338 // should skip over classes in the stream that aren't in the
339 // real classes hierarchy
341 Method readObjectMethod
= this.currentObjectStreamClass
.readObjectMethod
;
342 if (readObjectMethod
!= null)
344 fieldsAlreadyRead
= false;
345 boolean oldmode
= setBlockDataMode(true);
346 callReadMethod(readObjectMethod
, this.currentObjectStreamClass
.forClass(), obj
);
347 setBlockDataMode(oldmode
);
348 if(dump
) dumpElement("ENDBLOCKDATA? ");
351 // FIXME: XXX: This try block is to catch EOF which is
352 // thrown for some objects. That indicates a bug in the logic.
353 if (this.realInputStream
.readByte() != TC_ENDBLOCKDATA
)
354 throw new IOException
355 ("No end of block data seen for class with readObject (ObjectInputStream) method.");
356 if(dump
) dumpElementln("yes");
358 catch (EOFException e
)
360 if(dump
) dumpElementln("no, got EOFException");
362 catch (IOException e
)
364 if(dump
) dumpElementln("no, got IOException");
369 readFields(obj
, currentObjectStreamClass
);
373 this.currentObject
= null;
374 this.currentObjectStreamClass
= null;
375 ret_val
= processResolution(osc
, obj
, handle
);
380 if(dump
) dumpElementln("RESET");
382 ret_val
= readObject();
387 if(dump
) dumpElement("EXCEPTION=");
388 Exception e
= (Exception
)readObject();
389 if(dump
) dumpElementln(e
.toString());
391 throw new WriteAbortedException("Exception thrown during writing of stream", e
);
395 throw new IOException("Unknown marker on stream: " + marker
);
400 setBlockDataMode(old_mode
);
402 this.isDeserializing
= was_deserializing
;
404 if (! was_deserializing
)
406 if (validators
.size() > 0)
415 * This method reads a class descriptor from the real input stream
416 * and use these data to create a new instance of ObjectStreamClass.
417 * Fields are sorted and ordered for the real read which occurs for
418 * each instance of the described class. Be aware that if you call that
419 * method you must ensure that the stream is synchronized, in the other
420 * case it may be completely desynchronized.
422 * @return A new instance of ObjectStreamClass containing the freshly
423 * created descriptor.
424 * @throws ClassNotFoundException if the required class to build the
425 * descriptor has not been found in the system.
426 * @throws IOException An input/output error occured.
427 * @throws InvalidClassException If there was a compatibility problem
428 * between the class present in the system and the serialized class.
430 protected ObjectStreamClass
readClassDescriptor()
431 throws ClassNotFoundException
, IOException
433 if(dump
) dumpElement("CLASSDESC NAME=");
434 String name
= this.realInputStream
.readUTF();
435 if(dump
) dumpElement(name
+ "; UID=");
436 long uid
= this.realInputStream
.readLong ();
437 if(dump
) dumpElement(Long
.toHexString(uid
) + "; FLAGS=");
438 byte flags
= this.realInputStream
.readByte ();
439 if(dump
) dumpElement(Integer
.toHexString(flags
) + "; FIELD COUNT=");
440 short field_count
= this.realInputStream
.readShort();
441 if(dump
) dumpElementln(Short
.toString(field_count
));
442 ObjectStreamField
[] fields
= new ObjectStreamField
[field_count
];
443 ObjectStreamClass osc
= new ObjectStreamClass(name
, uid
,
445 assignNewHandle(osc
);
447 ClassLoader currentLoader
= currentLoader();
449 for (int i
= 0; i
< field_count
; i
++)
451 if(dump
) dumpElement(" TYPE CODE=");
452 char type_code
= (char)this.realInputStream
.readByte();
453 if(dump
) dumpElement(type_code
+ "; FIELD NAME=");
454 String field_name
= this.realInputStream
.readUTF();
455 if(dump
) dumpElementln(field_name
);
458 // If the type code is an array or an object we must
459 // decode a String here. In the other case we convert
460 // the type code and pass it to ObjectStreamField.
461 // Type codes are decoded by gnu.java.lang.reflect.TypeSignature.
462 if (type_code
== 'L' || type_code
== '[')
463 class_name
= (String
)readObject();
465 class_name
= String
.valueOf(type_code
);
468 new ObjectStreamField(field_name
, class_name
, currentLoader
);
471 /* Now that fields have been read we may resolve the class
472 * (and read annotation if needed). */
473 Class clazz
= resolveClass(osc
);
475 boolean oldmode
= setBlockDataMode(true);
476 osc
.setClass(clazz
, lookupClass(clazz
.getSuperclass()));
477 classLookupTable
.put(clazz
, osc
);
478 setBlockDataMode(oldmode
);
480 // find the first non-serializable, non-abstract
481 // class in clazz's inheritance hierarchy
482 Class first_nonserial
= clazz
.getSuperclass();
483 while (Serializable
.class.isAssignableFrom(first_nonserial
)
484 || Modifier
.isAbstract(first_nonserial
.getModifiers()))
485 first_nonserial
= first_nonserial
.getSuperclass();
487 osc
.firstNonSerializableParent
= first_nonserial
;
488 osc
.realClassIsSerializable
= Serializable
.class.isAssignableFrom(clazz
);
489 osc
.realClassIsExternalizable
= Externalizable
.class.isAssignableFrom(clazz
);
491 ObjectStreamField
[] stream_fields
= osc
.fields
;
492 ObjectStreamField
[] real_fields
= ObjectStreamClass
.lookup(clazz
).fields
;
493 ObjectStreamField
[] fieldmapping
= new ObjectStreamField
[2 * Math
.max(stream_fields
.length
, real_fields
.length
)];
494 osc
.fieldMapping
= fieldmapping
;
500 while (stream_idx
< stream_fields
.length
501 || real_idx
< real_fields
.length
)
503 ObjectStreamField stream_field
= null;
504 ObjectStreamField real_field
= null;
506 if (stream_idx
== stream_fields
.length
)
508 real_field
= real_fields
[real_idx
++];
510 else if (real_idx
== real_fields
.length
)
512 stream_field
= stream_fields
[stream_idx
++];
517 real_fields
[real_idx
].compareTo (stream_fields
[stream_idx
]);
521 real_field
= real_fields
[real_idx
++];
523 else if (comp_val
> 0)
525 stream_field
= stream_fields
[stream_idx
++];
529 stream_field
= stream_fields
[stream_idx
++];
530 real_field
= real_fields
[real_idx
++];
531 if(stream_field
.getType() != real_field
.getType())
532 throw new InvalidClassException
533 ("invalid field type for " + real_field
.getName() +
534 " in class " + name
);
537 if (stream_field
!= null)
539 if (stream_field
.getOffset() < 0)
541 else if (!stream_field
.isToSet())
544 if (real_field
!= null && !real_field
.isToSet())
546 fieldmapping
[map_idx
++] = stream_field
;
547 fieldmapping
[map_idx
++] = real_field
;
554 * Reads the current objects non-transient, non-static fields from
555 * the current class from the underlying output stream.
557 * This method is intended to be called from within a object's
558 * <code>private void readObject (ObjectInputStream)</code>
561 * @exception ClassNotFoundException The class that an object being
562 * read in belongs to cannot be found.
564 * @exception NotActiveException This method was called from a
565 * context other than from the current object's and current class's
566 * <code>private void readObject (ObjectInputStream)</code>
569 * @exception IOException Exception from underlying
570 * <code>OutputStream</code>.
572 public void defaultReadObject()
573 throws ClassNotFoundException
, IOException
, NotActiveException
575 if (this.currentObject
== null || this.currentObjectStreamClass
== null)
576 throw new NotActiveException("defaultReadObject called by non-active"
577 + " class and/or object");
579 if (fieldsAlreadyRead
)
580 throw new NotActiveException("defaultReadObject called but fields "
581 + "already read from stream (by "
582 + "defaultReadObject or readFields)");
584 boolean oldmode
= setBlockDataMode(false);
585 readFields(this.currentObject
, this.currentObjectStreamClass
);
586 setBlockDataMode(oldmode
);
588 fieldsAlreadyRead
= true;
593 * Registers a <code>ObjectInputValidation</code> to be carried out
594 * on the object graph currently being deserialized before it is
595 * returned to the original caller of <code>readObject ()</code>.
596 * The order of validation for multiple
597 * <code>ObjectInputValidation</code>s can be controled using
598 * <code>priority</code>. Validators with higher priorities are
601 * @see java.io.ObjectInputValidation
603 * @exception InvalidObjectException <code>validator</code> is
606 * @exception NotActiveException an attempt was made to add a
607 * validator outside of the <code>readObject</code> method of the
608 * object currently being deserialized
610 public void registerValidation(ObjectInputValidation validator
,
612 throws InvalidObjectException
, NotActiveException
614 if (this.currentObject
== null || this.currentObjectStreamClass
== null)
615 throw new NotActiveException("registerValidation called by non-active "
616 + "class and/or object");
618 if (validator
== null)
619 throw new InvalidObjectException("attempt to add a null "
620 + "ObjectInputValidation object");
622 this.validators
.addElement(new ValidatorAndPriority (validator
,
628 * Called when a class is being deserialized. This is a hook to
629 * allow subclasses to read in information written by the
630 * <code>annotateClass (Class)</code> method of an
631 * <code>ObjectOutputStream</code>.
633 * This implementation looks up the active call stack for a
634 * <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,
635 * it is used to load the class associated with <code>osc</code>,
636 * otherwise, the default system <code>ClassLoader</code> is used.
638 * @exception IOException Exception from underlying
639 * <code>OutputStream</code>.
641 * @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
643 protected Class
resolveClass(ObjectStreamClass osc
)
644 throws ClassNotFoundException
, IOException
646 return Class
.forName(osc
.getName(), true, currentLoader());
650 * This method invokes the method currentClassLoader for the
651 * current security manager (or build an empty one if it is not
654 * @return The most recent non-system ClassLoader on the execution stack.
655 * @see java.lang.SecurityManager#currentClassLoader()
657 private ClassLoader
currentLoader()
659 SecurityManager sm
= System
.getSecurityManager();
661 sm
= new SecurityManager () {};
663 return currentClassLoader(sm
);
667 * Lookup a class stored in the local hashtable. If it is not
668 * use the global lookup function in ObjectStreamClass to build
669 * the ObjectStreamClass. This method is requested according to
670 * the behaviour detected in the JDK by Kaffe's team.
672 * @param clazz Class to lookup in the hash table or for which
673 * we must build a descriptor.
674 * @return A valid instance of ObjectStreamClass corresponding
675 * to the specified class.
677 private ObjectStreamClass
lookupClass(Class clazz
)
679 ObjectStreamClass oclazz
;
681 oclazz
= (ObjectStreamClass
)classLookupTable
.get(clazz
);
683 return ObjectStreamClass
.lookup(clazz
);
689 * Reconstruct class hierarchy the same way
690 * {@link java.io.ObjectStreamClass.getObjectStreamClasses(java.lang.Class)} does
691 * but using lookupClass instead of ObjectStreamClass.lookup. This
692 * dup is necessary localize the lookup table. Hopefully some future
693 * rewritings will be able to prevent this.
695 * @param clazz This is the class for which we want the hierarchy.
697 * @return An array of valid {@link java.io.ObjectStreamClass} instances which
698 * represent the class hierarchy for clazz.
700 private ObjectStreamClass
[] inputGetObjectStreamClasses(Class clazz
)
702 ObjectStreamClass osc
= lookupClass(clazz
);
705 return new ObjectStreamClass
[0];
708 Vector oscs
= new Vector();
712 oscs
.addElement(osc
);
713 osc
= osc
.getSuper();
716 int count
= oscs
.size();
717 ObjectStreamClass
[] sorted_oscs
= new ObjectStreamClass
[count
];
719 for (int i
= count
- 1; i
>= 0; i
--)
720 sorted_oscs
[count
- i
- 1] = (ObjectStreamClass
) oscs
.elementAt(i
);
727 * Allows subclasses to resolve objects that are read from the
728 * stream with other objects to be returned in their place. This
729 * method is called the first time each object is encountered.
731 * This method must be enabled before it will be called in the
732 * serialization process.
734 * @exception IOException Exception from underlying
735 * <code>OutputStream</code>.
737 * @see #enableResolveObject(boolean)
739 protected Object
resolveObject(Object obj
) throws IOException
745 protected Class
resolveProxyClass(String
[] intfs
)
746 throws IOException
, ClassNotFoundException
748 SecurityManager sm
= System
.getSecurityManager();
751 sm
= new SecurityManager() {};
753 ClassLoader cl
= currentClassLoader(sm
);
755 Class
[] clss
= new Class
[intfs
.length
];
758 for (int i
= 0; i
< intfs
.length
; i
++)
759 clss
[i
] = Class
.forName(intfs
[i
]);
760 cl
= ClassLoader
.getSystemClassLoader();
763 for (int i
= 0; i
< intfs
.length
; i
++)
764 clss
[i
] = cl
.loadClass(intfs
[i
]);
767 return Proxy
.getProxyClass(cl
, clss
);
769 catch (IllegalArgumentException e
)
771 throw new ClassNotFoundException(null, e
);
776 * If <code>enable</code> is <code>true</code> and this object is
777 * trusted, then <code>resolveObject (Object)</code> will be called
778 * in subsequent calls to <code>readObject (Object)</code>.
779 * Otherwise, <code>resolveObject (Object)</code> will not be called.
781 * @exception SecurityException This class is not trusted.
783 protected boolean enableResolveObject (boolean enable
)
784 throws SecurityException
788 SecurityManager sm
= System
.getSecurityManager();
790 sm
.checkPermission(new SerializablePermission("enableSubstitution"));
793 boolean old_val
= this.resolveEnabled
;
794 this.resolveEnabled
= enable
;
799 * Reads stream magic and stream version information from the
802 * @exception IOException Exception from underlying stream.
804 * @exception StreamCorruptedException An invalid stream magic
805 * number or stream version was read from the stream.
807 protected void readStreamHeader()
808 throws IOException
, StreamCorruptedException
810 if(dump
) dumpElement("STREAM MAGIC ");
811 if (this.realInputStream
.readShort() != STREAM_MAGIC
)
812 throw new StreamCorruptedException("Invalid stream magic number");
814 if(dump
) dumpElementln("STREAM VERSION ");
815 if (this.realInputStream
.readShort() != STREAM_VERSION
)
816 throw new StreamCorruptedException("Invalid stream version number");
819 public int read() throws IOException
821 if (this.readDataFromBlock
)
823 if (this.blockDataPosition
>= this.blockDataBytes
)
825 return (this.blockData
[this.blockDataPosition
++] & 0xff);
828 return this.realInputStream
.read();
831 public int read(byte[] data
, int offset
, int length
) throws IOException
833 if (this.readDataFromBlock
)
835 if (this.blockDataPosition
+ length
> this.blockDataBytes
)
837 int remain
= this.blockDataBytes
- this.blockDataPosition
;
840 System
.arraycopy(this.blockData
, this.blockDataPosition
,
841 data
, offset
, remain
);
848 System
.arraycopy(this.blockData
, this.blockDataPosition
,
849 data
, offset
, length
);
850 this.blockDataPosition
+= length
;
855 return this.realInputStream
.read(data
, offset
, length
);
858 public int available() throws IOException
860 if (this.readDataFromBlock
)
862 if (this.blockDataPosition
>= this.blockDataBytes
)
865 return this.blockDataBytes
- this.blockDataPosition
;
868 return this.realInputStream
.available();
871 public void close() throws IOException
873 this.realInputStream
.close();
876 public boolean readBoolean() throws IOException
878 boolean switchmode
= true;
879 boolean oldmode
= this.readDataFromBlock
;
880 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 1)
883 oldmode
= setBlockDataMode (true);
884 boolean value
= this.dataInputStream
.readBoolean ();
886 setBlockDataMode (oldmode
);
890 public byte readByte() throws IOException
892 boolean switchmode
= true;
893 boolean oldmode
= this.readDataFromBlock
;
894 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 1)
897 oldmode
= setBlockDataMode(true);
898 byte value
= this.dataInputStream
.readByte();
900 setBlockDataMode(oldmode
);
904 public int readUnsignedByte() throws IOException
906 boolean switchmode
= true;
907 boolean oldmode
= this.readDataFromBlock
;
908 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 1)
911 oldmode
= setBlockDataMode(true);
912 int value
= this.dataInputStream
.readUnsignedByte();
914 setBlockDataMode(oldmode
);
918 public short readShort() throws IOException
920 boolean switchmode
= true;
921 boolean oldmode
= this.readDataFromBlock
;
922 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 2)
925 oldmode
= setBlockDataMode(true);
926 short value
= this.dataInputStream
.readShort();
928 setBlockDataMode(oldmode
);
932 public int readUnsignedShort() throws IOException
934 boolean switchmode
= true;
935 boolean oldmode
= this.readDataFromBlock
;
936 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 2)
939 oldmode
= setBlockDataMode(true);
940 int value
= this.dataInputStream
.readUnsignedShort();
942 setBlockDataMode(oldmode
);
946 public char readChar() throws IOException
948 boolean switchmode
= true;
949 boolean oldmode
= this.readDataFromBlock
;
950 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 2)
953 oldmode
= setBlockDataMode(true);
954 char value
= this.dataInputStream
.readChar();
956 setBlockDataMode(oldmode
);
960 public int readInt() throws IOException
962 boolean switchmode
= true;
963 boolean oldmode
= this.readDataFromBlock
;
964 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 4)
967 oldmode
= setBlockDataMode(true);
968 int value
= this.dataInputStream
.readInt();
970 setBlockDataMode(oldmode
);
974 public long readLong() throws IOException
976 boolean switchmode
= true;
977 boolean oldmode
= this.readDataFromBlock
;
978 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 8)
981 oldmode
= setBlockDataMode(true);
982 long value
= this.dataInputStream
.readLong();
984 setBlockDataMode(oldmode
);
988 public float readFloat() throws IOException
990 boolean switchmode
= true;
991 boolean oldmode
= this.readDataFromBlock
;
992 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 4)
995 oldmode
= setBlockDataMode(true);
996 float value
= this.dataInputStream
.readFloat();
998 setBlockDataMode(oldmode
);
1002 public double readDouble() throws IOException
1004 boolean switchmode
= true;
1005 boolean oldmode
= this.readDataFromBlock
;
1006 if (!oldmode
|| this.blockDataBytes
- this.blockDataPosition
>= 8)
1009 oldmode
= setBlockDataMode(true);
1010 double value
= this.dataInputStream
.readDouble();
1012 setBlockDataMode(oldmode
);
1016 public void readFully(byte data
[]) throws IOException
1018 this.dataInputStream
.readFully(data
);
1021 public void readFully(byte data
[], int offset
, int size
)
1024 this.dataInputStream
.readFully(data
, offset
, size
);
1027 public int skipBytes(int len
) throws IOException
1029 return this.dataInputStream
.skipBytes(len
);
1034 * @see java.io.DataInputStream#readLine ()
1036 public String
readLine() throws IOException
1038 return this.dataInputStream
.readLine();
1041 public String
readUTF() throws IOException
1043 return this.dataInputStream
.readUTF();
1047 * This class allows a class to specify exactly which fields should
1048 * be read, and what values should be read for these fields.
1050 * XXX: finish up comments
1052 public static abstract class GetField
1054 public abstract ObjectStreamClass
getObjectStreamClass();
1056 public abstract boolean defaulted(String name
)
1057 throws IOException
, IllegalArgumentException
;
1059 public abstract boolean get(String name
, boolean defvalue
)
1060 throws IOException
, IllegalArgumentException
;
1062 public abstract char get(String name
, char defvalue
)
1063 throws IOException
, IllegalArgumentException
;
1065 public abstract byte get(String name
, byte defvalue
)
1066 throws IOException
, IllegalArgumentException
;
1068 public abstract short get(String name
, short defvalue
)
1069 throws IOException
, IllegalArgumentException
;
1071 public abstract int get(String name
, int defvalue
)
1072 throws IOException
, IllegalArgumentException
;
1074 public abstract long get(String name
, long defvalue
)
1075 throws IOException
, IllegalArgumentException
;
1077 public abstract float get(String name
, float defvalue
)
1078 throws IOException
, IllegalArgumentException
;
1080 public abstract double get(String name
, double defvalue
)
1081 throws IOException
, IllegalArgumentException
;
1083 public abstract Object
get(String name
, Object defvalue
)
1084 throws IOException
, IllegalArgumentException
;
1088 * This method should be called by a method called 'readObject' in the
1089 * deserializing class (if present). It cannot (and should not)be called
1090 * outside of it. Its goal is to read all fields in the real input stream
1091 * and keep them accessible through the {@link #GetField} class. Calling
1092 * this method will not alter the deserializing object.
1094 * @return A valid freshly created 'GetField' instance to get access to
1095 * the deserialized stream.
1096 * @throws IOException An input/output exception occured.
1097 * @throws ClassNotFoundException
1098 * @throws NotActiveException
1100 public GetField
readFields()
1101 throws IOException
, ClassNotFoundException
, NotActiveException
1103 if (this.currentObject
== null || this.currentObjectStreamClass
== null)
1104 throw new NotActiveException("readFields called by non-active class and/or object");
1106 if (prereadFields
!= null)
1107 return prereadFields
;
1109 if (fieldsAlreadyRead
)
1110 throw new NotActiveException("readFields called but fields already read from"
1111 + " stream (by defaultReadObject or readFields)");
1113 final ObjectStreamClass clazz
= this.currentObjectStreamClass
;
1114 final byte[] prim_field_data
= new byte[clazz
.primFieldSize
];
1115 final Object
[] objs
= new Object
[clazz
.objectFieldCount
];
1117 // Apparently Block data is not used with GetField as per
1118 // empirical evidence against JDK 1.2. Also see Mauve test
1119 // java.io.ObjectInputOutput.Test.GetPutField.
1120 boolean oldmode
= setBlockDataMode(false);
1121 readFully(prim_field_data
);
1122 for (int i
= 0; i
< objs
.length
; ++ i
)
1123 objs
[i
] = readObject();
1124 setBlockDataMode(oldmode
);
1126 prereadFields
= new GetField()
1128 public ObjectStreamClass
getObjectStreamClass()
1133 public boolean defaulted(String name
)
1134 throws IOException
, IllegalArgumentException
1136 ObjectStreamField f
= clazz
.getField(name
);
1138 /* First if we have a serialized field use the descriptor */
1141 /* It is in serialPersistentFields but setClass tells us
1142 * it should not be set. This value is defaulted.
1144 if (f
.isPersistent() && !f
.isToSet())
1150 /* This is not a serialized field. There should be
1151 * a default value only if the field really exists.
1155 return (clazz
.forClass().getDeclaredField (name
) != null);
1157 catch (NoSuchFieldException e
)
1159 throw new IllegalArgumentException(e
.getMessage());
1163 public boolean get(String name
, boolean defvalue
)
1164 throws IOException
, IllegalArgumentException
1166 ObjectStreamField field
= getField(name
, Boolean
.TYPE
);
1171 return prim_field_data
[field
.getOffset()] == 0 ?
false : true;
1174 public char get(String name
, char defvalue
)
1175 throws IOException
, IllegalArgumentException
1177 ObjectStreamField field
= getField(name
, Character
.TYPE
);
1182 int off
= field
.getOffset();
1184 return (char)(((prim_field_data
[off
++] & 0xFF) << 8)
1185 | (prim_field_data
[off
] & 0xFF));
1188 public byte get(String name
, byte defvalue
)
1189 throws IOException
, IllegalArgumentException
1191 ObjectStreamField field
= getField(name
, Byte
.TYPE
);
1196 return prim_field_data
[field
.getOffset()];
1199 public short get(String name
, short defvalue
)
1200 throws IOException
, IllegalArgumentException
1202 ObjectStreamField field
= getField(name
, Short
.TYPE
);
1207 int off
= field
.getOffset();
1209 return (short)(((prim_field_data
[off
++] & 0xFF) << 8)
1210 | (prim_field_data
[off
] & 0xFF));
1213 public int get(String name
, int defvalue
)
1214 throws IOException
, IllegalArgumentException
1216 ObjectStreamField field
= getField(name
, Integer
.TYPE
);
1221 int off
= field
.getOffset();
1223 return ((prim_field_data
[off
++] & 0xFF) << 24)
1224 | ((prim_field_data
[off
++] & 0xFF) << 16)
1225 | ((prim_field_data
[off
++] & 0xFF) << 8)
1226 | (prim_field_data
[off
] & 0xFF);
1229 public long get(String name
, long defvalue
)
1230 throws IOException
, IllegalArgumentException
1232 ObjectStreamField field
= getField(name
, Long
.TYPE
);
1237 int off
= field
.getOffset();
1239 return (long)(((prim_field_data
[off
++] & 0xFF) << 56)
1240 | ((prim_field_data
[off
++] & 0xFF) << 48)
1241 | ((prim_field_data
[off
++] & 0xFF) << 40)
1242 | ((prim_field_data
[off
++] & 0xFF) << 32)
1243 | ((prim_field_data
[off
++] & 0xFF) << 24)
1244 | ((prim_field_data
[off
++] & 0xFF) << 16)
1245 | ((prim_field_data
[off
++] & 0xFF) << 8)
1246 | (prim_field_data
[off
] & 0xFF));
1249 public float get(String name
, float defvalue
)
1250 throws IOException
, IllegalArgumentException
1252 ObjectStreamField field
= getField(name
, Float
.TYPE
);
1257 int off
= field
.getOffset();
1259 return Float
.intBitsToFloat(((prim_field_data
[off
++] & 0xFF) << 24)
1260 | ((prim_field_data
[off
++] & 0xFF) << 16)
1261 | ((prim_field_data
[off
++] & 0xFF) << 8)
1262 | (prim_field_data
[off
] & 0xFF));
1265 public double get(String name
, double defvalue
)
1266 throws IOException
, IllegalArgumentException
1268 ObjectStreamField field
= getField(name
, Double
.TYPE
);
1273 int off
= field
.getOffset();
1275 return Double
.longBitsToDouble
1276 ( (long) (((prim_field_data
[off
++] & 0xFF) << 56)
1277 | ((prim_field_data
[off
++] & 0xFF) << 48)
1278 | ((prim_field_data
[off
++] & 0xFF) << 40)
1279 | ((prim_field_data
[off
++] & 0xFF) << 32)
1280 | ((prim_field_data
[off
++] & 0xFF) << 24)
1281 | ((prim_field_data
[off
++] & 0xFF) << 16)
1282 | ((prim_field_data
[off
++] & 0xFF) << 8)
1283 | (prim_field_data
[off
] & 0xFF)));
1286 public Object
get(String name
, Object defvalue
)
1287 throws IOException
, IllegalArgumentException
1289 ObjectStreamField field
=
1290 getField(name
, defvalue
== null ?
null : defvalue
.getClass ());
1295 return objs
[field
.getOffset()];
1298 private ObjectStreamField
getField(String name
, Class type
)
1299 throws IllegalArgumentException
1301 ObjectStreamField field
= clazz
.getField(name
);
1302 boolean illegal
= false;
1308 Class field_type
= field
.getType();
1310 if (type
== field_type
||
1311 (type
== null && !field_type
.isPrimitive()))
1318 throw new IllegalArgumentException
1319 ("Field requested is of type "
1320 + field_type
.getName()
1321 + ", but requested type was "
1322 + (type
== null ?
"Object" : type
.getName()));
1324 catch (NullPointerException _
)
1326 /* Here we catch NullPointerException, because it may
1327 only come from the call 'field.getType()'. If field
1328 is null, we have to return null and classpath ethic
1329 say we must try to avoid 'if (xxx == null)'.
1332 catch (IllegalArgumentException e
)
1341 /* If this is an unassigned field we should return
1342 * the default value.
1344 if (!illegal
&& field
!= null && !field
.isToSet() && field
.isPersistent())
1347 /* We do not want to modify transient fields. They should
1352 Field f
= clazz
.forClass().getDeclaredField(name
);
1353 if (Modifier
.isTransient(f
.getModifiers()))
1354 throw new IllegalArgumentException
1355 ("no such field (non transient) " + name
);
1356 if (field
== null && f
.getType() != type
)
1357 throw new IllegalArgumentException
1358 ("Invalid requested type for field " + name
);
1360 catch (NoSuchFieldException e
)
1363 throw new IllegalArgumentException(e
.getMessage());
1370 fieldsAlreadyRead
= true;
1371 return prereadFields
;
1375 * Protected constructor that allows subclasses to override
1376 * deserialization. This constructor should be called by subclasses
1377 * that wish to override <code>readObject (Object)</code>. This
1378 * method does a security check <i>NOTE: currently not
1379 * implemented</i>, then sets a flag that informs
1380 * <code>readObject (Object)</code> to call the subclasses
1381 * <code>readObjectOverride (Object)</code> method.
1383 * @see #readObjectOverride()
1385 protected ObjectInputStream()
1386 throws IOException
, SecurityException
1388 SecurityManager sec_man
= System
.getSecurityManager();
1389 if (sec_man
!= null)
1390 sec_man
.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION
);
1391 this.useSubclassMethod
= true;
1395 * This method allows subclasses to override the default
1396 * de serialization mechanism provided by
1397 * <code>ObjectInputStream</code>. To make this method be used for
1398 * writing objects, subclasses must invoke the 0-argument
1399 * constructor on this class from their constructor.
1401 * @see #ObjectInputStream()
1403 protected Object
readObjectOverride()
1404 throws ClassNotFoundException
, IOException
, OptionalDataException
1406 throw new IOException("Subclass of ObjectInputStream must implement readObjectOverride");
1410 * Assigns the next available handle to <code>obj</code>.
1412 * @param obj The object for which we want a new handle.
1413 * @return A valid handle for the specified object.
1415 private int assignNewHandle(Object obj
)
1417 this.objectLookupTable
.put(new Integer(this.nextOID
),
1418 new ObjectIdentityWrapper(obj
));
1419 return this.nextOID
++;
1422 private Object
processResolution(ObjectStreamClass osc
, Object obj
, int handle
)
1425 if (osc
!= null && obj
instanceof Serializable
)
1429 Method m
= osc
.readResolveMethod
;
1432 obj
= m
.invoke(obj
, new Object
[] {});
1435 catch (IllegalAccessException ignore
)
1438 catch (InvocationTargetException ignore
)
1443 if (this.resolveEnabled
)
1444 obj
= resolveObject(obj
);
1446 this.objectLookupTable
.put(new Integer(handle
),
1447 new ObjectIdentityWrapper(obj
));
1452 private void clearHandles()
1454 this.objectLookupTable
.clear();
1455 this.nextOID
= baseWireHandle
;
1458 private void readNextBlock() throws IOException
1460 readNextBlock(this.realInputStream
.readByte());
1463 private void readNextBlock(byte marker
) throws IOException
1465 if (marker
== TC_BLOCKDATA
)
1467 if(dump
) dumpElement("BLOCK DATA SIZE=");
1468 this.blockDataBytes
= this.realInputStream
.readUnsignedByte();
1469 if(dump
) dumpElementln (Integer
.toString(this.blockDataBytes
));
1471 else if (marker
== TC_BLOCKDATALONG
)
1473 if(dump
) dumpElement("BLOCK DATA LONG SIZE=");
1474 this.blockDataBytes
= this.realInputStream
.readInt();
1475 if(dump
) dumpElementln (Integer
.toString(this.blockDataBytes
));
1479 throw new EOFException("Attempt to read primitive data, but no data block is active.");
1482 if (this.blockData
.length
< this.blockDataBytes
)
1483 this.blockData
= new byte[this.blockDataBytes
];
1485 this.realInputStream
.readFully (this.blockData
, 0, this.blockDataBytes
);
1486 this.blockDataPosition
= 0;
1489 private void readArrayElements (Object array
, Class clazz
)
1490 throws ClassNotFoundException
, IOException
1492 if (clazz
.isPrimitive())
1494 if (clazz
== Boolean
.TYPE
)
1496 boolean[] cast_array
= (boolean[])array
;
1497 for (int i
=0; i
< cast_array
.length
; i
++)
1498 cast_array
[i
] = this.realInputStream
.readBoolean();
1501 if (clazz
== Byte
.TYPE
)
1503 byte[] cast_array
= (byte[])array
;
1504 for (int i
=0; i
< cast_array
.length
; i
++)
1505 cast_array
[i
] = this.realInputStream
.readByte();
1508 if (clazz
== Character
.TYPE
)
1510 char[] cast_array
= (char[])array
;
1511 for (int i
=0; i
< cast_array
.length
; i
++)
1512 cast_array
[i
] = this.realInputStream
.readChar();
1515 if (clazz
== Double
.TYPE
)
1517 double[] cast_array
= (double[])array
;
1518 for (int i
=0; i
< cast_array
.length
; i
++)
1519 cast_array
[i
] = this.realInputStream
.readDouble();
1522 if (clazz
== Float
.TYPE
)
1524 float[] cast_array
= (float[])array
;
1525 for (int i
=0; i
< cast_array
.length
; i
++)
1526 cast_array
[i
] = this.realInputStream
.readFloat();
1529 if (clazz
== Integer
.TYPE
)
1531 int[] cast_array
= (int[])array
;
1532 for (int i
=0; i
< cast_array
.length
; i
++)
1533 cast_array
[i
] = this.realInputStream
.readInt();
1536 if (clazz
== Long
.TYPE
)
1538 long[] cast_array
= (long[])array
;
1539 for (int i
=0; i
< cast_array
.length
; i
++)
1540 cast_array
[i
] = this.realInputStream
.readLong();
1543 if (clazz
== Short
.TYPE
)
1545 short[] cast_array
= (short[])array
;
1546 for (int i
=0; i
< cast_array
.length
; i
++)
1547 cast_array
[i
] = this.realInputStream
.readShort();
1553 Object
[] cast_array
= (Object
[])array
;
1554 for (int i
=0; i
< cast_array
.length
; i
++)
1555 cast_array
[i
] = readObject();
1559 private void readFields (Object obj
, ObjectStreamClass stream_osc
)
1560 throws ClassNotFoundException
, IOException
1562 ObjectStreamField
[] fields
= stream_osc
.fieldMapping
;
1564 for (int i
= 0; i
< fields
.length
; i
+= 2)
1566 ObjectStreamField stream_field
= fields
[i
];
1567 ObjectStreamField real_field
= fields
[i
+ 1];
1568 if(stream_field
!= null || real_field
!= null)
1570 boolean read_value
= stream_field
!= null;
1571 boolean set_value
= real_field
!= null;
1574 if (stream_field
!= null)
1576 field_name
= stream_field
.getName();
1577 type
= stream_field
.getTypeCode();
1581 field_name
= real_field
.getName();
1582 type
= real_field
.getTypeCode();
1590 read_value ?
this.realInputStream
.readBoolean() : false;
1591 if (dump
&& read_value
&& set_value
)
1592 dumpElementln(" " + field_name
+ ": " + value
);
1594 real_field
.setBooleanField(obj
, value
);
1600 read_value ?
this.realInputStream
.readByte() : 0;
1601 if (dump
&& read_value
&& set_value
)
1602 dumpElementln(" " + field_name
+ ": " + value
);
1604 real_field
.setByteField(obj
, value
);
1610 read_value ?
this.realInputStream
.readChar(): 0;
1611 if (dump
&& read_value
&& set_value
)
1612 dumpElementln(" " + field_name
+ ": " + value
);
1614 real_field
.setCharField(obj
, value
);
1620 read_value ?
this.realInputStream
.readDouble() : 0;
1621 if (dump
&& read_value
&& set_value
)
1622 dumpElementln(" " + field_name
+ ": " + value
);
1624 real_field
.setDoubleField(obj
, value
);
1630 read_value ?
this.realInputStream
.readFloat() : 0;
1631 if (dump
&& read_value
&& set_value
)
1632 dumpElementln(" " + field_name
+ ": " + value
);
1634 real_field
.setFloatField(obj
, value
);
1640 read_value ?
this.realInputStream
.readInt() : 0;
1641 if (dump
&& read_value
&& set_value
)
1642 dumpElementln(" " + field_name
+ ": " + value
);
1644 real_field
.setIntField(obj
, value
);
1650 read_value ?
this.realInputStream
.readLong() : 0;
1651 if (dump
&& read_value
&& set_value
)
1652 dumpElementln(" " + field_name
+ ": " + value
);
1654 real_field
.setLongField(obj
, value
);
1660 read_value ?
this.realInputStream
.readShort() : 0;
1661 if (dump
&& read_value
&& set_value
)
1662 dumpElementln(" " + field_name
+ ": " + value
);
1664 real_field
.setShortField(obj
, value
);
1671 read_value ?
readObject() : null;
1673 real_field
.setObjectField(obj
, value
);
1677 throw new InternalError("Invalid type code: " + type
);
1683 // Toggles writing primitive data to block-data buffer.
1684 private boolean setBlockDataMode (boolean on
)
1686 boolean oldmode
= this.readDataFromBlock
;
1687 this.readDataFromBlock
= on
;
1690 this.dataInputStream
= this.blockDataInput
;
1692 this.dataInputStream
= this.realInputStream
;
1696 // returns a new instance of REAL_CLASS that has been constructed
1697 // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
1698 private Object
newObject (Class real_class
, Class constructor_class
)
1699 throws ClassNotFoundException
1703 Object obj
= allocateObject (real_class
);
1704 callConstructor (constructor_class
, obj
);
1707 catch (InstantiationException e
)
1709 throw new ClassNotFoundException
1710 ("Instance of " + real_class
+ " could not be created");
1714 // runs all registered ObjectInputValidations in prioritized order
1716 private void invokeValidators() throws InvalidObjectException
1718 Object
[] validators
= new Object
[this.validators
.size()];
1719 this.validators
.copyInto (validators
);
1720 Arrays
.sort (validators
);
1724 for (int i
=0; i
< validators
.length
; i
++)
1725 ((ObjectInputValidation
)validators
[i
]).validateObject();
1729 this.validators
.removeAllElements();
1734 * This native method is used to get access to the protected method
1735 * of the same name in SecurityManger.
1737 * @param sm SecurityManager instance which should be called.
1738 * @return The current class loader in the calling stack.
1740 private static native ClassLoader
currentClassLoader (SecurityManager sm
);
1742 private void callReadMethod (Method readObject
, Class klass
, Object obj
) throws IOException
1746 readObject
.invoke(obj
, new Object
[] { this });
1748 catch (InvocationTargetException x
)
1750 /* Rethrow if possible. */
1751 Throwable exception
= x
.getTargetException();
1752 if (exception
instanceof RuntimeException
)
1753 throw (RuntimeException
) exception
;
1754 if (exception
instanceof IOException
)
1755 throw (IOException
) exception
;
1757 throw new IOException("Exception thrown from readObject() on " +
1758 klass
+ ": " + exception
.getClass().getName());
1762 throw new IOException("Failure invoking readObject() on " +
1763 klass
+ ": " + x
.getClass().getName());
1766 // Invalidate fields which has been read through readFields.
1767 prereadFields
= null;
1770 private native Object
allocateObject (Class clazz
)
1771 throws InstantiationException
;
1773 private native void callConstructor (Class clazz
, Object obj
);
1775 private static final int BUFFER_SIZE
= 1024;
1777 private DataInputStream realInputStream
;
1778 private DataInputStream dataInputStream
;
1779 private DataInputStream blockDataInput
;
1780 private int blockDataPosition
;
1781 private int blockDataBytes
;
1782 private byte[] blockData
;
1783 private boolean useSubclassMethod
;
1784 private int nextOID
;
1785 private boolean resolveEnabled
;
1786 private Hashtable objectLookupTable
;
1787 private Object currentObject
;
1788 private ObjectStreamClass currentObjectStreamClass
;
1789 private boolean readDataFromBlock
;
1790 private boolean isDeserializing
;
1791 private boolean fieldsAlreadyRead
;
1792 private Vector validators
;
1793 private Hashtable classLookupTable
;
1794 private GetField prereadFields
;
1796 private static boolean dump
= false && Configuration
.DEBUG
;
1798 private void dumpElement (String msg
)
1800 System
.out
.print(msg
);
1803 private void dumpElementln (String msg
)
1805 System
.out
.println(msg
);
1810 if (Configuration
.INIT_LOAD_LIBRARY
)
1812 System
.loadLibrary ("javaio");
1818 // used to keep a prioritized list of object validators
1819 class ValidatorAndPriority
implements Comparable
1822 ObjectInputValidation validator
;
1824 ValidatorAndPriority (ObjectInputValidation validator
, int priority
)
1826 this.priority
= priority
;
1827 this.validator
= validator
;
1830 public int compareTo (Object o
)
1832 ValidatorAndPriority vap
= (ValidatorAndPriority
)o
;
1833 return this.priority
- vap
.priority
;