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

Wed, 22 Jun 2016 18:25:00 +0100

author
msheppar
date
Wed, 22 Jun 2016 18:25:00 +0100
changeset 1288
f7b43e9f1665
parent 1066
05084f644c07
child 1410
9c913ea7e4a1
permissions
-rw-r--r--

8146975: NullPointerException in IIOPInputStream.inputClassFields
Reviewed-by: chegar, rriggs, coffeys

     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             if (!currentClassDesc.forClass().isAssignableFrom(
   571                     currentObject.getClass())) {
   572                 throw new IOException("Object Type mismatch");
   573             }
   575             // The array will be null unless fields were retrieved
   576             // remotely because of a serializable version difference.
   577             // Bug fix for 4365188.  See the definition of
   578             // defaultReadObjectFVDMembers for more information.
   579             if (defaultReadObjectFVDMembers != null &&
   580                 defaultReadObjectFVDMembers.length > 0) {
   582                 // WARNING:  Be very careful!  What if some of
   583                 // these fields actually have to do this, too?
   584                 // This works because the defaultReadObjectFVDMembers
   585                 // reference is passed to inputClassFields, but
   586                 // there is no guarantee that
   587                 // defaultReadObjectFVDMembers will point to the
   588                 // same array after calling inputClassFields.
   590                 // Use the remote fields to unmarshal.
   591                 inputClassFields(currentObject,
   592                                  currentClass,
   593                                  currentClassDesc,
   594                                  defaultReadObjectFVDMembers,
   595                                  cbSender);
   597             } else {
   599                 // Use the local fields to unmarshal.
   600                 ObjectStreamField[] fields =
   601                     currentClassDesc.getFieldsNoCopy();
   602                 if (fields.length > 0) {
   603                     inputClassFields(currentObject, currentClass, fields, cbSender);
   604                 }
   605             }
   606         }
   607         catch(NotActiveException nae)
   608             {
   609                 bridge.throwException( nae ) ;
   610             }
   611         catch(IOException ioe)
   612             {
   613                 bridge.throwException( ioe ) ;
   614             }
   615         catch(ClassNotFoundException cnfe)
   616             {
   617                 bridge.throwException( cnfe ) ;
   618             }
   620     }
   622     /**
   623      * Override the actions of the final method "enableResolveObject()"
   624      * in ObjectInputStream.
   625      * @since     JDK1.1.6
   626      *
   627      * Enable the stream to allow objects read from the stream to be replaced.
   628      * If the stream is a trusted class it is allowed to enable replacment.
   629      * Trusted classes are those classes with a classLoader equals null. <p>
   630      *
   631      * When enabled the resolveObject method is called for every object
   632      * being deserialized.
   633      *
   634      * @exception SecurityException The classloader of this stream object is non-null.
   635      * @since     JDK1.1
   636      */
   637     public final boolean enableResolveObjectDelegate(boolean enable)
   638     /* throws SecurityException */
   639     {
   640         return false;
   641     }
   643     // The following three methods allow the implementing orbStream
   644     // to provide mark/reset behavior as defined in java.io.InputStream.
   646     public final void mark(int readAheadLimit) {
   647         orbStream.mark(readAheadLimit);
   648     }
   650     public final boolean markSupported() {
   651         return orbStream.markSupported();
   652     }
   654     public final void reset() throws IOException {
   655         try {
   656             orbStream.reset();
   657         } catch (Error e) {
   658             IOException err = new IOException(e.getMessage());
   659             err.initCause(e) ;
   660             throw err ;
   661         }
   662     }
   664     public final int available() throws IOException{
   665         return 0; // unreliable
   666     }
   668     public final void close() throws IOException{
   669         // no op
   670     }
   672     public final int read() throws IOException{
   673         try{
   674             readObjectState.readData(this);
   676             return (orbStream.read_octet() << 0) & 0x000000FF;
   677         } catch (MARSHAL marshalException) {
   678             if (marshalException.minor
   679                 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   680                 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   681                 return -1;
   682             }
   684             throw marshalException;
   685         } catch(Error e) {
   686             IOException exc = new IOException(e.getMessage());
   687             exc.initCause(e) ;
   688             throw exc ;
   689         }
   690     }
   692     public final int read(byte data[], int offset, int length) throws IOException{
   693         try{
   694             readObjectState.readData(this);
   696             orbStream.read_octet_array(data, offset, length);
   697             return length;
   698         } catch (MARSHAL marshalException) {
   699             if (marshalException.minor
   700                 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   701                 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   702                 return -1;
   703             }
   705             throw marshalException;
   706         } catch(Error e) {
   707             IOException exc = new IOException(e.getMessage());
   708             exc.initCause(e) ;
   709             throw exc ;
   710         }
   712     }
   714     public final boolean readBoolean() throws IOException{
   715         try{
   716             readObjectState.readData(this);
   718             return orbStream.read_boolean();
   719         } catch (MARSHAL marshalException) {
   720             handleOptionalDataMarshalException(marshalException, false);
   721             throw marshalException;
   723         } catch(Error e) {
   724             IOException exc = new IOException(e.getMessage());
   725             exc.initCause(e);
   726             throw exc ;
   727         }
   728     }
   730     public final byte readByte() throws IOException{
   731         try{
   732             readObjectState.readData(this);
   734             return orbStream.read_octet();
   735         } catch (MARSHAL marshalException) {
   736             handleOptionalDataMarshalException(marshalException, false);
   737             throw marshalException;
   739         } catch(Error e) {
   740             IOException exc = new IOException(e.getMessage());
   741             exc.initCause(e);
   742             throw exc ;
   743         }
   744     }
   746     public final char readChar() throws IOException{
   747         try{
   748             readObjectState.readData(this);
   750             return orbStream.read_wchar();
   751         } catch (MARSHAL marshalException) {
   752             handleOptionalDataMarshalException(marshalException, false);
   753             throw marshalException;
   755         } catch(Error e) {
   756             IOException exc = new IOException(e.getMessage());
   757             exc.initCause(e);
   758             throw exc ;
   759         }
   760     }
   762     public final double readDouble() throws IOException{
   763         try{
   764             readObjectState.readData(this);
   766             return orbStream.read_double();
   767         } catch (MARSHAL marshalException) {
   768             handleOptionalDataMarshalException(marshalException, false);
   769             throw marshalException;
   770         } catch(Error e) {
   771             IOException exc = new IOException(e.getMessage());
   772             exc.initCause(e);
   773             throw exc ;
   774         }
   775     }
   777     public final float readFloat() throws IOException{
   778         try{
   779             readObjectState.readData(this);
   781             return orbStream.read_float();
   782         } catch (MARSHAL marshalException) {
   783             handleOptionalDataMarshalException(marshalException, false);
   784             throw marshalException;
   785         } catch(Error e) {
   786             IOException exc = new IOException(e.getMessage());
   787             exc.initCause(e);
   788             throw exc ;
   789         }
   790     }
   792     public final void readFully(byte data[]) throws IOException{
   793 // d11623 : implement readFully, required for serializing some core classes
   795         readFully(data, 0, data.length);
   796     }
   798     public final void readFully(byte data[],  int offset,  int size) throws IOException{
   799 // d11623 : implement readFully, required for serializing some core classes
   800         try{
   801             readObjectState.readData(this);
   803             orbStream.read_octet_array(data, offset, size);
   804         } catch (MARSHAL marshalException) {
   805             handleOptionalDataMarshalException(marshalException, false);
   807             throw marshalException;
   808         } catch(Error e) {
   809             IOException exc = new IOException(e.getMessage());
   810             exc.initCause(e);
   811             throw exc ;
   812         }
   813     }
   815     public final int readInt() throws IOException{
   816         try{
   817             readObjectState.readData(this);
   819             return orbStream.read_long();
   820         } catch (MARSHAL marshalException) {
   821             handleOptionalDataMarshalException(marshalException, false);
   822             throw marshalException;
   823         } catch(Error e) {
   824             IOException exc = new IOException(e.getMessage());
   825             exc.initCause(e);
   826             throw exc ;
   827         }
   828     }
   830     public final String readLine() throws IOException{
   831         // XXX I18N, logging needed.
   832         throw new IOException("Method readLine not supported");
   833     }
   835     public final long readLong() throws IOException{
   836         try{
   837             readObjectState.readData(this);
   839             return orbStream.read_longlong();
   840         } catch (MARSHAL marshalException) {
   841             handleOptionalDataMarshalException(marshalException, false);
   842             throw marshalException;
   843         } catch(Error e) {
   844             IOException exc = new IOException(e.getMessage());
   845             exc.initCause(e);
   846             throw exc ;
   847         }
   848     }
   850     public final short readShort() throws IOException{
   851         try{
   852             readObjectState.readData(this);
   854             return orbStream.read_short();
   855         } catch (MARSHAL marshalException) {
   856             handleOptionalDataMarshalException(marshalException, false);
   857             throw marshalException;
   858         } catch(Error e) {
   859             IOException exc = new IOException(e.getMessage());
   860             exc.initCause(e);
   861             throw exc ;
   862         }
   863     }
   865     protected final void readStreamHeader() throws IOException, StreamCorruptedException{
   866         // no op
   867     }
   869     public final int readUnsignedByte() throws IOException{
   870         try{
   871             readObjectState.readData(this);
   873             return (orbStream.read_octet() << 0) & 0x000000FF;
   874         } catch (MARSHAL marshalException) {
   875             handleOptionalDataMarshalException(marshalException, false);
   876             throw marshalException;
   877         } catch(Error e) {
   878             IOException exc = new IOException(e.getMessage());
   879             exc.initCause(e);
   880             throw exc ;
   881         }
   882     }
   884     public final int readUnsignedShort() throws IOException{
   885         try{
   886             readObjectState.readData(this);
   888             return (orbStream.read_ushort() << 0) & 0x0000FFFF;
   889         } catch (MARSHAL marshalException) {
   890             handleOptionalDataMarshalException(marshalException, false);
   891             throw marshalException;
   892         } catch(Error e) {
   893             IOException exc = new IOException(e.getMessage());
   894             exc.initCause(e);
   895             throw exc ;
   896         }
   897     }
   899     /**
   900      * Helper method for correcting the Kestrel bug 4367783 (dealing
   901      * with larger than 8-bit chars).  The old behavior is preserved
   902      * in orbutil.IIOPInputStream_1_3 in order to interoperate with
   903      * our legacy ORBs.
   904      */
   905     protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream)
   906     {
   907         return stream.read_wstring();
   908     }
   910     public final String readUTF() throws IOException{
   911         try{
   912             readObjectState.readData(this);
   914             return internalReadUTF(orbStream);
   915         } catch (MARSHAL marshalException) {
   916             handleOptionalDataMarshalException(marshalException, false);
   917             throw marshalException;
   918         } catch(Error e) {
   919             IOException exc = new IOException(e.getMessage());
   920             exc.initCause(e);
   921             throw exc ;
   922         }
   923     }
   925     // If the ORB stream detects an incompatibility between what's
   926     // on the wire and what our Serializable's readObject wants,
   927     // it throws a MARSHAL exception with a specific minor code.
   928     // This is rethrown to the readObject as an OptionalDataException.
   929     // So far in RMI-IIOP, this process isn't specific enough to
   930     // tell the readObject how much data is available, so we always
   931     // set the OptionalDataException's EOF marker to true.
   932     private void handleOptionalDataMarshalException(MARSHAL marshalException,
   933                                                     boolean objectRead)
   934         throws IOException {
   936         // Java Object Serialization spec 3.4: "If the readObject method
   937         // of the class attempts to read more data than is present in the
   938         // optional part of the stream for this class, the stream will
   939         // return -1 for bytewise reads, throw an EOFException for
   940         // primitive data reads, or throw an OptionalDataException
   941         // with the eof field set to true for object reads."
   942         if (marshalException.minor
   943             == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   945             IOException result;
   947             if (!objectRead)
   948                 result = new EOFException("No more optional data");
   949             else
   950                 result = createOptionalDataException();
   952             result.initCause(marshalException);
   954             setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   956             throw result;
   957         }
   958     }
   960     public final synchronized void registerValidation(ObjectInputValidation obj,
   961                                                       int prio)
   962         throws NotActiveException, InvalidObjectException{
   963         // XXX I18N, logging needed.
   964         throw new Error("Method registerValidation not supported");
   965     }
   967     protected final Class resolveClass(ObjectStreamClass v)
   968         throws IOException, ClassNotFoundException{
   969         // XXX I18N, logging needed.
   970         throw new IOException("Method resolveClass not supported");
   971     }
   973     protected final Object resolveObject(Object obj) throws IOException{
   974         // XXX I18N, logging needed.
   975         throw new IOException("Method resolveObject not supported");
   976     }
   978     public final int skipBytes(int len) throws IOException{
   979         try{
   980             readObjectState.readData(this);
   982             byte buf[] = new byte[len];
   983             orbStream.read_octet_array(buf, 0, len);
   984             return len;
   985         } catch (MARSHAL marshalException) {
   986             handleOptionalDataMarshalException(marshalException, false);
   988             throw marshalException;
   989         } catch(Error e) {
   990             IOException exc = new IOException(e.getMessage());
   991             exc.initCause(e) ;
   992             throw exc ;
   993         }
   994     }
   996     private synchronized Object inputObject(Class clz,
   997                                String repositoryID,
   998                                com.sun.org.omg.SendingContext.CodeBase sender,
   999                                int offset)
  1000         throws IOException, ClassNotFoundException
  1003         /*
  1004          * Get the descriptor and then class of the incoming object.
  1005          */
  1007         currentClassDesc = ObjectStreamClass.lookup(clz);
  1008         currentClass = currentClassDesc.forClass();
  1009         //currentClassDesc.setClass(currentClass);
  1010         if (currentClass == null)
  1011             // XXX I18N, logging needed.
  1012             throw new ClassNotFoundException(currentClassDesc.getName());
  1014         try {
  1015             /* If Externalizable,
  1016              *  Create an instance and tell it to read its data.
  1017              * else,
  1018              *  Handle it as a serializable class.
  1019              */
  1020             if (Enum.class.isAssignableFrom( clz )) {
  1021                 int ordinal = orbStream.read_long() ;
  1022                 String value = (String)orbStream.read_value( String.class ) ;
  1023                 return Enum.valueOf( clz, value ) ;
  1024             } else if (currentClassDesc.isExternalizable()) {
  1025                 try {
  1026                     currentObject = (currentClass == null) ?
  1027                         null : currentClassDesc.newInstance();
  1028                     if (currentObject != null) {
  1030                         // Store this object and its beginning position
  1031                         // since there might be indirections to it while
  1032                         // it's been unmarshalled.
  1033                         activeRecursionMgr.addObject(offset, currentObject);
  1035                         // Read format version
  1036                         readFormatVersion();
  1038                         Externalizable ext = (Externalizable)currentObject;
  1039                         ext.readExternal(this);
  1041             } catch (InvocationTargetException e) {
  1042                 InvalidClassException exc = new InvalidClassException(
  1043                     currentClass.getName(),
  1044                     "InvocationTargetException accessing no-arg constructor");
  1045                 exc.initCause( e ) ;
  1046                 throw exc ;
  1047             } catch (UnsupportedOperationException e) {
  1048                 InvalidClassException exc = new InvalidClassException(
  1049                     currentClass.getName(),
  1050                     "UnsupportedOperationException accessing no-arg constructor");
  1051                 exc.initCause( e ) ;
  1052                 throw exc ;
  1053             } catch (InstantiationException e) {
  1054                 InvalidClassException exc = new InvalidClassException(
  1055                     currentClass.getName(),
  1056                     "InstantiationException accessing no-arg constructor");
  1057                 exc.initCause( e ) ;
  1058                 throw exc ;
  1060         } // end : if (currentClassDesc.isExternalizable())
  1061         else {
  1062             /* Count number of classes and descriptors we might have
  1063              * to work on.
  1064              */
  1066             ObjectStreamClass currdesc = currentClassDesc;
  1067             Class currclass = currentClass;
  1069             int spBase = spClass;       // current top of stack
  1071             if (currentClass.getName().equals("java.lang.String")) {
  1072                 return this.readUTF();
  1074             /* The object's classes should be processed from supertype to subtype
  1075              * Push all the clases of the current object onto a stack.
  1076              * Note that only the serializable classes are represented
  1077              * in the descriptor list.
  1079              * Handle versioning where one or more supertypes of
  1080              * have been inserted or removed.  The stack will
  1081              * contain pairs of descriptors and the corresponding
  1082              * class.  If the object has a class that did not occur in
  1083              * the original the descriptor will be null.  If the
  1084              * original object had a descriptor for a class not
  1085              * present in the local hierarchy of the object the class will be
  1086              * null.
  1088              */
  1090             /*
  1091              * This is your basic diff pattern, made simpler
  1092              * because reordering is not allowed.
  1093              */
  1094             // sun.4296963 ibm.11861
  1095             // d11861 we should stop when we find the highest serializable class
  1096             // We need this so that when we allocate the new object below, we
  1097             // can call the constructor of the non-serializable superclass.
  1098             // Note that in the JRMP variant of this code the
  1099             // ObjectStreamClass.lookup() method handles this, but we've put
  1100             // this fix here rather than change lookup because the new behaviour
  1101             // is needed in other cases.
  1103             for (currdesc = currentClassDesc, currclass = currentClass;
  1104                  currdesc != null && currdesc.isSerializable();   /*sun.4296963 ibm.11861*/
  1105                  currdesc = currdesc.getSuperclass()) {
  1107                 /*
  1108                  * Search the classes to see if the class of this
  1109                  * descriptor appears further up the hierarchy. Until
  1110                  * it's found assume its an inserted class.  If it's
  1111                  * not found, its the descriptor's class that has been
  1112                  * removed.
  1113                  */
  1114                 Class cc = currdesc.forClass();
  1115                 Class cl;
  1116                 for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  1117                     if (cc == cl) {
  1118                         // found a superclass that matches this descriptor
  1119                         break;
  1120                     } else {
  1121                         /* Ignore a class that doesn't match.  No
  1122                          * action is needed since it is already
  1123                          * initialized.
  1124                          */
  1126                 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
  1127                 /* Test if there is room for this new entry.
  1128                  * If not, double the size of the arrays and copy the contents.
  1129                  */
  1130                 spClass++;
  1131                 if (spClass >= classes.length) {
  1132                     int newlen = classes.length * 2;
  1133                     Class[] newclasses = new Class[newlen];
  1134                     ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  1136                     System.arraycopy(classes, 0,
  1137                                      newclasses, 0,
  1138                                      classes.length);
  1139                     System.arraycopy(classdesc, 0,
  1140                                      newclassdesc, 0,
  1141                                      classes.length);
  1143                     classes = newclasses;
  1144                     classdesc = newclassdesc;
  1147                 if (cl == null) {
  1148                     /* Class not found corresponding to this descriptor.
  1149                      * Pop off all the extra classes pushed.
  1150                      * Push the descriptor and a null class.
  1151                      */
  1152                     classdesc[spClass] = currdesc;
  1153                     classes[spClass] = null;
  1154                 } else {
  1155                     /* Current class descriptor matches current class.
  1156                      * Some classes may have been inserted.
  1157                      * Record the match and advance the class, continue
  1158                      * with the next descriptor.
  1159                      */
  1160                     classdesc[spClass] = currdesc;
  1161                     classes[spClass] = cl;
  1162                     currclass = cl.getSuperclass();
  1164             } // end : for (currdesc = currentClassDesc, currclass = currentClass;
  1166             /* Allocate a new object.  The object is only constructed
  1167              * above the highest serializable class and is set to
  1168              * default values for all more specialized classes.
  1169              */
  1170             try {
  1171                 currentObject = (currentClass == null) ?
  1172                     null : currentClassDesc.newInstance() ;
  1174                 // Store this object and its beginning position
  1175                 // since there might be indirections to it while
  1176                 // it's been unmarshalled.
  1177                 activeRecursionMgr.addObject(offset, currentObject);
  1178             } catch (InvocationTargetException e) {
  1179                 InvalidClassException exc = new InvalidClassException(
  1180                     currentClass.getName(),
  1181                     "InvocationTargetException accessing no-arg constructor");
  1182                 exc.initCause( e ) ;
  1183                 throw exc ;
  1184             } catch (UnsupportedOperationException e) {
  1185                 InvalidClassException exc = new InvalidClassException(
  1186                     currentClass.getName(),
  1187                     "UnsupportedOperationException accessing no-arg constructor");
  1188                 exc.initCause( e ) ;
  1189                 throw exc ;
  1190             } catch (InstantiationException e) {
  1191                 InvalidClassException exc = new InvalidClassException(
  1192                     currentClass.getName(),
  1193                     "InstantiationException accessing no-arg constructor");
  1194                 exc.initCause( e ) ;
  1195                 throw exc ;
  1198             /*
  1199              * For all the pushed descriptors and classes.
  1200              *  if the class has its own writeObject and readObject methods
  1201              *      call the readObject method
  1202              *  else
  1203              *      invoke the defaultReadObject method
  1204              */
  1205             try {
  1206                 for (spClass = spClass; spClass > spBase; spClass--) {
  1207                     /*
  1208                      * Set current descriptor and corresponding class
  1209                      */
  1210                     currentClassDesc = classdesc[spClass];
  1211                     currentClass = classes[spClass];
  1212                     if (classes[spClass] != null) {
  1213                         /* Read the data from the stream described by the
  1214                          * descriptor and store into the matching class.
  1215                          */
  1217                         ReadObjectState oldState = readObjectState;
  1218                         setState(DEFAULT_STATE);
  1220                         try {
  1222                             // Changed since invokeObjectReader no longer does this.
  1223                             if (currentClassDesc.hasWriteObject()) {
  1225                                 // Read format version
  1226                                 readFormatVersion();
  1228                                 // Read defaultWriteObject indicator
  1229                                 boolean calledDefaultWriteObject = readBoolean();
  1231                                 readObjectState.beginUnmarshalCustomValue(this,
  1232                                                                           calledDefaultWriteObject,
  1233                                                                           (currentClassDesc.readObjectMethod
  1234                                                                            != null));
  1235                             } else {
  1236                                 if (currentClassDesc.hasReadObject())
  1237                                     setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
  1240                             if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) ||
  1241                                 readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) {
  1243                                 // Error case of no readObject and didn't call
  1244                                 // defaultWriteObject handled in default state
  1246                                 ObjectStreamField[] fields =
  1247                                     currentClassDesc.getFieldsNoCopy();
  1248                                 if (fields.length > 0) {
  1249                                     inputClassFields(currentObject, currentClass, fields, sender);
  1253                             if (currentClassDesc.hasWriteObject())
  1254                                 readObjectState.endUnmarshalCustomValue(this);
  1256                         } finally {
  1257                             setState(oldState);
  1260                     } else {
  1262                         // _REVISIT_ : Can we ever get here?
  1263                         /* No local class for this descriptor,
  1264                          * Skip over the data for this class.
  1265                          * like defaultReadObject with a null currentObject.
  1266                          * The code will read the values but discard them.
  1267                          */
  1268                             ObjectStreamField[] fields =
  1269                                 currentClassDesc.getFieldsNoCopy();
  1270                             if (fields.length > 0) {
  1271                                 inputClassFields(null, currentClass, fields, sender);
  1277             } finally {
  1278                                 // Make sure we exit at the same stack level as when we started.
  1279                 spClass = spBase;
  1282         } finally {
  1283             // We've completed deserializing this object.  Any
  1284             // future indirections will be handled correctly at the
  1285             // CDR level.  The ActiveRecursionManager only deals with
  1286             // objects currently being deserialized.
  1287             activeRecursionMgr.removeObject(offset);
  1290         return currentObject;
  1293     // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
  1294     // repositoryID.  It is assumed that the sender will not provide base_value id's for non-serializable
  1295     // classes!
  1296     private Vector getOrderedDescriptions(String repositoryID,
  1297                                           com.sun.org.omg.SendingContext.CodeBase sender) {
  1298         Vector descs = new Vector();
  1300         if (sender == null) {
  1301             return descs;
  1304         FullValueDescription aFVD = sender.meta(repositoryID);
  1305         while (aFVD != null) {
  1306             descs.insertElementAt(aFVD, 0);
  1307             if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
  1308                 aFVD = sender.meta(aFVD.base_value);
  1310             else return descs;
  1313         return descs;
  1316     /**
  1317      * This input method uses FullValueDescriptions retrieved from the sender's runtime to
  1318      * read in the data.  This method is capable of throwing out data not applicable to client's fields.
  1319      * This method handles instances where the reader has a class not sent by the sender, the sender sent
  1320      * a class not present on the reader, and/or the reader's class does not match the sender's class.
  1322      * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
  1323      * indicates custom marsahling than the local type is used to read the data off the wire.  However,
  1324      * if either says custom while the other does not, a MARSHAL error is thrown.  Externalizable is
  1325      * a form of custom marshaling.
  1327      */
  1328     private synchronized Object inputObjectUsingFVD(Class clz,
  1329                                        String repositoryID,
  1330                                        com.sun.org.omg.SendingContext.CodeBase sender,
  1331                                        int offset)
  1332         throws IOException, ClassNotFoundException
  1334         int spBase = spClass;   // current top of stack
  1335         try{
  1337             /*
  1338              * Get the descriptor and then class of the incoming object.
  1339              */
  1341             ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
  1342             Class currclass = currentClass = clz;
  1344             /* If Externalizable,
  1345              *  Create an instance and tell it to read its data.
  1346              * else,
  1347              *  Handle it as a serializable class.
  1348              */
  1349             if (currentClassDesc.isExternalizable()) {
  1350                 try {
  1351                     currentObject = (currentClass == null) ?
  1352                         null : currentClassDesc.newInstance();
  1353                     if (currentObject != null) {
  1354                         // Store this object and its beginning position
  1355                         // since there might be indirections to it while
  1356                         // it's been unmarshalled.
  1357                         activeRecursionMgr.addObject(offset, currentObject);
  1359                         // Read format version
  1360                         readFormatVersion();
  1362                         Externalizable ext = (Externalizable)currentObject;
  1363                         ext.readExternal(this);
  1365                 } catch (InvocationTargetException e) {
  1366                     InvalidClassException exc = new InvalidClassException(
  1367                         currentClass.getName(),
  1368                         "InvocationTargetException accessing no-arg constructor");
  1369                     exc.initCause( e ) ;
  1370                     throw exc ;
  1371                 } catch (UnsupportedOperationException e) {
  1372                     InvalidClassException exc = new InvalidClassException(
  1373                         currentClass.getName(),
  1374                         "UnsupportedOperationException accessing no-arg constructor");
  1375                     exc.initCause( e ) ;
  1376                     throw exc ;
  1377                 } catch (InstantiationException e) {
  1378                     InvalidClassException exc = new InvalidClassException(
  1379                         currentClass.getName(),
  1380                         "InstantiationException accessing no-arg constructor");
  1381                     exc.initCause( e ) ;
  1382                     throw exc ;
  1384             } else {
  1385                 /*
  1386                  * This is your basic diff pattern, made simpler
  1387                  * because reordering is not allowed.
  1388                  */
  1389                 for (currdesc = currentClassDesc, currclass = currentClass;
  1390                      currdesc != null && currdesc.isSerializable();   /*sun.4296963 ibm.11861*/
  1392                      currdesc = currdesc.getSuperclass()) {
  1394                     /*
  1395                      * Search the classes to see if the class of this
  1396                      * descriptor appears further up the hierarchy. Until
  1397                      * it's found assume its an inserted class.  If it's
  1398                      * not found, its the descriptor's class that has been
  1399                      * removed.
  1400                      */
  1401                     Class cc = currdesc.forClass();
  1402                     Class cl;
  1403                     for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  1404                         if (cc == cl) {
  1405                             // found a superclass that matches this descriptor
  1406                             break;
  1407                         } else {
  1408                             /* Ignore a class that doesn't match.  No
  1409                              * action is needed since it is already
  1410                              * initialized.
  1411                              */
  1413                     } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
  1414                     /* Test if there is room for this new entry.
  1415                      * If not, double the size of the arrays and copy the contents.
  1416                      */
  1417                     spClass++;
  1418                     if (spClass >= classes.length) {
  1419                         int newlen = classes.length * 2;
  1420                         Class[] newclasses = new Class[newlen];
  1421                         ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  1423                         System.arraycopy(classes, 0,
  1424                                          newclasses, 0,
  1425                                          classes.length);
  1426                         System.arraycopy(classdesc, 0,
  1427                                          newclassdesc, 0,
  1428                                          classes.length);
  1430                         classes = newclasses;
  1431                         classdesc = newclassdesc;
  1434                     if (cl == null) {
  1435                         /* Class not found corresponding to this descriptor.
  1436                          * Pop off all the extra classes pushed.
  1437                          * Push the descriptor and a null class.
  1438                          */
  1439                         classdesc[spClass] = currdesc;
  1440                         classes[spClass] = null;
  1441                     } else {
  1442                         /* Current class descriptor matches current class.
  1443                          * Some classes may have been inserted.
  1444                          * Record the match and advance the class, continue
  1445                          * with the next descriptor.
  1446                          */
  1447                         classdesc[spClass] = currdesc;
  1448                         classes[spClass] = cl;
  1449                         currclass = cl.getSuperclass();
  1451                 } // end : for (currdesc = currentClassDesc, currclass = currentClass;
  1453                 /* Allocate a new object.
  1454                  */
  1455                 try {
  1456                     currentObject = (currentClass == null) ?
  1457                         null : currentClassDesc.newInstance();
  1459                     // Store this object and its beginning position
  1460                     // since there might be indirections to it while
  1461                     // it's been unmarshalled.
  1462                     activeRecursionMgr.addObject(offset, currentObject);
  1463                 } catch (InvocationTargetException e) {
  1464                     InvalidClassException exc = new InvalidClassException(
  1465                         currentClass.getName(),
  1466                         "InvocationTargetException accessing no-arg constructor");
  1467                     exc.initCause( e ) ;
  1468                     throw exc ;
  1469                 } catch (UnsupportedOperationException e) {
  1470                     InvalidClassException exc = new InvalidClassException(
  1471                         currentClass.getName(),
  1472                         "UnsupportedOperationException accessing no-arg constructor");
  1473                     exc.initCause( e ) ;
  1474                     throw exc ;
  1475                 } catch (InstantiationException e) {
  1476                     InvalidClassException exc = new InvalidClassException(
  1477                         currentClass.getName(),
  1478                         "InstantiationException accessing no-arg constructor");
  1479                     exc.initCause( e ) ;
  1480                     throw exc ;
  1483                 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
  1485                 while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
  1486                     FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1487                     // d4365188: backward compatability
  1488                     String repIDForFVD = vhandler.getClassName(fvd.id);
  1489                     String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
  1491                     while ((spClass > spBase) &&
  1492                            (!repIDForFVD.equals(repIDForClass))) {
  1493                         int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
  1494                         if (pos != -1) {
  1495                             spClass = pos;
  1496                             currclass = currentClass = classes[spClass];
  1497                             repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
  1499                         else { // Read and throw away one level of the fvdslist
  1501                             // This seems to mean that the sender had a superclass that
  1502                             // we don't have
  1504                             if (fvd.is_custom) {
  1506                                 readFormatVersion();
  1507                                 boolean calledDefaultWriteObject = readBoolean();
  1509                                 if (calledDefaultWriteObject)
  1510                                     inputClassFields(null, null, null, fvd.members, sender);
  1512                                 if (getStreamFormatVersion() == 2) {
  1514                                     ((ValueInputStream)getOrbStream()).start_value();
  1515                                     ((ValueInputStream)getOrbStream()).end_value();
  1518                                 // WARNING: If stream format version is 1 and there's
  1519                                 // optional data, we'll get some form of exception down
  1520                                 // the line or data corruption.
  1522                             } else {
  1524                                 inputClassFields(null, currentClass, null, fvd.members, sender);
  1527                             if (fvdsList.hasMoreElements()){
  1528                                 fvd = (FullValueDescription)fvdsList.nextElement();
  1529                                 repIDForFVD = vhandler.getClassName(fvd.id);
  1531                             else return currentObject;
  1535                     currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
  1537                     if (!repIDForClass.equals("java.lang.Object")) {
  1539                         // If the sender used custom marshaling, then it should have put
  1540                         // the two bytes on the wire indicating stream format version
  1541                         // and whether or not the writeObject method called
  1542                         // defaultWriteObject/writeFields.
  1544                         ReadObjectState oldState = readObjectState;
  1545                         setState(DEFAULT_STATE);
  1547                         try {
  1549                             if (fvd.is_custom) {
  1551                                 // Read format version
  1552                                 readFormatVersion();
  1554                                 // Read defaultWriteObject indicator
  1555                                 boolean calledDefaultWriteObject = readBoolean();
  1557                                 readObjectState.beginUnmarshalCustomValue(this,
  1558                                                                           calledDefaultWriteObject,
  1559                                                                           (currentClassDesc.readObjectMethod
  1560                                                                            != null));
  1563                             boolean usedReadObject = false;
  1565                             // Always use readObject if it exists, and fall back to default
  1566                             // unmarshaling if it doesn't.
  1567                             try {
  1569                                 if (!fvd.is_custom && currentClassDesc.hasReadObject())
  1570                                     setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
  1572                                 // See the definition of defaultReadObjectFVDMembers
  1573                                 // for more information.  This concerns making sure
  1574                                 // we use the remote FVD's members in defaultReadObject.
  1575                                 defaultReadObjectFVDMembers = fvd.members;
  1576                                 usedReadObject = invokeObjectReader(currentClassDesc,
  1577                                                                     currentObject,
  1578                                                                     currentClass);
  1580                             } finally {
  1581                                 defaultReadObjectFVDMembers = null;
  1584                             // Note that the !usedReadObject !calledDefaultWriteObject
  1585                             // case is handled by the beginUnmarshalCustomValue method
  1586                             // of the default state
  1587                             if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT)
  1588                                 inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
  1590                             if (fvd.is_custom)
  1591                                 readObjectState.endUnmarshalCustomValue(this);
  1593                         } finally {
  1594                             setState(oldState);
  1597                         currclass = currentClass = classes[--spClass];
  1599                     } else {
  1601                         // The remaining hierarchy of the local class does not match the sender's FVD.
  1602                         // So, use remaining FVDs to read data off wire.  If any remaining FVDs indicate
  1603                         // custom marshaling, throw MARSHAL error.
  1604                         inputClassFields(null, currentClass, null, fvd.members, sender);
  1606                         while (fvdsList.hasMoreElements()){
  1607                             fvd = (FullValueDescription)fvdsList.nextElement();
  1609                             if (fvd.is_custom)
  1610                                 skipCustomUsingFVD(fvd.members, sender);
  1611                             else
  1612                                 inputClassFields(null, currentClass, null, fvd.members, sender);
  1617                 } // end : while(fvdsList.hasMoreElements())
  1618                 while (fvdsList.hasMoreElements()){
  1620                     FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1621                     if (fvd.is_custom)
  1622                         skipCustomUsingFVD(fvd.members, sender);
  1623                     else
  1624                         throwAwayData(fvd.members, sender);
  1628             return currentObject;
  1630         finally {
  1631                 // Make sure we exit at the same stack level as when we started.
  1632                 spClass = spBase;
  1634                 // We've completed deserializing this object.  Any
  1635                 // future indirections will be handled correctly at the
  1636                 // CDR level.  The ActiveRecursionManager only deals with
  1637                 // objects currently being deserialized.
  1638                 activeRecursionMgr.removeObject(offset);
  1643     /**
  1644      * This input method uses FullValueDescriptions retrieved from the sender's runtime to
  1645      * read in the data.  This method is capable of throwing out data not applicable to client's fields.
  1647      * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
  1648      * indicates custom marsahling than the local type is used to read the data off the wire.  However,
  1649      * if either says custom while the other does not, a MARSHAL error is thrown.  Externalizable is
  1650      * a form of custom marshaling.
  1652      */
  1653     private Object skipObjectUsingFVD(String repositoryID,
  1654                                       com.sun.org.omg.SendingContext.CodeBase sender)
  1655         throws IOException, ClassNotFoundException
  1658         Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
  1660         while(fvdsList.hasMoreElements()) {
  1661             FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1662             String repIDForFVD = vhandler.getClassName(fvd.id);
  1664             if (!repIDForFVD.equals("java.lang.Object")) {
  1665                 if (fvd.is_custom) {
  1667                     readFormatVersion();
  1669                     boolean calledDefaultWriteObject = readBoolean();
  1671                     if (calledDefaultWriteObject)
  1672                         inputClassFields(null, null, null, fvd.members, sender);
  1674                     if (getStreamFormatVersion() == 2) {
  1676                         ((ValueInputStream)getOrbStream()).start_value();
  1677                         ((ValueInputStream)getOrbStream()).end_value();
  1680                     // WARNING: If stream format version is 1 and there's
  1681                     // optional data, we'll get some form of exception down
  1682                     // the line.
  1684                 } else {
  1685                     // Use default marshaling
  1686                     inputClassFields(null, null, null, fvd.members, sender);
  1690         } // end : while(fvdsList.hasMoreElements())
  1691         return null;
  1695     ///////////////////
  1697     private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){
  1699         for (int i = _spClass; i > _spBase; i--){
  1700             if (classname.equals(classes[i].getName())) {
  1701                 return i;
  1705         return -1;
  1708     /*
  1709      * Invoke the readObject method if present.  Assumes that in the case of custom
  1710      * marshaling, the format version and defaultWriteObject indicator were already
  1711      * removed.
  1712      */
  1713     private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass)
  1714         throws InvalidClassException, StreamCorruptedException,
  1715                ClassNotFoundException, IOException
  1717         if (osc.readObjectMethod == null) {
  1718             return false;
  1721         try {
  1722             osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
  1723             return true;
  1724         } catch (InvocationTargetException e) {
  1725             Throwable t = e.getTargetException();
  1726             if (t instanceof ClassNotFoundException)
  1727                 throw (ClassNotFoundException)t;
  1728             else if (t instanceof IOException)
  1729                 throw (IOException)t;
  1730             else if (t instanceof RuntimeException)
  1731                 throw (RuntimeException) t;
  1732             else if (t instanceof Error)
  1733                 throw (Error) t;
  1734             else
  1735                 // XXX I18N, logging needed.
  1736                 throw new Error("internal error");
  1737         } catch (IllegalAccessException e) {
  1738             return false;
  1742     /*
  1743      * Reset the stream to be just like it was after the constructor.
  1744      */
  1745     private void resetStream() throws IOException {
  1747         if (classes == null)
  1748             classes = new Class[20];
  1749         else {
  1750             for (int i = 0; i < classes.length; i++)
  1751                 classes[i] = null;
  1753         if (classdesc == null)
  1754             classdesc = new ObjectStreamClass[20];
  1755         else {
  1756             for (int i = 0; i < classdesc.length; i++)
  1757                 classdesc[i] = null;
  1759         spClass = 0;
  1761         if (callbacks != null)
  1762             callbacks.setSize(0);       // discard any pending callbacks
  1765     /**
  1766      * Factored out of inputClassFields  This reads a primitive value and sets it
  1767      * in the field of o described by the ObjectStreamField field.
  1769      * Note that reflection cannot be used here, because reflection cannot be used
  1770      * to set final fields.
  1771      */
  1772     private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field)
  1773         throws InvalidClassException, IOException {
  1775         try {
  1776             switch (field.getTypeCode()) {
  1777                 case 'B':
  1778                     byte byteValue = orbStream.read_octet();
  1779                     if (field.getField() != null) {
  1780                         bridge.putByte( o, field.getFieldID(), byteValue ) ;
  1781                         //reflective code: field.getField().setByte( o, byteValue ) ;
  1783                     break;
  1784                 case 'Z':
  1785                     boolean booleanValue = orbStream.read_boolean();
  1786                     if (field.getField() != null) {
  1787                         bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
  1788                         //reflective code: field.getField().setBoolean( o, booleanValue ) ;
  1790                     break;
  1791                 case 'C':
  1792                     char charValue = orbStream.read_wchar();
  1793                     if (field.getField() != null) {
  1794                         bridge.putChar( o, field.getFieldID(), charValue ) ;
  1795                         //reflective code: field.getField().setChar( o, charValue ) ;
  1797                     break;
  1798                 case 'S':
  1799                     short shortValue = orbStream.read_short();
  1800                     if (field.getField() != null) {
  1801                         bridge.putShort( o, field.getFieldID(), shortValue ) ;
  1802                         //reflective code: field.getField().setShort( o, shortValue ) ;
  1804                     break;
  1805                 case 'I':
  1806                     int intValue = orbStream.read_long();
  1807                     if (field.getField() != null) {
  1808                         bridge.putInt( o, field.getFieldID(), intValue ) ;
  1809                         //reflective code: field.getField().setInt( o, intValue ) ;
  1811                     break;
  1812                 case 'J':
  1813                     long longValue = orbStream.read_longlong();
  1814                     if (field.getField() != null) {
  1815                         bridge.putLong( o, field.getFieldID(), longValue ) ;
  1816                         //reflective code: field.getField().setLong( o, longValue ) ;
  1818                     break;
  1819                 case 'F' :
  1820                     float floatValue = orbStream.read_float();
  1821                     if (field.getField() != null) {
  1822                         bridge.putFloat( o, field.getFieldID(), floatValue ) ;
  1823                         //reflective code: field.getField().setFloat( o, floatValue ) ;
  1825                     break;
  1826                 case 'D' :
  1827                     double doubleValue = orbStream.read_double();
  1828                     if (field.getField() != null) {
  1829                         bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
  1830                         //reflective code: field.getField().setDouble( o, doubleValue ) ;
  1832                     break;
  1833                 default:
  1834                     // XXX I18N, logging needed.
  1835                     throw new InvalidClassException(cl.getName());
  1837         } catch (IllegalArgumentException e) {
  1838             /* This case should never happen. If the field types
  1839                are not the same, InvalidClassException is raised when
  1840                matching the local class to the serialized ObjectStreamClass. */
  1841             ClassCastException cce = new ClassCastException("Assigning instance of class " +
  1842                                          field.getType().getName() +
  1843                                          " to field " +
  1844                                          currentClassDesc.getName() + '#' +
  1845                                          field.getField().getName());
  1846             cce.initCause( e ) ;
  1847             throw cce ;
  1851     private Object inputObjectField(org.omg.CORBA.ValueMember field,
  1852                                     com.sun.org.omg.SendingContext.CodeBase sender)
  1853         throws IndirectionException, ClassNotFoundException, IOException,
  1854                StreamCorruptedException {
  1856         Object objectValue = null;
  1857         Class type = null;
  1858         String id = field.id;
  1860         try {
  1861             type = vhandler.getClassFromType(id);
  1862         } catch(ClassNotFoundException cnfe) {
  1863             // Make sure type = null
  1864             type = null;
  1867         String signature = null;
  1868         if (type != null)
  1869             signature = ValueUtility.getSignature(field);
  1871         if (signature != null && (signature.equals("Ljava/lang/Object;") ||
  1872                                   signature.equals("Ljava/io/Serializable;") ||
  1873                                   signature.equals("Ljava/io/Externalizable;"))) {
  1874             objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
  1875         } else {
  1876             // Decide what method call to make based on the type. If
  1877             // it is a type for which we need to load a stub, convert
  1878             // the type to the correct stub type.
  1879             //
  1880             // NOTE : Since FullValueDescription does not allow us
  1881             // to ask whether something is an interface we do not
  1882             // have the ability to optimize this check.
  1884             int callType = ValueHandlerImpl.kValueType;
  1886             if (!vhandler.isSequence(id)) {
  1888                 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
  1890                     // RMI Object reference...
  1891                     callType = ValueHandlerImpl.kRemoteType;
  1893                 } else {
  1895                     // REVISIT.  If we don't have the local class,
  1896                     // we should probably verify that it's an RMI type,
  1897                     // query the remote FVD, and use is_abstract.
  1898                     // Our FVD seems to get NullPointerExceptions for any
  1899                     // non-RMI types.
  1901                     // This uses the local class in the same way as
  1902                     // inputObjectField(ObjectStreamField) does.  REVISIT
  1903                     // inputObjectField(ObjectStreamField)'s loadStubClass
  1904                     // logic.  Assumption is that the given type cannot
  1905                     // evolve to become a CORBA abstract interface or
  1906                     // a RMI abstract interface.
  1908                     if (type != null && type.isInterface() &&
  1909                         (vhandler.isAbstractBase(type) ||
  1910                          ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
  1912                         callType = ValueHandlerImpl.kAbstractType;
  1917             // Now that we have used the FVD of the field to determine the proper course
  1918             // of action, it is ok to use the type (Class) from this point forward since
  1919             // the rep. id for this read will also follow on the wire.
  1921             switch (callType) {
  1922                 case ValueHandlerImpl.kRemoteType:
  1923                     if (type != null)
  1924                         objectValue = Utility.readObjectAndNarrow(orbStream, type);
  1925                     else
  1926                         objectValue = orbStream.read_Object();
  1927                     break;
  1928                 case ValueHandlerImpl.kAbstractType:
  1929                     if (type != null)
  1930                         objectValue = Utility.readAbstractAndNarrow(orbStream, type);
  1931                     else
  1932                         objectValue = orbStream.read_abstract_interface();
  1933                     break;
  1934                 case ValueHandlerImpl.kValueType:
  1935                     if (type != null)
  1936                         objectValue = orbStream.read_value(type);
  1937                     else
  1938                                             objectValue = orbStream.read_value();
  1939                     break;
  1940                 default:
  1941                     // XXX I18N, logging needed.
  1942                     throw new StreamCorruptedException("Unknown callType: " + callType);
  1946         return objectValue;
  1949     /**
  1950      * Factored out of inputClassFields and reused in
  1951      * inputCurrentClassFieldsForReadFields.
  1953      * Reads the field (which of an Object type as opposed to a primitive)
  1954      * described by ObjectStreamField field and returns it.
  1955      */
  1956     private Object inputObjectField(ObjectStreamField field)
  1957         throws InvalidClassException, StreamCorruptedException,
  1958                ClassNotFoundException, IndirectionException, IOException {
  1960         if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
  1961             return javax.rmi.CORBA.Util.readAny(orbStream);
  1964         Object objectValue = null;
  1966         // fields have an API to provide the actual class
  1967         // corresponding to the data type
  1968         // Class type = osc.forClass();
  1969         Class fieldType = field.getType();
  1970         Class actualType = fieldType; // This may change if stub loaded.
  1972         // Decide what method call to make based on the fieldType. If
  1973         // it is a type for which we need to load a stub, convert
  1974         // the type to the correct stub type.
  1976         int callType = ValueHandlerImpl.kValueType;
  1977         boolean narrow = false;
  1979         if (fieldType.isInterface()) {
  1980             boolean loadStubClass = false;
  1982             if (java.rmi.Remote.class.isAssignableFrom(fieldType)) {
  1984                 // RMI Object reference...
  1985                 callType = ValueHandlerImpl.kRemoteType;
  1987             } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){
  1989                 // IDL Object reference...
  1990                 callType = ValueHandlerImpl.kRemoteType;
  1991                 loadStubClass = true;
  1993             } else if (vhandler.isAbstractBase(fieldType)) {
  1994                 // IDL Abstract Object reference...
  1996                 callType = ValueHandlerImpl.kAbstractType;
  1997                 loadStubClass = true;
  1998             } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
  1999                 // RMI Abstract Object reference...
  2001                 callType = ValueHandlerImpl.kAbstractType;
  2004             if (loadStubClass) {
  2005                 try {
  2006                     String codebase = Util.getCodebase(fieldType);
  2007                     String repID = vhandler.createForAnyType(fieldType);
  2008                     Class stubType =
  2009                         Utility.loadStubClass(repID, codebase, fieldType);
  2010                     actualType = stubType;
  2011                 } catch (ClassNotFoundException e) {
  2012                     narrow = true;
  2014             } else {
  2015                 narrow = true;
  2019         switch (callType) {
  2020             case ValueHandlerImpl.kRemoteType:
  2021                 if (!narrow)
  2022                     objectValue = (Object)orbStream.read_Object(actualType);
  2023                 else
  2024                     objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
  2025                 break;
  2026             case ValueHandlerImpl.kAbstractType:
  2027                 if (!narrow)
  2028                     objectValue = (Object)orbStream.read_abstract_interface(actualType);
  2029                 else
  2030                     objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
  2031                 break;
  2032             case ValueHandlerImpl.kValueType:
  2033                 objectValue = (Object)orbStream.read_value(actualType);
  2034                 break;
  2035             default:
  2036                 // XXX I18N, logging needed.
  2037                 throw new StreamCorruptedException("Unknown callType: " + callType);
  2040         return objectValue;
  2043     private final boolean mustUseRemoteValueMembers() {
  2044         return defaultReadObjectFVDMembers != null;
  2047     void readFields(java.util.Map fieldToValueMap)
  2048         throws InvalidClassException, StreamCorruptedException,
  2049                ClassNotFoundException, IOException {
  2051         if (mustUseRemoteValueMembers()) {
  2052             inputRemoteMembersForReadFields(fieldToValueMap);
  2053         } else
  2054             inputCurrentClassFieldsForReadFields(fieldToValueMap);
  2057     private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
  2058         throws InvalidClassException, StreamCorruptedException,
  2059                ClassNotFoundException, IOException {
  2061         // Must have this local variable since defaultReadObjectFVDMembers
  2062         // may get mangled by recursion.
  2063         ValueMember fields[] = defaultReadObjectFVDMembers;
  2065         try {
  2067             for (int i = 0; i < fields.length; i++) {
  2069                 switch (fields[i].type.kind().value()) {
  2071                 case TCKind._tk_octet:
  2072                     byte byteValue = orbStream.read_octet();
  2073                     fieldToValueMap.put(fields[i].name, new Byte(byteValue));
  2074                     break;
  2075                 case TCKind._tk_boolean:
  2076                     boolean booleanValue = orbStream.read_boolean();
  2077                     fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
  2078                     break;
  2079                 case TCKind._tk_char:
  2080                     // Backwards compatibility.  Older Sun ORBs sent
  2081                     // _tk_char even though they read and wrote wchars
  2082                     // correctly.
  2083                     //
  2084                     // Fall through to the _tk_wchar case.
  2085                 case TCKind._tk_wchar:
  2086                     char charValue = orbStream.read_wchar();
  2087                     fieldToValueMap.put(fields[i].name, new Character(charValue));
  2088                     break;
  2089                 case TCKind._tk_short:
  2090                     short shortValue = orbStream.read_short();
  2091                     fieldToValueMap.put(fields[i].name, new Short(shortValue));
  2092                     break;
  2093                 case TCKind._tk_long:
  2094                     int intValue = orbStream.read_long();
  2095                     fieldToValueMap.put(fields[i].name, new Integer(intValue));
  2096                     break;
  2097                 case TCKind._tk_longlong:
  2098                     long longValue = orbStream.read_longlong();
  2099                     fieldToValueMap.put(fields[i].name, new Long(longValue));
  2100                     break;
  2101                 case TCKind._tk_float:
  2102                     float floatValue = orbStream.read_float();
  2103                     fieldToValueMap.put(fields[i].name, new Float(floatValue));
  2104                     break;
  2105                 case TCKind._tk_double:
  2106                     double doubleValue = orbStream.read_double();
  2107                     fieldToValueMap.put(fields[i].name, new Double(doubleValue));
  2108                     break;
  2109                 case TCKind._tk_value:
  2110                 case TCKind._tk_objref:
  2111                 case TCKind._tk_value_box:
  2112                     Object objectValue = null;
  2113                     try {
  2114                         objectValue = inputObjectField(fields[i],
  2115                                                        cbSender);
  2117                     } catch (IndirectionException cdrie) {
  2118                         // The CDR stream had never seen the given offset before,
  2119                         // so check the recursion manager (it will throw an
  2120                         // IOException if it doesn't have a reference, either).
  2121                         objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2124                     fieldToValueMap.put(fields[i].name, objectValue);
  2125                     break;
  2126                 default:
  2127                     // XXX I18N, logging needed.
  2128                     throw new StreamCorruptedException("Unknown kind: "
  2129                                                        + fields[i].type.kind().value());
  2132         } catch (Throwable t) {
  2133             StreamCorruptedException result = new StreamCorruptedException(t.getMessage());
  2134             result.initCause(t);
  2135             throw result;
  2139     /**
  2140      * Called from InputStreamHook.
  2142      * Reads the fields of the current class (could be the ones
  2143      * queried from the remote FVD) and puts them in
  2144      * the given Map, name to value.  Wraps primitives in the
  2145      * corresponding java.lang Objects.
  2146      */
  2147     private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
  2148         throws InvalidClassException, StreamCorruptedException,
  2149                ClassNotFoundException, IOException {
  2151         ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
  2153         int primFields = fields.length - currentClassDesc.objFields;
  2155         // Handle the primitives first
  2156         for (int i = 0; i < primFields; ++i) {
  2158             switch (fields[i].getTypeCode()) {
  2159                 case 'B':
  2160                     byte byteValue = orbStream.read_octet();
  2161                     fieldToValueMap.put(fields[i].getName(),
  2162                                         new Byte(byteValue));
  2163                     break;
  2164                 case 'Z':
  2165                    boolean booleanValue = orbStream.read_boolean();
  2166                    fieldToValueMap.put(fields[i].getName(),
  2167                                        new Boolean(booleanValue));
  2168                    break;
  2169                 case 'C':
  2170                     char charValue = orbStream.read_wchar();
  2171                     fieldToValueMap.put(fields[i].getName(),
  2172                                         new Character(charValue));
  2173                     break;
  2174                 case 'S':
  2175                     short shortValue = orbStream.read_short();
  2176                     fieldToValueMap.put(fields[i].getName(),
  2177                                         new Short(shortValue));
  2178                     break;
  2179                 case 'I':
  2180                     int intValue = orbStream.read_long();
  2181                     fieldToValueMap.put(fields[i].getName(),
  2182                                         new Integer(intValue));
  2183                     break;
  2184                 case 'J':
  2185                     long longValue = orbStream.read_longlong();
  2186                     fieldToValueMap.put(fields[i].getName(),
  2187                                         new Long(longValue));
  2188                     break;
  2189                 case 'F' :
  2190                     float floatValue = orbStream.read_float();
  2191                     fieldToValueMap.put(fields[i].getName(),
  2192                                         new Float(floatValue));
  2193                     break;
  2194                 case 'D' :
  2195                     double doubleValue = orbStream.read_double();
  2196                     fieldToValueMap.put(fields[i].getName(),
  2197                                         new Double(doubleValue));
  2198                     break;
  2199                 default:
  2200                     // XXX I18N, logging needed.
  2201                     throw new InvalidClassException(currentClassDesc.getName());
  2205         /* Read and set object fields from the input stream. */
  2206         if (currentClassDesc.objFields > 0) {
  2207             for (int i = primFields; i < fields.length; i++) {
  2208                 Object objectValue = null;
  2209                 try {
  2210                     objectValue = inputObjectField(fields[i]);
  2211                 } catch(IndirectionException cdrie) {
  2212                     // The CDR stream had never seen the given offset before,
  2213                     // so check the recursion manager (it will throw an
  2214                     // IOException if it doesn't have a reference, either).
  2215                     objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2218                 fieldToValueMap.put(fields[i].getName(), objectValue);
  2223     /*
  2224      * Read the fields of the specified class from the input stream and set
  2225      * the values of the fields in the specified object. If the specified
  2226      * object is null, just consume the fields without setting any values. If
  2227      * any ObjectStreamField does not have a reflected Field, don't try to set
  2228      * that field in the object.
  2230      * REVISIT -- This code doesn't do what the comment says to when
  2231      * getField() is null!
  2232      */
  2233     private void inputClassFields(Object o, final Class<?> cl,
  2234                                   ObjectStreamField[] fields,
  2235                                   com.sun.org.omg.SendingContext.CodeBase sender)
  2236         throws InvalidClassException, StreamCorruptedException,
  2237                ClassNotFoundException, IOException
  2240         int primFields = fields.length - currentClassDesc.objFields;
  2242         if (o != null) {
  2243             for (int i = 0; i < primFields; ++i) {
  2244                 inputPrimitiveField(o, cl, fields[i]);
  2248         /* Read and set object fields from the input stream. */
  2249         if (currentClassDesc.objFields > 0) {
  2250             for (int i = primFields; i < fields.length; i++) {
  2251                 Object objectValue = null;
  2253                 try {
  2254                     objectValue = inputObjectField(fields[i]);
  2255                 } catch(IndirectionException cdrie) {
  2256                     // The CDR stream had never seen the given offset before,
  2257                     // so check the recursion manager (it will throw an
  2258                     // IOException if it doesn't have a reference, either).
  2259                     objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2262                 if ((o == null) || (fields[i].getField() == null)) {
  2263                     continue;
  2266                 try {
  2267                     Class<?> fieldCl = fields[i].getClazz();
  2268                     if ((objectValue != null)
  2269                             && (!fieldCl.isAssignableFrom(
  2270                                     objectValue.getClass()))) {
  2271                         throw new IllegalArgumentException("Field mismatch");
  2273                     Field declaredClassField = null;
  2274                     final String inputStreamFieldName = fields[i].getName();
  2275                     try {
  2276                         declaredClassField = getDeclaredField( cl, inputStreamFieldName);
  2277                     } catch (PrivilegedActionException paEx) {
  2278                         throw new IllegalArgumentException(
  2279                             (NoSuchFieldException) paEx.getException());
  2280                     } catch (SecurityException secEx) {
  2281                         throw new IllegalArgumentException(secEx);
  2282                     }  catch (NullPointerException npEx) {
  2283                         continue;
  2284                     } catch (NoSuchFieldException e) {
  2285                         continue;
  2288                     if (declaredClassField == null) {
  2289                         continue;
  2291                     Class<?> declaredFieldClass = declaredClassField.getType();
  2293                     // check input field type is a declared field type
  2294                     // input field is a subclass of the declared field
  2295                     if (!declaredFieldClass.isAssignableFrom(fieldCl)) {
  2296                         throw new IllegalArgumentException(
  2297                                 "Field Type mismatch");
  2299                     if (objectValue != null && !fieldCl.isInstance(objectValue)) {
  2300                         throw new IllegalArgumentException();
  2302                     bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
  2303                     // reflective code: fields[i].getField().set( o, objectValue ) ;
  2304                 } catch (IllegalArgumentException iaEx) {
  2305                     String objectValueClassName = "null";
  2306                     String currentClassDescClassName = "null";
  2307                     String fieldName = "null";
  2308                     if (objectValue != null) {
  2309                         objectValueClassName = objectValue.getClass().getName();
  2311                     if (currentClassDesc != null) {
  2312                         currentClassDescClassName = currentClassDesc.getName();
  2314                     if (fields[i] != null && fields[i].getField() != null) {
  2315                         fieldName = fields[i].getField().getName();
  2317                     ClassCastException ccEx = new ClassCastException(
  2318                             "Assigning instance of class " + objectValueClassName
  2319                                     + " to field " + currentClassDescClassName + '#' + fieldName);
  2320                     ccEx.initCause( iaEx ) ;
  2321                     throw ccEx ;
  2323             } // end : for loop
  2327     /*
  2328      * Read the fields of the specified class from the input stream and set
  2329      * the values of the fields in the specified object. If the specified
  2330      * object is null, just consume the fields without setting any values. If
  2331      * any ObjectStreamField does not have a reflected Field, don't try to set
  2332      * that field in the object.
  2333      */
  2334     private void inputClassFields(Object o, Class cl,
  2335                                   ObjectStreamClass osc,
  2336                                   ValueMember[] fields,
  2337                                   com.sun.org.omg.SendingContext.CodeBase sender)
  2338         throws InvalidClassException, StreamCorruptedException,
  2339                ClassNotFoundException, IOException
  2341         try{
  2342             for (int i = 0; i < fields.length; ++i) {
  2343                 try {
  2344                     switch (fields[i].type.kind().value()) {
  2345                     case TCKind._tk_octet:
  2346                         byte byteValue = orbStream.read_octet();
  2347                         if ((o != null) && osc.hasField(fields[i]))
  2348                         setByteField(o, cl, fields[i].name, byteValue);
  2349                         break;
  2350                     case TCKind._tk_boolean:
  2351                         boolean booleanValue = orbStream.read_boolean();
  2352                         if ((o != null) && osc.hasField(fields[i]))
  2353                         setBooleanField(o, cl, fields[i].name, booleanValue);
  2354                         break;
  2355                     case TCKind._tk_char:
  2356                         // Backwards compatibility.  Older Sun ORBs sent
  2357                         // _tk_char even though they read and wrote wchars
  2358                         // correctly.
  2359                         //
  2360                         // Fall through to the _tk_wchar case.
  2361                     case TCKind._tk_wchar:
  2362                         char charValue = orbStream.read_wchar();
  2363                         if ((o != null) && osc.hasField(fields[i]))
  2364                         setCharField(o, cl, fields[i].name, charValue);
  2365                         break;
  2366                     case TCKind._tk_short:
  2367                         short shortValue = orbStream.read_short();
  2368                         if ((o != null) && osc.hasField(fields[i]))
  2369                         setShortField(o, cl, fields[i].name, shortValue);
  2370                         break;
  2371                     case TCKind._tk_long:
  2372                         int intValue = orbStream.read_long();
  2373                         if ((o != null) && osc.hasField(fields[i]))
  2374                         setIntField(o, cl, fields[i].name, intValue);
  2375                         break;
  2376                     case TCKind._tk_longlong:
  2377                         long longValue = orbStream.read_longlong();
  2378                         if ((o != null) && osc.hasField(fields[i]))
  2379                         setLongField(o, cl, fields[i].name, longValue);
  2380                         break;
  2381                     case TCKind._tk_float:
  2382                         float floatValue = orbStream.read_float();
  2383                         if ((o != null) && osc.hasField(fields[i]))
  2384                         setFloatField(o, cl, fields[i].name, floatValue);
  2385                         break;
  2386                     case TCKind._tk_double:
  2387                         double doubleValue = orbStream.read_double();
  2388                         if ((o != null) && osc.hasField(fields[i]))
  2389                         setDoubleField(o, cl, fields[i].name, doubleValue);
  2390                         break;
  2391                     case TCKind._tk_value:
  2392                     case TCKind._tk_objref:
  2393                     case TCKind._tk_value_box:
  2394                         Object objectValue = null;
  2395                         try {
  2396                             objectValue = inputObjectField(fields[i], sender);
  2397                         } catch (IndirectionException cdrie) {
  2398                             // The CDR stream had never seen the given offset before,
  2399                             // so check the recursion manager (it will throw an
  2400                             // IOException if it doesn't have a reference, either).
  2401                             objectValue = activeRecursionMgr.getObject(cdrie.offset);
  2404                         if (o == null)
  2405                             continue;
  2406                         try {
  2407                             if (osc.hasField(fields[i])){
  2408                                 setObjectField(o,
  2409                                                cl,
  2410                                                fields[i].name,
  2411                                                objectValue);
  2412                             } else {
  2413                                 // REVISIT.  Convert to a log message.
  2414                                 // This is a normal case when fields have
  2415                                 // been added as part of evolution, but
  2416                                 // silently skipping can make it hard to
  2417                                 // debug if there's an error
  2418 //                                 System.out.println("**** warning, not setting field: "
  2419 //                                                    + fields[i].name
  2420 //                                                    + " since not on class "
  2421 //                                                    + osc.getName());
  2424                         } catch (IllegalArgumentException e) {
  2425                             // XXX I18N, logging needed.
  2426                             ClassCastException cce = new ClassCastException("Assigning instance of class " +
  2427                                 objectValue.getClass().getName() + " to field " + fields[i].name);
  2428                             cce.initCause(e) ;
  2429                             throw cce ;
  2431                         break;
  2432                     default:
  2433                         // XXX I18N, logging needed.
  2434                         throw new StreamCorruptedException("Unknown kind: "
  2435                                                            + fields[i].type.kind().value());
  2437                 } catch (IllegalArgumentException e) {
  2438                     /* This case should never happen. If the field types
  2439                        are not the same, InvalidClassException is raised when
  2440                        matching the local class to the serialized ObjectStreamClass. */
  2441                     // XXX I18N, logging needed.
  2442                     ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id +
  2443                         " to field " + currentClassDesc.getName() + '#' + fields[i].name);
  2444                     cce.initCause( e ) ;
  2445                     throw cce ;
  2448         } catch(Throwable t){
  2449             // XXX I18N, logging needed.
  2450             StreamCorruptedException sce = new StreamCorruptedException(t.getMessage());
  2451             sce.initCause(t) ;
  2452             throw sce ;
  2456     private void skipCustomUsingFVD(ValueMember[] fields,
  2457                                     com.sun.org.omg.SendingContext.CodeBase sender)
  2458                                     throws InvalidClassException, StreamCorruptedException,
  2459                                            ClassNotFoundException, IOException
  2461         readFormatVersion();
  2462         boolean calledDefaultWriteObject = readBoolean();
  2464         if (calledDefaultWriteObject)
  2465             throwAwayData(fields, sender);
  2467         if (getStreamFormatVersion() == 2) {
  2469             ((ValueInputStream)getOrbStream()).start_value();
  2470             ((ValueInputStream)getOrbStream()).end_value();
  2474     /*
  2475      * Read the fields of the specified class from the input stream throw data away.
  2476      * This must handle same switch logic as above.
  2477      */
  2478     private void throwAwayData(ValueMember[] fields,
  2479                                com.sun.org.omg.SendingContext.CodeBase sender)
  2480         throws InvalidClassException, StreamCorruptedException,
  2481                ClassNotFoundException, IOException {
  2483         for (int i = 0; i < fields.length; ++i) {
  2485             try {
  2487                 switch (fields[i].type.kind().value()) {
  2488                 case TCKind._tk_octet:
  2489                     orbStream.read_octet();
  2490                     break;
  2491                 case TCKind._tk_boolean:
  2492                     orbStream.read_boolean();
  2493                     break;
  2494                 case TCKind._tk_char:
  2495                     // Backwards compatibility.  Older Sun ORBs sent
  2496                     // _tk_char even though they read and wrote wchars
  2497                     // correctly.
  2498                     //
  2499                     // Fall through to the _tk_wchar case.
  2500                 case TCKind._tk_wchar:
  2501                     orbStream.read_wchar();
  2502                     break;
  2503                 case TCKind._tk_short:
  2504                     orbStream.read_short();
  2505                     break;
  2506                 case TCKind._tk_long:
  2507                     orbStream.read_long();
  2508                     break;
  2509                 case TCKind._tk_longlong:
  2510                     orbStream.read_longlong();
  2511                     break;
  2512                 case TCKind._tk_float:
  2513                     orbStream.read_float();
  2514                     break;
  2515                 case TCKind._tk_double:
  2516                     orbStream.read_double();
  2517                     break;
  2518                 case TCKind._tk_value:
  2519                 case TCKind._tk_objref:
  2520                 case TCKind._tk_value_box:
  2521                     Class type = null;
  2522                     String id = fields[i].id;
  2524                     try {
  2525                         type = vhandler.getClassFromType(id);
  2527                     catch(ClassNotFoundException cnfe){
  2528                         // Make sure type = null
  2529                         type = null;
  2531                     String signature = null;
  2532                     if (type != null)
  2533                         signature = ValueUtility.getSignature(fields[i]);
  2535                     // Read value
  2536                     try {
  2537                         if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
  2538                                                      signature.equals("Ljava/io/Serializable;") ||
  2539                                                      signature.equals("Ljava/io/Externalizable;")) ) {
  2540                             javax.rmi.CORBA.Util.readAny(orbStream);
  2542                         else {
  2543                             // Decide what method call to make based on the type.
  2544                             //
  2545                             // NOTE : Since FullValueDescription does not allow us
  2546                             // to ask whether something is an interface we do not
  2547                             // have the ability to optimize this check.
  2549                             int callType = ValueHandlerImpl.kValueType;
  2551                             if (!vhandler.isSequence(id)) {
  2552                                 FullValueDescription fieldFVD = sender.meta(fields[i].id);
  2553                                 if (kRemoteTypeCode == fields[i].type) {
  2555                                     // RMI Object reference...
  2556                                     callType = ValueHandlerImpl.kRemoteType;
  2557                                 } else if (fieldFVD.is_abstract) {
  2558                                     // RMI Abstract Object reference...
  2560                                     callType = ValueHandlerImpl.kAbstractType;
  2564                             // Now that we have used the FVD of the field to determine the proper course
  2565                             // of action, it is ok to use the type (Class) from this point forward since
  2566                             // the rep. id for this read will also follow on the wire.
  2568                             switch (callType) {
  2569                             case ValueHandlerImpl.kRemoteType:
  2570                                 orbStream.read_Object();
  2571                                 break;
  2572                             case ValueHandlerImpl.kAbstractType:
  2573                                 orbStream.read_abstract_interface();
  2574                                 break;
  2575                             case ValueHandlerImpl.kValueType:
  2576                                 if (type != null) {
  2577                                     orbStream.read_value(type);
  2578                                 } else {
  2579                                     orbStream.read_value();
  2581                                 break;
  2582                             default:
  2583                                 // XXX I18N, logging needed.
  2584                                 throw new StreamCorruptedException("Unknown callType: "
  2585                                                                    + callType);
  2590                     catch(IndirectionException cdrie) {
  2591                         // Since we are throwing this away, don't bother handling recursion.
  2592                         continue;
  2595                     break;
  2596                 default:
  2597                     // XXX I18N, logging needed.
  2598                     throw new StreamCorruptedException("Unknown kind: "
  2599                                                        + fields[i].type.kind().value());
  2602             } catch (IllegalArgumentException e) {
  2603                 /* This case should never happen. If the field types
  2604                    are not the same, InvalidClassException is raised when
  2605                    matching the local class to the serialized ObjectStreamClass. */
  2606                 // XXX I18N, logging needed.
  2607                 ClassCastException cce = new ClassCastException("Assigning instance of class " +
  2608                     fields[i].id + " to field " + currentClassDesc.getName() +
  2609                     '#' + fields[i].name);
  2610                 cce.initCause(e) ;
  2611                 throw cce ;
  2617     private static void setObjectField(Object o, Class<?> c, String fieldName, Object v) {
  2618         try {
  2619             Field fld = getDeclaredField( c, fieldName ) ;
  2620             Class fieldCl = fld.getType();
  2621             if(v != null && !fieldCl.isInstance(v)) {
  2622                 throw new Exception();
  2624             long key = bridge.objectFieldOffset( fld ) ;
  2625             bridge.putObject( o, key, v ) ;
  2626         } catch (Exception e) {
  2627             if (o != null) {
  2628                 throw utilWrapper.errorSetObjectField( e, fieldName,
  2629                     o.toString(),
  2630                     v.toString() ) ;
  2631             } else {
  2632                 throw utilWrapper.errorSetObjectField( e, fieldName,
  2633                     "null " + c.getName() + " object",
  2634                     v.toString() ) ;
  2639     private static void setBooleanField(Object o, Class<?> c, String fieldName, boolean v)
  2641         try {
  2642             Field fld = getDeclaredField( c, fieldName ) ;
  2643             if ((fld != null) && (fld.getType() == Boolean.TYPE)) {
  2644                 long key = bridge.objectFieldOffset( fld ) ;
  2645                 bridge.putBoolean( o, key, v ) ;
  2646             } else {
  2647                 throw new InvalidObjectException("Field Type mismatch");
  2649         } catch (Exception e) {
  2650             if (o != null) {
  2651             throw utilWrapper.errorSetBooleanField( e, fieldName,
  2652                 o.toString(),
  2653                 new Boolean(v) ) ;
  2654             } else {
  2655                 throw utilWrapper.errorSetBooleanField( e, fieldName,
  2656                     "null " + c.getName() + " object",
  2657                     new Boolean(v) ) ;
  2662     private static void setByteField(Object o, Class<?> c, String fieldName, byte v)
  2664         try {
  2665             Field fld = getDeclaredField( c, fieldName ) ;
  2666             if ((fld != null) && (fld.getType() == Byte.TYPE)) {
  2667                 long key = bridge.objectFieldOffset( fld ) ;
  2668                 bridge.putByte( o, key, v ) ;
  2669             } else {
  2670                 throw new InvalidObjectException("Field Type mismatch");
  2672         } catch (Exception e) {
  2673             if (o != null) {
  2674                 throw utilWrapper.errorSetByteField( e, fieldName,
  2675                     o.toString(),
  2676                     new Byte(v) ) ;
  2677             } else {
  2678                 throw utilWrapper.errorSetByteField( e, fieldName,
  2679                     "null " + c.getName() + " object",
  2680                     new Byte(v) ) ;
  2685     private static void setCharField(Object o, Class<?> c, String fieldName, char v)
  2687         try {
  2688             Field fld = getDeclaredField( c, fieldName ) ;
  2689             if ((fld != null) && (fld.getType() == Character.TYPE)) {
  2690                 long key = bridge.objectFieldOffset( fld ) ;
  2691                 bridge.putChar( o, key, v ) ;
  2692             } else {
  2693                 throw new InvalidObjectException("Field Type mismatch");
  2695         } catch (Exception e) {
  2696             if (o != null) {
  2697                 throw utilWrapper.errorSetCharField( e, fieldName,
  2698                     o.toString(),
  2699                     new Character(v) ) ;
  2700             } else {
  2701                 throw utilWrapper.errorSetCharField( e, fieldName,
  2702                     "null " + c.getName() + " object",
  2703                     new Character(v) ) ;
  2708     private static void setShortField(Object o, Class<?> c, String fieldName, short v)
  2710         try {
  2711             Field fld = getDeclaredField( c, fieldName ) ;
  2712             if ((fld != null) && (fld.getType() == Short.TYPE)) {
  2713                 long key = bridge.objectFieldOffset( fld ) ;
  2714                 bridge.putShort( o, key, v ) ;
  2715             } else {
  2716                 throw new InvalidObjectException("Field Type mismatch");
  2718         } catch (Exception e) {
  2719             if (o != null) {
  2720             throw utilWrapper.errorSetShortField( e, fieldName,
  2721                 o.toString(),
  2722                 new Short(v) ) ;
  2723             } else {
  2724                 throw utilWrapper.errorSetShortField( e, fieldName,
  2725                     "null " + c.getName() + " object",
  2726                     new Short(v) ) ;
  2731     private static void setIntField(Object o, final Class<?> c, final String fieldName, int v)
  2733         try {
  2734             Field fld = getDeclaredField( c, fieldName ) ;
  2735             if ((fld != null) && (fld.getType() == Integer.TYPE)) {
  2736                 long key = bridge.objectFieldOffset( fld ) ;
  2737                 bridge.putInt( o, key, v ) ;
  2738             } else {
  2739                 throw new InvalidObjectException("Field Type mismatch");
  2741         } catch (Exception e) {
  2742             if (o != null) {
  2743                 throw utilWrapper.errorSetIntField( e, fieldName,
  2744                     o.toString(),
  2745                     new Integer(v) ) ;
  2746             } else {
  2747                 throw utilWrapper.errorSetIntField( e, fieldName,
  2748                     "null " + c.getName() + " object",
  2749                     new Integer(v) ) ;
  2754     private static void setLongField(Object o, Class<?> c, String fieldName, long v)
  2756         try {
  2757             Field fld = getDeclaredField( c, fieldName ) ;
  2758             if ((fld != null) && (fld.getType() == Long.TYPE)) {
  2759                 long key = bridge.objectFieldOffset( fld ) ;
  2760                 bridge.putLong( o, key, v ) ;
  2761             } else {
  2762                 throw new InvalidObjectException("Field Type mismatch");
  2764         } catch (Exception e) {
  2765             if (o != null) {
  2766                 throw utilWrapper.errorSetLongField( e, fieldName,
  2767                     o.toString(),
  2768                     new Long(v) ) ;
  2769             } else {
  2770                 throw utilWrapper.errorSetLongField( e, fieldName,
  2771                     "null " + c.getName() + " object",
  2772                     new Long(v) ) ;
  2777     private static void setFloatField(Object o, Class<?> c, String fieldName, float v)
  2779         try {
  2780             Field fld = getDeclaredField( c, fieldName ) ;
  2781             if ((fld != null) && (fld.getType() == Float.TYPE)) {
  2782                 long key = bridge.objectFieldOffset( fld ) ;
  2783                 bridge.putFloat( o, key, v ) ;
  2784             } else {
  2785                 throw new InvalidObjectException("Field Type mismatch");
  2787         } catch (Exception e) {
  2788             if (o != null) {
  2789                 throw utilWrapper.errorSetFloatField( e, fieldName,
  2790                     o.toString(),
  2791                     new Float(v) ) ;
  2792             } else {
  2793                 throw utilWrapper.errorSetFloatField( e, fieldName,
  2794                     "null " + c.getName() + " object",
  2795                     new Float(v) ) ;
  2800     private static void setDoubleField(Object o, Class<?> c, String fieldName, double v)
  2802         try {
  2803             Field fld = getDeclaredField(c, fieldName ) ;
  2804             if ((fld != null) && (fld.getType() == Double.TYPE)) {
  2805                 long key = bridge.objectFieldOffset( fld ) ;
  2806                 bridge.putDouble( o, key, v ) ;
  2807             } else {
  2808                 throw new InvalidObjectException("Field Type mismatch");
  2810         } catch (Exception e) {
  2811             if (o != null) {
  2812                 throw utilWrapper.errorSetDoubleField( e, fieldName,
  2813                     o.toString(),
  2814                     new Double(v) ) ;
  2815             } else {
  2816                 throw utilWrapper.errorSetDoubleField( e, fieldName,
  2817                     "null " + c.getName() + " object",
  2818                     new Double(v) ) ;
  2824     private static Field getDeclaredField(final Class<?> c,
  2825                                            final String fieldName)
  2826         throws PrivilegedActionException, NoSuchFieldException, SecurityException {
  2827         if (System.getSecurityManager() == null) {
  2828             return c.getDeclaredField(fieldName);
  2829         } else {
  2830             return AccessController
  2831                 .doPrivileged(new PrivilegedExceptionAction<Field>() {
  2832                     public Field run()
  2833                             throws NoSuchFieldException {
  2834                         return c.getDeclaredField(fieldName);
  2836                 });
  2840     /**
  2841      * This class maintains a map of stream position to
  2842      * an Object currently being deserialized.  It is used
  2843      * to handle the cases where the are indirections to
  2844      * an object on the recursion stack.  The CDR level
  2845      * handles indirections to objects previously seen
  2846      * (and completely deserialized) in the stream.
  2847      */
  2848     static class ActiveRecursionManager
  2850         private Map<Integer, Object> offsetToObjectMap;
  2852         public ActiveRecursionManager() {
  2853             // A hash map is unsynchronized and allows
  2854             // null values
  2855             offsetToObjectMap = new HashMap<>();
  2858         // Called right after allocating a new object.
  2859         // Offset is the starting position in the stream
  2860         // of the object.
  2861         public void addObject(int offset, Object value) {
  2862             offsetToObjectMap.put(new Integer(offset), value);
  2865         // If the given starting position doesn't refer
  2866         // to the beginning of an object currently being
  2867         // deserialized, this throws an IOException.
  2868         // Otherwise, it returns a reference to the
  2869         // object.
  2870         public Object getObject(int offset) throws IOException {
  2871             Integer position = new Integer(offset);
  2873             if (!offsetToObjectMap.containsKey(position))
  2874                 // XXX I18N, logging needed.
  2875                 throw new IOException("Invalid indirection to offset "
  2876                                       + offset);
  2878             return offsetToObjectMap.get(position);
  2881         // Called when an object has been completely
  2882         // deserialized, so it should no longer be in
  2883         // this mapping.  The CDR level can handle
  2884         // further indirections.
  2885         public void removeObject(int offset) {
  2886             offsetToObjectMap.remove(new Integer(offset));
  2889         // If the given offset doesn't map to an Object,
  2890         // then it isn't an indirection to an object
  2891         // currently being deserialized.
  2892         public boolean containsObject(int offset) {
  2893             return offsetToObjectMap.containsKey(new Integer(offset));

mercurial