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

changeset 0
7ef37b2cdcad
child 748
6845b95cba6b
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java	Wed Apr 27 01:21:28 2016 +0800
     1.3 @@ -0,0 +1,2733 @@
     1.4 +/*
     1.5 + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +/*
    1.29 + * Licensed Materials - Property of IBM
    1.30 + * RMI-IIOP v1.0
    1.31 + * Copyright IBM Corp. 1998 1999  All Rights Reserved
    1.32 + *
    1.33 + */
    1.34 +
    1.35 +package com.sun.corba.se.impl.io;
    1.36 +
    1.37 +import java.io.InputStream;
    1.38 +import java.io.IOException;
    1.39 +import java.io.StreamCorruptedException;
    1.40 +import java.io.ObjectInputValidation;
    1.41 +import java.io.NotActiveException;
    1.42 +import java.io.InvalidObjectException;
    1.43 +import java.io.InvalidClassException;
    1.44 +import java.io.DataInputStream;
    1.45 +import java.io.OptionalDataException;
    1.46 +import java.io.WriteAbortedException;
    1.47 +import java.io.Externalizable;
    1.48 +import java.io.EOFException;
    1.49 +import java.lang.reflect.*;
    1.50 +import java.util.Vector;
    1.51 +import java.util.Stack;
    1.52 +import java.util.Hashtable;
    1.53 +import java.util.Enumeration;
    1.54 +
    1.55 +import sun.corba.Bridge ;
    1.56 +
    1.57 +import java.security.AccessController ;
    1.58 +import java.security.PrivilegedAction ;
    1.59 +
    1.60 +import com.sun.corba.se.impl.io.ObjectStreamClass;
    1.61 +import com.sun.corba.se.impl.util.Utility;
    1.62 +
    1.63 +import org.omg.CORBA.portable.ValueInputStream;
    1.64 +
    1.65 +import org.omg.CORBA.ValueMember;
    1.66 +import org.omg.CORBA.SystemException;
    1.67 +import org.omg.CORBA.TCKind;
    1.68 +import org.omg.CORBA.ORB;
    1.69 +import org.omg.CORBA.CompletionStatus;
    1.70 +import org.omg.CORBA.portable.IndirectionException;
    1.71 +import org.omg.CORBA.MARSHAL;
    1.72 +import org.omg.CORBA.TypeCode;
    1.73 +
    1.74 +import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
    1.75 +import com.sun.org.omg.SendingContext.CodeBase;
    1.76 +
    1.77 +import javax.rmi.PortableRemoteObject;
    1.78 +import javax.rmi.CORBA.Util;
    1.79 +import javax.rmi.CORBA.ValueHandler;
    1.80 +
    1.81 +import java.security.*;
    1.82 +import java.util.*;
    1.83 +
    1.84 +import com.sun.corba.se.impl.orbutil.ObjectUtility ;
    1.85 +import com.sun.corba.se.impl.logging.OMGSystemException ;
    1.86 +import com.sun.corba.se.impl.logging.UtilSystemException ;
    1.87 +
    1.88 +import com.sun.corba.se.spi.logging.CORBALogDomains ;
    1.89 +
    1.90 +/**
    1.91 + * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization
    1.92 + * input semantics.
    1.93 + *
    1.94 + * @author  Stephen Lewallen
    1.95 + * @since   JDK1.1.6
    1.96 + */
    1.97 +
    1.98 +public class IIOPInputStream
    1.99 +    extends com.sun.corba.se.impl.io.InputStreamHook
   1.100 +{
   1.101 +    private static Bridge bridge =
   1.102 +        (Bridge)AccessController.doPrivileged(
   1.103 +            new PrivilegedAction() {
   1.104 +                public Object run() {
   1.105 +                    return Bridge.get() ;
   1.106 +                }
   1.107 +            }
   1.108 +        ) ;
   1.109 +
   1.110 +    private static OMGSystemException omgWrapper = OMGSystemException.get(
   1.111 +        CORBALogDomains.RPC_ENCODING ) ;
   1.112 +    private static UtilSystemException utilWrapper = UtilSystemException.get(
   1.113 +        CORBALogDomains.RPC_ENCODING ) ;
   1.114 +
   1.115 +    // Necessary to pass the appropriate fields into the
   1.116 +    // defaultReadObjectDelegate method (which takes no
   1.117 +    // parameters since it's called from
   1.118 +    // java.io.ObjectInpuStream defaultReadObject()
   1.119 +    // which we can't change).
   1.120 +    //
   1.121 +    // This is only used in the case where the fields had
   1.122 +    // to be obtained remotely because of a serializable
   1.123 +    // version difference.  Set in inputObjectUsingFVD.
   1.124 +    // Part of serialization evolution fixes for Ladybird,
   1.125 +    // bug 4365188.
   1.126 +    private ValueMember defaultReadObjectFVDMembers[] = null;
   1.127 +
   1.128 +    private org.omg.CORBA_2_3.portable.InputStream orbStream;
   1.129 +
   1.130 +    private CodeBase cbSender;
   1.131 +
   1.132 +    private ValueHandlerImpl vhandler;  //d4365188
   1.133 +
   1.134 +    private Object currentObject = null;
   1.135 +
   1.136 +    private ObjectStreamClass currentClassDesc = null;
   1.137 +
   1.138 +    private Class currentClass = null;
   1.139 +
   1.140 +    private int recursionDepth = 0;
   1.141 +
   1.142 +    private int simpleReadDepth = 0;
   1.143 +
   1.144 +    // The ActiveRecursionManager replaces the old RecursionManager which
   1.145 +    // used to record how many recursions were made, and resolve them after
   1.146 +    // an object was completely deserialized.
   1.147 +    //
   1.148 +    // That created problems (as in bug 4414154) because when custom
   1.149 +    // unmarshaling in readObject, there can be recursive references
   1.150 +    // to one of the objects currently being unmarshaled, and the
   1.151 +    // passive recursion system failed.
   1.152 +    ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager();
   1.153 +
   1.154 +    private IOException abortIOException = null;
   1.155 +
   1.156 +    /* Remember the first exception that stopped this stream. */
   1.157 +    private ClassNotFoundException abortClassNotFoundException = null;
   1.158 +
   1.159 +    /* Vector of validation callback objects
   1.160 +     * The vector is created as needed. The vector is maintained in
   1.161 +     * order of highest (first) priority to lowest
   1.162 +     */
   1.163 +    private Vector callbacks;
   1.164 +
   1.165 +    // Serialization machinery fields
   1.166 +    /* Arrays used to keep track of classes and ObjectStreamClasses
   1.167 +     * as they are being merged; used in inputObject.
   1.168 +     * spClass is the stack pointer for both.  */
   1.169 +    ObjectStreamClass[] classdesc;
   1.170 +    Class[] classes;
   1.171 +    int spClass;
   1.172 +
   1.173 +    private static final String kEmptyStr = "";
   1.174 +
   1.175 +    // TCKind TypeCodes used in FVD inputClassFields
   1.176 +    //public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref);
   1.177 +    //public static final TypeCode kValueTypeCode =  new TypeCodeImpl(TCKind._tk_value);
   1.178 +    // removed TypeCodeImpl dependency
   1.179 +    public static final TypeCode kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref);
   1.180 +    public static final TypeCode kValueTypeCode =  ORB.init().get_primitive_tc(TCKind.tk_value);
   1.181 +
   1.182 +    // TESTING CODE - useFVDOnly should be made final before FCS in order to
   1.183 +    // optimize out the check.
   1.184 +    private static final boolean useFVDOnly = false;
   1.185 +
   1.186 +    private byte streamFormatVersion;
   1.187 +
   1.188 +    // Since java.io.OptionalDataException's constructors are
   1.189 +    // package private, but we need to throw it in some special
   1.190 +    // cases, we try to do it by reflection.
   1.191 +    private static final Constructor OPT_DATA_EXCEPTION_CTOR;
   1.192 +
   1.193 +    private Object[] readObjectArgList = { this } ;
   1.194 +
   1.195 +    static {
   1.196 +        OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor();
   1.197 +    }
   1.198 +
   1.199 +    // Grab the OptionalDataException boolean ctor and make
   1.200 +    // it accessible.  Note that any exceptions
   1.201 +    // will be wrapped in ExceptionInInitializerErrors.
   1.202 +    private static Constructor getOptDataExceptionCtor() {
   1.203 +
   1.204 +        try {
   1.205 +
   1.206 +            Constructor result =
   1.207 +
   1.208 +                (Constructor) AccessController.doPrivileged(
   1.209 +                                    new PrivilegedExceptionAction() {
   1.210 +                    public java.lang.Object run()
   1.211 +                        throws NoSuchMethodException,
   1.212 +                        SecurityException {
   1.213 +
   1.214 +                        Constructor boolCtor
   1.215 +                            = OptionalDataException.class.getDeclaredConstructor(
   1.216 +                                                               new Class[] {
   1.217 +                                Boolean.TYPE });
   1.218 +
   1.219 +                        boolCtor.setAccessible(true);
   1.220 +
   1.221 +                        return boolCtor;
   1.222 +                    }});
   1.223 +
   1.224 +            if (result == null)
   1.225 +                // XXX I18N, logging needed.
   1.226 +                throw new Error("Unable to find OptionalDataException constructor");
   1.227 +
   1.228 +            return result;
   1.229 +
   1.230 +        } catch (Exception ex) {
   1.231 +            // XXX I18N, logging needed.
   1.232 +            throw new ExceptionInInitializerError(ex);
   1.233 +        }
   1.234 +    }
   1.235 +
   1.236 +    // Create a new OptionalDataException with the EOF marker
   1.237 +    // set to true.  See handleOptionalDataMarshalException.
   1.238 +    private OptionalDataException createOptionalDataException() {
   1.239 +        try {
   1.240 +            OptionalDataException result
   1.241 +                = (OptionalDataException)
   1.242 +                   OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] {
   1.243 +                       Boolean.TRUE });
   1.244 +
   1.245 +            if (result == null)
   1.246 +                // XXX I18N, logging needed.
   1.247 +                throw new Error("Created null OptionalDataException");
   1.248 +
   1.249 +            return result;
   1.250 +
   1.251 +        } catch (Exception ex) {
   1.252 +            // XXX I18N, logging needed.
   1.253 +            throw new Error("Couldn't create OptionalDataException", ex);
   1.254 +        }
   1.255 +    }
   1.256 +
   1.257 +    // Return the stream format version currently being used
   1.258 +    // to deserialize an object
   1.259 +    protected byte getStreamFormatVersion() {
   1.260 +        return streamFormatVersion;
   1.261 +    }
   1.262 +
   1.263 +    // At the beginning of data sent by a writeObject or
   1.264 +    // writeExternal method there is a byte telling the
   1.265 +    // reader the stream format version.
   1.266 +    private void readFormatVersion() throws IOException {
   1.267 +
   1.268 +        streamFormatVersion = orbStream.read_octet();
   1.269 +
   1.270 +        if (streamFormatVersion < 1 ||
   1.271 +            streamFormatVersion > vhandler.getMaximumStreamFormatVersion()) {
   1.272 +            SystemException sysex = omgWrapper.unsupportedFormatVersion(
   1.273 +                    CompletionStatus.COMPLETED_MAYBE);
   1.274 +            // XXX I18N?  Logging for IOException?
   1.275 +            IOException result = new IOException("Unsupported format version: "
   1.276 +                                                 + streamFormatVersion);
   1.277 +            result.initCause( sysex ) ;
   1.278 +            throw result ;
   1.279 +        }
   1.280 +
   1.281 +        if (streamFormatVersion == 2) {
   1.282 +            if (!(orbStream instanceof ValueInputStream)) {
   1.283 +                SystemException sysex = omgWrapper.notAValueinputstream(
   1.284 +                    CompletionStatus.COMPLETED_MAYBE);
   1.285 +                // XXX I18N?  Logging for IOException?
   1.286 +                IOException result = new IOException("Not a ValueInputStream");
   1.287 +                result.initCause( sysex ) ;
   1.288 +                throw result;
   1.289 +            }
   1.290 +        }
   1.291 +    }
   1.292 +
   1.293 +    public static void setTestFVDFlag(boolean val){
   1.294 +        //  useFVDOnly = val;
   1.295 +    }
   1.296 +
   1.297 +    /**
   1.298 +     * Dummy constructor; passes upper stream a dummy stream;
   1.299 +     **/
   1.300 +    public IIOPInputStream()
   1.301 +        throws java.io.IOException {
   1.302 +        super();
   1.303 +        resetStream();
   1.304 +    }
   1.305 +
   1.306 +    final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) {
   1.307 +        orbStream = os;
   1.308 +    }
   1.309 +
   1.310 +    final org.omg.CORBA_2_3.portable.InputStream getOrbStream() {
   1.311 +        return orbStream;
   1.312 +    }
   1.313 +
   1.314 +    //added setSender and getSender
   1.315 +    public final void setSender(CodeBase cb) {
   1.316 +        cbSender = cb;
   1.317 +    }
   1.318 +
   1.319 +    public final CodeBase getSender() {
   1.320 +        return cbSender;
   1.321 +    }
   1.322 +
   1.323 +    // 4365188 this is added to enable backward compatability w/ wrong
   1.324 +    // rep-ids
   1.325 +    public final void setValueHandler(ValueHandler vh) {
   1.326 +        vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh;
   1.327 +    }
   1.328 +
   1.329 +    public final ValueHandler getValueHandler() {
   1.330 +        return (javax.rmi.CORBA.ValueHandler) vhandler;
   1.331 +    }
   1.332 +
   1.333 +    final void increaseRecursionDepth(){
   1.334 +        recursionDepth++;
   1.335 +    }
   1.336 +
   1.337 +    final int decreaseRecursionDepth(){
   1.338 +        return --recursionDepth;
   1.339 +    }
   1.340 +
   1.341 +    /**
   1.342 +     * Override the actions of the final method "readObject()"
   1.343 +     * in ObjectInputStream.
   1.344 +     * @since     JDK1.1.6
   1.345 +     *
   1.346 +     * Read an object from the ObjectInputStream.
   1.347 +     * The class of the object, the signature of the class, and the values
   1.348 +     * of the non-transient and non-static fields of the class and all
   1.349 +     * of its supertypes are read.  Default deserializing for a class can be
   1.350 +     * overriden using the writeObject and readObject methods.
   1.351 +     * Objects referenced by this object are read transitively so
   1.352 +     * that a complete equivalent graph of objects is reconstructed by readObject. <p>
   1.353 +     *
   1.354 +     * The root object is completly restored when all of its fields
   1.355 +     * and the objects it references are completely restored.  At this
   1.356 +     * point the object validation callbacks are executed in order
   1.357 +     * based on their registered priorities. The callbacks are
   1.358 +     * registered by objects (in the readObject special methods)
   1.359 +     * as they are individually restored.
   1.360 +     *
   1.361 +     * Exceptions are thrown for problems with the InputStream and for classes
   1.362 +     * that should not be deserialized.  All exceptions are fatal to the
   1.363 +     * InputStream and leave it in an indeterminate state; it is up to the caller
   1.364 +     * to ignore or recover the stream state.
   1.365 +     * @exception java.lang.ClassNotFoundException Class of a serialized object
   1.366 +     *      cannot be found.
   1.367 +     * @exception InvalidClassException Something is wrong with a class used by
   1.368 +     *     serialization.
   1.369 +     * @exception StreamCorruptedException Control information in the
   1.370 +     *     stream is inconsistent.
   1.371 +     * @exception OptionalDataException Primitive data was found in the
   1.372 +     * stream instead of objects.
   1.373 +     * @exception IOException Any of the usual Input/Output related exceptions.
   1.374 +     * @since     JDK1.1
   1.375 +     */
   1.376 +    public final synchronized Object readObjectDelegate() throws IOException
   1.377 +    {
   1.378 +        try {
   1.379 +
   1.380 +            readObjectState.readData(this);
   1.381 +
   1.382 +            return orbStream.read_abstract_interface();
   1.383 +        } catch (MARSHAL marshalException) {
   1.384 +            handleOptionalDataMarshalException(marshalException, true);
   1.385 +            throw marshalException;
   1.386 +        } catch(IndirectionException cdrie)
   1.387 +            {
   1.388 +                // The CDR stream had never seen the given offset before,
   1.389 +                // so check the recursion manager (it will throw an
   1.390 +                // IOException if it doesn't have a reference, either).
   1.391 +                return activeRecursionMgr.getObject(cdrie.offset);
   1.392 +            }
   1.393 +    }
   1.394 +
   1.395 +    final synchronized Object simpleReadObject(Class clz,
   1.396 +                                  String repositoryID,
   1.397 +                                  com.sun.org.omg.SendingContext.CodeBase sender,
   1.398 +                                  int offset)
   1.399 +                                         /* throws OptionalDataException, ClassNotFoundException, IOException */
   1.400 +    {
   1.401 +
   1.402 +        /* Save the current state and get ready to read an object. */
   1.403 +        Object prevObject = currentObject;
   1.404 +        ObjectStreamClass prevClassDesc = currentClassDesc;
   1.405 +        Class prevClass = currentClass;
   1.406 +        byte oldStreamFormatVersion = streamFormatVersion;
   1.407 +
   1.408 +        simpleReadDepth++;      // Entering
   1.409 +        Object obj = null;
   1.410 +
   1.411 +        /*
   1.412 +         * Check for reset, handle it before reading an object.
   1.413 +         */
   1.414 +        try {
   1.415 +            // d4365188: backward compatability
   1.416 +            if (vhandler.useFullValueDescription(clz, repositoryID)) {
   1.417 +                obj = inputObjectUsingFVD(clz, repositoryID, sender, offset);
   1.418 +            } else {
   1.419 +                obj = inputObject(clz, repositoryID, sender, offset);
   1.420 +            }
   1.421 +
   1.422 +            obj = currentClassDesc.readResolve(obj);
   1.423 +        }
   1.424 +        catch(ClassNotFoundException cnfe)
   1.425 +            {
   1.426 +                bridge.throwException( cnfe ) ;
   1.427 +                return null;
   1.428 +            }
   1.429 +        catch(IOException ioe)
   1.430 +            {
   1.431 +                // System.out.println("CLZ = " + clz + "; " + ioe.toString());
   1.432 +                bridge.throwException(ioe) ;
   1.433 +                return null;
   1.434 +            }
   1.435 +        finally {
   1.436 +            simpleReadDepth --;
   1.437 +            currentObject = prevObject;
   1.438 +            currentClassDesc = prevClassDesc;
   1.439 +            currentClass = prevClass;
   1.440 +            streamFormatVersion = oldStreamFormatVersion;
   1.441 +        }
   1.442 +
   1.443 +
   1.444 +        /* Check for thrown exceptions and re-throw them, clearing them if
   1.445 +         * this is the last recursive call .
   1.446 +         */
   1.447 +        IOException exIOE = abortIOException;
   1.448 +        if (simpleReadDepth == 0)
   1.449 +            abortIOException = null;
   1.450 +        if (exIOE != null){
   1.451 +            bridge.throwException( exIOE ) ;
   1.452 +            return null;
   1.453 +        }
   1.454 +
   1.455 +
   1.456 +        ClassNotFoundException exCNF = abortClassNotFoundException;
   1.457 +        if (simpleReadDepth == 0)
   1.458 +            abortClassNotFoundException = null;
   1.459 +        if (exCNF != null) {
   1.460 +            bridge.throwException( exCNF ) ;
   1.461 +            return null;
   1.462 +        }
   1.463 +
   1.464 +        return obj;
   1.465 +    }
   1.466 +
   1.467 +    public final synchronized  void simpleSkipObject(String repositoryID,
   1.468 +                                       com.sun.org.omg.SendingContext.CodeBase sender)
   1.469 +                                       /* throws OptionalDataException, ClassNotFoundException, IOException */
   1.470 +    {
   1.471 +
   1.472 +        /* Save the current state and get ready to read an object. */
   1.473 +        Object prevObject = currentObject;
   1.474 +        ObjectStreamClass prevClassDesc = currentClassDesc;
   1.475 +        Class prevClass = currentClass;
   1.476 +        byte oldStreamFormatVersion = streamFormatVersion;
   1.477 +
   1.478 +        simpleReadDepth++;      // Entering
   1.479 +        Object obj = null;
   1.480 +
   1.481 +        /*
   1.482 +         * Check for reset, handle it before reading an object.
   1.483 +         */
   1.484 +        try {
   1.485 +            skipObjectUsingFVD(repositoryID, sender);
   1.486 +        }
   1.487 +        catch(ClassNotFoundException cnfe)
   1.488 +            {
   1.489 +                bridge.throwException( cnfe ) ;
   1.490 +                return;
   1.491 +            }
   1.492 +        catch(IOException ioe)
   1.493 +            {
   1.494 +                bridge.throwException( ioe ) ;
   1.495 +                return;
   1.496 +            }
   1.497 +        finally {
   1.498 +            simpleReadDepth --;
   1.499 +            streamFormatVersion = oldStreamFormatVersion;
   1.500 +            currentObject = prevObject;
   1.501 +            currentClassDesc = prevClassDesc;
   1.502 +            currentClass = prevClass;
   1.503 +        }
   1.504 +
   1.505 +
   1.506 +        /* Check for thrown exceptions and re-throw them, clearing them if
   1.507 +         * this is the last recursive call .
   1.508 +         */
   1.509 +        IOException exIOE = abortIOException;
   1.510 +        if (simpleReadDepth == 0)
   1.511 +            abortIOException = null;
   1.512 +        if (exIOE != null){
   1.513 +            bridge.throwException( exIOE ) ;
   1.514 +            return;
   1.515 +        }
   1.516 +
   1.517 +
   1.518 +        ClassNotFoundException exCNF = abortClassNotFoundException;
   1.519 +        if (simpleReadDepth == 0)
   1.520 +            abortClassNotFoundException = null;
   1.521 +        if (exCNF != null) {
   1.522 +            bridge.throwException( exCNF ) ;
   1.523 +            return;
   1.524 +        }
   1.525 +
   1.526 +        return;
   1.527 +    }
   1.528 +    /////////////////
   1.529 +
   1.530 +    /**
   1.531 +     * This method is called by trusted subclasses of ObjectOutputStream
   1.532 +     * that constructed ObjectOutputStream using the
   1.533 +     * protected no-arg constructor. The subclass is expected to provide
   1.534 +     * an override method with the modifier "final".
   1.535 +     *
   1.536 +     * @return the Object read from the stream.
   1.537 +     *
   1.538 +     * @see #ObjectInputStream()
   1.539 +     * @see #readObject
   1.540 +     * @since JDK 1.2
   1.541 +     */
   1.542 +    protected final Object readObjectOverride()
   1.543 +        throws OptionalDataException, ClassNotFoundException, IOException
   1.544 +    {
   1.545 +        return readObjectDelegate();
   1.546 +    }
   1.547 +
   1.548 +    /**
   1.549 +     * Override the actions of the final method "defaultReadObject()"
   1.550 +     * in ObjectInputStream.
   1.551 +     * @since     JDK1.1.6
   1.552 +     *
   1.553 +     * Read the non-static and non-transient fields of the current class
   1.554 +     * from this stream.  This may only be called from the readObject method
   1.555 +     * of the class being deserialized. It will throw the NotActiveException
   1.556 +     * if it is called otherwise.
   1.557 +     *
   1.558 +     * @exception java.lang.ClassNotFoundException if the class of a serialized
   1.559 +     *              object could not be found.
   1.560 +     * @exception IOException        if an I/O error occurs.
   1.561 +     * @exception NotActiveException if the stream is not currently reading
   1.562 +     *              objects.
   1.563 +     * @since     JDK1.1
   1.564 +     */
   1.565 +    final synchronized void defaultReadObjectDelegate()
   1.566 +    /* throws IOException, ClassNotFoundException, NotActiveException */
   1.567 +    {
   1.568 +        try {
   1.569 +            if (currentObject == null || currentClassDesc == null)
   1.570 +                // XXX I18N, logging needed.
   1.571 +                throw new NotActiveException("defaultReadObjectDelegate");
   1.572 +
   1.573 +            // The array will be null unless fields were retrieved
   1.574 +            // remotely because of a serializable version difference.
   1.575 +            // Bug fix for 4365188.  See the definition of
   1.576 +            // defaultReadObjectFVDMembers for more information.
   1.577 +            if (defaultReadObjectFVDMembers != null &&
   1.578 +                defaultReadObjectFVDMembers.length > 0) {
   1.579 +
   1.580 +                // WARNING:  Be very careful!  What if some of
   1.581 +                // these fields actually have to do this, too?
   1.582 +                // This works because the defaultReadObjectFVDMembers
   1.583 +                // reference is passed to inputClassFields, but
   1.584 +                // there is no guarantee that
   1.585 +                // defaultReadObjectFVDMembers will point to the
   1.586 +                // same array after calling inputClassFields.
   1.587 +
   1.588 +                // Use the remote fields to unmarshal.
   1.589 +                inputClassFields(currentObject,
   1.590 +                                 currentClass,
   1.591 +                                 currentClassDesc,
   1.592 +                                 defaultReadObjectFVDMembers,
   1.593 +                                 cbSender);
   1.594 +
   1.595 +            } else {
   1.596 +
   1.597 +                // Use the local fields to unmarshal.
   1.598 +                ObjectStreamField[] fields =
   1.599 +                    currentClassDesc.getFieldsNoCopy();
   1.600 +                if (fields.length > 0) {
   1.601 +                    inputClassFields(currentObject, currentClass, fields, cbSender);
   1.602 +                }
   1.603 +            }
   1.604 +        }
   1.605 +        catch(NotActiveException nae)
   1.606 +            {
   1.607 +                bridge.throwException( nae ) ;
   1.608 +            }
   1.609 +        catch(IOException ioe)
   1.610 +            {
   1.611 +                bridge.throwException( ioe ) ;
   1.612 +            }
   1.613 +        catch(ClassNotFoundException cnfe)
   1.614 +            {
   1.615 +                bridge.throwException( cnfe ) ;
   1.616 +            }
   1.617 +
   1.618 +    }
   1.619 +
   1.620 +    /**
   1.621 +     * Override the actions of the final method "enableResolveObject()"
   1.622 +     * in ObjectInputStream.
   1.623 +     * @since     JDK1.1.6
   1.624 +     *
   1.625 +     * Enable the stream to allow objects read from the stream to be replaced.
   1.626 +     * If the stream is a trusted class it is allowed to enable replacment.
   1.627 +     * Trusted classes are those classes with a classLoader equals null. <p>
   1.628 +     *
   1.629 +     * When enabled the resolveObject method is called for every object
   1.630 +     * being deserialized.
   1.631 +     *
   1.632 +     * @exception SecurityException The classloader of this stream object is non-null.
   1.633 +     * @since     JDK1.1
   1.634 +     */
   1.635 +    public final boolean enableResolveObjectDelegate(boolean enable)
   1.636 +    /* throws SecurityException */
   1.637 +    {
   1.638 +        return false;
   1.639 +    }
   1.640 +
   1.641 +    // The following three methods allow the implementing orbStream
   1.642 +    // to provide mark/reset behavior as defined in java.io.InputStream.
   1.643 +
   1.644 +    public final void mark(int readAheadLimit) {
   1.645 +        orbStream.mark(readAheadLimit);
   1.646 +    }
   1.647 +
   1.648 +    public final boolean markSupported() {
   1.649 +        return orbStream.markSupported();
   1.650 +    }
   1.651 +
   1.652 +    public final void reset() throws IOException {
   1.653 +        try {
   1.654 +            orbStream.reset();
   1.655 +        } catch (Error e) {
   1.656 +            IOException err = new IOException(e.getMessage());
   1.657 +            err.initCause(e) ;
   1.658 +            throw err ;
   1.659 +        }
   1.660 +    }
   1.661 +
   1.662 +    public final int available() throws IOException{
   1.663 +        return 0; // unreliable
   1.664 +    }
   1.665 +
   1.666 +    public final void close() throws IOException{
   1.667 +        // no op
   1.668 +    }
   1.669 +
   1.670 +    public final int read() throws IOException{
   1.671 +        try{
   1.672 +            readObjectState.readData(this);
   1.673 +
   1.674 +            return (orbStream.read_octet() << 0) & 0x000000FF;
   1.675 +        } catch (MARSHAL marshalException) {
   1.676 +            if (marshalException.minor
   1.677 +                == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   1.678 +                setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   1.679 +                return -1;
   1.680 +            }
   1.681 +
   1.682 +            throw marshalException;
   1.683 +        } catch(Error e) {
   1.684 +            IOException exc = new IOException(e.getMessage());
   1.685 +            exc.initCause(e) ;
   1.686 +            throw exc ;
   1.687 +        }
   1.688 +    }
   1.689 +
   1.690 +    public final int read(byte data[], int offset, int length) throws IOException{
   1.691 +        try{
   1.692 +            readObjectState.readData(this);
   1.693 +
   1.694 +            orbStream.read_octet_array(data, offset, length);
   1.695 +            return length;
   1.696 +        } catch (MARSHAL marshalException) {
   1.697 +            if (marshalException.minor
   1.698 +                == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   1.699 +                setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   1.700 +                return -1;
   1.701 +            }
   1.702 +
   1.703 +            throw marshalException;
   1.704 +        } catch(Error e) {
   1.705 +            IOException exc = new IOException(e.getMessage());
   1.706 +            exc.initCause(e) ;
   1.707 +            throw exc ;
   1.708 +        }
   1.709 +
   1.710 +    }
   1.711 +
   1.712 +    public final boolean readBoolean() throws IOException{
   1.713 +        try{
   1.714 +            readObjectState.readData(this);
   1.715 +
   1.716 +            return orbStream.read_boolean();
   1.717 +        } catch (MARSHAL marshalException) {
   1.718 +            handleOptionalDataMarshalException(marshalException, false);
   1.719 +            throw marshalException;
   1.720 +
   1.721 +        } catch(Error e) {
   1.722 +            IOException exc = new IOException(e.getMessage());
   1.723 +            exc.initCause(e);
   1.724 +            throw exc ;
   1.725 +        }
   1.726 +    }
   1.727 +
   1.728 +    public final byte readByte() throws IOException{
   1.729 +        try{
   1.730 +            readObjectState.readData(this);
   1.731 +
   1.732 +            return orbStream.read_octet();
   1.733 +        } catch (MARSHAL marshalException) {
   1.734 +            handleOptionalDataMarshalException(marshalException, false);
   1.735 +            throw marshalException;
   1.736 +
   1.737 +        } catch(Error e) {
   1.738 +            IOException exc = new IOException(e.getMessage());
   1.739 +            exc.initCause(e);
   1.740 +            throw exc ;
   1.741 +        }
   1.742 +    }
   1.743 +
   1.744 +    public final char readChar() throws IOException{
   1.745 +        try{
   1.746 +            readObjectState.readData(this);
   1.747 +
   1.748 +            return orbStream.read_wchar();
   1.749 +        } catch (MARSHAL marshalException) {
   1.750 +            handleOptionalDataMarshalException(marshalException, false);
   1.751 +            throw marshalException;
   1.752 +
   1.753 +        } catch(Error e) {
   1.754 +            IOException exc = new IOException(e.getMessage());
   1.755 +            exc.initCause(e);
   1.756 +            throw exc ;
   1.757 +        }
   1.758 +    }
   1.759 +
   1.760 +    public final double readDouble() throws IOException{
   1.761 +        try{
   1.762 +            readObjectState.readData(this);
   1.763 +
   1.764 +            return orbStream.read_double();
   1.765 +        } catch (MARSHAL marshalException) {
   1.766 +            handleOptionalDataMarshalException(marshalException, false);
   1.767 +            throw marshalException;
   1.768 +        } catch(Error e) {
   1.769 +            IOException exc = new IOException(e.getMessage());
   1.770 +            exc.initCause(e);
   1.771 +            throw exc ;
   1.772 +        }
   1.773 +    }
   1.774 +
   1.775 +    public final float readFloat() throws IOException{
   1.776 +        try{
   1.777 +            readObjectState.readData(this);
   1.778 +
   1.779 +            return orbStream.read_float();
   1.780 +        } catch (MARSHAL marshalException) {
   1.781 +            handleOptionalDataMarshalException(marshalException, false);
   1.782 +            throw marshalException;
   1.783 +        } catch(Error e) {
   1.784 +            IOException exc = new IOException(e.getMessage());
   1.785 +            exc.initCause(e);
   1.786 +            throw exc ;
   1.787 +        }
   1.788 +    }
   1.789 +
   1.790 +    public final void readFully(byte data[]) throws IOException{
   1.791 +// d11623 : implement readFully, required for serializing some core classes
   1.792 +
   1.793 +        readFully(data, 0, data.length);
   1.794 +    }
   1.795 +
   1.796 +    public final void readFully(byte data[],  int offset,  int size) throws IOException{
   1.797 +// d11623 : implement readFully, required for serializing some core classes
   1.798 +        try{
   1.799 +            readObjectState.readData(this);
   1.800 +
   1.801 +            orbStream.read_octet_array(data, offset, size);
   1.802 +        } catch (MARSHAL marshalException) {
   1.803 +            handleOptionalDataMarshalException(marshalException, false);
   1.804 +
   1.805 +            throw marshalException;
   1.806 +        } catch(Error e) {
   1.807 +            IOException exc = new IOException(e.getMessage());
   1.808 +            exc.initCause(e);
   1.809 +            throw exc ;
   1.810 +        }
   1.811 +    }
   1.812 +
   1.813 +    public final int readInt() throws IOException{
   1.814 +        try{
   1.815 +            readObjectState.readData(this);
   1.816 +
   1.817 +            return orbStream.read_long();
   1.818 +        } catch (MARSHAL marshalException) {
   1.819 +            handleOptionalDataMarshalException(marshalException, false);
   1.820 +            throw marshalException;
   1.821 +        } catch(Error e) {
   1.822 +            IOException exc = new IOException(e.getMessage());
   1.823 +            exc.initCause(e);
   1.824 +            throw exc ;
   1.825 +        }
   1.826 +    }
   1.827 +
   1.828 +    public final String readLine() throws IOException{
   1.829 +        // XXX I18N, logging needed.
   1.830 +        throw new IOException("Method readLine not supported");
   1.831 +    }
   1.832 +
   1.833 +    public final long readLong() throws IOException{
   1.834 +        try{
   1.835 +            readObjectState.readData(this);
   1.836 +
   1.837 +            return orbStream.read_longlong();
   1.838 +        } catch (MARSHAL marshalException) {
   1.839 +            handleOptionalDataMarshalException(marshalException, false);
   1.840 +            throw marshalException;
   1.841 +        } catch(Error e) {
   1.842 +            IOException exc = new IOException(e.getMessage());
   1.843 +            exc.initCause(e);
   1.844 +            throw exc ;
   1.845 +        }
   1.846 +    }
   1.847 +
   1.848 +    public final short readShort() throws IOException{
   1.849 +        try{
   1.850 +            readObjectState.readData(this);
   1.851 +
   1.852 +            return orbStream.read_short();
   1.853 +        } catch (MARSHAL marshalException) {
   1.854 +            handleOptionalDataMarshalException(marshalException, false);
   1.855 +            throw marshalException;
   1.856 +        } catch(Error e) {
   1.857 +            IOException exc = new IOException(e.getMessage());
   1.858 +            exc.initCause(e);
   1.859 +            throw exc ;
   1.860 +        }
   1.861 +    }
   1.862 +
   1.863 +    protected final void readStreamHeader() throws IOException, StreamCorruptedException{
   1.864 +        // no op
   1.865 +    }
   1.866 +
   1.867 +    public final int readUnsignedByte() throws IOException{
   1.868 +        try{
   1.869 +            readObjectState.readData(this);
   1.870 +
   1.871 +            return (orbStream.read_octet() << 0) & 0x000000FF;
   1.872 +        } catch (MARSHAL marshalException) {
   1.873 +            handleOptionalDataMarshalException(marshalException, false);
   1.874 +            throw marshalException;
   1.875 +        } catch(Error e) {
   1.876 +            IOException exc = new IOException(e.getMessage());
   1.877 +            exc.initCause(e);
   1.878 +            throw exc ;
   1.879 +        }
   1.880 +    }
   1.881 +
   1.882 +    public final int readUnsignedShort() throws IOException{
   1.883 +        try{
   1.884 +            readObjectState.readData(this);
   1.885 +
   1.886 +            return (orbStream.read_ushort() << 0) & 0x0000FFFF;
   1.887 +        } catch (MARSHAL marshalException) {
   1.888 +            handleOptionalDataMarshalException(marshalException, false);
   1.889 +            throw marshalException;
   1.890 +        } catch(Error e) {
   1.891 +            IOException exc = new IOException(e.getMessage());
   1.892 +            exc.initCause(e);
   1.893 +            throw exc ;
   1.894 +        }
   1.895 +    }
   1.896 +
   1.897 +    /**
   1.898 +     * Helper method for correcting the Kestrel bug 4367783 (dealing
   1.899 +     * with larger than 8-bit chars).  The old behavior is preserved
   1.900 +     * in orbutil.IIOPInputStream_1_3 in order to interoperate with
   1.901 +     * our legacy ORBs.
   1.902 +     */
   1.903 +    protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream)
   1.904 +    {
   1.905 +        return stream.read_wstring();
   1.906 +    }
   1.907 +
   1.908 +    public final String readUTF() throws IOException{
   1.909 +        try{
   1.910 +            readObjectState.readData(this);
   1.911 +
   1.912 +            return internalReadUTF(orbStream);
   1.913 +        } catch (MARSHAL marshalException) {
   1.914 +            handleOptionalDataMarshalException(marshalException, false);
   1.915 +            throw marshalException;
   1.916 +        } catch(Error e) {
   1.917 +            IOException exc = new IOException(e.getMessage());
   1.918 +            exc.initCause(e);
   1.919 +            throw exc ;
   1.920 +        }
   1.921 +    }
   1.922 +
   1.923 +    // If the ORB stream detects an incompatibility between what's
   1.924 +    // on the wire and what our Serializable's readObject wants,
   1.925 +    // it throws a MARSHAL exception with a specific minor code.
   1.926 +    // This is rethrown to the readObject as an OptionalDataException.
   1.927 +    // So far in RMI-IIOP, this process isn't specific enough to
   1.928 +    // tell the readObject how much data is available, so we always
   1.929 +    // set the OptionalDataException's EOF marker to true.
   1.930 +    private void handleOptionalDataMarshalException(MARSHAL marshalException,
   1.931 +                                                    boolean objectRead)
   1.932 +        throws IOException {
   1.933 +
   1.934 +        // Java Object Serialization spec 3.4: "If the readObject method
   1.935 +        // of the class attempts to read more data than is present in the
   1.936 +        // optional part of the stream for this class, the stream will
   1.937 +        // return -1 for bytewise reads, throw an EOFException for
   1.938 +        // primitive data reads, or throw an OptionalDataException
   1.939 +        // with the eof field set to true for object reads."
   1.940 +        if (marshalException.minor
   1.941 +            == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
   1.942 +
   1.943 +            IOException result;
   1.944 +
   1.945 +            if (!objectRead)
   1.946 +                result = new EOFException("No more optional data");
   1.947 +            else
   1.948 +                result = createOptionalDataException();
   1.949 +
   1.950 +            result.initCause(marshalException);
   1.951 +
   1.952 +            setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
   1.953 +
   1.954 +            throw result;
   1.955 +        }
   1.956 +    }
   1.957 +
   1.958 +    public final synchronized void registerValidation(ObjectInputValidation obj,
   1.959 +                                                      int prio)
   1.960 +        throws NotActiveException, InvalidObjectException{
   1.961 +        // XXX I18N, logging needed.
   1.962 +        throw new Error("Method registerValidation not supported");
   1.963 +    }
   1.964 +
   1.965 +    protected final Class resolveClass(ObjectStreamClass v)
   1.966 +        throws IOException, ClassNotFoundException{
   1.967 +        // XXX I18N, logging needed.
   1.968 +        throw new IOException("Method resolveClass not supported");
   1.969 +    }
   1.970 +
   1.971 +    protected final Object resolveObject(Object obj) throws IOException{
   1.972 +        // XXX I18N, logging needed.
   1.973 +        throw new IOException("Method resolveObject not supported");
   1.974 +    }
   1.975 +
   1.976 +    public final int skipBytes(int len) throws IOException{
   1.977 +        try{
   1.978 +            readObjectState.readData(this);
   1.979 +
   1.980 +            byte buf[] = new byte[len];
   1.981 +            orbStream.read_octet_array(buf, 0, len);
   1.982 +            return len;
   1.983 +        } catch (MARSHAL marshalException) {
   1.984 +            handleOptionalDataMarshalException(marshalException, false);
   1.985 +
   1.986 +            throw marshalException;
   1.987 +        } catch(Error e) {
   1.988 +            IOException exc = new IOException(e.getMessage());
   1.989 +            exc.initCause(e) ;
   1.990 +            throw exc ;
   1.991 +        }
   1.992 +    }
   1.993 +
   1.994 +    private synchronized Object inputObject(Class clz,
   1.995 +                               String repositoryID,
   1.996 +                               com.sun.org.omg.SendingContext.CodeBase sender,
   1.997 +                               int offset)
   1.998 +        throws IOException, ClassNotFoundException
   1.999 +    {
  1.1000 +
  1.1001 +        /*
  1.1002 +         * Get the descriptor and then class of the incoming object.
  1.1003 +         */
  1.1004 +
  1.1005 +        currentClassDesc = ObjectStreamClass.lookup(clz);
  1.1006 +        currentClass = currentClassDesc.forClass();
  1.1007 +        //currentClassDesc.setClass(currentClass);
  1.1008 +        if (currentClass == null)
  1.1009 +            // XXX I18N, logging needed.
  1.1010 +            throw new ClassNotFoundException(currentClassDesc.getName());
  1.1011 +
  1.1012 +        try {
  1.1013 +            /* If Externalizable,
  1.1014 +             *  Create an instance and tell it to read its data.
  1.1015 +             * else,
  1.1016 +             *  Handle it as a serializable class.
  1.1017 +             */
  1.1018 +            if (Enum.class.isAssignableFrom( clz )) {
  1.1019 +                int ordinal = orbStream.read_long() ;
  1.1020 +                String value = (String)orbStream.read_value( String.class ) ;
  1.1021 +                return Enum.valueOf( clz, value ) ;
  1.1022 +            } else if (currentClassDesc.isExternalizable()) {
  1.1023 +                try {
  1.1024 +                    currentObject = (currentClass == null) ?
  1.1025 +                        null : currentClassDesc.newInstance();
  1.1026 +                    if (currentObject != null) {
  1.1027 +
  1.1028 +                        // Store this object and its beginning position
  1.1029 +                        // since there might be indirections to it while
  1.1030 +                        // it's been unmarshalled.
  1.1031 +                        activeRecursionMgr.addObject(offset, currentObject);
  1.1032 +
  1.1033 +                        // Read format version
  1.1034 +                        readFormatVersion();
  1.1035 +
  1.1036 +                        Externalizable ext = (Externalizable)currentObject;
  1.1037 +                        ext.readExternal(this);
  1.1038 +                }
  1.1039 +            } catch (InvocationTargetException e) {
  1.1040 +                InvalidClassException exc = new InvalidClassException(
  1.1041 +                    currentClass.getName(),
  1.1042 +                    "InvocationTargetException accessing no-arg constructor");
  1.1043 +                exc.initCause( e ) ;
  1.1044 +                throw exc ;
  1.1045 +            } catch (UnsupportedOperationException e) {
  1.1046 +                InvalidClassException exc = new InvalidClassException(
  1.1047 +                    currentClass.getName(),
  1.1048 +                    "UnsupportedOperationException accessing no-arg constructor");
  1.1049 +                exc.initCause( e ) ;
  1.1050 +                throw exc ;
  1.1051 +            } catch (InstantiationException e) {
  1.1052 +                InvalidClassException exc = new InvalidClassException(
  1.1053 +                    currentClass.getName(),
  1.1054 +                    "InstantiationException accessing no-arg constructor");
  1.1055 +                exc.initCause( e ) ;
  1.1056 +                throw exc ;
  1.1057 +            }
  1.1058 +        } // end : if (currentClassDesc.isExternalizable())
  1.1059 +        else {
  1.1060 +            /* Count number of classes and descriptors we might have
  1.1061 +             * to work on.
  1.1062 +             */
  1.1063 +
  1.1064 +            ObjectStreamClass currdesc = currentClassDesc;
  1.1065 +            Class currclass = currentClass;
  1.1066 +
  1.1067 +            int spBase = spClass;       // current top of stack
  1.1068 +
  1.1069 +            /* The object's classes should be processed from supertype to subtype
  1.1070 +             * Push all the clases of the current object onto a stack.
  1.1071 +             * Note that only the serializable classes are represented
  1.1072 +             * in the descriptor list.
  1.1073 +             *
  1.1074 +             * Handle versioning where one or more supertypes of
  1.1075 +             * have been inserted or removed.  The stack will
  1.1076 +             * contain pairs of descriptors and the corresponding
  1.1077 +             * class.  If the object has a class that did not occur in
  1.1078 +             * the original the descriptor will be null.  If the
  1.1079 +             * original object had a descriptor for a class not
  1.1080 +             * present in the local hierarchy of the object the class will be
  1.1081 +             * null.
  1.1082 +             *
  1.1083 +             */
  1.1084 +
  1.1085 +            /*
  1.1086 +             * This is your basic diff pattern, made simpler
  1.1087 +             * because reordering is not allowed.
  1.1088 +             */
  1.1089 +            // sun.4296963 ibm.11861
  1.1090 +            // d11861 we should stop when we find the highest serializable class
  1.1091 +            // We need this so that when we allocate the new object below, we
  1.1092 +            // can call the constructor of the non-serializable superclass.
  1.1093 +            // Note that in the JRMP variant of this code the
  1.1094 +            // ObjectStreamClass.lookup() method handles this, but we've put
  1.1095 +            // this fix here rather than change lookup because the new behaviour
  1.1096 +            // is needed in other cases.
  1.1097 +
  1.1098 +            for (currdesc = currentClassDesc, currclass = currentClass;
  1.1099 +                 currdesc != null && currdesc.isSerializable();   /*sun.4296963 ibm.11861*/
  1.1100 +                 currdesc = currdesc.getSuperclass()) {
  1.1101 +
  1.1102 +                /*
  1.1103 +                 * Search the classes to see if the class of this
  1.1104 +                 * descriptor appears further up the hierarchy. Until
  1.1105 +                 * it's found assume its an inserted class.  If it's
  1.1106 +                 * not found, its the descriptor's class that has been
  1.1107 +                 * removed.
  1.1108 +                 */
  1.1109 +                Class cc = currdesc.forClass();
  1.1110 +                Class cl;
  1.1111 +                for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  1.1112 +                    if (cc == cl) {
  1.1113 +                        // found a superclass that matches this descriptor
  1.1114 +                        break;
  1.1115 +                    } else {
  1.1116 +                        /* Ignore a class that doesn't match.  No
  1.1117 +                         * action is needed since it is already
  1.1118 +                         * initialized.
  1.1119 +                         */
  1.1120 +                    }
  1.1121 +                } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
  1.1122 +                /* Test if there is room for this new entry.
  1.1123 +                 * If not, double the size of the arrays and copy the contents.
  1.1124 +                 */
  1.1125 +                spClass++;
  1.1126 +                if (spClass >= classes.length) {
  1.1127 +                    int newlen = classes.length * 2;
  1.1128 +                    Class[] newclasses = new Class[newlen];
  1.1129 +                    ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  1.1130 +
  1.1131 +                    System.arraycopy(classes, 0,
  1.1132 +                                     newclasses, 0,
  1.1133 +                                     classes.length);
  1.1134 +                    System.arraycopy(classdesc, 0,
  1.1135 +                                     newclassdesc, 0,
  1.1136 +                                     classes.length);
  1.1137 +
  1.1138 +                    classes = newclasses;
  1.1139 +                    classdesc = newclassdesc;
  1.1140 +                }
  1.1141 +
  1.1142 +                if (cl == null) {
  1.1143 +                    /* Class not found corresponding to this descriptor.
  1.1144 +                     * Pop off all the extra classes pushed.
  1.1145 +                     * Push the descriptor and a null class.
  1.1146 +                     */
  1.1147 +                    classdesc[spClass] = currdesc;
  1.1148 +                    classes[spClass] = null;
  1.1149 +                } else {
  1.1150 +                    /* Current class descriptor matches current class.
  1.1151 +                     * Some classes may have been inserted.
  1.1152 +                     * Record the match and advance the class, continue
  1.1153 +                     * with the next descriptor.
  1.1154 +                     */
  1.1155 +                    classdesc[spClass] = currdesc;
  1.1156 +                    classes[spClass] = cl;
  1.1157 +                    currclass = cl.getSuperclass();
  1.1158 +                }
  1.1159 +            } // end : for (currdesc = currentClassDesc, currclass = currentClass;
  1.1160 +
  1.1161 +            /* Allocate a new object.  The object is only constructed
  1.1162 +             * above the highest serializable class and is set to
  1.1163 +             * default values for all more specialized classes.
  1.1164 +             */
  1.1165 +            try {
  1.1166 +                currentObject = (currentClass == null) ?
  1.1167 +                    null : currentClassDesc.newInstance() ;
  1.1168 +
  1.1169 +                // Store this object and its beginning position
  1.1170 +                // since there might be indirections to it while
  1.1171 +                // it's been unmarshalled.
  1.1172 +                activeRecursionMgr.addObject(offset, currentObject);
  1.1173 +            } catch (InvocationTargetException e) {
  1.1174 +                InvalidClassException exc = new InvalidClassException(
  1.1175 +                    currentClass.getName(),
  1.1176 +                    "InvocationTargetException accessing no-arg constructor");
  1.1177 +                exc.initCause( e ) ;
  1.1178 +                throw exc ;
  1.1179 +            } catch (UnsupportedOperationException e) {
  1.1180 +                InvalidClassException exc = new InvalidClassException(
  1.1181 +                    currentClass.getName(),
  1.1182 +                    "UnsupportedOperationException accessing no-arg constructor");
  1.1183 +                exc.initCause( e ) ;
  1.1184 +                throw exc ;
  1.1185 +            } catch (InstantiationException e) {
  1.1186 +                InvalidClassException exc = new InvalidClassException(
  1.1187 +                    currentClass.getName(),
  1.1188 +                    "InstantiationException accessing no-arg constructor");
  1.1189 +                exc.initCause( e ) ;
  1.1190 +                throw exc ;
  1.1191 +            }
  1.1192 +
  1.1193 +            /*
  1.1194 +             * For all the pushed descriptors and classes.
  1.1195 +             *  if the class has its own writeObject and readObject methods
  1.1196 +             *      call the readObject method
  1.1197 +             *  else
  1.1198 +             *      invoke the defaultReadObject method
  1.1199 +             */
  1.1200 +            try {
  1.1201 +                for (spClass = spClass; spClass > spBase; spClass--) {
  1.1202 +                    /*
  1.1203 +                     * Set current descriptor and corresponding class
  1.1204 +                     */
  1.1205 +                    currentClassDesc = classdesc[spClass];
  1.1206 +                    currentClass = classes[spClass];
  1.1207 +                    if (classes[spClass] != null) {
  1.1208 +                        /* Read the data from the stream described by the
  1.1209 +                         * descriptor and store into the matching class.
  1.1210 +                         */
  1.1211 +
  1.1212 +                        ReadObjectState oldState = readObjectState;
  1.1213 +                        setState(DEFAULT_STATE);
  1.1214 +
  1.1215 +                        try {
  1.1216 +
  1.1217 +                            // Changed since invokeObjectReader no longer does this.
  1.1218 +                            if (currentClassDesc.hasWriteObject()) {
  1.1219 +
  1.1220 +                                // Read format version
  1.1221 +                                readFormatVersion();
  1.1222 +
  1.1223 +                                // Read defaultWriteObject indicator
  1.1224 +                                boolean calledDefaultWriteObject = readBoolean();
  1.1225 +
  1.1226 +                                readObjectState.beginUnmarshalCustomValue(this,
  1.1227 +                                                                          calledDefaultWriteObject,
  1.1228 +                                                                          (currentClassDesc.readObjectMethod
  1.1229 +                                                                           != null));
  1.1230 +                            } else {
  1.1231 +                                if (currentClassDesc.hasReadObject())
  1.1232 +                                    setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
  1.1233 +                            }
  1.1234 +
  1.1235 +                            if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) ||
  1.1236 +                                readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) {
  1.1237 +
  1.1238 +                                // Error case of no readObject and didn't call
  1.1239 +                                // defaultWriteObject handled in default state
  1.1240 +
  1.1241 +                                ObjectStreamField[] fields =
  1.1242 +                                    currentClassDesc.getFieldsNoCopy();
  1.1243 +                                if (fields.length > 0) {
  1.1244 +                                    inputClassFields(currentObject, currentClass, fields, sender);
  1.1245 +                                }
  1.1246 +                            }
  1.1247 +
  1.1248 +                            if (currentClassDesc.hasWriteObject())
  1.1249 +                                readObjectState.endUnmarshalCustomValue(this);
  1.1250 +
  1.1251 +                        } finally {
  1.1252 +                            setState(oldState);
  1.1253 +                        }
  1.1254 +
  1.1255 +                    } else {
  1.1256 +
  1.1257 +                        // _REVISIT_ : Can we ever get here?
  1.1258 +                        /* No local class for this descriptor,
  1.1259 +                         * Skip over the data for this class.
  1.1260 +                         * like defaultReadObject with a null currentObject.
  1.1261 +                         * The code will read the values but discard them.
  1.1262 +                         */
  1.1263 +                            ObjectStreamField[] fields =
  1.1264 +                                currentClassDesc.getFieldsNoCopy();
  1.1265 +                            if (fields.length > 0) {
  1.1266 +                                inputClassFields(null, currentClass, fields, sender);
  1.1267 +                            }
  1.1268 +
  1.1269 +                        }
  1.1270 +
  1.1271 +                }
  1.1272 +            } finally {
  1.1273 +                                // Make sure we exit at the same stack level as when we started.
  1.1274 +                spClass = spBase;
  1.1275 +            }
  1.1276 +        }
  1.1277 +        } finally {
  1.1278 +            // We've completed deserializing this object.  Any
  1.1279 +            // future indirections will be handled correctly at the
  1.1280 +            // CDR level.  The ActiveRecursionManager only deals with
  1.1281 +            // objects currently being deserialized.
  1.1282 +            activeRecursionMgr.removeObject(offset);
  1.1283 +        }
  1.1284 +
  1.1285 +        return currentObject;
  1.1286 +    }
  1.1287 +
  1.1288 +    // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
  1.1289 +    // repositoryID.  It is assumed that the sender will not provide base_value id's for non-serializable
  1.1290 +    // classes!
  1.1291 +    private Vector getOrderedDescriptions(String repositoryID,
  1.1292 +                                          com.sun.org.omg.SendingContext.CodeBase sender) {
  1.1293 +        Vector descs = new Vector();
  1.1294 +
  1.1295 +        if (sender == null) {
  1.1296 +            return descs;
  1.1297 +        }
  1.1298 +
  1.1299 +        FullValueDescription aFVD = sender.meta(repositoryID);
  1.1300 +        while (aFVD != null) {
  1.1301 +            descs.insertElementAt(aFVD, 0);
  1.1302 +            if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
  1.1303 +                aFVD = sender.meta(aFVD.base_value);
  1.1304 +            }
  1.1305 +            else return descs;
  1.1306 +        }
  1.1307 +
  1.1308 +        return descs;
  1.1309 +    }
  1.1310 +
  1.1311 +    /**
  1.1312 +     * This input method uses FullValueDescriptions retrieved from the sender's runtime to
  1.1313 +     * read in the data.  This method is capable of throwing out data not applicable to client's fields.
  1.1314 +     * This method handles instances where the reader has a class not sent by the sender, the sender sent
  1.1315 +     * a class not present on the reader, and/or the reader's class does not match the sender's class.
  1.1316 +     *
  1.1317 +     * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
  1.1318 +     * indicates custom marsahling than the local type is used to read the data off the wire.  However,
  1.1319 +     * if either says custom while the other does not, a MARSHAL error is thrown.  Externalizable is
  1.1320 +     * a form of custom marshaling.
  1.1321 +     *
  1.1322 +     */
  1.1323 +    private synchronized Object inputObjectUsingFVD(Class clz,
  1.1324 +                                       String repositoryID,
  1.1325 +                                       com.sun.org.omg.SendingContext.CodeBase sender,
  1.1326 +                                       int offset)
  1.1327 +        throws IOException, ClassNotFoundException
  1.1328 +    {
  1.1329 +        int spBase = spClass;   // current top of stack
  1.1330 +        try{
  1.1331 +
  1.1332 +            /*
  1.1333 +             * Get the descriptor and then class of the incoming object.
  1.1334 +             */
  1.1335 +
  1.1336 +            ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
  1.1337 +            Class currclass = currentClass = clz;
  1.1338 +
  1.1339 +            /* If Externalizable,
  1.1340 +             *  Create an instance and tell it to read its data.
  1.1341 +             * else,
  1.1342 +             *  Handle it as a serializable class.
  1.1343 +             */
  1.1344 +            if (currentClassDesc.isExternalizable()) {
  1.1345 +                try {
  1.1346 +                    currentObject = (currentClass == null) ?
  1.1347 +                        null : currentClassDesc.newInstance();
  1.1348 +                    if (currentObject != null) {
  1.1349 +                        // Store this object and its beginning position
  1.1350 +                        // since there might be indirections to it while
  1.1351 +                        // it's been unmarshalled.
  1.1352 +                        activeRecursionMgr.addObject(offset, currentObject);
  1.1353 +
  1.1354 +                        // Read format version
  1.1355 +                        readFormatVersion();
  1.1356 +
  1.1357 +                        Externalizable ext = (Externalizable)currentObject;
  1.1358 +                        ext.readExternal(this);
  1.1359 +                    }
  1.1360 +                } catch (InvocationTargetException e) {
  1.1361 +                    InvalidClassException exc = new InvalidClassException(
  1.1362 +                        currentClass.getName(),
  1.1363 +                        "InvocationTargetException accessing no-arg constructor");
  1.1364 +                    exc.initCause( e ) ;
  1.1365 +                    throw exc ;
  1.1366 +                } catch (UnsupportedOperationException e) {
  1.1367 +                    InvalidClassException exc = new InvalidClassException(
  1.1368 +                        currentClass.getName(),
  1.1369 +                        "UnsupportedOperationException accessing no-arg constructor");
  1.1370 +                    exc.initCause( e ) ;
  1.1371 +                    throw exc ;
  1.1372 +                } catch (InstantiationException e) {
  1.1373 +                    InvalidClassException exc = new InvalidClassException(
  1.1374 +                        currentClass.getName(),
  1.1375 +                        "InstantiationException accessing no-arg constructor");
  1.1376 +                    exc.initCause( e ) ;
  1.1377 +                    throw exc ;
  1.1378 +                }
  1.1379 +            } else {
  1.1380 +                /*
  1.1381 +                 * This is your basic diff pattern, made simpler
  1.1382 +                 * because reordering is not allowed.
  1.1383 +                 */
  1.1384 +                for (currdesc = currentClassDesc, currclass = currentClass;
  1.1385 +                     currdesc != null && currdesc.isSerializable();   /*sun.4296963 ibm.11861*/
  1.1386 +
  1.1387 +                     currdesc = currdesc.getSuperclass()) {
  1.1388 +
  1.1389 +                    /*
  1.1390 +                     * Search the classes to see if the class of this
  1.1391 +                     * descriptor appears further up the hierarchy. Until
  1.1392 +                     * it's found assume its an inserted class.  If it's
  1.1393 +                     * not found, its the descriptor's class that has been
  1.1394 +                     * removed.
  1.1395 +                     */
  1.1396 +                    Class cc = currdesc.forClass();
  1.1397 +                    Class cl;
  1.1398 +                    for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  1.1399 +                        if (cc == cl) {
  1.1400 +                            // found a superclass that matches this descriptor
  1.1401 +                            break;
  1.1402 +                        } else {
  1.1403 +                            /* Ignore a class that doesn't match.  No
  1.1404 +                             * action is needed since it is already
  1.1405 +                             * initialized.
  1.1406 +                             */
  1.1407 +                        }
  1.1408 +                    } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
  1.1409 +                    /* Test if there is room for this new entry.
  1.1410 +                     * If not, double the size of the arrays and copy the contents.
  1.1411 +                     */
  1.1412 +                    spClass++;
  1.1413 +                    if (spClass >= classes.length) {
  1.1414 +                        int newlen = classes.length * 2;
  1.1415 +                        Class[] newclasses = new Class[newlen];
  1.1416 +                        ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  1.1417 +
  1.1418 +                        System.arraycopy(classes, 0,
  1.1419 +                                         newclasses, 0,
  1.1420 +                                         classes.length);
  1.1421 +                        System.arraycopy(classdesc, 0,
  1.1422 +                                         newclassdesc, 0,
  1.1423 +                                         classes.length);
  1.1424 +
  1.1425 +                        classes = newclasses;
  1.1426 +                        classdesc = newclassdesc;
  1.1427 +                    }
  1.1428 +
  1.1429 +                    if (cl == null) {
  1.1430 +                        /* Class not found corresponding to this descriptor.
  1.1431 +                         * Pop off all the extra classes pushed.
  1.1432 +                         * Push the descriptor and a null class.
  1.1433 +                         */
  1.1434 +                        classdesc[spClass] = currdesc;
  1.1435 +                        classes[spClass] = null;
  1.1436 +                    } else {
  1.1437 +                        /* Current class descriptor matches current class.
  1.1438 +                         * Some classes may have been inserted.
  1.1439 +                         * Record the match and advance the class, continue
  1.1440 +                         * with the next descriptor.
  1.1441 +                         */
  1.1442 +                        classdesc[spClass] = currdesc;
  1.1443 +                        classes[spClass] = cl;
  1.1444 +                        currclass = cl.getSuperclass();
  1.1445 +                    }
  1.1446 +                } // end : for (currdesc = currentClassDesc, currclass = currentClass;
  1.1447 +
  1.1448 +                /* Allocate a new object.
  1.1449 +                 */
  1.1450 +                try {
  1.1451 +                    currentObject = (currentClass == null) ?
  1.1452 +                        null : currentClassDesc.newInstance();
  1.1453 +
  1.1454 +                    // Store this object and its beginning position
  1.1455 +                    // since there might be indirections to it while
  1.1456 +                    // it's been unmarshalled.
  1.1457 +                    activeRecursionMgr.addObject(offset, currentObject);
  1.1458 +                } catch (InvocationTargetException e) {
  1.1459 +                    InvalidClassException exc = new InvalidClassException(
  1.1460 +                        currentClass.getName(),
  1.1461 +                        "InvocationTargetException accessing no-arg constructor");
  1.1462 +                    exc.initCause( e ) ;
  1.1463 +                    throw exc ;
  1.1464 +                } catch (UnsupportedOperationException e) {
  1.1465 +                    InvalidClassException exc = new InvalidClassException(
  1.1466 +                        currentClass.getName(),
  1.1467 +                        "UnsupportedOperationException accessing no-arg constructor");
  1.1468 +                    exc.initCause( e ) ;
  1.1469 +                    throw exc ;
  1.1470 +                } catch (InstantiationException e) {
  1.1471 +                    InvalidClassException exc = new InvalidClassException(
  1.1472 +                        currentClass.getName(),
  1.1473 +                        "InstantiationException accessing no-arg constructor");
  1.1474 +                    exc.initCause( e ) ;
  1.1475 +                    throw exc ;
  1.1476 +                }
  1.1477 +
  1.1478 +                Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
  1.1479 +
  1.1480 +                while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
  1.1481 +                    FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1.1482 +                    // d4365188: backward compatability
  1.1483 +                    String repIDForFVD = vhandler.getClassName(fvd.id);
  1.1484 +                    String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
  1.1485 +
  1.1486 +                    while ((spClass > spBase) &&
  1.1487 +                           (!repIDForFVD.equals(repIDForClass))) {
  1.1488 +                        int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
  1.1489 +                        if (pos != -1) {
  1.1490 +                            spClass = pos;
  1.1491 +                            currclass = currentClass = classes[spClass];
  1.1492 +                            repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
  1.1493 +                        }
  1.1494 +                        else { // Read and throw away one level of the fvdslist
  1.1495 +
  1.1496 +                            // This seems to mean that the sender had a superclass that
  1.1497 +                            // we don't have
  1.1498 +
  1.1499 +                            if (fvd.is_custom) {
  1.1500 +
  1.1501 +                                readFormatVersion();
  1.1502 +                                boolean calledDefaultWriteObject = readBoolean();
  1.1503 +
  1.1504 +                                if (calledDefaultWriteObject)
  1.1505 +                                    inputClassFields(null, null, null, fvd.members, sender);
  1.1506 +
  1.1507 +                                if (getStreamFormatVersion() == 2) {
  1.1508 +
  1.1509 +                                    ((ValueInputStream)getOrbStream()).start_value();
  1.1510 +                                    ((ValueInputStream)getOrbStream()).end_value();
  1.1511 +                                }
  1.1512 +
  1.1513 +                                // WARNING: If stream format version is 1 and there's
  1.1514 +                                // optional data, we'll get some form of exception down
  1.1515 +                                // the line or data corruption.
  1.1516 +
  1.1517 +                            } else {
  1.1518 +
  1.1519 +                                inputClassFields(null, currentClass, null, fvd.members, sender);
  1.1520 +                            }
  1.1521 +
  1.1522 +                            if (fvdsList.hasMoreElements()){
  1.1523 +                                fvd = (FullValueDescription)fvdsList.nextElement();
  1.1524 +                                repIDForFVD = vhandler.getClassName(fvd.id);
  1.1525 +                            }
  1.1526 +                            else return currentObject;
  1.1527 +                        }
  1.1528 +                    }
  1.1529 +
  1.1530 +                    currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
  1.1531 +
  1.1532 +                    if (!repIDForClass.equals("java.lang.Object")) {
  1.1533 +
  1.1534 +                        // If the sender used custom marshaling, then it should have put
  1.1535 +                        // the two bytes on the wire indicating stream format version
  1.1536 +                        // and whether or not the writeObject method called
  1.1537 +                        // defaultWriteObject/writeFields.
  1.1538 +
  1.1539 +                        ReadObjectState oldState = readObjectState;
  1.1540 +                        setState(DEFAULT_STATE);
  1.1541 +
  1.1542 +                        try {
  1.1543 +
  1.1544 +                            if (fvd.is_custom) {
  1.1545 +
  1.1546 +                                // Read format version
  1.1547 +                                readFormatVersion();
  1.1548 +
  1.1549 +                                // Read defaultWriteObject indicator
  1.1550 +                                boolean calledDefaultWriteObject = readBoolean();
  1.1551 +
  1.1552 +                                readObjectState.beginUnmarshalCustomValue(this,
  1.1553 +                                                                          calledDefaultWriteObject,
  1.1554 +                                                                          (currentClassDesc.readObjectMethod
  1.1555 +                                                                           != null));
  1.1556 +                            }
  1.1557 +
  1.1558 +                            boolean usedReadObject = false;
  1.1559 +
  1.1560 +                            // Always use readObject if it exists, and fall back to default
  1.1561 +                            // unmarshaling if it doesn't.
  1.1562 +                            try {
  1.1563 +
  1.1564 +                                if (!fvd.is_custom && currentClassDesc.hasReadObject())
  1.1565 +                                    setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
  1.1566 +
  1.1567 +                                // See the definition of defaultReadObjectFVDMembers
  1.1568 +                                // for more information.  This concerns making sure
  1.1569 +                                // we use the remote FVD's members in defaultReadObject.
  1.1570 +                                defaultReadObjectFVDMembers = fvd.members;
  1.1571 +                                usedReadObject = invokeObjectReader(currentClassDesc,
  1.1572 +                                                                    currentObject,
  1.1573 +                                                                    currentClass);
  1.1574 +
  1.1575 +                            } finally {
  1.1576 +                                defaultReadObjectFVDMembers = null;
  1.1577 +                            }
  1.1578 +
  1.1579 +                            // Note that the !usedReadObject !calledDefaultWriteObject
  1.1580 +                            // case is handled by the beginUnmarshalCustomValue method
  1.1581 +                            // of the default state
  1.1582 +                            if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT)
  1.1583 +                                inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
  1.1584 +
  1.1585 +                            if (fvd.is_custom)
  1.1586 +                                readObjectState.endUnmarshalCustomValue(this);
  1.1587 +
  1.1588 +                        } finally {
  1.1589 +                            setState(oldState);
  1.1590 +                        }
  1.1591 +
  1.1592 +                        currclass = currentClass = classes[--spClass];
  1.1593 +
  1.1594 +                    } else {
  1.1595 +
  1.1596 +                        // The remaining hierarchy of the local class does not match the sender's FVD.
  1.1597 +                        // So, use remaining FVDs to read data off wire.  If any remaining FVDs indicate
  1.1598 +                        // custom marshaling, throw MARSHAL error.
  1.1599 +                        inputClassFields(null, currentClass, null, fvd.members, sender);
  1.1600 +
  1.1601 +                        while (fvdsList.hasMoreElements()){
  1.1602 +                            fvd = (FullValueDescription)fvdsList.nextElement();
  1.1603 +
  1.1604 +                            if (fvd.is_custom)
  1.1605 +                                skipCustomUsingFVD(fvd.members, sender);
  1.1606 +                            else
  1.1607 +                                inputClassFields(null, currentClass, null, fvd.members, sender);
  1.1608 +                        }
  1.1609 +
  1.1610 +                    }
  1.1611 +
  1.1612 +                } // end : while(fvdsList.hasMoreElements())
  1.1613 +                while (fvdsList.hasMoreElements()){
  1.1614 +
  1.1615 +                    FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1.1616 +                    if (fvd.is_custom)
  1.1617 +                        skipCustomUsingFVD(fvd.members, sender);
  1.1618 +                    else
  1.1619 +                        throwAwayData(fvd.members, sender);
  1.1620 +                }
  1.1621 +            }
  1.1622 +
  1.1623 +            return currentObject;
  1.1624 +        }
  1.1625 +        finally {
  1.1626 +                // Make sure we exit at the same stack level as when we started.
  1.1627 +                spClass = spBase;
  1.1628 +
  1.1629 +                // We've completed deserializing this object.  Any
  1.1630 +                // future indirections will be handled correctly at the
  1.1631 +                // CDR level.  The ActiveRecursionManager only deals with
  1.1632 +                // objects currently being deserialized.
  1.1633 +                activeRecursionMgr.removeObject(offset);
  1.1634 +            }
  1.1635 +
  1.1636 +        }
  1.1637 +
  1.1638 +    /**
  1.1639 +     * This input method uses FullValueDescriptions retrieved from the sender's runtime to
  1.1640 +     * read in the data.  This method is capable of throwing out data not applicable to client's fields.
  1.1641 +     *
  1.1642 +     * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
  1.1643 +     * indicates custom marsahling than the local type is used to read the data off the wire.  However,
  1.1644 +     * if either says custom while the other does not, a MARSHAL error is thrown.  Externalizable is
  1.1645 +     * a form of custom marshaling.
  1.1646 +     *
  1.1647 +     */
  1.1648 +    private Object skipObjectUsingFVD(String repositoryID,
  1.1649 +                                      com.sun.org.omg.SendingContext.CodeBase sender)
  1.1650 +        throws IOException, ClassNotFoundException
  1.1651 +    {
  1.1652 +
  1.1653 +        Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
  1.1654 +
  1.1655 +        while(fvdsList.hasMoreElements()) {
  1.1656 +            FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1.1657 +            String repIDForFVD = vhandler.getClassName(fvd.id);
  1.1658 +
  1.1659 +            if (!repIDForFVD.equals("java.lang.Object")) {
  1.1660 +                if (fvd.is_custom) {
  1.1661 +
  1.1662 +                    readFormatVersion();
  1.1663 +
  1.1664 +                    boolean calledDefaultWriteObject = readBoolean();
  1.1665 +
  1.1666 +                    if (calledDefaultWriteObject)
  1.1667 +                        inputClassFields(null, null, null, fvd.members, sender);
  1.1668 +
  1.1669 +                    if (getStreamFormatVersion() == 2) {
  1.1670 +
  1.1671 +                        ((ValueInputStream)getOrbStream()).start_value();
  1.1672 +                        ((ValueInputStream)getOrbStream()).end_value();
  1.1673 +                    }
  1.1674 +
  1.1675 +                    // WARNING: If stream format version is 1 and there's
  1.1676 +                    // optional data, we'll get some form of exception down
  1.1677 +                    // the line.
  1.1678 +
  1.1679 +                } else {
  1.1680 +                    // Use default marshaling
  1.1681 +                    inputClassFields(null, null, null, fvd.members, sender);
  1.1682 +                }
  1.1683 +            }
  1.1684 +
  1.1685 +        } // end : while(fvdsList.hasMoreElements())
  1.1686 +        return null;
  1.1687 +
  1.1688 +    }
  1.1689 +
  1.1690 +    ///////////////////
  1.1691 +
  1.1692 +    private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){
  1.1693 +
  1.1694 +        for (int i = _spClass; i > _spBase; i--){
  1.1695 +            if (classname.equals(classes[i].getName())) {
  1.1696 +                return i;
  1.1697 +            }
  1.1698 +        }
  1.1699 +
  1.1700 +        return -1;
  1.1701 +    }
  1.1702 +
  1.1703 +    /*
  1.1704 +     * Invoke the readObject method if present.  Assumes that in the case of custom
  1.1705 +     * marshaling, the format version and defaultWriteObject indicator were already
  1.1706 +     * removed.
  1.1707 +     */
  1.1708 +    private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass)
  1.1709 +        throws InvalidClassException, StreamCorruptedException,
  1.1710 +               ClassNotFoundException, IOException
  1.1711 +    {
  1.1712 +        if (osc.readObjectMethod == null) {
  1.1713 +            return false;
  1.1714 +        }
  1.1715 +
  1.1716 +        try {
  1.1717 +            osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
  1.1718 +            return true;
  1.1719 +        } catch (InvocationTargetException e) {
  1.1720 +            Throwable t = e.getTargetException();
  1.1721 +            if (t instanceof ClassNotFoundException)
  1.1722 +                throw (ClassNotFoundException)t;
  1.1723 +            else if (t instanceof IOException)
  1.1724 +                throw (IOException)t;
  1.1725 +            else if (t instanceof RuntimeException)
  1.1726 +                throw (RuntimeException) t;
  1.1727 +            else if (t instanceof Error)
  1.1728 +                throw (Error) t;
  1.1729 +            else
  1.1730 +                // XXX I18N, logging needed.
  1.1731 +                throw new Error("internal error");
  1.1732 +        } catch (IllegalAccessException e) {
  1.1733 +            return false;
  1.1734 +        }
  1.1735 +    }
  1.1736 +
  1.1737 +    /*
  1.1738 +     * Reset the stream to be just like it was after the constructor.
  1.1739 +     */
  1.1740 +    private void resetStream() throws IOException {
  1.1741 +
  1.1742 +        if (classes == null)
  1.1743 +            classes = new Class[20];
  1.1744 +        else {
  1.1745 +            for (int i = 0; i < classes.length; i++)
  1.1746 +                classes[i] = null;
  1.1747 +        }
  1.1748 +        if (classdesc == null)
  1.1749 +            classdesc = new ObjectStreamClass[20];
  1.1750 +        else {
  1.1751 +            for (int i = 0; i < classdesc.length; i++)
  1.1752 +                classdesc[i] = null;
  1.1753 +        }
  1.1754 +        spClass = 0;
  1.1755 +
  1.1756 +        if (callbacks != null)
  1.1757 +            callbacks.setSize(0);       // discard any pending callbacks
  1.1758 +    }
  1.1759 +
  1.1760 +    /**
  1.1761 +     * Factored out of inputClassFields  This reads a primitive value and sets it
  1.1762 +     * in the field of o described by the ObjectStreamField field.
  1.1763 +     *
  1.1764 +     * Note that reflection cannot be used here, because reflection cannot be used
  1.1765 +     * to set final fields.
  1.1766 +     */
  1.1767 +    private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field)
  1.1768 +        throws InvalidClassException, IOException {
  1.1769 +
  1.1770 +        try {
  1.1771 +            switch (field.getTypeCode()) {
  1.1772 +                case 'B':
  1.1773 +                    byte byteValue = orbStream.read_octet();
  1.1774 +                    bridge.putByte( o, field.getFieldID(), byteValue ) ;
  1.1775 +                    //reflective code: field.getField().setByte( o, byteValue ) ;
  1.1776 +                    break;
  1.1777 +                case 'Z':
  1.1778 +                    boolean booleanValue = orbStream.read_boolean();
  1.1779 +                    bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
  1.1780 +                    //reflective code: field.getField().setBoolean( o, booleanValue ) ;
  1.1781 +                    break;
  1.1782 +                case 'C':
  1.1783 +                    char charValue = orbStream.read_wchar();
  1.1784 +                    bridge.putChar( o, field.getFieldID(), charValue ) ;
  1.1785 +                    //reflective code: field.getField().setChar( o, charValue ) ;
  1.1786 +                    break;
  1.1787 +                case 'S':
  1.1788 +                    short shortValue = orbStream.read_short();
  1.1789 +                    bridge.putShort( o, field.getFieldID(), shortValue ) ;
  1.1790 +                    //reflective code: field.getField().setShort( o, shortValue ) ;
  1.1791 +                    break;
  1.1792 +                case 'I':
  1.1793 +                    int intValue = orbStream.read_long();
  1.1794 +                    bridge.putInt( o, field.getFieldID(), intValue ) ;
  1.1795 +                    //reflective code: field.getField().setInt( o, intValue ) ;
  1.1796 +                    break;
  1.1797 +                case 'J':
  1.1798 +                    long longValue = orbStream.read_longlong();
  1.1799 +                    bridge.putLong( o, field.getFieldID(), longValue ) ;
  1.1800 +                    //reflective code: field.getField().setLong( o, longValue ) ;
  1.1801 +                    break;
  1.1802 +                case 'F' :
  1.1803 +                    float floatValue = orbStream.read_float();
  1.1804 +                    bridge.putFloat( o, field.getFieldID(), floatValue ) ;
  1.1805 +                    //reflective code: field.getField().setFloat( o, floatValue ) ;
  1.1806 +                    break;
  1.1807 +                case 'D' :
  1.1808 +                    double doubleValue = orbStream.read_double();
  1.1809 +                    bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
  1.1810 +                    //reflective code: field.getField().setDouble( o, doubleValue ) ;
  1.1811 +                    break;
  1.1812 +                default:
  1.1813 +                    // XXX I18N, logging needed.
  1.1814 +                    throw new InvalidClassException(cl.getName());
  1.1815 +            }
  1.1816 +        } catch (IllegalArgumentException e) {
  1.1817 +            /* This case should never happen. If the field types
  1.1818 +               are not the same, InvalidClassException is raised when
  1.1819 +               matching the local class to the serialized ObjectStreamClass. */
  1.1820 +            ClassCastException cce = new ClassCastException("Assigning instance of class " +
  1.1821 +                                         field.getType().getName() +
  1.1822 +                                         " to field " +
  1.1823 +                                         currentClassDesc.getName() + '#' +
  1.1824 +                                         field.getField().getName());
  1.1825 +            cce.initCause( e ) ;
  1.1826 +            throw cce ;
  1.1827 +        }
  1.1828 +     }
  1.1829 +
  1.1830 +    private Object inputObjectField(org.omg.CORBA.ValueMember field,
  1.1831 +                                    com.sun.org.omg.SendingContext.CodeBase sender)
  1.1832 +        throws IndirectionException, ClassNotFoundException, IOException,
  1.1833 +               StreamCorruptedException {
  1.1834 +
  1.1835 +        Object objectValue = null;
  1.1836 +        Class type = null;
  1.1837 +        String id = field.id;
  1.1838 +
  1.1839 +        try {
  1.1840 +            type = vhandler.getClassFromType(id);
  1.1841 +        } catch(ClassNotFoundException cnfe) {
  1.1842 +            // Make sure type = null
  1.1843 +            type = null;
  1.1844 +        }
  1.1845 +
  1.1846 +        String signature = null;
  1.1847 +        if (type != null)
  1.1848 +            signature = ValueUtility.getSignature(field);
  1.1849 +
  1.1850 +        if (signature != null && (signature.equals("Ljava/lang/Object;") ||
  1.1851 +                                  signature.equals("Ljava/io/Serializable;") ||
  1.1852 +                                  signature.equals("Ljava/io/Externalizable;"))) {
  1.1853 +            objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
  1.1854 +        } else {
  1.1855 +            // Decide what method call to make based on the type. If
  1.1856 +            // it is a type for which we need to load a stub, convert
  1.1857 +            // the type to the correct stub type.
  1.1858 +            //
  1.1859 +            // NOTE : Since FullValueDescription does not allow us
  1.1860 +            // to ask whether something is an interface we do not
  1.1861 +            // have the ability to optimize this check.
  1.1862 +
  1.1863 +            int callType = ValueHandlerImpl.kValueType;
  1.1864 +
  1.1865 +            if (!vhandler.isSequence(id)) {
  1.1866 +
  1.1867 +                if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
  1.1868 +
  1.1869 +                    // RMI Object reference...
  1.1870 +                    callType = ValueHandlerImpl.kRemoteType;
  1.1871 +
  1.1872 +                } else {
  1.1873 +
  1.1874 +                    // REVISIT.  If we don't have the local class,
  1.1875 +                    // we should probably verify that it's an RMI type,
  1.1876 +                    // query the remote FVD, and use is_abstract.
  1.1877 +                    // Our FVD seems to get NullPointerExceptions for any
  1.1878 +                    // non-RMI types.
  1.1879 +
  1.1880 +                    // This uses the local class in the same way as
  1.1881 +                    // inputObjectField(ObjectStreamField) does.  REVISIT
  1.1882 +                    // inputObjectField(ObjectStreamField)'s loadStubClass
  1.1883 +                    // logic.  Assumption is that the given type cannot
  1.1884 +                    // evolve to become a CORBA abstract interface or
  1.1885 +                    // a RMI abstract interface.
  1.1886 +
  1.1887 +                    if (type != null && type.isInterface() &&
  1.1888 +                        (vhandler.isAbstractBase(type) ||
  1.1889 +                         ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
  1.1890 +
  1.1891 +                        callType = ValueHandlerImpl.kAbstractType;
  1.1892 +                    }
  1.1893 +                }
  1.1894 +            }
  1.1895 +
  1.1896 +            // Now that we have used the FVD of the field to determine the proper course
  1.1897 +            // of action, it is ok to use the type (Class) from this point forward since
  1.1898 +            // the rep. id for this read will also follow on the wire.
  1.1899 +
  1.1900 +            switch (callType) {
  1.1901 +                case ValueHandlerImpl.kRemoteType:
  1.1902 +                    if (type != null)
  1.1903 +                        objectValue = Utility.readObjectAndNarrow(orbStream, type);
  1.1904 +                    else
  1.1905 +                        objectValue = orbStream.read_Object();
  1.1906 +                    break;
  1.1907 +                case ValueHandlerImpl.kAbstractType:
  1.1908 +                    if (type != null)
  1.1909 +                        objectValue = Utility.readAbstractAndNarrow(orbStream, type);
  1.1910 +                    else
  1.1911 +                        objectValue = orbStream.read_abstract_interface();
  1.1912 +                    break;
  1.1913 +                case ValueHandlerImpl.kValueType:
  1.1914 +                    if (type != null)
  1.1915 +                        objectValue = orbStream.read_value(type);
  1.1916 +                    else
  1.1917 +                                            objectValue = orbStream.read_value();
  1.1918 +                    break;
  1.1919 +                default:
  1.1920 +                    // XXX I18N, logging needed.
  1.1921 +                    throw new StreamCorruptedException("Unknown callType: " + callType);
  1.1922 +            }
  1.1923 +        }
  1.1924 +
  1.1925 +        return objectValue;
  1.1926 +    }
  1.1927 +
  1.1928 +    /**
  1.1929 +     * Factored out of inputClassFields and reused in
  1.1930 +     * inputCurrentClassFieldsForReadFields.
  1.1931 +     *
  1.1932 +     * Reads the field (which of an Object type as opposed to a primitive)
  1.1933 +     * described by ObjectStreamField field and returns it.
  1.1934 +     */
  1.1935 +    private Object inputObjectField(ObjectStreamField field)
  1.1936 +        throws InvalidClassException, StreamCorruptedException,
  1.1937 +               ClassNotFoundException, IndirectionException, IOException {
  1.1938 +
  1.1939 +        if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
  1.1940 +            return javax.rmi.CORBA.Util.readAny(orbStream);
  1.1941 +        }
  1.1942 +
  1.1943 +        Object objectValue = null;
  1.1944 +
  1.1945 +        // fields have an API to provide the actual class
  1.1946 +        // corresponding to the data type
  1.1947 +        // Class type = osc.forClass();
  1.1948 +        Class fieldType = field.getType();
  1.1949 +        Class actualType = fieldType; // This may change if stub loaded.
  1.1950 +
  1.1951 +        // Decide what method call to make based on the fieldType. If
  1.1952 +        // it is a type for which we need to load a stub, convert
  1.1953 +        // the type to the correct stub type.
  1.1954 +
  1.1955 +        int callType = ValueHandlerImpl.kValueType;
  1.1956 +        boolean narrow = false;
  1.1957 +
  1.1958 +        if (fieldType.isInterface()) {
  1.1959 +            boolean loadStubClass = false;
  1.1960 +
  1.1961 +            if (java.rmi.Remote.class.isAssignableFrom(fieldType)) {
  1.1962 +
  1.1963 +                // RMI Object reference...
  1.1964 +                callType = ValueHandlerImpl.kRemoteType;
  1.1965 +
  1.1966 +            } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){
  1.1967 +
  1.1968 +                // IDL Object reference...
  1.1969 +                callType = ValueHandlerImpl.kRemoteType;
  1.1970 +                loadStubClass = true;
  1.1971 +
  1.1972 +            } else if (vhandler.isAbstractBase(fieldType)) {
  1.1973 +                // IDL Abstract Object reference...
  1.1974 +
  1.1975 +                callType = ValueHandlerImpl.kAbstractType;
  1.1976 +                loadStubClass = true;
  1.1977 +            } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
  1.1978 +                // RMI Abstract Object reference...
  1.1979 +
  1.1980 +                callType = ValueHandlerImpl.kAbstractType;
  1.1981 +            }
  1.1982 +
  1.1983 +            if (loadStubClass) {
  1.1984 +                try {
  1.1985 +                    String codebase = Util.getCodebase(fieldType);
  1.1986 +                    String repID = vhandler.createForAnyType(fieldType);
  1.1987 +                    Class stubType =
  1.1988 +                        Utility.loadStubClass(repID, codebase, fieldType);
  1.1989 +                    actualType = stubType;
  1.1990 +                } catch (ClassNotFoundException e) {
  1.1991 +                    narrow = true;
  1.1992 +                }
  1.1993 +            } else {
  1.1994 +                narrow = true;
  1.1995 +            }
  1.1996 +        }
  1.1997 +
  1.1998 +        switch (callType) {
  1.1999 +            case ValueHandlerImpl.kRemoteType:
  1.2000 +                if (!narrow)
  1.2001 +                    objectValue = (Object)orbStream.read_Object(actualType);
  1.2002 +                else
  1.2003 +                    objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
  1.2004 +                break;
  1.2005 +            case ValueHandlerImpl.kAbstractType:
  1.2006 +                if (!narrow)
  1.2007 +                    objectValue = (Object)orbStream.read_abstract_interface(actualType);
  1.2008 +                else
  1.2009 +                    objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
  1.2010 +                break;
  1.2011 +            case ValueHandlerImpl.kValueType:
  1.2012 +                objectValue = (Object)orbStream.read_value(actualType);
  1.2013 +                break;
  1.2014 +            default:
  1.2015 +                // XXX I18N, logging needed.
  1.2016 +                throw new StreamCorruptedException("Unknown callType: " + callType);
  1.2017 +        }
  1.2018 +
  1.2019 +        return objectValue;
  1.2020 +    }
  1.2021 +
  1.2022 +    private final boolean mustUseRemoteValueMembers() {
  1.2023 +        return defaultReadObjectFVDMembers != null;
  1.2024 +    }
  1.2025 +
  1.2026 +    void readFields(java.util.Map fieldToValueMap)
  1.2027 +        throws InvalidClassException, StreamCorruptedException,
  1.2028 +               ClassNotFoundException, IOException {
  1.2029 +
  1.2030 +        if (mustUseRemoteValueMembers()) {
  1.2031 +            inputRemoteMembersForReadFields(fieldToValueMap);
  1.2032 +        } else
  1.2033 +            inputCurrentClassFieldsForReadFields(fieldToValueMap);
  1.2034 +    }
  1.2035 +
  1.2036 +    private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
  1.2037 +        throws InvalidClassException, StreamCorruptedException,
  1.2038 +               ClassNotFoundException, IOException {
  1.2039 +
  1.2040 +        // Must have this local variable since defaultReadObjectFVDMembers
  1.2041 +        // may get mangled by recursion.
  1.2042 +        ValueMember fields[] = defaultReadObjectFVDMembers;
  1.2043 +
  1.2044 +        try {
  1.2045 +
  1.2046 +            for (int i = 0; i < fields.length; i++) {
  1.2047 +
  1.2048 +                switch (fields[i].type.kind().value()) {
  1.2049 +
  1.2050 +                case TCKind._tk_octet:
  1.2051 +                    byte byteValue = orbStream.read_octet();
  1.2052 +                    fieldToValueMap.put(fields[i].name, new Byte(byteValue));
  1.2053 +                    break;
  1.2054 +                case TCKind._tk_boolean:
  1.2055 +                    boolean booleanValue = orbStream.read_boolean();
  1.2056 +                    fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
  1.2057 +                    break;
  1.2058 +                case TCKind._tk_char:
  1.2059 +                    // Backwards compatibility.  Older Sun ORBs sent
  1.2060 +                    // _tk_char even though they read and wrote wchars
  1.2061 +                    // correctly.
  1.2062 +                    //
  1.2063 +                    // Fall through to the _tk_wchar case.
  1.2064 +                case TCKind._tk_wchar:
  1.2065 +                    char charValue = orbStream.read_wchar();
  1.2066 +                    fieldToValueMap.put(fields[i].name, new Character(charValue));
  1.2067 +                    break;
  1.2068 +                case TCKind._tk_short:
  1.2069 +                    short shortValue = orbStream.read_short();
  1.2070 +                    fieldToValueMap.put(fields[i].name, new Short(shortValue));
  1.2071 +                    break;
  1.2072 +                case TCKind._tk_long:
  1.2073 +                    int intValue = orbStream.read_long();
  1.2074 +                    fieldToValueMap.put(fields[i].name, new Integer(intValue));
  1.2075 +                    break;
  1.2076 +                case TCKind._tk_longlong:
  1.2077 +                    long longValue = orbStream.read_longlong();
  1.2078 +                    fieldToValueMap.put(fields[i].name, new Long(longValue));
  1.2079 +                    break;
  1.2080 +                case TCKind._tk_float:
  1.2081 +                    float floatValue = orbStream.read_float();
  1.2082 +                    fieldToValueMap.put(fields[i].name, new Float(floatValue));
  1.2083 +                    break;
  1.2084 +                case TCKind._tk_double:
  1.2085 +                    double doubleValue = orbStream.read_double();
  1.2086 +                    fieldToValueMap.put(fields[i].name, new Double(doubleValue));
  1.2087 +                    break;
  1.2088 +                case TCKind._tk_value:
  1.2089 +                case TCKind._tk_objref:
  1.2090 +                case TCKind._tk_value_box:
  1.2091 +                    Object objectValue = null;
  1.2092 +                    try {
  1.2093 +                        objectValue = inputObjectField(fields[i],
  1.2094 +                                                       cbSender);
  1.2095 +
  1.2096 +                    } catch (IndirectionException cdrie) {
  1.2097 +                        // The CDR stream had never seen the given offset before,
  1.2098 +                        // so check the recursion manager (it will throw an
  1.2099 +                        // IOException if it doesn't have a reference, either).
  1.2100 +                        objectValue = activeRecursionMgr.getObject(cdrie.offset);
  1.2101 +                    }
  1.2102 +
  1.2103 +                    fieldToValueMap.put(fields[i].name, objectValue);
  1.2104 +                    break;
  1.2105 +                default:
  1.2106 +                    // XXX I18N, logging needed.
  1.2107 +                    throw new StreamCorruptedException("Unknown kind: "
  1.2108 +                                                       + fields[i].type.kind().value());
  1.2109 +                }
  1.2110 +            }
  1.2111 +        } catch (Throwable t) {
  1.2112 +            StreamCorruptedException result = new StreamCorruptedException(t.getMessage());
  1.2113 +            result.initCause(t);
  1.2114 +            throw result;
  1.2115 +        }
  1.2116 +    }
  1.2117 +
  1.2118 +    /**
  1.2119 +     * Called from InputStreamHook.
  1.2120 +     *
  1.2121 +     * Reads the fields of the current class (could be the ones
  1.2122 +     * queried from the remote FVD) and puts them in
  1.2123 +     * the given Map, name to value.  Wraps primitives in the
  1.2124 +     * corresponding java.lang Objects.
  1.2125 +     */
  1.2126 +    private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
  1.2127 +        throws InvalidClassException, StreamCorruptedException,
  1.2128 +               ClassNotFoundException, IOException {
  1.2129 +
  1.2130 +        ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
  1.2131 +
  1.2132 +        int primFields = fields.length - currentClassDesc.objFields;
  1.2133 +
  1.2134 +        // Handle the primitives first
  1.2135 +        for (int i = 0; i < primFields; ++i) {
  1.2136 +
  1.2137 +            switch (fields[i].getTypeCode()) {
  1.2138 +                case 'B':
  1.2139 +                    byte byteValue = orbStream.read_octet();
  1.2140 +                    fieldToValueMap.put(fields[i].getName(),
  1.2141 +                                        new Byte(byteValue));
  1.2142 +                    break;
  1.2143 +                case 'Z':
  1.2144 +                   boolean booleanValue = orbStream.read_boolean();
  1.2145 +                   fieldToValueMap.put(fields[i].getName(),
  1.2146 +                                       new Boolean(booleanValue));
  1.2147 +                   break;
  1.2148 +                case 'C':
  1.2149 +                    char charValue = orbStream.read_wchar();
  1.2150 +                    fieldToValueMap.put(fields[i].getName(),
  1.2151 +                                        new Character(charValue));
  1.2152 +                    break;
  1.2153 +                case 'S':
  1.2154 +                    short shortValue = orbStream.read_short();
  1.2155 +                    fieldToValueMap.put(fields[i].getName(),
  1.2156 +                                        new Short(shortValue));
  1.2157 +                    break;
  1.2158 +                case 'I':
  1.2159 +                    int intValue = orbStream.read_long();
  1.2160 +                    fieldToValueMap.put(fields[i].getName(),
  1.2161 +                                        new Integer(intValue));
  1.2162 +                    break;
  1.2163 +                case 'J':
  1.2164 +                    long longValue = orbStream.read_longlong();
  1.2165 +                    fieldToValueMap.put(fields[i].getName(),
  1.2166 +                                        new Long(longValue));
  1.2167 +                    break;
  1.2168 +                case 'F' :
  1.2169 +                    float floatValue = orbStream.read_float();
  1.2170 +                    fieldToValueMap.put(fields[i].getName(),
  1.2171 +                                        new Float(floatValue));
  1.2172 +                    break;
  1.2173 +                case 'D' :
  1.2174 +                    double doubleValue = orbStream.read_double();
  1.2175 +                    fieldToValueMap.put(fields[i].getName(),
  1.2176 +                                        new Double(doubleValue));
  1.2177 +                    break;
  1.2178 +                default:
  1.2179 +                    // XXX I18N, logging needed.
  1.2180 +                    throw new InvalidClassException(currentClassDesc.getName());
  1.2181 +            }
  1.2182 +        }
  1.2183 +
  1.2184 +        /* Read and set object fields from the input stream. */
  1.2185 +        if (currentClassDesc.objFields > 0) {
  1.2186 +            for (int i = primFields; i < fields.length; i++) {
  1.2187 +                Object objectValue = null;
  1.2188 +                try {
  1.2189 +                    objectValue = inputObjectField(fields[i]);
  1.2190 +                } catch(IndirectionException cdrie) {
  1.2191 +                    // The CDR stream had never seen the given offset before,
  1.2192 +                    // so check the recursion manager (it will throw an
  1.2193 +                    // IOException if it doesn't have a reference, either).
  1.2194 +                    objectValue = activeRecursionMgr.getObject(cdrie.offset);
  1.2195 +                }
  1.2196 +
  1.2197 +                fieldToValueMap.put(fields[i].getName(), objectValue);
  1.2198 +            }
  1.2199 +        }
  1.2200 +    }
  1.2201 +
  1.2202 +    /*
  1.2203 +     * Read the fields of the specified class from the input stream and set
  1.2204 +     * the values of the fields in the specified object. If the specified
  1.2205 +     * object is null, just consume the fields without setting any values. If
  1.2206 +     * any ObjectStreamField does not have a reflected Field, don't try to set
  1.2207 +     * that field in the object.
  1.2208 +     *
  1.2209 +     * REVISIT -- This code doesn't do what the comment says to when
  1.2210 +     * getField() is null!
  1.2211 +     */
  1.2212 +    private void inputClassFields(Object o, Class cl,
  1.2213 +                                  ObjectStreamField[] fields,
  1.2214 +                                  com.sun.org.omg.SendingContext.CodeBase sender)
  1.2215 +        throws InvalidClassException, StreamCorruptedException,
  1.2216 +               ClassNotFoundException, IOException
  1.2217 +    {
  1.2218 +
  1.2219 +        int primFields = fields.length - currentClassDesc.objFields;
  1.2220 +
  1.2221 +        if (o != null) {
  1.2222 +            for (int i = 0; i < primFields; ++i) {
  1.2223 +                if (fields[i].getField() == null)
  1.2224 +                    continue;
  1.2225 +
  1.2226 +                inputPrimitiveField(o, cl, fields[i]);
  1.2227 +            }
  1.2228 +        }
  1.2229 +
  1.2230 +        /* Read and set object fields from the input stream. */
  1.2231 +        if (currentClassDesc.objFields > 0) {
  1.2232 +            for (int i = primFields; i < fields.length; i++) {
  1.2233 +                Object objectValue = null;
  1.2234 +
  1.2235 +                try {
  1.2236 +                    objectValue = inputObjectField(fields[i]);
  1.2237 +                } catch(IndirectionException cdrie) {
  1.2238 +                    // The CDR stream had never seen the given offset before,
  1.2239 +                    // so check the recursion manager (it will throw an
  1.2240 +                    // IOException if it doesn't have a reference, either).
  1.2241 +                    objectValue = activeRecursionMgr.getObject(cdrie.offset);
  1.2242 +                }
  1.2243 +
  1.2244 +                if ((o == null) || (fields[i].getField() == null)) {
  1.2245 +                    continue;
  1.2246 +                }
  1.2247 +
  1.2248 +                try {
  1.2249 +                    Class fieldCl = fields[i].getClazz();
  1.2250 +                    if (objectValue != null && !fieldCl.isInstance(objectValue)) {
  1.2251 +                        throw new IllegalArgumentException();
  1.2252 +                    }
  1.2253 +                    bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
  1.2254 +                    // reflective code: fields[i].getField().set( o, objectValue ) ;
  1.2255 +                } catch (IllegalArgumentException e) {
  1.2256 +                    ClassCastException exc = new ClassCastException("Assigning instance of class " +
  1.2257 +                                                 objectValue.getClass().getName() +
  1.2258 +                                                 " to field " +
  1.2259 +                                                 currentClassDesc.getName() +
  1.2260 +                                                 '#' +
  1.2261 +                                                 fields[i].getField().getName());
  1.2262 +                    exc.initCause( e ) ;
  1.2263 +                    throw exc ;
  1.2264 +                }
  1.2265 +            } // end : for loop
  1.2266 +            }
  1.2267 +        }
  1.2268 +
  1.2269 +    /*
  1.2270 +     * Read the fields of the specified class from the input stream and set
  1.2271 +     * the values of the fields in the specified object. If the specified
  1.2272 +     * object is null, just consume the fields without setting any values. If
  1.2273 +     * any ObjectStreamField does not have a reflected Field, don't try to set
  1.2274 +     * that field in the object.
  1.2275 +     */
  1.2276 +    private void inputClassFields(Object o, Class cl,
  1.2277 +                                  ObjectStreamClass osc,
  1.2278 +                                  ValueMember[] fields,
  1.2279 +                                  com.sun.org.omg.SendingContext.CodeBase sender)
  1.2280 +        throws InvalidClassException, StreamCorruptedException,
  1.2281 +               ClassNotFoundException, IOException
  1.2282 +    {
  1.2283 +        try{
  1.2284 +            for (int i = 0; i < fields.length; ++i) {
  1.2285 +                try {
  1.2286 +                    switch (fields[i].type.kind().value()) {
  1.2287 +                    case TCKind._tk_octet:
  1.2288 +                        byte byteValue = orbStream.read_octet();
  1.2289 +                        if ((o != null) && osc.hasField(fields[i]))
  1.2290 +                        setByteField(o, cl, fields[i].name, byteValue);
  1.2291 +                        break;
  1.2292 +                    case TCKind._tk_boolean:
  1.2293 +                        boolean booleanValue = orbStream.read_boolean();
  1.2294 +                        if ((o != null) && osc.hasField(fields[i]))
  1.2295 +                        setBooleanField(o, cl, fields[i].name, booleanValue);
  1.2296 +                        break;
  1.2297 +                    case TCKind._tk_char:
  1.2298 +                        // Backwards compatibility.  Older Sun ORBs sent
  1.2299 +                        // _tk_char even though they read and wrote wchars
  1.2300 +                        // correctly.
  1.2301 +                        //
  1.2302 +                        // Fall through to the _tk_wchar case.
  1.2303 +                    case TCKind._tk_wchar:
  1.2304 +                        char charValue = orbStream.read_wchar();
  1.2305 +                        if ((o != null) && osc.hasField(fields[i]))
  1.2306 +                        setCharField(o, cl, fields[i].name, charValue);
  1.2307 +                        break;
  1.2308 +                    case TCKind._tk_short:
  1.2309 +                        short shortValue = orbStream.read_short();
  1.2310 +                        if ((o != null) && osc.hasField(fields[i]))
  1.2311 +                        setShortField(o, cl, fields[i].name, shortValue);
  1.2312 +                        break;
  1.2313 +                    case TCKind._tk_long:
  1.2314 +                        int intValue = orbStream.read_long();
  1.2315 +                        if ((o != null) && osc.hasField(fields[i]))
  1.2316 +                        setIntField(o, cl, fields[i].name, intValue);
  1.2317 +                        break;
  1.2318 +                    case TCKind._tk_longlong:
  1.2319 +                        long longValue = orbStream.read_longlong();
  1.2320 +                        if ((o != null) && osc.hasField(fields[i]))
  1.2321 +                        setLongField(o, cl, fields[i].name, longValue);
  1.2322 +                        break;
  1.2323 +                    case TCKind._tk_float:
  1.2324 +                        float floatValue = orbStream.read_float();
  1.2325 +                        if ((o != null) && osc.hasField(fields[i]))
  1.2326 +                        setFloatField(o, cl, fields[i].name, floatValue);
  1.2327 +                        break;
  1.2328 +                    case TCKind._tk_double:
  1.2329 +                        double doubleValue = orbStream.read_double();
  1.2330 +                        if ((o != null) && osc.hasField(fields[i]))
  1.2331 +                        setDoubleField(o, cl, fields[i].name, doubleValue);
  1.2332 +                        break;
  1.2333 +                    case TCKind._tk_value:
  1.2334 +                    case TCKind._tk_objref:
  1.2335 +                    case TCKind._tk_value_box:
  1.2336 +                        Object objectValue = null;
  1.2337 +                        try {
  1.2338 +                            objectValue = inputObjectField(fields[i], sender);
  1.2339 +                        } catch (IndirectionException cdrie) {
  1.2340 +                            // The CDR stream had never seen the given offset before,
  1.2341 +                            // so check the recursion manager (it will throw an
  1.2342 +                            // IOException if it doesn't have a reference, either).
  1.2343 +                            objectValue = activeRecursionMgr.getObject(cdrie.offset);
  1.2344 +                        }
  1.2345 +
  1.2346 +                        if (o == null)
  1.2347 +                            continue;
  1.2348 +                        try {
  1.2349 +                            if (osc.hasField(fields[i])){
  1.2350 +                                setObjectField(o,
  1.2351 +                                               cl,
  1.2352 +                                               fields[i].name,
  1.2353 +                                               objectValue);
  1.2354 +                            } else {
  1.2355 +                                // REVISIT.  Convert to a log message.
  1.2356 +                                // This is a normal case when fields have
  1.2357 +                                // been added as part of evolution, but
  1.2358 +                                // silently skipping can make it hard to
  1.2359 +                                // debug if there's an error
  1.2360 +//                                 System.out.println("**** warning, not setting field: "
  1.2361 +//                                                    + fields[i].name
  1.2362 +//                                                    + " since not on class "
  1.2363 +//                                                    + osc.getName());
  1.2364 +
  1.2365 +                            }
  1.2366 +                        } catch (IllegalArgumentException e) {
  1.2367 +                            // XXX I18N, logging needed.
  1.2368 +                            ClassCastException cce = new ClassCastException("Assigning instance of class " +
  1.2369 +                                objectValue.getClass().getName() + " to field " + fields[i].name);
  1.2370 +                            cce.initCause(e) ;
  1.2371 +                            throw cce ;
  1.2372 +                        }
  1.2373 +                        break;
  1.2374 +                    default:
  1.2375 +                        // XXX I18N, logging needed.
  1.2376 +                        throw new StreamCorruptedException("Unknown kind: "
  1.2377 +                                                           + fields[i].type.kind().value());
  1.2378 +                    }
  1.2379 +                } catch (IllegalArgumentException e) {
  1.2380 +                    /* This case should never happen. If the field types
  1.2381 +                       are not the same, InvalidClassException is raised when
  1.2382 +                       matching the local class to the serialized ObjectStreamClass. */
  1.2383 +                    // XXX I18N, logging needed.
  1.2384 +                    ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id +
  1.2385 +                        " to field " + currentClassDesc.getName() + '#' + fields[i].name);
  1.2386 +                    cce.initCause( e ) ;
  1.2387 +                    throw cce ;
  1.2388 +                }
  1.2389 +            }
  1.2390 +        } catch(Throwable t){
  1.2391 +            // XXX I18N, logging needed.
  1.2392 +            StreamCorruptedException sce = new StreamCorruptedException(t.getMessage());
  1.2393 +            sce.initCause(t) ;
  1.2394 +            throw sce ;
  1.2395 +        }
  1.2396 +    }
  1.2397 +
  1.2398 +    private void skipCustomUsingFVD(ValueMember[] fields,
  1.2399 +                                    com.sun.org.omg.SendingContext.CodeBase sender)
  1.2400 +                                    throws InvalidClassException, StreamCorruptedException,
  1.2401 +                                           ClassNotFoundException, IOException
  1.2402 +    {
  1.2403 +        readFormatVersion();
  1.2404 +        boolean calledDefaultWriteObject = readBoolean();
  1.2405 +
  1.2406 +        if (calledDefaultWriteObject)
  1.2407 +            throwAwayData(fields, sender);
  1.2408 +
  1.2409 +        if (getStreamFormatVersion() == 2) {
  1.2410 +
  1.2411 +            ((ValueInputStream)getOrbStream()).start_value();
  1.2412 +            ((ValueInputStream)getOrbStream()).end_value();
  1.2413 +        }
  1.2414 +    }
  1.2415 +
  1.2416 +    /*
  1.2417 +     * Read the fields of the specified class from the input stream throw data away.
  1.2418 +     * This must handle same switch logic as above.
  1.2419 +     */
  1.2420 +    private void throwAwayData(ValueMember[] fields,
  1.2421 +                               com.sun.org.omg.SendingContext.CodeBase sender)
  1.2422 +        throws InvalidClassException, StreamCorruptedException,
  1.2423 +               ClassNotFoundException, IOException
  1.2424 +    {
  1.2425 +        for (int i = 0; i < fields.length; ++i) {
  1.2426 +
  1.2427 +            try {
  1.2428 +
  1.2429 +                switch (fields[i].type.kind().value()) {
  1.2430 +                case TCKind._tk_octet:
  1.2431 +                    orbStream.read_octet();
  1.2432 +                    break;
  1.2433 +                case TCKind._tk_boolean:
  1.2434 +                    orbStream.read_boolean();
  1.2435 +                    break;
  1.2436 +                case TCKind._tk_char:
  1.2437 +                    // Backwards compatibility.  Older Sun ORBs sent
  1.2438 +                    // _tk_char even though they read and wrote wchars
  1.2439 +                    // correctly.
  1.2440 +                    //
  1.2441 +                    // Fall through to the _tk_wchar case.
  1.2442 +                case TCKind._tk_wchar:
  1.2443 +                    orbStream.read_wchar();
  1.2444 +                    break;
  1.2445 +                case TCKind._tk_short:
  1.2446 +                    orbStream.read_short();
  1.2447 +                    break;
  1.2448 +                case TCKind._tk_long:
  1.2449 +                    orbStream.read_long();
  1.2450 +                    break;
  1.2451 +                case TCKind._tk_longlong:
  1.2452 +                    orbStream.read_longlong();
  1.2453 +                    break;
  1.2454 +                case TCKind._tk_float:
  1.2455 +                    orbStream.read_float();
  1.2456 +                    break;
  1.2457 +                case TCKind._tk_double:
  1.2458 +                    orbStream.read_double();
  1.2459 +                    break;
  1.2460 +                case TCKind._tk_value:
  1.2461 +                case TCKind._tk_objref:
  1.2462 +                case TCKind._tk_value_box:
  1.2463 +                    Class type = null;
  1.2464 +                    String id = fields[i].id;
  1.2465 +
  1.2466 +                    try {
  1.2467 +                        type = vhandler.getClassFromType(id);
  1.2468 +                    }
  1.2469 +                    catch(ClassNotFoundException cnfe){
  1.2470 +                        // Make sure type = null
  1.2471 +                        type = null;
  1.2472 +                    }
  1.2473 +                    String signature = null;
  1.2474 +                    if (type != null)
  1.2475 +                        signature = ValueUtility.getSignature(fields[i]);
  1.2476 +
  1.2477 +                    // Read value
  1.2478 +                    try {
  1.2479 +                        if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
  1.2480 +                                                     signature.equals("Ljava/io/Serializable;") ||
  1.2481 +                                                     signature.equals("Ljava/io/Externalizable;")) ) {
  1.2482 +                            javax.rmi.CORBA.Util.readAny(orbStream);
  1.2483 +                        }
  1.2484 +                        else {
  1.2485 +                            // Decide what method call to make based on the type.
  1.2486 +                            //
  1.2487 +                            // NOTE : Since FullValueDescription does not allow us
  1.2488 +                            // to ask whether something is an interface we do not
  1.2489 +                            // have the ability to optimize this check.
  1.2490 +
  1.2491 +                            int callType = ValueHandlerImpl.kValueType;
  1.2492 +
  1.2493 +                            if (!vhandler.isSequence(id)) {
  1.2494 +                                FullValueDescription fieldFVD = sender.meta(fields[i].id);
  1.2495 +                                if (kRemoteTypeCode == fields[i].type) {
  1.2496 +
  1.2497 +                                    // RMI Object reference...
  1.2498 +                                    callType = ValueHandlerImpl.kRemoteType;
  1.2499 +                                } else if (fieldFVD.is_abstract) {
  1.2500 +                                    // RMI Abstract Object reference...
  1.2501 +
  1.2502 +                                    callType = ValueHandlerImpl.kAbstractType;
  1.2503 +                                }
  1.2504 +                            }
  1.2505 +
  1.2506 +                            // Now that we have used the FVD of the field to determine the proper course
  1.2507 +                            // of action, it is ok to use the type (Class) from this point forward since
  1.2508 +                            // the rep. id for this read will also follow on the wire.
  1.2509 +
  1.2510 +                            switch (callType) {
  1.2511 +                            case ValueHandlerImpl.kRemoteType:
  1.2512 +                                orbStream.read_Object();
  1.2513 +                                break;
  1.2514 +                            case ValueHandlerImpl.kAbstractType:
  1.2515 +                                orbStream.read_abstract_interface();
  1.2516 +                                break;
  1.2517 +                            case ValueHandlerImpl.kValueType:
  1.2518 +                                if (type != null) {
  1.2519 +                                    orbStream.read_value(type);
  1.2520 +                                } else {
  1.2521 +                                    orbStream.read_value();
  1.2522 +                                }
  1.2523 +                                break;
  1.2524 +                            default:
  1.2525 +                                // XXX I18N, logging needed.
  1.2526 +                                throw new StreamCorruptedException("Unknown callType: "
  1.2527 +                                                                   + callType);
  1.2528 +                            }
  1.2529 +                        }
  1.2530 +
  1.2531 +                    }
  1.2532 +                    catch(IndirectionException cdrie) {
  1.2533 +                        // Since we are throwing this away, don't bother handling recursion.
  1.2534 +                        continue;
  1.2535 +                    }
  1.2536 +
  1.2537 +                    break;
  1.2538 +                default:
  1.2539 +                    // XXX I18N, logging needed.
  1.2540 +                    throw new StreamCorruptedException("Unknown kind: "
  1.2541 +                                                       + fields[i].type.kind().value());
  1.2542 +
  1.2543 +                }
  1.2544 +            } catch (IllegalArgumentException e) {
  1.2545 +                /* This case should never happen. If the field types
  1.2546 +                   are not the same, InvalidClassException is raised when
  1.2547 +                   matching the local class to the serialized ObjectStreamClass. */
  1.2548 +                // XXX I18N, logging needed.
  1.2549 +                ClassCastException cce = new ClassCastException("Assigning instance of class " +
  1.2550 +                    fields[i].id + " to field " + currentClassDesc.getName() +
  1.2551 +                    '#' + fields[i].name);
  1.2552 +                cce.initCause(e) ;
  1.2553 +                throw cce ;
  1.2554 +            }
  1.2555 +        }
  1.2556 +
  1.2557 +    }
  1.2558 +
  1.2559 +    private static void setObjectField(Object o, Class c, String fieldName, Object v)
  1.2560 +    {
  1.2561 +        try {
  1.2562 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2563 +            Class fieldCl = fld.getType();
  1.2564 +            if(v != null && !fieldCl.isInstance(v)) {
  1.2565 +                throw new Exception();
  1.2566 +            }
  1.2567 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2568 +            bridge.putObject( o, key, v ) ;
  1.2569 +        } catch (Exception e) {
  1.2570 +            throw utilWrapper.errorSetObjectField( e, fieldName,
  1.2571 +                o.toString(),
  1.2572 +                v.toString() ) ;
  1.2573 +        }
  1.2574 +    }
  1.2575 +
  1.2576 +    private static void setBooleanField(Object o, Class c, String fieldName, boolean v)
  1.2577 +    {
  1.2578 +        try {
  1.2579 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2580 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2581 +            bridge.putBoolean( o, key, v ) ;
  1.2582 +        } catch (Exception e) {
  1.2583 +            throw utilWrapper.errorSetBooleanField( e, fieldName,
  1.2584 +                o.toString(),
  1.2585 +                new Boolean(v) ) ;
  1.2586 +        }
  1.2587 +    }
  1.2588 +
  1.2589 +    private static void setByteField(Object o, Class c, String fieldName, byte v)
  1.2590 +    {
  1.2591 +        try {
  1.2592 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2593 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2594 +            bridge.putByte( o, key, v ) ;
  1.2595 +        } catch (Exception e) {
  1.2596 +            throw utilWrapper.errorSetByteField( e, fieldName,
  1.2597 +                o.toString(),
  1.2598 +                new Byte(v) ) ;
  1.2599 +        }
  1.2600 +    }
  1.2601 +
  1.2602 +    private static void setCharField(Object o, Class c, String fieldName, char v)
  1.2603 +    {
  1.2604 +        try {
  1.2605 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2606 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2607 +            bridge.putChar( o, key, v ) ;
  1.2608 +        } catch (Exception e) {
  1.2609 +            throw utilWrapper.errorSetCharField( e, fieldName,
  1.2610 +                o.toString(),
  1.2611 +                new Character(v) ) ;
  1.2612 +        }
  1.2613 +    }
  1.2614 +
  1.2615 +    private static void setShortField(Object o, Class c, String fieldName, short v)
  1.2616 +    {
  1.2617 +        try {
  1.2618 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2619 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2620 +            bridge.putShort( o, key, v ) ;
  1.2621 +        } catch (Exception e) {
  1.2622 +            throw utilWrapper.errorSetShortField( e, fieldName,
  1.2623 +                o.toString(),
  1.2624 +                new Short(v) ) ;
  1.2625 +        }
  1.2626 +    }
  1.2627 +
  1.2628 +    private static void setIntField(Object o, Class c, String fieldName, int v)
  1.2629 +    {
  1.2630 +        try {
  1.2631 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2632 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2633 +            bridge.putInt( o, key, v ) ;
  1.2634 +        } catch (Exception e) {
  1.2635 +            throw utilWrapper.errorSetIntField( e, fieldName,
  1.2636 +                o.toString(),
  1.2637 +                new Integer(v) ) ;
  1.2638 +        }
  1.2639 +    }
  1.2640 +
  1.2641 +    private static void setLongField(Object o, Class c, String fieldName, long v)
  1.2642 +    {
  1.2643 +        try {
  1.2644 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2645 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2646 +            bridge.putLong( o, key, v ) ;
  1.2647 +        } catch (Exception e) {
  1.2648 +            throw utilWrapper.errorSetLongField( e, fieldName,
  1.2649 +                o.toString(),
  1.2650 +                new Long(v) ) ;
  1.2651 +        }
  1.2652 +    }
  1.2653 +
  1.2654 +    private static void setFloatField(Object o, Class c, String fieldName, float v)
  1.2655 +    {
  1.2656 +        try {
  1.2657 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2658 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2659 +            bridge.putFloat( o, key, v ) ;
  1.2660 +        } catch (Exception e) {
  1.2661 +            throw utilWrapper.errorSetFloatField( e, fieldName,
  1.2662 +                o.toString(),
  1.2663 +                new Float(v) ) ;
  1.2664 +        }
  1.2665 +    }
  1.2666 +
  1.2667 +    private static void setDoubleField(Object o, Class c, String fieldName, double v)
  1.2668 +    {
  1.2669 +        try {
  1.2670 +            Field fld = c.getDeclaredField( fieldName ) ;
  1.2671 +            long key = bridge.objectFieldOffset( fld ) ;
  1.2672 +            bridge.putDouble( o, key, v ) ;
  1.2673 +        } catch (Exception e) {
  1.2674 +            throw utilWrapper.errorSetDoubleField( e, fieldName,
  1.2675 +                o.toString(),
  1.2676 +                new Double(v) ) ;
  1.2677 +        }
  1.2678 +    }
  1.2679 +
  1.2680 +    /**
  1.2681 +     * This class maintains a map of stream position to
  1.2682 +     * an Object currently being deserialized.  It is used
  1.2683 +     * to handle the cases where the are indirections to
  1.2684 +     * an object on the recursion stack.  The CDR level
  1.2685 +     * handles indirections to objects previously seen
  1.2686 +     * (and completely deserialized) in the stream.
  1.2687 +     */
  1.2688 +    static class ActiveRecursionManager
  1.2689 +    {
  1.2690 +        private Map offsetToObjectMap;
  1.2691 +
  1.2692 +        public ActiveRecursionManager() {
  1.2693 +            // A hash map is unsynchronized and allows
  1.2694 +            // null values
  1.2695 +            offsetToObjectMap = new HashMap();
  1.2696 +        }
  1.2697 +
  1.2698 +        // Called right after allocating a new object.
  1.2699 +        // Offset is the starting position in the stream
  1.2700 +        // of the object.
  1.2701 +        public void addObject(int offset, Object value) {
  1.2702 +            offsetToObjectMap.put(new Integer(offset), value);
  1.2703 +        }
  1.2704 +
  1.2705 +        // If the given starting position doesn't refer
  1.2706 +        // to the beginning of an object currently being
  1.2707 +        // deserialized, this throws an IOException.
  1.2708 +        // Otherwise, it returns a reference to the
  1.2709 +        // object.
  1.2710 +        public Object getObject(int offset) throws IOException {
  1.2711 +            Integer position = new Integer(offset);
  1.2712 +
  1.2713 +            if (!offsetToObjectMap.containsKey(position))
  1.2714 +                // XXX I18N, logging needed.
  1.2715 +                throw new IOException("Invalid indirection to offset "
  1.2716 +                                      + offset);
  1.2717 +
  1.2718 +            return offsetToObjectMap.get(position);
  1.2719 +        }
  1.2720 +
  1.2721 +        // Called when an object has been completely
  1.2722 +        // deserialized, so it should no longer be in
  1.2723 +        // this mapping.  The CDR level can handle
  1.2724 +        // further indirections.
  1.2725 +        public void removeObject(int offset) {
  1.2726 +            offsetToObjectMap.remove(new Integer(offset));
  1.2727 +        }
  1.2728 +
  1.2729 +        // If the given offset doesn't map to an Object,
  1.2730 +        // then it isn't an indirection to an object
  1.2731 +        // currently being deserialized.
  1.2732 +        public boolean containsObject(int offset) {
  1.2733 +            return offsetToObjectMap.containsKey(new Integer(offset));
  1.2734 +        }
  1.2735 +    }
  1.2736 +}

mercurial