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

Tue, 19 May 2015 21:51:03 +0100

author
msheppar
date
Tue, 19 May 2015 21:51:03 +0100
changeset 940
303fd9eb7e21
parent 566
7ec1c16f6fb8
child 993
fd75ec7ff603
permissions
-rw-r--r--

8068721: RMI-IIOP communication fails when ConcurrentHashMap is passed to remote method
Reviewed-by: chegar, alanb

     1 /*
     2  * Copyright (c) 1998, 2015, 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     final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) {
   304         orbStream = os;
   305     }
   307     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     final void increaseRecursionDepth(){
   331         recursionDepth++;
   332     }
   334     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 synchronized 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 synchronized 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 synchronized  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     final synchronized 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 synchronized 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 synchronized 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                     if (field.getField() != null) {
  1772                         bridge.putByte( o, field.getFieldID(), byteValue ) ;
  1773                         //reflective code: field.getField().setByte( o, byteValue ) ;
  1775                     break;
  1776                 case 'Z':
  1777                     boolean booleanValue = orbStream.read_boolean();
  1778                     if (field.getField() != null) {
  1779                         bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
  1780                         //reflective code: field.getField().setBoolean( o, booleanValue ) ;
  1782                     break;
  1783                 case 'C':
  1784                     char charValue = orbStream.read_wchar();
  1785                     if (field.getField() != null) {
  1786                         bridge.putChar( o, field.getFieldID(), charValue ) ;
  1787                         //reflective code: field.getField().setChar( o, charValue ) ;
  1789                     break;
  1790                 case 'S':
  1791                     short shortValue = orbStream.read_short();
  1792                     if (field.getField() != null) {
  1793                         bridge.putShort( o, field.getFieldID(), shortValue ) ;
  1794                         //reflective code: field.getField().setShort( o, shortValue ) ;
  1796                     break;
  1797                 case 'I':
  1798                     int intValue = orbStream.read_long();
  1799                     if (field.getField() != null) {
  1800                         bridge.putInt( o, field.getFieldID(), intValue ) ;
  1801                         //reflective code: field.getField().setInt( o, intValue ) ;
  1803                     break;
  1804                 case 'J':
  1805                     long longValue = orbStream.read_longlong();
  1806                     if (field.getField() != null) {
  1807                         bridge.putLong( o, field.getFieldID(), longValue ) ;
  1808                         //reflective code: field.getField().setLong( o, longValue ) ;
  1810                     break;
  1811                 case 'F' :
  1812                     float floatValue = orbStream.read_float();
  1813                     if (field.getField() != null) {
  1814                         bridge.putFloat( o, field.getFieldID(), floatValue ) ;
  1815                         //reflective code: field.getField().setFloat( o, floatValue ) ;
  1817                     break;
  1818                 case 'D' :
  1819                     double doubleValue = orbStream.read_double();
  1820                     if (field.getField() != null) {
  1821                         bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
  1822                         //reflective code: field.getField().setDouble( o, doubleValue ) ;
  1824                     break;
  1825                 default:
  1826                     // XXX I18N, logging needed.
  1827                     throw new InvalidClassException(cl.getName());
  1829         } catch (IllegalArgumentException e) {
  1830             /* This case should never happen. If the field types
  1831                are not the same, InvalidClassException is raised when
  1832                matching the local class to the serialized ObjectStreamClass. */
  1833             ClassCastException cce = new ClassCastException("Assigning instance of class " +
  1834                                          field.getType().getName() +
  1835                                          " to field " +
  1836                                          currentClassDesc.getName() + '#' +
  1837                                          field.getField().getName());
  1838             cce.initCause( e ) ;
  1839             throw cce ;
  1843     private Object inputObjectField(org.omg.CORBA.ValueMember field,
  1844                                     com.sun.org.omg.SendingContext.CodeBase sender)
  1845         throws IndirectionException, ClassNotFoundException, IOException,
  1846                StreamCorruptedException {
  1848         Object objectValue = null;
  1849         Class type = null;
  1850         String id = field.id;
  1852         try {
  1853             type = vhandler.getClassFromType(id);
  1854         } catch(ClassNotFoundException cnfe) {
  1855             // Make sure type = null
  1856             type = null;
  1859         String signature = null;
  1860         if (type != null)
  1861             signature = ValueUtility.getSignature(field);
  1863         if (signature != null && (signature.equals("Ljava/lang/Object;") ||
  1864                                   signature.equals("Ljava/io/Serializable;") ||
  1865                                   signature.equals("Ljava/io/Externalizable;"))) {
  1866             objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
  1867         } else {
  1868             // Decide what method call to make based on the type. If
  1869             // it is a type for which we need to load a stub, convert
  1870             // the type to the correct stub type.
  1871             //
  1872             // NOTE : Since FullValueDescription does not allow us
  1873             // to ask whether something is an interface we do not
  1874             // have the ability to optimize this check.
  1876             int callType = ValueHandlerImpl.kValueType;
  1878             if (!vhandler.isSequence(id)) {
  1880                 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
  1882                     // RMI Object reference...
  1883                     callType = ValueHandlerImpl.kRemoteType;
  1885                 } else {
  1887                     // REVISIT.  If we don't have the local class,
  1888                     // we should probably verify that it's an RMI type,
  1889                     // query the remote FVD, and use is_abstract.
  1890                     // Our FVD seems to get NullPointerExceptions for any
  1891                     // non-RMI types.
  1893                     // This uses the local class in the same way as
  1894                     // inputObjectField(ObjectStreamField) does.  REVISIT
  1895                     // inputObjectField(ObjectStreamField)'s loadStubClass
  1896                     // logic.  Assumption is that the given type cannot
  1897                     // evolve to become a CORBA abstract interface or
  1898                     // a RMI abstract interface.
  1900                     if (type != null && type.isInterface() &&
  1901                         (vhandler.isAbstractBase(type) ||
  1902                          ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
  1904                         callType = ValueHandlerImpl.kAbstractType;
  1909             // Now that we have used the FVD of the field to determine the proper course
  1910             // of action, it is ok to use the type (Class) from this point forward since
  1911             // the rep. id for this read will also follow on the wire.
  1913             switch (callType) {
  1914                 case ValueHandlerImpl.kRemoteType:
  1915                     if (type != null)
  1916                         objectValue = Utility.readObjectAndNarrow(orbStream, type);
  1917                     else
  1918                         objectValue = orbStream.read_Object();
  1919                     break;
  1920                 case ValueHandlerImpl.kAbstractType:
  1921                     if (type != null)
  1922                         objectValue = Utility.readAbstractAndNarrow(orbStream, type);
  1923                     else
  1924                         objectValue = orbStream.read_abstract_interface();
  1925                     break;
  1926                 case ValueHandlerImpl.kValueType:
  1927                     if (type != null)
  1928                         objectValue = orbStream.read_value(type);
  1929                     else
  1930                                             objectValue = orbStream.read_value();
  1931                     break;
  1932                 default:
  1933                     // XXX I18N, logging needed.
  1934                     throw new StreamCorruptedException("Unknown callType: " + callType);
  1938         return objectValue;
  1941     /**
  1942      * Factored out of inputClassFields and reused in
  1943      * inputCurrentClassFieldsForReadFields.
  1945      * Reads the field (which of an Object type as opposed to a primitive)
  1946      * described by ObjectStreamField field and returns it.
  1947      */
  1948     private Object inputObjectField(ObjectStreamField field)
  1949         throws InvalidClassException, StreamCorruptedException,
  1950                ClassNotFoundException, IndirectionException, IOException {
  1952         if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
  1953             return javax.rmi.CORBA.Util.readAny(orbStream);
  1956         Object objectValue = null;
  1958         // fields have an API to provide the actual class
  1959         // corresponding to the data type
  1960         // Class type = osc.forClass();
  1961         Class fieldType = field.getType();
  1962         Class actualType = fieldType; // This may change if stub loaded.
  1964         // Decide what method call to make based on the fieldType. If
  1965         // it is a type for which we need to load a stub, convert
  1966         // the type to the correct stub type.
  1968         int callType = ValueHandlerImpl.kValueType;
  1969         boolean narrow = false;
  1971         if (fieldType.isInterface()) {
  1972             boolean loadStubClass = false;
  1974             if (java.rmi.Remote.class.isAssignableFrom(fieldType)) {
  1976                 // RMI Object reference...
  1977                 callType = ValueHandlerImpl.kRemoteType;
  1979             } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){
  1981                 // IDL Object reference...
  1982                 callType = ValueHandlerImpl.kRemoteType;
  1983                 loadStubClass = true;
  1985             } else if (vhandler.isAbstractBase(fieldType)) {
  1986                 // IDL Abstract Object reference...
  1988                 callType = ValueHandlerImpl.kAbstractType;
  1989                 loadStubClass = true;
  1990             } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
  1991                 // RMI Abstract Object reference...
  1993                 callType = ValueHandlerImpl.kAbstractType;
  1996             if (loadStubClass) {
  1997                 try {
  1998                     String codebase = Util.getCodebase(fieldType);
  1999                     String repID = vhandler.createForAnyType(fieldType);
  2000                     Class stubType =
  2001                         Utility.loadStubClass(repID, codebase, fieldType);
  2002                     actualType = stubType;
  2003                 } catch (ClassNotFoundException e) {
  2004                     narrow = true;
  2006             } else {
  2007                 narrow = true;
  2011         switch (callType) {
  2012             case ValueHandlerImpl.kRemoteType:
  2013                 if (!narrow)
  2014                     objectValue = (Object)orbStream.read_Object(actualType);
  2015                 else
  2016                     objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
  2017                 break;
  2018             case ValueHandlerImpl.kAbstractType:
  2019                 if (!narrow)
  2020                     objectValue = (Object)orbStream.read_abstract_interface(actualType);
  2021                 else
  2022                     objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
  2023                 break;
  2024             case ValueHandlerImpl.kValueType:
  2025                 objectValue = (Object)orbStream.read_value(actualType);
  2026                 break;
  2027             default:
  2028                 // XXX I18N, logging needed.
  2029                 throw new StreamCorruptedException("Unknown callType: " + callType);
  2032         return objectValue;
  2035     private final boolean mustUseRemoteValueMembers() {
  2036         return defaultReadObjectFVDMembers != null;
  2039     void readFields(java.util.Map fieldToValueMap)
  2040         throws InvalidClassException, StreamCorruptedException,
  2041                ClassNotFoundException, IOException {
  2043         if (mustUseRemoteValueMembers()) {
  2044             inputRemoteMembersForReadFields(fieldToValueMap);
  2045         } else
  2046             inputCurrentClassFieldsForReadFields(fieldToValueMap);
  2049     private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
  2050         throws InvalidClassException, StreamCorruptedException,
  2051                ClassNotFoundException, IOException {
  2053         // Must have this local variable since defaultReadObjectFVDMembers
  2054         // may get mangled by recursion.
  2055         ValueMember fields[] = defaultReadObjectFVDMembers;
  2057         try {
  2059             for (int i = 0; i < fields.length; i++) {
  2061                 switch (fields[i].type.kind().value()) {
  2063                 case TCKind._tk_octet:
  2064                     byte byteValue = orbStream.read_octet();
  2065                     fieldToValueMap.put(fields[i].name, new Byte(byteValue));
  2066                     break;
  2067                 case TCKind._tk_boolean:
  2068                     boolean booleanValue = orbStream.read_boolean();
  2069                     fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
  2070                     break;
  2071                 case TCKind._tk_char:
  2072                     // Backwards compatibility.  Older Sun ORBs sent
  2073                     // _tk_char even though they read and wrote wchars
  2074                     // correctly.
  2075                     //
  2076                     // Fall through to the _tk_wchar case.
  2077                 case TCKind._tk_wchar:
  2078                     char charValue = orbStream.read_wchar();
  2079                     fieldToValueMap.put(fields[i].name, new Character(charValue));
  2080                     break;
  2081                 case TCKind._tk_short:
  2082                     short shortValue = orbStream.read_short();
  2083                     fieldToValueMap.put(fields[i].name, new Short(shortValue));
  2084                     break;
  2085                 case TCKind._tk_long:
  2086                     int intValue = orbStream.read_long();
  2087                     fieldToValueMap.put(fields[i].name, new Integer(intValue));
  2088                     break;
  2089                 case TCKind._tk_longlong:
  2090                     long longValue = orbStream.read_longlong();
  2091                     fieldToValueMap.put(fields[i].name, new Long(longValue));
  2092                     break;
  2093                 case TCKind._tk_float:
  2094                     float floatValue = orbStream.read_float();
  2095                     fieldToValueMap.put(fields[i].name, new Float(floatValue));
  2096                     break;
  2097                 case TCKind._tk_double:
  2098                     double doubleValue = orbStream.read_double();
  2099                     fieldToValueMap.put(fields[i].name, new Double(doubleValue));
  2100                     break;
  2101                 case TCKind._tk_value:
  2102                 case TCKind._tk_objref:
  2103                 case TCKind._tk_value_box:
  2104                     Object objectValue = null;
  2105                     try {
  2106                         objectValue = inputObjectField(fields[i],
  2107                                                        cbSender);
  2109                     } catch (IndirectionException cdrie) {
  2110                         // The CDR stream had never seen the given offset before,
  2111                         // so check the recursion manager (it will throw an
  2112                         // IOException if it doesn't have a reference, either).
  2113                         objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2116                     fieldToValueMap.put(fields[i].name, objectValue);
  2117                     break;
  2118                 default:
  2119                     // XXX I18N, logging needed.
  2120                     throw new StreamCorruptedException("Unknown kind: "
  2121                                                        + fields[i].type.kind().value());
  2124         } catch (Throwable t) {
  2125             StreamCorruptedException result = new StreamCorruptedException(t.getMessage());
  2126             result.initCause(t);
  2127             throw result;
  2131     /**
  2132      * Called from InputStreamHook.
  2134      * Reads the fields of the current class (could be the ones
  2135      * queried from the remote FVD) and puts them in
  2136      * the given Map, name to value.  Wraps primitives in the
  2137      * corresponding java.lang Objects.
  2138      */
  2139     private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
  2140         throws InvalidClassException, StreamCorruptedException,
  2141                ClassNotFoundException, IOException {
  2143         ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
  2145         int primFields = fields.length - currentClassDesc.objFields;
  2147         // Handle the primitives first
  2148         for (int i = 0; i < primFields; ++i) {
  2150             switch (fields[i].getTypeCode()) {
  2151                 case 'B':
  2152                     byte byteValue = orbStream.read_octet();
  2153                     fieldToValueMap.put(fields[i].getName(),
  2154                                         new Byte(byteValue));
  2155                     break;
  2156                 case 'Z':
  2157                    boolean booleanValue = orbStream.read_boolean();
  2158                    fieldToValueMap.put(fields[i].getName(),
  2159                                        new Boolean(booleanValue));
  2160                    break;
  2161                 case 'C':
  2162                     char charValue = orbStream.read_wchar();
  2163                     fieldToValueMap.put(fields[i].getName(),
  2164                                         new Character(charValue));
  2165                     break;
  2166                 case 'S':
  2167                     short shortValue = orbStream.read_short();
  2168                     fieldToValueMap.put(fields[i].getName(),
  2169                                         new Short(shortValue));
  2170                     break;
  2171                 case 'I':
  2172                     int intValue = orbStream.read_long();
  2173                     fieldToValueMap.put(fields[i].getName(),
  2174                                         new Integer(intValue));
  2175                     break;
  2176                 case 'J':
  2177                     long longValue = orbStream.read_longlong();
  2178                     fieldToValueMap.put(fields[i].getName(),
  2179                                         new Long(longValue));
  2180                     break;
  2181                 case 'F' :
  2182                     float floatValue = orbStream.read_float();
  2183                     fieldToValueMap.put(fields[i].getName(),
  2184                                         new Float(floatValue));
  2185                     break;
  2186                 case 'D' :
  2187                     double doubleValue = orbStream.read_double();
  2188                     fieldToValueMap.put(fields[i].getName(),
  2189                                         new Double(doubleValue));
  2190                     break;
  2191                 default:
  2192                     // XXX I18N, logging needed.
  2193                     throw new InvalidClassException(currentClassDesc.getName());
  2197         /* Read and set object fields from the input stream. */
  2198         if (currentClassDesc.objFields > 0) {
  2199             for (int i = primFields; i < fields.length; i++) {
  2200                 Object objectValue = null;
  2201                 try {
  2202                     objectValue = inputObjectField(fields[i]);
  2203                 } catch(IndirectionException cdrie) {
  2204                     // The CDR stream had never seen the given offset before,
  2205                     // so check the recursion manager (it will throw an
  2206                     // IOException if it doesn't have a reference, either).
  2207                     objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2210                 fieldToValueMap.put(fields[i].getName(), objectValue);
  2215     /*
  2216      * Read the fields of the specified class from the input stream and set
  2217      * the values of the fields in the specified object. If the specified
  2218      * object is null, just consume the fields without setting any values. If
  2219      * any ObjectStreamField does not have a reflected Field, don't try to set
  2220      * that field in the object.
  2222      * REVISIT -- This code doesn't do what the comment says to when
  2223      * getField() is null!
  2224      */
  2225     private void inputClassFields(Object o, Class cl,
  2226                                   ObjectStreamField[] fields,
  2227                                   com.sun.org.omg.SendingContext.CodeBase sender)
  2228         throws InvalidClassException, StreamCorruptedException,
  2229                ClassNotFoundException, IOException
  2232         int primFields = fields.length - currentClassDesc.objFields;
  2234         if (o != null) {
  2235             for (int i = 0; i < primFields; ++i) {
  2236                 inputPrimitiveField(o, cl, fields[i]);
  2240         /* Read and set object fields from the input stream. */
  2241         if (currentClassDesc.objFields > 0) {
  2242             for (int i = primFields; i < fields.length; i++) {
  2243                 Object objectValue = null;
  2245                 try {
  2246                     objectValue = inputObjectField(fields[i]);
  2247                 } catch(IndirectionException cdrie) {
  2248                     // The CDR stream had never seen the given offset before,
  2249                     // so check the recursion manager (it will throw an
  2250                     // IOException if it doesn't have a reference, either).
  2251                     objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2254                 if ((o == null) || (fields[i].getField() == null)) {
  2255                     continue;
  2258                 try {
  2259                     Class fieldCl = fields[i].getClazz();
  2260                     if (objectValue != null && !fieldCl.isInstance(objectValue)) {
  2261                         throw new IllegalArgumentException();
  2263                     bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
  2264                     // reflective code: fields[i].getField().set( o, objectValue ) ;
  2265                 } catch (IllegalArgumentException e) {
  2266                     ClassCastException exc = new ClassCastException("Assigning instance of class " +
  2267                                                  objectValue.getClass().getName() +
  2268                                                  " to field " +
  2269                                                  currentClassDesc.getName() +
  2270                                                  '#' +
  2271                                                  fields[i].getField().getName());
  2272                     exc.initCause( e ) ;
  2273                     throw exc ;
  2275             } // end : for loop
  2279     /*
  2280      * Read the fields of the specified class from the input stream and set
  2281      * the values of the fields in the specified object. If the specified
  2282      * object is null, just consume the fields without setting any values. If
  2283      * any ObjectStreamField does not have a reflected Field, don't try to set
  2284      * that field in the object.
  2285      */
  2286     private void inputClassFields(Object o, Class cl,
  2287                                   ObjectStreamClass osc,
  2288                                   ValueMember[] fields,
  2289                                   com.sun.org.omg.SendingContext.CodeBase sender)
  2290         throws InvalidClassException, StreamCorruptedException,
  2291                ClassNotFoundException, IOException
  2293         try{
  2294             for (int i = 0; i < fields.length; ++i) {
  2295                 try {
  2296                     switch (fields[i].type.kind().value()) {
  2297                     case TCKind._tk_octet:
  2298                         byte byteValue = orbStream.read_octet();
  2299                         if ((o != null) && osc.hasField(fields[i]))
  2300                         setByteField(o, cl, fields[i].name, byteValue);
  2301                         break;
  2302                     case TCKind._tk_boolean:
  2303                         boolean booleanValue = orbStream.read_boolean();
  2304                         if ((o != null) && osc.hasField(fields[i]))
  2305                         setBooleanField(o, cl, fields[i].name, booleanValue);
  2306                         break;
  2307                     case TCKind._tk_char:
  2308                         // Backwards compatibility.  Older Sun ORBs sent
  2309                         // _tk_char even though they read and wrote wchars
  2310                         // correctly.
  2311                         //
  2312                         // Fall through to the _tk_wchar case.
  2313                     case TCKind._tk_wchar:
  2314                         char charValue = orbStream.read_wchar();
  2315                         if ((o != null) && osc.hasField(fields[i]))
  2316                         setCharField(o, cl, fields[i].name, charValue);
  2317                         break;
  2318                     case TCKind._tk_short:
  2319                         short shortValue = orbStream.read_short();
  2320                         if ((o != null) && osc.hasField(fields[i]))
  2321                         setShortField(o, cl, fields[i].name, shortValue);
  2322                         break;
  2323                     case TCKind._tk_long:
  2324                         int intValue = orbStream.read_long();
  2325                         if ((o != null) && osc.hasField(fields[i]))
  2326                         setIntField(o, cl, fields[i].name, intValue);
  2327                         break;
  2328                     case TCKind._tk_longlong:
  2329                         long longValue = orbStream.read_longlong();
  2330                         if ((o != null) && osc.hasField(fields[i]))
  2331                         setLongField(o, cl, fields[i].name, longValue);
  2332                         break;
  2333                     case TCKind._tk_float:
  2334                         float floatValue = orbStream.read_float();
  2335                         if ((o != null) && osc.hasField(fields[i]))
  2336                         setFloatField(o, cl, fields[i].name, floatValue);
  2337                         break;
  2338                     case TCKind._tk_double:
  2339                         double doubleValue = orbStream.read_double();
  2340                         if ((o != null) && osc.hasField(fields[i]))
  2341                         setDoubleField(o, cl, fields[i].name, doubleValue);
  2342                         break;
  2343                     case TCKind._tk_value:
  2344                     case TCKind._tk_objref:
  2345                     case TCKind._tk_value_box:
  2346                         Object objectValue = null;
  2347                         try {
  2348                             objectValue = inputObjectField(fields[i], sender);
  2349                         } catch (IndirectionException cdrie) {
  2350                             // The CDR stream had never seen the given offset before,
  2351                             // so check the recursion manager (it will throw an
  2352                             // IOException if it doesn't have a reference, either).
  2353                             objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2356                         if (o == null)
  2357                             continue;
  2358                         try {
  2359                             if (osc.hasField(fields[i])){
  2360                                 setObjectField(o,
  2361                                                cl,
  2362                                                fields[i].name,
  2363                                                objectValue);
  2364                             } else {
  2365                                 // REVISIT.  Convert to a log message.
  2366                                 // This is a normal case when fields have
  2367                                 // been added as part of evolution, but
  2368                                 // silently skipping can make it hard to
  2369                                 // debug if there's an error
  2370 //                                 System.out.println("**** warning, not setting field: "
  2371 //                                                    + fields[i].name
  2372 //                                                    + " since not on class "
  2373 //                                                    + osc.getName());
  2376                         } catch (IllegalArgumentException e) {
  2377                             // XXX I18N, logging needed.
  2378                             ClassCastException cce = new ClassCastException("Assigning instance of class " +
  2379                                 objectValue.getClass().getName() + " to field " + fields[i].name);
  2380                             cce.initCause(e) ;
  2381                             throw cce ;
  2383                         break;
  2384                     default:
  2385                         // XXX I18N, logging needed.
  2386                         throw new StreamCorruptedException("Unknown kind: "
  2387                                                            + fields[i].type.kind().value());
  2389                 } catch (IllegalArgumentException e) {
  2390                     /* This case should never happen. If the field types
  2391                        are not the same, InvalidClassException is raised when
  2392                        matching the local class to the serialized ObjectStreamClass. */
  2393                     // XXX I18N, logging needed.
  2394                     ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id +
  2395                         " to field " + currentClassDesc.getName() + '#' + fields[i].name);
  2396                     cce.initCause( e ) ;
  2397                     throw cce ;
  2400         } catch(Throwable t){
  2401             // XXX I18N, logging needed.
  2402             StreamCorruptedException sce = new StreamCorruptedException(t.getMessage());
  2403             sce.initCause(t) ;
  2404             throw sce ;
  2408     private void skipCustomUsingFVD(ValueMember[] fields,
  2409                                     com.sun.org.omg.SendingContext.CodeBase sender)
  2410                                     throws InvalidClassException, StreamCorruptedException,
  2411                                            ClassNotFoundException, IOException
  2413         readFormatVersion();
  2414         boolean calledDefaultWriteObject = readBoolean();
  2416         if (calledDefaultWriteObject)
  2417             throwAwayData(fields, sender);
  2419         if (getStreamFormatVersion() == 2) {
  2421             ((ValueInputStream)getOrbStream()).start_value();
  2422             ((ValueInputStream)getOrbStream()).end_value();
  2426     /*
  2427      * Read the fields of the specified class from the input stream throw data away.
  2428      * This must handle same switch logic as above.
  2429      */
  2430     private void throwAwayData(ValueMember[] fields,
  2431                                com.sun.org.omg.SendingContext.CodeBase sender)
  2432         throws InvalidClassException, StreamCorruptedException,
  2433                ClassNotFoundException, IOException
  2435         for (int i = 0; i < fields.length; ++i) {
  2437             try {
  2439                 switch (fields[i].type.kind().value()) {
  2440                 case TCKind._tk_octet:
  2441                     orbStream.read_octet();
  2442                     break;
  2443                 case TCKind._tk_boolean:
  2444                     orbStream.read_boolean();
  2445                     break;
  2446                 case TCKind._tk_char:
  2447                     // Backwards compatibility.  Older Sun ORBs sent
  2448                     // _tk_char even though they read and wrote wchars
  2449                     // correctly.
  2450                     //
  2451                     // Fall through to the _tk_wchar case.
  2452                 case TCKind._tk_wchar:
  2453                     orbStream.read_wchar();
  2454                     break;
  2455                 case TCKind._tk_short:
  2456                     orbStream.read_short();
  2457                     break;
  2458                 case TCKind._tk_long:
  2459                     orbStream.read_long();
  2460                     break;
  2461                 case TCKind._tk_longlong:
  2462                     orbStream.read_longlong();
  2463                     break;
  2464                 case TCKind._tk_float:
  2465                     orbStream.read_float();
  2466                     break;
  2467                 case TCKind._tk_double:
  2468                     orbStream.read_double();
  2469                     break;
  2470                 case TCKind._tk_value:
  2471                 case TCKind._tk_objref:
  2472                 case TCKind._tk_value_box:
  2473                     Class type = null;
  2474                     String id = fields[i].id;
  2476                     try {
  2477                         type = vhandler.getClassFromType(id);
  2479                     catch(ClassNotFoundException cnfe){
  2480                         // Make sure type = null
  2481                         type = null;
  2483                     String signature = null;
  2484                     if (type != null)
  2485                         signature = ValueUtility.getSignature(fields[i]);
  2487                     // Read value
  2488                     try {
  2489                         if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
  2490                                                      signature.equals("Ljava/io/Serializable;") ||
  2491                                                      signature.equals("Ljava/io/Externalizable;")) ) {
  2492                             javax.rmi.CORBA.Util.readAny(orbStream);
  2494                         else {
  2495                             // Decide what method call to make based on the type.
  2496                             //
  2497                             // NOTE : Since FullValueDescription does not allow us
  2498                             // to ask whether something is an interface we do not
  2499                             // have the ability to optimize this check.
  2501                             int callType = ValueHandlerImpl.kValueType;
  2503                             if (!vhandler.isSequence(id)) {
  2504                                 FullValueDescription fieldFVD = sender.meta(fields[i].id);
  2505                                 if (kRemoteTypeCode == fields[i].type) {
  2507                                     // RMI Object reference...
  2508                                     callType = ValueHandlerImpl.kRemoteType;
  2509                                 } else if (fieldFVD.is_abstract) {
  2510                                     // RMI Abstract Object reference...
  2512                                     callType = ValueHandlerImpl.kAbstractType;
  2516                             // Now that we have used the FVD of the field to determine the proper course
  2517                             // of action, it is ok to use the type (Class) from this point forward since
  2518                             // the rep. id for this read will also follow on the wire.
  2520                             switch (callType) {
  2521                             case ValueHandlerImpl.kRemoteType:
  2522                                 orbStream.read_Object();
  2523                                 break;
  2524                             case ValueHandlerImpl.kAbstractType:
  2525                                 orbStream.read_abstract_interface();
  2526                                 break;
  2527                             case ValueHandlerImpl.kValueType:
  2528                                 if (type != null) {
  2529                                     orbStream.read_value(type);
  2530                                 } else {
  2531                                     orbStream.read_value();
  2533                                 break;
  2534                             default:
  2535                                 // XXX I18N, logging needed.
  2536                                 throw new StreamCorruptedException("Unknown callType: "
  2537                                                                    + callType);
  2542                     catch(IndirectionException cdrie) {
  2543                         // Since we are throwing this away, don't bother handling recursion.
  2544                         continue;
  2547                     break;
  2548                 default:
  2549                     // XXX I18N, logging needed.
  2550                     throw new StreamCorruptedException("Unknown kind: "
  2551                                                        + fields[i].type.kind().value());
  2554             } catch (IllegalArgumentException e) {
  2555                 /* This case should never happen. If the field types
  2556                    are not the same, InvalidClassException is raised when
  2557                    matching the local class to the serialized ObjectStreamClass. */
  2558                 // XXX I18N, logging needed.
  2559                 ClassCastException cce = new ClassCastException("Assigning instance of class " +
  2560                     fields[i].id + " to field " + currentClassDesc.getName() +
  2561                     '#' + fields[i].name);
  2562                 cce.initCause(e) ;
  2563                 throw cce ;
  2569     private static void setObjectField(Object o, Class c, String fieldName, Object v)
  2571         try {
  2572             Field fld = c.getDeclaredField( fieldName ) ;
  2573             Class fieldCl = fld.getType();
  2574             if(v != null && !fieldCl.isInstance(v)) {
  2575                 throw new Exception();
  2577             long key = bridge.objectFieldOffset( fld ) ;
  2578             bridge.putObject( o, key, v ) ;
  2579         } catch (Exception e) {
  2580             throw utilWrapper.errorSetObjectField( e, fieldName,
  2581                 o.toString(),
  2582                 v.toString() ) ;
  2586     private static void setBooleanField(Object o, Class c, String fieldName, boolean v)
  2588         try {
  2589             Field fld = c.getDeclaredField( fieldName ) ;
  2590             long key = bridge.objectFieldOffset( fld ) ;
  2591             bridge.putBoolean( o, key, v ) ;
  2592         } catch (Exception e) {
  2593             throw utilWrapper.errorSetBooleanField( e, fieldName,
  2594                 o.toString(),
  2595                 new Boolean(v) ) ;
  2599     private static void setByteField(Object o, Class c, String fieldName, byte v)
  2601         try {
  2602             Field fld = c.getDeclaredField( fieldName ) ;
  2603             long key = bridge.objectFieldOffset( fld ) ;
  2604             bridge.putByte( o, key, v ) ;
  2605         } catch (Exception e) {
  2606             throw utilWrapper.errorSetByteField( e, fieldName,
  2607                 o.toString(),
  2608                 new Byte(v) ) ;
  2612     private static void setCharField(Object o, Class c, String fieldName, char v)
  2614         try {
  2615             Field fld = c.getDeclaredField( fieldName ) ;
  2616             long key = bridge.objectFieldOffset( fld ) ;
  2617             bridge.putChar( o, key, v ) ;
  2618         } catch (Exception e) {
  2619             throw utilWrapper.errorSetCharField( e, fieldName,
  2620                 o.toString(),
  2621                 new Character(v) ) ;
  2625     private static void setShortField(Object o, Class c, String fieldName, short v)
  2627         try {
  2628             Field fld = c.getDeclaredField( fieldName ) ;
  2629             long key = bridge.objectFieldOffset( fld ) ;
  2630             bridge.putShort( o, key, v ) ;
  2631         } catch (Exception e) {
  2632             throw utilWrapper.errorSetShortField( e, fieldName,
  2633                 o.toString(),
  2634                 new Short(v) ) ;
  2638     private static void setIntField(Object o, Class c, String fieldName, int v)
  2640         try {
  2641             Field fld = c.getDeclaredField( fieldName ) ;
  2642             long key = bridge.objectFieldOffset( fld ) ;
  2643             bridge.putInt( o, key, v ) ;
  2644         } catch (Exception e) {
  2645             throw utilWrapper.errorSetIntField( e, fieldName,
  2646                 o.toString(),
  2647                 new Integer(v) ) ;
  2651     private static void setLongField(Object o, Class c, String fieldName, long v)
  2653         try {
  2654             Field fld = c.getDeclaredField( fieldName ) ;
  2655             long key = bridge.objectFieldOffset( fld ) ;
  2656             bridge.putLong( o, key, v ) ;
  2657         } catch (Exception e) {
  2658             throw utilWrapper.errorSetLongField( e, fieldName,
  2659                 o.toString(),
  2660                 new Long(v) ) ;
  2664     private static void setFloatField(Object o, Class c, String fieldName, float v)
  2666         try {
  2667             Field fld = c.getDeclaredField( fieldName ) ;
  2668             long key = bridge.objectFieldOffset( fld ) ;
  2669             bridge.putFloat( o, key, v ) ;
  2670         } catch (Exception e) {
  2671             throw utilWrapper.errorSetFloatField( e, fieldName,
  2672                 o.toString(),
  2673                 new Float(v) ) ;
  2677     private static void setDoubleField(Object o, Class c, String fieldName, double v)
  2679         try {
  2680             Field fld = c.getDeclaredField( fieldName ) ;
  2681             long key = bridge.objectFieldOffset( fld ) ;
  2682             bridge.putDouble( o, key, v ) ;
  2683         } catch (Exception e) {
  2684             throw utilWrapper.errorSetDoubleField( e, fieldName,
  2685                 o.toString(),
  2686                 new Double(v) ) ;
  2690     /**
  2691      * This class maintains a map of stream position to
  2692      * an Object currently being deserialized.  It is used
  2693      * to handle the cases where the are indirections to
  2694      * an object on the recursion stack.  The CDR level
  2695      * handles indirections to objects previously seen
  2696      * (and completely deserialized) in the stream.
  2697      */
  2698     static class ActiveRecursionManager
  2700         private Map offsetToObjectMap;
  2702         public ActiveRecursionManager() {
  2703             // A hash map is unsynchronized and allows
  2704             // null values
  2705             offsetToObjectMap = new HashMap();
  2708         // Called right after allocating a new object.
  2709         // Offset is the starting position in the stream
  2710         // of the object.
  2711         public void addObject(int offset, Object value) {
  2712             offsetToObjectMap.put(new Integer(offset), value);
  2715         // If the given starting position doesn't refer
  2716         // to the beginning of an object currently being
  2717         // deserialized, this throws an IOException.
  2718         // Otherwise, it returns a reference to the
  2719         // object.
  2720         public Object getObject(int offset) throws IOException {
  2721             Integer position = new Integer(offset);
  2723             if (!offsetToObjectMap.containsKey(position))
  2724                 // XXX I18N, logging needed.
  2725                 throw new IOException("Invalid indirection to offset "
  2726                                       + offset);
  2728             return offsetToObjectMap.get(position);
  2731         // Called when an object has been completely
  2732         // deserialized, so it should no longer be in
  2733         // this mapping.  The CDR level can handle
  2734         // further indirections.
  2735         public void removeObject(int offset) {
  2736             offsetToObjectMap.remove(new Integer(offset));
  2739         // If the given offset doesn't map to an Object,
  2740         // then it isn't an indirection to an object
  2741         // currently being deserialized.
  2742         public boolean containsObject(int offset) {
  2743             return offsetToObjectMap.containsKey(new Integer(offset));

mercurial