src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java

Tue, 28 Dec 2010 15:52:36 -0800

author
ohair
date
Tue, 28 Dec 2010 15:52:36 -0800
changeset 240
f90b3e014e83
parent 214
f642c9ec81a0
child 310
21369018a679
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

     1 /*
     2  * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 /*
    26  * Licensed Materials - Property of IBM
    27  * RMI-IIOP v1.0
    28  * Copyright IBM Corp. 1998 1999  All Rights Reserved
    29  *
    30  */
    32 package com.sun.corba.se.impl.io;
    34 import java.io.InputStream;
    35 import java.io.IOException;
    36 import java.io.StreamCorruptedException;
    37 import java.io.ObjectInputValidation;
    38 import java.io.NotActiveException;
    39 import java.io.InvalidObjectException;
    40 import java.io.InvalidClassException;
    41 import java.io.DataInputStream;
    42 import java.io.OptionalDataException;
    43 import java.io.WriteAbortedException;
    44 import java.io.Externalizable;
    45 import java.io.EOFException;
    46 import java.lang.reflect.*;
    47 import java.util.Vector;
    48 import java.util.Stack;
    49 import java.util.Hashtable;
    50 import java.util.Enumeration;
    52 import sun.corba.Bridge ;
    54 import java.security.AccessController ;
    55 import java.security.PrivilegedAction ;
    57 import com.sun.corba.se.impl.io.ObjectStreamClass;
    58 import com.sun.corba.se.impl.util.Utility;
    60 import org.omg.CORBA.portable.ValueInputStream;
    62 import org.omg.CORBA.ValueMember;
    63 import org.omg.CORBA.SystemException;
    64 import org.omg.CORBA.TCKind;
    65 import org.omg.CORBA.ORB;
    66 import org.omg.CORBA.CompletionStatus;
    67 import org.omg.CORBA.portable.IndirectionException;
    68 import org.omg.CORBA.MARSHAL;
    69 import org.omg.CORBA.TypeCode;
    71 import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
    72 import com.sun.org.omg.SendingContext.CodeBase;
    74 import javax.rmi.PortableRemoteObject;
    75 import javax.rmi.CORBA.Util;
    76 import javax.rmi.CORBA.ValueHandler;
    78 import java.security.*;
    79 import java.util.*;
    81 import com.sun.corba.se.impl.orbutil.ObjectUtility ;
    82 import com.sun.corba.se.impl.logging.OMGSystemException ;
    83 import com.sun.corba.se.impl.logging.UtilSystemException ;
    85 import com.sun.corba.se.spi.logging.CORBALogDomains ;
    87 /**
    88  * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization
    89  * input semantics.
    90  *
    91  * @author  Stephen Lewallen
    92  * @since   JDK1.1.6
    93  */
    95 public class IIOPInputStream
    96     extends com.sun.corba.se.impl.io.InputStreamHook
    97 {
    98     private static Bridge bridge =
    99         (Bridge)AccessController.doPrivileged(
   100             new PrivilegedAction() {
   101                 public Object run() {
   102                     return Bridge.get() ;
   103                 }
   104             }
   105         ) ;
   107     private static OMGSystemException omgWrapper = OMGSystemException.get(
   108         CORBALogDomains.RPC_ENCODING ) ;
   109     private static UtilSystemException utilWrapper = UtilSystemException.get(
   110         CORBALogDomains.RPC_ENCODING ) ;
   112     // Necessary to pass the appropriate fields into the
   113     // defaultReadObjectDelegate method (which takes no
   114     // parameters since it's called from
   115     // java.io.ObjectInpuStream defaultReadObject()
   116     // which we can't change).
   117     //
   118     // This is only used in the case where the fields had
   119     // to be obtained remotely because of a serializable
   120     // version difference.  Set in inputObjectUsingFVD.
   121     // Part of serialization evolution fixes for Ladybird,
   122     // bug 4365188.
   123     private ValueMember defaultReadObjectFVDMembers[] = null;
   125     private org.omg.CORBA_2_3.portable.InputStream orbStream;
   127     private CodeBase cbSender;
   129     private ValueHandlerImpl vhandler;  //d4365188
   131     private Object currentObject = null;
   133     private ObjectStreamClass currentClassDesc = null;
   135     private Class currentClass = null;
   137     private int recursionDepth = 0;
   139     private int simpleReadDepth = 0;
   141     // The ActiveRecursionManager replaces the old RecursionManager which
   142     // used to record how many recursions were made, and resolve them after
   143     // an object was completely deserialized.
   144     //
   145     // That created problems (as in bug 4414154) because when custom
   146     // unmarshaling in readObject, there can be recursive references
   147     // to one of the objects currently being unmarshaled, and the
   148     // passive recursion system failed.
   149     ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager();
   151     private IOException abortIOException = null;
   153     /* Remember the first exception that stopped this stream. */
   154     private ClassNotFoundException abortClassNotFoundException = null;
   156     /* Vector of validation callback objects
   157      * The vector is created as needed. The vector is maintained in
   158      * order of highest (first) priority to lowest
   159      */
   160     private Vector callbacks;
   162     // Serialization machinery fields
   163     /* Arrays used to keep track of classes and ObjectStreamClasses
   164      * as they are being merged; used in inputObject.
   165      * spClass is the stack pointer for both.  */
   166     ObjectStreamClass[] classdesc;
   167     Class[] classes;
   168     int spClass;
   170     private static final String kEmptyStr = "";
   172     // TCKind TypeCodes used in FVD inputClassFields
   173     //public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref);
   174     //public static final TypeCode kValueTypeCode =  new TypeCodeImpl(TCKind._tk_value);
   175     // removed TypeCodeImpl dependency
   176     public static final TypeCode kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref);
   177     public static final TypeCode kValueTypeCode =  ORB.init().get_primitive_tc(TCKind.tk_value);
   179     // TESTING CODE - useFVDOnly should be made final before FCS in order to
   180     // optimize out the check.
   181     private static final boolean useFVDOnly = false;
   183     private byte streamFormatVersion;
   185     // Since java.io.OptionalDataException's constructors are
   186     // package private, but we need to throw it in some special
   187     // cases, we try to do it by reflection.
   188     private static final Constructor OPT_DATA_EXCEPTION_CTOR;
   190     private Object[] readObjectArgList = { this } ;
   192     static {
   193         OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor();
   194     }
   196     // Grab the OptionalDataException boolean ctor and make
   197     // it accessible.  Note that any exceptions
   198     // will be wrapped in ExceptionInInitializerErrors.
   199     private static Constructor getOptDataExceptionCtor() {
   201         try {
   203             Constructor result =
   205                 (Constructor) AccessController.doPrivileged(
   206                                     new PrivilegedExceptionAction() {
   207                     public java.lang.Object run()
   208                         throws NoSuchMethodException,
   209                         SecurityException {
   211                         Constructor boolCtor
   212                             = OptionalDataException.class.getDeclaredConstructor(
   213                                                                new Class[] {
   214                                 Boolean.TYPE });
   216                         boolCtor.setAccessible(true);
   218                         return boolCtor;
   219                     }});
   221             if (result == null)
   222                 // XXX I18N, logging needed.
   223                 throw new Error("Unable to find OptionalDataException constructor");
   225             return result;
   227         } catch (Exception ex) {
   228             // XXX I18N, logging needed.
   229             throw new ExceptionInInitializerError(ex);
   230         }
   231     }
   233     // Create a new OptionalDataException with the EOF marker
   234     // set to true.  See handleOptionalDataMarshalException.
   235     private OptionalDataException createOptionalDataException() {
   236         try {
   237             OptionalDataException result
   238                 = (OptionalDataException)
   239                    OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] {
   240                        Boolean.TRUE });
   242             if (result == null)
   243                 // XXX I18N, logging needed.
   244                 throw new Error("Created null OptionalDataException");
   246             return result;
   248         } catch (Exception ex) {
   249             // XXX I18N, logging needed.
   250             throw new Error("Couldn't create OptionalDataException", ex);
   251         }
   252     }
   254     // Return the stream format version currently being used
   255     // to deserialize an object
   256     protected byte getStreamFormatVersion() {
   257         return streamFormatVersion;
   258     }
   260     // At the beginning of data sent by a writeObject or
   261     // writeExternal method there is a byte telling the
   262     // reader the stream format version.
   263     private void readFormatVersion() throws IOException {
   265         streamFormatVersion = orbStream.read_octet();
   267         if (streamFormatVersion < 1 ||
   268             streamFormatVersion > vhandler.getMaximumStreamFormatVersion()) {
   269             SystemException sysex = omgWrapper.unsupportedFormatVersion(
   270                     CompletionStatus.COMPLETED_MAYBE);
   271             // XXX I18N?  Logging for IOException?
   272             IOException result = new IOException("Unsupported format version: "
   273                                                  + streamFormatVersion);
   274             result.initCause( sysex ) ;
   275             throw result ;
   276         }
   278         if (streamFormatVersion == 2) {
   279             if (!(orbStream instanceof ValueInputStream)) {
   280                 SystemException sysex = omgWrapper.notAValueinputstream(
   281                     CompletionStatus.COMPLETED_MAYBE);
   282                 // XXX I18N?  Logging for IOException?
   283                 IOException result = new IOException("Not a ValueInputStream");
   284                 result.initCause( sysex ) ;
   285                 throw result;
   286             }
   287         }
   288     }
   290     public static void setTestFVDFlag(boolean val){
   291         //  useFVDOnly = val;
   292     }
   294     /**
   295      * Dummy constructor; passes upper stream a dummy stream;
   296      **/
   297     public IIOPInputStream()
   298         throws java.io.IOException {
   299         super();
   300         resetStream();
   301     }
   303     public final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) {
   304         orbStream = os;
   305     }
   307     public final org.omg.CORBA_2_3.portable.InputStream getOrbStream() {
   308         return orbStream;
   309     }
   311     //added setSender and getSender
   312     public final void setSender(CodeBase cb) {
   313         cbSender = cb;
   314     }
   316     public final CodeBase getSender() {
   317         return cbSender;
   318     }
   320     // 4365188 this is added to enable backward compatability w/ wrong
   321     // rep-ids
   322     public final void setValueHandler(ValueHandler vh) {
   323         vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh;
   324     }
   326     public final ValueHandler getValueHandler() {
   327         return (javax.rmi.CORBA.ValueHandler) vhandler;
   328     }
   330     public final void increaseRecursionDepth(){
   331         recursionDepth++;
   332     }
   334     public final int decreaseRecursionDepth(){
   335         return --recursionDepth;
   336     }
   338     /**
   339      * Override the actions of the final method "readObject()"
   340      * in ObjectInputStream.
   341      * @since     JDK1.1.6
   342      *
   343      * Read an object from the ObjectInputStream.
   344      * The class of the object, the signature of the class, and the values
   345      * of the non-transient and non-static fields of the class and all
   346      * of its supertypes are read.  Default deserializing for a class can be
   347      * overriden using the writeObject and readObject methods.
   348      * Objects referenced by this object are read transitively so
   349      * that a complete equivalent graph of objects is reconstructed by readObject. <p>
   350      *
   351      * The root object is completly restored when all of its fields
   352      * and the objects it references are completely restored.  At this
   353      * point the object validation callbacks are executed in order
   354      * based on their registered priorities. The callbacks are
   355      * registered by objects (in the readObject special methods)
   356      * as they are individually restored.
   357      *
   358      * Exceptions are thrown for problems with the InputStream and for classes
   359      * that should not be deserialized.  All exceptions are fatal to the
   360      * InputStream and leave it in an indeterminate state; it is up to the caller
   361      * to ignore or recover the stream state.
   362      * @exception java.lang.ClassNotFoundException Class of a serialized object
   363      *      cannot be found.
   364      * @exception InvalidClassException Something is wrong with a class used by
   365      *     serialization.
   366      * @exception StreamCorruptedException Control information in the
   367      *     stream is inconsistent.
   368      * @exception OptionalDataException Primitive data was found in the
   369      * stream instead of objects.
   370      * @exception IOException Any of the usual Input/Output related exceptions.
   371      * @since     JDK1.1
   372      */
   373     public final Object readObjectDelegate() throws IOException
   374     {
   375         try {
   377             readObjectState.readData(this);
   379             return orbStream.read_abstract_interface();
   380         } catch (MARSHAL marshalException) {
   381             handleOptionalDataMarshalException(marshalException, true);
   382             throw marshalException;
   383         } catch(IndirectionException cdrie)
   384             {
   385                 // The CDR stream had never seen the given offset before,
   386                 // so check the recursion manager (it will throw an
   387                 // IOException if it doesn't have a reference, either).
   388                 return activeRecursionMgr.getObject(cdrie.offset);
   389             }
   390     }
   392     final Object simpleReadObject(Class clz,
   393                                   String repositoryID,
   394                                   com.sun.org.omg.SendingContext.CodeBase sender,
   395                                   int offset)
   396                                          /* throws OptionalDataException, ClassNotFoundException, IOException */
   397     {
   399         /* Save the current state and get ready to read an object. */
   400         Object prevObject = currentObject;
   401         ObjectStreamClass prevClassDesc = currentClassDesc;
   402         Class prevClass = currentClass;
   403         byte oldStreamFormatVersion = streamFormatVersion;
   405         simpleReadDepth++;      // Entering
   406         Object obj = null;
   408         /*
   409          * Check for reset, handle it before reading an object.
   410          */
   411         try {
   412             // d4365188: backward compatability
   413             if (vhandler.useFullValueDescription(clz, repositoryID)) {
   414                 obj = inputObjectUsingFVD(clz, repositoryID, sender, offset);
   415             } else {
   416                 obj = inputObject(clz, repositoryID, sender, offset);
   417             }
   419             obj = currentClassDesc.readResolve(obj);
   420         }
   421         catch(ClassNotFoundException cnfe)
   422             {
   423                 bridge.throwException( cnfe ) ;
   424                 return null;
   425             }
   426         catch(IOException ioe)
   427             {
   428                 // System.out.println("CLZ = " + clz + "; " + ioe.toString());
   429                 bridge.throwException(ioe) ;
   430                 return null;
   431             }
   432         finally {
   433             simpleReadDepth --;
   434             currentObject = prevObject;
   435             currentClassDesc = prevClassDesc;
   436             currentClass = prevClass;
   437             streamFormatVersion = oldStreamFormatVersion;
   438         }
   441         /* Check for thrown exceptions and re-throw them, clearing them if
   442          * this is the last recursive call .
   443          */
   444         IOException exIOE = abortIOException;
   445         if (simpleReadDepth == 0)
   446             abortIOException = null;
   447         if (exIOE != null){
   448             bridge.throwException( exIOE ) ;
   449             return null;
   450         }
   453         ClassNotFoundException exCNF = abortClassNotFoundException;
   454         if (simpleReadDepth == 0)
   455             abortClassNotFoundException = null;
   456         if (exCNF != null) {
   457             bridge.throwException( exCNF ) ;
   458             return null;
   459         }
   461         return obj;
   462     }
   464     public final void simpleSkipObject(String repositoryID,
   465                                        com.sun.org.omg.SendingContext.CodeBase sender)
   466                                        /* throws OptionalDataException, ClassNotFoundException, IOException */
   467     {
   469         /* Save the current state and get ready to read an object. */
   470         Object prevObject = currentObject;
   471         ObjectStreamClass prevClassDesc = currentClassDesc;
   472         Class prevClass = currentClass;
   473         byte oldStreamFormatVersion = streamFormatVersion;
   475         simpleReadDepth++;      // Entering
   476         Object obj = null;
   478         /*
   479          * Check for reset, handle it before reading an object.
   480          */
   481         try {
   482             skipObjectUsingFVD(repositoryID, sender);
   483         }
   484         catch(ClassNotFoundException cnfe)
   485             {
   486                 bridge.throwException( cnfe ) ;
   487                 return;
   488             }
   489         catch(IOException ioe)
   490             {
   491                 bridge.throwException( ioe ) ;
   492                 return;
   493             }
   494         finally {
   495             simpleReadDepth --;
   496             streamFormatVersion = oldStreamFormatVersion;
   497             currentObject = prevObject;
   498             currentClassDesc = prevClassDesc;
   499             currentClass = prevClass;
   500         }
   503         /* Check for thrown exceptions and re-throw them, clearing them if
   504          * this is the last recursive call .
   505          */
   506         IOException exIOE = abortIOException;
   507         if (simpleReadDepth == 0)
   508             abortIOException = null;
   509         if (exIOE != null){
   510             bridge.throwException( exIOE ) ;
   511             return;
   512         }
   515         ClassNotFoundException exCNF = abortClassNotFoundException;
   516         if (simpleReadDepth == 0)
   517             abortClassNotFoundException = null;
   518         if (exCNF != null) {
   519             bridge.throwException( exCNF ) ;
   520             return;
   521         }
   523         return;
   524     }
   525     /////////////////
   527     /**
   528      * This method is called by trusted subclasses of ObjectOutputStream
   529      * that constructed ObjectOutputStream using the
   530      * protected no-arg constructor. The subclass is expected to provide
   531      * an override method with the modifier "final".
   532      *
   533      * @return the Object read from the stream.
   534      *
   535      * @see #ObjectInputStream()
   536      * @see #readObject
   537      * @since JDK 1.2
   538      */
   539     protected final Object readObjectOverride()
   540         throws OptionalDataException, ClassNotFoundException, IOException
   541     {
   542         return readObjectDelegate();
   543     }
   545     /**
   546      * Override the actions of the final method "defaultReadObject()"
   547      * in ObjectInputStream.
   548      * @since     JDK1.1.6
   549      *
   550      * Read the non-static and non-transient fields of the current class
   551      * from this stream.  This may only be called from the readObject method
   552      * of the class being deserialized. It will throw the NotActiveException
   553      * if it is called otherwise.
   554      *
   555      * @exception java.lang.ClassNotFoundException if the class of a serialized
   556      *              object could not be found.
   557      * @exception IOException        if an I/O error occurs.
   558      * @exception NotActiveException if the stream is not currently reading
   559      *              objects.
   560      * @since     JDK1.1
   561      */
   562     public final void defaultReadObjectDelegate()
   563     /* throws IOException, ClassNotFoundException, NotActiveException */
   564     {
   565         try {
   566             if (currentObject == null || currentClassDesc == null)
   567                 // XXX I18N, logging needed.
   568                 throw new NotActiveException("defaultReadObjectDelegate");
   570             // The array will be null unless fields were retrieved
   571             // remotely because of a serializable version difference.
   572             // Bug fix for 4365188.  See the definition of
   573             // defaultReadObjectFVDMembers for more information.
   574             if (defaultReadObjectFVDMembers != null &&
   575                 defaultReadObjectFVDMembers.length > 0) {
   577                 // WARNING:  Be very careful!  What if some of
   578                 // these fields actually have to do this, too?
   579                 // This works because the defaultReadObjectFVDMembers
   580                 // reference is passed to inputClassFields, but
   581                 // there is no guarantee that
   582                 // defaultReadObjectFVDMembers will point to the
   583                 // same array after calling inputClassFields.
   585                 // Use the remote fields to unmarshal.
   586                 inputClassFields(currentObject,
   587                                  currentClass,
   588                                  currentClassDesc,
   589                                  defaultReadObjectFVDMembers,
   590                                  cbSender);
   592             } else {
   594                 // Use the local fields to unmarshal.
   595                 ObjectStreamField[] fields =
   596                     currentClassDesc.getFieldsNoCopy();
   597                 if (fields.length > 0) {
   598                     inputClassFields(currentObject, currentClass, fields, cbSender);
   599                 }
   600             }
   601         }
   602         catch(NotActiveException nae)
   603             {
   604                 bridge.throwException( nae ) ;
   605             }
   606         catch(IOException ioe)
   607             {
   608                 bridge.throwException( ioe ) ;
   609             }
   610         catch(ClassNotFoundException cnfe)
   611             {
   612                 bridge.throwException( cnfe ) ;
   613             }
   615     }
   617     /**
   618      * Override the actions of the final method "enableResolveObject()"
   619      * in ObjectInputStream.
   620      * @since     JDK1.1.6
   621      *
   622      * Enable the stream to allow objects read from the stream to be replaced.
   623      * If the stream is a trusted class it is allowed to enable replacment.
   624      * Trusted classes are those classes with a classLoader equals null. <p>
   625      *
   626      * When enabled the resolveObject method is called for every object
   627      * being deserialized.
   628      *
   629      * @exception SecurityException The classloader of this stream object is non-null.
   630      * @since     JDK1.1
   631      */
   632     public final boolean enableResolveObjectDelegate(boolean enable)
   633     /* throws SecurityException */
   634     {
   635         return false;
   636     }
   638     // The following three methods allow the implementing orbStream
   639     // to provide mark/reset behavior as defined in java.io.InputStream.
   641     public final void mark(int readAheadLimit) {
   642         orbStream.mark(readAheadLimit);
   643     }
   645     public final boolean markSupported() {
   646         return orbStream.markSupported();
   647     }
   649     public final void reset() throws IOException {
   650         try {
   651             orbStream.reset();
   652         } catch (Error e) {
   653             IOException err = new IOException(e.getMessage());
   654             err.initCause(e) ;
   655             throw err ;
   656         }
   657     }
   659     public final int available() throws IOException{
   660         return 0; // unreliable
   661     }
   663     public final void close() throws IOException{
   664         // no op
   665     }
   667     public final int read() throws IOException{
   668         try{
   669             readObjectState.readData(this);
   671             return (orbStream.read_octet() << 0) & 0x000000FF;
   672         } catch (MARSHAL marshalException) {
   673             if (marshalException.minor
   674                 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   675                 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   676                 return -1;
   677             }
   679             throw marshalException;
   680         } catch(Error e) {
   681             IOException exc = new IOException(e.getMessage());
   682             exc.initCause(e) ;
   683             throw exc ;
   684         }
   685     }
   687     public final int read(byte data[], int offset, int length) throws IOException{
   688         try{
   689             readObjectState.readData(this);
   691             orbStream.read_octet_array(data, offset, length);
   692             return length;
   693         } catch (MARSHAL marshalException) {
   694             if (marshalException.minor
   695                 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   696                 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   697                 return -1;
   698             }
   700             throw marshalException;
   701         } catch(Error e) {
   702             IOException exc = new IOException(e.getMessage());
   703             exc.initCause(e) ;
   704             throw exc ;
   705         }
   707     }
   709     public final boolean readBoolean() throws IOException{
   710         try{
   711             readObjectState.readData(this);
   713             return orbStream.read_boolean();
   714         } catch (MARSHAL marshalException) {
   715             handleOptionalDataMarshalException(marshalException, false);
   716             throw marshalException;
   718         } catch(Error e) {
   719             IOException exc = new IOException(e.getMessage());
   720             exc.initCause(e);
   721             throw exc ;
   722         }
   723     }
   725     public final byte readByte() throws IOException{
   726         try{
   727             readObjectState.readData(this);
   729             return orbStream.read_octet();
   730         } catch (MARSHAL marshalException) {
   731             handleOptionalDataMarshalException(marshalException, false);
   732             throw marshalException;
   734         } catch(Error e) {
   735             IOException exc = new IOException(e.getMessage());
   736             exc.initCause(e);
   737             throw exc ;
   738         }
   739     }
   741     public final char readChar() throws IOException{
   742         try{
   743             readObjectState.readData(this);
   745             return orbStream.read_wchar();
   746         } catch (MARSHAL marshalException) {
   747             handleOptionalDataMarshalException(marshalException, false);
   748             throw marshalException;
   750         } catch(Error e) {
   751             IOException exc = new IOException(e.getMessage());
   752             exc.initCause(e);
   753             throw exc ;
   754         }
   755     }
   757     public final double readDouble() throws IOException{
   758         try{
   759             readObjectState.readData(this);
   761             return orbStream.read_double();
   762         } catch (MARSHAL marshalException) {
   763             handleOptionalDataMarshalException(marshalException, false);
   764             throw marshalException;
   765         } catch(Error e) {
   766             IOException exc = new IOException(e.getMessage());
   767             exc.initCause(e);
   768             throw exc ;
   769         }
   770     }
   772     public final float readFloat() throws IOException{
   773         try{
   774             readObjectState.readData(this);
   776             return orbStream.read_float();
   777         } catch (MARSHAL marshalException) {
   778             handleOptionalDataMarshalException(marshalException, false);
   779             throw marshalException;
   780         } catch(Error e) {
   781             IOException exc = new IOException(e.getMessage());
   782             exc.initCause(e);
   783             throw exc ;
   784         }
   785     }
   787     public final void readFully(byte data[]) throws IOException{
   788 // d11623 : implement readFully, required for serializing some core classes
   790         readFully(data, 0, data.length);
   791     }
   793     public final void readFully(byte data[],  int offset,  int size) throws IOException{
   794 // d11623 : implement readFully, required for serializing some core classes
   795         try{
   796             readObjectState.readData(this);
   798             orbStream.read_octet_array(data, offset, size);
   799         } catch (MARSHAL marshalException) {
   800             handleOptionalDataMarshalException(marshalException, false);
   802             throw marshalException;
   803         } catch(Error e) {
   804             IOException exc = new IOException(e.getMessage());
   805             exc.initCause(e);
   806             throw exc ;
   807         }
   808     }
   810     public final int readInt() throws IOException{
   811         try{
   812             readObjectState.readData(this);
   814             return orbStream.read_long();
   815         } catch (MARSHAL marshalException) {
   816             handleOptionalDataMarshalException(marshalException, false);
   817             throw marshalException;
   818         } catch(Error e) {
   819             IOException exc = new IOException(e.getMessage());
   820             exc.initCause(e);
   821             throw exc ;
   822         }
   823     }
   825     public final String readLine() throws IOException{
   826         // XXX I18N, logging needed.
   827         throw new IOException("Method readLine not supported");
   828     }
   830     public final long readLong() throws IOException{
   831         try{
   832             readObjectState.readData(this);
   834             return orbStream.read_longlong();
   835         } catch (MARSHAL marshalException) {
   836             handleOptionalDataMarshalException(marshalException, false);
   837             throw marshalException;
   838         } catch(Error e) {
   839             IOException exc = new IOException(e.getMessage());
   840             exc.initCause(e);
   841             throw exc ;
   842         }
   843     }
   845     public final short readShort() throws IOException{
   846         try{
   847             readObjectState.readData(this);
   849             return orbStream.read_short();
   850         } catch (MARSHAL marshalException) {
   851             handleOptionalDataMarshalException(marshalException, false);
   852             throw marshalException;
   853         } catch(Error e) {
   854             IOException exc = new IOException(e.getMessage());
   855             exc.initCause(e);
   856             throw exc ;
   857         }
   858     }
   860     protected final void readStreamHeader() throws IOException, StreamCorruptedException{
   861         // no op
   862     }
   864     public final int readUnsignedByte() throws IOException{
   865         try{
   866             readObjectState.readData(this);
   868             return (orbStream.read_octet() << 0) & 0x000000FF;
   869         } catch (MARSHAL marshalException) {
   870             handleOptionalDataMarshalException(marshalException, false);
   871             throw marshalException;
   872         } catch(Error e) {
   873             IOException exc = new IOException(e.getMessage());
   874             exc.initCause(e);
   875             throw exc ;
   876         }
   877     }
   879     public final int readUnsignedShort() throws IOException{
   880         try{
   881             readObjectState.readData(this);
   883             return (orbStream.read_ushort() << 0) & 0x0000FFFF;
   884         } catch (MARSHAL marshalException) {
   885             handleOptionalDataMarshalException(marshalException, false);
   886             throw marshalException;
   887         } catch(Error e) {
   888             IOException exc = new IOException(e.getMessage());
   889             exc.initCause(e);
   890             throw exc ;
   891         }
   892     }
   894     /**
   895      * Helper method for correcting the Kestrel bug 4367783 (dealing
   896      * with larger than 8-bit chars).  The old behavior is preserved
   897      * in orbutil.IIOPInputStream_1_3 in order to interoperate with
   898      * our legacy ORBs.
   899      */
   900     protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream)
   901     {
   902         return stream.read_wstring();
   903     }
   905     public final String readUTF() throws IOException{
   906         try{
   907             readObjectState.readData(this);
   909             return internalReadUTF(orbStream);
   910         } catch (MARSHAL marshalException) {
   911             handleOptionalDataMarshalException(marshalException, false);
   912             throw marshalException;
   913         } catch(Error e) {
   914             IOException exc = new IOException(e.getMessage());
   915             exc.initCause(e);
   916             throw exc ;
   917         }
   918     }
   920     // If the ORB stream detects an incompatibility between what's
   921     // on the wire and what our Serializable's readObject wants,
   922     // it throws a MARSHAL exception with a specific minor code.
   923     // This is rethrown to the readObject as an OptionalDataException.
   924     // So far in RMI-IIOP, this process isn't specific enough to
   925     // tell the readObject how much data is available, so we always
   926     // set the OptionalDataException's EOF marker to true.
   927     private void handleOptionalDataMarshalException(MARSHAL marshalException,
   928                                                     boolean objectRead)
   929         throws IOException {
   931         // Java Object Serialization spec 3.4: "If the readObject method
   932         // of the class attempts to read more data than is present in the
   933         // optional part of the stream for this class, the stream will
   934         // return -1 for bytewise reads, throw an EOFException for
   935         // primitive data reads, or throw an OptionalDataException
   936         // with the eof field set to true for object reads."
   937         if (marshalException.minor
   938             == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   940             IOException result;
   942             if (!objectRead)
   943                 result = new EOFException("No more optional data");
   944             else
   945                 result = createOptionalDataException();
   947             result.initCause(marshalException);
   949             setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   951             throw result;
   952         }
   953     }
   955     public final synchronized void registerValidation(ObjectInputValidation obj,
   956                                                       int prio)
   957         throws NotActiveException, InvalidObjectException{
   958         // XXX I18N, logging needed.
   959         throw new Error("Method registerValidation not supported");
   960     }
   962     protected final Class resolveClass(ObjectStreamClass v)
   963         throws IOException, ClassNotFoundException{
   964         // XXX I18N, logging needed.
   965         throw new IOException("Method resolveClass not supported");
   966     }
   968     protected final Object resolveObject(Object obj) throws IOException{
   969         // XXX I18N, logging needed.
   970         throw new IOException("Method resolveObject not supported");
   971     }
   973     public final int skipBytes(int len) throws IOException{
   974         try{
   975             readObjectState.readData(this);
   977             byte buf[] = new byte[len];
   978             orbStream.read_octet_array(buf, 0, len);
   979             return len;
   980         } catch (MARSHAL marshalException) {
   981             handleOptionalDataMarshalException(marshalException, false);
   983             throw marshalException;
   984         } catch(Error e) {
   985             IOException exc = new IOException(e.getMessage());
   986             exc.initCause(e) ;
   987             throw exc ;
   988         }
   989     }
   991     private Object inputObject(Class clz,
   992                                String repositoryID,
   993                                com.sun.org.omg.SendingContext.CodeBase sender,
   994                                int offset)
   995         throws IOException, ClassNotFoundException
   996     {
   998         /*
   999          * Get the descriptor and then class of the incoming object.
  1000          */
  1002         currentClassDesc = ObjectStreamClass.lookup(clz);
  1003         currentClass = currentClassDesc.forClass();
  1004         //currentClassDesc.setClass(currentClass);
  1005         if (currentClass == null)
  1006             // XXX I18N, logging needed.
  1007             throw new ClassNotFoundException(currentClassDesc.getName());
  1009         try {
  1010             /* If Externalizable,
  1011              *  Create an instance and tell it to read its data.
  1012              * else,
  1013              *  Handle it as a serializable class.
  1014              */
  1015             if (Enum.class.isAssignableFrom( clz )) {
  1016                 int ordinal = orbStream.read_long() ;
  1017                 String value = (String)orbStream.read_value( String.class ) ;
  1018                 return Enum.valueOf( clz, value ) ;
  1019             } else if (currentClassDesc.isExternalizable()) {
  1020                 try {
  1021                     currentObject = (currentClass == null) ?
  1022                         null : currentClassDesc.newInstance();
  1023                     if (currentObject != null) {
  1025                         // Store this object and its beginning position
  1026                         // since there might be indirections to it while
  1027                         // it's been unmarshalled.
  1028                         activeRecursionMgr.addObject(offset, currentObject);
  1030                         // Read format version
  1031                         readFormatVersion();
  1033                         Externalizable ext = (Externalizable)currentObject;
  1034                         ext.readExternal(this);
  1036             } catch (InvocationTargetException e) {
  1037                 InvalidClassException exc = new InvalidClassException(
  1038                     currentClass.getName(),
  1039                     "InvocationTargetException accessing no-arg constructor");
  1040                 exc.initCause( e ) ;
  1041                 throw exc ;
  1042             } catch (UnsupportedOperationException e) {
  1043                 InvalidClassException exc = new InvalidClassException(
  1044                     currentClass.getName(),
  1045                     "UnsupportedOperationException accessing no-arg constructor");
  1046                 exc.initCause( e ) ;
  1047                 throw exc ;
  1048             } catch (InstantiationException e) {
  1049                 InvalidClassException exc = new InvalidClassException(
  1050                     currentClass.getName(),
  1051                     "InstantiationException accessing no-arg constructor");
  1052                 exc.initCause( e ) ;
  1053                 throw exc ;
  1055         } // end : if (currentClassDesc.isExternalizable())
  1056         else {
  1057             /* Count number of classes and descriptors we might have
  1058              * to work on.
  1059              */
  1061             ObjectStreamClass currdesc = currentClassDesc;
  1062             Class currclass = currentClass;
  1064             int spBase = spClass;       // current top of stack
  1066             /* The object's classes should be processed from supertype to subtype
  1067              * Push all the clases of the current object onto a stack.
  1068              * Note that only the serializable classes are represented
  1069              * in the descriptor list.
  1071              * Handle versioning where one or more supertypes of
  1072              * have been inserted or removed.  The stack will
  1073              * contain pairs of descriptors and the corresponding
  1074              * class.  If the object has a class that did not occur in
  1075              * the original the descriptor will be null.  If the
  1076              * original object had a descriptor for a class not
  1077              * present in the local hierarchy of the object the class will be
  1078              * null.
  1080              */
  1082             /*
  1083              * This is your basic diff pattern, made simpler
  1084              * because reordering is not allowed.
  1085              */
  1086             // sun.4296963 ibm.11861
  1087             // d11861 we should stop when we find the highest serializable class
  1088             // We need this so that when we allocate the new object below, we
  1089             // can call the constructor of the non-serializable superclass.
  1090             // Note that in the JRMP variant of this code the
  1091             // ObjectStreamClass.lookup() method handles this, but we've put
  1092             // this fix here rather than change lookup because the new behaviour
  1093             // is needed in other cases.
  1095             for (currdesc = currentClassDesc, currclass = currentClass;
  1096                  currdesc != null && currdesc.isSerializable();   /*sun.4296963 ibm.11861*/
  1097                  currdesc = currdesc.getSuperclass()) {
  1099                 /*
  1100                  * Search the classes to see if the class of this
  1101                  * descriptor appears further up the hierarchy. Until
  1102                  * it's found assume its an inserted class.  If it's
  1103                  * not found, its the descriptor's class that has been
  1104                  * removed.
  1105                  */
  1106                 Class cc = currdesc.forClass();
  1107                 Class cl;
  1108                 for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  1109                     if (cc == cl) {
  1110                         // found a superclass that matches this descriptor
  1111                         break;
  1112                     } else {
  1113                         /* Ignore a class that doesn't match.  No
  1114                          * action is needed since it is already
  1115                          * initialized.
  1116                          */
  1118                 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
  1119                 /* Test if there is room for this new entry.
  1120                  * If not, double the size of the arrays and copy the contents.
  1121                  */
  1122                 spClass++;
  1123                 if (spClass >= classes.length) {
  1124                     int newlen = classes.length * 2;
  1125                     Class[] newclasses = new Class[newlen];
  1126                     ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  1128                     System.arraycopy(classes, 0,
  1129                                      newclasses, 0,
  1130                                      classes.length);
  1131                     System.arraycopy(classdesc, 0,
  1132                                      newclassdesc, 0,
  1133                                      classes.length);
  1135                     classes = newclasses;
  1136                     classdesc = newclassdesc;
  1139                 if (cl == null) {
  1140                     /* Class not found corresponding to this descriptor.
  1141                      * Pop off all the extra classes pushed.
  1142                      * Push the descriptor and a null class.
  1143                      */
  1144                     classdesc[spClass] = currdesc;
  1145                     classes[spClass] = null;
  1146                 } else {
  1147                     /* Current class descriptor matches current class.
  1148                      * Some classes may have been inserted.
  1149                      * Record the match and advance the class, continue
  1150                      * with the next descriptor.
  1151                      */
  1152                     classdesc[spClass] = currdesc;
  1153                     classes[spClass] = cl;
  1154                     currclass = cl.getSuperclass();
  1156             } // end : for (currdesc = currentClassDesc, currclass = currentClass;
  1158             /* Allocate a new object.  The object is only constructed
  1159              * above the highest serializable class and is set to
  1160              * default values for all more specialized classes.
  1161              */
  1162             try {
  1163                 currentObject = (currentClass == null) ?
  1164                     null : currentClassDesc.newInstance() ;
  1166                 // Store this object and its beginning position
  1167                 // since there might be indirections to it while
  1168                 // it's been unmarshalled.
  1169                 activeRecursionMgr.addObject(offset, currentObject);
  1170             } catch (InvocationTargetException e) {
  1171                 InvalidClassException exc = new InvalidClassException(
  1172                     currentClass.getName(),
  1173                     "InvocationTargetException accessing no-arg constructor");
  1174                 exc.initCause( e ) ;
  1175                 throw exc ;
  1176             } catch (UnsupportedOperationException e) {
  1177                 InvalidClassException exc = new InvalidClassException(
  1178                     currentClass.getName(),
  1179                     "UnsupportedOperationException accessing no-arg constructor");
  1180                 exc.initCause( e ) ;
  1181                 throw exc ;
  1182             } catch (InstantiationException e) {
  1183                 InvalidClassException exc = new InvalidClassException(
  1184                     currentClass.getName(),
  1185                     "InstantiationException accessing no-arg constructor");
  1186                 exc.initCause( e ) ;
  1187                 throw exc ;
  1190             /*
  1191              * For all the pushed descriptors and classes.
  1192              *  if the class has its own writeObject and readObject methods
  1193              *      call the readObject method
  1194              *  else
  1195              *      invoke the defaultReadObject method
  1196              */
  1197             try {
  1198                 for (spClass = spClass; spClass > spBase; spClass--) {
  1199                     /*
  1200                      * Set current descriptor and corresponding class
  1201                      */
  1202                     currentClassDesc = classdesc[spClass];
  1203                     currentClass = classes[spClass];
  1204                     if (classes[spClass] != null) {
  1205                         /* Read the data from the stream described by the
  1206                          * descriptor and store into the matching class.
  1207                          */
  1209                         ReadObjectState oldState = readObjectState;
  1210                         setState(DEFAULT_STATE);
  1212                         try {
  1214                             // Changed since invokeObjectReader no longer does this.
  1215                             if (currentClassDesc.hasWriteObject()) {
  1217                                 // Read format version
  1218                                 readFormatVersion();
  1220                                 // Read defaultWriteObject indicator
  1221                                 boolean calledDefaultWriteObject = readBoolean();
  1223                                 readObjectState.beginUnmarshalCustomValue(this,
  1224                                                                           calledDefaultWriteObject,
  1225                                                                           (currentClassDesc.readObjectMethod
  1226                                                                            != null));
  1227                             } else {
  1228                                 if (currentClassDesc.hasReadObject())
  1229                                     setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
  1232                             if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) ||
  1233                                 readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) {
  1235                                 // Error case of no readObject and didn't call
  1236                                 // defaultWriteObject handled in default state
  1238                                 ObjectStreamField[] fields =
  1239                                     currentClassDesc.getFieldsNoCopy();
  1240                                 if (fields.length > 0) {
  1241                                     inputClassFields(currentObject, currentClass, fields, sender);
  1245                             if (currentClassDesc.hasWriteObject())
  1246                                 readObjectState.endUnmarshalCustomValue(this);
  1248                         } finally {
  1249                             setState(oldState);
  1252                     } else {
  1254                         // _REVISIT_ : Can we ever get here?
  1255                         /* No local class for this descriptor,
  1256                          * Skip over the data for this class.
  1257                          * like defaultReadObject with a null currentObject.
  1258                          * The code will read the values but discard them.
  1259                          */
  1260                             ObjectStreamField[] fields =
  1261                                 currentClassDesc.getFieldsNoCopy();
  1262                             if (fields.length > 0) {
  1263                                 inputClassFields(null, currentClass, fields, sender);
  1269             } finally {
  1270                                 // Make sure we exit at the same stack level as when we started.
  1271                 spClass = spBase;
  1274         } finally {
  1275             // We've completed deserializing this object.  Any
  1276             // future indirections will be handled correctly at the
  1277             // CDR level.  The ActiveRecursionManager only deals with
  1278             // objects currently being deserialized.
  1279             activeRecursionMgr.removeObject(offset);
  1282         return currentObject;
  1285     // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
  1286     // repositoryID.  It is assumed that the sender will not provide base_value id's for non-serializable
  1287     // classes!
  1288     private Vector getOrderedDescriptions(String repositoryID,
  1289                                           com.sun.org.omg.SendingContext.CodeBase sender) {
  1290         Vector descs = new Vector();
  1292         if (sender == null) {
  1293             return descs;
  1296         FullValueDescription aFVD = sender.meta(repositoryID);
  1297         while (aFVD != null) {
  1298             descs.insertElementAt(aFVD, 0);
  1299             if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
  1300                 aFVD = sender.meta(aFVD.base_value);
  1302             else return descs;
  1305         return descs;
  1308     /**
  1309      * This input method uses FullValueDescriptions retrieved from the sender's runtime to
  1310      * read in the data.  This method is capable of throwing out data not applicable to client's fields.
  1311      * This method handles instances where the reader has a class not sent by the sender, the sender sent
  1312      * a class not present on the reader, and/or the reader's class does not match the sender's class.
  1314      * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
  1315      * indicates custom marsahling than the local type is used to read the data off the wire.  However,
  1316      * if either says custom while the other does not, a MARSHAL error is thrown.  Externalizable is
  1317      * a form of custom marshaling.
  1319      */
  1320     private Object inputObjectUsingFVD(Class clz,
  1321                                        String repositoryID,
  1322                                        com.sun.org.omg.SendingContext.CodeBase sender,
  1323                                        int offset)
  1324         throws IOException, ClassNotFoundException
  1326         int spBase = spClass;   // current top of stack
  1327         try{
  1329             /*
  1330              * Get the descriptor and then class of the incoming object.
  1331              */
  1333             ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
  1334             Class currclass = currentClass = clz;
  1336             /* If Externalizable,
  1337              *  Create an instance and tell it to read its data.
  1338              * else,
  1339              *  Handle it as a serializable class.
  1340              */
  1341             if (currentClassDesc.isExternalizable()) {
  1342                 try {
  1343                     currentObject = (currentClass == null) ?
  1344                         null : currentClassDesc.newInstance();
  1345                     if (currentObject != null) {
  1346                         // Store this object and its beginning position
  1347                         // since there might be indirections to it while
  1348                         // it's been unmarshalled.
  1349                         activeRecursionMgr.addObject(offset, currentObject);
  1351                         // Read format version
  1352                         readFormatVersion();
  1354                         Externalizable ext = (Externalizable)currentObject;
  1355                         ext.readExternal(this);
  1357                 } catch (InvocationTargetException e) {
  1358                     InvalidClassException exc = new InvalidClassException(
  1359                         currentClass.getName(),
  1360                         "InvocationTargetException accessing no-arg constructor");
  1361                     exc.initCause( e ) ;
  1362                     throw exc ;
  1363                 } catch (UnsupportedOperationException e) {
  1364                     InvalidClassException exc = new InvalidClassException(
  1365                         currentClass.getName(),
  1366                         "UnsupportedOperationException accessing no-arg constructor");
  1367                     exc.initCause( e ) ;
  1368                     throw exc ;
  1369                 } catch (InstantiationException e) {
  1370                     InvalidClassException exc = new InvalidClassException(
  1371                         currentClass.getName(),
  1372                         "InstantiationException accessing no-arg constructor");
  1373                     exc.initCause( e ) ;
  1374                     throw exc ;
  1376             } else {
  1377                 /*
  1378                  * This is your basic diff pattern, made simpler
  1379                  * because reordering is not allowed.
  1380                  */
  1381                 for (currdesc = currentClassDesc, currclass = currentClass;
  1382                      currdesc != null && currdesc.isSerializable();   /*sun.4296963 ibm.11861*/
  1384                      currdesc = currdesc.getSuperclass()) {
  1386                     /*
  1387                      * Search the classes to see if the class of this
  1388                      * descriptor appears further up the hierarchy. Until
  1389                      * it's found assume its an inserted class.  If it's
  1390                      * not found, its the descriptor's class that has been
  1391                      * removed.
  1392                      */
  1393                     Class cc = currdesc.forClass();
  1394                     Class cl;
  1395                     for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  1396                         if (cc == cl) {
  1397                             // found a superclass that matches this descriptor
  1398                             break;
  1399                         } else {
  1400                             /* Ignore a class that doesn't match.  No
  1401                              * action is needed since it is already
  1402                              * initialized.
  1403                              */
  1405                     } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
  1406                     /* Test if there is room for this new entry.
  1407                      * If not, double the size of the arrays and copy the contents.
  1408                      */
  1409                     spClass++;
  1410                     if (spClass >= classes.length) {
  1411                         int newlen = classes.length * 2;
  1412                         Class[] newclasses = new Class[newlen];
  1413                         ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  1415                         System.arraycopy(classes, 0,
  1416                                          newclasses, 0,
  1417                                          classes.length);
  1418                         System.arraycopy(classdesc, 0,
  1419                                          newclassdesc, 0,
  1420                                          classes.length);
  1422                         classes = newclasses;
  1423                         classdesc = newclassdesc;
  1426                     if (cl == null) {
  1427                         /* Class not found corresponding to this descriptor.
  1428                          * Pop off all the extra classes pushed.
  1429                          * Push the descriptor and a null class.
  1430                          */
  1431                         classdesc[spClass] = currdesc;
  1432                         classes[spClass] = null;
  1433                     } else {
  1434                         /* Current class descriptor matches current class.
  1435                          * Some classes may have been inserted.
  1436                          * Record the match and advance the class, continue
  1437                          * with the next descriptor.
  1438                          */
  1439                         classdesc[spClass] = currdesc;
  1440                         classes[spClass] = cl;
  1441                         currclass = cl.getSuperclass();
  1443                 } // end : for (currdesc = currentClassDesc, currclass = currentClass;
  1445                 /* Allocate a new object.
  1446                  */
  1447                 try {
  1448                     currentObject = (currentClass == null) ?
  1449                         null : currentClassDesc.newInstance();
  1451                     // Store this object and its beginning position
  1452                     // since there might be indirections to it while
  1453                     // it's been unmarshalled.
  1454                     activeRecursionMgr.addObject(offset, currentObject);
  1455                 } catch (InvocationTargetException e) {
  1456                     InvalidClassException exc = new InvalidClassException(
  1457                         currentClass.getName(),
  1458                         "InvocationTargetException accessing no-arg constructor");
  1459                     exc.initCause( e ) ;
  1460                     throw exc ;
  1461                 } catch (UnsupportedOperationException e) {
  1462                     InvalidClassException exc = new InvalidClassException(
  1463                         currentClass.getName(),
  1464                         "UnsupportedOperationException accessing no-arg constructor");
  1465                     exc.initCause( e ) ;
  1466                     throw exc ;
  1467                 } catch (InstantiationException e) {
  1468                     InvalidClassException exc = new InvalidClassException(
  1469                         currentClass.getName(),
  1470                         "InstantiationException accessing no-arg constructor");
  1471                     exc.initCause( e ) ;
  1472                     throw exc ;
  1475                 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
  1477                 while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
  1478                     FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1479                     // d4365188: backward compatability
  1480                     String repIDForFVD = vhandler.getClassName(fvd.id);
  1481                     String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
  1483                     while ((spClass > spBase) &&
  1484                            (!repIDForFVD.equals(repIDForClass))) {
  1485                         int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
  1486                         if (pos != -1) {
  1487                             spClass = pos;
  1488                             currclass = currentClass = classes[spClass];
  1489                             repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
  1491                         else { // Read and throw away one level of the fvdslist
  1493                             // This seems to mean that the sender had a superclass that
  1494                             // we don't have
  1496                             if (fvd.is_custom) {
  1498                                 readFormatVersion();
  1499                                 boolean calledDefaultWriteObject = readBoolean();
  1501                                 if (calledDefaultWriteObject)
  1502                                     inputClassFields(null, null, null, fvd.members, sender);
  1504                                 if (getStreamFormatVersion() == 2) {
  1506                                     ((ValueInputStream)getOrbStream()).start_value();
  1507                                     ((ValueInputStream)getOrbStream()).end_value();
  1510                                 // WARNING: If stream format version is 1 and there's
  1511                                 // optional data, we'll get some form of exception down
  1512                                 // the line or data corruption.
  1514                             } else {
  1516                                 inputClassFields(null, currentClass, null, fvd.members, sender);
  1519                             if (fvdsList.hasMoreElements()){
  1520                                 fvd = (FullValueDescription)fvdsList.nextElement();
  1521                                 repIDForFVD = vhandler.getClassName(fvd.id);
  1523                             else return currentObject;
  1527                     currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
  1529                     if (!repIDForClass.equals("java.lang.Object")) {
  1531                         // If the sender used custom marshaling, then it should have put
  1532                         // the two bytes on the wire indicating stream format version
  1533                         // and whether or not the writeObject method called
  1534                         // defaultWriteObject/writeFields.
  1536                         ReadObjectState oldState = readObjectState;
  1537                         setState(DEFAULT_STATE);
  1539                         try {
  1541                             if (fvd.is_custom) {
  1543                                 // Read format version
  1544                                 readFormatVersion();
  1546                                 // Read defaultWriteObject indicator
  1547                                 boolean calledDefaultWriteObject = readBoolean();
  1549                                 readObjectState.beginUnmarshalCustomValue(this,
  1550                                                                           calledDefaultWriteObject,
  1551                                                                           (currentClassDesc.readObjectMethod
  1552                                                                            != null));
  1555                             boolean usedReadObject = false;
  1557                             // Always use readObject if it exists, and fall back to default
  1558                             // unmarshaling if it doesn't.
  1559                             try {
  1561                                 if (!fvd.is_custom && currentClassDesc.hasReadObject())
  1562                                     setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
  1564                                 // See the definition of defaultReadObjectFVDMembers
  1565                                 // for more information.  This concerns making sure
  1566                                 // we use the remote FVD's members in defaultReadObject.
  1567                                 defaultReadObjectFVDMembers = fvd.members;
  1568                                 usedReadObject = invokeObjectReader(currentClassDesc,
  1569                                                                     currentObject,
  1570                                                                     currentClass);
  1572                             } finally {
  1573                                 defaultReadObjectFVDMembers = null;
  1576                             // Note that the !usedReadObject !calledDefaultWriteObject
  1577                             // case is handled by the beginUnmarshalCustomValue method
  1578                             // of the default state
  1579                             if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT)
  1580                                 inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
  1582                             if (fvd.is_custom)
  1583                                 readObjectState.endUnmarshalCustomValue(this);
  1585                         } finally {
  1586                             setState(oldState);
  1589                         currclass = currentClass = classes[--spClass];
  1591                     } else {
  1593                         // The remaining hierarchy of the local class does not match the sender's FVD.
  1594                         // So, use remaining FVDs to read data off wire.  If any remaining FVDs indicate
  1595                         // custom marshaling, throw MARSHAL error.
  1596                         inputClassFields(null, currentClass, null, fvd.members, sender);
  1598                         while (fvdsList.hasMoreElements()){
  1599                             fvd = (FullValueDescription)fvdsList.nextElement();
  1601                             if (fvd.is_custom)
  1602                                 skipCustomUsingFVD(fvd.members, sender);
  1603                             else
  1604                                 inputClassFields(null, currentClass, null, fvd.members, sender);
  1609                 } // end : while(fvdsList.hasMoreElements())
  1610                 while (fvdsList.hasMoreElements()){
  1612                     FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1613                     if (fvd.is_custom)
  1614                         skipCustomUsingFVD(fvd.members, sender);
  1615                     else
  1616                         throwAwayData(fvd.members, sender);
  1620             return currentObject;
  1622         finally {
  1623                 // Make sure we exit at the same stack level as when we started.
  1624                 spClass = spBase;
  1626                 // We've completed deserializing this object.  Any
  1627                 // future indirections will be handled correctly at the
  1628                 // CDR level.  The ActiveRecursionManager only deals with
  1629                 // objects currently being deserialized.
  1630                 activeRecursionMgr.removeObject(offset);
  1635     /**
  1636      * This input method uses FullValueDescriptions retrieved from the sender's runtime to
  1637      * read in the data.  This method is capable of throwing out data not applicable to client's fields.
  1639      * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
  1640      * indicates custom marsahling than the local type is used to read the data off the wire.  However,
  1641      * if either says custom while the other does not, a MARSHAL error is thrown.  Externalizable is
  1642      * a form of custom marshaling.
  1644      */
  1645     private Object skipObjectUsingFVD(String repositoryID,
  1646                                       com.sun.org.omg.SendingContext.CodeBase sender)
  1647         throws IOException, ClassNotFoundException
  1650         Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
  1652         while(fvdsList.hasMoreElements()) {
  1653             FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1654             String repIDForFVD = vhandler.getClassName(fvd.id);
  1656             if (!repIDForFVD.equals("java.lang.Object")) {
  1657                 if (fvd.is_custom) {
  1659                     readFormatVersion();
  1661                     boolean calledDefaultWriteObject = readBoolean();
  1663                     if (calledDefaultWriteObject)
  1664                         inputClassFields(null, null, null, fvd.members, sender);
  1666                     if (getStreamFormatVersion() == 2) {
  1668                         ((ValueInputStream)getOrbStream()).start_value();
  1669                         ((ValueInputStream)getOrbStream()).end_value();
  1672                     // WARNING: If stream format version is 1 and there's
  1673                     // optional data, we'll get some form of exception down
  1674                     // the line.
  1676                 } else {
  1677                     // Use default marshaling
  1678                     inputClassFields(null, null, null, fvd.members, sender);
  1682         } // end : while(fvdsList.hasMoreElements())
  1683         return null;
  1687     ///////////////////
  1689     private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){
  1691         for (int i = _spClass; i > _spBase; i--){
  1692             if (classname.equals(classes[i].getName())) {
  1693                 return i;
  1697         return -1;
  1700     /*
  1701      * Invoke the readObject method if present.  Assumes that in the case of custom
  1702      * marshaling, the format version and defaultWriteObject indicator were already
  1703      * removed.
  1704      */
  1705     private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass)
  1706         throws InvalidClassException, StreamCorruptedException,
  1707                ClassNotFoundException, IOException
  1709         if (osc.readObjectMethod == null) {
  1710             return false;
  1713         try {
  1714             osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
  1715             return true;
  1716         } catch (InvocationTargetException e) {
  1717             Throwable t = e.getTargetException();
  1718             if (t instanceof ClassNotFoundException)
  1719                 throw (ClassNotFoundException)t;
  1720             else if (t instanceof IOException)
  1721                 throw (IOException)t;
  1722             else if (t instanceof RuntimeException)
  1723                 throw (RuntimeException) t;
  1724             else if (t instanceof Error)
  1725                 throw (Error) t;
  1726             else
  1727                 // XXX I18N, logging needed.
  1728                 throw new Error("internal error");
  1729         } catch (IllegalAccessException e) {
  1730             return false;
  1734     /*
  1735      * Reset the stream to be just like it was after the constructor.
  1736      */
  1737     private void resetStream() throws IOException {
  1739         if (classes == null)
  1740             classes = new Class[20];
  1741         else {
  1742             for (int i = 0; i < classes.length; i++)
  1743                 classes[i] = null;
  1745         if (classdesc == null)
  1746             classdesc = new ObjectStreamClass[20];
  1747         else {
  1748             for (int i = 0; i < classdesc.length; i++)
  1749                 classdesc[i] = null;
  1751         spClass = 0;
  1753         if (callbacks != null)
  1754             callbacks.setSize(0);       // discard any pending callbacks
  1757     /**
  1758      * Factored out of inputClassFields  This reads a primitive value and sets it
  1759      * in the field of o described by the ObjectStreamField field.
  1761      * Note that reflection cannot be used here, because reflection cannot be used
  1762      * to set final fields.
  1763      */
  1764     private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field)
  1765         throws InvalidClassException, IOException {
  1767         try {
  1768             switch (field.getTypeCode()) {
  1769                 case 'B':
  1770                     byte byteValue = orbStream.read_octet();
  1771                     bridge.putByte( o, field.getFieldID(), byteValue ) ;
  1772                     //reflective code: field.getField().setByte( o, byteValue ) ;
  1773                     break;
  1774                 case 'Z':
  1775                     boolean booleanValue = orbStream.read_boolean();
  1776                     bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
  1777                     //reflective code: field.getField().setBoolean( o, booleanValue ) ;
  1778                     break;
  1779                 case 'C':
  1780                     char charValue = orbStream.read_wchar();
  1781                     bridge.putChar( o, field.getFieldID(), charValue ) ;
  1782                     //reflective code: field.getField().setChar( o, charValue ) ;
  1783                     break;
  1784                 case 'S':
  1785                     short shortValue = orbStream.read_short();
  1786                     bridge.putShort( o, field.getFieldID(), shortValue ) ;
  1787                     //reflective code: field.getField().setShort( o, shortValue ) ;
  1788                     break;
  1789                 case 'I':
  1790                     int intValue = orbStream.read_long();
  1791                     bridge.putInt( o, field.getFieldID(), intValue ) ;
  1792                     //reflective code: field.getField().setInt( o, intValue ) ;
  1793                     break;
  1794                 case 'J':
  1795                     long longValue = orbStream.read_longlong();
  1796                     bridge.putLong( o, field.getFieldID(), longValue ) ;
  1797                     //reflective code: field.getField().setLong( o, longValue ) ;
  1798                     break;
  1799                 case 'F' :
  1800                     float floatValue = orbStream.read_float();
  1801                     bridge.putFloat( o, field.getFieldID(), floatValue ) ;
  1802                     //reflective code: field.getField().setFloat( o, floatValue ) ;
  1803                     break;
  1804                 case 'D' :
  1805                     double doubleValue = orbStream.read_double();
  1806                     bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
  1807                     //reflective code: field.getField().setDouble( o, doubleValue ) ;
  1808                     break;
  1809                 default:
  1810                     // XXX I18N, logging needed.
  1811                     throw new InvalidClassException(cl.getName());
  1813         } catch (IllegalArgumentException e) {
  1814             /* This case should never happen. If the field types
  1815                are not the same, InvalidClassException is raised when
  1816                matching the local class to the serialized ObjectStreamClass. */
  1817             ClassCastException cce = new ClassCastException("Assigning instance of class " +
  1818                                          field.getType().getName() +
  1819                                          " to field " +
  1820                                          currentClassDesc.getName() + '#' +
  1821                                          field.getField().getName());
  1822             cce.initCause( e ) ;
  1823             throw cce ;
  1827     private Object inputObjectField(org.omg.CORBA.ValueMember field,
  1828                                     com.sun.org.omg.SendingContext.CodeBase sender)
  1829         throws IndirectionException, ClassNotFoundException, IOException,
  1830                StreamCorruptedException {
  1832         Object objectValue = null;
  1833         Class type = null;
  1834         String id = field.id;
  1836         try {
  1837             type = vhandler.getClassFromType(id);
  1838         } catch(ClassNotFoundException cnfe) {
  1839             // Make sure type = null
  1840             type = null;
  1843         String signature = null;
  1844         if (type != null)
  1845             signature = ValueUtility.getSignature(field);
  1847         if (signature != null && (signature.equals("Ljava/lang/Object;") ||
  1848                                   signature.equals("Ljava/io/Serializable;") ||
  1849                                   signature.equals("Ljava/io/Externalizable;"))) {
  1850             objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
  1851         } else {
  1852             // Decide what method call to make based on the type. If
  1853             // it is a type for which we need to load a stub, convert
  1854             // the type to the correct stub type.
  1855             //
  1856             // NOTE : Since FullValueDescription does not allow us
  1857             // to ask whether something is an interface we do not
  1858             // have the ability to optimize this check.
  1860             int callType = ValueHandlerImpl.kValueType;
  1862             if (!vhandler.isSequence(id)) {
  1864                 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
  1866                     // RMI Object reference...
  1867                     callType = ValueHandlerImpl.kRemoteType;
  1869                 } else {
  1871                     // REVISIT.  If we don't have the local class,
  1872                     // we should probably verify that it's an RMI type,
  1873                     // query the remote FVD, and use is_abstract.
  1874                     // Our FVD seems to get NullPointerExceptions for any
  1875                     // non-RMI types.
  1877                     // This uses the local class in the same way as
  1878                     // inputObjectField(ObjectStreamField) does.  REVISIT
  1879                     // inputObjectField(ObjectStreamField)'s loadStubClass
  1880                     // logic.  Assumption is that the given type cannot
  1881                     // evolve to become a CORBA abstract interface or
  1882                     // a RMI abstract interface.
  1884                     if (type != null && type.isInterface() &&
  1885                         (vhandler.isAbstractBase(type) ||
  1886                          ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
  1888                         callType = ValueHandlerImpl.kAbstractType;
  1893             // Now that we have used the FVD of the field to determine the proper course
  1894             // of action, it is ok to use the type (Class) from this point forward since
  1895             // the rep. id for this read will also follow on the wire.
  1897             switch (callType) {
  1898                 case ValueHandlerImpl.kRemoteType:
  1899                     if (type != null)
  1900                         objectValue = Utility.readObjectAndNarrow(orbStream, type);
  1901                     else
  1902                         objectValue = orbStream.read_Object();
  1903                     break;
  1904                 case ValueHandlerImpl.kAbstractType:
  1905                     if (type != null)
  1906                         objectValue = Utility.readAbstractAndNarrow(orbStream, type);
  1907                     else
  1908                         objectValue = orbStream.read_abstract_interface();
  1909                     break;
  1910                 case ValueHandlerImpl.kValueType:
  1911                     if (type != null)
  1912                         objectValue = orbStream.read_value(type);
  1913                     else
  1914                                             objectValue = orbStream.read_value();
  1915                     break;
  1916                 default:
  1917                     // XXX I18N, logging needed.
  1918                     throw new StreamCorruptedException("Unknown callType: " + callType);
  1922         return objectValue;
  1925     /**
  1926      * Factored out of inputClassFields and reused in
  1927      * inputCurrentClassFieldsForReadFields.
  1929      * Reads the field (which of an Object type as opposed to a primitive)
  1930      * described by ObjectStreamField field and returns it.
  1931      */
  1932     private Object inputObjectField(ObjectStreamField field)
  1933         throws InvalidClassException, StreamCorruptedException,
  1934                ClassNotFoundException, IndirectionException, IOException {
  1936         if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
  1937             return javax.rmi.CORBA.Util.readAny(orbStream);
  1940         Object objectValue = null;
  1942         // fields have an API to provide the actual class
  1943         // corresponding to the data type
  1944         // Class type = osc.forClass();
  1945         Class fieldType = field.getType();
  1946         Class actualType = fieldType; // This may change if stub loaded.
  1948         // Decide what method call to make based on the fieldType. If
  1949         // it is a type for which we need to load a stub, convert
  1950         // the type to the correct stub type.
  1952         int callType = ValueHandlerImpl.kValueType;
  1953         boolean narrow = false;
  1955         if (fieldType.isInterface()) {
  1956             boolean loadStubClass = false;
  1958             if (java.rmi.Remote.class.isAssignableFrom(fieldType)) {
  1960                 // RMI Object reference...
  1961                 callType = ValueHandlerImpl.kRemoteType;
  1963             } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){
  1965                 // IDL Object reference...
  1966                 callType = ValueHandlerImpl.kRemoteType;
  1967                 loadStubClass = true;
  1969             } else if (vhandler.isAbstractBase(fieldType)) {
  1970                 // IDL Abstract Object reference...
  1972                 callType = ValueHandlerImpl.kAbstractType;
  1973                 loadStubClass = true;
  1974             } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
  1975                 // RMI Abstract Object reference...
  1977                 callType = ValueHandlerImpl.kAbstractType;
  1980             if (loadStubClass) {
  1981                 try {
  1982                     String codebase = Util.getCodebase(fieldType);
  1983                     String repID = vhandler.createForAnyType(fieldType);
  1984                     Class stubType =
  1985                         Utility.loadStubClass(repID, codebase, fieldType);
  1986                     actualType = stubType;
  1987                 } catch (ClassNotFoundException e) {
  1988                     narrow = true;
  1990             } else {
  1991                 narrow = true;
  1995         switch (callType) {
  1996             case ValueHandlerImpl.kRemoteType:
  1997                 if (!narrow)
  1998                     objectValue = (Object)orbStream.read_Object(actualType);
  1999                 else
  2000                     objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
  2001                 break;
  2002             case ValueHandlerImpl.kAbstractType:
  2003                 if (!narrow)
  2004                     objectValue = (Object)orbStream.read_abstract_interface(actualType);
  2005                 else
  2006                     objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
  2007                 break;
  2008             case ValueHandlerImpl.kValueType:
  2009                 objectValue = (Object)orbStream.read_value(actualType);
  2010                 break;
  2011             default:
  2012                 // XXX I18N, logging needed.
  2013                 throw new StreamCorruptedException("Unknown callType: " + callType);
  2016         return objectValue;
  2019     private final boolean mustUseRemoteValueMembers() {
  2020         return defaultReadObjectFVDMembers != null;
  2023     void readFields(java.util.Map fieldToValueMap)
  2024         throws InvalidClassException, StreamCorruptedException,
  2025                ClassNotFoundException, IOException {
  2027         if (mustUseRemoteValueMembers()) {
  2028             inputRemoteMembersForReadFields(fieldToValueMap);
  2029         } else
  2030             inputCurrentClassFieldsForReadFields(fieldToValueMap);
  2033     private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
  2034         throws InvalidClassException, StreamCorruptedException,
  2035                ClassNotFoundException, IOException {
  2037         // Must have this local variable since defaultReadObjectFVDMembers
  2038         // may get mangled by recursion.
  2039         ValueMember fields[] = defaultReadObjectFVDMembers;
  2041         try {
  2043             for (int i = 0; i < fields.length; i++) {
  2045                 switch (fields[i].type.kind().value()) {
  2047                 case TCKind._tk_octet:
  2048                     byte byteValue = orbStream.read_octet();
  2049                     fieldToValueMap.put(fields[i].name, new Byte(byteValue));
  2050                     break;
  2051                 case TCKind._tk_boolean:
  2052                     boolean booleanValue = orbStream.read_boolean();
  2053                     fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
  2054                     break;
  2055                 case TCKind._tk_char:
  2056                     // Backwards compatibility.  Older Sun ORBs sent
  2057                     // _tk_char even though they read and wrote wchars
  2058                     // correctly.
  2059                     //
  2060                     // Fall through to the _tk_wchar case.
  2061                 case TCKind._tk_wchar:
  2062                     char charValue = orbStream.read_wchar();
  2063                     fieldToValueMap.put(fields[i].name, new Character(charValue));
  2064                     break;
  2065                 case TCKind._tk_short:
  2066                     short shortValue = orbStream.read_short();
  2067                     fieldToValueMap.put(fields[i].name, new Short(shortValue));
  2068                     break;
  2069                 case TCKind._tk_long:
  2070                     int intValue = orbStream.read_long();
  2071                     fieldToValueMap.put(fields[i].name, new Integer(intValue));
  2072                     break;
  2073                 case TCKind._tk_longlong:
  2074                     long longValue = orbStream.read_longlong();
  2075                     fieldToValueMap.put(fields[i].name, new Long(longValue));
  2076                     break;
  2077                 case TCKind._tk_float:
  2078                     float floatValue = orbStream.read_float();
  2079                     fieldToValueMap.put(fields[i].name, new Float(floatValue));
  2080                     break;
  2081                 case TCKind._tk_double:
  2082                     double doubleValue = orbStream.read_double();
  2083                     fieldToValueMap.put(fields[i].name, new Double(doubleValue));
  2084                     break;
  2085                 case TCKind._tk_value:
  2086                 case TCKind._tk_objref:
  2087                 case TCKind._tk_value_box:
  2088                     Object objectValue = null;
  2089                     try {
  2090                         objectValue = inputObjectField(fields[i],
  2091                                                        cbSender);
  2093                     } catch (IndirectionException cdrie) {
  2094                         // The CDR stream had never seen the given offset before,
  2095                         // so check the recursion manager (it will throw an
  2096                         // IOException if it doesn't have a reference, either).
  2097                         objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2100                     fieldToValueMap.put(fields[i].name, objectValue);
  2101                     break;
  2102                 default:
  2103                     // XXX I18N, logging needed.
  2104                     throw new StreamCorruptedException("Unknown kind: "
  2105                                                        + fields[i].type.kind().value());
  2108         } catch (Throwable t) {
  2109             StreamCorruptedException result = new StreamCorruptedException(t.getMessage());
  2110             result.initCause(t);
  2111             throw result;
  2115     /**
  2116      * Called from InputStreamHook.
  2118      * Reads the fields of the current class (could be the ones
  2119      * queried from the remote FVD) and puts them in
  2120      * the given Map, name to value.  Wraps primitives in the
  2121      * corresponding java.lang Objects.
  2122      */
  2123     private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
  2124         throws InvalidClassException, StreamCorruptedException,
  2125                ClassNotFoundException, IOException {
  2127         ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
  2129         int primFields = fields.length - currentClassDesc.objFields;
  2131         // Handle the primitives first
  2132         for (int i = 0; i < primFields; ++i) {
  2134             switch (fields[i].getTypeCode()) {
  2135                 case 'B':
  2136                     byte byteValue = orbStream.read_octet();
  2137                     fieldToValueMap.put(fields[i].getName(),
  2138                                         new Byte(byteValue));
  2139                     break;
  2140                 case 'Z':
  2141                    boolean booleanValue = orbStream.read_boolean();
  2142                    fieldToValueMap.put(fields[i].getName(),
  2143                                        new Boolean(booleanValue));
  2144                    break;
  2145                 case 'C':
  2146                     char charValue = orbStream.read_wchar();
  2147                     fieldToValueMap.put(fields[i].getName(),
  2148                                         new Character(charValue));
  2149                     break;
  2150                 case 'S':
  2151                     short shortValue = orbStream.read_short();
  2152                     fieldToValueMap.put(fields[i].getName(),
  2153                                         new Short(shortValue));
  2154                     break;
  2155                 case 'I':
  2156                     int intValue = orbStream.read_long();
  2157                     fieldToValueMap.put(fields[i].getName(),
  2158                                         new Integer(intValue));
  2159                     break;
  2160                 case 'J':
  2161                     long longValue = orbStream.read_longlong();
  2162                     fieldToValueMap.put(fields[i].getName(),
  2163                                         new Long(longValue));
  2164                     break;
  2165                 case 'F' :
  2166                     float floatValue = orbStream.read_float();
  2167                     fieldToValueMap.put(fields[i].getName(),
  2168                                         new Float(floatValue));
  2169                     break;
  2170                 case 'D' :
  2171                     double doubleValue = orbStream.read_double();
  2172                     fieldToValueMap.put(fields[i].getName(),
  2173                                         new Double(doubleValue));
  2174                     break;
  2175                 default:
  2176                     // XXX I18N, logging needed.
  2177                     throw new InvalidClassException(currentClassDesc.getName());
  2181         /* Read and set object fields from the input stream. */
  2182         if (currentClassDesc.objFields > 0) {
  2183             for (int i = primFields; i < fields.length; i++) {
  2184                 Object objectValue = null;
  2185                 try {
  2186                     objectValue = inputObjectField(fields[i]);
  2187                 } catch(IndirectionException cdrie) {
  2188                     // The CDR stream had never seen the given offset before,
  2189                     // so check the recursion manager (it will throw an
  2190                     // IOException if it doesn't have a reference, either).
  2191                     objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2194                 fieldToValueMap.put(fields[i].getName(), objectValue);
  2199     /*
  2200      * Read the fields of the specified class from the input stream and set
  2201      * the values of the fields in the specified object. If the specified
  2202      * object is null, just consume the fields without setting any values. If
  2203      * any ObjectStreamField does not have a reflected Field, don't try to set
  2204      * that field in the object.
  2206      * REVISIT -- This code doesn't do what the comment says to when
  2207      * getField() is null!
  2208      */
  2209     private void inputClassFields(Object o, Class cl,
  2210                                   ObjectStreamField[] fields,
  2211                                   com.sun.org.omg.SendingContext.CodeBase sender)
  2212         throws InvalidClassException, StreamCorruptedException,
  2213                ClassNotFoundException, IOException
  2216         int primFields = fields.length - currentClassDesc.objFields;
  2218         if (o != null) {
  2219             for (int i = 0; i < primFields; ++i) {
  2220                 if (fields[i].getField() == null)
  2221                     continue;
  2223                 inputPrimitiveField(o, cl, fields[i]);
  2227         /* Read and set object fields from the input stream. */
  2228         if (currentClassDesc.objFields > 0) {
  2229             for (int i = primFields; i < fields.length; i++) {
  2230                 Object objectValue = null;
  2232                 try {
  2233                     objectValue = inputObjectField(fields[i]);
  2234                 } catch(IndirectionException cdrie) {
  2235                     // The CDR stream had never seen the given offset before,
  2236                     // so check the recursion manager (it will throw an
  2237                     // IOException if it doesn't have a reference, either).
  2238                     objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2241                 if ((o == null) || (fields[i].getField() == null)) {
  2242                     continue;
  2245                 try {
  2246                     bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
  2247                     // reflective code: fields[i].getField().set( o, objectValue ) ;
  2248                 } catch (IllegalArgumentException e) {
  2249                     ClassCastException exc = new ClassCastException("Assigning instance of class " +
  2250                                                  objectValue.getClass().getName() +
  2251                                                  " to field " +
  2252                                                  currentClassDesc.getName() +
  2253                                                  '#' +
  2254                                                  fields[i].getField().getName());
  2255                     exc.initCause( e ) ;
  2256                     throw exc ;
  2258             } // end : for loop
  2262     /*
  2263      * Read the fields of the specified class from the input stream and set
  2264      * the values of the fields in the specified object. If the specified
  2265      * object is null, just consume the fields without setting any values. If
  2266      * any ObjectStreamField does not have a reflected Field, don't try to set
  2267      * that field in the object.
  2268      */
  2269     private void inputClassFields(Object o, Class cl,
  2270                                   ObjectStreamClass osc,
  2271                                   ValueMember[] fields,
  2272                                   com.sun.org.omg.SendingContext.CodeBase sender)
  2273         throws InvalidClassException, StreamCorruptedException,
  2274                ClassNotFoundException, IOException
  2276         try{
  2277             for (int i = 0; i < fields.length; ++i) {
  2278                 try {
  2279                     switch (fields[i].type.kind().value()) {
  2280                     case TCKind._tk_octet:
  2281                         byte byteValue = orbStream.read_octet();
  2282                         if ((o != null) && osc.hasField(fields[i]))
  2283                         setByteField(o, cl, fields[i].name, byteValue);
  2284                         break;
  2285                     case TCKind._tk_boolean:
  2286                         boolean booleanValue = orbStream.read_boolean();
  2287                         if ((o != null) && osc.hasField(fields[i]))
  2288                         setBooleanField(o, cl, fields[i].name, booleanValue);
  2289                         break;
  2290                     case TCKind._tk_char:
  2291                         // Backwards compatibility.  Older Sun ORBs sent
  2292                         // _tk_char even though they read and wrote wchars
  2293                         // correctly.
  2294                         //
  2295                         // Fall through to the _tk_wchar case.
  2296                     case TCKind._tk_wchar:
  2297                         char charValue = orbStream.read_wchar();
  2298                         if ((o != null) && osc.hasField(fields[i]))
  2299                         setCharField(o, cl, fields[i].name, charValue);
  2300                         break;
  2301                     case TCKind._tk_short:
  2302                         short shortValue = orbStream.read_short();
  2303                         if ((o != null) && osc.hasField(fields[i]))
  2304                         setShortField(o, cl, fields[i].name, shortValue);
  2305                         break;
  2306                     case TCKind._tk_long:
  2307                         int intValue = orbStream.read_long();
  2308                         if ((o != null) && osc.hasField(fields[i]))
  2309                         setIntField(o, cl, fields[i].name, intValue);
  2310                         break;
  2311                     case TCKind._tk_longlong:
  2312                         long longValue = orbStream.read_longlong();
  2313                         if ((o != null) && osc.hasField(fields[i]))
  2314                         setLongField(o, cl, fields[i].name, longValue);
  2315                         break;
  2316                     case TCKind._tk_float:
  2317                         float floatValue = orbStream.read_float();
  2318                         if ((o != null) && osc.hasField(fields[i]))
  2319                         setFloatField(o, cl, fields[i].name, floatValue);
  2320                         break;
  2321                     case TCKind._tk_double:
  2322                         double doubleValue = orbStream.read_double();
  2323                         if ((o != null) && osc.hasField(fields[i]))
  2324                         setDoubleField(o, cl, fields[i].name, doubleValue);
  2325                         break;
  2326                     case TCKind._tk_value:
  2327                     case TCKind._tk_objref:
  2328                     case TCKind._tk_value_box:
  2329                         Object objectValue = null;
  2330                         try {
  2331                             objectValue = inputObjectField(fields[i], sender);
  2332                         } catch (IndirectionException cdrie) {
  2333                             // The CDR stream had never seen the given offset before,
  2334                             // so check the recursion manager (it will throw an
  2335                             // IOException if it doesn't have a reference, either).
  2336                             objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2339                         if (o == null)
  2340                             continue;
  2341                         try {
  2342                             if (osc.hasField(fields[i])){
  2343                                 setObjectField(o,
  2344                                                cl,
  2345                                                fields[i].name,
  2346                                                objectValue);
  2347                             } else {
  2348                                 // REVISIT.  Convert to a log message.
  2349                                 // This is a normal case when fields have
  2350                                 // been added as part of evolution, but
  2351                                 // silently skipping can make it hard to
  2352                                 // debug if there's an error
  2353 //                                 System.out.println("**** warning, not setting field: "
  2354 //                                                    + fields[i].name
  2355 //                                                    + " since not on class "
  2356 //                                                    + osc.getName());
  2359                         } catch (IllegalArgumentException e) {
  2360                             // XXX I18N, logging needed.
  2361                             ClassCastException cce = new ClassCastException("Assigning instance of class " +
  2362                                 objectValue.getClass().getName() + " to field " + fields[i].name);
  2363                             cce.initCause(e) ;
  2364                             throw cce ;
  2366                         break;
  2367                     default:
  2368                         // XXX I18N, logging needed.
  2369                         throw new StreamCorruptedException("Unknown kind: "
  2370                                                            + fields[i].type.kind().value());
  2372                 } catch (IllegalArgumentException e) {
  2373                     /* This case should never happen. If the field types
  2374                        are not the same, InvalidClassException is raised when
  2375                        matching the local class to the serialized ObjectStreamClass. */
  2376                     // XXX I18N, logging needed.
  2377                     ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id +
  2378                         " to field " + currentClassDesc.getName() + '#' + fields[i].name);
  2379                     cce.initCause( e ) ;
  2380                     throw cce ;
  2383         } catch(Throwable t){
  2384             // XXX I18N, logging needed.
  2385             StreamCorruptedException sce = new StreamCorruptedException(t.getMessage());
  2386             sce.initCause(t) ;
  2387             throw sce ;
  2391     private void skipCustomUsingFVD(ValueMember[] fields,
  2392                                     com.sun.org.omg.SendingContext.CodeBase sender)
  2393                                     throws InvalidClassException, StreamCorruptedException,
  2394                                            ClassNotFoundException, IOException
  2396         readFormatVersion();
  2397         boolean calledDefaultWriteObject = readBoolean();
  2399         if (calledDefaultWriteObject)
  2400             throwAwayData(fields, sender);
  2402         if (getStreamFormatVersion() == 2) {
  2404             ((ValueInputStream)getOrbStream()).start_value();
  2405             ((ValueInputStream)getOrbStream()).end_value();
  2409     /*
  2410      * Read the fields of the specified class from the input stream throw data away.
  2411      * This must handle same switch logic as above.
  2412      */
  2413     private void throwAwayData(ValueMember[] fields,
  2414                                com.sun.org.omg.SendingContext.CodeBase sender)
  2415         throws InvalidClassException, StreamCorruptedException,
  2416                ClassNotFoundException, IOException
  2418         for (int i = 0; i < fields.length; ++i) {
  2420             try {
  2422                 switch (fields[i].type.kind().value()) {
  2423                 case TCKind._tk_octet:
  2424                     orbStream.read_octet();
  2425                     break;
  2426                 case TCKind._tk_boolean:
  2427                     orbStream.read_boolean();
  2428                     break;
  2429                 case TCKind._tk_char:
  2430                     // Backwards compatibility.  Older Sun ORBs sent
  2431                     // _tk_char even though they read and wrote wchars
  2432                     // correctly.
  2433                     //
  2434                     // Fall through to the _tk_wchar case.
  2435                 case TCKind._tk_wchar:
  2436                     orbStream.read_wchar();
  2437                     break;
  2438                 case TCKind._tk_short:
  2439                     orbStream.read_short();
  2440                     break;
  2441                 case TCKind._tk_long:
  2442                     orbStream.read_long();
  2443                     break;
  2444                 case TCKind._tk_longlong:
  2445                     orbStream.read_longlong();
  2446                     break;
  2447                 case TCKind._tk_float:
  2448                     orbStream.read_float();
  2449                     break;
  2450                 case TCKind._tk_double:
  2451                     orbStream.read_double();
  2452                     break;
  2453                 case TCKind._tk_value:
  2454                 case TCKind._tk_objref:
  2455                 case TCKind._tk_value_box:
  2456                     Class type = null;
  2457                     String id = fields[i].id;
  2459                     try {
  2460                         type = vhandler.getClassFromType(id);
  2462                     catch(ClassNotFoundException cnfe){
  2463                         // Make sure type = null
  2464                         type = null;
  2466                     String signature = null;
  2467                     if (type != null)
  2468                         signature = ValueUtility.getSignature(fields[i]);
  2470                     // Read value
  2471                     try {
  2472                         if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
  2473                                                      signature.equals("Ljava/io/Serializable;") ||
  2474                                                      signature.equals("Ljava/io/Externalizable;")) ) {
  2475                             javax.rmi.CORBA.Util.readAny(orbStream);
  2477                         else {
  2478                             // Decide what method call to make based on the type.
  2479                             //
  2480                             // NOTE : Since FullValueDescription does not allow us
  2481                             // to ask whether something is an interface we do not
  2482                             // have the ability to optimize this check.
  2484                             int callType = ValueHandlerImpl.kValueType;
  2486                             if (!vhandler.isSequence(id)) {
  2487                                 FullValueDescription fieldFVD = sender.meta(fields[i].id);
  2488                                 if (kRemoteTypeCode == fields[i].type) {
  2490                                     // RMI Object reference...
  2491                                     callType = ValueHandlerImpl.kRemoteType;
  2492                                 } else if (fieldFVD.is_abstract) {
  2493                                     // RMI Abstract Object reference...
  2495                                     callType = ValueHandlerImpl.kAbstractType;
  2499                             // Now that we have used the FVD of the field to determine the proper course
  2500                             // of action, it is ok to use the type (Class) from this point forward since
  2501                             // the rep. id for this read will also follow on the wire.
  2503                             switch (callType) {
  2504                             case ValueHandlerImpl.kRemoteType:
  2505                                 orbStream.read_Object();
  2506                                 break;
  2507                             case ValueHandlerImpl.kAbstractType:
  2508                                 orbStream.read_abstract_interface();
  2509                                 break;
  2510                             case ValueHandlerImpl.kValueType:
  2511                                 if (type != null) {
  2512                                     orbStream.read_value(type);
  2513                                 } else {
  2514                                     orbStream.read_value();
  2516                                 break;
  2517                             default:
  2518                                 // XXX I18N, logging needed.
  2519                                 throw new StreamCorruptedException("Unknown callType: "
  2520                                                                    + callType);
  2525                     catch(IndirectionException cdrie) {
  2526                         // Since we are throwing this away, don't bother handling recursion.
  2527                         continue;
  2530                     break;
  2531                 default:
  2532                     // XXX I18N, logging needed.
  2533                     throw new StreamCorruptedException("Unknown kind: "
  2534                                                        + fields[i].type.kind().value());
  2537             } catch (IllegalArgumentException e) {
  2538                 /* This case should never happen. If the field types
  2539                    are not the same, InvalidClassException is raised when
  2540                    matching the local class to the serialized ObjectStreamClass. */
  2541                 // XXX I18N, logging needed.
  2542                 ClassCastException cce = new ClassCastException("Assigning instance of class " +
  2543                     fields[i].id + " to field " + currentClassDesc.getName() +
  2544                     '#' + fields[i].name);
  2545                 cce.initCause(e) ;
  2546                 throw cce ;
  2552     private static void setObjectField(Object o, Class c, String fieldName, Object v)
  2554         try {
  2555             Field fld = c.getDeclaredField( fieldName ) ;
  2556             long key = bridge.objectFieldOffset( fld ) ;
  2557             bridge.putObject( o, key, v ) ;
  2558         } catch (Exception e) {
  2559             throw utilWrapper.errorSetObjectField( e, fieldName,
  2560                 o.toString(),
  2561                 v.toString() ) ;
  2565     private static void setBooleanField(Object o, Class c, String fieldName, boolean v)
  2567         try {
  2568             Field fld = c.getDeclaredField( fieldName ) ;
  2569             long key = bridge.objectFieldOffset( fld ) ;
  2570             bridge.putBoolean( o, key, v ) ;
  2571         } catch (Exception e) {
  2572             throw utilWrapper.errorSetBooleanField( e, fieldName,
  2573                 o.toString(),
  2574                 new Boolean(v) ) ;
  2578     private static void setByteField(Object o, Class c, String fieldName, byte v)
  2580         try {
  2581             Field fld = c.getDeclaredField( fieldName ) ;
  2582             long key = bridge.objectFieldOffset( fld ) ;
  2583             bridge.putByte( o, key, v ) ;
  2584         } catch (Exception e) {
  2585             throw utilWrapper.errorSetByteField( e, fieldName,
  2586                 o.toString(),
  2587                 new Byte(v) ) ;
  2591     private static void setCharField(Object o, Class c, String fieldName, char v)
  2593         try {
  2594             Field fld = c.getDeclaredField( fieldName ) ;
  2595             long key = bridge.objectFieldOffset( fld ) ;
  2596             bridge.putChar( o, key, v ) ;
  2597         } catch (Exception e) {
  2598             throw utilWrapper.errorSetCharField( e, fieldName,
  2599                 o.toString(),
  2600                 new Character(v) ) ;
  2604     private static void setShortField(Object o, Class c, String fieldName, short v)
  2606         try {
  2607             Field fld = c.getDeclaredField( fieldName ) ;
  2608             long key = bridge.objectFieldOffset( fld ) ;
  2609             bridge.putShort( o, key, v ) ;
  2610         } catch (Exception e) {
  2611             throw utilWrapper.errorSetShortField( e, fieldName,
  2612                 o.toString(),
  2613                 new Short(v) ) ;
  2617     private static void setIntField(Object o, Class c, String fieldName, int v)
  2619         try {
  2620             Field fld = c.getDeclaredField( fieldName ) ;
  2621             long key = bridge.objectFieldOffset( fld ) ;
  2622             bridge.putInt( o, key, v ) ;
  2623         } catch (Exception e) {
  2624             throw utilWrapper.errorSetIntField( e, fieldName,
  2625                 o.toString(),
  2626                 new Integer(v) ) ;
  2630     private static void setLongField(Object o, Class c, String fieldName, long v)
  2632         try {
  2633             Field fld = c.getDeclaredField( fieldName ) ;
  2634             long key = bridge.objectFieldOffset( fld ) ;
  2635             bridge.putLong( o, key, v ) ;
  2636         } catch (Exception e) {
  2637             throw utilWrapper.errorSetLongField( e, fieldName,
  2638                 o.toString(),
  2639                 new Long(v) ) ;
  2643     private static void setFloatField(Object o, Class c, String fieldName, float v)
  2645         try {
  2646             Field fld = c.getDeclaredField( fieldName ) ;
  2647             long key = bridge.objectFieldOffset( fld ) ;
  2648             bridge.putFloat( o, key, v ) ;
  2649         } catch (Exception e) {
  2650             throw utilWrapper.errorSetFloatField( e, fieldName,
  2651                 o.toString(),
  2652                 new Float(v) ) ;
  2656     private static void setDoubleField(Object o, Class c, String fieldName, double v)
  2658         try {
  2659             Field fld = c.getDeclaredField( fieldName ) ;
  2660             long key = bridge.objectFieldOffset( fld ) ;
  2661             bridge.putDouble( o, key, v ) ;
  2662         } catch (Exception e) {
  2663             throw utilWrapper.errorSetDoubleField( e, fieldName,
  2664                 o.toString(),
  2665                 new Double(v) ) ;
  2669     /**
  2670      * This class maintains a map of stream position to
  2671      * an Object currently being deserialized.  It is used
  2672      * to handle the cases where the are indirections to
  2673      * an object on the recursion stack.  The CDR level
  2674      * handles indirections to objects previously seen
  2675      * (and completely deserialized) in the stream.
  2676      */
  2677     static class ActiveRecursionManager
  2679         private Map offsetToObjectMap;
  2681         public ActiveRecursionManager() {
  2682             // A hash map is unsynchronized and allows
  2683             // null values
  2684             offsetToObjectMap = new HashMap();
  2687         // Called right after allocating a new object.
  2688         // Offset is the starting position in the stream
  2689         // of the object.
  2690         public void addObject(int offset, Object value) {
  2691             offsetToObjectMap.put(new Integer(offset), value);
  2694         // If the given starting position doesn't refer
  2695         // to the beginning of an object currently being
  2696         // deserialized, this throws an IOException.
  2697         // Otherwise, it returns a reference to the
  2698         // object.
  2699         public Object getObject(int offset) throws IOException {
  2700             Integer position = new Integer(offset);
  2702             if (!offsetToObjectMap.containsKey(position))
  2703                 // XXX I18N, logging needed.
  2704                 throw new IOException("Invalid indirection to offset "
  2705                                       + offset);
  2707             return offsetToObjectMap.get(position);
  2710         // Called when an object has been completely
  2711         // deserialized, so it should no longer be in
  2712         // this mapping.  The CDR level can handle
  2713         // further indirections.
  2714         public void removeObject(int offset) {
  2715             offsetToObjectMap.remove(new Integer(offset));
  2718         // If the given offset doesn't map to an Object,
  2719         // then it isn't an indirection to an object
  2720         // currently being deserialized.
  2721         public boolean containsObject(int offset) {
  2722             return offsetToObjectMap.containsKey(new Integer(offset));

mercurial