home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Internet / Javadraw / DATA.Z / ObjectInputStream.java < prev    next >
Text File  |  1997-08-30  |  53KB  |  1,569 lines

  1. /*
  2.  * @(#)ObjectInputStream.java    1.30 97/05/02
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  */
  21.  
  22. package java.io;
  23.  
  24. import java.util.Vector;
  25. import java.util.Stack;
  26. import java.util.Hashtable;
  27.  
  28. /**
  29.  * An ObjectInputStream deserializes primitive data and objects previously
  30.  * written using an ObjectOutputStream.
  31.  * 
  32.  * ObjectOutputStream and ObjectInputStream can provide an application
  33.  * with persistent storage for graphs of objects when used with a
  34.  * FileOutputStream and FileInputStream respectively.
  35.  * ObjectInputStream is used to recover those objects previously
  36.  * serialized. Other uses include passing objects between hosts using
  37.  * a socket stream or for marshaling and unmarshaling arguments and
  38.  * parameters in a remote communication system.<p>
  39.  *
  40.  * ObjectInputStream ensures that the types of all objects in the
  41.  * graph created from the stream match the classes present in the
  42.  * Java Virtual Machine.  Classes are loaded as required using the
  43.  * standard mechanisms. <p>
  44.  *
  45.  * Only objects that support the java.io.Serializable or
  46.  * java.io.Externalizable interface can be read from streams.
  47.  *
  48.  * The method <STRONG>readObject</STRONG> is used to read an object
  49.  * from the stream.  Java's safe casting should be used to get the
  50.  * desired type.  In Java, strings and arrays are objects and are
  51.  * treated as objects during serialization. When read they need to be
  52.  * cast to the expected type.<p>
  53.  *
  54.  * Primitive data types can be read from the stream using the appropriate
  55.  * method on DataInput. <p>
  56.  * 
  57.  * The default deserialization mechanism for objects restores the
  58.  * contents of each field to the value and type it had when it was written.
  59.  * Fields declared as transient or static are ignored by the
  60.  * deserialization process.  References to other objects cause those
  61.  * objects to be read from the stream as necessary.  Graphs of objects
  62.  * are restored correctly using a reference sharing mechanism.  New
  63.  * objects are always allocated when deserializing, which prevents
  64.  * existing objects from being overwritten. <p>
  65.  *
  66.  * Reading an object is analogous to running the constructors of a new
  67.  * object.  Memory is allocated for the object and initialized to zero
  68.  * (NULL).  No-arg constructors are invoked for the non-serializable
  69.  * classes and then the fields of the serializable classes are
  70.  * restored from the stream starting with the serializable class closest to
  71.  * java.lang.object and finishing with the object's most specifiec
  72.  * class. <p>
  73.  *
  74.  * For example to read from a stream as written by the example in
  75.  * ObjectOutputStream: <br>
  76.  *
  77.  * <PRE>
  78.  *    FileInputStream istream = new FileInputStream("t.tmp");
  79.  *    ObjectInputStream p = new ObjectInputStream(istream);
  80.  *
  81.  *    int i = p.readInt();
  82.  *    String today = (String)p.readObject();
  83.  *    Date date = (Date)p.readObject();
  84.  *
  85.  *    istream.close();
  86.  * </PRE>
  87.  *
  88.  * Classes control how they are serialized by implementing either the
  89.  * java.io.Serializable or java.io.Externalizable interfaces.<P>
  90.  *
  91.  * Implementing the Serializable interface allows object serialization
  92.  * to save and restore the entire state of the object and it allows
  93.  * classes to evolve between the time the stream is written and the time it is
  94.  * read.  It automatically traverses references between objects,
  95.  * saving and restoring entire graphs.
  96.  *
  97.  * Serializable classes that require special handling during the
  98.  * serialization and deserialization process should implement both
  99.  * of these methods:<p>
  100.  *
  101.  * <PRE>
  102.  * private void writeObject(java.io.ObjectOutputStream stream)
  103.  *     throws IOException;
  104.  * private void readObject(java.io.ObjectInputStream stream)
  105.  *     throws IOException, ClassNotFoundException; 
  106.  * </PRE><p>
  107.  *
  108.  * The readObject method is responsible for reading and restoring the
  109.  * state of the object for its particular class using data written to
  110.  * the stream by the corresponding writeObject method.  The method
  111.  * does not need to concern itself with the state belonging to its
  112.  * superclasses or subclasses.  State is restored by reading data from
  113.  * the ObjectInputStream for the individual fields and making
  114.  * assignments to the appropriate fields of the object.  Reading
  115.  * primitive data types is supported by DataInput. <p>
  116.  *
  117.  * Serialization does not read or assign values to the fields of any
  118.  * object that does not implement the java.io.Serializable interface.
  119.  * Subclasses of Objects that are not serializable can be
  120.  * serializable. In this case the non-serializable class must have a
  121.  * no-arg constructor to allow its fields to be initialized.  In this
  122.  * case it is the responsibility of the subclass to save and restore
  123.  * the state of the non-serializable class. It is frequently the case that
  124.  * the fields of that class are accessible (public, package, or
  125.  * protected) or that there are get and set methods that can be used
  126.  * to restore the state. <p>
  127.  *
  128.  * Any exception that occurs while deserializing an object will be
  129.  * caught by the ObjectInputStream and abort the reading process. <p>
  130.  *
  131.  * Implementing the Externalizable interface allows the object to
  132.  * assume complete control over the contents and format of the object's
  133.  * serialized form.  The methods of the Externalizable interface,
  134.  * writeExternal and readExternal, are called to save and restore the
  135.  * objects state.  When implemented by a class they can write and read
  136.  * their own state using all of the methods of ObjectOutput and
  137.  * ObjectInput.  It is the responsibility of the objects to handle any
  138.  * versioning that occurs.
  139.  *
  140.  * @author  Roger Riggs
  141.  * @version 1.30, 05/02/97
  142.  * @see java.io.DataInput
  143.  * @see java.io.ObjectOutputStream
  144.  * @see java.io.Serializable
  145.  * @since   JDK1.1
  146.  */
  147. public class ObjectInputStream extends InputStream
  148.     implements ObjectInput, ObjectStreamConstants
  149.     /**
  150.      * Create an ObjectInputStream that reads from the specified InputStream.
  151.      * The stream header containing the magic number and version number
  152.      * are read from the stream and verified. This method will block
  153.      * until the corresponding ObjectOutputStream has written and flushed the header.
  154.      * @exception StreamCorruptedException The version or magic number are incorrect.
  155.      * @exception IOException An exception occurred in the underlying stream.
  156.      * @since     JDK1.1
  157.      */
  158.     public ObjectInputStream(InputStream in)
  159.     throws IOException, StreamCorruptedException
  160.   {
  161.       /*
  162.        * Save the input stream to read bytes from
  163.        * Create a DataInputStream used to read primitive types.
  164.        * Setup the DataInputStream to read from this ObjectInputStream
  165.        */
  166.     this.in = in;
  167.     dis  = new DataInputStream(this); 
  168.     readStreamHeader();
  169.     resetStream();
  170.     }
  171.  
  172.     /**
  173.      * Read an object from the ObjectInputStream.
  174.      * The class of the object, the signature of the class, and the values
  175.      * of the non-transient and non-static fields of the class and all
  176.      * of its supertypes are read.  Default deserializing for a class can be
  177.      * overriden using the writeObject and readObject methods.
  178.      * Objects referenced by this object are read transitively so
  179.      * that a complete equivalent graph of objects is reconstructed by readObject. <p>
  180.      *
  181.      * The root object is completly restored when all of its fields
  182.      * and the objects it references are completely restored.  At this
  183.      * point the object validation callbacks are executed in order
  184.      * based on their registered priorities. The callbacks are
  185.      * registered by objects (in the readObject special methods)
  186.      * as they are individually restored.
  187.      *
  188.      * Exceptions are thrown for problems with the InputStream and for classes
  189.      * that should not be deserialized.  All exceptions are fatal to the 
  190.      * InputStream and leave it in an indeterminate state; it is up to the caller
  191.      * to ignore or recover the stream state.
  192.      * @exception java.lang.ClassNotFoundException Class of a serialized object
  193.      *      cannot be found.
  194.      * @exception InvalidClassException Something is wrong with a class used by
  195.      *     serialization.
  196.      * @exception StreamCorruptedException Control information in the
  197.      *     stream is inconsistent.
  198.      * @exception OptionalDataException Primitive data was found in the 
  199.      * stream instead of objects.
  200.      * @exception IOException Any of the usual Input/Output related exceptions.
  201.      * @since     JDK1.1
  202.      */
  203.     public final Object readObject()
  204.     throws OptionalDataException, ClassNotFoundException, IOException
  205.     {
  206.     /* If the stream is in blockData mode and there's any data
  207.      * left throw an exception to report how much there is.
  208.      */
  209.     int n;
  210.     if (blockDataMode && (n = available()) > 0) {
  211.         throw new OptionalDataException(n);
  212.     }
  213.     
  214.     /*
  215.      * Look ahead now to absorb any pending reset's.
  216.      * Before changing the state.
  217.      */
  218.     peekCode();
  219.  
  220.     /* Save the current state and get ready to read an object. */
  221.     Object prevObject = currentObject;
  222.     ObjectStreamClass prevClass = currentClassDesc;
  223.     boolean prevBlockDataMode = setBlockData(false);
  224.     
  225.     recursionDepth++;    // Entering
  226.     Object obj = null;
  227.  
  228.     /* 
  229.      * Check for reset, handle it before reading an object.
  230.      */
  231.  
  232.     byte rcode;
  233.     rcode = readCode();
  234.     try {
  235.         /*
  236.          * Dispatch on the next code in the stream.
  237.          */
  238.         int wireoffset = -1;
  239.  
  240.         switch (rcode) {
  241.         
  242.         case TC_NULL:
  243.         obj = null;
  244.         break;
  245.         
  246.         case TC_REFERENCE: 
  247.         /* This is a reference to a pre-existing object */
  248.         wireoffset = readInt() - baseWireHandle; 
  249.         
  250.         try {
  251.             obj = wireHandle2Object.elementAt(wireoffset);
  252.         } catch (ArrayIndexOutOfBoundsException e) {
  253.             throw new StreamCorruptedException("Reference to object never serialized.");
  254.         }
  255.         break;
  256.         
  257.         case TC_STRING:
  258.         obj = readUTF(); 
  259.         assignWireOffset(obj);
  260.         break;
  261.         
  262.         case TC_CLASS:
  263.         ObjectStreamClass v = (ObjectStreamClass)readObject();
  264.         if (v == null) {
  265.             /*
  266.              * No class descriptor in stream or class not serializable
  267.              */
  268.             throw new StreamCorruptedException("Class not in stream");
  269.         }
  270.         obj = v.forClass();
  271.         assignWireOffset(obj);
  272.         break;
  273.         
  274.         case TC_CLASSDESC:
  275.         obj = inputClassDescriptor();
  276.         break;
  277.         
  278.         case TC_ARRAY:
  279.         obj = inputArray();
  280.         break;
  281.         
  282.         case TC_OBJECT:
  283.         wireoffset = inputObject();
  284.         obj = currentObject;
  285.         if (enableResolve) {
  286.             /* Hook for alternate object */
  287.             obj = resolveObject(obj);
  288.             wireHandle2Object.setElementAt(obj, wireoffset);
  289.         }
  290.         break;
  291.         
  292.         case TC_ENDBLOCKDATA:
  293.         if (!prevBlockDataMode)
  294.             throw new StreamCorruptedException("Unexpected end of block data");
  295.         pushbackCode(TC_ENDBLOCKDATA);
  296.         count = -1;    /* Flag EOF */ 
  297.         throw new OptionalDataException(true);
  298.         
  299.         case TC_BLOCKDATA:
  300.         case TC_BLOCKDATALONG:
  301.         if (rcode == TC_BLOCKDATALONG) { /* long block: 32 bit size */
  302.             int b3 = in.read();
  303.             int b2 = in.read();
  304.             int b1 = in.read();
  305.             int b0 = in.read();
  306.             if ((b3 | b2 | b1 | b0) < 0)
  307.             throw new StreamCorruptedException("EOF expecting count");
  308.             count = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
  309.             if (count < 0)
  310.             throw new StreamCorruptedException("Negative block data size");
  311.         } else {            /* normal block: 8 bit size */
  312.             count = in.read();
  313.             if (count < 0)
  314.             throw new StreamCorruptedException("EOF expecting count");
  315.         }
  316.  
  317.             if (!prevBlockDataMode)
  318.             throw new StreamCorruptedException("Unexpected blockdata");
  319.         
  320.         throw new OptionalDataException(count);
  321.         
  322.         case TC_EXCEPTION:
  323.         /* An exception happened during writing, reset the
  324.          * stream, read the exception, reset the stream and
  325.          * throw a writeAbortedException with the exception
  326.          * that was read.
  327.          */
  328.         resetStream();
  329.         IOException ee = (IOException)readObject();
  330.         resetStream();
  331.         throw new WriteAbortedException("Writing aborted by exception", ee);
  332.  
  333.         default:
  334.         throw new StreamCorruptedException("Unknown code in readObject " + rcode);
  335.         }
  336.     } catch (OptionalDataException optdata) {
  337.         /* OptionalDataExceptions won't terminate everything.
  338.          * so just rethrow it.
  339.          */
  340.         throw optdata;
  341.     } catch(IOException ee) {
  342.         if (abortIOException == null && abortClassNotFoundException == null)
  343.         abortIOException = ee;
  344.     } catch(ClassNotFoundException ee) {
  345.         if (abortIOException == null && abortClassNotFoundException == null)
  346.         abortClassNotFoundException = ee;
  347.     } finally {
  348.         recursionDepth --;
  349.         currentObject = prevObject;
  350.         currentClassDesc = prevClass;
  351.         setBlockData(prevBlockDataMode);
  352.     }
  353.     
  354.     /* Check for thrown exceptions and re-throw them, clearing them if
  355.      * this is the last recursive call .
  356.      */
  357.     IOException exIOE = abortIOException;
  358.     if (recursionDepth == 0)
  359.         abortIOException = null;
  360.     if (exIOE != null)
  361.         throw exIOE;
  362.  
  363.     
  364.     ClassNotFoundException exCNF = abortClassNotFoundException;
  365.     if (recursionDepth == 0)
  366.         abortClassNotFoundException = null;
  367.     if (exCNF != null) {
  368.         throw exCNF;
  369.     }
  370.     
  371.     // Check if this is the last nested read, if so
  372.     // Call the validations
  373.     if (recursionDepth == 0) {
  374.         doValidations();
  375.     }
  376.  
  377.     return obj;
  378.     }
  379.  
  380.     /**
  381.      * Read the non-static and non-transient fields of the current class
  382.      * from this stream.  This may only be called from the readObject method
  383.      * of the class being deserialized. It will throw the NotActiveException
  384.      * if it is called otherwise.
  385.      *
  386.      * @exception java.lang.ClassNotFoundException if the class of a serialized
  387.      *              object could not be found.
  388.      * @exception IOException        if an I/O error occurs.
  389.      * @exception NotActiveException if the stream is not currently reading
  390.      *              objects.
  391.      * @since     JDK1.1
  392.      */
  393.     public final void defaultReadObject()
  394.     throws IOException, ClassNotFoundException, NotActiveException
  395.     {
  396.     if (currentObject == null || currentClassDesc == null)
  397.         throw new NotActiveException("defaultReadObject");
  398.     
  399.  
  400.     if (currentClassDesc.getFieldSequence() != null) {
  401.         boolean prevmode = setBlockData(false);
  402.         inputClassFields(currentObject, currentClass,
  403.                  currentClassDesc.getFieldSequence());
  404.         setBlockData(prevmode);
  405.     }
  406.     }
  407.     
  408.     /**
  409.      * Register an object to be validated before the graph is
  410.      * returned.  While similar to resolveObject these validations are
  411.      * called after the entire graph has been reconstituted.
  412.      * Typically, a readObject method will register the object with
  413.      * the stream so that when all of the objects are restored a final
  414.      * set of validations can be performed.
  415.      * @param obj the object to receive the validation callback.
  416.      * @param prio controls the order of callbacks;zero is a good default.
  417.      * Use higher numbers to be called back earlier, lower numbers for later
  418.      * callbacks. Within a priority, callbacks are processed in no
  419.      * particular order.
  420.      *
  421.      * @exception NotActiveException The stream is not currently reading objects
  422.      * so it is invalid to register a callback.
  423.      * @exception InvalidObjectException The validation object is null.
  424.      * @since     JDK1.1
  425.      */
  426.     public synchronized void registerValidation(ObjectInputValidation obj,
  427.                         int prio)
  428.     throws NotActiveException, InvalidObjectException
  429.     {
  430.     if (recursionDepth == 0) {
  431.         throw new NotActiveException("readObject not Active");
  432.     }
  433.     if (obj == null) {
  434.         throw new InvalidObjectException("Null is not a valid callback object");
  435.     }
  436.  
  437.     ValidationCallback cb = new ValidationCallback(obj, prio);
  438.  
  439.     if (callbacks == null) {
  440.         callbacks = new Vector(100,100);
  441.     }
  442.     // insert at the end if the priority is less than or equal to
  443.     // the last element.
  444.     if (callbacks.isEmpty() ||
  445.         ((ValidationCallback)(callbacks.lastElement())).priority >= prio) {
  446.         callbacks.addElement(cb);
  447.         return;
  448.     }
  449.  
  450.     // search for the element with priority that is <= to the new
  451.     // priority, insert before it. 
  452.     int size = callbacks.size();
  453.     for (int i = 0; i < size; i++) {
  454.         ValidationCallback curr = (ValidationCallback)callbacks.elementAt(i);
  455.         if (curr.priority <= prio) {
  456.         callbacks.insertElementAt(cb, i);
  457.         break;
  458.         }
  459.     }
  460.     }
  461.  
  462.     /*
  463.      * If any validations are pending, do them and cleanup the validation vector
  464.      * if an exception is raised, it is passed on to abort the deserialization.
  465.      */
  466.     private void doValidations() throws InvalidObjectException {
  467.     if (callbacks == null)
  468.         return;
  469.     
  470.     int size = callbacks.size();
  471.     for (int i = 0; i < size; i++) {
  472.         ValidationCallback curr = (ValidationCallback)callbacks.elementAt(i);
  473.         curr.callback.validateObject();
  474.     }
  475.     }
  476.  
  477.     /**
  478.      * Subclasses may implement this method to allow classes to be
  479.      * fetched from an alternate source. 
  480.      *
  481.      * The corresponding method in ObjectOutputStream is
  482.      * annotateClass.  This method will be invoked only once for each
  483.      * unique class in the stream.  This method can be implemented by
  484.      * subclasses to use an alternate loading mechanism but must
  485.      * return a Class object.  Once returned, the serialVersionUID of the
  486.      * class is compared to the serialVersionUID of the serialized class.
  487.      * If there is a mismatch, the deserialization fails and an exception
  488.      * is raised. <p>
  489.      *
  490.      * By default the class name is resolved relative to the class
  491.      * that called readObject. <p>
  492.      *
  493.      * @exception ClassNotFoundException If class of
  494.      * a serialized object cannot be found.
  495.      * @since     JDK1.1
  496.      */
  497.     protected Class resolveClass(ObjectStreamClass v)
  498.     throws IOException, ClassNotFoundException
  499.     {
  500.     /* Resolve by looking up the stack for a non-zero class
  501.      * loader. If not found use the system loader.
  502.      */
  503.     return loadClass0(null, v.getName());
  504.     }
  505.  
  506.     /* Resolve a class name relative to the specified class.  If the
  507.      * class is null find the first available class loader up the
  508.      * stack.  This will resolve classes relative to the caller of
  509.      * ObjectInputStream instead of the itself. Classes must be
  510.      * loaded/resolved relative to the application.
  511.      */
  512.     private native Class loadClass0(Class cl, String classname)
  513.     throws ClassNotFoundException;
  514.  
  515.     /**
  516.      * This method will allow trusted subclasses of ObjectInputStream
  517.      * to substitute one object for another during
  518.      * deserialization. Replacing objects is disabled until
  519.      * enableResolveObject is called. The enableResolveObject method
  520.      * checks that the stream requesting to resolve object can be
  521.      * trusted. Every reference to serializable objects is passed to
  522.      * resolveObject.  To insure that the private state of objects is
  523.      * not unintentionally exposed only trusted streams may use
  524.      * resolveObject. <p>
  525.      *
  526.      * This method is called after an object has been read but before it is
  527.      * returned from readObject.  The default resolveObject method
  528.      * just returns the new object. <p>
  529.      *
  530.      * When a subclass is replacing objects it must insure that the
  531.      * substituted object is compatible with every field where the
  532.      * reference will be stored.  Objects whose type is not a subclass
  533.      * of the type of the field or array element abort the
  534.      * serialization by raising an exception and the object is not be
  535.      * stored. <p>
  536.      *
  537.      * This method is called only once when each object is first encountered.
  538.      * All subsequent references to the object will be redirected to the
  539.      * new object. <P>
  540.      *
  541.      * @exception IOException Any of the usual Input/Output exceptions.
  542.      * @since     JDK1.1
  543.      */
  544.     protected Object resolveObject(Object obj)
  545.         throws IOException
  546.     {
  547.     return obj;
  548.     }
  549.  
  550.     /**
  551.      * Enable the stream to allow objects read from the stream to be replaced.
  552.      * If the stream is a trusted class it is allowed to enable replacment.
  553.      * Trusted classes are those classes with a classLoader equals null. <p>
  554.      * 
  555.      * When enabled the resolveObject method is called for every object
  556.      * being deserialized.
  557.      * 
  558.      * @exception SecurityException The classloader of this stream object is non-null.
  559.      * @since     JDK1.1
  560.      */
  561.     protected final boolean enableResolveObject(boolean enable)
  562.     throws SecurityException
  563.     {
  564.     boolean previous = enableResolve;
  565.     if (enable) {
  566.         ClassLoader loader = this.getClass().getClassLoader();
  567.         if (loader == null) {
  568.         enableResolve = true;
  569.         return previous;
  570.         }
  571.         throw new SecurityException("Not trusted class");
  572.     } else {
  573.         enableResolve = false;
  574.     }
  575.     return previous;
  576.     }
  577.  
  578.  
  579.     /**
  580.      * The readStreamHeader method is provided to allow subclasses to
  581.      * read and verify their own stream headers. It reads and
  582.      * verifies the magic number and version number.
  583.      * @since     JDK1.1
  584.      */
  585.     protected void readStreamHeader()
  586.     throws IOException, StreamCorruptedException
  587.     {
  588.     short incoming_magic = readShort();
  589.     short incoming_version = readShort();
  590.     if (incoming_magic != STREAM_MAGIC)
  591.         throw new StreamCorruptedException("InputStream does not contain a serialized object");
  592.     
  593.     if (incoming_version != STREAM_VERSION)
  594.         throw new StreamCorruptedException("Version Mismatch, Expected " +
  595.                            STREAM_VERSION + " and got " +
  596.                            incoming_version);
  597.     }
  598.  
  599.     /*
  600.      * Read a ObjectStreamClasss from the stream, it may recursively
  601.      * create other ObjectStreamClasss for the classes it references.
  602.      */
  603.     private ObjectStreamClass inputClassDescriptor()
  604.     throws IOException, InvalidClassException, ClassNotFoundException
  605.     {
  606.  
  607.     /* Read the class name and hash */
  608.     Class aclass;
  609.     String classname = readUTF(); 
  610.     long hash = readLong();
  611.  
  612.     /* Read a new class version descriptor from the stream */
  613.     ObjectStreamClass v = new ObjectStreamClass(classname, hash);
  614.  
  615.     /* Assign the wire handle for this ObjectStreamClass and read it */
  616.     int wireoffset = assignWireOffset(v); 
  617.     v.read(this);
  618.  
  619.     /* Switch to BlockDataMode and call resolveClass.
  620.      * It may raise ClassNotFoundException.
  621.      * Consume any extra data or objects left by resolve class and
  622.      * read the endOfBlockData. Then switch out of BlockDataMode.
  623.      */
  624.     boolean prevMode = setBlockData(true);
  625.     aclass = resolveClass((ObjectStreamClass)v);
  626.     SkipToEndOfBlockData();
  627.     prevMode = setBlockData(prevMode);
  628.  
  629.  
  630.     /* Verify that the class returned is "compatible" with
  631.      * the class description.  i.e. the name and hash match.
  632.      * Set the class this ObjectStreamClass will use to create 
  633.      * instances.
  634.      */
  635.     if (aclass == null) {
  636.         throw new ClassNotFoundException(v.getName());
  637.     }
  638.     v.setClass(aclass);
  639.  
  640.     /* Get the superdescriptor of this one and it set it.
  641.      */
  642.     ObjectStreamClass superdesc = (ObjectStreamClass)readObject();
  643.     v.setSuperclass(superdesc);
  644.  
  645.     return v;
  646.     }
  647.  
  648.     /* Private routine to read in an array. Called from inputObject
  649.      * after the typecode has been read from the stream.
  650.      */
  651.     private Object inputArray()
  652.     throws IOException, ClassNotFoundException
  653.     {
  654.     /* May raise ClassNotFoundException */
  655.     ObjectStreamClass v = (ObjectStreamClass)readObject();
  656.     
  657.     Class arrayclass = v.forClass();
  658.  
  659.     /* This can't be done with new because only the top level array
  660.      * is needed and the type must be set properly.
  661.      * the lower level arrays will be created when they are read.
  662.      */
  663.     int length = readInt();
  664.     currentObject = allocateNewArray(arrayclass, length);
  665.     assignWireOffset(currentObject);
  666.     
  667.     /* Read in the values from the array,
  668.      * It dispatches using the type and read using the read* methods.
  669.      */
  670.     int i;
  671.     Class type = arrayclass.getComponentType();
  672.  
  673.     if (type.isPrimitive()) {
  674.         /* Arrays of primitive types read data in blocks and
  675.          * decode the data types from the buffer.
  676.          */
  677.         if (buffer == null)
  678.         buffer = new byte[1024];
  679.         int offset = buffer.length;
  680.         int buflen = buffer.length;
  681.  
  682.         if (type == Boolean.TYPE) {
  683.         boolean[] array = (boolean[])currentObject;
  684.         for (i = 0; i < length; i++) {
  685.             if (offset >= buflen) {
  686.             int readlen = Math.min(length-i, buflen);
  687.             readFully(buffer, 0, readlen);
  688.             offset = 0;
  689.             }
  690.             array[i] = (buffer[offset] != 0);
  691.             offset += 1;
  692.         }
  693.         } else if (type == Byte.TYPE) {
  694.         byte[] array = (byte[])currentObject;
  695.         readFully(array, 0, length);
  696.         } else if (type == Short.TYPE) {
  697.         short[] array = (short[])currentObject;
  698.         for (i = 0; i < length; i++) {
  699.             if (offset > buflen - 2) {
  700.             int readlen = Math.min((length-i)*2, buflen);
  701.             readFully(buffer, 0, readlen);
  702.             offset = 0;
  703.             }
  704.             array[i] = (short)(((buffer[offset] & 0xff) << 8) +
  705.                        ((buffer[offset+1] & 0xff) << 0));
  706.             offset += 2;
  707.         }
  708.         } else if (type == Integer.TYPE) {
  709.         int[] array = (int[])currentObject;
  710.         for (i = 0; i < length; i++) {
  711.             if (offset > buflen - 4) {
  712.             int readlen = Math.min((length-i)*4, buflen);
  713.             readFully(buffer, 0, readlen);
  714.             offset = 0;
  715.             }
  716.             array[i] = (((buffer[offset] & 0xff) << 24) +
  717.                 ((buffer[offset+1] & 0xff) << 16) +
  718.                 ((buffer[offset+2] & 0xff) << 8) +
  719.                 ((buffer[offset+3] & 0xff) << 0));
  720.             offset += 4;
  721.         }
  722.         } else if (type == Long.TYPE) {
  723.         long[] array = (long[])currentObject;
  724.         for (i = 0; i < length; i++) {
  725.             if (offset > buflen - 8) {
  726.             int readlen = Math.min((length-i)*8, buflen);
  727.             readFully(buffer, 0, readlen);
  728.             offset = 0;
  729.             }
  730.             int upper = (((buffer[offset] & 0xff) << 24) +
  731.                 ((buffer[offset+1] & 0xff) << 16) +
  732.                 ((buffer[offset+2] & 0xff) << 8) +
  733.                 ((buffer[offset+3] & 0xff) << 0));
  734.             int lower = (((buffer[offset+4] & 0xff) << 24) +
  735.                 ((buffer[offset+5] & 0xff) << 16) +
  736.                 ((buffer[offset+6] & 0xff) << 8) +
  737.                 ((buffer[offset+7] & 0xff) << 0));
  738.             array[i] = ((long)upper << 32) + ((long)lower & 0xFFFFFFFFL);
  739.             offset += 8;
  740.         }
  741.         } else if (type == Float.TYPE) {
  742.         float[] array = (float[])currentObject;
  743.         for (i = 0; i < length; i++) {
  744.             if (offset > buflen - 4) {
  745.             int readlen = Math.min((length-i)*4, buflen);
  746.             readFully(buffer, 0, readlen);
  747.             offset = 0;
  748.             }
  749.             int value = (((buffer[offset] & 0xff) << 24) +
  750.                  ((buffer[offset+1] & 0xff) << 16) +
  751.                  ((buffer[offset+2] & 0xff) << 8) +
  752.                  ((buffer[offset+3] & 0xff) << 0));
  753.             offset += 4;
  754.             array[i] = Float.intBitsToFloat(value);
  755.         }
  756.         } else if (type == Double.TYPE) {
  757.         double[] array = (double[])currentObject;
  758.         for (i = 0; i < length; i++) {
  759.             if (offset > buflen - 8) {
  760.             int readlen = Math.min((length-i)*8, buflen);
  761.             readFully(buffer, 0, readlen);
  762.             offset = 0;
  763.             }
  764.             int upper = (((buffer[offset] & 0xff) << 24) +
  765.                  ((buffer[offset+1] & 0xff) << 16) +
  766.                  ((buffer[offset+2] & 0xff) << 8) +
  767.                  ((buffer[offset+3] & 0xff) << 0));
  768.             int lower = (((buffer[offset+4] & 0xff) << 24) +
  769.                  ((buffer[offset+5] & 0xff) << 16) +
  770.                  ((buffer[offset+6] & 0xff) << 8) +
  771.                  ((buffer[offset+7] & 0xff) << 0));
  772.             offset += 8;
  773.             array[i] = Double.longBitsToDouble((((long)upper) << 32) +
  774.                                (lower & 0xFFFFFFFFL));
  775.         }
  776.         } else if (type == Character.TYPE) {
  777.         char[] array = (char[])currentObject;
  778.         for (i = 0; i < length; i++) {
  779.             if (offset > buflen - 2) {
  780.             int readlen = Math.min((length-i)*2, buflen);
  781.             readFully(buffer, 0, readlen);
  782.             offset = 0;
  783.             }
  784.             array[i] = (char)(((buffer[offset] & 0xff) << 8) +
  785.                       ((buffer[offset+1] & 0xff) << 0));
  786.             offset += 2;
  787.         }
  788.         } else {
  789.         throw new InvalidClassException(arrayclass.getName());
  790.         }
  791.     } else {        // Is array of objects
  792.         Object[] array = (Object[])currentObject;
  793.         for (i = 0; i < length; i++) {
  794.         array[i] = readObject();
  795.         }
  796.     }
  797.  
  798.     return currentObject;
  799.     }
  800.  
  801.     /*
  802.      * Read an instance of a class from the stream
  803.      * The new object typecode has already been read and used to dispatch to here.
  804.      * The ObjectStreamClass for the class is read and the class
  805.      * of the object retrieved from it.
  806.      * A new object is created of the specified class and
  807.      * each serializable class is processed using either
  808.      * the default serialization methods or class defined special methods
  809.      * if they have been defined.
  810.      * The handle for the object is returned, the object itself is in currentObject.
  811.      */
  812.     private int inputObject()
  813.     throws IOException, ClassNotFoundException
  814.     {
  815.     int handle = -1;
  816.     /*
  817.      * Get the descriptor and then class of the incomming object.
  818.      */
  819.     currentClassDesc = (ObjectStreamClass)readObject();
  820.     currentClass = currentClassDesc.forClass();
  821.     
  822.     
  823.     /* If Externalizable,
  824.      *  Create an instance and tell it to read its data.
  825.      * else,
  826.      *  Handle it as a serializable class.
  827.      */
  828.     if (currentClassDesc.isExternalizable()) {
  829.         try {
  830.         currentObject = allocateNewObject(currentClass, currentClass);
  831.         handle = assignWireOffset(currentObject);
  832.         Externalizable ext = (Externalizable)currentObject;
  833.         ext.readExternal(this);
  834.         } catch (IllegalAccessException e) {
  835.         throw new InvalidClassException(currentClass.getName(),
  836.                         "IllegalAccessException");
  837.         } catch (InstantiationException e) {
  838.         throw new InvalidClassException(currentClass.getName(),
  839.                         "InstantiationException");
  840.         }
  841.     } else {
  842.         /* Count number of classes and descriptors we might have
  843.          * to work on.
  844.          */
  845.         ObjectStreamClass currdesc = currentClassDesc;
  846.         Class currclass = currentClass;
  847.  
  848.         int spBase = spClass;    // current top of stack
  849.  
  850.         /* The object's classes should be processed from supertype to subtype
  851.          * Push all the clases of the current object onto a stack.
  852.          * Note that only the serializable classes are represented
  853.          * in the descriptor list. 
  854.          *
  855.          * Handle versioning where one or more supertypes of
  856.          * have been inserted or removed.  The stack will
  857.          * contain pairs of descriptors and the corresponding
  858.          * class.  If the object has a class that did not occur in
  859.          * the original the descriptor will be null.  If the
  860.          * original object had a descriptor for a class not
  861.          * present in the local hierarchy of the object the class will be
  862.          * null.
  863.          *
  864.          */
  865.  
  866.         /*
  867.          * This is your basic diff pattern, made simpler
  868.          * because reordering is not allowed.
  869.          */
  870.         for (currdesc = currentClassDesc, currclass = currentClass;
  871.          currdesc != null;
  872.          currdesc = currdesc.getSuperclass()) {
  873.  
  874.         /*
  875.          * Search the classes to see if thisthe class of this
  876.          * descriptor appears further up the hierarchy. Until
  877.          * it's found assume its an inserted class.  If it's
  878.          * not found, its the descriptor's class that has been
  879.          * removed.
  880.          */
  881.         Class cc = currdesc.forClass();
  882.         Class cl;
  883.         for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  884.             if (cc == cl) {
  885.             // found a superclass that matches this descriptor
  886.             break;
  887.             } else {
  888.             /* Ignore a class that doesn't match.  No
  889.              * action is needed since it is already
  890.              * initialized.
  891.              */
  892.             }
  893.         }
  894.         /* Test if there is room for this new entry.
  895.          * If not, double the size of the arrays and copy the contents.
  896.          */
  897.         spClass++;
  898.         if (spClass >= classes.length) {
  899.             int newlen = classes.length * 2;
  900.             Class[] newclasses = new Class[newlen];
  901.             ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  902.  
  903.             System.arraycopy(classes, 0,
  904.                  newclasses, 0,
  905.                  classes.length);
  906.             System.arraycopy(classdesc, 0,
  907.                      newclassdesc, 0,
  908.                      classes.length);
  909.  
  910.             classes = newclasses;
  911.             classdesc = newclassdesc;
  912.         }
  913.  
  914.         if (cl == null) {
  915.             /* Class not found corresponding to this descriptor.
  916.              * Pop off all the extra classes pushed.
  917.              * Push the descriptor and a null class.
  918.              */
  919.             classdesc[spClass] = currdesc;
  920.             classes[spClass] = null;
  921.         } else {
  922.                    /* Current class descriptor matches current class.
  923.              * Some classes may have been inserted.
  924.              * Record the match and advance the class, continue
  925.              * with the next descriptor.
  926.              */
  927.             classdesc[spClass] = currdesc;
  928.             classes[spClass] = cl;
  929.             currclass = cl.getSuperclass();
  930.         }
  931.         }
  932.  
  933.         /* Allocate a new object.  The object is only constructed
  934.          * above the highest serializable class and is set to
  935.          * default values for all more specialized classes.
  936.          * Remember the next wirehandle goes with the new object
  937.          */
  938.         try {
  939.         currentObject = allocateNewObject(currentClass, currclass);
  940.         } catch (NoSuchMethodError e) {
  941.         throw new InvalidClassException(currclass.getName(),
  942.                         "NoSuchMethodError");
  943.         } catch (IllegalAccessException e) {
  944.         throw new InvalidClassException(currclass.getName(),
  945.                         "IllegalAccessException");
  946.         } catch (InstantiationException e) {
  947.         throw new InvalidClassException(currclass.getName(),
  948.                         "InstantiationException");
  949.         }
  950.         handle = assignWireOffset(currentObject);
  951.         
  952.         /* 
  953.          * For all the pushed descriptors and classes.
  954.          * If there is a descriptor but no class, skip the
  955.          * data for that class.
  956.          * If there is a class but no descriptor, just advance,
  957.          * The classes fields have already been initialized to default
  958.          * values.
  959.          * Otherwise, there is both a descriptor and class,
  960.          *     if the class has its own writeObject and readObject methods
  961.          *        set blockData = true; and call the readObject method
  962.          *    else
  963.          *        invoke the defaultReadObject method
  964.          *    if the stream was written by class specific methods
  965.          *        skip any remaining data a objects until TC_ENDBLOCKDATA
  966.          * Avoid setting BlockData=true unless necessary becase it flushes
  967.          * the buffer.
  968.          */
  969.         try {
  970.         for (spClass = spClass; spClass > spBase; spClass--) {
  971.             /*
  972.              * Set current descriptor and corresponding class
  973.              */
  974.             currentClassDesc = classdesc[spClass];
  975.             currentClass = classes[spClass];
  976.  
  977.             if (classes[spClass] != null) {
  978.             /* Read the data from the stream described by the
  979.              * descriptor and store into the matching class.
  980.              */
  981.             setBlockData(true);    /* any reads are from datablocks */
  982.             ObjectStreamClass localDesc = currentClassDesc.localClassDescriptor();
  983.             if (!invokeObjectReader(currentObject, currentClass)) {
  984.                 defaultReadObject();
  985.             }
  986.             } else {
  987.             /* No class for this descriptor,
  988.              * Skip over the data for this class.
  989.              * like defaultReadObject with a null currentObject.
  990.              * The native code will read the values but discard them.
  991.              */
  992.             if (currentClassDesc.getFieldSequence() != null) {
  993.                 boolean prevmode = setBlockData(false);
  994.                 inputClassFields(null, currentClass,
  995.                          currentClassDesc.getFieldSequence());
  996.                 setBlockData(prevmode);
  997.             }
  998.             }
  999.  
  1000.             /*
  1001.              * If the source class (stream) had a write object method
  1002.              * it may have written more data and will have written the
  1003.              * TC_ENDBLOCKDATA.  Skip anything up to that and read it.
  1004.              */
  1005.             if (currentClassDesc.hasWriteObject()) {
  1006.             SkipToEndOfBlockData();
  1007.             }
  1008.             setBlockData(false);
  1009.         }
  1010.         } finally {
  1011.         // Make sure we exit at the same stack level as when we started.
  1012.         spClass = spBase;
  1013.         }
  1014.     }
  1015.     return handle;
  1016.     }
  1017.  
  1018.     /*
  1019.      * Skip any unread block data and objects up to the next
  1020.      * TC_ENDBLOCKDATA.  Anybody can do this because readObject
  1021.      * handles the details of reporting if there is data left.
  1022.      * Try reading objects.  If it throws optional data
  1023.      * skip over it and try again. 
  1024.      */
  1025.     private void SkipToEndOfBlockData()
  1026.     throws IOException, ClassNotFoundException
  1027.     {
  1028.     while (peekCode() != TC_ENDBLOCKDATA) {
  1029.         try {
  1030.         Object ignore = readObject();
  1031.         } catch (OptionalDataException data) {
  1032.         if (data.length > 0)
  1033.             skip(data.length);
  1034.         }
  1035.     }
  1036.     readCode();            /* Consume TC_ENDBLOCKDATA */
  1037.     }
  1038.     
  1039.     /*
  1040.      * Reset the stream to be just like it was after the constructor.
  1041.      */
  1042.     private void resetStream() throws IOException {
  1043.     wireHandle2Object = new Vector(100,100);
  1044.     nextWireOffset = 0;
  1045.     classes = new Class[20];
  1046.     classdesc = new ObjectStreamClass[20];
  1047.     spClass = 0;
  1048.     setBlockData(true);        // Re-enable buffering
  1049.     callbacks = null;        // discard any pending callbacks
  1050.     }
  1051.  
  1052.     /* Allocate a handle for an object.
  1053.      * The Vector is indexed by the wireHandleOffset
  1054.      * and contains the object.
  1055.      */
  1056.     private int assignWireOffset(Object obj)
  1057.     throws IOException
  1058.     {
  1059.     wireHandle2Object.addElement(obj);
  1060.     if (++nextWireOffset != wireHandle2Object.size())
  1061.       throw new StreamCorruptedException("Elements not assigned in order");;
  1062.     return nextWireOffset-1;
  1063.     }
  1064.  
  1065.     /*
  1066.      * Peek at the next control code in the stream.
  1067.      * If the code has not been peeked at yet, read it from the stream.
  1068.      */
  1069.     private byte peekCode() throws IOException, StreamCorruptedException{
  1070.     while (currCode == 0) {
  1071.  
  1072.         int newcode = in.read();    // Read byte from the underlying stream
  1073.         if (newcode < 0) 
  1074.         throw new EOFException("Expecting code");
  1075.         
  1076.         currCode = (byte)newcode;
  1077.         if (currCode < TC_BASE || currCode > TC_MAX)
  1078.         throw new StreamCorruptedException("Type code out of range, is " + currCode);
  1079.  
  1080.         /* 
  1081.          * Handle reset as a hidden code and reset the stream.
  1082.          */
  1083.         if (currCode == TC_RESET) {
  1084.         if (recursionDepth != 0 ||
  1085.             currentObject != null ||
  1086.             currentClassDesc != null)
  1087.             throw new StreamCorruptedException("Illegal stream state for reset");
  1088.         
  1089.         /* Reset the stream, and repeat the peek at the next code
  1090.          */
  1091.         resetStream();
  1092.         currCode = 0;
  1093.         }
  1094.     }
  1095.     return currCode;
  1096.     }
  1097.     
  1098.     /*
  1099.      * Return the next control code in the stream.
  1100.      * peekCode gets the next code.  readCode just consumes it.
  1101.      */
  1102.     private byte readCode()
  1103.     throws IOException, StreamCorruptedException
  1104.     {
  1105.     byte tc = peekCode();
  1106.     currCode = 0;
  1107.     return tc;
  1108.     }
  1109.     
  1110.     /*
  1111.      * Put back the specified code to be peeked at next time.
  1112.      */
  1113.     private void pushbackCode(byte code) {
  1114.     currCode = code;
  1115.     }
  1116.     /* -----------------------------------------------------*/
  1117.     /*
  1118.      * Implement the InputStream methods.  The stream has
  1119.      * two modes used internally to ObjectInputStream.  When
  1120.      * in BlockData mode, all reads are only from datablocks
  1121.      * as original written. End of data (-1) is returned
  1122.      * if something other than a datablock is next in the stream.
  1123.      * When not in BlockData mode (false), reads pass directly
  1124.      * through to the underlying stream.
  1125.      * The BlockData mode is used to encapsulate data written
  1126.      * by class specific writeObject methods that is intended
  1127.      * only to be read by corresponding readObject method of the 
  1128.      * same class.  The blocking of data allows it to be skipped
  1129.      * if necessary.
  1130.      *
  1131.      * The setBlockData method is used to switch buffering
  1132.      * on and off.  When switching between on and off 
  1133.      * there must be no data pending to be read. This is 
  1134.      * an internal consistency check that will throw an exception. 
  1135.      *
  1136.      */
  1137.     private InputStream in;
  1138.  
  1139.     /*
  1140.      * Count of bytes available from blockData, if zero, call refill
  1141.      * to look for more.  If -1 always return eof (-1)
  1142.      */
  1143.     private int count;
  1144.         
  1145.     private boolean blockDataMode;
  1146.  
  1147.     private byte[] buffer;    // buffer for reading array data
  1148.  
  1149.     /*
  1150.      * Set the blockdata buffering mode.
  1151.      * If it is being set to false after being true there must
  1152.      * be no pending data. If count > 0 a corrupted exception is thrown.
  1153.      */
  1154.     private boolean setBlockData(boolean mode) throws IOException {
  1155.     if (blockDataMode == mode)
  1156.         return mode;
  1157.     if (blockDataMode && count > 0)
  1158.         throw new StreamCorruptedException("Unread data");
  1159.  
  1160.     /* Set count to allow reading or not */
  1161.     count =  mode ? 0 : -1;
  1162.  
  1163.     blockDataMode = mode;
  1164.     return !mode;
  1165.     }
  1166.     
  1167.     /**
  1168.      * Reads a byte of data. This method will block if no input is 
  1169.      * available.
  1170.      * @return     the byte read, or -1 if the end of the
  1171.      *        stream is reached.
  1172.      * @exception IOException If an I/O error has occurred.
  1173.      * @since     JDK1.1
  1174.      */
  1175.     public int read() throws IOException {
  1176.     int data;
  1177.     if (blockDataMode) {
  1178.         while (count == 0)
  1179.         refill();
  1180.         if (count < 0)
  1181.         return -1;            /* EOF */
  1182.         data = in.read();
  1183.         if (data >= 0)
  1184.         count--;
  1185.     } else {
  1186.         data = in.read();        /* read directly from input stream */
  1187.     }
  1188.     return data;
  1189.     }
  1190.  
  1191.     /*
  1192.      * Expect the next thing in the stream is a datablock, If its a
  1193.      * datablock, extract the count of bytes to allow.  If data is not
  1194.      * available set the count to zero.  On error or EOF, set count to -1.
  1195.      */
  1196.     private void refill() throws IOException {
  1197.     count = -1;        /*  No more data to read, EOF */
  1198.     byte code;
  1199.     try {
  1200.         code = peekCode();
  1201.     } catch (EOFException e) {
  1202.         return;
  1203.     }
  1204.     if (code == TC_BLOCKDATA) {
  1205.         code = readCode();            /* Consume the code */
  1206.         int c = in.read();
  1207.         if (c < 0)
  1208.         throw new StreamCorruptedException("EOF expecting count");
  1209.         
  1210.         count = c & 0xff;
  1211.     } else if (code == TC_BLOCKDATALONG) {
  1212.         code = readCode();
  1213.         int b3 = in.read();
  1214.         int b2 = in.read();
  1215.         int b1 = in.read();
  1216.         int b0 = in.read();
  1217.         if ((b3 | b2 | b1 | b0) < 0)
  1218.         throw new StreamCorruptedException("EOF expecting count");
  1219.         int c = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
  1220.         /*
  1221.          * The 32 bit integer size in the long block data format is
  1222.          * signed (unlike like the normal block data format), and
  1223.          * negative values are invalid.
  1224.          */
  1225.         if (c < 0)
  1226.         throw new StreamCorruptedException("Negative block data size");
  1227.  
  1228.         count = c;
  1229.     }
  1230.     }
  1231.     
  1232.     /**
  1233.      * Reads into an array of bytes.  This method will
  1234.      * block until some input is available.
  1235.      * @param b    the buffer into which the data is read
  1236.      * @param off the start offset of the data
  1237.      * @param len the maximum number of bytes read
  1238.      * @return  the actual number of bytes read, -1 is
  1239.      *         returned when the end of the stream is reached.
  1240.      * @exception IOException If an I/O error has occurred.
  1241.      * @since     JDK1.1
  1242.      */
  1243.     public int read(byte[] data, int offset, int length) throws IOException {
  1244.     int v;
  1245.     int i;
  1246.  
  1247.     if (length < 0)
  1248.         throw new IndexOutOfBoundsException();
  1249.  
  1250.     if (blockDataMode) {
  1251.         while (count == 0)
  1252.         refill();
  1253.         if (count < 0)
  1254.         return -1;
  1255.         int l = Math.min(length, count);
  1256.         i = in.read(data, offset, l);
  1257.         if (i > 0)
  1258.         count -= i;
  1259.         return i;            /* return number of bytes read */
  1260.     } else {
  1261.         /* read directly from input stream */
  1262.         return in.read(data, offset, length);
  1263.     }
  1264.     }
  1265.  
  1266.     /**
  1267.      * Returns the number of bytes that can be read without blocking.
  1268.      * @return the number of available bytes.
  1269.      * @since     JDK1.1
  1270.      */
  1271.     /*
  1272.      * If in blockdataMode returns the number of bytes in the
  1273.      * current block. If that is zero, it will try to read
  1274.      * another blockdata from the stream if any data is available from the
  1275.      * underlying stream..
  1276.      * If not in blockdata mode it returns zero.
  1277.      */
  1278.     public int available() throws IOException {
  1279.     if (blockDataMode) {
  1280.         if (count == 0 && in.available() > 0)
  1281.         refill();
  1282.         if (count >= 0) {
  1283.         return count;
  1284.         } else
  1285.         return 0;    /* EOF is no bytes available */
  1286.     } else {
  1287.         return 0;        /* Not blockdata, no bytes available */
  1288.     }
  1289.     }
  1290.  
  1291.     /**
  1292.      * Closes the input stream. Must be called
  1293.      * to release any resources associated with
  1294.      * the stream.
  1295.      * @exception IOException If an I/O error has occurred.
  1296.      * @since     JDK1.1
  1297.      */
  1298.     public void close() throws IOException {
  1299.     in.close();
  1300.     }
  1301.  
  1302.     /* -----------------------------------------------------*/
  1303.     /*
  1304.      * Provide the methods to implement DataInput.
  1305.      * They delegate to an Instance of DataInputStream that
  1306.      * reads its input from the ObjectInputStream.
  1307.      * This allows this stream to manage the blocked data the data
  1308.      * as necessary.
  1309.      */
  1310.     private DataInputStream dis;
  1311.     
  1312.     /**
  1313.      * Reads in a boolean.
  1314.      * @return the boolean read.
  1315.      * @exception EOFException If end of file is reached.
  1316.      * @exception IOException If other I/O error has occurred.
  1317.      * @since     JDK1.1
  1318.      */
  1319.     public boolean readBoolean() throws IOException {
  1320.     return dis.readBoolean();
  1321.     }
  1322.  
  1323.     /**
  1324.      * Reads an 8 bit byte.
  1325.      * @return the 8 bit byte read.
  1326.      * @exception EOFException If end of file is reached.
  1327.      * @exception IOException If other I/O error has occurred.
  1328.      * @since     JDK1.1
  1329.      */
  1330.     public byte readByte() throws IOException  {
  1331.     return dis.readByte();
  1332.     }
  1333.  
  1334.     /**
  1335.      * Reads an unsigned 8 bit byte.
  1336.      * @return the 8 bit byte read.
  1337.      * @exception EOFException If end of file is reached.
  1338.      * @exception IOException If other I/O error has occurred.
  1339.      * @since     JDK1.1
  1340.      */
  1341.     public int readUnsignedByte()  throws IOException {
  1342.     return dis.readUnsignedByte();
  1343.     }
  1344.  
  1345.     /**
  1346.      * Reads a 16 bit short.
  1347.      * @return the 16 bit short read.
  1348.      * @exception EOFException If end of file is reached.
  1349.      * @exception IOException If other I/O error has occurred.
  1350.      * @since     JDK1.1
  1351.      */
  1352.     public short readShort()  throws IOException {
  1353.     return dis.readShort();
  1354.     }
  1355.  
  1356.     /**
  1357.      * Reads an unsigned 16 bit short.
  1358.      * @return the 16 bit short read.
  1359.      * @exception EOFException If end of file is reached.
  1360.      * @exception IOException If other I/O error has occurred.
  1361.      * @since     JDK1.1
  1362.      */
  1363.     public int readUnsignedShort() throws IOException {
  1364.     return dis.readUnsignedShort();
  1365.     }
  1366.  
  1367.     /**
  1368.      * Reads a 16 bit char.
  1369.      * @return the 16 bit char read. 
  1370.      * @exception EOFException If end of file is reached.
  1371.      * @exception IOException If other I/O error has occurred.
  1372.      * @since     JDK1.1
  1373.      */
  1374.     public char readChar()  throws IOException {
  1375.     return dis.readChar();
  1376.     }
  1377.  
  1378.     /**
  1379.      * Reads a 32 bit int.
  1380.      * @return the 32 bit integer read.
  1381.      * @exception EOFException If end of file is reached.
  1382.      * @exception IOException If other I/O error has occurred.
  1383.      * @since     JDK1.1
  1384.      */
  1385.     public int readInt()  throws IOException {
  1386.     return dis.readInt();
  1387.     }
  1388.  
  1389.     /**
  1390.      * Reads a 64 bit long.
  1391.      * @return the read 64 bit long.
  1392.      * @exception EOFException If end of file is reached.
  1393.      * @exception IOException If other I/O error has occurred.
  1394.      * @since     JDK1.1
  1395.      */
  1396.     public long readLong()  throws IOException {
  1397.     return dis.readLong();
  1398.     }
  1399.  
  1400.     /**
  1401.      * Reads a 32 bit float.
  1402.      * @return the 32 bit float read.
  1403.      * @exception EOFException If end of file is reached.
  1404.      * @exception IOException If other I/O error has occurred.
  1405.      * @since     JDK1.1
  1406.      */
  1407.     public float readFloat() throws IOException {
  1408.     return dis.readFloat();
  1409.     }
  1410.  
  1411.     /**
  1412.      * Reads a 64 bit double.
  1413.      * @return the 64 bit double read.
  1414.      * @exception EOFException If end of file is reached.
  1415.      * @exception IOException If other I/O error has occurred.
  1416.      * @since     JDK1.1
  1417.      */
  1418.     public double readDouble() throws IOException {
  1419.     return dis.readDouble();
  1420.     }
  1421.  
  1422.     /**
  1423.      * Reads bytes, blocking until all bytes are read.
  1424.      * @param b    the buffer into which the data is read
  1425.      * @exception EOFException If end of file is reached.
  1426.      * @exception IOException If other I/O error has occurred.
  1427.      * @since     JDK1.1
  1428.      */
  1429.     public void readFully(byte[] data) throws IOException {
  1430.     dis.readFully(data);
  1431.     }
  1432.  
  1433.     /**
  1434.      * Reads bytes, blocking until all bytes are read.
  1435.      * @param b    the buffer into which the data is read
  1436.      * @param off the start offset of the data
  1437.      * @param len the maximum number of bytes to read
  1438.      * @exception EOFException If end of file is reached.
  1439.      * @exception IOException If other I/O error has occurred.
  1440.      * @since     JDK1.1
  1441.      */
  1442.     public void readFully(byte[] data, int offset, int size) throws IOException {
  1443.     if (size < 0)
  1444.         throw new IndexOutOfBoundsException();
  1445.     
  1446.     dis.readFully(data, offset, size);
  1447.     }
  1448.  
  1449.     /**
  1450.      * Skips bytes, block until all bytes are skipped.
  1451.      * @param n the number of bytes to be skipped
  1452.      * @return    the actual number of bytes skipped.
  1453.      * @exception EOFException If end of file is reached.
  1454.      * @exception IOException If other I/O error has occurred.
  1455.      * @since     JDK1.1
  1456.      */
  1457.     public int skipBytes(int len) throws IOException {
  1458.     return dis.skipBytes(len);
  1459.     }
  1460.  
  1461.     /**
  1462.      * Reads in a line that has been terminated by a \n, \r, 
  1463.      * \r\n or EOF.
  1464.      * @return a String copy of the line.
  1465.      * @since     JDK1.1
  1466.      */
  1467.     public String readLine() throws IOException {
  1468.     return dis.readLine();
  1469.     }
  1470.  
  1471.     /**
  1472.      * Reads a UTF format String.
  1473.      * @return the String.
  1474.      * @since     JDK1.1
  1475.      */
  1476.      public String readUTF() throws IOException {
  1477.     return dis.readUTF();
  1478.     }
  1479.     
  1480.     /* Remember the first exception that stopped this stream. */
  1481.     private IOException abortIOException = null;
  1482.     private ClassNotFoundException abortClassNotFoundException = null;
  1483.  
  1484.     /* Read the fields of the specified class.
  1485.      * The native implementation sorts the field names to put them
  1486.      * in cononical order, ignores transient and static fields
  1487.      * and invokes the appropriate write* method on this class.
  1488.      */
  1489.     private native void inputClassFields(Object o, Class cl, int[] fieldSequence)
  1490.     throws InvalidClassException,
  1491.         StreamCorruptedException, ClassNotFoundException, IOException;
  1492.  
  1493.     /* Allocate a new object for the specified class
  1494.      * Native since newInstance may not be able to find a zero arg constructor.
  1495.      */
  1496.     private static native Object allocateNewObject(Class aclass, Class initclass)
  1497.     throws InstantiationException, IllegalAccessException;
  1498.     
  1499.     /* Allocate a new array for the specified class
  1500.      * Native since the type of the array needs to be set to the class
  1501.      */
  1502.     private static native Object allocateNewArray(Class aclass, int length);
  1503.     
  1504.     /* Test if readObject/Writer methods are present, if so
  1505.      * invoke the reader and return true.
  1506.      */
  1507.     private native boolean invokeObjectReader(Object o, Class aclass)
  1508.     throws InvalidClassException,
  1509.         StreamCorruptedException, ClassNotFoundException, IOException;
  1510.  
  1511.     
  1512.     /* The object is the current object and class is the the current
  1513.      * subclass of the object being read. Nesting information is kept
  1514.      * on the stack.
  1515.      */
  1516.     private Object currentObject;
  1517.     private ObjectStreamClass currentClassDesc;
  1518.     private Class currentClass;
  1519.  
  1520.     /* Arrays used to keep track of classes and ObjectStreamClasses
  1521.      * as they are being merged; used in inputObject.
  1522.      * spClass is the stack pointer for both.
  1523.      */
  1524.     ObjectStreamClass[] classdesc;
  1525.     Class[] classes;
  1526.     int spClass;
  1527.  
  1528.     /* During deserialization the objects in the stream are represented by
  1529.      * handles (ints), they need to be mapped to the objects.
  1530.      * The vector is indexed by the offset between baseWireHandle and the
  1531.      * wire handle in the stream.
  1532.      */
  1533.     private Vector wireHandle2Object;
  1534.     private int nextWireOffset;
  1535.  
  1536.     /* Vector of validation callback objects
  1537.      * The vector is created as needed, and ValidationCallback objects added
  1538.      * for each call to registerObject. The vector is maintained in
  1539.      * order of highest (first) priority to lowest
  1540.      */
  1541.     private Vector callbacks;
  1542.  
  1543.     /* Recursion level, starts at zero and is incremented for each entry
  1544.      * to readObject.  Decremented before exit.
  1545.      */ 
  1546.     private int recursionDepth;
  1547.  
  1548.     /* Last code Peek'ed, if any */
  1549.     private byte currCode;
  1550.  
  1551.     /* 
  1552.      * Flag set to true to allow resolveObject to be called.
  1553.      * Set by enableResolveObject.
  1554.      */
  1555.     private boolean enableResolve;
  1556. }
  1557.  
  1558. // Internal class to hold the Callback object and priority
  1559. class ValidationCallback {
  1560.     ValidationCallback(ObjectInputValidation cb, int prio) {
  1561.     callback = cb;
  1562.     priority = prio;
  1563.     }
  1564.  
  1565.     int priority;            // priority of this callback
  1566.     ObjectInputValidation callback; // object to be called back
  1567. }
  1568.