fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / libjava / java / io / ObjectInputStream.java
bloba277691e9761b351543597cbde465cb08dca6712
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 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 dumpElementln("BLOCKDATALONG");
159 else
160 dumpElementln("BLOCKDATA");
161 readNextBlock(marker);
162 throw new StreamCorruptedException("Unexpected blockData");
165 case TC_NULL:
167 dumpElementln("NULL");
168 ret_val = null;
169 break;
172 case TC_REFERENCE:
174 dumpElement("REFERENCE ");
175 Integer oid = new Integer(this.realInputStream.readInt());
176 dumpElementln(Integer.toHexString(oid.intValue()));
177 ret_val = ((ObjectIdentityWrapper)
178 this.objectLookupTable.get(oid)).object;
179 break;
182 case TC_CLASS:
184 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 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 dumpElement("STRING=");
246 String s = this.realInputStream.readUTF();
247 dumpElementln(s);
248 ret_val = processResolution(s, assignNewHandle(s));
249 break;
252 case TC_ARRAY:
254 dumpElementln("ARRAY");
255 ObjectStreamClass osc = (ObjectStreamClass)readObject();
256 Class componentType = osc.forClass().getComponentType();
257 dumpElement("ARRAY LENGTH=");
258 int length = this.realInputStream.readInt();
259 dumpElementln (length + "; COMPONENT TYPE=" + componentType);
260 Object array = Array.newInstance(componentType, length);
261 int handle = assignNewHandle(array);
262 readArrayElements(array, componentType);
263 for (int i = 0, len = Array.getLength(array); i < len; i++)
264 dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i));
265 ret_val = processResolution(array, handle);
266 break;
269 case TC_OBJECT:
271 dumpElementln("OBJECT");
272 ObjectStreamClass osc = (ObjectStreamClass)readObject();
273 Class clazz = osc.forClass();
275 if (!Serializable.class.isAssignableFrom(clazz))
276 throw new NotSerializableException
277 (clazz + " is not Serializable, and thus cannot be deserialized.");
279 if (Externalizable.class.isAssignableFrom(clazz))
281 Externalizable obj = null;
285 obj = (Externalizable)clazz.newInstance();
287 catch (InstantiationException e)
289 throw new ClassNotFoundException
290 ("Instance of " + clazz + " could not be created");
292 catch (IllegalAccessException e)
294 throw new ClassNotFoundException
295 ("Instance of " + clazz + " could not be created because class or "
296 + "zero-argument constructor is not accessible");
298 catch (NoSuchMethodError e)
300 throw new ClassNotFoundException
301 ("Instance of " + clazz
302 + " could not be created because zero-argument constructor is not defined");
305 int handle = assignNewHandle(obj);
307 boolean read_from_blocks = ((osc.getFlags() & SC_BLOCK_DATA) != 0);
309 boolean oldmode = this.readDataFromBlock;
310 if (read_from_blocks)
311 setBlockDataMode(true);
313 obj.readExternal(this);
315 if (read_from_blocks)
316 setBlockDataMode(oldmode);
318 ret_val = processResolution(obj, handle);
319 break;
320 } // end if (Externalizable.class.isAssignableFrom (clazz))
322 // find the first non-serializable, non-abstract
323 // class in clazz's inheritance hierarchy
324 Class first_nonserial = clazz.getSuperclass();
325 while (Serializable.class.isAssignableFrom(first_nonserial)
326 || Modifier.isAbstract(first_nonserial.getModifiers()))
327 first_nonserial = first_nonserial.getSuperclass();
329 Object obj = null;
330 obj = newObject(clazz, first_nonserial);
332 if (obj == null)
333 throw new ClassNotFoundException
334 ("Instance of " + clazz + " could not be created");
336 int handle = assignNewHandle(obj);
337 this.currentObject = obj;
338 ObjectStreamClass[] hierarchy =
339 inputGetObjectStreamClasses(clazz);
341 for (int i = 0; i < hierarchy.length; i++)
343 this.currentObjectStreamClass = hierarchy[i];
345 dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ());
347 // XXX: should initialize fields in classes in the hierarchy
348 // that aren't in the stream
349 // should skip over classes in the stream that aren't in the
350 // real classes hierarchy
352 if (this.currentObjectStreamClass.hasReadMethod())
354 fieldsAlreadyRead = false;
355 boolean oldmode = setBlockDataMode(true);
356 callReadMethod(obj, this.currentObjectStreamClass);
357 setBlockDataMode(oldmode);
358 dumpElement("ENDBLOCKDATA? ");
361 // FIXME: XXX: This try block is to catch EOF which is
362 // thrown for some objects. That indicates a bug in the logic.
363 if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
364 throw new IOException
365 ("No end of block data seen for class with readObject (ObjectInputStream) method.");
366 dumpElementln("yes");
368 catch (EOFException e)
370 dumpElementln("no, got EOFException");
372 catch (IOException e)
374 dumpElementln("no, got IOException");
377 else
379 readFields(obj, currentObjectStreamClass);
383 this.currentObject = null;
384 this.currentObjectStreamClass = null;
385 ret_val = processResolution(obj, handle);
386 break;
389 case TC_RESET:
390 dumpElementln("RESET");
391 clearHandles();
392 ret_val = readObject();
393 break;
395 case TC_EXCEPTION:
397 dumpElement("EXCEPTION=");
398 Exception e = (Exception)readObject();
399 dumpElementln(e.toString());
400 clearHandles();
401 throw new WriteAbortedException("Exception thrown during writing of stream", e);
404 default:
405 throw new IOException("Unknown marker on stream: " + marker);
408 finally
410 setBlockDataMode(old_mode);
412 this.isDeserializing = was_deserializing;
414 if (! was_deserializing)
416 if (validators.size() > 0)
417 invokeValidators();
421 return ret_val;
425 * This method reads a class descriptor from the real input stream
426 * and use these data to create a new instance of ObjectStreamClass.
427 * Fields are sorted and ordered for the real read which occurs for
428 * each instance of the described class. Be aware that if you call that
429 * method you must ensure that the stream is synchronized, in the other
430 * case it may be completely desynchronized.
432 * @return A new instance of ObjectStreamClass containing the freshly
433 * created descriptor.
434 * @throws ClassNotFoundException if the required class to build the
435 * descriptor has not been found in the system.
436 * @throws IOException An input/output error occured.
437 * @throws InvalidClassException If there was a compatibility problem
438 * between the class present in the system and the serialized class.
440 protected ObjectStreamClass readClassDescriptor()
441 throws ClassNotFoundException, IOException
443 dumpElement("CLASSDESC NAME=");
444 String name = this.realInputStream.readUTF();
445 dumpElement(name + "; UID=");
446 long uid = this.realInputStream.readLong ();
447 dumpElement(Long.toHexString(uid) + "; FLAGS=");
448 byte flags = this.realInputStream.readByte ();
449 dumpElement(Integer.toHexString(flags) + "; FIELD COUNT=");
450 short field_count = this.realInputStream.readShort();
451 dumpElementln(Short.toString(field_count));
452 ObjectStreamField[] fields = new ObjectStreamField[field_count];
453 ObjectStreamClass osc = new ObjectStreamClass(name, uid,
454 flags, fields);
455 assignNewHandle(osc);
457 for (int i = 0; i < field_count; i++)
459 dumpElement(" TYPE CODE=");
460 char type_code = (char)this.realInputStream.readByte();
461 dumpElement(type_code + "; FIELD NAME=");
462 String field_name = this.realInputStream.readUTF();
463 dumpElementln(field_name);
464 String class_name;
466 // If the type code is an array or an object we must
467 // decode a String here. In the other case we convert
468 // the type code and pass it to ObjectStreamField.
469 // Type codes are decoded by gnu.java.lang.reflect.TypeSignature.
470 if (type_code == 'L' || type_code == '[')
471 class_name = (String)readObject();
472 else
473 class_name = String.valueOf(type_code);
475 fields[i] =
476 new ObjectStreamField(field_name, class_name, currentLoader());
479 /* Now that fields have been read we may resolve the class
480 * (and read annotation if needed). */
481 Class clazz = resolveClass(osc);
483 for (int i = 0; i < field_count; i++)
485 Field f;
489 f = clazz.getDeclaredField(fields[i].getName());
490 if (f != null && !f.getType().equals(fields[i].getType()))
491 throw new InvalidClassException
492 ("invalid field type for " + fields[i].getName() + " in class "
493 + name + " (requested was \"" + fields[i].getType()
494 + " and found \"" + f.getType() + "\")");
496 catch (NoSuchFieldException _)
501 boolean oldmode = setBlockDataMode(true);
502 osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
503 classLookupTable.put(clazz, osc);
504 setBlockDataMode(oldmode);
506 return osc;
510 * Reads the current objects non-transient, non-static fields from
511 * the current class from the underlying output stream.
513 * This method is intended to be called from within a object's
514 * <code>private void readObject (ObjectInputStream)</code>
515 * method.
517 * @exception ClassNotFoundException The class that an object being
518 * read in belongs to cannot be found.
520 * @exception NotActiveException This method was called from a
521 * context other than from the current object's and current class's
522 * <code>private void readObject (ObjectInputStream)</code>
523 * method.
525 * @exception IOException Exception from underlying
526 * <code>OutputStream</code>.
528 public void defaultReadObject()
529 throws ClassNotFoundException, IOException, NotActiveException
531 if (this.currentObject == null || this.currentObjectStreamClass == null)
532 throw new NotActiveException("defaultReadObject called by non-active"
533 + " class and/or object");
535 if (fieldsAlreadyRead)
536 throw new NotActiveException("defaultReadObject called but fields "
537 + "already read from stream (by "
538 + "defaultReadObject or readFields)");
540 boolean oldmode = setBlockDataMode(false);
541 readFields(this.currentObject, this.currentObjectStreamClass);
542 setBlockDataMode(oldmode);
544 fieldsAlreadyRead = true;
549 * Registers a <code>ObjectInputValidation</code> to be carried out
550 * on the object graph currently being deserialized before it is
551 * returned to the original caller of <code>readObject ()</code>.
552 * The order of validation for multiple
553 * <code>ObjectInputValidation</code>s can be controled using
554 * <code>priority</code>. Validators with higher priorities are
555 * called first.
557 * @see java.io.ObjectInputValidation
559 * @exception InvalidObjectException <code>validator</code> is
560 * <code>null</code>
562 * @exception NotActiveException an attempt was made to add a
563 * validator outside of the <code>readObject</code> method of the
564 * object currently being deserialized
566 public void registerValidation(ObjectInputValidation validator,
567 int priority)
568 throws InvalidObjectException, NotActiveException
570 if (this.currentObject == null || this.currentObjectStreamClass == null)
571 throw new NotActiveException("registerValidation called by non-active "
572 + "class and/or object");
574 if (validator == null)
575 throw new InvalidObjectException("attempt to add a null "
576 + "ObjectInputValidation object");
578 this.validators.addElement(new ValidatorAndPriority (validator,
579 priority));
584 * Called when a class is being deserialized. This is a hook to
585 * allow subclasses to read in information written by the
586 * <code>annotateClass (Class)</code> method of an
587 * <code>ObjectOutputStream</code>.
589 * This implementation looks up the active call stack for a
590 * <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,
591 * it is used to load the class associated with <code>osc</code>,
592 * otherwise, the default system <code>ClassLoader</code> is used.
594 * @exception IOException Exception from underlying
595 * <code>OutputStream</code>.
597 * @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
599 protected Class resolveClass(ObjectStreamClass osc)
600 throws ClassNotFoundException, IOException
602 return Class.forName(osc.getName(), true, currentLoader());
606 * This method invokes the method currentClassLoader for the
607 * current security manager (or build an empty one if it is not
608 * present).
610 * @return The most recent non-system ClassLoader on the execution stack.
611 * @see java.lang.SecurityManager#currentClassLoader()
613 private ClassLoader currentLoader()
615 SecurityManager sm = System.getSecurityManager();
616 if (sm == null)
617 sm = new SecurityManager () {};
619 return currentClassLoader(sm);
623 * Lookup a class stored in the local hashtable. If it is not
624 * use the global lookup function in ObjectStreamClass to build
625 * the ObjectStreamClass. This method is requested according to
626 * the behaviour detected in the JDK by Kaffe's team.
628 * @param clazz Class to lookup in the hash table or for which
629 * we must build a descriptor.
630 * @return A valid instance of ObjectStreamClass corresponding
631 * to the specified class.
633 private ObjectStreamClass lookupClass(Class clazz)
635 ObjectStreamClass oclazz;
637 oclazz = (ObjectStreamClass)classLookupTable.get(clazz);
638 if (oclazz == null)
639 return ObjectStreamClass.lookup(clazz);
640 else
641 return oclazz;
645 * Reconstruct class hierarchy the same way
646 * {@link java.io.ObjectStreamClass.getObjectStreamClasses(java.lang.Class)} does
647 * but using lookupClass instead of ObjectStreamClass.lookup. This
648 * dup is necessary localize the lookup table. Hopefully some future
649 * rewritings will be able to prevent this.
651 * @param clazz This is the class for which we want the hierarchy.
653 * @return An array of valid {@link java.io.ObjectStreamClass} instances which
654 * represent the class hierarchy for clazz.
656 private ObjectStreamClass[] inputGetObjectStreamClasses(Class clazz)
658 ObjectStreamClass osc = lookupClass(clazz);
660 if (osc == null)
661 return new ObjectStreamClass[0];
662 else
664 Vector oscs = new Vector();
666 while (osc != null)
668 oscs.addElement(osc);
669 osc = osc.getSuper();
672 int count = oscs.size();
673 ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[count];
675 for (int i = count - 1; i >= 0; i--)
676 sorted_oscs[count - i - 1] = (ObjectStreamClass) oscs.elementAt(i);
678 return sorted_oscs;
683 * Allows subclasses to resolve objects that are read from the
684 * stream with other objects to be returned in their place. This
685 * method is called the first time each object is encountered.
687 * This method must be enabled before it will be called in the
688 * serialization process.
690 * @exception IOException Exception from underlying
691 * <code>OutputStream</code>.
693 * @see #enableResolveObject(boolean)
695 protected Object resolveObject(Object obj) throws IOException
697 return obj;
701 protected Class resolveProxyClass(String[] intfs)
702 throws IOException, ClassNotFoundException
704 SecurityManager sm = System.getSecurityManager();
706 if (sm == null)
707 sm = new SecurityManager() {};
709 ClassLoader cl = currentClassLoader(sm);
711 Class[] clss = new Class[intfs.length];
712 if(cl == null)
714 for (int i = 0; i < intfs.length; i++)
715 clss[i] = Class.forName(intfs[i]);
716 cl = ClassLoader.getSystemClassLoader();
718 else
719 for (int i = 0; i < intfs.length; i++)
720 clss[i] = cl.loadClass(intfs[i]);
721 try
723 return Proxy.getProxyClass(cl, clss);
725 catch (IllegalArgumentException e)
727 throw new ClassNotFoundException(null, e);
732 * If <code>enable</code> is <code>true</code> and this object is
733 * trusted, then <code>resolveObject (Object)</code> will be called
734 * in subsequent calls to <code>readObject (Object)</code>.
735 * Otherwise, <code>resolveObject (Object)</code> will not be called.
737 * @exception SecurityException This class is not trusted.
739 protected boolean enableResolveObject (boolean enable)
740 throws SecurityException
742 if (enable)
744 SecurityManager sm = System.getSecurityManager();
745 if (sm != null)
746 sm.checkPermission(new SerializablePermission("enableSubstitution"));
749 boolean old_val = this.resolveEnabled;
750 this.resolveEnabled = enable;
751 return old_val;
755 * Reads stream magic and stream version information from the
756 * underlying stream.
758 * @exception IOException Exception from underlying stream.
760 * @exception StreamCorruptedException An invalid stream magic
761 * number or stream version was read from the stream.
763 protected void readStreamHeader()
764 throws IOException, StreamCorruptedException
766 dumpElement("STREAM MAGIC ");
767 if (this.realInputStream.readShort() != STREAM_MAGIC)
768 throw new StreamCorruptedException("Invalid stream magic number");
770 dumpElementln("STREAM VERSION ");
771 if (this.realInputStream.readShort() != STREAM_VERSION)
772 throw new StreamCorruptedException("Invalid stream version number");
775 public int read() throws IOException
777 if (this.readDataFromBlock)
779 if (this.blockDataPosition >= this.blockDataBytes)
780 readNextBlock();
781 return (this.blockData[this.blockDataPosition++] & 0xff);
783 else
784 return this.realInputStream.read();
787 public int read(byte[] data, int offset, int length) throws IOException
789 if (this.readDataFromBlock)
791 if (this.blockDataPosition + length > this.blockDataBytes)
793 int remain = this.blockDataBytes - this.blockDataPosition;
794 if (remain != 0)
796 System.arraycopy(this.blockData, this.blockDataPosition,
797 data, offset, remain);
798 offset += remain;
799 length -= remain;
801 readNextBlock ();
804 System.arraycopy(this.blockData, this.blockDataPosition,
805 data, offset, length);
806 this.blockDataPosition += length;
808 return length;
810 else
811 return this.realInputStream.read(data, offset, length);
814 public int available() throws IOException
816 if (this.readDataFromBlock)
818 if (this.blockDataPosition >= this.blockDataBytes)
819 readNextBlock ();
821 return this.blockDataBytes - this.blockDataPosition;
823 else
824 return this.realInputStream.available();
827 public void close() throws IOException
829 this.realInputStream.close();
832 public boolean readBoolean() throws IOException
834 boolean switchmode = true;
835 boolean oldmode = this.readDataFromBlock;
836 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
837 switchmode = false;
838 if (switchmode)
839 oldmode = setBlockDataMode (true);
840 boolean value = this.dataInputStream.readBoolean ();
841 if (switchmode)
842 setBlockDataMode (oldmode);
843 return value;
846 public byte readByte() throws IOException
848 boolean switchmode = true;
849 boolean oldmode = this.readDataFromBlock;
850 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
851 switchmode = false;
852 if (switchmode)
853 oldmode = setBlockDataMode(true);
854 byte value = this.dataInputStream.readByte();
855 if (switchmode)
856 setBlockDataMode(oldmode);
857 return value;
860 public int readUnsignedByte() throws IOException
862 boolean switchmode = true;
863 boolean oldmode = this.readDataFromBlock;
864 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1)
865 switchmode = false;
866 if (switchmode)
867 oldmode = setBlockDataMode(true);
868 int value = this.dataInputStream.readUnsignedByte();
869 if (switchmode)
870 setBlockDataMode(oldmode);
871 return value;
874 public short readShort() throws IOException
876 boolean switchmode = true;
877 boolean oldmode = this.readDataFromBlock;
878 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
879 switchmode = false;
880 if (switchmode)
881 oldmode = setBlockDataMode(true);
882 short value = this.dataInputStream.readShort();
883 if (switchmode)
884 setBlockDataMode(oldmode);
885 return value;
888 public int readUnsignedShort() throws IOException
890 boolean switchmode = true;
891 boolean oldmode = this.readDataFromBlock;
892 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
893 switchmode = false;
894 if (switchmode)
895 oldmode = setBlockDataMode(true);
896 int value = this.dataInputStream.readUnsignedShort();
897 if (switchmode)
898 setBlockDataMode(oldmode);
899 return value;
902 public char readChar() throws IOException
904 boolean switchmode = true;
905 boolean oldmode = this.readDataFromBlock;
906 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 2)
907 switchmode = false;
908 if (switchmode)
909 oldmode = setBlockDataMode(true);
910 char value = this.dataInputStream.readChar();
911 if (switchmode)
912 setBlockDataMode(oldmode);
913 return value;
916 public int readInt() throws IOException
918 boolean switchmode = true;
919 boolean oldmode = this.readDataFromBlock;
920 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
921 switchmode = false;
922 if (switchmode)
923 oldmode = setBlockDataMode(true);
924 int value = this.dataInputStream.readInt();
925 if (switchmode)
926 setBlockDataMode(oldmode);
927 return value;
930 public long readLong() throws IOException
932 boolean switchmode = true;
933 boolean oldmode = this.readDataFromBlock;
934 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
935 switchmode = false;
936 if (switchmode)
937 oldmode = setBlockDataMode(true);
938 long value = this.dataInputStream.readLong();
939 if (switchmode)
940 setBlockDataMode(oldmode);
941 return value;
944 public float readFloat() throws IOException
946 boolean switchmode = true;
947 boolean oldmode = this.readDataFromBlock;
948 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 4)
949 switchmode = false;
950 if (switchmode)
951 oldmode = setBlockDataMode(true);
952 float value = this.dataInputStream.readFloat();
953 if (switchmode)
954 setBlockDataMode(oldmode);
955 return value;
958 public double readDouble() throws IOException
960 boolean switchmode = true;
961 boolean oldmode = this.readDataFromBlock;
962 if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 8)
963 switchmode = false;
964 if (switchmode)
965 oldmode = setBlockDataMode(true);
966 double value = this.dataInputStream.readDouble();
967 if (switchmode)
968 setBlockDataMode(oldmode);
969 return value;
972 public void readFully(byte data[]) throws IOException
974 this.dataInputStream.readFully(data);
977 public void readFully(byte data[], int offset, int size)
978 throws IOException
980 this.dataInputStream.readFully(data, offset, size);
983 public int skipBytes(int len) throws IOException
985 return this.dataInputStream.skipBytes(len);
989 * @deprecated
990 * @see java.io.DataInputStream#readLine ()
992 public String readLine() throws IOException
994 return this.dataInputStream.readLine();
997 public String readUTF() throws IOException
999 return this.dataInputStream.readUTF();
1003 * This class allows a class to specify exactly which fields should
1004 * be read, and what values should be read for these fields.
1006 * XXX: finish up comments
1008 public static abstract class GetField
1010 public abstract ObjectStreamClass getObjectStreamClass();
1012 public abstract boolean defaulted(String name)
1013 throws IOException, IllegalArgumentException;
1015 public abstract boolean get(String name, boolean defvalue)
1016 throws IOException, IllegalArgumentException;
1018 public abstract char get(String name, char defvalue)
1019 throws IOException, IllegalArgumentException;
1021 public abstract byte get(String name, byte defvalue)
1022 throws IOException, IllegalArgumentException;
1024 public abstract short get(String name, short defvalue)
1025 throws IOException, IllegalArgumentException;
1027 public abstract int get(String name, int defvalue)
1028 throws IOException, IllegalArgumentException;
1030 public abstract long get(String name, long defvalue)
1031 throws IOException, IllegalArgumentException;
1033 public abstract float get(String name, float defvalue)
1034 throws IOException, IllegalArgumentException;
1036 public abstract double get(String name, double defvalue)
1037 throws IOException, IllegalArgumentException;
1039 public abstract Object get(String name, Object defvalue)
1040 throws IOException, IllegalArgumentException;
1044 * This method should be called by a method called 'readObject' in the
1045 * deserializing class (if present). It cannot (and should not)be called
1046 * outside of it. Its goal is to read all fields in the real input stream
1047 * and keep them accessible through the {@link #GetField} class. Calling
1048 * this method will not alterate the deserializing object.
1050 * @return A valid freshly created 'GetField' instance to get access to
1051 * the deserialized stream.
1052 * @throws IOException An input/output exception occured.
1053 * @throws ClassNotFoundException
1054 * @throws NotActiveException
1056 public GetField readFields()
1057 throws IOException, ClassNotFoundException, NotActiveException
1059 if (this.currentObject == null || this.currentObjectStreamClass == null)
1060 throw new NotActiveException("readFields called by non-active class and/or object");
1062 if (prereadFields != null)
1063 return prereadFields;
1065 if (fieldsAlreadyRead)
1066 throw new NotActiveException("readFields called but fields already read from"
1067 + " stream (by defaultReadObject or readFields)");
1069 final ObjectStreamClass clazz = this.currentObjectStreamClass;
1070 final byte[] prim_field_data = new byte[clazz.primFieldSize];
1071 final Object[] objs = new Object[clazz.objectFieldCount];
1073 // Apparently Block data is not used with GetField as per
1074 // empirical evidence against JDK 1.2. Also see Mauve test
1075 // java.io.ObjectInputOutput.Test.GetPutField.
1076 boolean oldmode = setBlockDataMode(false);
1077 readFully(prim_field_data);
1078 for (int i = 0; i < objs.length; ++ i)
1079 objs[i] = readObject();
1080 setBlockDataMode(oldmode);
1082 prereadFields = new GetField()
1084 public ObjectStreamClass getObjectStreamClass()
1086 return clazz;
1089 public boolean defaulted(String name)
1090 throws IOException, IllegalArgumentException
1092 ObjectStreamField f = clazz.getField(name);
1094 /* First if we have a serialized field use the descriptor */
1095 if (f != null)
1097 /* It is in serialPersistentFields but setClass tells us
1098 * it should not be set. This value is defaulted.
1100 if (f.isPersistent() && !f.isToSet())
1101 return true;
1103 return false;
1106 /* This is not a serialized field. There should be
1107 * a default value only if the field really exists.
1111 return (clazz.forClass().getDeclaredField (name) != null);
1113 catch (NoSuchFieldException e)
1115 throw new IllegalArgumentException(e.getMessage());
1119 public boolean get(String name, boolean defvalue)
1120 throws IOException, IllegalArgumentException
1122 ObjectStreamField field = getField(name, Boolean.TYPE);
1124 if (field == null)
1125 return defvalue;
1127 return prim_field_data[field.getOffset()] == 0 ? false : true;
1130 public char get(String name, char defvalue)
1131 throws IOException, IllegalArgumentException
1133 ObjectStreamField field = getField(name, Character.TYPE);
1135 if (field == null)
1136 return defvalue;
1138 int off = field.getOffset();
1140 return (char)(((prim_field_data[off++] & 0xFF) << 8)
1141 | (prim_field_data[off] & 0xFF));
1144 public byte get(String name, byte defvalue)
1145 throws IOException, IllegalArgumentException
1147 ObjectStreamField field = getField(name, Byte.TYPE);
1149 if (field == null)
1150 return defvalue;
1152 return prim_field_data[field.getOffset()];
1155 public short get(String name, short defvalue)
1156 throws IOException, IllegalArgumentException
1158 ObjectStreamField field = getField(name, Short.TYPE);
1160 if (field == null)
1161 return defvalue;
1163 int off = field.getOffset();
1165 return (short)(((prim_field_data[off++] & 0xFF) << 8)
1166 | (prim_field_data[off] & 0xFF));
1169 public int get(String name, int defvalue)
1170 throws IOException, IllegalArgumentException
1172 ObjectStreamField field = getField(name, Integer.TYPE);
1174 if (field == null)
1175 return defvalue;
1177 int off = field.getOffset();
1179 return ((prim_field_data[off++] & 0xFF) << 24)
1180 | ((prim_field_data[off++] & 0xFF) << 16)
1181 | ((prim_field_data[off++] & 0xFF) << 8)
1182 | (prim_field_data[off] & 0xFF);
1185 public long get(String name, long defvalue)
1186 throws IOException, IllegalArgumentException
1188 ObjectStreamField field = getField(name, Long.TYPE);
1190 if (field == null)
1191 return defvalue;
1193 int off = field.getOffset();
1195 return (long)(((prim_field_data[off++] & 0xFF) << 56)
1196 | ((prim_field_data[off++] & 0xFF) << 48)
1197 | ((prim_field_data[off++] & 0xFF) << 40)
1198 | ((prim_field_data[off++] & 0xFF) << 32)
1199 | ((prim_field_data[off++] & 0xFF) << 24)
1200 | ((prim_field_data[off++] & 0xFF) << 16)
1201 | ((prim_field_data[off++] & 0xFF) << 8)
1202 | (prim_field_data[off] & 0xFF));
1205 public float get(String name, float defvalue)
1206 throws IOException, IllegalArgumentException
1208 ObjectStreamField field = getField(name, Float.TYPE);
1210 if (field == null)
1211 return defvalue;
1213 int off = field.getOffset();
1215 return Float.intBitsToFloat(((prim_field_data[off++] & 0xFF) << 24)
1216 | ((prim_field_data[off++] & 0xFF) << 16)
1217 | ((prim_field_data[off++] & 0xFF) << 8)
1218 | (prim_field_data[off] & 0xFF));
1221 public double get(String name, double defvalue)
1222 throws IOException, IllegalArgumentException
1224 ObjectStreamField field = getField(name, Double.TYPE);
1226 if (field == null)
1227 return defvalue;
1229 int off = field.getOffset();
1231 return Double.longBitsToDouble
1232 ( (long) (((prim_field_data[off++] & 0xFF) << 56)
1233 | ((prim_field_data[off++] & 0xFF) << 48)
1234 | ((prim_field_data[off++] & 0xFF) << 40)
1235 | ((prim_field_data[off++] & 0xFF) << 32)
1236 | ((prim_field_data[off++] & 0xFF) << 24)
1237 | ((prim_field_data[off++] & 0xFF) << 16)
1238 | ((prim_field_data[off++] & 0xFF) << 8)
1239 | (prim_field_data[off] & 0xFF)));
1242 public Object get(String name, Object defvalue)
1243 throws IOException, IllegalArgumentException
1245 ObjectStreamField field =
1246 getField(name, defvalue == null ? null : defvalue.getClass ());
1248 if (field == null)
1249 return defvalue;
1251 return objs[field.getOffset()];
1254 private ObjectStreamField getField(String name, Class type)
1255 throws IllegalArgumentException
1257 ObjectStreamField field = clazz.getField(name);
1258 boolean illegal = false;
1264 Class field_type = field.getType();
1266 if (type == field_type ||
1267 (type == null && !field_type.isPrimitive()))
1269 /* See defaulted */
1270 return field;
1273 illegal = true;
1274 throw new IllegalArgumentException
1275 ("Field requested is of type "
1276 + field_type.getName()
1277 + ", but requested type was "
1278 + (type == null ? "Object" : type.getName()));
1280 catch (NullPointerException _)
1282 /* Here we catch NullPointerException, because it may
1283 only come from the call 'field.getType()'. If field
1284 is null, we have to return null and classpath ethic
1285 say we must try to avoid 'if (xxx == null)'.
1288 catch (IllegalArgumentException e)
1290 throw e;
1293 return null;
1295 finally
1297 /* If this is an unassigned field we should return
1298 * the default value.
1300 if (!illegal && field != null && !field.isToSet() && field.isPersistent())
1301 return null;
1303 /* We do not want to modify transient fields. They should
1304 * be left to 0.
1308 Field f = clazz.forClass().getDeclaredField(name);
1309 if (Modifier.isTransient(f.getModifiers()))
1310 throw new IllegalArgumentException
1311 ("no such field (non transient) " + name);
1312 if (field == null && f.getType() != type)
1313 throw new IllegalArgumentException
1314 ("Invalid requested type for field " + name);
1316 catch (NoSuchFieldException e)
1318 if (field == null)
1319 throw new IllegalArgumentException(e.getMessage());
1326 fieldsAlreadyRead = true;
1327 return prereadFields;
1331 * Protected constructor that allows subclasses to override
1332 * deserialization. This constructor should be called by subclasses
1333 * that wish to override <code>readObject (Object)</code>. This
1334 * method does a security check <i>NOTE: currently not
1335 * implemented</i>, then sets a flag that informs
1336 * <code>readObject (Object)</code> to call the subclasses
1337 * <code>readObjectOverride (Object)</code> method.
1339 * @see #readObjectOverride()
1341 protected ObjectInputStream()
1342 throws IOException, SecurityException
1344 SecurityManager sec_man = System.getSecurityManager();
1345 if (sec_man != null)
1346 sec_man.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
1347 this.useSubclassMethod = true;
1351 * This method allows subclasses to override the default
1352 * de serialization mechanism provided by
1353 * <code>ObjectInputStream</code>. To make this method be used for
1354 * writing objects, subclasses must invoke the 0-argument
1355 * constructor on this class from their constructor.
1357 * @see #ObjectInputStream()
1359 protected Object readObjectOverride()
1360 throws ClassNotFoundException, IOException, OptionalDataException
1362 throw new IOException("Subclass of ObjectInputStream must implement readObjectOverride");
1366 * Assigns the next available handle to <code>obj</code>.
1368 * @param obj The object for which we want a new handle.
1369 * @return A valid handle for the specified object.
1371 private int assignNewHandle(Object obj)
1373 this.objectLookupTable.put(new Integer(this.nextOID),
1374 new ObjectIdentityWrapper(obj));
1375 return this.nextOID++;
1378 private Object processResolution(Object obj, int handle)
1379 throws IOException
1381 if (obj instanceof Serializable)
1383 Method m = null;
1386 Class classArgs[] = {};
1387 m = getMethod(obj.getClass(), "readResolve", classArgs);
1388 obj = m.invoke(obj, new Object[] {});
1390 catch (NoSuchMethodException ignore)
1393 catch (IllegalAccessException ignore)
1396 catch (InvocationTargetException ignore)
1401 if (this.resolveEnabled)
1402 obj = resolveObject(obj);
1404 this.objectLookupTable.put(new Integer(handle),
1405 new ObjectIdentityWrapper(obj));
1407 return obj;
1410 private void clearHandles()
1412 this.objectLookupTable.clear();
1413 this.nextOID = baseWireHandle;
1416 private void readNextBlock() throws IOException
1418 readNextBlock(this.realInputStream.readByte());
1421 private void readNextBlock(byte marker) throws IOException
1423 if (marker == TC_BLOCKDATA)
1425 dumpElement("BLOCK DATA SIZE=");
1426 this.blockDataBytes = this.realInputStream.readUnsignedByte();
1427 dumpElementln (Integer.toString(this.blockDataBytes));
1429 else if (marker == TC_BLOCKDATALONG)
1431 dumpElement("BLOCK DATA LONG SIZE=");
1432 this.blockDataBytes = this.realInputStream.readInt();
1433 dumpElementln (Integer.toString(this.blockDataBytes));
1435 else
1437 throw new EOFException("Attempt to read primitive data, but no data block is active.");
1440 if (this.blockData.length < this.blockDataBytes)
1441 this.blockData = new byte[this.blockDataBytes];
1443 this.realInputStream.readFully (this.blockData, 0, this.blockDataBytes);
1444 this.blockDataPosition = 0;
1447 private void readArrayElements (Object array, Class clazz)
1448 throws ClassNotFoundException, IOException
1450 if (clazz.isPrimitive())
1452 if (clazz == Boolean.TYPE)
1454 boolean[] cast_array = (boolean[])array;
1455 for (int i=0; i < cast_array.length; i++)
1456 cast_array[i] = this.realInputStream.readBoolean();
1457 return;
1459 if (clazz == Byte.TYPE)
1461 byte[] cast_array = (byte[])array;
1462 for (int i=0; i < cast_array.length; i++)
1463 cast_array[i] = this.realInputStream.readByte();
1464 return;
1466 if (clazz == Character.TYPE)
1468 char[] cast_array = (char[])array;
1469 for (int i=0; i < cast_array.length; i++)
1470 cast_array[i] = this.realInputStream.readChar();
1471 return;
1473 if (clazz == Double.TYPE)
1475 double[] cast_array = (double[])array;
1476 for (int i=0; i < cast_array.length; i++)
1477 cast_array[i] = this.realInputStream.readDouble();
1478 return;
1480 if (clazz == Float.TYPE)
1482 float[] cast_array = (float[])array;
1483 for (int i=0; i < cast_array.length; i++)
1484 cast_array[i] = this.realInputStream.readFloat();
1485 return;
1487 if (clazz == Integer.TYPE)
1489 int[] cast_array = (int[])array;
1490 for (int i=0; i < cast_array.length; i++)
1491 cast_array[i] = this.realInputStream.readInt();
1492 return;
1494 if (clazz == Long.TYPE)
1496 long[] cast_array = (long[])array;
1497 for (int i=0; i < cast_array.length; i++)
1498 cast_array[i] = this.realInputStream.readLong();
1499 return;
1501 if (clazz == Short.TYPE)
1503 short[] cast_array = (short[])array;
1504 for (int i=0; i < cast_array.length; i++)
1505 cast_array[i] = this.realInputStream.readShort();
1506 return;
1509 else
1511 Object[] cast_array = (Object[])array;
1512 for (int i=0; i < cast_array.length; i++)
1513 cast_array[i] = readObject();
1517 private void readFields (Object obj, ObjectStreamClass stream_osc)
1518 throws ClassNotFoundException, IOException
1520 ObjectStreamField[] stream_fields = stream_osc.fields;
1521 ObjectStreamField[] real_fields =
1522 lookupClass(stream_osc.forClass()).fields;
1524 boolean default_initialize, set_value;
1525 String field_name = null;
1526 Class type = null;
1527 ObjectStreamField stream_field = null;
1528 ObjectStreamField real_field = null;
1529 int stream_idx = 0;
1530 int real_idx = 0;
1532 while (stream_idx < stream_fields.length
1533 && real_idx < real_fields.length)
1535 default_initialize = false;
1536 set_value = true;
1538 if (stream_idx == stream_fields.length)
1539 default_initialize = true;
1540 else
1542 stream_field = stream_fields[stream_idx];
1543 type = stream_field.getType();
1546 if (real_idx == real_fields.length)
1547 set_value = false;
1548 else
1550 real_field = real_fields[real_idx];
1551 type = real_field.getType();
1552 field_name = real_field.getName();
1555 if (set_value && !default_initialize)
1557 int comp_val =
1558 real_field.compareTo (stream_field);
1560 if (comp_val < 0)
1562 default_initialize = true;
1563 real_idx++;
1565 else if (comp_val > 0)
1567 set_value = false;
1568 stream_idx++;
1570 else
1572 real_idx++;
1573 stream_idx++;
1577 if (stream_field.getOffset() < 0)
1579 default_initialize = true;
1580 set_value = false;
1583 if (!stream_field.isToSet())
1584 set_value = false;
1588 if (type == Boolean.TYPE)
1590 boolean value =
1591 default_initialize ? false : this.realInputStream.readBoolean();
1592 if (!default_initialize && set_value)
1593 dumpElementln(" " + field_name + ": " + value);
1594 if (set_value)
1595 setBooleanField(obj, stream_osc.forClass(), field_name, value);
1597 else if (type == Byte.TYPE)
1599 byte value =
1600 default_initialize ? 0 : this.realInputStream.readByte();
1601 if (!default_initialize && set_value)
1602 dumpElementln(" " + field_name + ": " + value);
1603 if (set_value)
1604 setByteField(obj, stream_osc.forClass(), field_name, value);
1606 else if (type == Character.TYPE)
1608 char value =
1609 default_initialize ? (char)0 : this.realInputStream.readChar();
1610 if (!default_initialize && set_value)
1611 dumpElementln(" " + field_name + ": " + value);
1612 if (set_value)
1613 setCharField(obj, stream_osc.forClass(), field_name, value);
1615 else if (type == Double.TYPE)
1617 double value =
1618 default_initialize ? 0 : this.realInputStream.readDouble();
1619 if (!default_initialize && set_value)
1620 dumpElementln(" " + field_name + ": " + value);
1621 if (set_value)
1622 setDoubleField(obj, stream_osc.forClass(), field_name, value);
1624 else if (type == Float.TYPE)
1626 float value =
1627 default_initialize ? 0 : this.realInputStream.readFloat();
1628 if (!default_initialize && set_value)
1629 dumpElementln(" " + field_name + ": " + value);
1630 if (set_value)
1631 setFloatField(obj, stream_osc.forClass(), field_name, value);
1633 else if (type == Integer.TYPE)
1635 int value =
1636 default_initialize ? 0 : this.realInputStream.readInt();
1637 if (!default_initialize && set_value)
1638 dumpElementln(" " + field_name + ": " + value);
1639 if (set_value)
1640 setIntField(obj, stream_osc.forClass(), field_name, value);
1642 else if (type == Long.TYPE)
1644 long value =
1645 default_initialize ? 0 : this.realInputStream.readLong();
1646 if (!default_initialize && set_value)
1647 dumpElementln(" " + field_name + ": " + value);
1648 if (set_value)
1649 setLongField(obj, stream_osc.forClass(), field_name, value);
1651 else if (type == Short.TYPE)
1653 short value =
1654 default_initialize ? (short)0 : this.realInputStream.readShort();
1655 if (!default_initialize && set_value)
1656 dumpElementln(" " + field_name + ": " + value);
1657 if (set_value)
1658 setShortField(obj, stream_osc.forClass(), field_name, value);
1660 else
1662 Object value =
1663 default_initialize ? null : readObject();
1664 if (set_value)
1665 setObjectField(obj, stream_osc.forClass(), field_name,
1666 real_field.getTypeString(), value);
1669 catch (NoSuchFieldError e)
1671 dumpElementln("XXXX " + field_name + " does not exist.");
1676 // Toggles writing primitive data to block-data buffer.
1677 private boolean setBlockDataMode (boolean on)
1679 boolean oldmode = this.readDataFromBlock;
1680 this.readDataFromBlock = on;
1682 if (on)
1683 this.dataInputStream = this.blockDataInput;
1684 else
1685 this.dataInputStream = this.realInputStream;
1686 return oldmode;
1689 // returns a new instance of REAL_CLASS that has been constructed
1690 // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
1691 private Object newObject (Class real_class, Class constructor_class)
1695 Object obj = allocateObject (real_class);
1696 callConstructor (constructor_class, obj);
1697 return obj;
1699 catch (InstantiationException e)
1701 return null;
1705 // runs all registered ObjectInputValidations in prioritized order
1706 // on OBJ
1707 private void invokeValidators() throws InvalidObjectException
1709 Object[] validators = new Object[this.validators.size()];
1710 this.validators.copyInto (validators);
1711 Arrays.sort (validators);
1715 for (int i=0; i < validators.length; i++)
1716 ((ObjectInputValidation)validators[i]).validateObject();
1718 finally
1720 this.validators.removeAllElements();
1725 * This native method is used to get access to the protected method
1726 * of the same name in SecurityManger.
1728 * @param sm SecurityManager instance which should be called.
1729 * @return The current class loader in the calling stack.
1731 private static ClassLoader currentClassLoader (SecurityManager sm)
1733 // FIXME: This is too simple.
1734 return ClassLoader.getSystemClassLoader ();
1738 * This method tries to access a precise field called in the
1739 * specified class. Before accessing the field, it tries to
1740 * gain control on this field. If the field is either declared as
1741 * not persistent or transient then it returns null
1742 * immediately.
1744 * @param klass Class to get the field from.
1745 * @param name Name of the field to access.
1746 * @return Field instance representing the requested field.
1747 * @throws NoSuchFieldException if the field does not exist.
1749 private Field getField(Class klass, String name)
1750 throws java.lang.NoSuchFieldException
1752 final Field f = klass.getDeclaredField(name);
1753 ObjectStreamField sf = lookupClass(klass).getField(name);
1755 AccessController.doPrivileged(new PrivilegedAction()
1757 public Object run()
1759 f.setAccessible(true);
1760 return null;
1764 /* We do not want to modify transient fields. They should
1765 * be left to 0.
1766 * N.B.: Not valid if the field is in serialPersistentFields.
1768 if (Modifier.isTransient(f.getModifiers()) && !sf.isPersistent())
1769 return null;
1771 return f;
1774 private static Method getMethod (Class klass, String name, Class args[])
1775 throws java.lang.NoSuchMethodException
1777 final Method m = klass.getDeclaredMethod(name, args);
1778 AccessController.doPrivileged(new PrivilegedAction()
1780 public Object run()
1782 m.setAccessible(true);
1783 return null;
1786 return m;
1789 private void callReadMethod (Object obj, ObjectStreamClass osc) throws IOException
1791 Class klass = osc.forClass();
1794 Class classArgs[] = {ObjectInputStream.class};
1795 Method m = getMethod (klass, "readObject", classArgs);
1796 Object args[] = {this};
1797 m.invoke(obj, args);
1799 catch (NoSuchMethodException nsme)
1801 // Nothing.
1803 catch (InvocationTargetException x)
1805 /* Rethrow if possible. */
1806 Throwable exception = x.getTargetException();
1807 if (exception instanceof RuntimeException)
1808 throw (RuntimeException) exception;
1809 if (exception instanceof IOException)
1810 throw (IOException) exception;
1812 throw new IOException("Exception thrown from readObject() on " +
1813 klass + ": " + exception.getClass().getName());
1815 catch (Exception x)
1817 throw new IOException("Failure invoking readObject() on " +
1818 klass + ": " + x.getClass().getName());
1821 // Invalidate fields which has been read through readFields.
1822 prereadFields = null;
1825 private native Object allocateObject (Class clazz)
1826 throws InstantiationException;
1828 private native void callConstructor (Class clazz, Object obj);
1831 * This method writes a "boolean" value <code>val</code> in the specified field
1832 * of the instance <code>obj</code> of the type <code>klass</code>.
1834 * @param obj Instance to setup.
1835 * @param klass Class type of the specified instance.
1836 * @param field_name Name of the field in the specified class type.
1837 * @param val The boolean value to write into the field.
1838 * @throws InvalidClassException if the specified field has not the required type.
1839 * @throws IOException if there is no field of that name in the specified class.
1841 private void setBooleanField(Object obj, Class klass, String field_name,
1842 boolean val) throws IOException, InvalidClassException
1846 Field f = getField(klass, field_name);
1847 f.setBoolean(obj, val);
1849 catch (IllegalArgumentException _)
1851 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
1853 catch (Exception _)
1859 * This method writes a "byte" value <code>val</code> in the specified field
1860 * of the instance <code>obj</code> of the type <code>klass</code>.
1862 * @param obj Instance to setup.
1863 * @param klass Class type of the specified instance.
1864 * @param field_name Name of the field in the specified class type.
1865 * @param val The byte value to write into the field.
1866 * @throws InvalidClassException if the specified field has not the required type.
1867 * @throws IOException if there is no field of that name in the specified class.
1869 private void setByteField(Object obj, Class klass, String field_name,
1870 byte val) throws IOException, InvalidClassException
1874 Field f = getField(klass, field_name);
1875 f.setByte(obj, val);
1877 catch (IllegalArgumentException _)
1879 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
1881 catch (Exception _)
1887 * This method writes a "character" value <code>val</code> in the specified field
1888 * of the instance <code>obj</code> of the type <code>klass</code>.
1890 * @param obj Instance to setup.
1891 * @param klass Class type of the specified instance.
1892 * @param field_name Name of the field in the specified class type.
1893 * @param val The character value to write into the field.
1894 * @throws InvalidClassException if the specified field has not the required type.
1895 * @throws IOException if there is no field of that name in the specified class.
1897 private void setCharField(Object obj, Class klass, String field_name,
1898 char val) throws IOException, InvalidClassException
1902 Field f = getField(klass, field_name);
1903 f.setChar(obj, val);
1905 catch (IllegalArgumentException _)
1907 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
1909 catch (Exception _)
1915 * This method writes a "double" value <code>val</code> in the specified field
1916 * of the instance <code>obj</code> of the type <code>klass</code>.
1918 * @param obj Instance to setup.
1919 * @param klass Class type of the specified instance.
1920 * @param field_name Name of the field in the specified class type.
1921 * @param val The double value to write into the field.
1922 * @throws InvalidClassException if the specified field has not the required type.
1923 * @throws IOException if there is no field of that name in the specified class.
1925 private void setDoubleField(Object obj, Class klass, String field_name,
1926 double val) throws IOException, InvalidClassException
1930 Field f = getField(klass, field_name);
1931 f.setDouble(obj, val);
1933 catch (IllegalArgumentException _)
1935 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
1937 catch (Exception _)
1943 * This method writes a "float" value <code>val</code> in the specified field
1944 * of the instance <code>obj</code> of the type <code>klass</code>.
1946 * @param obj Instance to setup.
1947 * @param klass Class type of the specified instance.
1948 * @param field_name Name of the field in the specified class type.
1949 * @param val The float value to write into the field.
1950 * @throws InvalidClassException if the specified field has not the required type.
1951 * @throws IOException if there is no field of that name in the specified class.
1953 private void setFloatField(Object obj, Class klass, String field_name,
1954 float val) throws IOException, InvalidClassException
1958 Field f = getField(klass, field_name);
1959 f.setFloat(obj, val);
1961 catch (IllegalArgumentException _)
1963 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
1965 catch (Exception _)
1971 * This method writes an "integer" value <code>val</code> in the specified field
1972 * of the instance <code>obj</code> of the type <code>klass</code>.
1974 * @param obj Instance to setup.
1975 * @param klass Class type of the specified instance.
1976 * @param field_name Name of the field in the specified class type.
1977 * @param val The integer value to write into the field.
1978 * @throws InvalidClassException if the specified field has not the required type.
1979 * @throws IOException if there is no field of that name in the specified class.
1981 private void setIntField(Object obj, Class klass, String field_name,
1982 int val) throws IOException, InvalidClassException
1986 Field f = getField(klass, field_name);
1987 f.setInt(obj, val);
1989 catch (IllegalArgumentException _)
1991 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
1993 catch (Exception _)
1999 * This method writes the long value <code>val</code> in the specified field
2000 * of the instance <code>obj</code> of the type <code>klass</code>.
2002 * @param obj Instance to setup.
2003 * @param klass Class type of the specified instance.
2004 * @param field_name Name of the field in the specified class type.
2005 * @param val The long value to write into the field.
2006 * @throws InvalidClassException if the specified field has not the required type.
2007 * @throws IOException if there is no field of that name in the specified class.
2009 private void setLongField(Object obj, Class klass, String field_name,
2010 long val) throws IOException, InvalidClassException
2014 Field f = getField(klass, field_name);
2015 f.setLong(obj, val);
2017 catch (IllegalArgumentException _)
2019 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
2021 catch (Exception _)
2027 * This method writes a "short" value <code>val</code> in the specified field
2028 * of the instance <code>obj</code> of the type <code>klass</code>.
2030 * @param obj Instance to setup.
2031 * @param klass Class type of the specified instance.
2032 * @param field_name Name of the field in the specified class type.
2033 * @param val The short value to write into the field.
2034 * @throws InvalidClassException if the specified field has not the required type.
2035 * @throws IOException if there is no field of that name in the specified class.
2037 private void setShortField(Object obj, Class klass, String field_name,
2038 short val) throws IOException, InvalidClassException
2042 Field f = getField(klass, field_name);
2043 f.setShort(obj, val);
2045 catch (IllegalArgumentException _)
2047 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
2049 catch (Exception _)
2055 * This method writes an "object" value <code>val</code> in the specified field
2056 * of the instance <code>obj</code> of the type <code>klass</code>.
2058 * @param obj Instance to setup.
2059 * @param klass Class type of the specified instance.
2060 * @param field_name Name of the field in the specified class type.
2061 * @param val The "object" value to write into the field.
2062 * @throws InvalidClassException if the specified field has not the required type.
2063 * @throws IOException if there is no field of that name in the specified class.
2065 private void setObjectField(Object obj, Class klass, String field_name,
2066 String type_code, Object val) throws IOException, InvalidClassException
2070 Field f = getField(klass, field_name);
2071 ObjectStreamField of = new ObjectStreamField(field_name, f.getType());
2073 if (of.getTypeString() == null ||
2074 !of.getTypeString().equals(type_code))
2075 throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
2076 f.set(obj, val);
2078 catch (InvalidClassException e)
2080 throw e;
2082 catch (Exception _)
2087 private static final int BUFFER_SIZE = 1024;
2088 private static final Class[] readObjectParams = { ObjectInputStream.class };
2090 private DataInputStream realInputStream;
2091 private DataInputStream dataInputStream;
2092 private DataInputStream blockDataInput;
2093 private int blockDataPosition;
2094 private int blockDataBytes;
2095 private byte[] blockData;
2096 private boolean useSubclassMethod;
2097 private int nextOID;
2098 private boolean resolveEnabled;
2099 private Hashtable objectLookupTable;
2100 private Object currentObject;
2101 private ObjectStreamClass currentObjectStreamClass;
2102 private boolean readDataFromBlock;
2103 private boolean isDeserializing;
2104 private boolean fieldsAlreadyRead;
2105 private Vector validators;
2106 private Hashtable classLookupTable;
2107 private GetField prereadFields;
2109 private static boolean dump;
2111 private void dumpElement (String msg)
2113 if (Configuration.DEBUG && dump)
2114 System.out.print(msg);
2117 private void dumpElementln (String msg)
2119 if (Configuration.DEBUG && dump)
2120 System.out.println(msg);
2123 static
2125 if (Configuration.INIT_LOAD_LIBRARY)
2127 System.loadLibrary ("javaio");
2133 // used to keep a prioritized list of object validators
2134 class ValidatorAndPriority implements Comparable
2136 int priority;
2137 ObjectInputValidation validator;
2139 ValidatorAndPriority (ObjectInputValidation validator, int priority)
2141 this.priority = priority;
2142 this.validator = validator;
2145 public int compareTo (Object o)
2147 ValidatorAndPriority vap = (ValidatorAndPriority)o;
2148 return this.priority - vap.priority;