IIOPInputStream.java revision 717:a88d571b42b6
14Srgrimes/* 24Srgrimes * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 34Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 44Srgrimes * 54Srgrimes * This code is free software; you can redistribute it and/or modify it 64Srgrimes * under the terms of the GNU General Public License version 2 only, as 74Srgrimes * published by the Free Software Foundation. Oracle designates this 84Srgrimes * particular file as subject to the "Classpath" exception as provided 94Srgrimes * by Oracle in the LICENSE file that accompanied this code. 104Srgrimes * 114Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT 124Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 134Srgrimes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 144Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 154Srgrimes * accompanied this code). 164Srgrimes * 174Srgrimes * You should have received a copy of the GNU General Public License version 184Srgrimes * 2 along with this work; if not, write to the Free Software Foundation, 194Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 204Srgrimes * 214Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 224Srgrimes * or visit www.oracle.com if you need additional information or have any 234Srgrimes * questions. 244Srgrimes */ 254Srgrimes/* 264Srgrimes * Licensed Materials - Property of IBM 274Srgrimes * RMI-IIOP v1.0 284Srgrimes * Copyright IBM Corp. 1998 1999 All Rights Reserved 29620Srgrimes * 30620Srgrimes */ 314Srgrimes 324Srgrimespackage com.sun.corba.se.impl.io; 33115683Sobrien 34115683Sobrienimport java.io.InputStream; 35115683Sobrienimport java.io.IOException; 362056Swollmanimport java.io.StreamCorruptedException; 372056Swollmanimport java.io.ObjectInputValidation; 382056Swollmanimport java.io.NotActiveException; 394Srgrimesimport java.io.InvalidObjectException; 4028270Swollmanimport java.io.InvalidClassException; 4128270Swollmanimport java.io.DataInputStream; 4228270Swollmanimport java.io.OptionalDataException; 4312607Sbdeimport java.io.WriteAbortedException; 4428270Swollmanimport java.io.Externalizable; 4528270Swollmanimport java.io.EOFException; 464Srgrimesimport java.lang.reflect.*; 474Srgrimesimport java.util.Vector; 484Srgrimesimport java.util.Stack; 494Srgrimesimport java.util.Hashtable; 504Srgrimesimport java.util.Enumeration; 518876Srgrimes 524Srgrimesimport sun.corba.Bridge ; 534Srgrimes 544Srgrimesimport java.security.AccessController ; 554Srgrimesimport java.security.PrivilegedAction ; 564Srgrimes 57143063Sjoergimport com.sun.corba.se.impl.io.ObjectStreamClass; 58143063Sjoergimport com.sun.corba.se.impl.util.Utility; 59143063Sjoerg 60143063Sjoergimport org.omg.CORBA.portable.ValueInputStream; 61143063Sjoerg 62126891Strhodesimport org.omg.CORBA.ValueMember; 63126891Strhodesimport org.omg.CORBA.SystemException; 64126891Strhodesimport org.omg.CORBA.TCKind; 65126891Strhodesimport org.omg.CORBA.ORB; 66126891Strhodesimport org.omg.CORBA.CompletionStatus; 67126891Strhodesimport org.omg.CORBA.portable.IndirectionException; 68126891Strhodesimport org.omg.CORBA.MARSHAL; 69126891Strhodesimport org.omg.CORBA.TypeCode; 70126891Strhodes 71126891Strhodesimport com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription; 72126891Strhodesimport com.sun.org.omg.SendingContext.CodeBase; 73126891Strhodes 74126891Strhodesimport javax.rmi.PortableRemoteObject; 75126891Strhodesimport javax.rmi.CORBA.Util; 764Srgrimesimport javax.rmi.CORBA.ValueHandler; 774Srgrimes 78143063Sjoergimport java.security.*; 79126891Strhodesimport java.util.*; 80126891Strhodes 81126891Strhodesimport com.sun.corba.se.impl.orbutil.ObjectUtility ; 82126891Strhodesimport com.sun.corba.se.impl.logging.OMGSystemException ; 83126891Strhodesimport com.sun.corba.se.impl.logging.UtilSystemException ; 84126891Strhodes 85126891Strhodesimport com.sun.corba.se.spi.logging.CORBALogDomains ; 86126891Strhodes 87126891Strhodes/** 88126891Strhodes * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization 89126891Strhodes * input semantics. 90126891Strhodes * 91126891Strhodes * @author Stephen Lewallen 92126891Strhodes * @since JDK1.1.6 93126891Strhodes */ 94126891Strhodes 95126891Strhodespublic class IIOPInputStream 96126891Strhodes extends com.sun.corba.se.impl.io.InputStreamHook 97126891Strhodes{ 98126891Strhodes private static Bridge bridge = 99126891Strhodes (Bridge)AccessController.doPrivileged( 100126891Strhodes new PrivilegedAction() { 101126891Strhodes public Object run() { 102126891Strhodes return Bridge.get() ; 103126891Strhodes } 104126891Strhodes } 105126891Strhodes ) ; 106126891Strhodes 107126891Strhodes private static OMGSystemException omgWrapper = OMGSystemException.get( 108126891Strhodes CORBALogDomains.RPC_ENCODING ) ; 109126891Strhodes private static UtilSystemException utilWrapper = UtilSystemException.get( 110126891Strhodes CORBALogDomains.RPC_ENCODING ) ; 111126891Strhodes 112126891Strhodes // Necessary to pass the appropriate fields into the 113126891Strhodes // defaultReadObjectDelegate method (which takes no 114126891Strhodes // parameters since it's called from 115126891Strhodes // java.io.ObjectInpuStream defaultReadObject() 116126891Strhodes // which we can't change). 117126891Strhodes // 118126891Strhodes // This is only used in the case where the fields had 119126891Strhodes // to be obtained remotely because of a serializable 120126891Strhodes // version difference. Set in inputObjectUsingFVD. 121126891Strhodes // Part of serialization evolution fixes for Ladybird, 122126891Strhodes // bug 4365188. 123126891Strhodes private ValueMember defaultReadObjectFVDMembers[] = null; 124126891Strhodes 125126891Strhodes private org.omg.CORBA_2_3.portable.InputStream orbStream; 126126891Strhodes 127126891Strhodes private CodeBase cbSender; 128126891Strhodes 129126891Strhodes private ValueHandlerImpl vhandler; //d4365188 130126891Strhodes 131126891Strhodes private Object currentObject = null; 132126891Strhodes 133126891Strhodes private ObjectStreamClass currentClassDesc = null; 134126891Strhodes 135126891Strhodes private Class currentClass = null; 136126891Strhodes 137126891Strhodes private int recursionDepth = 0; 138126891Strhodes 139126891Strhodes private int simpleReadDepth = 0; 140126891Strhodes 141126891Strhodes // The ActiveRecursionManager replaces the old RecursionManager which 142126891Strhodes // used to record how many recursions were made, and resolve them after 143126891Strhodes // an object was completely deserialized. 144126891Strhodes // 145126891Strhodes // That created problems (as in bug 4414154) because when custom 146126891Strhodes // unmarshaling in readObject, there can be recursive references 147126891Strhodes // to one of the objects currently being unmarshaled, and the 148126891Strhodes // passive recursion system failed. 149126891Strhodes ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager(); 150126891Strhodes 151126891Strhodes private IOException abortIOException = null; 152126891Strhodes 153126891Strhodes /* Remember the first exception that stopped this stream. */ 154126891Strhodes private ClassNotFoundException abortClassNotFoundException = null; 155126891Strhodes 156126891Strhodes /* Vector of validation callback objects 157126891Strhodes * The vector is created as needed. The vector is maintained in 158126891Strhodes * order of highest (first) priority to lowest 159126891Strhodes */ 160126891Strhodes private Vector callbacks; 161126891Strhodes 162126891Strhodes // Serialization machinery fields 163126891Strhodes /* Arrays used to keep track of classes and ObjectStreamClasses 164126891Strhodes * as they are being merged; used in inputObject. 165126891Strhodes * spClass is the stack pointer for both. */ 166126891Strhodes ObjectStreamClass[] classdesc; 167126891Strhodes Class[] classes; 168126891Strhodes int spClass; 169126891Strhodes 170126891Strhodes private static final String kEmptyStr = ""; 171126891Strhodes 172126891Strhodes // TCKind TypeCodes used in FVD inputClassFields 173126891Strhodes //public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref); 174126891Strhodes //public static final TypeCode kValueTypeCode = new TypeCodeImpl(TCKind._tk_value); 175126891Strhodes // removed TypeCodeImpl dependency 176126891Strhodes public static final TypeCode kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref); 177126891Strhodes public static final TypeCode kValueTypeCode = ORB.init().get_primitive_tc(TCKind.tk_value); 178126891Strhodes 179126891Strhodes // TESTING CODE - useFVDOnly should be made final before FCS in order to 180126891Strhodes // optimize out the check. 181126891Strhodes private static final boolean useFVDOnly = false; 182126891Strhodes 183126891Strhodes private byte streamFormatVersion; 184126891Strhodes 185126891Strhodes // Since java.io.OptionalDataException's constructors are 186126891Strhodes // package private, but we need to throw it in some special 187126891Strhodes // cases, we try to do it by reflection. 188126891Strhodes private static final Constructor OPT_DATA_EXCEPTION_CTOR; 189126891Strhodes 190126891Strhodes private Object[] readObjectArgList = { this } ; 191126891Strhodes 192126891Strhodes static { 193126891Strhodes OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor(); 194126891Strhodes } 195126891Strhodes 196126891Strhodes // Grab the OptionalDataException boolean ctor and make 197126891Strhodes // it accessible. Note that any exceptions 198126891Strhodes // will be wrapped in ExceptionInInitializerErrors. 199126891Strhodes private static Constructor getOptDataExceptionCtor() { 200126891Strhodes 201126891Strhodes try { 202126891Strhodes 203126891Strhodes Constructor result = 204126891Strhodes 205126891Strhodes (Constructor) AccessController.doPrivileged( 206126891Strhodes new PrivilegedExceptionAction() { 207126891Strhodes public java.lang.Object run() 208126891Strhodes throws NoSuchMethodException, 209126891Strhodes SecurityException { 210126891Strhodes 211126891Strhodes Constructor boolCtor 212126891Strhodes = OptionalDataException.class.getDeclaredConstructor( 213126891Strhodes new Class[] { 214126891Strhodes Boolean.TYPE }); 215126891Strhodes 216126891Strhodes boolCtor.setAccessible(true); 217126891Strhodes 218126891Strhodes return boolCtor; 219126891Strhodes }}); 220126891Strhodes 221126891Strhodes if (result == null) 222126891Strhodes // XXX I18N, logging needed. 223126891Strhodes throw new Error("Unable to find OptionalDataException constructor"); 224126891Strhodes 225126891Strhodes return result; 226126891Strhodes 227126891Strhodes } catch (Exception ex) { 228126891Strhodes // XXX I18N, logging needed. 229126891Strhodes throw new ExceptionInInitializerError(ex); 230126891Strhodes } 231126891Strhodes } 232126891Strhodes 233126891Strhodes // Create a new OptionalDataException with the EOF marker 234126891Strhodes // set to true. See handleOptionalDataMarshalException. 235126891Strhodes private OptionalDataException createOptionalDataException() { 236126891Strhodes try { 237126891Strhodes OptionalDataException result 238126891Strhodes = (OptionalDataException) 239126891Strhodes OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] { 240126891Strhodes Boolean.TRUE }); 241126891Strhodes 242126891Strhodes if (result == null) 243126891Strhodes // XXX I18N, logging needed. 244126891Strhodes throw new Error("Created null OptionalDataException"); 245126891Strhodes 246126891Strhodes return result; 247126891Strhodes 248126891Strhodes } catch (Exception ex) { 249126891Strhodes // XXX I18N, logging needed. 2504Srgrimes throw new Error("Couldn't create OptionalDataException", ex); 25198648Sjdp } 25298648Sjdp } 25398648Sjdp 25498648Sjdp // Return the stream format version currently being used 25598648Sjdp // to deserialize an object 25698648Sjdp protected byte getStreamFormatVersion() { 25798648Sjdp return streamFormatVersion; 25898648Sjdp } 2594Srgrimes 26058698Sjlemon // At the beginning of data sent by a writeObject or 26158698Sjlemon // writeExternal method there is a byte telling the 26258698Sjlemon // reader the stream format version. 26358698Sjlemon private void readFormatVersion() throws IOException { 26458698Sjlemon 26558698Sjlemon streamFormatVersion = orbStream.read_octet(); 266331643Sdim 267331643Sdim if (streamFormatVersion < 1 || 268331643Sdim streamFormatVersion > vhandler.getMaximumStreamFormatVersion()) { 26958698Sjlemon SystemException sysex = omgWrapper.unsupportedFormatVersion( 27058698Sjlemon CompletionStatus.COMPLETED_MAYBE); 27158698Sjlemon // XXX I18N? Logging for IOException? 27258698Sjlemon IOException result = new IOException("Unsupported format version: " 27358698Sjlemon + streamFormatVersion); 27458698Sjlemon result.initCause( sysex ) ; 27558698Sjlemon throw result ; 27658698Sjlemon } 27758698Sjlemon 27858698Sjlemon if (streamFormatVersion == 2) { 27958698Sjlemon if (!(orbStream instanceof ValueInputStream)) { 28058698Sjlemon SystemException sysex = omgWrapper.notAValueinputstream( 28158698Sjlemon CompletionStatus.COMPLETED_MAYBE); 28258698Sjlemon // XXX I18N? Logging for IOException? 28358698Sjlemon IOException result = new IOException("Not a ValueInputStream"); 28458698Sjlemon result.initCause( sysex ) ; 28558698Sjlemon throw result; 28658698Sjlemon } 28758698Sjlemon } 28858698Sjlemon } 28958698Sjlemon 29058698Sjlemon public static void setTestFVDFlag(boolean val){ 29158698Sjlemon // useFVDOnly = val; 29258698Sjlemon } 29358698Sjlemon 29458698Sjlemon /** 29558698Sjlemon * Dummy constructor; passes upper stream a dummy stream; 29658698Sjlemon **/ 29758698Sjlemon public IIOPInputStream() 29858698Sjlemon throws java.io.IOException { 29958698Sjlemon super(); 30058698Sjlemon resetStream(); 30158698Sjlemon } 30258698Sjlemon 30358698Sjlemon final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) { 30458698Sjlemon orbStream = os; 30558698Sjlemon } 30658698Sjlemon 30758698Sjlemon final org.omg.CORBA_2_3.portable.InputStream getOrbStream() { 30858698Sjlemon return orbStream; 30958698Sjlemon } 31058698Sjlemon 31158698Sjlemon //added setSender and getSender 31258698Sjlemon public final void setSender(CodeBase cb) { 31358698Sjlemon cbSender = cb; 31458698Sjlemon } 31558698Sjlemon 31658698Sjlemon public final CodeBase getSender() { 31758698Sjlemon return cbSender; 31858698Sjlemon } 31958698Sjlemon 32058698Sjlemon // 4365188 this is added to enable backward compatability w/ wrong 32158698Sjlemon // rep-ids 32258698Sjlemon public final void setValueHandler(ValueHandler vh) { 32358698Sjlemon vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh; 32458698Sjlemon } 32558698Sjlemon 32658698Sjlemon public final ValueHandler getValueHandler() { 32758698Sjlemon return (javax.rmi.CORBA.ValueHandler) vhandler; 32858698Sjlemon } 32958698Sjlemon 330172835Sbz final void increaseRecursionDepth(){ 331172835Sbz recursionDepth++; 332172835Sbz } 333172835Sbz 334172835Sbz final int decreaseRecursionDepth(){ 335172835Sbz return --recursionDepth; 33658698Sjlemon } 33758698Sjlemon 33858698Sjlemon /** 33958698Sjlemon * Override the actions of the final method "readObject()" 340172835Sbz * in ObjectInputStream. 341172835Sbz * @since JDK1.1.6 342172835Sbz * 343172835Sbz * Read an object from the ObjectInputStream. 344172835Sbz * The class of the object, the signature of the class, and the values 345172835Sbz * of the non-transient and non-static fields of the class and all 346172835Sbz * of its supertypes are read. Default deserializing for a class can be 347172835Sbz * overriden using the writeObject and readObject methods. 34858698Sjlemon * Objects referenced by this object are read transitively so 34958698Sjlemon * that a complete equivalent graph of objects is reconstructed by readObject. <p> 35058698Sjlemon * 35158698Sjlemon * The root object is completly restored when all of its fields 35258698Sjlemon * and the objects it references are completely restored. At this 35358698Sjlemon * point the object validation callbacks are executed in order 35458698Sjlemon * based on their registered priorities. The callbacks are 35558698Sjlemon * registered by objects (in the readObject special methods) 35658698Sjlemon * as they are individually restored. 35758698Sjlemon * 35858698Sjlemon * Exceptions are thrown for problems with the InputStream and for classes 35958698Sjlemon * that should not be deserialized. All exceptions are fatal to the 36058698Sjlemon * InputStream and leave it in an indeterminate state; it is up to the caller 36158698Sjlemon * to ignore or recover the stream state. 36258698Sjlemon * @exception java.lang.ClassNotFoundException Class of a serialized object 36358698Sjlemon * cannot be found. 36458698Sjlemon * @exception InvalidClassException Something is wrong with a class used by 36558698Sjlemon * serialization. 36658698Sjlemon * @exception StreamCorruptedException Control information in the 36758698Sjlemon * stream is inconsistent. 36858698Sjlemon * @exception OptionalDataException Primitive data was found in the 36958698Sjlemon * stream instead of objects. 37058698Sjlemon * @exception IOException Any of the usual Input/Output related exceptions. 37158698Sjlemon * @since JDK1.1 37258698Sjlemon */ 37358698Sjlemon public final synchronized Object readObjectDelegate() throws IOException 37458698Sjlemon { 37558698Sjlemon try { 37658698Sjlemon 377172835Sbz readObjectState.readData(this); 378172835Sbz 379172835Sbz return orbStream.read_abstract_interface(); 380172835Sbz } catch (MARSHAL marshalException) { 381172835Sbz handleOptionalDataMarshalException(marshalException, true); 382172835Sbz throw marshalException; 383172835Sbz } catch(IndirectionException cdrie) 384172835Sbz { 385172835Sbz // The CDR stream had never seen the given offset before, 386172835Sbz // so check the recursion manager (it will throw an 387172835Sbz // IOException if it doesn't have a reference, either). 388172835Sbz return activeRecursionMgr.getObject(cdrie.offset); 389172835Sbz } 390172835Sbz } 391172835Sbz 392172835Sbz final synchronized Object simpleReadObject(Class clz, 393172835Sbz String repositoryID, 394172835Sbz com.sun.org.omg.SendingContext.CodeBase sender, 395172835Sbz int offset) 396172835Sbz /* throws OptionalDataException, ClassNotFoundException, IOException */ 397172835Sbz { 398172835Sbz 399172835Sbz /* Save the current state and get ready to read an object. */ 40058698Sjlemon Object prevObject = currentObject; 40158698Sjlemon ObjectStreamClass prevClassDesc = currentClassDesc; 40258698Sjlemon Class prevClass = currentClass; 40358698Sjlemon byte oldStreamFormatVersion = streamFormatVersion; 404172835Sbz 405172835Sbz simpleReadDepth++; // Entering 406172835Sbz Object obj = null; 407172835Sbz 408172835Sbz /* 409172835Sbz * Check for reset, handle it before reading an object. 410172835Sbz */ 411172835Sbz try { 412172835Sbz // d4365188: backward compatability 413172835Sbz if (vhandler.useFullValueDescription(clz, repositoryID)) { 414172835Sbz obj = inputObjectUsingFVD(clz, repositoryID, sender, offset); 415172835Sbz } else { 416172835Sbz obj = inputObject(clz, repositoryID, sender, offset); 417172835Sbz } 418172835Sbz 419172835Sbz obj = currentClassDesc.readResolve(obj); 420172835Sbz } 421172835Sbz catch(ClassNotFoundException cnfe) 422172835Sbz { 423172835Sbz bridge.throwException( cnfe ) ; 42458698Sjlemon return null; 42558698Sjlemon } 42658698Sjlemon catch(IOException ioe) 42758698Sjlemon { 428172835Sbz // System.out.println("CLZ = " + clz + "; " + ioe.toString()); 429172835Sbz bridge.throwException(ioe) ; 430172835Sbz return null; 431172835Sbz } 432172835Sbz finally { 433172835Sbz simpleReadDepth --; 434172835Sbz currentObject = prevObject; 435172835Sbz currentClassDesc = prevClassDesc; 436172835Sbz currentClass = prevClass; 437172835Sbz streamFormatVersion = oldStreamFormatVersion; 438172835Sbz } 439172835Sbz 44058698Sjlemon 44158698Sjlemon /* Check for thrown exceptions and re-throw them, clearing them if 44258698Sjlemon * this is the last recursive call . 44358698Sjlemon */ 444172835Sbz IOException exIOE = abortIOException; 445172835Sbz if (simpleReadDepth == 0) 446172835Sbz abortIOException = null; 447172835Sbz if (exIOE != null){ 448172835Sbz bridge.throwException( exIOE ) ; 449172835Sbz return null; 450172835Sbz } 451172835Sbz 45258698Sjlemon 45358698Sjlemon ClassNotFoundException exCNF = abortClassNotFoundException; 45458698Sjlemon if (simpleReadDepth == 0) 45558698Sjlemon abortClassNotFoundException = null; 45658698Sjlemon if (exCNF != null) { 45758698Sjlemon bridge.throwException( exCNF ) ; 45858698Sjlemon return null; 45958698Sjlemon } 46058698Sjlemon 46158698Sjlemon return obj; 46258698Sjlemon } 46358698Sjlemon 46458698Sjlemon public final synchronized void simpleSkipObject(String repositoryID, 46558698Sjlemon com.sun.org.omg.SendingContext.CodeBase sender) 46658698Sjlemon /* throws OptionalDataException, ClassNotFoundException, IOException */ 46758698Sjlemon { 46858698Sjlemon 46958698Sjlemon /* Save the current state and get ready to read an object. */ 47058698Sjlemon Object prevObject = currentObject; 47158698Sjlemon ObjectStreamClass prevClassDesc = currentClassDesc; 47258698Sjlemon Class prevClass = currentClass; 47358698Sjlemon byte oldStreamFormatVersion = streamFormatVersion; 47458698Sjlemon 47558698Sjlemon simpleReadDepth++; // Entering 47658698Sjlemon Object obj = null; 47758698Sjlemon 47858698Sjlemon /* 47958698Sjlemon * Check for reset, handle it before reading an object. 48058698Sjlemon */ 48158937Sshin try { 48258698Sjlemon skipObjectUsingFVD(repositoryID, sender); 48358698Sjlemon } 48458698Sjlemon catch(ClassNotFoundException cnfe) 48558698Sjlemon { 48658698Sjlemon bridge.throwException( cnfe ) ; 48758698Sjlemon return; 48858698Sjlemon } 48960162Sps catch(IOException ioe) 49058698Sjlemon { 491126891Strhodes bridge.throwException( ioe ) ; 492 return; 493 } 494 finally { 495 simpleReadDepth --; 496 streamFormatVersion = oldStreamFormatVersion; 497 currentObject = prevObject; 498 currentClassDesc = prevClassDesc; 499 currentClass = prevClass; 500 } 501 502 503 /* Check for thrown exceptions and re-throw them, clearing them if 504 * this is the last recursive call . 505 */ 506 IOException exIOE = abortIOException; 507 if (simpleReadDepth == 0) 508 abortIOException = null; 509 if (exIOE != null){ 510 bridge.throwException( exIOE ) ; 511 return; 512 } 513 514 515 ClassNotFoundException exCNF = abortClassNotFoundException; 516 if (simpleReadDepth == 0) 517 abortClassNotFoundException = null; 518 if (exCNF != null) { 519 bridge.throwException( exCNF ) ; 520 return; 521 } 522 523 return; 524 } 525 ///////////////// 526 527 /** 528 * This method is called by trusted subclasses of ObjectOutputStream 529 * that constructed ObjectOutputStream using the 530 * protected no-arg constructor. The subclass is expected to provide 531 * an override method with the modifier "final". 532 * 533 * @return the Object read from the stream. 534 * 535 * @see #ObjectInputStream() 536 * @see #readObject 537 * @since JDK 1.2 538 */ 539 protected final Object readObjectOverride() 540 throws OptionalDataException, ClassNotFoundException, IOException 541 { 542 return readObjectDelegate(); 543 } 544 545 /** 546 * Override the actions of the final method "defaultReadObject()" 547 * in ObjectInputStream. 548 * @since JDK1.1.6 549 * 550 * Read the non-static and non-transient fields of the current class 551 * from this stream. This may only be called from the readObject method 552 * of the class being deserialized. It will throw the NotActiveException 553 * if it is called otherwise. 554 * 555 * @exception java.lang.ClassNotFoundException if the class of a serialized 556 * object could not be found. 557 * @exception IOException if an I/O error occurs. 558 * @exception NotActiveException if the stream is not currently reading 559 * objects. 560 * @since JDK1.1 561 */ 562 final synchronized void defaultReadObjectDelegate() 563 /* throws IOException, ClassNotFoundException, NotActiveException */ 564 { 565 try { 566 if (currentObject == null || currentClassDesc == null) 567 // XXX I18N, logging needed. 568 throw new NotActiveException("defaultReadObjectDelegate"); 569 570 if (!currentClassDesc.forClass().isAssignableFrom( 571 currentObject.getClass())) { 572 throw new IOException("Object Type mismatch"); 573 } 574 575 // The array will be null unless fields were retrieved 576 // remotely because of a serializable version difference. 577 // Bug fix for 4365188. See the definition of 578 // defaultReadObjectFVDMembers for more information. 579 if (defaultReadObjectFVDMembers != null && 580 defaultReadObjectFVDMembers.length > 0) { 581 582 // WARNING: Be very careful! What if some of 583 // these fields actually have to do this, too? 584 // This works because the defaultReadObjectFVDMembers 585 // reference is passed to inputClassFields, but 586 // there is no guarantee that 587 // defaultReadObjectFVDMembers will point to the 588 // same array after calling inputClassFields. 589 590 // Use the remote fields to unmarshal. 591 inputClassFields(currentObject, 592 currentClass, 593 currentClassDesc, 594 defaultReadObjectFVDMembers, 595 cbSender); 596 597 } else { 598 599 // Use the local fields to unmarshal. 600 ObjectStreamField[] fields = 601 currentClassDesc.getFieldsNoCopy(); 602 if (fields.length > 0) { 603 inputClassFields(currentObject, currentClass, fields, cbSender); 604 } 605 } 606 } 607 catch(NotActiveException nae) 608 { 609 bridge.throwException( nae ) ; 610 } 611 catch(IOException ioe) 612 { 613 bridge.throwException( ioe ) ; 614 } 615 catch(ClassNotFoundException cnfe) 616 { 617 bridge.throwException( cnfe ) ; 618 } 619 620 } 621 622 /** 623 * Override the actions of the final method "enableResolveObject()" 624 * in ObjectInputStream. 625 * @since JDK1.1.6 626 * 627 * Enable the stream to allow objects read from the stream to be replaced. 628 * If the stream is a trusted class it is allowed to enable replacment. 629 * Trusted classes are those classes with a classLoader equals null. <p> 630 * 631 * When enabled the resolveObject method is called for every object 632 * being deserialized. 633 * 634 * @exception SecurityException The classloader of this stream object is non-null. 635 * @since JDK1.1 636 */ 637 public final boolean enableResolveObjectDelegate(boolean enable) 638 /* throws SecurityException */ 639 { 640 return false; 641 } 642 643 // The following three methods allow the implementing orbStream 644 // to provide mark/reset behavior as defined in java.io.InputStream. 645 646 public final void mark(int readAheadLimit) { 647 orbStream.mark(readAheadLimit); 648 } 649 650 public final boolean markSupported() { 651 return orbStream.markSupported(); 652 } 653 654 public final void reset() throws IOException { 655 try { 656 orbStream.reset(); 657 } catch (Error e) { 658 IOException err = new IOException(e.getMessage()); 659 err.initCause(e) ; 660 throw err ; 661 } 662 } 663 664 public final int available() throws IOException{ 665 return 0; // unreliable 666 } 667 668 public final void close() throws IOException{ 669 // no op 670 } 671 672 public final int read() throws IOException{ 673 try{ 674 readObjectState.readData(this); 675 676 return (orbStream.read_octet() << 0) & 0x000000FF; 677 } catch (MARSHAL marshalException) { 678 if (marshalException.minor 679 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { 680 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); 681 return -1; 682 } 683 684 throw marshalException; 685 } catch(Error e) { 686 IOException exc = new IOException(e.getMessage()); 687 exc.initCause(e) ; 688 throw exc ; 689 } 690 } 691 692 public final int read(byte data[], int offset, int length) throws IOException{ 693 try{ 694 readObjectState.readData(this); 695 696 orbStream.read_octet_array(data, offset, length); 697 return length; 698 } catch (MARSHAL marshalException) { 699 if (marshalException.minor 700 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { 701 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); 702 return -1; 703 } 704 705 throw marshalException; 706 } catch(Error e) { 707 IOException exc = new IOException(e.getMessage()); 708 exc.initCause(e) ; 709 throw exc ; 710 } 711 712 } 713 714 public final boolean readBoolean() throws IOException{ 715 try{ 716 readObjectState.readData(this); 717 718 return orbStream.read_boolean(); 719 } catch (MARSHAL marshalException) { 720 handleOptionalDataMarshalException(marshalException, false); 721 throw marshalException; 722 723 } catch(Error e) { 724 IOException exc = new IOException(e.getMessage()); 725 exc.initCause(e); 726 throw exc ; 727 } 728 } 729 730 public final byte readByte() throws IOException{ 731 try{ 732 readObjectState.readData(this); 733 734 return orbStream.read_octet(); 735 } catch (MARSHAL marshalException) { 736 handleOptionalDataMarshalException(marshalException, false); 737 throw marshalException; 738 739 } catch(Error e) { 740 IOException exc = new IOException(e.getMessage()); 741 exc.initCause(e); 742 throw exc ; 743 } 744 } 745 746 public final char readChar() throws IOException{ 747 try{ 748 readObjectState.readData(this); 749 750 return orbStream.read_wchar(); 751 } catch (MARSHAL marshalException) { 752 handleOptionalDataMarshalException(marshalException, false); 753 throw marshalException; 754 755 } catch(Error e) { 756 IOException exc = new IOException(e.getMessage()); 757 exc.initCause(e); 758 throw exc ; 759 } 760 } 761 762 public final double readDouble() throws IOException{ 763 try{ 764 readObjectState.readData(this); 765 766 return orbStream.read_double(); 767 } catch (MARSHAL marshalException) { 768 handleOptionalDataMarshalException(marshalException, false); 769 throw marshalException; 770 } catch(Error e) { 771 IOException exc = new IOException(e.getMessage()); 772 exc.initCause(e); 773 throw exc ; 774 } 775 } 776 777 public final float readFloat() throws IOException{ 778 try{ 779 readObjectState.readData(this); 780 781 return orbStream.read_float(); 782 } catch (MARSHAL marshalException) { 783 handleOptionalDataMarshalException(marshalException, false); 784 throw marshalException; 785 } catch(Error e) { 786 IOException exc = new IOException(e.getMessage()); 787 exc.initCause(e); 788 throw exc ; 789 } 790 } 791 792 public final void readFully(byte data[]) throws IOException{ 793// d11623 : implement readFully, required for serializing some core classes 794 795 readFully(data, 0, data.length); 796 } 797 798 public final void readFully(byte data[], int offset, int size) throws IOException{ 799// d11623 : implement readFully, required for serializing some core classes 800 try{ 801 readObjectState.readData(this); 802 803 orbStream.read_octet_array(data, offset, size); 804 } catch (MARSHAL marshalException) { 805 handleOptionalDataMarshalException(marshalException, false); 806 807 throw marshalException; 808 } catch(Error e) { 809 IOException exc = new IOException(e.getMessage()); 810 exc.initCause(e); 811 throw exc ; 812 } 813 } 814 815 public final int readInt() throws IOException{ 816 try{ 817 readObjectState.readData(this); 818 819 return orbStream.read_long(); 820 } catch (MARSHAL marshalException) { 821 handleOptionalDataMarshalException(marshalException, false); 822 throw marshalException; 823 } catch(Error e) { 824 IOException exc = new IOException(e.getMessage()); 825 exc.initCause(e); 826 throw exc ; 827 } 828 } 829 830 public final String readLine() throws IOException{ 831 // XXX I18N, logging needed. 832 throw new IOException("Method readLine not supported"); 833 } 834 835 public final long readLong() throws IOException{ 836 try{ 837 readObjectState.readData(this); 838 839 return orbStream.read_longlong(); 840 } catch (MARSHAL marshalException) { 841 handleOptionalDataMarshalException(marshalException, false); 842 throw marshalException; 843 } catch(Error e) { 844 IOException exc = new IOException(e.getMessage()); 845 exc.initCause(e); 846 throw exc ; 847 } 848 } 849 850 public final short readShort() throws IOException{ 851 try{ 852 readObjectState.readData(this); 853 854 return orbStream.read_short(); 855 } catch (MARSHAL marshalException) { 856 handleOptionalDataMarshalException(marshalException, false); 857 throw marshalException; 858 } catch(Error e) { 859 IOException exc = new IOException(e.getMessage()); 860 exc.initCause(e); 861 throw exc ; 862 } 863 } 864 865 protected final void readStreamHeader() throws IOException, StreamCorruptedException{ 866 // no op 867 } 868 869 public final int readUnsignedByte() throws IOException{ 870 try{ 871 readObjectState.readData(this); 872 873 return (orbStream.read_octet() << 0) & 0x000000FF; 874 } catch (MARSHAL marshalException) { 875 handleOptionalDataMarshalException(marshalException, false); 876 throw marshalException; 877 } catch(Error e) { 878 IOException exc = new IOException(e.getMessage()); 879 exc.initCause(e); 880 throw exc ; 881 } 882 } 883 884 public final int readUnsignedShort() throws IOException{ 885 try{ 886 readObjectState.readData(this); 887 888 return (orbStream.read_ushort() << 0) & 0x0000FFFF; 889 } catch (MARSHAL marshalException) { 890 handleOptionalDataMarshalException(marshalException, false); 891 throw marshalException; 892 } catch(Error e) { 893 IOException exc = new IOException(e.getMessage()); 894 exc.initCause(e); 895 throw exc ; 896 } 897 } 898 899 /** 900 * Helper method for correcting the Kestrel bug 4367783 (dealing 901 * with larger than 8-bit chars). The old behavior is preserved 902 * in orbutil.IIOPInputStream_1_3 in order to interoperate with 903 * our legacy ORBs. 904 */ 905 protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream) 906 { 907 return stream.read_wstring(); 908 } 909 910 public final String readUTF() throws IOException{ 911 try{ 912 readObjectState.readData(this); 913 914 return internalReadUTF(orbStream); 915 } catch (MARSHAL marshalException) { 916 handleOptionalDataMarshalException(marshalException, false); 917 throw marshalException; 918 } catch(Error e) { 919 IOException exc = new IOException(e.getMessage()); 920 exc.initCause(e); 921 throw exc ; 922 } 923 } 924 925 // If the ORB stream detects an incompatibility between what's 926 // on the wire and what our Serializable's readObject wants, 927 // it throws a MARSHAL exception with a specific minor code. 928 // This is rethrown to the readObject as an OptionalDataException. 929 // So far in RMI-IIOP, this process isn't specific enough to 930 // tell the readObject how much data is available, so we always 931 // set the OptionalDataException's EOF marker to true. 932 private void handleOptionalDataMarshalException(MARSHAL marshalException, 933 boolean objectRead) 934 throws IOException { 935 936 // Java Object Serialization spec 3.4: "If the readObject method 937 // of the class attempts to read more data than is present in the 938 // optional part of the stream for this class, the stream will 939 // return -1 for bytewise reads, throw an EOFException for 940 // primitive data reads, or throw an OptionalDataException 941 // with the eof field set to true for object reads." 942 if (marshalException.minor 943 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { 944 945 IOException result; 946 947 if (!objectRead) 948 result = new EOFException("No more optional data"); 949 else 950 result = createOptionalDataException(); 951 952 result.initCause(marshalException); 953 954 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); 955 956 throw result; 957 } 958 } 959 960 public final synchronized void registerValidation(ObjectInputValidation obj, 961 int prio) 962 throws NotActiveException, InvalidObjectException{ 963 // XXX I18N, logging needed. 964 throw new Error("Method registerValidation not supported"); 965 } 966 967 protected final Class resolveClass(ObjectStreamClass v) 968 throws IOException, ClassNotFoundException{ 969 // XXX I18N, logging needed. 970 throw new IOException("Method resolveClass not supported"); 971 } 972 973 protected final Object resolveObject(Object obj) throws IOException{ 974 // XXX I18N, logging needed. 975 throw new IOException("Method resolveObject not supported"); 976 } 977 978 public final int skipBytes(int len) throws IOException{ 979 try{ 980 readObjectState.readData(this); 981 982 byte buf[] = new byte[len]; 983 orbStream.read_octet_array(buf, 0, len); 984 return len; 985 } catch (MARSHAL marshalException) { 986 handleOptionalDataMarshalException(marshalException, false); 987 988 throw marshalException; 989 } catch(Error e) { 990 IOException exc = new IOException(e.getMessage()); 991 exc.initCause(e) ; 992 throw exc ; 993 } 994 } 995 996 private synchronized Object inputObject(Class clz, 997 String repositoryID, 998 com.sun.org.omg.SendingContext.CodeBase sender, 999 int offset) 1000 throws IOException, ClassNotFoundException 1001 { 1002 1003 /* 1004 * Get the descriptor and then class of the incoming object. 1005 */ 1006 1007 currentClassDesc = ObjectStreamClass.lookup(clz); 1008 currentClass = currentClassDesc.forClass(); 1009 //currentClassDesc.setClass(currentClass); 1010 if (currentClass == null) 1011 // XXX I18N, logging needed. 1012 throw new ClassNotFoundException(currentClassDesc.getName()); 1013 1014 try { 1015 /* If Externalizable, 1016 * Create an instance and tell it to read its data. 1017 * else, 1018 * Handle it as a serializable class. 1019 */ 1020 if (Enum.class.isAssignableFrom( clz )) { 1021 int ordinal = orbStream.read_long() ; 1022 String value = (String)orbStream.read_value( String.class ) ; 1023 return Enum.valueOf( clz, value ) ; 1024 } else if (currentClassDesc.isExternalizable()) { 1025 try { 1026 currentObject = (currentClass == null) ? 1027 null : currentClassDesc.newInstance(); 1028 if (currentObject != null) { 1029 1030 // Store this object and its beginning position 1031 // since there might be indirections to it while 1032 // it's been unmarshalled. 1033 activeRecursionMgr.addObject(offset, currentObject); 1034 1035 // Read format version 1036 readFormatVersion(); 1037 1038 Externalizable ext = (Externalizable)currentObject; 1039 ext.readExternal(this); 1040 } 1041 } catch (InvocationTargetException e) { 1042 InvalidClassException exc = new InvalidClassException( 1043 currentClass.getName(), 1044 "InvocationTargetException accessing no-arg constructor"); 1045 exc.initCause( e ) ; 1046 throw exc ; 1047 } catch (UnsupportedOperationException e) { 1048 InvalidClassException exc = new InvalidClassException( 1049 currentClass.getName(), 1050 "UnsupportedOperationException accessing no-arg constructor"); 1051 exc.initCause( e ) ; 1052 throw exc ; 1053 } catch (InstantiationException e) { 1054 InvalidClassException exc = new InvalidClassException( 1055 currentClass.getName(), 1056 "InstantiationException accessing no-arg constructor"); 1057 exc.initCause( e ) ; 1058 throw exc ; 1059 } 1060 } // end : if (currentClassDesc.isExternalizable()) 1061 else { 1062 /* Count number of classes and descriptors we might have 1063 * to work on. 1064 */ 1065 1066 ObjectStreamClass currdesc = currentClassDesc; 1067 Class currclass = currentClass; 1068 1069 int spBase = spClass; // current top of stack 1070 1071 if (currentClass.getName().equals("java.lang.String")) { 1072 return this.readUTF(); 1073 } 1074 /* The object's classes should be processed from supertype to subtype 1075 * Push all the clases of the current object onto a stack. 1076 * Note that only the serializable classes are represented 1077 * in the descriptor list. 1078 * 1079 * Handle versioning where one or more supertypes of 1080 * have been inserted or removed. The stack will 1081 * contain pairs of descriptors and the corresponding 1082 * class. If the object has a class that did not occur in 1083 * the original the descriptor will be null. If the 1084 * original object had a descriptor for a class not 1085 * present in the local hierarchy of the object the class will be 1086 * null. 1087 * 1088 */ 1089 1090 /* 1091 * This is your basic diff pattern, made simpler 1092 * because reordering is not allowed. 1093 */ 1094 // sun.4296963 ibm.11861 1095 // d11861 we should stop when we find the highest serializable class 1096 // We need this so that when we allocate the new object below, we 1097 // can call the constructor of the non-serializable superclass. 1098 // Note that in the JRMP variant of this code the 1099 // ObjectStreamClass.lookup() method handles this, but we've put 1100 // this fix here rather than change lookup because the new behaviour 1101 // is needed in other cases. 1102 1103 for (currdesc = currentClassDesc, currclass = currentClass; 1104 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/ 1105 currdesc = currdesc.getSuperclass()) { 1106 1107 /* 1108 * Search the classes to see if the class of this 1109 * descriptor appears further up the hierarchy. Until 1110 * it's found assume its an inserted class. If it's 1111 * not found, its the descriptor's class that has been 1112 * removed. 1113 */ 1114 Class cc = currdesc.forClass(); 1115 Class cl; 1116 for (cl = currclass; cl != null; cl = cl.getSuperclass()) { 1117 if (cc == cl) { 1118 // found a superclass that matches this descriptor 1119 break; 1120 } else { 1121 /* Ignore a class that doesn't match. No 1122 * action is needed since it is already 1123 * initialized. 1124 */ 1125 } 1126 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass()) 1127 /* Test if there is room for this new entry. 1128 * If not, double the size of the arrays and copy the contents. 1129 */ 1130 spClass++; 1131 if (spClass >= classes.length) { 1132 int newlen = classes.length * 2; 1133 Class[] newclasses = new Class[newlen]; 1134 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen]; 1135 1136 System.arraycopy(classes, 0, 1137 newclasses, 0, 1138 classes.length); 1139 System.arraycopy(classdesc, 0, 1140 newclassdesc, 0, 1141 classes.length); 1142 1143 classes = newclasses; 1144 classdesc = newclassdesc; 1145 } 1146 1147 if (cl == null) { 1148 /* Class not found corresponding to this descriptor. 1149 * Pop off all the extra classes pushed. 1150 * Push the descriptor and a null class. 1151 */ 1152 classdesc[spClass] = currdesc; 1153 classes[spClass] = null; 1154 } else { 1155 /* Current class descriptor matches current class. 1156 * Some classes may have been inserted. 1157 * Record the match and advance the class, continue 1158 * with the next descriptor. 1159 */ 1160 classdesc[spClass] = currdesc; 1161 classes[spClass] = cl; 1162 currclass = cl.getSuperclass(); 1163 } 1164 } // end : for (currdesc = currentClassDesc, currclass = currentClass; 1165 1166 /* Allocate a new object. The object is only constructed 1167 * above the highest serializable class and is set to 1168 * default values for all more specialized classes. 1169 */ 1170 try { 1171 currentObject = (currentClass == null) ? 1172 null : currentClassDesc.newInstance() ; 1173 1174 // Store this object and its beginning position 1175 // since there might be indirections to it while 1176 // it's been unmarshalled. 1177 activeRecursionMgr.addObject(offset, currentObject); 1178 } catch (InvocationTargetException e) { 1179 InvalidClassException exc = new InvalidClassException( 1180 currentClass.getName(), 1181 "InvocationTargetException accessing no-arg constructor"); 1182 exc.initCause( e ) ; 1183 throw exc ; 1184 } catch (UnsupportedOperationException e) { 1185 InvalidClassException exc = new InvalidClassException( 1186 currentClass.getName(), 1187 "UnsupportedOperationException accessing no-arg constructor"); 1188 exc.initCause( e ) ; 1189 throw exc ; 1190 } catch (InstantiationException e) { 1191 InvalidClassException exc = new InvalidClassException( 1192 currentClass.getName(), 1193 "InstantiationException accessing no-arg constructor"); 1194 exc.initCause( e ) ; 1195 throw exc ; 1196 } 1197 1198 /* 1199 * For all the pushed descriptors and classes. 1200 * if the class has its own writeObject and readObject methods 1201 * call the readObject method 1202 * else 1203 * invoke the defaultReadObject method 1204 */ 1205 try { 1206 for (spClass = spClass; spClass > spBase; spClass--) { 1207 /* 1208 * Set current descriptor and corresponding class 1209 */ 1210 currentClassDesc = classdesc[spClass]; 1211 currentClass = classes[spClass]; 1212 if (classes[spClass] != null) { 1213 /* Read the data from the stream described by the 1214 * descriptor and store into the matching class. 1215 */ 1216 1217 ReadObjectState oldState = readObjectState; 1218 setState(DEFAULT_STATE); 1219 1220 try { 1221 1222 // Changed since invokeObjectReader no longer does this. 1223 if (currentClassDesc.hasWriteObject()) { 1224 1225 // Read format version 1226 readFormatVersion(); 1227 1228 // Read defaultWriteObject indicator 1229 boolean calledDefaultWriteObject = readBoolean(); 1230 1231 readObjectState.beginUnmarshalCustomValue(this, 1232 calledDefaultWriteObject, 1233 (currentClassDesc.readObjectMethod 1234 != null)); 1235 } else { 1236 if (currentClassDesc.hasReadObject()) 1237 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); 1238 } 1239 1240 if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) || 1241 readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) { 1242 1243 // Error case of no readObject and didn't call 1244 // defaultWriteObject handled in default state 1245 1246 ObjectStreamField[] fields = 1247 currentClassDesc.getFieldsNoCopy(); 1248 if (fields.length > 0) { 1249 inputClassFields(currentObject, currentClass, fields, sender); 1250 } 1251 } 1252 1253 if (currentClassDesc.hasWriteObject()) 1254 readObjectState.endUnmarshalCustomValue(this); 1255 1256 } finally { 1257 setState(oldState); 1258 } 1259 1260 } else { 1261 1262 // _REVISIT_ : Can we ever get here? 1263 /* No local class for this descriptor, 1264 * Skip over the data for this class. 1265 * like defaultReadObject with a null currentObject. 1266 * The code will read the values but discard them. 1267 */ 1268 ObjectStreamField[] fields = 1269 currentClassDesc.getFieldsNoCopy(); 1270 if (fields.length > 0) { 1271 inputClassFields(null, currentClass, fields, sender); 1272 } 1273 1274 } 1275 1276 } 1277 } finally { 1278 // Make sure we exit at the same stack level as when we started. 1279 spClass = spBase; 1280 } 1281 } 1282 } finally { 1283 // We've completed deserializing this object. Any 1284 // future indirections will be handled correctly at the 1285 // CDR level. The ActiveRecursionManager only deals with 1286 // objects currently being deserialized. 1287 activeRecursionMgr.removeObject(offset); 1288 } 1289 1290 return currentObject; 1291 } 1292 1293 // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from 1294 // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable 1295 // classes! 1296 private Vector getOrderedDescriptions(String repositoryID, 1297 com.sun.org.omg.SendingContext.CodeBase sender) { 1298 Vector descs = new Vector(); 1299 1300 if (sender == null) { 1301 return descs; 1302 } 1303 1304 FullValueDescription aFVD = sender.meta(repositoryID); 1305 while (aFVD != null) { 1306 descs.insertElementAt(aFVD, 0); 1307 if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) { 1308 aFVD = sender.meta(aFVD.base_value); 1309 } 1310 else return descs; 1311 } 1312 1313 return descs; 1314 } 1315 1316 /** 1317 * This input method uses FullValueDescriptions retrieved from the sender's runtime to 1318 * read in the data. This method is capable of throwing out data not applicable to client's fields. 1319 * This method handles instances where the reader has a class not sent by the sender, the sender sent 1320 * a class not present on the reader, and/or the reader's class does not match the sender's class. 1321 * 1322 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also 1323 * indicates custom marsahling than the local type is used to read the data off the wire. However, 1324 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is 1325 * a form of custom marshaling. 1326 * 1327 */ 1328 private synchronized Object inputObjectUsingFVD(Class clz, 1329 String repositoryID, 1330 com.sun.org.omg.SendingContext.CodeBase sender, 1331 int offset) 1332 throws IOException, ClassNotFoundException 1333 { 1334 int spBase = spClass; // current top of stack 1335 try{ 1336 1337 /* 1338 * Get the descriptor and then class of the incoming object. 1339 */ 1340 1341 ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz); 1342 Class currclass = currentClass = clz; 1343 1344 /* If Externalizable, 1345 * Create an instance and tell it to read its data. 1346 * else, 1347 * Handle it as a serializable class. 1348 */ 1349 if (currentClassDesc.isExternalizable()) { 1350 try { 1351 currentObject = (currentClass == null) ? 1352 null : currentClassDesc.newInstance(); 1353 if (currentObject != null) { 1354 // Store this object and its beginning position 1355 // since there might be indirections to it while 1356 // it's been unmarshalled. 1357 activeRecursionMgr.addObject(offset, currentObject); 1358 1359 // Read format version 1360 readFormatVersion(); 1361 1362 Externalizable ext = (Externalizable)currentObject; 1363 ext.readExternal(this); 1364 } 1365 } catch (InvocationTargetException e) { 1366 InvalidClassException exc = new InvalidClassException( 1367 currentClass.getName(), 1368 "InvocationTargetException accessing no-arg constructor"); 1369 exc.initCause( e ) ; 1370 throw exc ; 1371 } catch (UnsupportedOperationException e) { 1372 InvalidClassException exc = new InvalidClassException( 1373 currentClass.getName(), 1374 "UnsupportedOperationException accessing no-arg constructor"); 1375 exc.initCause( e ) ; 1376 throw exc ; 1377 } catch (InstantiationException e) { 1378 InvalidClassException exc = new InvalidClassException( 1379 currentClass.getName(), 1380 "InstantiationException accessing no-arg constructor"); 1381 exc.initCause( e ) ; 1382 throw exc ; 1383 } 1384 } else { 1385 /* 1386 * This is your basic diff pattern, made simpler 1387 * because reordering is not allowed. 1388 */ 1389 for (currdesc = currentClassDesc, currclass = currentClass; 1390 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/ 1391 1392 currdesc = currdesc.getSuperclass()) { 1393 1394 /* 1395 * Search the classes to see if the class of this 1396 * descriptor appears further up the hierarchy. Until 1397 * it's found assume its an inserted class. If it's 1398 * not found, its the descriptor's class that has been 1399 * removed. 1400 */ 1401 Class cc = currdesc.forClass(); 1402 Class cl; 1403 for (cl = currclass; cl != null; cl = cl.getSuperclass()) { 1404 if (cc == cl) { 1405 // found a superclass that matches this descriptor 1406 break; 1407 } else { 1408 /* Ignore a class that doesn't match. No 1409 * action is needed since it is already 1410 * initialized. 1411 */ 1412 } 1413 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass()) 1414 /* Test if there is room for this new entry. 1415 * If not, double the size of the arrays and copy the contents. 1416 */ 1417 spClass++; 1418 if (spClass >= classes.length) { 1419 int newlen = classes.length * 2; 1420 Class[] newclasses = new Class[newlen]; 1421 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen]; 1422 1423 System.arraycopy(classes, 0, 1424 newclasses, 0, 1425 classes.length); 1426 System.arraycopy(classdesc, 0, 1427 newclassdesc, 0, 1428 classes.length); 1429 1430 classes = newclasses; 1431 classdesc = newclassdesc; 1432 } 1433 1434 if (cl == null) { 1435 /* Class not found corresponding to this descriptor. 1436 * Pop off all the extra classes pushed. 1437 * Push the descriptor and a null class. 1438 */ 1439 classdesc[spClass] = currdesc; 1440 classes[spClass] = null; 1441 } else { 1442 /* Current class descriptor matches current class. 1443 * Some classes may have been inserted. 1444 * Record the match and advance the class, continue 1445 * with the next descriptor. 1446 */ 1447 classdesc[spClass] = currdesc; 1448 classes[spClass] = cl; 1449 currclass = cl.getSuperclass(); 1450 } 1451 } // end : for (currdesc = currentClassDesc, currclass = currentClass; 1452 1453 /* Allocate a new object. 1454 */ 1455 try { 1456 currentObject = (currentClass == null) ? 1457 null : currentClassDesc.newInstance(); 1458 1459 // Store this object and its beginning position 1460 // since there might be indirections to it while 1461 // it's been unmarshalled. 1462 activeRecursionMgr.addObject(offset, currentObject); 1463 } catch (InvocationTargetException e) { 1464 InvalidClassException exc = new InvalidClassException( 1465 currentClass.getName(), 1466 "InvocationTargetException accessing no-arg constructor"); 1467 exc.initCause( e ) ; 1468 throw exc ; 1469 } catch (UnsupportedOperationException e) { 1470 InvalidClassException exc = new InvalidClassException( 1471 currentClass.getName(), 1472 "UnsupportedOperationException accessing no-arg constructor"); 1473 exc.initCause( e ) ; 1474 throw exc ; 1475 } catch (InstantiationException e) { 1476 InvalidClassException exc = new InvalidClassException( 1477 currentClass.getName(), 1478 "InstantiationException accessing no-arg constructor"); 1479 exc.initCause( e ) ; 1480 throw exc ; 1481 } 1482 1483 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements(); 1484 1485 while((fvdsList.hasMoreElements()) && (spClass > spBase)) { 1486 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); 1487 // d4365188: backward compatability 1488 String repIDForFVD = vhandler.getClassName(fvd.id); 1489 String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass)); 1490 1491 while ((spClass > spBase) && 1492 (!repIDForFVD.equals(repIDForClass))) { 1493 int pos = findNextClass(repIDForFVD, classes, spClass, spBase); 1494 if (pos != -1) { 1495 spClass = pos; 1496 currclass = currentClass = classes[spClass]; 1497 repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass)); 1498 } 1499 else { // Read and throw away one level of the fvdslist 1500 1501 // This seems to mean that the sender had a superclass that 1502 // we don't have 1503 1504 if (fvd.is_custom) { 1505 1506 readFormatVersion(); 1507 boolean calledDefaultWriteObject = readBoolean(); 1508 1509 if (calledDefaultWriteObject) 1510 inputClassFields(null, null, null, fvd.members, sender); 1511 1512 if (getStreamFormatVersion() == 2) { 1513 1514 ((ValueInputStream)getOrbStream()).start_value(); 1515 ((ValueInputStream)getOrbStream()).end_value(); 1516 } 1517 1518 // WARNING: If stream format version is 1 and there's 1519 // optional data, we'll get some form of exception down 1520 // the line or data corruption. 1521 1522 } else { 1523 1524 inputClassFields(null, currentClass, null, fvd.members, sender); 1525 } 1526 1527 if (fvdsList.hasMoreElements()){ 1528 fvd = (FullValueDescription)fvdsList.nextElement(); 1529 repIDForFVD = vhandler.getClassName(fvd.id); 1530 } 1531 else return currentObject; 1532 } 1533 } 1534 1535 currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass); 1536 1537 if (!repIDForClass.equals("java.lang.Object")) { 1538 1539 // If the sender used custom marshaling, then it should have put 1540 // the two bytes on the wire indicating stream format version 1541 // and whether or not the writeObject method called 1542 // defaultWriteObject/writeFields. 1543 1544 ReadObjectState oldState = readObjectState; 1545 setState(DEFAULT_STATE); 1546 1547 try { 1548 1549 if (fvd.is_custom) { 1550 1551 // Read format version 1552 readFormatVersion(); 1553 1554 // Read defaultWriteObject indicator 1555 boolean calledDefaultWriteObject = readBoolean(); 1556 1557 readObjectState.beginUnmarshalCustomValue(this, 1558 calledDefaultWriteObject, 1559 (currentClassDesc.readObjectMethod 1560 != null)); 1561 } 1562 1563 boolean usedReadObject = false; 1564 1565 // Always use readObject if it exists, and fall back to default 1566 // unmarshaling if it doesn't. 1567 try { 1568 1569 if (!fvd.is_custom && currentClassDesc.hasReadObject()) 1570 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); 1571 1572 // See the definition of defaultReadObjectFVDMembers 1573 // for more information. This concerns making sure 1574 // we use the remote FVD's members in defaultReadObject. 1575 defaultReadObjectFVDMembers = fvd.members; 1576 usedReadObject = invokeObjectReader(currentClassDesc, 1577 currentObject, 1578 currentClass); 1579 1580 } finally { 1581 defaultReadObjectFVDMembers = null; 1582 } 1583 1584 // Note that the !usedReadObject !calledDefaultWriteObject 1585 // case is handled by the beginUnmarshalCustomValue method 1586 // of the default state 1587 if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) 1588 inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender); 1589 1590 if (fvd.is_custom) 1591 readObjectState.endUnmarshalCustomValue(this); 1592 1593 } finally { 1594 setState(oldState); 1595 } 1596 1597 currclass = currentClass = classes[--spClass]; 1598 1599 } else { 1600 1601 // The remaining hierarchy of the local class does not match the sender's FVD. 1602 // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate 1603 // custom marshaling, throw MARSHAL error. 1604 inputClassFields(null, currentClass, null, fvd.members, sender); 1605 1606 while (fvdsList.hasMoreElements()){ 1607 fvd = (FullValueDescription)fvdsList.nextElement(); 1608 1609 if (fvd.is_custom) 1610 skipCustomUsingFVD(fvd.members, sender); 1611 else 1612 inputClassFields(null, currentClass, null, fvd.members, sender); 1613 } 1614 1615 } 1616 1617 } // end : while(fvdsList.hasMoreElements()) 1618 while (fvdsList.hasMoreElements()){ 1619 1620 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); 1621 if (fvd.is_custom) 1622 skipCustomUsingFVD(fvd.members, sender); 1623 else 1624 throwAwayData(fvd.members, sender); 1625 } 1626 } 1627 1628 return currentObject; 1629 } 1630 finally { 1631 // Make sure we exit at the same stack level as when we started. 1632 spClass = spBase; 1633 1634 // We've completed deserializing this object. Any 1635 // future indirections will be handled correctly at the 1636 // CDR level. The ActiveRecursionManager only deals with 1637 // objects currently being deserialized. 1638 activeRecursionMgr.removeObject(offset); 1639 } 1640 1641 } 1642 1643 /** 1644 * This input method uses FullValueDescriptions retrieved from the sender's runtime to 1645 * read in the data. This method is capable of throwing out data not applicable to client's fields. 1646 * 1647 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also 1648 * indicates custom marsahling than the local type is used to read the data off the wire. However, 1649 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is 1650 * a form of custom marshaling. 1651 * 1652 */ 1653 private Object skipObjectUsingFVD(String repositoryID, 1654 com.sun.org.omg.SendingContext.CodeBase sender) 1655 throws IOException, ClassNotFoundException 1656 { 1657 1658 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements(); 1659 1660 while(fvdsList.hasMoreElements()) { 1661 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); 1662 String repIDForFVD = vhandler.getClassName(fvd.id); 1663 1664 if (!repIDForFVD.equals("java.lang.Object")) { 1665 if (fvd.is_custom) { 1666 1667 readFormatVersion(); 1668 1669 boolean calledDefaultWriteObject = readBoolean(); 1670 1671 if (calledDefaultWriteObject) 1672 inputClassFields(null, null, null, fvd.members, sender); 1673 1674 if (getStreamFormatVersion() == 2) { 1675 1676 ((ValueInputStream)getOrbStream()).start_value(); 1677 ((ValueInputStream)getOrbStream()).end_value(); 1678 } 1679 1680 // WARNING: If stream format version is 1 and there's 1681 // optional data, we'll get some form of exception down 1682 // the line. 1683 1684 } else { 1685 // Use default marshaling 1686 inputClassFields(null, null, null, fvd.members, sender); 1687 } 1688 } 1689 1690 } // end : while(fvdsList.hasMoreElements()) 1691 return null; 1692 1693 } 1694 1695 /////////////////// 1696 1697 private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){ 1698 1699 for (int i = _spClass; i > _spBase; i--){ 1700 if (classname.equals(classes[i].getName())) { 1701 return i; 1702 } 1703 } 1704 1705 return -1; 1706 } 1707 1708 /* 1709 * Invoke the readObject method if present. Assumes that in the case of custom 1710 * marshaling, the format version and defaultWriteObject indicator were already 1711 * removed. 1712 */ 1713 private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass) 1714 throws InvalidClassException, StreamCorruptedException, 1715 ClassNotFoundException, IOException 1716 { 1717 if (osc.readObjectMethod == null) { 1718 return false; 1719 } 1720 1721 try { 1722 osc.readObjectMethod.invoke( obj, readObjectArgList ) ; 1723 return true; 1724 } catch (InvocationTargetException e) { 1725 Throwable t = e.getTargetException(); 1726 if (t instanceof ClassNotFoundException) 1727 throw (ClassNotFoundException)t; 1728 else if (t instanceof IOException) 1729 throw (IOException)t; 1730 else if (t instanceof RuntimeException) 1731 throw (RuntimeException) t; 1732 else if (t instanceof Error) 1733 throw (Error) t; 1734 else 1735 // XXX I18N, logging needed. 1736 throw new Error("internal error"); 1737 } catch (IllegalAccessException e) { 1738 return false; 1739 } 1740 } 1741 1742 /* 1743 * Reset the stream to be just like it was after the constructor. 1744 */ 1745 private void resetStream() throws IOException { 1746 1747 if (classes == null) 1748 classes = new Class[20]; 1749 else { 1750 for (int i = 0; i < classes.length; i++) 1751 classes[i] = null; 1752 } 1753 if (classdesc == null) 1754 classdesc = new ObjectStreamClass[20]; 1755 else { 1756 for (int i = 0; i < classdesc.length; i++) 1757 classdesc[i] = null; 1758 } 1759 spClass = 0; 1760 1761 if (callbacks != null) 1762 callbacks.setSize(0); // discard any pending callbacks 1763 } 1764 1765 /** 1766 * Factored out of inputClassFields This reads a primitive value and sets it 1767 * in the field of o described by the ObjectStreamField field. 1768 * 1769 * Note that reflection cannot be used here, because reflection cannot be used 1770 * to set final fields. 1771 */ 1772 private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field) 1773 throws InvalidClassException, IOException { 1774 1775 try { 1776 switch (field.getTypeCode()) { 1777 case 'B': 1778 byte byteValue = orbStream.read_octet(); 1779 if (field.getField() != null) { 1780 bridge.putByte( o, field.getFieldID(), byteValue ) ; 1781 //reflective code: field.getField().setByte( o, byteValue ) ; 1782 } 1783 break; 1784 case 'Z': 1785 boolean booleanValue = orbStream.read_boolean(); 1786 if (field.getField() != null) { 1787 bridge.putBoolean( o, field.getFieldID(), booleanValue ) ; 1788 //reflective code: field.getField().setBoolean( o, booleanValue ) ; 1789 } 1790 break; 1791 case 'C': 1792 char charValue = orbStream.read_wchar(); 1793 if (field.getField() != null) { 1794 bridge.putChar( o, field.getFieldID(), charValue ) ; 1795 //reflective code: field.getField().setChar( o, charValue ) ; 1796 } 1797 break; 1798 case 'S': 1799 short shortValue = orbStream.read_short(); 1800 if (field.getField() != null) { 1801 bridge.putShort( o, field.getFieldID(), shortValue ) ; 1802 //reflective code: field.getField().setShort( o, shortValue ) ; 1803 } 1804 break; 1805 case 'I': 1806 int intValue = orbStream.read_long(); 1807 if (field.getField() != null) { 1808 bridge.putInt( o, field.getFieldID(), intValue ) ; 1809 //reflective code: field.getField().setInt( o, intValue ) ; 1810 } 1811 break; 1812 case 'J': 1813 long longValue = orbStream.read_longlong(); 1814 if (field.getField() != null) { 1815 bridge.putLong( o, field.getFieldID(), longValue ) ; 1816 //reflective code: field.getField().setLong( o, longValue ) ; 1817 } 1818 break; 1819 case 'F' : 1820 float floatValue = orbStream.read_float(); 1821 if (field.getField() != null) { 1822 bridge.putFloat( o, field.getFieldID(), floatValue ) ; 1823 //reflective code: field.getField().setFloat( o, floatValue ) ; 1824 } 1825 break; 1826 case 'D' : 1827 double doubleValue = orbStream.read_double(); 1828 if (field.getField() != null) { 1829 bridge.putDouble( o, field.getFieldID(), doubleValue ) ; 1830 //reflective code: field.getField().setDouble( o, doubleValue ) ; 1831 } 1832 break; 1833 default: 1834 // XXX I18N, logging needed. 1835 throw new InvalidClassException(cl.getName()); 1836 } 1837 } catch (IllegalArgumentException e) { 1838 /* This case should never happen. If the field types 1839 are not the same, InvalidClassException is raised when 1840 matching the local class to the serialized ObjectStreamClass. */ 1841 ClassCastException cce = new ClassCastException("Assigning instance of class " + 1842 field.getType().getName() + 1843 " to field " + 1844 currentClassDesc.getName() + '#' + 1845 field.getField().getName()); 1846 cce.initCause( e ) ; 1847 throw cce ; 1848 } 1849 } 1850 1851 private Object inputObjectField(org.omg.CORBA.ValueMember field, 1852 com.sun.org.omg.SendingContext.CodeBase sender) 1853 throws IndirectionException, ClassNotFoundException, IOException, 1854 StreamCorruptedException { 1855 1856 Object objectValue = null; 1857 Class type = null; 1858 String id = field.id; 1859 1860 try { 1861 type = vhandler.getClassFromType(id); 1862 } catch(ClassNotFoundException cnfe) { 1863 // Make sure type = null 1864 type = null; 1865 } 1866 1867 String signature = null; 1868 if (type != null) 1869 signature = ValueUtility.getSignature(field); 1870 1871 if (signature != null && (signature.equals("Ljava/lang/Object;") || 1872 signature.equals("Ljava/io/Serializable;") || 1873 signature.equals("Ljava/io/Externalizable;"))) { 1874 objectValue = javax.rmi.CORBA.Util.readAny(orbStream); 1875 } else { 1876 // Decide what method call to make based on the type. If 1877 // it is a type for which we need to load a stub, convert 1878 // the type to the correct stub type. 1879 // 1880 // NOTE : Since FullValueDescription does not allow us 1881 // to ask whether something is an interface we do not 1882 // have the ability to optimize this check. 1883 1884 int callType = ValueHandlerImpl.kValueType; 1885 1886 if (!vhandler.isSequence(id)) { 1887 1888 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) { 1889 1890 // RMI Object reference... 1891 callType = ValueHandlerImpl.kRemoteType; 1892 1893 } else { 1894 1895 // REVISIT. If we don't have the local class, 1896 // we should probably verify that it's an RMI type, 1897 // query the remote FVD, and use is_abstract. 1898 // Our FVD seems to get NullPointerExceptions for any 1899 // non-RMI types. 1900 1901 // This uses the local class in the same way as 1902 // inputObjectField(ObjectStreamField) does. REVISIT 1903 // inputObjectField(ObjectStreamField)'s loadStubClass 1904 // logic. Assumption is that the given type cannot 1905 // evolve to become a CORBA abstract interface or 1906 // a RMI abstract interface. 1907 1908 if (type != null && type.isInterface() && 1909 (vhandler.isAbstractBase(type) || 1910 ObjectStreamClassCorbaExt.isAbstractInterface(type))) { 1911 1912 callType = ValueHandlerImpl.kAbstractType; 1913 } 1914 } 1915 } 1916 1917 // Now that we have used the FVD of the field to determine the proper course 1918 // of action, it is ok to use the type (Class) from this point forward since 1919 // the rep. id for this read will also follow on the wire. 1920 1921 switch (callType) { 1922 case ValueHandlerImpl.kRemoteType: 1923 if (type != null) 1924 objectValue = Utility.readObjectAndNarrow(orbStream, type); 1925 else 1926 objectValue = orbStream.read_Object(); 1927 break; 1928 case ValueHandlerImpl.kAbstractType: 1929 if (type != null) 1930 objectValue = Utility.readAbstractAndNarrow(orbStream, type); 1931 else 1932 objectValue = orbStream.read_abstract_interface(); 1933 break; 1934 case ValueHandlerImpl.kValueType: 1935 if (type != null) 1936 objectValue = orbStream.read_value(type); 1937 else 1938 objectValue = orbStream.read_value(); 1939 break; 1940 default: 1941 // XXX I18N, logging needed. 1942 throw new StreamCorruptedException("Unknown callType: " + callType); 1943 } 1944 } 1945 1946 return objectValue; 1947 } 1948 1949 /** 1950 * Factored out of inputClassFields and reused in 1951 * inputCurrentClassFieldsForReadFields. 1952 * 1953 * Reads the field (which of an Object type as opposed to a primitive) 1954 * described by ObjectStreamField field and returns it. 1955 */ 1956 private Object inputObjectField(ObjectStreamField field) 1957 throws InvalidClassException, StreamCorruptedException, 1958 ClassNotFoundException, IndirectionException, IOException { 1959 1960 if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) { 1961 return javax.rmi.CORBA.Util.readAny(orbStream); 1962 } 1963 1964 Object objectValue = null; 1965 1966 // fields have an API to provide the actual class 1967 // corresponding to the data type 1968 // Class type = osc.forClass(); 1969 Class fieldType = field.getType(); 1970 Class actualType = fieldType; // This may change if stub loaded. 1971 1972 // Decide what method call to make based on the fieldType. If 1973 // it is a type for which we need to load a stub, convert 1974 // the type to the correct stub type. 1975 1976 int callType = ValueHandlerImpl.kValueType; 1977 boolean narrow = false; 1978 1979 if (fieldType.isInterface()) { 1980 boolean loadStubClass = false; 1981 1982 if (java.rmi.Remote.class.isAssignableFrom(fieldType)) { 1983 1984 // RMI Object reference... 1985 callType = ValueHandlerImpl.kRemoteType; 1986 1987 } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){ 1988 1989 // IDL Object reference... 1990 callType = ValueHandlerImpl.kRemoteType; 1991 loadStubClass = true; 1992 1993 } else if (vhandler.isAbstractBase(fieldType)) { 1994 // IDL Abstract Object reference... 1995 1996 callType = ValueHandlerImpl.kAbstractType; 1997 loadStubClass = true; 1998 } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) { 1999 // RMI Abstract Object reference... 2000 2001 callType = ValueHandlerImpl.kAbstractType; 2002 } 2003 2004 if (loadStubClass) { 2005 try { 2006 String codebase = Util.getCodebase(fieldType); 2007 String repID = vhandler.createForAnyType(fieldType); 2008 Class stubType = 2009 Utility.loadStubClass(repID, codebase, fieldType); 2010 actualType = stubType; 2011 } catch (ClassNotFoundException e) { 2012 narrow = true; 2013 } 2014 } else { 2015 narrow = true; 2016 } 2017 } 2018 2019 switch (callType) { 2020 case ValueHandlerImpl.kRemoteType: 2021 if (!narrow) 2022 objectValue = (Object)orbStream.read_Object(actualType); 2023 else 2024 objectValue = Utility.readObjectAndNarrow(orbStream, actualType); 2025 break; 2026 case ValueHandlerImpl.kAbstractType: 2027 if (!narrow) 2028 objectValue = (Object)orbStream.read_abstract_interface(actualType); 2029 else 2030 objectValue = Utility.readAbstractAndNarrow(orbStream, actualType); 2031 break; 2032 case ValueHandlerImpl.kValueType: 2033 objectValue = (Object)orbStream.read_value(actualType); 2034 break; 2035 default: 2036 // XXX I18N, logging needed. 2037 throw new StreamCorruptedException("Unknown callType: " + callType); 2038 } 2039 2040 return objectValue; 2041 } 2042 2043 private final boolean mustUseRemoteValueMembers() { 2044 return defaultReadObjectFVDMembers != null; 2045 } 2046 2047 void readFields(java.util.Map fieldToValueMap) 2048 throws InvalidClassException, StreamCorruptedException, 2049 ClassNotFoundException, IOException { 2050 2051 if (mustUseRemoteValueMembers()) { 2052 inputRemoteMembersForReadFields(fieldToValueMap); 2053 } else 2054 inputCurrentClassFieldsForReadFields(fieldToValueMap); 2055 } 2056 2057 private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap) 2058 throws InvalidClassException, StreamCorruptedException, 2059 ClassNotFoundException, IOException { 2060 2061 // Must have this local variable since defaultReadObjectFVDMembers 2062 // may get mangled by recursion. 2063 ValueMember fields[] = defaultReadObjectFVDMembers; 2064 2065 try { 2066 2067 for (int i = 0; i < fields.length; i++) { 2068 2069 switch (fields[i].type.kind().value()) { 2070 2071 case TCKind._tk_octet: 2072 byte byteValue = orbStream.read_octet(); 2073 fieldToValueMap.put(fields[i].name, new Byte(byteValue)); 2074 break; 2075 case TCKind._tk_boolean: 2076 boolean booleanValue = orbStream.read_boolean(); 2077 fieldToValueMap.put(fields[i].name, new Boolean(booleanValue)); 2078 break; 2079 case TCKind._tk_char: 2080 // Backwards compatibility. Older Sun ORBs sent 2081 // _tk_char even though they read and wrote wchars 2082 // correctly. 2083 // 2084 // Fall through to the _tk_wchar case. 2085 case TCKind._tk_wchar: 2086 char charValue = orbStream.read_wchar(); 2087 fieldToValueMap.put(fields[i].name, new Character(charValue)); 2088 break; 2089 case TCKind._tk_short: 2090 short shortValue = orbStream.read_short(); 2091 fieldToValueMap.put(fields[i].name, new Short(shortValue)); 2092 break; 2093 case TCKind._tk_long: 2094 int intValue = orbStream.read_long(); 2095 fieldToValueMap.put(fields[i].name, new Integer(intValue)); 2096 break; 2097 case TCKind._tk_longlong: 2098 long longValue = orbStream.read_longlong(); 2099 fieldToValueMap.put(fields[i].name, new Long(longValue)); 2100 break; 2101 case TCKind._tk_float: 2102 float floatValue = orbStream.read_float(); 2103 fieldToValueMap.put(fields[i].name, new Float(floatValue)); 2104 break; 2105 case TCKind._tk_double: 2106 double doubleValue = orbStream.read_double(); 2107 fieldToValueMap.put(fields[i].name, new Double(doubleValue)); 2108 break; 2109 case TCKind._tk_value: 2110 case TCKind._tk_objref: 2111 case TCKind._tk_value_box: 2112 Object objectValue = null; 2113 try { 2114 objectValue = inputObjectField(fields[i], 2115 cbSender); 2116 2117 } catch (IndirectionException cdrie) { 2118 // The CDR stream had never seen the given offset before, 2119 // so check the recursion manager (it will throw an 2120 // IOException if it doesn't have a reference, either). 2121 objectValue = activeRecursionMgr.getObject(cdrie.offset); 2122 } 2123 2124 fieldToValueMap.put(fields[i].name, objectValue); 2125 break; 2126 default: 2127 // XXX I18N, logging needed. 2128 throw new StreamCorruptedException("Unknown kind: " 2129 + fields[i].type.kind().value()); 2130 } 2131 } 2132 } catch (Throwable t) { 2133 StreamCorruptedException result = new StreamCorruptedException(t.getMessage()); 2134 result.initCause(t); 2135 throw result; 2136 } 2137 } 2138 2139 /** 2140 * Called from InputStreamHook. 2141 * 2142 * Reads the fields of the current class (could be the ones 2143 * queried from the remote FVD) and puts them in 2144 * the given Map, name to value. Wraps primitives in the 2145 * corresponding java.lang Objects. 2146 */ 2147 private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap) 2148 throws InvalidClassException, StreamCorruptedException, 2149 ClassNotFoundException, IOException { 2150 2151 ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy(); 2152 2153 int primFields = fields.length - currentClassDesc.objFields; 2154 2155 // Handle the primitives first 2156 for (int i = 0; i < primFields; ++i) { 2157 2158 switch (fields[i].getTypeCode()) { 2159 case 'B': 2160 byte byteValue = orbStream.read_octet(); 2161 fieldToValueMap.put(fields[i].getName(), 2162 new Byte(byteValue)); 2163 break; 2164 case 'Z': 2165 boolean booleanValue = orbStream.read_boolean(); 2166 fieldToValueMap.put(fields[i].getName(), 2167 new Boolean(booleanValue)); 2168 break; 2169 case 'C': 2170 char charValue = orbStream.read_wchar(); 2171 fieldToValueMap.put(fields[i].getName(), 2172 new Character(charValue)); 2173 break; 2174 case 'S': 2175 short shortValue = orbStream.read_short(); 2176 fieldToValueMap.put(fields[i].getName(), 2177 new Short(shortValue)); 2178 break; 2179 case 'I': 2180 int intValue = orbStream.read_long(); 2181 fieldToValueMap.put(fields[i].getName(), 2182 new Integer(intValue)); 2183 break; 2184 case 'J': 2185 long longValue = orbStream.read_longlong(); 2186 fieldToValueMap.put(fields[i].getName(), 2187 new Long(longValue)); 2188 break; 2189 case 'F' : 2190 float floatValue = orbStream.read_float(); 2191 fieldToValueMap.put(fields[i].getName(), 2192 new Float(floatValue)); 2193 break; 2194 case 'D' : 2195 double doubleValue = orbStream.read_double(); 2196 fieldToValueMap.put(fields[i].getName(), 2197 new Double(doubleValue)); 2198 break; 2199 default: 2200 // XXX I18N, logging needed. 2201 throw new InvalidClassException(currentClassDesc.getName()); 2202 } 2203 } 2204 2205 /* Read and set object fields from the input stream. */ 2206 if (currentClassDesc.objFields > 0) { 2207 for (int i = primFields; i < fields.length; i++) { 2208 Object objectValue = null; 2209 try { 2210 objectValue = inputObjectField(fields[i]); 2211 } catch(IndirectionException cdrie) { 2212 // The CDR stream had never seen the given offset before, 2213 // so check the recursion manager (it will throw an 2214 // IOException if it doesn't have a reference, either). 2215 objectValue = activeRecursionMgr.getObject(cdrie.offset); 2216 } 2217 2218 fieldToValueMap.put(fields[i].getName(), objectValue); 2219 } 2220 } 2221 } 2222 2223 /* 2224 * Read the fields of the specified class from the input stream and set 2225 * the values of the fields in the specified object. If the specified 2226 * object is null, just consume the fields without setting any values. If 2227 * any ObjectStreamField does not have a reflected Field, don't try to set 2228 * that field in the object. 2229 * 2230 * REVISIT -- This code doesn't do what the comment says to when 2231 * getField() is null! 2232 */ 2233 private void inputClassFields(Object o, Class cl, 2234 ObjectStreamField[] fields, 2235 com.sun.org.omg.SendingContext.CodeBase sender) 2236 throws InvalidClassException, StreamCorruptedException, 2237 ClassNotFoundException, IOException 2238 { 2239 2240 int primFields = fields.length - currentClassDesc.objFields; 2241 2242 if (o != null) { 2243 for (int i = 0; i < primFields; ++i) { 2244 inputPrimitiveField(o, cl, fields[i]); 2245 } 2246 } 2247 2248 /* Read and set object fields from the input stream. */ 2249 if (currentClassDesc.objFields > 0) { 2250 for (int i = primFields; i < fields.length; i++) { 2251 Object objectValue = null; 2252 2253 try { 2254 objectValue = inputObjectField(fields[i]); 2255 } catch(IndirectionException cdrie) { 2256 // The CDR stream had never seen the given offset before, 2257 // so check the recursion manager (it will throw an 2258 // IOException if it doesn't have a reference, either). 2259 objectValue = activeRecursionMgr.getObject(cdrie.offset); 2260 } 2261 2262 if ((o == null) || (fields[i].getField() == null)) { 2263 continue; 2264 } 2265 2266 try { 2267 Class fieldCl = fields[i].getClazz(); 2268 if ((objectValue != null) 2269 && (!fieldCl.isAssignableFrom( 2270 objectValue.getClass()))) { 2271 throw new IllegalArgumentException("Field mismatch"); 2272 } 2273 Field classField = null; 2274 try { 2275 classField = cl.getDeclaredField(fields[i].getName()); 2276 } catch (NoSuchFieldException nsfEx) { 2277 throw new IllegalArgumentException(nsfEx); 2278 } catch (SecurityException secEx) { 2279 throw new IllegalArgumentException(secEx.getCause()); 2280 } 2281 Class<?> declaredFieldClass = classField.getType(); 2282 2283 // check input field type is a declared field type 2284 // input field is a subclass of the declared field 2285 if (!declaredFieldClass.isAssignableFrom(fieldCl)) { 2286 throw new IllegalArgumentException( 2287 "Field Type mismatch"); 2288 } 2289 if (objectValue != null && !fieldCl.isInstance(objectValue)) { 2290 throw new IllegalArgumentException(); 2291 } 2292 bridge.putObject( o, fields[i].getFieldID(), objectValue ) ; 2293 // reflective code: fields[i].getField().set( o, objectValue ) ; 2294 } catch (IllegalArgumentException e) { 2295 ClassCastException exc = new ClassCastException("Assigning instance of class " + 2296 objectValue.getClass().getName() + 2297 " to field " + 2298 currentClassDesc.getName() + 2299 '#' + 2300 fields[i].getField().getName()); 2301 exc.initCause( e ) ; 2302 throw exc ; 2303 } 2304 } // end : for loop 2305 } 2306 } 2307 2308 /* 2309 * Read the fields of the specified class from the input stream and set 2310 * the values of the fields in the specified object. If the specified 2311 * object is null, just consume the fields without setting any values. If 2312 * any ObjectStreamField does not have a reflected Field, don't try to set 2313 * that field in the object. 2314 */ 2315 private void inputClassFields(Object o, Class cl, 2316 ObjectStreamClass osc, 2317 ValueMember[] fields, 2318 com.sun.org.omg.SendingContext.CodeBase sender) 2319 throws InvalidClassException, StreamCorruptedException, 2320 ClassNotFoundException, IOException 2321 { 2322 try{ 2323 for (int i = 0; i < fields.length; ++i) { 2324 try { 2325 switch (fields[i].type.kind().value()) { 2326 case TCKind._tk_octet: 2327 byte byteValue = orbStream.read_octet(); 2328 if ((o != null) && osc.hasField(fields[i])) 2329 setByteField(o, cl, fields[i].name, byteValue); 2330 break; 2331 case TCKind._tk_boolean: 2332 boolean booleanValue = orbStream.read_boolean(); 2333 if ((o != null) && osc.hasField(fields[i])) 2334 setBooleanField(o, cl, fields[i].name, booleanValue); 2335 break; 2336 case TCKind._tk_char: 2337 // Backwards compatibility. Older Sun ORBs sent 2338 // _tk_char even though they read and wrote wchars 2339 // correctly. 2340 // 2341 // Fall through to the _tk_wchar case. 2342 case TCKind._tk_wchar: 2343 char charValue = orbStream.read_wchar(); 2344 if ((o != null) && osc.hasField(fields[i])) 2345 setCharField(o, cl, fields[i].name, charValue); 2346 break; 2347 case TCKind._tk_short: 2348 short shortValue = orbStream.read_short(); 2349 if ((o != null) && osc.hasField(fields[i])) 2350 setShortField(o, cl, fields[i].name, shortValue); 2351 break; 2352 case TCKind._tk_long: 2353 int intValue = orbStream.read_long(); 2354 if ((o != null) && osc.hasField(fields[i])) 2355 setIntField(o, cl, fields[i].name, intValue); 2356 break; 2357 case TCKind._tk_longlong: 2358 long longValue = orbStream.read_longlong(); 2359 if ((o != null) && osc.hasField(fields[i])) 2360 setLongField(o, cl, fields[i].name, longValue); 2361 break; 2362 case TCKind._tk_float: 2363 float floatValue = orbStream.read_float(); 2364 if ((o != null) && osc.hasField(fields[i])) 2365 setFloatField(o, cl, fields[i].name, floatValue); 2366 break; 2367 case TCKind._tk_double: 2368 double doubleValue = orbStream.read_double(); 2369 if ((o != null) && osc.hasField(fields[i])) 2370 setDoubleField(o, cl, fields[i].name, doubleValue); 2371 break; 2372 case TCKind._tk_value: 2373 case TCKind._tk_objref: 2374 case TCKind._tk_value_box: 2375 Object objectValue = null; 2376 try { 2377 objectValue = inputObjectField(fields[i], sender); 2378 } catch (IndirectionException cdrie) { 2379 // The CDR stream had never seen the given offset before, 2380 // so check the recursion manager (it will throw an 2381 // IOException if it doesn't have a reference, either). 2382 objectValue = activeRecursionMgr.getObject(cdrie.offset); 2383 } 2384 2385 if (o == null) 2386 continue; 2387 try { 2388 if (osc.hasField(fields[i])){ 2389 setObjectField(o, 2390 cl, 2391 fields[i].name, 2392 objectValue); 2393 } else { 2394 // REVISIT. Convert to a log message. 2395 // This is a normal case when fields have 2396 // been added as part of evolution, but 2397 // silently skipping can make it hard to 2398 // debug if there's an error 2399// System.out.println("**** warning, not setting field: " 2400// + fields[i].name 2401// + " since not on class " 2402// + osc.getName()); 2403 2404 } 2405 } catch (IllegalArgumentException e) { 2406 // XXX I18N, logging needed. 2407 ClassCastException cce = new ClassCastException("Assigning instance of class " + 2408 objectValue.getClass().getName() + " to field " + fields[i].name); 2409 cce.initCause(e) ; 2410 throw cce ; 2411 } 2412 break; 2413 default: 2414 // XXX I18N, logging needed. 2415 throw new StreamCorruptedException("Unknown kind: " 2416 + fields[i].type.kind().value()); 2417 } 2418 } catch (IllegalArgumentException e) { 2419 /* This case should never happen. If the field types 2420 are not the same, InvalidClassException is raised when 2421 matching the local class to the serialized ObjectStreamClass. */ 2422 // XXX I18N, logging needed. 2423 ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id + 2424 " to field " + currentClassDesc.getName() + '#' + fields[i].name); 2425 cce.initCause( e ) ; 2426 throw cce ; 2427 } 2428 } 2429 } catch(Throwable t){ 2430 // XXX I18N, logging needed. 2431 StreamCorruptedException sce = new StreamCorruptedException(t.getMessage()); 2432 sce.initCause(t) ; 2433 throw sce ; 2434 } 2435 } 2436 2437 private void skipCustomUsingFVD(ValueMember[] fields, 2438 com.sun.org.omg.SendingContext.CodeBase sender) 2439 throws InvalidClassException, StreamCorruptedException, 2440 ClassNotFoundException, IOException 2441 { 2442 readFormatVersion(); 2443 boolean calledDefaultWriteObject = readBoolean(); 2444 2445 if (calledDefaultWriteObject) 2446 throwAwayData(fields, sender); 2447 2448 if (getStreamFormatVersion() == 2) { 2449 2450 ((ValueInputStream)getOrbStream()).start_value(); 2451 ((ValueInputStream)getOrbStream()).end_value(); 2452 } 2453 } 2454 2455 /* 2456 * Read the fields of the specified class from the input stream throw data away. 2457 * This must handle same switch logic as above. 2458 */ 2459 private void throwAwayData(ValueMember[] fields, 2460 com.sun.org.omg.SendingContext.CodeBase sender) 2461 throws InvalidClassException, StreamCorruptedException, 2462 ClassNotFoundException, IOException { 2463 2464 for (int i = 0; i < fields.length; ++i) { 2465 2466 try { 2467 2468 switch (fields[i].type.kind().value()) { 2469 case TCKind._tk_octet: 2470 orbStream.read_octet(); 2471 break; 2472 case TCKind._tk_boolean: 2473 orbStream.read_boolean(); 2474 break; 2475 case TCKind._tk_char: 2476 // Backwards compatibility. Older Sun ORBs sent 2477 // _tk_char even though they read and wrote wchars 2478 // correctly. 2479 // 2480 // Fall through to the _tk_wchar case. 2481 case TCKind._tk_wchar: 2482 orbStream.read_wchar(); 2483 break; 2484 case TCKind._tk_short: 2485 orbStream.read_short(); 2486 break; 2487 case TCKind._tk_long: 2488 orbStream.read_long(); 2489 break; 2490 case TCKind._tk_longlong: 2491 orbStream.read_longlong(); 2492 break; 2493 case TCKind._tk_float: 2494 orbStream.read_float(); 2495 break; 2496 case TCKind._tk_double: 2497 orbStream.read_double(); 2498 break; 2499 case TCKind._tk_value: 2500 case TCKind._tk_objref: 2501 case TCKind._tk_value_box: 2502 Class type = null; 2503 String id = fields[i].id; 2504 2505 try { 2506 type = vhandler.getClassFromType(id); 2507 } 2508 catch(ClassNotFoundException cnfe){ 2509 // Make sure type = null 2510 type = null; 2511 } 2512 String signature = null; 2513 if (type != null) 2514 signature = ValueUtility.getSignature(fields[i]); 2515 2516 // Read value 2517 try { 2518 if ((signature != null) && ( signature.equals("Ljava/lang/Object;") || 2519 signature.equals("Ljava/io/Serializable;") || 2520 signature.equals("Ljava/io/Externalizable;")) ) { 2521 javax.rmi.CORBA.Util.readAny(orbStream); 2522 } 2523 else { 2524 // Decide what method call to make based on the type. 2525 // 2526 // NOTE : Since FullValueDescription does not allow us 2527 // to ask whether something is an interface we do not 2528 // have the ability to optimize this check. 2529 2530 int callType = ValueHandlerImpl.kValueType; 2531 2532 if (!vhandler.isSequence(id)) { 2533 FullValueDescription fieldFVD = sender.meta(fields[i].id); 2534 if (kRemoteTypeCode == fields[i].type) { 2535 2536 // RMI Object reference... 2537 callType = ValueHandlerImpl.kRemoteType; 2538 } else if (fieldFVD.is_abstract) { 2539 // RMI Abstract Object reference... 2540 2541 callType = ValueHandlerImpl.kAbstractType; 2542 } 2543 } 2544 2545 // Now that we have used the FVD of the field to determine the proper course 2546 // of action, it is ok to use the type (Class) from this point forward since 2547 // the rep. id for this read will also follow on the wire. 2548 2549 switch (callType) { 2550 case ValueHandlerImpl.kRemoteType: 2551 orbStream.read_Object(); 2552 break; 2553 case ValueHandlerImpl.kAbstractType: 2554 orbStream.read_abstract_interface(); 2555 break; 2556 case ValueHandlerImpl.kValueType: 2557 if (type != null) { 2558 orbStream.read_value(type); 2559 } else { 2560 orbStream.read_value(); 2561 } 2562 break; 2563 default: 2564 // XXX I18N, logging needed. 2565 throw new StreamCorruptedException("Unknown callType: " 2566 + callType); 2567 } 2568 } 2569 2570 } 2571 catch(IndirectionException cdrie) { 2572 // Since we are throwing this away, don't bother handling recursion. 2573 continue; 2574 } 2575 2576 break; 2577 default: 2578 // XXX I18N, logging needed. 2579 throw new StreamCorruptedException("Unknown kind: " 2580 + fields[i].type.kind().value()); 2581 2582 } 2583 } catch (IllegalArgumentException e) { 2584 /* This case should never happen. If the field types 2585 are not the same, InvalidClassException is raised when 2586 matching the local class to the serialized ObjectStreamClass. */ 2587 // XXX I18N, logging needed. 2588 ClassCastException cce = new ClassCastException("Assigning instance of class " + 2589 fields[i].id + " to field " + currentClassDesc.getName() + 2590 '#' + fields[i].name); 2591 cce.initCause(e) ; 2592 throw cce ; 2593 } 2594 } 2595 2596 } 2597 2598 private static void setObjectField(Object o, Class c, String fieldName, Object v) { 2599 try { 2600 Field fld = c.getDeclaredField( fieldName ) ; 2601 Class fieldCl = fld.getType(); 2602 if(v != null && !fieldCl.isInstance(v)) { 2603 throw new Exception(); 2604 } 2605 long key = bridge.objectFieldOffset( fld ) ; 2606 bridge.putObject( o, key, v ) ; 2607 } catch (Exception e) { 2608 if (o != null) { 2609 throw utilWrapper.errorSetObjectField( e, fieldName, 2610 o.toString(), 2611 v.toString() ) ; 2612 } else { 2613 throw utilWrapper.errorSetObjectField( e, fieldName, 2614 "null " + c.getName() + " object", 2615 v.toString() ) ; 2616 } 2617 } 2618 } 2619 2620 private static void setBooleanField(Object o, Class c, String fieldName, boolean v) 2621 { 2622 try { 2623 Field fld = c.getDeclaredField( fieldName ) ; 2624 if ((fld != null) && (fld.getType() == Boolean.TYPE)) { 2625 long key = bridge.objectFieldOffset( fld ) ; 2626 bridge.putBoolean( o, key, v ) ; 2627 } else { 2628 throw new InvalidObjectException("Field Type mismatch"); 2629 } 2630 } catch (Exception e) { 2631 if (o != null) { 2632 throw utilWrapper.errorSetBooleanField( e, fieldName, 2633 o.toString(), 2634 new Boolean(v) ) ; 2635 } else { 2636 throw utilWrapper.errorSetBooleanField( e, fieldName, 2637 "null " + c.getName() + " object", 2638 new Boolean(v) ) ; 2639 } 2640 } 2641 } 2642 2643 private static void setByteField(Object o, Class c, String fieldName, byte v) 2644 { 2645 try { 2646 Field fld = c.getDeclaredField( fieldName ) ; 2647 if ((fld != null) && (fld.getType() == Byte.TYPE)) { 2648 long key = bridge.objectFieldOffset( fld ) ; 2649 bridge.putByte( o, key, v ) ; 2650 } else { 2651 throw new InvalidObjectException("Field Type mismatch"); 2652 } 2653 } catch (Exception e) { 2654 if (o != null) { 2655 throw utilWrapper.errorSetByteField( e, fieldName, 2656 o.toString(), 2657 new Byte(v) ) ; 2658 } else { 2659 throw utilWrapper.errorSetByteField( e, fieldName, 2660 "null " + c.getName() + " object", 2661 new Byte(v) ) ; 2662 } 2663 } 2664 } 2665 2666 private static void setCharField(Object o, Class c, String fieldName, char v) 2667 { 2668 try { 2669 Field fld = c.getDeclaredField( fieldName ) ; 2670 if ((fld != null) && (fld.getType() == Character.TYPE)) { 2671 long key = bridge.objectFieldOffset( fld ) ; 2672 bridge.putChar( o, key, v ) ; 2673 } else { 2674 throw new InvalidObjectException("Field Type mismatch"); 2675 } 2676 } catch (Exception e) { 2677 if (o != null) { 2678 throw utilWrapper.errorSetCharField( e, fieldName, 2679 o.toString(), 2680 new Character(v) ) ; 2681 } else { 2682 throw utilWrapper.errorSetCharField( e, fieldName, 2683 "null " + c.getName() + " object", 2684 new Character(v) ) ; 2685 } 2686 } 2687 } 2688 2689 private static void setShortField(Object o, Class c, String fieldName, short v) 2690 { 2691 try { 2692 Field fld = c.getDeclaredField( fieldName ) ; 2693 if ((fld != null) && (fld.getType() == Short.TYPE)) { 2694 long key = bridge.objectFieldOffset( fld ) ; 2695 bridge.putShort( o, key, v ) ; 2696 } else { 2697 throw new InvalidObjectException("Field Type mismatch"); 2698 } 2699 } catch (Exception e) { 2700 if (o != null) { 2701 throw utilWrapper.errorSetShortField( e, fieldName, 2702 o.toString(), 2703 new Short(v) ) ; 2704 } else { 2705 throw utilWrapper.errorSetShortField( e, fieldName, 2706 "null " + c.getName() + " object", 2707 new Short(v) ) ; 2708 } 2709 } 2710 } 2711 2712 private static void setIntField(Object o, Class c, String fieldName, int v) 2713 { 2714 try { 2715 Field fld = c.getDeclaredField( fieldName ) ; 2716 if ((fld != null) && (fld.getType() == Integer.TYPE)) { 2717 long key = bridge.objectFieldOffset( fld ) ; 2718 bridge.putInt( o, key, v ) ; 2719 } else { 2720 throw new InvalidObjectException("Field Type mismatch"); 2721 } 2722 } catch (Exception e) { 2723 if (o != null) { 2724 throw utilWrapper.errorSetIntField( e, fieldName, 2725 o.toString(), 2726 new Integer(v) ) ; 2727 } else { 2728 throw utilWrapper.errorSetIntField( e, fieldName, 2729 "null " + c.getName() + " object", 2730 new Integer(v) ) ; 2731 } 2732 } 2733 } 2734 2735 private static void setLongField(Object o, Class c, String fieldName, long v) 2736 { 2737 try { 2738 Field fld = c.getDeclaredField( fieldName ) ; 2739 if ((fld != null) && (fld.getType() == Long.TYPE)) { 2740 long key = bridge.objectFieldOffset( fld ) ; 2741 bridge.putLong( o, key, v ) ; 2742 } else { 2743 throw new InvalidObjectException("Field Type mismatch"); 2744 } 2745 } catch (Exception e) { 2746 if (o != null) { 2747 throw utilWrapper.errorSetLongField( e, fieldName, 2748 o.toString(), 2749 new Long(v) ) ; 2750 } else { 2751 throw utilWrapper.errorSetLongField( e, fieldName, 2752 "null " + c.getName() + " object", 2753 new Long(v) ) ; 2754 } 2755 } 2756 } 2757 2758 private static void setFloatField(Object o, Class c, String fieldName, float v) 2759 { 2760 try { 2761 Field fld = c.getDeclaredField( fieldName ) ; 2762 if ((fld != null) && (fld.getType() == Float.TYPE)) { 2763 long key = bridge.objectFieldOffset( fld ) ; 2764 bridge.putFloat( o, key, v ) ; 2765 } else { 2766 throw new InvalidObjectException("Field Type mismatch"); 2767 } 2768 } catch (Exception e) { 2769 if (o != null) { 2770 throw utilWrapper.errorSetFloatField( e, fieldName, 2771 o.toString(), 2772 new Float(v) ) ; 2773 } else { 2774 throw utilWrapper.errorSetFloatField( e, fieldName, 2775 "null " + c.getName() + " object", 2776 new Float(v) ) ; 2777 } 2778 } 2779 } 2780 2781 private static void setDoubleField(Object o, Class c, String fieldName, double v) 2782 { 2783 try { 2784 Field fld = c.getDeclaredField( fieldName ) ; 2785 if ((fld != null) && (fld.getType() == Double.TYPE)) { 2786 long key = bridge.objectFieldOffset( fld ) ; 2787 bridge.putDouble( o, key, v ) ; 2788 } else { 2789 throw new InvalidObjectException("Field Type mismatch"); 2790 } 2791 } catch (Exception e) { 2792 if (o != null) { 2793 throw utilWrapper.errorSetDoubleField( e, fieldName, 2794 o.toString(), 2795 new Double(v) ) ; 2796 } else { 2797 throw utilWrapper.errorSetDoubleField( e, fieldName, 2798 "null " + c.getName() + " object", 2799 new Double(v) ) ; 2800 } 2801 } 2802 } 2803 2804 /** 2805 * This class maintains a map of stream position to 2806 * an Object currently being deserialized. It is used 2807 * to handle the cases where the are indirections to 2808 * an object on the recursion stack. The CDR level 2809 * handles indirections to objects previously seen 2810 * (and completely deserialized) in the stream. 2811 */ 2812 static class ActiveRecursionManager 2813 { 2814 private Map offsetToObjectMap; 2815 2816 public ActiveRecursionManager() { 2817 // A hash map is unsynchronized and allows 2818 // null values 2819 offsetToObjectMap = new HashMap(); 2820 } 2821 2822 // Called right after allocating a new object. 2823 // Offset is the starting position in the stream 2824 // of the object. 2825 public void addObject(int offset, Object value) { 2826 offsetToObjectMap.put(new Integer(offset), value); 2827 } 2828 2829 // If the given starting position doesn't refer 2830 // to the beginning of an object currently being 2831 // deserialized, this throws an IOException. 2832 // Otherwise, it returns a reference to the 2833 // object. 2834 public Object getObject(int offset) throws IOException { 2835 Integer position = new Integer(offset); 2836 2837 if (!offsetToObjectMap.containsKey(position)) 2838 // XXX I18N, logging needed. 2839 throw new IOException("Invalid indirection to offset " 2840 + offset); 2841 2842 return offsetToObjectMap.get(position); 2843 } 2844 2845 // Called when an object has been completely 2846 // deserialized, so it should no longer be in 2847 // this mapping. The CDR level can handle 2848 // further indirections. 2849 public void removeObject(int offset) { 2850 offsetToObjectMap.remove(new Integer(offset)); 2851 } 2852 2853 // If the given offset doesn't map to an Object, 2854 // then it isn't an indirection to an object 2855 // currently being deserialized. 2856 public boolean containsObject(int offset) { 2857 return offsetToObjectMap.containsKey(new Integer(offset)); 2858 } 2859 } 2860} 2861