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