home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / ObjectInputStream.java < prev    next >
Text File  |  1998-01-23  |  55KB  |  1,581 lines

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