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

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

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

6962318: Update copyright year
Reviewed-by: xdono

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

mercurial