2004-02-06 Jeroen Frijters <jeroen@frijters.net>
[official-gcc.git] / libjava / java / io / ObjectInputStream.java
blobd0def09181c98cef9bb875fa6e6ede8afadbdb5e
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)
9 any later version.
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
19 02111-1307 USA.
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
24 combination.
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. */
39 package java.io;
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
62 /**
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(""))
84 dump = true;
85 System.out.println ("Serialization debugging enabled");
87 else if (dump == true && (val == null || val.equals("")))
89 dump = false;
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);
106 readStreamHeader();
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;
132 Object ret_val;
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) + " ");
145 switch (marker)
147 case TC_ENDBLOCKDATA:
149 ret_val = null;
150 is_consumed = true;
151 break;
154 case TC_BLOCKDATA:
155 case TC_BLOCKDATALONG:
157 if (marker == TC_BLOCKDATALONG)
158 if(dump) dumpElementln("BLOCKDATALONG");
159 else
160 if(dump) dumpElementln("BLOCKDATA");
161 readNextBlock(marker);
162 throw new StreamCorruptedException("Unexpected blockData");
165 case TC_NULL:
167 if(dump) dumpElementln("NULL");
168 ret_val = null;
169 break;
172 case TC_REFERENCE:
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;
179 break;
182 case TC_CLASS:
184 if(dump) dumpElementln("CLASS");
185 ObjectStreamClass osc = (ObjectStreamClass)readObject();
186 Class clazz = osc.forClass();
187 assignNewHandle(clazz);
188 ret_val = clazz;
189 break;
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);
210 if (!is_consumed)
212 byte b = this.realInputStream.readByte();
213 if (b != TC_ENDBLOCKDATA)
214 throw new IOException("Data annotated to class was not consumed." + b);
216 else
217 is_consumed = false;
218 ObjectStreamClass superosc = (ObjectStreamClass)readObject();
219 osc.setSuperclass(superosc);
220 ret_val = osc;
221 break;
224 case TC_CLASSDESC:
226 ObjectStreamClass osc = readClassDescriptor();
228 if (!is_consumed)
230 byte b = this.realInputStream.readByte();
231 if (b != TC_ENDBLOCKDATA)
232 throw new IOException("Data annotated to class was not consumed." + b);
234 else
235 is_consumed = false;
237 osc.setSuperclass ((ObjectStreamClass)readObject());
238 ret_val = osc;
239 break;
242 case TC_STRING:
243 case TC_LONGSTRING:
245 if(dump) dumpElement("STRING=");
246 String s = this.realInputStream.readUTF();
247 if(dump) dumpElementln(s);
248 ret_val = processResolution(null, s, assignNewHandle(s));
249 break;
252 case TC_ARRAY:
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);
263 if(dump)
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);
267 break;
270 case TC_OBJECT:
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);
320 break;
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");
367 else
369 readFields(obj, currentObjectStreamClass);
373 this.currentObject = null;
374 this.currentObjectStreamClass = null;
375 ret_val = processResolution(osc, obj, handle);
376 break;
379 case TC_RESET:
380 if(dump) dumpElementln("RESET");
381 clearHandles();
382 ret_val = readObject();
383 break;
385 case TC_EXCEPTION:
387 if(dump) dumpElement("EXCEPTION=");
388 Exception e = (Exception)readObject();
389 if(dump) dumpElementln(e.toString());
390 clearHandles();
391 throw new WriteAbortedException("Exception thrown during writing of stream", e);
394 default:
395 throw new IOException("Unknown marker on stream: " + marker);
398 finally
400 setBlockDataMode(old_mode);
402 this.isDeserializing = was_deserializing;
404 if (! was_deserializing)
406 if (validators.size() > 0)
407 invokeValidators();
411 return ret_val;
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,
444 flags, fields);
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);
456 String class_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();
464 else
465 class_name = String.valueOf(type_code);
467 fields[i] =
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;
496 int stream_idx = 0;
497 int real_idx = 0;
498 int map_idx = 0;
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++];
514 else
516 int comp_val =
517 real_fields[real_idx].compareTo (stream_fields[stream_idx]);
519 if (comp_val < 0)
521 real_field = real_fields[real_idx++];
523 else if (comp_val > 0)
525 stream_field = stream_fields[stream_idx++];
527 else
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)
540 stream_field = null;
541 else if (!stream_field.isToSet())
542 real_field = null;
544 if (real_field != null && !real_field.isToSet())
545 real_field = null;
546 fieldmapping[map_idx++] = stream_field;
547 fieldmapping[map_idx++] = real_field;
550 return osc;
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>
559 * method.
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>
567 * method.
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
599 * called first.
601 * @see java.io.ObjectInputValidation
603 * @exception InvalidObjectException <code>validator</code> is
604 * <code>null</code>
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,
611 int priority)
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,
623 priority));
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
652 * present).
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();
660 if (sm == null)
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);
682 if (oclazz == null)
683 return ObjectStreamClass.lookup(clazz);
684 else
685 return oclazz;
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);
704 if (osc == null)
705 return new ObjectStreamClass[0];
706 else
708 Vector oscs = new Vector();
710 while (osc != null)
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);
722 return sorted_oscs;
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
741 return obj;
745 protected Class resolveProxyClass(String[] intfs)
746 throws IOException, ClassNotFoundException
748 SecurityManager sm = System.getSecurityManager();
750 if (sm == null)
751 sm = new SecurityManager() {};
753 ClassLoader cl = currentClassLoader(sm);
755 Class[] clss = new Class[intfs.length];
756 if(cl == null)
758 for (int i = 0; i < intfs.length; i++)
759 clss[i] = Class.forName(intfs[i]);
760 cl = ClassLoader.getSystemClassLoader();
762 else
763 for (int i = 0; i < intfs.length; i++)
764 clss[i] = cl.loadClass(intfs[i]);
765 try
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
786 if (enable)
788 SecurityManager sm = System.getSecurityManager();
789 if (sm != null)
790 sm.checkPermission(new SerializablePermission("enableSubstitution"));
793 boolean old_val = this.resolveEnabled;
794 this.resolveEnabled = enable;
795 return old_val;
799 * Reads stream magic and stream version information from the
800 * underlying stream.
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)
824 readNextBlock();
825 return (this.blockData[this.blockDataPosition++] & 0xff);
827 else
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;
838 if (remain != 0)
840 System.arraycopy(this.blockData, this.blockDataPosition,
841 data, offset, remain);
842 offset += remain;
843 length -= remain;
845 readNextBlock ();
848 System.arraycopy(this.blockData, this.blockDataPosition,
849 data, offset, length);
850 this.blockDataPosition += length;
852 return length;
854 else
855 return this.realInputStream.read(data, offset, length);
858 public int available() throws IOException
860 if (this.readDataFromBlock)
862 if (this.blockDataPosition >= this.blockDataBytes)
863 readNextBlock ();
865 return this.blockDataBytes - this.blockDataPosition;
867 else
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)
881 switchmode = false;
882 if (switchmode)
883 oldmode = setBlockDataMode (true);
884 boolean value = this.dataInputStream.readBoolean ();
885 if (switchmode)
886 setBlockDataMode (oldmode);
887 return value;
890 public byte readByte() throws IOException
892 boolean switchmode = true;
893 boolean oldmode = this.readDataFromBlock;
894 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
895 switchmode = false;
896 if (switchmode)
897 oldmode = setBlockDataMode(true);
898 byte value = this.dataInputStream.readByte();
899 if (switchmode)
900 setBlockDataMode(oldmode);
901 return value;
904 public int readUnsignedByte() throws IOException
906 boolean switchmode = true;
907 boolean oldmode = this.readDataFromBlock;
908 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
909 switchmode = false;
910 if (switchmode)
911 oldmode = setBlockDataMode(true);
912 int value = this.dataInputStream.readUnsignedByte();
913 if (switchmode)
914 setBlockDataMode(oldmode);
915 return value;
918 public short readShort() throws IOException
920 boolean switchmode = true;
921 boolean oldmode = this.readDataFromBlock;
922 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
923 switchmode = false;
924 if (switchmode)
925 oldmode = setBlockDataMode(true);
926 short value = this.dataInputStream.readShort();
927 if (switchmode)
928 setBlockDataMode(oldmode);
929 return value;
932 public int readUnsignedShort() throws IOException
934 boolean switchmode = true;
935 boolean oldmode = this.readDataFromBlock;
936 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
937 switchmode = false;
938 if (switchmode)
939 oldmode = setBlockDataMode(true);
940 int value = this.dataInputStream.readUnsignedShort();
941 if (switchmode)
942 setBlockDataMode(oldmode);
943 return value;
946 public char readChar() throws IOException
948 boolean switchmode = true;
949 boolean oldmode = this.readDataFromBlock;
950 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
951 switchmode = false;
952 if (switchmode)
953 oldmode = setBlockDataMode(true);
954 char value = this.dataInputStream.readChar();
955 if (switchmode)
956 setBlockDataMode(oldmode);
957 return value;
960 public int readInt() throws IOException
962 boolean switchmode = true;
963 boolean oldmode = this.readDataFromBlock;
964 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
965 switchmode = false;
966 if (switchmode)
967 oldmode = setBlockDataMode(true);
968 int value = this.dataInputStream.readInt();
969 if (switchmode)
970 setBlockDataMode(oldmode);
971 return value;
974 public long readLong() throws IOException
976 boolean switchmode = true;
977 boolean oldmode = this.readDataFromBlock;
978 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
979 switchmode = false;
980 if (switchmode)
981 oldmode = setBlockDataMode(true);
982 long value = this.dataInputStream.readLong();
983 if (switchmode)
984 setBlockDataMode(oldmode);
985 return value;
988 public float readFloat() throws IOException
990 boolean switchmode = true;
991 boolean oldmode = this.readDataFromBlock;
992 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
993 switchmode = false;
994 if (switchmode)
995 oldmode = setBlockDataMode(true);
996 float value = this.dataInputStream.readFloat();
997 if (switchmode)
998 setBlockDataMode(oldmode);
999 return value;
1002 public double readDouble() throws IOException
1004 boolean switchmode = true;
1005 boolean oldmode = this.readDataFromBlock;
1006 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
1007 switchmode = false;
1008 if (switchmode)
1009 oldmode = setBlockDataMode(true);
1010 double value = this.dataInputStream.readDouble();
1011 if (switchmode)
1012 setBlockDataMode(oldmode);
1013 return value;
1016 public void readFully(byte data[]) throws IOException
1018 this.dataInputStream.readFully(data);
1021 public void readFully(byte data[], int offset, int size)
1022 throws IOException
1024 this.dataInputStream.readFully(data, offset, size);
1027 public int skipBytes(int len) throws IOException
1029 return this.dataInputStream.skipBytes(len);
1033 * @deprecated
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()
1130 return clazz;
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 */
1139 if (f != null)
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())
1145 return true;
1147 return false;
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);
1168 if (field == null)
1169 return defvalue;
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);
1179 if (field == null)
1180 return defvalue;
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);
1193 if (field == null)
1194 return defvalue;
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);
1204 if (field == null)
1205 return defvalue;
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);
1218 if (field == null)
1219 return defvalue;
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);
1234 if (field == null)
1235 return defvalue;
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);
1254 if (field == null)
1255 return defvalue;
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);
1270 if (field == null)
1271 return defvalue;
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 ());
1292 if (field == null)
1293 return defvalue;
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()))
1313 /* See defaulted */
1314 return field;
1317 illegal = true;
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)
1334 throw e;
1337 return null;
1339 finally
1341 /* If this is an unassigned field we should return
1342 * the default value.
1344 if (!illegal && field != null && !field.isToSet() && field.isPersistent())
1345 return null;
1347 /* We do not want to modify transient fields. They should
1348 * be left to 0.
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)
1362 if (field == null)
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)
1423 throws IOException
1425 if (osc != null && obj instanceof Serializable)
1429 Method m = osc.readResolveMethod;
1430 if(m != null)
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));
1449 return 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));
1477 else
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();
1499 return;
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();
1506 return;
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();
1513 return;
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();
1520 return;
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();
1527 return;
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();
1534 return;
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();
1541 return;
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();
1548 return;
1551 else
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;
1572 String field_name;
1573 char type;
1574 if (stream_field != null)
1576 field_name = stream_field.getName();
1577 type = stream_field.getTypeCode();
1579 else
1581 field_name = real_field.getName();
1582 type = real_field.getTypeCode();
1585 switch(type)
1587 case 'Z':
1589 boolean value =
1590 read_value ? this.realInputStream.readBoolean() : false;
1591 if (dump && read_value && set_value)
1592 dumpElementln(" " + field_name + ": " + value);
1593 if (set_value)
1594 real_field.setBooleanField(obj, value);
1595 break;
1597 case 'B':
1599 byte value =
1600 read_value ? this.realInputStream.readByte() : 0;
1601 if (dump && read_value && set_value)
1602 dumpElementln(" " + field_name + ": " + value);
1603 if (set_value)
1604 real_field.setByteField(obj, value);
1605 break;
1607 case 'C':
1609 char value =
1610 read_value ? this.realInputStream.readChar(): 0;
1611 if (dump && read_value && set_value)
1612 dumpElementln(" " + field_name + ": " + value);
1613 if (set_value)
1614 real_field.setCharField(obj, value);
1615 break;
1617 case 'D':
1619 double value =
1620 read_value ? this.realInputStream.readDouble() : 0;
1621 if (dump && read_value && set_value)
1622 dumpElementln(" " + field_name + ": " + value);
1623 if (set_value)
1624 real_field.setDoubleField(obj, value);
1625 break;
1627 case 'F':
1629 float value =
1630 read_value ? this.realInputStream.readFloat() : 0;
1631 if (dump && read_value && set_value)
1632 dumpElementln(" " + field_name + ": " + value);
1633 if (set_value)
1634 real_field.setFloatField(obj, value);
1635 break;
1637 case 'I':
1639 int value =
1640 read_value ? this.realInputStream.readInt() : 0;
1641 if (dump && read_value && set_value)
1642 dumpElementln(" " + field_name + ": " + value);
1643 if (set_value)
1644 real_field.setIntField(obj, value);
1645 break;
1647 case 'J':
1649 long value =
1650 read_value ? this.realInputStream.readLong() : 0;
1651 if (dump && read_value && set_value)
1652 dumpElementln(" " + field_name + ": " + value);
1653 if (set_value)
1654 real_field.setLongField(obj, value);
1655 break;
1657 case 'S':
1659 short value =
1660 read_value ? this.realInputStream.readShort() : 0;
1661 if (dump && read_value && set_value)
1662 dumpElementln(" " + field_name + ": " + value);
1663 if (set_value)
1664 real_field.setShortField(obj, value);
1665 break;
1667 case 'L':
1668 case '[':
1670 Object value =
1671 read_value ? readObject() : null;
1672 if (set_value)
1673 real_field.setObjectField(obj, value);
1674 break;
1676 default:
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;
1689 if (on)
1690 this.dataInputStream = this.blockDataInput;
1691 else
1692 this.dataInputStream = this.realInputStream;
1693 return oldmode;
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);
1705 return 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
1715 // on OBJ
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();
1727 finally
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());
1760 catch (Exception x)
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);
1808 static
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
1821 int priority;
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;