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

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

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

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

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

mercurial