aoqi@0: /* msheppar@940: * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: /* aoqi@0: * Licensed Materials - Property of IBM aoqi@0: * RMI-IIOP v1.0 aoqi@0: * Copyright IBM Corp. 1998 1999 All Rights Reserved aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: package com.sun.corba.se.impl.io; aoqi@0: aoqi@0: import java.io.InputStream; aoqi@0: import java.io.IOException; aoqi@0: import java.io.StreamCorruptedException; aoqi@0: import java.io.ObjectInputValidation; aoqi@0: import java.io.NotActiveException; aoqi@0: import java.io.InvalidObjectException; aoqi@0: import java.io.InvalidClassException; aoqi@0: import java.io.DataInputStream; aoqi@0: import java.io.OptionalDataException; aoqi@0: import java.io.WriteAbortedException; aoqi@0: import java.io.Externalizable; aoqi@0: import java.io.EOFException; aoqi@0: import java.lang.reflect.*; aoqi@0: import java.util.Vector; aoqi@0: import java.util.Stack; aoqi@0: import java.util.Hashtable; aoqi@0: import java.util.Enumeration; aoqi@0: aoqi@0: import sun.corba.Bridge ; aoqi@0: aoqi@0: import java.security.AccessController ; aoqi@0: import java.security.PrivilegedAction ; aoqi@0: aoqi@0: import com.sun.corba.se.impl.io.ObjectStreamClass; aoqi@0: import com.sun.corba.se.impl.util.Utility; aoqi@0: aoqi@0: import org.omg.CORBA.portable.ValueInputStream; aoqi@0: aoqi@0: import org.omg.CORBA.ValueMember; aoqi@0: import org.omg.CORBA.SystemException; aoqi@0: import org.omg.CORBA.TCKind; aoqi@0: import org.omg.CORBA.ORB; aoqi@0: import org.omg.CORBA.CompletionStatus; aoqi@0: import org.omg.CORBA.portable.IndirectionException; aoqi@0: import org.omg.CORBA.MARSHAL; aoqi@0: import org.omg.CORBA.TypeCode; aoqi@0: aoqi@0: import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription; aoqi@0: import com.sun.org.omg.SendingContext.CodeBase; aoqi@0: aoqi@0: import javax.rmi.PortableRemoteObject; aoqi@0: import javax.rmi.CORBA.Util; aoqi@0: import javax.rmi.CORBA.ValueHandler; aoqi@0: aoqi@0: import java.security.*; aoqi@0: import java.util.*; aoqi@0: aoqi@0: import com.sun.corba.se.impl.orbutil.ObjectUtility ; aoqi@0: import com.sun.corba.se.impl.logging.OMGSystemException ; aoqi@0: import com.sun.corba.se.impl.logging.UtilSystemException ; aoqi@0: aoqi@0: import com.sun.corba.se.spi.logging.CORBALogDomains ; aoqi@0: aoqi@0: /** aoqi@0: * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization aoqi@0: * input semantics. aoqi@0: * aoqi@0: * @author Stephen Lewallen aoqi@0: * @since JDK1.1.6 aoqi@0: */ aoqi@0: aoqi@0: public class IIOPInputStream aoqi@0: extends com.sun.corba.se.impl.io.InputStreamHook aoqi@0: { aoqi@0: private static Bridge bridge = aoqi@0: (Bridge)AccessController.doPrivileged( aoqi@0: new PrivilegedAction() { aoqi@0: public Object run() { aoqi@0: return Bridge.get() ; aoqi@0: } aoqi@0: } aoqi@0: ) ; aoqi@0: aoqi@0: private static OMGSystemException omgWrapper = OMGSystemException.get( aoqi@0: CORBALogDomains.RPC_ENCODING ) ; aoqi@0: private static UtilSystemException utilWrapper = UtilSystemException.get( aoqi@0: CORBALogDomains.RPC_ENCODING ) ; aoqi@0: aoqi@0: // Necessary to pass the appropriate fields into the aoqi@0: // defaultReadObjectDelegate method (which takes no aoqi@0: // parameters since it's called from aoqi@0: // java.io.ObjectInpuStream defaultReadObject() aoqi@0: // which we can't change). aoqi@0: // aoqi@0: // This is only used in the case where the fields had aoqi@0: // to be obtained remotely because of a serializable aoqi@0: // version difference. Set in inputObjectUsingFVD. aoqi@0: // Part of serialization evolution fixes for Ladybird, aoqi@0: // bug 4365188. aoqi@0: private ValueMember defaultReadObjectFVDMembers[] = null; aoqi@0: aoqi@0: private org.omg.CORBA_2_3.portable.InputStream orbStream; aoqi@0: aoqi@0: private CodeBase cbSender; aoqi@0: aoqi@0: private ValueHandlerImpl vhandler; //d4365188 aoqi@0: aoqi@0: private Object currentObject = null; aoqi@0: aoqi@0: private ObjectStreamClass currentClassDesc = null; aoqi@0: aoqi@0: private Class currentClass = null; aoqi@0: aoqi@0: private int recursionDepth = 0; aoqi@0: aoqi@0: private int simpleReadDepth = 0; aoqi@0: aoqi@0: // The ActiveRecursionManager replaces the old RecursionManager which aoqi@0: // used to record how many recursions were made, and resolve them after aoqi@0: // an object was completely deserialized. aoqi@0: // aoqi@0: // That created problems (as in bug 4414154) because when custom aoqi@0: // unmarshaling in readObject, there can be recursive references aoqi@0: // to one of the objects currently being unmarshaled, and the aoqi@0: // passive recursion system failed. aoqi@0: ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager(); aoqi@0: aoqi@0: private IOException abortIOException = null; aoqi@0: aoqi@0: /* Remember the first exception that stopped this stream. */ aoqi@0: private ClassNotFoundException abortClassNotFoundException = null; aoqi@0: aoqi@0: /* Vector of validation callback objects aoqi@0: * The vector is created as needed. The vector is maintained in aoqi@0: * order of highest (first) priority to lowest aoqi@0: */ aoqi@0: private Vector callbacks; aoqi@0: aoqi@0: // Serialization machinery fields aoqi@0: /* Arrays used to keep track of classes and ObjectStreamClasses aoqi@0: * as they are being merged; used in inputObject. aoqi@0: * spClass is the stack pointer for both. */ aoqi@0: ObjectStreamClass[] classdesc; aoqi@0: Class[] classes; aoqi@0: int spClass; aoqi@0: aoqi@0: private static final String kEmptyStr = ""; aoqi@0: aoqi@0: // TCKind TypeCodes used in FVD inputClassFields aoqi@0: //public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref); aoqi@0: //public static final TypeCode kValueTypeCode = new TypeCodeImpl(TCKind._tk_value); aoqi@0: // removed TypeCodeImpl dependency aoqi@0: public static final TypeCode kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref); aoqi@0: public static final TypeCode kValueTypeCode = ORB.init().get_primitive_tc(TCKind.tk_value); aoqi@0: aoqi@0: // TESTING CODE - useFVDOnly should be made final before FCS in order to aoqi@0: // optimize out the check. aoqi@0: private static final boolean useFVDOnly = false; aoqi@0: aoqi@0: private byte streamFormatVersion; aoqi@0: aoqi@0: // Since java.io.OptionalDataException's constructors are aoqi@0: // package private, but we need to throw it in some special aoqi@0: // cases, we try to do it by reflection. aoqi@0: private static final Constructor OPT_DATA_EXCEPTION_CTOR; aoqi@0: aoqi@0: private Object[] readObjectArgList = { this } ; aoqi@0: aoqi@0: static { aoqi@0: OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor(); aoqi@0: } aoqi@0: aoqi@0: // Grab the OptionalDataException boolean ctor and make aoqi@0: // it accessible. Note that any exceptions aoqi@0: // will be wrapped in ExceptionInInitializerErrors. aoqi@0: private static Constructor getOptDataExceptionCtor() { aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: Constructor result = aoqi@0: aoqi@0: (Constructor) AccessController.doPrivileged( aoqi@0: new PrivilegedExceptionAction() { aoqi@0: public java.lang.Object run() aoqi@0: throws NoSuchMethodException, aoqi@0: SecurityException { aoqi@0: aoqi@0: Constructor boolCtor aoqi@0: = OptionalDataException.class.getDeclaredConstructor( aoqi@0: new Class[] { aoqi@0: Boolean.TYPE }); aoqi@0: aoqi@0: boolCtor.setAccessible(true); aoqi@0: aoqi@0: return boolCtor; aoqi@0: }}); aoqi@0: aoqi@0: if (result == null) aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new Error("Unable to find OptionalDataException constructor"); aoqi@0: aoqi@0: return result; aoqi@0: aoqi@0: } catch (Exception ex) { aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new ExceptionInInitializerError(ex); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Create a new OptionalDataException with the EOF marker aoqi@0: // set to true. See handleOptionalDataMarshalException. aoqi@0: private OptionalDataException createOptionalDataException() { aoqi@0: try { aoqi@0: OptionalDataException result aoqi@0: = (OptionalDataException) aoqi@0: OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] { aoqi@0: Boolean.TRUE }); aoqi@0: aoqi@0: if (result == null) aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new Error("Created null OptionalDataException"); aoqi@0: aoqi@0: return result; aoqi@0: aoqi@0: } catch (Exception ex) { aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new Error("Couldn't create OptionalDataException", ex); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Return the stream format version currently being used aoqi@0: // to deserialize an object aoqi@0: protected byte getStreamFormatVersion() { aoqi@0: return streamFormatVersion; aoqi@0: } aoqi@0: aoqi@0: // At the beginning of data sent by a writeObject or aoqi@0: // writeExternal method there is a byte telling the aoqi@0: // reader the stream format version. aoqi@0: private void readFormatVersion() throws IOException { aoqi@0: aoqi@0: streamFormatVersion = orbStream.read_octet(); aoqi@0: aoqi@0: if (streamFormatVersion < 1 || aoqi@0: streamFormatVersion > vhandler.getMaximumStreamFormatVersion()) { aoqi@0: SystemException sysex = omgWrapper.unsupportedFormatVersion( aoqi@0: CompletionStatus.COMPLETED_MAYBE); aoqi@0: // XXX I18N? Logging for IOException? aoqi@0: IOException result = new IOException("Unsupported format version: " aoqi@0: + streamFormatVersion); aoqi@0: result.initCause( sysex ) ; aoqi@0: throw result ; aoqi@0: } aoqi@0: aoqi@0: if (streamFormatVersion == 2) { aoqi@0: if (!(orbStream instanceof ValueInputStream)) { aoqi@0: SystemException sysex = omgWrapper.notAValueinputstream( aoqi@0: CompletionStatus.COMPLETED_MAYBE); aoqi@0: // XXX I18N? Logging for IOException? aoqi@0: IOException result = new IOException("Not a ValueInputStream"); aoqi@0: result.initCause( sysex ) ; aoqi@0: throw result; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public static void setTestFVDFlag(boolean val){ aoqi@0: // useFVDOnly = val; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Dummy constructor; passes upper stream a dummy stream; aoqi@0: **/ aoqi@0: public IIOPInputStream() aoqi@0: throws java.io.IOException { aoqi@0: super(); aoqi@0: resetStream(); aoqi@0: } aoqi@0: aoqi@0: final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) { aoqi@0: orbStream = os; aoqi@0: } aoqi@0: aoqi@0: final org.omg.CORBA_2_3.portable.InputStream getOrbStream() { aoqi@0: return orbStream; aoqi@0: } aoqi@0: aoqi@0: //added setSender and getSender aoqi@0: public final void setSender(CodeBase cb) { aoqi@0: cbSender = cb; aoqi@0: } aoqi@0: aoqi@0: public final CodeBase getSender() { aoqi@0: return cbSender; aoqi@0: } aoqi@0: aoqi@0: // 4365188 this is added to enable backward compatability w/ wrong aoqi@0: // rep-ids aoqi@0: public final void setValueHandler(ValueHandler vh) { aoqi@0: vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh; aoqi@0: } aoqi@0: aoqi@0: public final ValueHandler getValueHandler() { aoqi@0: return (javax.rmi.CORBA.ValueHandler) vhandler; aoqi@0: } aoqi@0: aoqi@0: final void increaseRecursionDepth(){ aoqi@0: recursionDepth++; aoqi@0: } aoqi@0: aoqi@0: final int decreaseRecursionDepth(){ aoqi@0: return --recursionDepth; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Override the actions of the final method "readObject()" aoqi@0: * in ObjectInputStream. aoqi@0: * @since JDK1.1.6 aoqi@0: * aoqi@0: * Read an object from the ObjectInputStream. aoqi@0: * The class of the object, the signature of the class, and the values aoqi@0: * of the non-transient and non-static fields of the class and all aoqi@0: * of its supertypes are read. Default deserializing for a class can be aoqi@0: * overriden using the writeObject and readObject methods. aoqi@0: * Objects referenced by this object are read transitively so aoqi@0: * that a complete equivalent graph of objects is reconstructed by readObject.

aoqi@0: * aoqi@0: * The root object is completly restored when all of its fields aoqi@0: * and the objects it references are completely restored. At this aoqi@0: * point the object validation callbacks are executed in order aoqi@0: * based on their registered priorities. The callbacks are aoqi@0: * registered by objects (in the readObject special methods) aoqi@0: * as they are individually restored. aoqi@0: * aoqi@0: * Exceptions are thrown for problems with the InputStream and for classes aoqi@0: * that should not be deserialized. All exceptions are fatal to the aoqi@0: * InputStream and leave it in an indeterminate state; it is up to the caller aoqi@0: * to ignore or recover the stream state. aoqi@0: * @exception java.lang.ClassNotFoundException Class of a serialized object aoqi@0: * cannot be found. aoqi@0: * @exception InvalidClassException Something is wrong with a class used by aoqi@0: * serialization. aoqi@0: * @exception StreamCorruptedException Control information in the aoqi@0: * stream is inconsistent. aoqi@0: * @exception OptionalDataException Primitive data was found in the aoqi@0: * stream instead of objects. aoqi@0: * @exception IOException Any of the usual Input/Output related exceptions. aoqi@0: * @since JDK1.1 aoqi@0: */ aoqi@0: public final synchronized Object readObjectDelegate() throws IOException aoqi@0: { aoqi@0: try { aoqi@0: aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_abstract_interface(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, true); aoqi@0: throw marshalException; aoqi@0: } catch(IndirectionException cdrie) aoqi@0: { aoqi@0: // The CDR stream had never seen the given offset before, aoqi@0: // so check the recursion manager (it will throw an aoqi@0: // IOException if it doesn't have a reference, either). aoqi@0: return activeRecursionMgr.getObject(cdrie.offset); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: final synchronized Object simpleReadObject(Class clz, aoqi@0: String repositoryID, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender, aoqi@0: int offset) aoqi@0: /* throws OptionalDataException, ClassNotFoundException, IOException */ aoqi@0: { aoqi@0: aoqi@0: /* Save the current state and get ready to read an object. */ aoqi@0: Object prevObject = currentObject; aoqi@0: ObjectStreamClass prevClassDesc = currentClassDesc; aoqi@0: Class prevClass = currentClass; aoqi@0: byte oldStreamFormatVersion = streamFormatVersion; aoqi@0: aoqi@0: simpleReadDepth++; // Entering aoqi@0: Object obj = null; aoqi@0: aoqi@0: /* aoqi@0: * Check for reset, handle it before reading an object. aoqi@0: */ aoqi@0: try { aoqi@0: // d4365188: backward compatability aoqi@0: if (vhandler.useFullValueDescription(clz, repositoryID)) { aoqi@0: obj = inputObjectUsingFVD(clz, repositoryID, sender, offset); aoqi@0: } else { aoqi@0: obj = inputObject(clz, repositoryID, sender, offset); aoqi@0: } aoqi@0: aoqi@0: obj = currentClassDesc.readResolve(obj); aoqi@0: } aoqi@0: catch(ClassNotFoundException cnfe) aoqi@0: { aoqi@0: bridge.throwException( cnfe ) ; aoqi@0: return null; aoqi@0: } aoqi@0: catch(IOException ioe) aoqi@0: { aoqi@0: // System.out.println("CLZ = " + clz + "; " + ioe.toString()); aoqi@0: bridge.throwException(ioe) ; aoqi@0: return null; aoqi@0: } aoqi@0: finally { aoqi@0: simpleReadDepth --; aoqi@0: currentObject = prevObject; aoqi@0: currentClassDesc = prevClassDesc; aoqi@0: currentClass = prevClass; aoqi@0: streamFormatVersion = oldStreamFormatVersion; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /* Check for thrown exceptions and re-throw them, clearing them if aoqi@0: * this is the last recursive call . aoqi@0: */ aoqi@0: IOException exIOE = abortIOException; aoqi@0: if (simpleReadDepth == 0) aoqi@0: abortIOException = null; aoqi@0: if (exIOE != null){ aoqi@0: bridge.throwException( exIOE ) ; aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: ClassNotFoundException exCNF = abortClassNotFoundException; aoqi@0: if (simpleReadDepth == 0) aoqi@0: abortClassNotFoundException = null; aoqi@0: if (exCNF != null) { aoqi@0: bridge.throwException( exCNF ) ; aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: return obj; aoqi@0: } aoqi@0: aoqi@0: public final synchronized void simpleSkipObject(String repositoryID, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender) aoqi@0: /* throws OptionalDataException, ClassNotFoundException, IOException */ aoqi@0: { aoqi@0: aoqi@0: /* Save the current state and get ready to read an object. */ aoqi@0: Object prevObject = currentObject; aoqi@0: ObjectStreamClass prevClassDesc = currentClassDesc; aoqi@0: Class prevClass = currentClass; aoqi@0: byte oldStreamFormatVersion = streamFormatVersion; aoqi@0: aoqi@0: simpleReadDepth++; // Entering aoqi@0: Object obj = null; aoqi@0: aoqi@0: /* aoqi@0: * Check for reset, handle it before reading an object. aoqi@0: */ aoqi@0: try { aoqi@0: skipObjectUsingFVD(repositoryID, sender); aoqi@0: } aoqi@0: catch(ClassNotFoundException cnfe) aoqi@0: { aoqi@0: bridge.throwException( cnfe ) ; aoqi@0: return; aoqi@0: } aoqi@0: catch(IOException ioe) aoqi@0: { aoqi@0: bridge.throwException( ioe ) ; aoqi@0: return; aoqi@0: } aoqi@0: finally { aoqi@0: simpleReadDepth --; aoqi@0: streamFormatVersion = oldStreamFormatVersion; aoqi@0: currentObject = prevObject; aoqi@0: currentClassDesc = prevClassDesc; aoqi@0: currentClass = prevClass; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /* Check for thrown exceptions and re-throw them, clearing them if aoqi@0: * this is the last recursive call . aoqi@0: */ aoqi@0: IOException exIOE = abortIOException; aoqi@0: if (simpleReadDepth == 0) aoqi@0: abortIOException = null; aoqi@0: if (exIOE != null){ aoqi@0: bridge.throwException( exIOE ) ; aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: ClassNotFoundException exCNF = abortClassNotFoundException; aoqi@0: if (simpleReadDepth == 0) aoqi@0: abortClassNotFoundException = null; aoqi@0: if (exCNF != null) { aoqi@0: bridge.throwException( exCNF ) ; aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: return; aoqi@0: } aoqi@0: ///////////////// aoqi@0: aoqi@0: /** aoqi@0: * This method is called by trusted subclasses of ObjectOutputStream aoqi@0: * that constructed ObjectOutputStream using the aoqi@0: * protected no-arg constructor. The subclass is expected to provide aoqi@0: * an override method with the modifier "final". aoqi@0: * aoqi@0: * @return the Object read from the stream. aoqi@0: * aoqi@0: * @see #ObjectInputStream() aoqi@0: * @see #readObject aoqi@0: * @since JDK 1.2 aoqi@0: */ aoqi@0: protected final Object readObjectOverride() aoqi@0: throws OptionalDataException, ClassNotFoundException, IOException aoqi@0: { aoqi@0: return readObjectDelegate(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Override the actions of the final method "defaultReadObject()" aoqi@0: * in ObjectInputStream. aoqi@0: * @since JDK1.1.6 aoqi@0: * aoqi@0: * Read the non-static and non-transient fields of the current class aoqi@0: * from this stream. This may only be called from the readObject method aoqi@0: * of the class being deserialized. It will throw the NotActiveException aoqi@0: * if it is called otherwise. aoqi@0: * aoqi@0: * @exception java.lang.ClassNotFoundException if the class of a serialized aoqi@0: * object could not be found. aoqi@0: * @exception IOException if an I/O error occurs. aoqi@0: * @exception NotActiveException if the stream is not currently reading aoqi@0: * objects. aoqi@0: * @since JDK1.1 aoqi@0: */ aoqi@0: final synchronized void defaultReadObjectDelegate() aoqi@0: /* throws IOException, ClassNotFoundException, NotActiveException */ aoqi@0: { aoqi@0: try { aoqi@0: if (currentObject == null || currentClassDesc == null) aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new NotActiveException("defaultReadObjectDelegate"); aoqi@0: aoqi@0: // The array will be null unless fields were retrieved aoqi@0: // remotely because of a serializable version difference. aoqi@0: // Bug fix for 4365188. See the definition of aoqi@0: // defaultReadObjectFVDMembers for more information. aoqi@0: if (defaultReadObjectFVDMembers != null && aoqi@0: defaultReadObjectFVDMembers.length > 0) { aoqi@0: aoqi@0: // WARNING: Be very careful! What if some of aoqi@0: // these fields actually have to do this, too? aoqi@0: // This works because the defaultReadObjectFVDMembers aoqi@0: // reference is passed to inputClassFields, but aoqi@0: // there is no guarantee that aoqi@0: // defaultReadObjectFVDMembers will point to the aoqi@0: // same array after calling inputClassFields. aoqi@0: aoqi@0: // Use the remote fields to unmarshal. aoqi@0: inputClassFields(currentObject, aoqi@0: currentClass, aoqi@0: currentClassDesc, aoqi@0: defaultReadObjectFVDMembers, aoqi@0: cbSender); aoqi@0: aoqi@0: } else { aoqi@0: aoqi@0: // Use the local fields to unmarshal. aoqi@0: ObjectStreamField[] fields = aoqi@0: currentClassDesc.getFieldsNoCopy(); aoqi@0: if (fields.length > 0) { aoqi@0: inputClassFields(currentObject, currentClass, fields, cbSender); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: catch(NotActiveException nae) aoqi@0: { aoqi@0: bridge.throwException( nae ) ; aoqi@0: } aoqi@0: catch(IOException ioe) aoqi@0: { aoqi@0: bridge.throwException( ioe ) ; aoqi@0: } aoqi@0: catch(ClassNotFoundException cnfe) aoqi@0: { aoqi@0: bridge.throwException( cnfe ) ; aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Override the actions of the final method "enableResolveObject()" aoqi@0: * in ObjectInputStream. aoqi@0: * @since JDK1.1.6 aoqi@0: * aoqi@0: * Enable the stream to allow objects read from the stream to be replaced. aoqi@0: * If the stream is a trusted class it is allowed to enable replacment. aoqi@0: * Trusted classes are those classes with a classLoader equals null.

aoqi@0: * aoqi@0: * When enabled the resolveObject method is called for every object aoqi@0: * being deserialized. aoqi@0: * aoqi@0: * @exception SecurityException The classloader of this stream object is non-null. aoqi@0: * @since JDK1.1 aoqi@0: */ aoqi@0: public final boolean enableResolveObjectDelegate(boolean enable) aoqi@0: /* throws SecurityException */ aoqi@0: { aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: // The following three methods allow the implementing orbStream aoqi@0: // to provide mark/reset behavior as defined in java.io.InputStream. aoqi@0: aoqi@0: public final void mark(int readAheadLimit) { aoqi@0: orbStream.mark(readAheadLimit); aoqi@0: } aoqi@0: aoqi@0: public final boolean markSupported() { aoqi@0: return orbStream.markSupported(); aoqi@0: } aoqi@0: aoqi@0: public final void reset() throws IOException { aoqi@0: try { aoqi@0: orbStream.reset(); aoqi@0: } catch (Error e) { aoqi@0: IOException err = new IOException(e.getMessage()); aoqi@0: err.initCause(e) ; aoqi@0: throw err ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final int available() throws IOException{ aoqi@0: return 0; // unreliable aoqi@0: } aoqi@0: aoqi@0: public final void close() throws IOException{ aoqi@0: // no op aoqi@0: } aoqi@0: aoqi@0: public final int read() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return (orbStream.read_octet() << 0) & 0x000000FF; aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: if (marshalException.minor aoqi@0: == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { aoqi@0: setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); aoqi@0: return -1; aoqi@0: } aoqi@0: aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e) ; aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final int read(byte data[], int offset, int length) throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: orbStream.read_octet_array(data, offset, length); aoqi@0: return length; aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: if (marshalException.minor aoqi@0: == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { aoqi@0: setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); aoqi@0: return -1; aoqi@0: } aoqi@0: aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e) ; aoqi@0: throw exc ; aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: public final boolean readBoolean() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_boolean(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final byte readByte() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_octet(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final char readChar() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_wchar(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final double readDouble() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_double(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final float readFloat() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_float(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final void readFully(byte data[]) throws IOException{ aoqi@0: // d11623 : implement readFully, required for serializing some core classes aoqi@0: aoqi@0: readFully(data, 0, data.length); aoqi@0: } aoqi@0: aoqi@0: public final void readFully(byte data[], int offset, int size) throws IOException{ aoqi@0: // d11623 : implement readFully, required for serializing some core classes aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: orbStream.read_octet_array(data, offset, size); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final int readInt() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_long(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final String readLine() throws IOException{ aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new IOException("Method readLine not supported"); aoqi@0: } aoqi@0: aoqi@0: public final long readLong() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_longlong(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final short readShort() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return orbStream.read_short(); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void readStreamHeader() throws IOException, StreamCorruptedException{ aoqi@0: // no op aoqi@0: } aoqi@0: aoqi@0: public final int readUnsignedByte() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return (orbStream.read_octet() << 0) & 0x000000FF; aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final int readUnsignedShort() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return (orbStream.read_ushort() << 0) & 0x0000FFFF; aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Helper method for correcting the Kestrel bug 4367783 (dealing aoqi@0: * with larger than 8-bit chars). The old behavior is preserved aoqi@0: * in orbutil.IIOPInputStream_1_3 in order to interoperate with aoqi@0: * our legacy ORBs. aoqi@0: */ aoqi@0: protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream) aoqi@0: { aoqi@0: return stream.read_wstring(); aoqi@0: } aoqi@0: aoqi@0: public final String readUTF() throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: return internalReadUTF(orbStream); aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e); aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // If the ORB stream detects an incompatibility between what's aoqi@0: // on the wire and what our Serializable's readObject wants, aoqi@0: // it throws a MARSHAL exception with a specific minor code. aoqi@0: // This is rethrown to the readObject as an OptionalDataException. aoqi@0: // So far in RMI-IIOP, this process isn't specific enough to aoqi@0: // tell the readObject how much data is available, so we always aoqi@0: // set the OptionalDataException's EOF marker to true. aoqi@0: private void handleOptionalDataMarshalException(MARSHAL marshalException, aoqi@0: boolean objectRead) aoqi@0: throws IOException { aoqi@0: aoqi@0: // Java Object Serialization spec 3.4: "If the readObject method aoqi@0: // of the class attempts to read more data than is present in the aoqi@0: // optional part of the stream for this class, the stream will aoqi@0: // return -1 for bytewise reads, throw an EOFException for aoqi@0: // primitive data reads, or throw an OptionalDataException aoqi@0: // with the eof field set to true for object reads." aoqi@0: if (marshalException.minor aoqi@0: == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) { aoqi@0: aoqi@0: IOException result; aoqi@0: aoqi@0: if (!objectRead) aoqi@0: result = new EOFException("No more optional data"); aoqi@0: else aoqi@0: result = createOptionalDataException(); aoqi@0: aoqi@0: result.initCause(marshalException); aoqi@0: aoqi@0: setState(IN_READ_OBJECT_NO_MORE_OPT_DATA); aoqi@0: aoqi@0: throw result; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final synchronized void registerValidation(ObjectInputValidation obj, aoqi@0: int prio) aoqi@0: throws NotActiveException, InvalidObjectException{ aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new Error("Method registerValidation not supported"); aoqi@0: } aoqi@0: aoqi@0: protected final Class resolveClass(ObjectStreamClass v) aoqi@0: throws IOException, ClassNotFoundException{ aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new IOException("Method resolveClass not supported"); aoqi@0: } aoqi@0: aoqi@0: protected final Object resolveObject(Object obj) throws IOException{ aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new IOException("Method resolveObject not supported"); aoqi@0: } aoqi@0: aoqi@0: public final int skipBytes(int len) throws IOException{ aoqi@0: try{ aoqi@0: readObjectState.readData(this); aoqi@0: aoqi@0: byte buf[] = new byte[len]; aoqi@0: orbStream.read_octet_array(buf, 0, len); aoqi@0: return len; aoqi@0: } catch (MARSHAL marshalException) { aoqi@0: handleOptionalDataMarshalException(marshalException, false); aoqi@0: aoqi@0: throw marshalException; aoqi@0: } catch(Error e) { aoqi@0: IOException exc = new IOException(e.getMessage()); aoqi@0: exc.initCause(e) ; aoqi@0: throw exc ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private synchronized Object inputObject(Class clz, aoqi@0: String repositoryID, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender, aoqi@0: int offset) aoqi@0: throws IOException, ClassNotFoundException aoqi@0: { aoqi@0: aoqi@0: /* aoqi@0: * Get the descriptor and then class of the incoming object. aoqi@0: */ aoqi@0: aoqi@0: currentClassDesc = ObjectStreamClass.lookup(clz); aoqi@0: currentClass = currentClassDesc.forClass(); aoqi@0: //currentClassDesc.setClass(currentClass); aoqi@0: if (currentClass == null) aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new ClassNotFoundException(currentClassDesc.getName()); aoqi@0: aoqi@0: try { aoqi@0: /* If Externalizable, aoqi@0: * Create an instance and tell it to read its data. aoqi@0: * else, aoqi@0: * Handle it as a serializable class. aoqi@0: */ aoqi@0: if (Enum.class.isAssignableFrom( clz )) { aoqi@0: int ordinal = orbStream.read_long() ; aoqi@0: String value = (String)orbStream.read_value( String.class ) ; aoqi@0: return Enum.valueOf( clz, value ) ; aoqi@0: } else if (currentClassDesc.isExternalizable()) { aoqi@0: try { aoqi@0: currentObject = (currentClass == null) ? aoqi@0: null : currentClassDesc.newInstance(); aoqi@0: if (currentObject != null) { aoqi@0: aoqi@0: // Store this object and its beginning position aoqi@0: // since there might be indirections to it while aoqi@0: // it's been unmarshalled. aoqi@0: activeRecursionMgr.addObject(offset, currentObject); aoqi@0: aoqi@0: // Read format version aoqi@0: readFormatVersion(); aoqi@0: aoqi@0: Externalizable ext = (Externalizable)currentObject; aoqi@0: ext.readExternal(this); aoqi@0: } aoqi@0: } catch (InvocationTargetException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "InvocationTargetException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } catch (UnsupportedOperationException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "UnsupportedOperationException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } catch (InstantiationException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "InstantiationException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } aoqi@0: } // end : if (currentClassDesc.isExternalizable()) aoqi@0: else { aoqi@0: /* Count number of classes and descriptors we might have aoqi@0: * to work on. aoqi@0: */ aoqi@0: aoqi@0: ObjectStreamClass currdesc = currentClassDesc; aoqi@0: Class currclass = currentClass; aoqi@0: aoqi@0: int spBase = spClass; // current top of stack aoqi@0: aoqi@0: /* The object's classes should be processed from supertype to subtype aoqi@0: * Push all the clases of the current object onto a stack. aoqi@0: * Note that only the serializable classes are represented aoqi@0: * in the descriptor list. aoqi@0: * aoqi@0: * Handle versioning where one or more supertypes of aoqi@0: * have been inserted or removed. The stack will aoqi@0: * contain pairs of descriptors and the corresponding aoqi@0: * class. If the object has a class that did not occur in aoqi@0: * the original the descriptor will be null. If the aoqi@0: * original object had a descriptor for a class not aoqi@0: * present in the local hierarchy of the object the class will be aoqi@0: * null. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * This is your basic diff pattern, made simpler aoqi@0: * because reordering is not allowed. aoqi@0: */ aoqi@0: // sun.4296963 ibm.11861 aoqi@0: // d11861 we should stop when we find the highest serializable class aoqi@0: // We need this so that when we allocate the new object below, we aoqi@0: // can call the constructor of the non-serializable superclass. aoqi@0: // Note that in the JRMP variant of this code the aoqi@0: // ObjectStreamClass.lookup() method handles this, but we've put aoqi@0: // this fix here rather than change lookup because the new behaviour aoqi@0: // is needed in other cases. aoqi@0: aoqi@0: for (currdesc = currentClassDesc, currclass = currentClass; aoqi@0: currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/ aoqi@0: currdesc = currdesc.getSuperclass()) { aoqi@0: aoqi@0: /* aoqi@0: * Search the classes to see if the class of this aoqi@0: * descriptor appears further up the hierarchy. Until aoqi@0: * it's found assume its an inserted class. If it's aoqi@0: * not found, its the descriptor's class that has been aoqi@0: * removed. aoqi@0: */ aoqi@0: Class cc = currdesc.forClass(); aoqi@0: Class cl; aoqi@0: for (cl = currclass; cl != null; cl = cl.getSuperclass()) { aoqi@0: if (cc == cl) { aoqi@0: // found a superclass that matches this descriptor aoqi@0: break; aoqi@0: } else { aoqi@0: /* Ignore a class that doesn't match. No aoqi@0: * action is needed since it is already aoqi@0: * initialized. aoqi@0: */ aoqi@0: } aoqi@0: } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass()) aoqi@0: /* Test if there is room for this new entry. aoqi@0: * If not, double the size of the arrays and copy the contents. aoqi@0: */ aoqi@0: spClass++; aoqi@0: if (spClass >= classes.length) { aoqi@0: int newlen = classes.length * 2; aoqi@0: Class[] newclasses = new Class[newlen]; aoqi@0: ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen]; aoqi@0: aoqi@0: System.arraycopy(classes, 0, aoqi@0: newclasses, 0, aoqi@0: classes.length); aoqi@0: System.arraycopy(classdesc, 0, aoqi@0: newclassdesc, 0, aoqi@0: classes.length); aoqi@0: aoqi@0: classes = newclasses; aoqi@0: classdesc = newclassdesc; aoqi@0: } aoqi@0: aoqi@0: if (cl == null) { aoqi@0: /* Class not found corresponding to this descriptor. aoqi@0: * Pop off all the extra classes pushed. aoqi@0: * Push the descriptor and a null class. aoqi@0: */ aoqi@0: classdesc[spClass] = currdesc; aoqi@0: classes[spClass] = null; aoqi@0: } else { aoqi@0: /* Current class descriptor matches current class. aoqi@0: * Some classes may have been inserted. aoqi@0: * Record the match and advance the class, continue aoqi@0: * with the next descriptor. aoqi@0: */ aoqi@0: classdesc[spClass] = currdesc; aoqi@0: classes[spClass] = cl; aoqi@0: currclass = cl.getSuperclass(); aoqi@0: } aoqi@0: } // end : for (currdesc = currentClassDesc, currclass = currentClass; aoqi@0: aoqi@0: /* Allocate a new object. The object is only constructed aoqi@0: * above the highest serializable class and is set to aoqi@0: * default values for all more specialized classes. aoqi@0: */ aoqi@0: try { aoqi@0: currentObject = (currentClass == null) ? aoqi@0: null : currentClassDesc.newInstance() ; aoqi@0: aoqi@0: // Store this object and its beginning position aoqi@0: // since there might be indirections to it while aoqi@0: // it's been unmarshalled. aoqi@0: activeRecursionMgr.addObject(offset, currentObject); aoqi@0: } catch (InvocationTargetException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "InvocationTargetException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } catch (UnsupportedOperationException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "UnsupportedOperationException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } catch (InstantiationException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "InstantiationException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * For all the pushed descriptors and classes. aoqi@0: * if the class has its own writeObject and readObject methods aoqi@0: * call the readObject method aoqi@0: * else aoqi@0: * invoke the defaultReadObject method aoqi@0: */ aoqi@0: try { aoqi@0: for (spClass = spClass; spClass > spBase; spClass--) { aoqi@0: /* aoqi@0: * Set current descriptor and corresponding class aoqi@0: */ aoqi@0: currentClassDesc = classdesc[spClass]; aoqi@0: currentClass = classes[spClass]; aoqi@0: if (classes[spClass] != null) { aoqi@0: /* Read the data from the stream described by the aoqi@0: * descriptor and store into the matching class. aoqi@0: */ aoqi@0: aoqi@0: ReadObjectState oldState = readObjectState; aoqi@0: setState(DEFAULT_STATE); aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: // Changed since invokeObjectReader no longer does this. aoqi@0: if (currentClassDesc.hasWriteObject()) { aoqi@0: aoqi@0: // Read format version aoqi@0: readFormatVersion(); aoqi@0: aoqi@0: // Read defaultWriteObject indicator aoqi@0: boolean calledDefaultWriteObject = readBoolean(); aoqi@0: aoqi@0: readObjectState.beginUnmarshalCustomValue(this, aoqi@0: calledDefaultWriteObject, aoqi@0: (currentClassDesc.readObjectMethod aoqi@0: != null)); aoqi@0: } else { aoqi@0: if (currentClassDesc.hasReadObject()) aoqi@0: setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); aoqi@0: } aoqi@0: aoqi@0: if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) || aoqi@0: readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) { aoqi@0: aoqi@0: // Error case of no readObject and didn't call aoqi@0: // defaultWriteObject handled in default state aoqi@0: aoqi@0: ObjectStreamField[] fields = aoqi@0: currentClassDesc.getFieldsNoCopy(); aoqi@0: if (fields.length > 0) { aoqi@0: inputClassFields(currentObject, currentClass, fields, sender); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (currentClassDesc.hasWriteObject()) aoqi@0: readObjectState.endUnmarshalCustomValue(this); aoqi@0: aoqi@0: } finally { aoqi@0: setState(oldState); aoqi@0: } aoqi@0: aoqi@0: } else { aoqi@0: aoqi@0: // _REVISIT_ : Can we ever get here? aoqi@0: /* No local class for this descriptor, aoqi@0: * Skip over the data for this class. aoqi@0: * like defaultReadObject with a null currentObject. aoqi@0: * The code will read the values but discard them. aoqi@0: */ aoqi@0: ObjectStreamField[] fields = aoqi@0: currentClassDesc.getFieldsNoCopy(); aoqi@0: if (fields.length > 0) { aoqi@0: inputClassFields(null, currentClass, fields, sender); aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: } finally { aoqi@0: // Make sure we exit at the same stack level as when we started. aoqi@0: spClass = spBase; aoqi@0: } aoqi@0: } aoqi@0: } finally { aoqi@0: // We've completed deserializing this object. Any aoqi@0: // future indirections will be handled correctly at the aoqi@0: // CDR level. The ActiveRecursionManager only deals with aoqi@0: // objects currently being deserialized. aoqi@0: activeRecursionMgr.removeObject(offset); aoqi@0: } aoqi@0: aoqi@0: return currentObject; aoqi@0: } aoqi@0: aoqi@0: // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from aoqi@0: // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable aoqi@0: // classes! aoqi@0: private Vector getOrderedDescriptions(String repositoryID, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender) { aoqi@0: Vector descs = new Vector(); aoqi@0: aoqi@0: if (sender == null) { aoqi@0: return descs; aoqi@0: } aoqi@0: aoqi@0: FullValueDescription aFVD = sender.meta(repositoryID); aoqi@0: while (aFVD != null) { aoqi@0: descs.insertElementAt(aFVD, 0); aoqi@0: if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) { aoqi@0: aFVD = sender.meta(aFVD.base_value); aoqi@0: } aoqi@0: else return descs; aoqi@0: } aoqi@0: aoqi@0: return descs; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * This input method uses FullValueDescriptions retrieved from the sender's runtime to aoqi@0: * read in the data. This method is capable of throwing out data not applicable to client's fields. aoqi@0: * This method handles instances where the reader has a class not sent by the sender, the sender sent aoqi@0: * a class not present on the reader, and/or the reader's class does not match the sender's class. aoqi@0: * aoqi@0: * NOTE : If the local description indicates custom marshaling and the remote type's FVD also aoqi@0: * indicates custom marsahling than the local type is used to read the data off the wire. However, aoqi@0: * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is aoqi@0: * a form of custom marshaling. aoqi@0: * aoqi@0: */ aoqi@0: private synchronized Object inputObjectUsingFVD(Class clz, aoqi@0: String repositoryID, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender, aoqi@0: int offset) aoqi@0: throws IOException, ClassNotFoundException aoqi@0: { aoqi@0: int spBase = spClass; // current top of stack aoqi@0: try{ aoqi@0: aoqi@0: /* aoqi@0: * Get the descriptor and then class of the incoming object. aoqi@0: */ aoqi@0: aoqi@0: ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz); aoqi@0: Class currclass = currentClass = clz; aoqi@0: aoqi@0: /* If Externalizable, aoqi@0: * Create an instance and tell it to read its data. aoqi@0: * else, aoqi@0: * Handle it as a serializable class. aoqi@0: */ aoqi@0: if (currentClassDesc.isExternalizable()) { aoqi@0: try { aoqi@0: currentObject = (currentClass == null) ? aoqi@0: null : currentClassDesc.newInstance(); aoqi@0: if (currentObject != null) { aoqi@0: // Store this object and its beginning position aoqi@0: // since there might be indirections to it while aoqi@0: // it's been unmarshalled. aoqi@0: activeRecursionMgr.addObject(offset, currentObject); aoqi@0: aoqi@0: // Read format version aoqi@0: readFormatVersion(); aoqi@0: aoqi@0: Externalizable ext = (Externalizable)currentObject; aoqi@0: ext.readExternal(this); aoqi@0: } aoqi@0: } catch (InvocationTargetException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "InvocationTargetException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } catch (UnsupportedOperationException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "UnsupportedOperationException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } catch (InstantiationException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "InstantiationException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } aoqi@0: } else { aoqi@0: /* aoqi@0: * This is your basic diff pattern, made simpler aoqi@0: * because reordering is not allowed. aoqi@0: */ aoqi@0: for (currdesc = currentClassDesc, currclass = currentClass; aoqi@0: currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/ aoqi@0: aoqi@0: currdesc = currdesc.getSuperclass()) { aoqi@0: aoqi@0: /* aoqi@0: * Search the classes to see if the class of this aoqi@0: * descriptor appears further up the hierarchy. Until aoqi@0: * it's found assume its an inserted class. If it's aoqi@0: * not found, its the descriptor's class that has been aoqi@0: * removed. aoqi@0: */ aoqi@0: Class cc = currdesc.forClass(); aoqi@0: Class cl; aoqi@0: for (cl = currclass; cl != null; cl = cl.getSuperclass()) { aoqi@0: if (cc == cl) { aoqi@0: // found a superclass that matches this descriptor aoqi@0: break; aoqi@0: } else { aoqi@0: /* Ignore a class that doesn't match. No aoqi@0: * action is needed since it is already aoqi@0: * initialized. aoqi@0: */ aoqi@0: } aoqi@0: } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass()) aoqi@0: /* Test if there is room for this new entry. aoqi@0: * If not, double the size of the arrays and copy the contents. aoqi@0: */ aoqi@0: spClass++; aoqi@0: if (spClass >= classes.length) { aoqi@0: int newlen = classes.length * 2; aoqi@0: Class[] newclasses = new Class[newlen]; aoqi@0: ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen]; aoqi@0: aoqi@0: System.arraycopy(classes, 0, aoqi@0: newclasses, 0, aoqi@0: classes.length); aoqi@0: System.arraycopy(classdesc, 0, aoqi@0: newclassdesc, 0, aoqi@0: classes.length); aoqi@0: aoqi@0: classes = newclasses; aoqi@0: classdesc = newclassdesc; aoqi@0: } aoqi@0: aoqi@0: if (cl == null) { aoqi@0: /* Class not found corresponding to this descriptor. aoqi@0: * Pop off all the extra classes pushed. aoqi@0: * Push the descriptor and a null class. aoqi@0: */ aoqi@0: classdesc[spClass] = currdesc; aoqi@0: classes[spClass] = null; aoqi@0: } else { aoqi@0: /* Current class descriptor matches current class. aoqi@0: * Some classes may have been inserted. aoqi@0: * Record the match and advance the class, continue aoqi@0: * with the next descriptor. aoqi@0: */ aoqi@0: classdesc[spClass] = currdesc; aoqi@0: classes[spClass] = cl; aoqi@0: currclass = cl.getSuperclass(); aoqi@0: } aoqi@0: } // end : for (currdesc = currentClassDesc, currclass = currentClass; aoqi@0: aoqi@0: /* Allocate a new object. aoqi@0: */ aoqi@0: try { aoqi@0: currentObject = (currentClass == null) ? aoqi@0: null : currentClassDesc.newInstance(); aoqi@0: aoqi@0: // Store this object and its beginning position aoqi@0: // since there might be indirections to it while aoqi@0: // it's been unmarshalled. aoqi@0: activeRecursionMgr.addObject(offset, currentObject); aoqi@0: } catch (InvocationTargetException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "InvocationTargetException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } catch (UnsupportedOperationException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "UnsupportedOperationException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } catch (InstantiationException e) { aoqi@0: InvalidClassException exc = new InvalidClassException( aoqi@0: currentClass.getName(), aoqi@0: "InstantiationException accessing no-arg constructor"); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } aoqi@0: aoqi@0: Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements(); aoqi@0: aoqi@0: while((fvdsList.hasMoreElements()) && (spClass > spBase)) { aoqi@0: FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); aoqi@0: // d4365188: backward compatability aoqi@0: String repIDForFVD = vhandler.getClassName(fvd.id); aoqi@0: String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass)); aoqi@0: aoqi@0: while ((spClass > spBase) && aoqi@0: (!repIDForFVD.equals(repIDForClass))) { aoqi@0: int pos = findNextClass(repIDForFVD, classes, spClass, spBase); aoqi@0: if (pos != -1) { aoqi@0: spClass = pos; aoqi@0: currclass = currentClass = classes[spClass]; aoqi@0: repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass)); aoqi@0: } aoqi@0: else { // Read and throw away one level of the fvdslist aoqi@0: aoqi@0: // This seems to mean that the sender had a superclass that aoqi@0: // we don't have aoqi@0: aoqi@0: if (fvd.is_custom) { aoqi@0: aoqi@0: readFormatVersion(); aoqi@0: boolean calledDefaultWriteObject = readBoolean(); aoqi@0: aoqi@0: if (calledDefaultWriteObject) aoqi@0: inputClassFields(null, null, null, fvd.members, sender); aoqi@0: aoqi@0: if (getStreamFormatVersion() == 2) { aoqi@0: aoqi@0: ((ValueInputStream)getOrbStream()).start_value(); aoqi@0: ((ValueInputStream)getOrbStream()).end_value(); aoqi@0: } aoqi@0: aoqi@0: // WARNING: If stream format version is 1 and there's aoqi@0: // optional data, we'll get some form of exception down aoqi@0: // the line or data corruption. aoqi@0: aoqi@0: } else { aoqi@0: aoqi@0: inputClassFields(null, currentClass, null, fvd.members, sender); aoqi@0: } aoqi@0: aoqi@0: if (fvdsList.hasMoreElements()){ aoqi@0: fvd = (FullValueDescription)fvdsList.nextElement(); aoqi@0: repIDForFVD = vhandler.getClassName(fvd.id); aoqi@0: } aoqi@0: else return currentObject; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass); aoqi@0: aoqi@0: if (!repIDForClass.equals("java.lang.Object")) { aoqi@0: aoqi@0: // If the sender used custom marshaling, then it should have put aoqi@0: // the two bytes on the wire indicating stream format version aoqi@0: // and whether or not the writeObject method called aoqi@0: // defaultWriteObject/writeFields. aoqi@0: aoqi@0: ReadObjectState oldState = readObjectState; aoqi@0: setState(DEFAULT_STATE); aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: if (fvd.is_custom) { aoqi@0: aoqi@0: // Read format version aoqi@0: readFormatVersion(); aoqi@0: aoqi@0: // Read defaultWriteObject indicator aoqi@0: boolean calledDefaultWriteObject = readBoolean(); aoqi@0: aoqi@0: readObjectState.beginUnmarshalCustomValue(this, aoqi@0: calledDefaultWriteObject, aoqi@0: (currentClassDesc.readObjectMethod aoqi@0: != null)); aoqi@0: } aoqi@0: aoqi@0: boolean usedReadObject = false; aoqi@0: aoqi@0: // Always use readObject if it exists, and fall back to default aoqi@0: // unmarshaling if it doesn't. aoqi@0: try { aoqi@0: aoqi@0: if (!fvd.is_custom && currentClassDesc.hasReadObject()) aoqi@0: setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); aoqi@0: aoqi@0: // See the definition of defaultReadObjectFVDMembers aoqi@0: // for more information. This concerns making sure aoqi@0: // we use the remote FVD's members in defaultReadObject. aoqi@0: defaultReadObjectFVDMembers = fvd.members; aoqi@0: usedReadObject = invokeObjectReader(currentClassDesc, aoqi@0: currentObject, aoqi@0: currentClass); aoqi@0: aoqi@0: } finally { aoqi@0: defaultReadObjectFVDMembers = null; aoqi@0: } aoqi@0: aoqi@0: // Note that the !usedReadObject !calledDefaultWriteObject aoqi@0: // case is handled by the beginUnmarshalCustomValue method aoqi@0: // of the default state aoqi@0: if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) aoqi@0: inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender); aoqi@0: aoqi@0: if (fvd.is_custom) aoqi@0: readObjectState.endUnmarshalCustomValue(this); aoqi@0: aoqi@0: } finally { aoqi@0: setState(oldState); aoqi@0: } aoqi@0: aoqi@0: currclass = currentClass = classes[--spClass]; aoqi@0: aoqi@0: } else { aoqi@0: aoqi@0: // The remaining hierarchy of the local class does not match the sender's FVD. aoqi@0: // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate aoqi@0: // custom marshaling, throw MARSHAL error. aoqi@0: inputClassFields(null, currentClass, null, fvd.members, sender); aoqi@0: aoqi@0: while (fvdsList.hasMoreElements()){ aoqi@0: fvd = (FullValueDescription)fvdsList.nextElement(); aoqi@0: aoqi@0: if (fvd.is_custom) aoqi@0: skipCustomUsingFVD(fvd.members, sender); aoqi@0: else aoqi@0: inputClassFields(null, currentClass, null, fvd.members, sender); aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: } // end : while(fvdsList.hasMoreElements()) aoqi@0: while (fvdsList.hasMoreElements()){ aoqi@0: aoqi@0: FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); aoqi@0: if (fvd.is_custom) aoqi@0: skipCustomUsingFVD(fvd.members, sender); aoqi@0: else aoqi@0: throwAwayData(fvd.members, sender); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return currentObject; aoqi@0: } aoqi@0: finally { aoqi@0: // Make sure we exit at the same stack level as when we started. aoqi@0: spClass = spBase; aoqi@0: aoqi@0: // We've completed deserializing this object. Any aoqi@0: // future indirections will be handled correctly at the aoqi@0: // CDR level. The ActiveRecursionManager only deals with aoqi@0: // objects currently being deserialized. aoqi@0: activeRecursionMgr.removeObject(offset); aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * This input method uses FullValueDescriptions retrieved from the sender's runtime to aoqi@0: * read in the data. This method is capable of throwing out data not applicable to client's fields. aoqi@0: * aoqi@0: * NOTE : If the local description indicates custom marshaling and the remote type's FVD also aoqi@0: * indicates custom marsahling than the local type is used to read the data off the wire. However, aoqi@0: * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is aoqi@0: * a form of custom marshaling. aoqi@0: * aoqi@0: */ aoqi@0: private Object skipObjectUsingFVD(String repositoryID, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender) aoqi@0: throws IOException, ClassNotFoundException aoqi@0: { aoqi@0: aoqi@0: Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements(); aoqi@0: aoqi@0: while(fvdsList.hasMoreElements()) { aoqi@0: FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement(); aoqi@0: String repIDForFVD = vhandler.getClassName(fvd.id); aoqi@0: aoqi@0: if (!repIDForFVD.equals("java.lang.Object")) { aoqi@0: if (fvd.is_custom) { aoqi@0: aoqi@0: readFormatVersion(); aoqi@0: aoqi@0: boolean calledDefaultWriteObject = readBoolean(); aoqi@0: aoqi@0: if (calledDefaultWriteObject) aoqi@0: inputClassFields(null, null, null, fvd.members, sender); aoqi@0: aoqi@0: if (getStreamFormatVersion() == 2) { aoqi@0: aoqi@0: ((ValueInputStream)getOrbStream()).start_value(); aoqi@0: ((ValueInputStream)getOrbStream()).end_value(); aoqi@0: } aoqi@0: aoqi@0: // WARNING: If stream format version is 1 and there's aoqi@0: // optional data, we'll get some form of exception down aoqi@0: // the line. aoqi@0: aoqi@0: } else { aoqi@0: // Use default marshaling aoqi@0: inputClassFields(null, null, null, fvd.members, sender); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: } // end : while(fvdsList.hasMoreElements()) aoqi@0: return null; aoqi@0: aoqi@0: } aoqi@0: aoqi@0: /////////////////// aoqi@0: aoqi@0: private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){ aoqi@0: aoqi@0: for (int i = _spClass; i > _spBase; i--){ aoqi@0: if (classname.equals(classes[i].getName())) { aoqi@0: return i; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return -1; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Invoke the readObject method if present. Assumes that in the case of custom aoqi@0: * marshaling, the format version and defaultWriteObject indicator were already aoqi@0: * removed. aoqi@0: */ aoqi@0: private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass) aoqi@0: throws InvalidClassException, StreamCorruptedException, aoqi@0: ClassNotFoundException, IOException aoqi@0: { aoqi@0: if (osc.readObjectMethod == null) { aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: try { aoqi@0: osc.readObjectMethod.invoke( obj, readObjectArgList ) ; aoqi@0: return true; aoqi@0: } catch (InvocationTargetException e) { aoqi@0: Throwable t = e.getTargetException(); aoqi@0: if (t instanceof ClassNotFoundException) aoqi@0: throw (ClassNotFoundException)t; aoqi@0: else if (t instanceof IOException) aoqi@0: throw (IOException)t; aoqi@0: else if (t instanceof RuntimeException) aoqi@0: throw (RuntimeException) t; aoqi@0: else if (t instanceof Error) aoqi@0: throw (Error) t; aoqi@0: else aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new Error("internal error"); aoqi@0: } catch (IllegalAccessException e) { aoqi@0: return false; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Reset the stream to be just like it was after the constructor. aoqi@0: */ aoqi@0: private void resetStream() throws IOException { aoqi@0: aoqi@0: if (classes == null) aoqi@0: classes = new Class[20]; aoqi@0: else { aoqi@0: for (int i = 0; i < classes.length; i++) aoqi@0: classes[i] = null; aoqi@0: } aoqi@0: if (classdesc == null) aoqi@0: classdesc = new ObjectStreamClass[20]; aoqi@0: else { aoqi@0: for (int i = 0; i < classdesc.length; i++) aoqi@0: classdesc[i] = null; aoqi@0: } aoqi@0: spClass = 0; aoqi@0: aoqi@0: if (callbacks != null) aoqi@0: callbacks.setSize(0); // discard any pending callbacks aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Factored out of inputClassFields This reads a primitive value and sets it aoqi@0: * in the field of o described by the ObjectStreamField field. aoqi@0: * aoqi@0: * Note that reflection cannot be used here, because reflection cannot be used aoqi@0: * to set final fields. aoqi@0: */ aoqi@0: private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field) aoqi@0: throws InvalidClassException, IOException { aoqi@0: aoqi@0: try { aoqi@0: switch (field.getTypeCode()) { aoqi@0: case 'B': aoqi@0: byte byteValue = orbStream.read_octet(); msheppar@940: if (field.getField() != null) { msheppar@940: bridge.putByte( o, field.getFieldID(), byteValue ) ; msheppar@940: //reflective code: field.getField().setByte( o, byteValue ) ; msheppar@940: } aoqi@0: break; aoqi@0: case 'Z': aoqi@0: boolean booleanValue = orbStream.read_boolean(); msheppar@940: if (field.getField() != null) { msheppar@940: bridge.putBoolean( o, field.getFieldID(), booleanValue ) ; msheppar@940: //reflective code: field.getField().setBoolean( o, booleanValue ) ; msheppar@940: } aoqi@0: break; aoqi@0: case 'C': aoqi@0: char charValue = orbStream.read_wchar(); msheppar@940: if (field.getField() != null) { msheppar@940: bridge.putChar( o, field.getFieldID(), charValue ) ; msheppar@940: //reflective code: field.getField().setChar( o, charValue ) ; msheppar@940: } aoqi@0: break; aoqi@0: case 'S': aoqi@0: short shortValue = orbStream.read_short(); msheppar@940: if (field.getField() != null) { msheppar@940: bridge.putShort( o, field.getFieldID(), shortValue ) ; msheppar@940: //reflective code: field.getField().setShort( o, shortValue ) ; msheppar@940: } aoqi@0: break; aoqi@0: case 'I': aoqi@0: int intValue = orbStream.read_long(); msheppar@940: if (field.getField() != null) { msheppar@940: bridge.putInt( o, field.getFieldID(), intValue ) ; msheppar@940: //reflective code: field.getField().setInt( o, intValue ) ; msheppar@940: } aoqi@0: break; aoqi@0: case 'J': aoqi@0: long longValue = orbStream.read_longlong(); msheppar@940: if (field.getField() != null) { msheppar@940: bridge.putLong( o, field.getFieldID(), longValue ) ; msheppar@940: //reflective code: field.getField().setLong( o, longValue ) ; msheppar@940: } aoqi@0: break; aoqi@0: case 'F' : aoqi@0: float floatValue = orbStream.read_float(); msheppar@940: if (field.getField() != null) { msheppar@940: bridge.putFloat( o, field.getFieldID(), floatValue ) ; msheppar@940: //reflective code: field.getField().setFloat( o, floatValue ) ; msheppar@940: } aoqi@0: break; aoqi@0: case 'D' : aoqi@0: double doubleValue = orbStream.read_double(); msheppar@940: if (field.getField() != null) { msheppar@940: bridge.putDouble( o, field.getFieldID(), doubleValue ) ; msheppar@940: //reflective code: field.getField().setDouble( o, doubleValue ) ; msheppar@940: } aoqi@0: break; aoqi@0: default: aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new InvalidClassException(cl.getName()); aoqi@0: } aoqi@0: } catch (IllegalArgumentException e) { aoqi@0: /* This case should never happen. If the field types aoqi@0: are not the same, InvalidClassException is raised when aoqi@0: matching the local class to the serialized ObjectStreamClass. */ aoqi@0: ClassCastException cce = new ClassCastException("Assigning instance of class " + aoqi@0: field.getType().getName() + aoqi@0: " to field " + aoqi@0: currentClassDesc.getName() + '#' + aoqi@0: field.getField().getName()); aoqi@0: cce.initCause( e ) ; aoqi@0: throw cce ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private Object inputObjectField(org.omg.CORBA.ValueMember field, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender) aoqi@0: throws IndirectionException, ClassNotFoundException, IOException, aoqi@0: StreamCorruptedException { aoqi@0: aoqi@0: Object objectValue = null; aoqi@0: Class type = null; aoqi@0: String id = field.id; aoqi@0: aoqi@0: try { aoqi@0: type = vhandler.getClassFromType(id); aoqi@0: } catch(ClassNotFoundException cnfe) { aoqi@0: // Make sure type = null aoqi@0: type = null; aoqi@0: } aoqi@0: aoqi@0: String signature = null; aoqi@0: if (type != null) aoqi@0: signature = ValueUtility.getSignature(field); aoqi@0: aoqi@0: if (signature != null && (signature.equals("Ljava/lang/Object;") || aoqi@0: signature.equals("Ljava/io/Serializable;") || aoqi@0: signature.equals("Ljava/io/Externalizable;"))) { aoqi@0: objectValue = javax.rmi.CORBA.Util.readAny(orbStream); aoqi@0: } else { aoqi@0: // Decide what method call to make based on the type. If aoqi@0: // it is a type for which we need to load a stub, convert aoqi@0: // the type to the correct stub type. aoqi@0: // aoqi@0: // NOTE : Since FullValueDescription does not allow us aoqi@0: // to ask whether something is an interface we do not aoqi@0: // have the ability to optimize this check. aoqi@0: aoqi@0: int callType = ValueHandlerImpl.kValueType; aoqi@0: aoqi@0: if (!vhandler.isSequence(id)) { aoqi@0: aoqi@0: if (field.type.kind().value() == kRemoteTypeCode.kind().value()) { aoqi@0: aoqi@0: // RMI Object reference... aoqi@0: callType = ValueHandlerImpl.kRemoteType; aoqi@0: aoqi@0: } else { aoqi@0: aoqi@0: // REVISIT. If we don't have the local class, aoqi@0: // we should probably verify that it's an RMI type, aoqi@0: // query the remote FVD, and use is_abstract. aoqi@0: // Our FVD seems to get NullPointerExceptions for any aoqi@0: // non-RMI types. aoqi@0: aoqi@0: // This uses the local class in the same way as aoqi@0: // inputObjectField(ObjectStreamField) does. REVISIT aoqi@0: // inputObjectField(ObjectStreamField)'s loadStubClass aoqi@0: // logic. Assumption is that the given type cannot aoqi@0: // evolve to become a CORBA abstract interface or aoqi@0: // a RMI abstract interface. aoqi@0: aoqi@0: if (type != null && type.isInterface() && aoqi@0: (vhandler.isAbstractBase(type) || aoqi@0: ObjectStreamClassCorbaExt.isAbstractInterface(type))) { aoqi@0: aoqi@0: callType = ValueHandlerImpl.kAbstractType; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Now that we have used the FVD of the field to determine the proper course aoqi@0: // of action, it is ok to use the type (Class) from this point forward since aoqi@0: // the rep. id for this read will also follow on the wire. aoqi@0: aoqi@0: switch (callType) { aoqi@0: case ValueHandlerImpl.kRemoteType: aoqi@0: if (type != null) aoqi@0: objectValue = Utility.readObjectAndNarrow(orbStream, type); aoqi@0: else aoqi@0: objectValue = orbStream.read_Object(); aoqi@0: break; aoqi@0: case ValueHandlerImpl.kAbstractType: aoqi@0: if (type != null) aoqi@0: objectValue = Utility.readAbstractAndNarrow(orbStream, type); aoqi@0: else aoqi@0: objectValue = orbStream.read_abstract_interface(); aoqi@0: break; aoqi@0: case ValueHandlerImpl.kValueType: aoqi@0: if (type != null) aoqi@0: objectValue = orbStream.read_value(type); aoqi@0: else aoqi@0: objectValue = orbStream.read_value(); aoqi@0: break; aoqi@0: default: aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new StreamCorruptedException("Unknown callType: " + callType); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return objectValue; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Factored out of inputClassFields and reused in aoqi@0: * inputCurrentClassFieldsForReadFields. aoqi@0: * aoqi@0: * Reads the field (which of an Object type as opposed to a primitive) aoqi@0: * described by ObjectStreamField field and returns it. aoqi@0: */ aoqi@0: private Object inputObjectField(ObjectStreamField field) aoqi@0: throws InvalidClassException, StreamCorruptedException, aoqi@0: ClassNotFoundException, IndirectionException, IOException { aoqi@0: aoqi@0: if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) { aoqi@0: return javax.rmi.CORBA.Util.readAny(orbStream); aoqi@0: } aoqi@0: aoqi@0: Object objectValue = null; aoqi@0: aoqi@0: // fields have an API to provide the actual class aoqi@0: // corresponding to the data type aoqi@0: // Class type = osc.forClass(); aoqi@0: Class fieldType = field.getType(); aoqi@0: Class actualType = fieldType; // This may change if stub loaded. aoqi@0: aoqi@0: // Decide what method call to make based on the fieldType. If aoqi@0: // it is a type for which we need to load a stub, convert aoqi@0: // the type to the correct stub type. aoqi@0: aoqi@0: int callType = ValueHandlerImpl.kValueType; aoqi@0: boolean narrow = false; aoqi@0: aoqi@0: if (fieldType.isInterface()) { aoqi@0: boolean loadStubClass = false; aoqi@0: aoqi@0: if (java.rmi.Remote.class.isAssignableFrom(fieldType)) { aoqi@0: aoqi@0: // RMI Object reference... aoqi@0: callType = ValueHandlerImpl.kRemoteType; aoqi@0: aoqi@0: } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){ aoqi@0: aoqi@0: // IDL Object reference... aoqi@0: callType = ValueHandlerImpl.kRemoteType; aoqi@0: loadStubClass = true; aoqi@0: aoqi@0: } else if (vhandler.isAbstractBase(fieldType)) { aoqi@0: // IDL Abstract Object reference... aoqi@0: aoqi@0: callType = ValueHandlerImpl.kAbstractType; aoqi@0: loadStubClass = true; aoqi@0: } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) { aoqi@0: // RMI Abstract Object reference... aoqi@0: aoqi@0: callType = ValueHandlerImpl.kAbstractType; aoqi@0: } aoqi@0: aoqi@0: if (loadStubClass) { aoqi@0: try { aoqi@0: String codebase = Util.getCodebase(fieldType); aoqi@0: String repID = vhandler.createForAnyType(fieldType); aoqi@0: Class stubType = aoqi@0: Utility.loadStubClass(repID, codebase, fieldType); aoqi@0: actualType = stubType; aoqi@0: } catch (ClassNotFoundException e) { aoqi@0: narrow = true; aoqi@0: } aoqi@0: } else { aoqi@0: narrow = true; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: switch (callType) { aoqi@0: case ValueHandlerImpl.kRemoteType: aoqi@0: if (!narrow) aoqi@0: objectValue = (Object)orbStream.read_Object(actualType); aoqi@0: else aoqi@0: objectValue = Utility.readObjectAndNarrow(orbStream, actualType); aoqi@0: break; aoqi@0: case ValueHandlerImpl.kAbstractType: aoqi@0: if (!narrow) aoqi@0: objectValue = (Object)orbStream.read_abstract_interface(actualType); aoqi@0: else aoqi@0: objectValue = Utility.readAbstractAndNarrow(orbStream, actualType); aoqi@0: break; aoqi@0: case ValueHandlerImpl.kValueType: aoqi@0: objectValue = (Object)orbStream.read_value(actualType); aoqi@0: break; aoqi@0: default: aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new StreamCorruptedException("Unknown callType: " + callType); aoqi@0: } aoqi@0: aoqi@0: return objectValue; aoqi@0: } aoqi@0: aoqi@0: private final boolean mustUseRemoteValueMembers() { aoqi@0: return defaultReadObjectFVDMembers != null; aoqi@0: } aoqi@0: aoqi@0: void readFields(java.util.Map fieldToValueMap) aoqi@0: throws InvalidClassException, StreamCorruptedException, aoqi@0: ClassNotFoundException, IOException { aoqi@0: aoqi@0: if (mustUseRemoteValueMembers()) { aoqi@0: inputRemoteMembersForReadFields(fieldToValueMap); aoqi@0: } else aoqi@0: inputCurrentClassFieldsForReadFields(fieldToValueMap); aoqi@0: } aoqi@0: aoqi@0: private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap) aoqi@0: throws InvalidClassException, StreamCorruptedException, aoqi@0: ClassNotFoundException, IOException { aoqi@0: aoqi@0: // Must have this local variable since defaultReadObjectFVDMembers aoqi@0: // may get mangled by recursion. aoqi@0: ValueMember fields[] = defaultReadObjectFVDMembers; aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: for (int i = 0; i < fields.length; i++) { aoqi@0: aoqi@0: switch (fields[i].type.kind().value()) { aoqi@0: aoqi@0: case TCKind._tk_octet: aoqi@0: byte byteValue = orbStream.read_octet(); aoqi@0: fieldToValueMap.put(fields[i].name, new Byte(byteValue)); aoqi@0: break; aoqi@0: case TCKind._tk_boolean: aoqi@0: boolean booleanValue = orbStream.read_boolean(); aoqi@0: fieldToValueMap.put(fields[i].name, new Boolean(booleanValue)); aoqi@0: break; aoqi@0: case TCKind._tk_char: aoqi@0: // Backwards compatibility. Older Sun ORBs sent aoqi@0: // _tk_char even though they read and wrote wchars aoqi@0: // correctly. aoqi@0: // aoqi@0: // Fall through to the _tk_wchar case. aoqi@0: case TCKind._tk_wchar: aoqi@0: char charValue = orbStream.read_wchar(); aoqi@0: fieldToValueMap.put(fields[i].name, new Character(charValue)); aoqi@0: break; aoqi@0: case TCKind._tk_short: aoqi@0: short shortValue = orbStream.read_short(); aoqi@0: fieldToValueMap.put(fields[i].name, new Short(shortValue)); aoqi@0: break; aoqi@0: case TCKind._tk_long: aoqi@0: int intValue = orbStream.read_long(); aoqi@0: fieldToValueMap.put(fields[i].name, new Integer(intValue)); aoqi@0: break; aoqi@0: case TCKind._tk_longlong: aoqi@0: long longValue = orbStream.read_longlong(); aoqi@0: fieldToValueMap.put(fields[i].name, new Long(longValue)); aoqi@0: break; aoqi@0: case TCKind._tk_float: aoqi@0: float floatValue = orbStream.read_float(); aoqi@0: fieldToValueMap.put(fields[i].name, new Float(floatValue)); aoqi@0: break; aoqi@0: case TCKind._tk_double: aoqi@0: double doubleValue = orbStream.read_double(); aoqi@0: fieldToValueMap.put(fields[i].name, new Double(doubleValue)); aoqi@0: break; aoqi@0: case TCKind._tk_value: aoqi@0: case TCKind._tk_objref: aoqi@0: case TCKind._tk_value_box: aoqi@0: Object objectValue = null; aoqi@0: try { aoqi@0: objectValue = inputObjectField(fields[i], aoqi@0: cbSender); aoqi@0: aoqi@0: } catch (IndirectionException cdrie) { aoqi@0: // The CDR stream had never seen the given offset before, aoqi@0: // so check the recursion manager (it will throw an aoqi@0: // IOException if it doesn't have a reference, either). aoqi@0: objectValue = activeRecursionMgr.getObject(cdrie.offset); aoqi@0: } aoqi@0: aoqi@0: fieldToValueMap.put(fields[i].name, objectValue); aoqi@0: break; aoqi@0: default: aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new StreamCorruptedException("Unknown kind: " aoqi@0: + fields[i].type.kind().value()); aoqi@0: } aoqi@0: } aoqi@0: } catch (Throwable t) { aoqi@0: StreamCorruptedException result = new StreamCorruptedException(t.getMessage()); aoqi@0: result.initCause(t); aoqi@0: throw result; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Called from InputStreamHook. aoqi@0: * aoqi@0: * Reads the fields of the current class (could be the ones aoqi@0: * queried from the remote FVD) and puts them in aoqi@0: * the given Map, name to value. Wraps primitives in the aoqi@0: * corresponding java.lang Objects. aoqi@0: */ aoqi@0: private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap) aoqi@0: throws InvalidClassException, StreamCorruptedException, aoqi@0: ClassNotFoundException, IOException { aoqi@0: aoqi@0: ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy(); aoqi@0: aoqi@0: int primFields = fields.length - currentClassDesc.objFields; aoqi@0: aoqi@0: // Handle the primitives first aoqi@0: for (int i = 0; i < primFields; ++i) { aoqi@0: aoqi@0: switch (fields[i].getTypeCode()) { aoqi@0: case 'B': aoqi@0: byte byteValue = orbStream.read_octet(); aoqi@0: fieldToValueMap.put(fields[i].getName(), aoqi@0: new Byte(byteValue)); aoqi@0: break; aoqi@0: case 'Z': aoqi@0: boolean booleanValue = orbStream.read_boolean(); aoqi@0: fieldToValueMap.put(fields[i].getName(), aoqi@0: new Boolean(booleanValue)); aoqi@0: break; aoqi@0: case 'C': aoqi@0: char charValue = orbStream.read_wchar(); aoqi@0: fieldToValueMap.put(fields[i].getName(), aoqi@0: new Character(charValue)); aoqi@0: break; aoqi@0: case 'S': aoqi@0: short shortValue = orbStream.read_short(); aoqi@0: fieldToValueMap.put(fields[i].getName(), aoqi@0: new Short(shortValue)); aoqi@0: break; aoqi@0: case 'I': aoqi@0: int intValue = orbStream.read_long(); aoqi@0: fieldToValueMap.put(fields[i].getName(), aoqi@0: new Integer(intValue)); aoqi@0: break; aoqi@0: case 'J': aoqi@0: long longValue = orbStream.read_longlong(); aoqi@0: fieldToValueMap.put(fields[i].getName(), aoqi@0: new Long(longValue)); aoqi@0: break; aoqi@0: case 'F' : aoqi@0: float floatValue = orbStream.read_float(); aoqi@0: fieldToValueMap.put(fields[i].getName(), aoqi@0: new Float(floatValue)); aoqi@0: break; aoqi@0: case 'D' : aoqi@0: double doubleValue = orbStream.read_double(); aoqi@0: fieldToValueMap.put(fields[i].getName(), aoqi@0: new Double(doubleValue)); aoqi@0: break; aoqi@0: default: aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new InvalidClassException(currentClassDesc.getName()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* Read and set object fields from the input stream. */ aoqi@0: if (currentClassDesc.objFields > 0) { aoqi@0: for (int i = primFields; i < fields.length; i++) { aoqi@0: Object objectValue = null; aoqi@0: try { aoqi@0: objectValue = inputObjectField(fields[i]); aoqi@0: } catch(IndirectionException cdrie) { aoqi@0: // The CDR stream had never seen the given offset before, aoqi@0: // so check the recursion manager (it will throw an aoqi@0: // IOException if it doesn't have a reference, either). aoqi@0: objectValue = activeRecursionMgr.getObject(cdrie.offset); aoqi@0: } aoqi@0: aoqi@0: fieldToValueMap.put(fields[i].getName(), objectValue); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Read the fields of the specified class from the input stream and set aoqi@0: * the values of the fields in the specified object. If the specified aoqi@0: * object is null, just consume the fields without setting any values. If aoqi@0: * any ObjectStreamField does not have a reflected Field, don't try to set aoqi@0: * that field in the object. aoqi@0: * aoqi@0: * REVISIT -- This code doesn't do what the comment says to when aoqi@0: * getField() is null! aoqi@0: */ aoqi@0: private void inputClassFields(Object o, Class cl, aoqi@0: ObjectStreamField[] fields, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender) aoqi@0: throws InvalidClassException, StreamCorruptedException, aoqi@0: ClassNotFoundException, IOException aoqi@0: { aoqi@0: aoqi@0: int primFields = fields.length - currentClassDesc.objFields; aoqi@0: aoqi@0: if (o != null) { aoqi@0: for (int i = 0; i < primFields; ++i) { aoqi@0: inputPrimitiveField(o, cl, fields[i]); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* Read and set object fields from the input stream. */ aoqi@0: if (currentClassDesc.objFields > 0) { aoqi@0: for (int i = primFields; i < fields.length; i++) { aoqi@0: Object objectValue = null; aoqi@0: aoqi@0: try { aoqi@0: objectValue = inputObjectField(fields[i]); aoqi@0: } catch(IndirectionException cdrie) { aoqi@0: // The CDR stream had never seen the given offset before, aoqi@0: // so check the recursion manager (it will throw an aoqi@0: // IOException if it doesn't have a reference, either). aoqi@0: objectValue = activeRecursionMgr.getObject(cdrie.offset); aoqi@0: } aoqi@0: aoqi@0: if ((o == null) || (fields[i].getField() == null)) { aoqi@0: continue; aoqi@0: } aoqi@0: aoqi@0: try { aoqi@0: Class fieldCl = fields[i].getClazz(); aoqi@0: if (objectValue != null && !fieldCl.isInstance(objectValue)) { aoqi@0: throw new IllegalArgumentException(); aoqi@0: } aoqi@0: bridge.putObject( o, fields[i].getFieldID(), objectValue ) ; aoqi@0: // reflective code: fields[i].getField().set( o, objectValue ) ; aoqi@0: } catch (IllegalArgumentException e) { aoqi@0: ClassCastException exc = new ClassCastException("Assigning instance of class " + aoqi@0: objectValue.getClass().getName() + aoqi@0: " to field " + aoqi@0: currentClassDesc.getName() + aoqi@0: '#' + aoqi@0: fields[i].getField().getName()); aoqi@0: exc.initCause( e ) ; aoqi@0: throw exc ; aoqi@0: } aoqi@0: } // end : for loop aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Read the fields of the specified class from the input stream and set aoqi@0: * the values of the fields in the specified object. If the specified aoqi@0: * object is null, just consume the fields without setting any values. If aoqi@0: * any ObjectStreamField does not have a reflected Field, don't try to set aoqi@0: * that field in the object. aoqi@0: */ aoqi@0: private void inputClassFields(Object o, Class cl, aoqi@0: ObjectStreamClass osc, aoqi@0: ValueMember[] fields, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender) aoqi@0: throws InvalidClassException, StreamCorruptedException, aoqi@0: ClassNotFoundException, IOException aoqi@0: { aoqi@0: try{ aoqi@0: for (int i = 0; i < fields.length; ++i) { aoqi@0: try { aoqi@0: switch (fields[i].type.kind().value()) { aoqi@0: case TCKind._tk_octet: aoqi@0: byte byteValue = orbStream.read_octet(); aoqi@0: if ((o != null) && osc.hasField(fields[i])) aoqi@0: setByteField(o, cl, fields[i].name, byteValue); aoqi@0: break; aoqi@0: case TCKind._tk_boolean: aoqi@0: boolean booleanValue = orbStream.read_boolean(); aoqi@0: if ((o != null) && osc.hasField(fields[i])) aoqi@0: setBooleanField(o, cl, fields[i].name, booleanValue); aoqi@0: break; aoqi@0: case TCKind._tk_char: aoqi@0: // Backwards compatibility. Older Sun ORBs sent aoqi@0: // _tk_char even though they read and wrote wchars aoqi@0: // correctly. aoqi@0: // aoqi@0: // Fall through to the _tk_wchar case. aoqi@0: case TCKind._tk_wchar: aoqi@0: char charValue = orbStream.read_wchar(); aoqi@0: if ((o != null) && osc.hasField(fields[i])) aoqi@0: setCharField(o, cl, fields[i].name, charValue); aoqi@0: break; aoqi@0: case TCKind._tk_short: aoqi@0: short shortValue = orbStream.read_short(); aoqi@0: if ((o != null) && osc.hasField(fields[i])) aoqi@0: setShortField(o, cl, fields[i].name, shortValue); aoqi@0: break; aoqi@0: case TCKind._tk_long: aoqi@0: int intValue = orbStream.read_long(); aoqi@0: if ((o != null) && osc.hasField(fields[i])) aoqi@0: setIntField(o, cl, fields[i].name, intValue); aoqi@0: break; aoqi@0: case TCKind._tk_longlong: aoqi@0: long longValue = orbStream.read_longlong(); aoqi@0: if ((o != null) && osc.hasField(fields[i])) aoqi@0: setLongField(o, cl, fields[i].name, longValue); aoqi@0: break; aoqi@0: case TCKind._tk_float: aoqi@0: float floatValue = orbStream.read_float(); aoqi@0: if ((o != null) && osc.hasField(fields[i])) aoqi@0: setFloatField(o, cl, fields[i].name, floatValue); aoqi@0: break; aoqi@0: case TCKind._tk_double: aoqi@0: double doubleValue = orbStream.read_double(); aoqi@0: if ((o != null) && osc.hasField(fields[i])) aoqi@0: setDoubleField(o, cl, fields[i].name, doubleValue); aoqi@0: break; aoqi@0: case TCKind._tk_value: aoqi@0: case TCKind._tk_objref: aoqi@0: case TCKind._tk_value_box: aoqi@0: Object objectValue = null; aoqi@0: try { aoqi@0: objectValue = inputObjectField(fields[i], sender); aoqi@0: } catch (IndirectionException cdrie) { aoqi@0: // The CDR stream had never seen the given offset before, aoqi@0: // so check the recursion manager (it will throw an aoqi@0: // IOException if it doesn't have a reference, either). aoqi@0: objectValue = activeRecursionMgr.getObject(cdrie.offset); aoqi@0: } aoqi@0: aoqi@0: if (o == null) aoqi@0: continue; aoqi@0: try { aoqi@0: if (osc.hasField(fields[i])){ aoqi@0: setObjectField(o, aoqi@0: cl, aoqi@0: fields[i].name, aoqi@0: objectValue); aoqi@0: } else { aoqi@0: // REVISIT. Convert to a log message. aoqi@0: // This is a normal case when fields have aoqi@0: // been added as part of evolution, but aoqi@0: // silently skipping can make it hard to aoqi@0: // debug if there's an error aoqi@0: // System.out.println("**** warning, not setting field: " aoqi@0: // + fields[i].name aoqi@0: // + " since not on class " aoqi@0: // + osc.getName()); aoqi@0: aoqi@0: } aoqi@0: } catch (IllegalArgumentException e) { aoqi@0: // XXX I18N, logging needed. aoqi@0: ClassCastException cce = new ClassCastException("Assigning instance of class " + aoqi@0: objectValue.getClass().getName() + " to field " + fields[i].name); aoqi@0: cce.initCause(e) ; aoqi@0: throw cce ; aoqi@0: } aoqi@0: break; aoqi@0: default: aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new StreamCorruptedException("Unknown kind: " aoqi@0: + fields[i].type.kind().value()); aoqi@0: } aoqi@0: } catch (IllegalArgumentException e) { aoqi@0: /* This case should never happen. If the field types aoqi@0: are not the same, InvalidClassException is raised when aoqi@0: matching the local class to the serialized ObjectStreamClass. */ aoqi@0: // XXX I18N, logging needed. aoqi@0: ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id + aoqi@0: " to field " + currentClassDesc.getName() + '#' + fields[i].name); aoqi@0: cce.initCause( e ) ; aoqi@0: throw cce ; aoqi@0: } aoqi@0: } aoqi@0: } catch(Throwable t){ aoqi@0: // XXX I18N, logging needed. aoqi@0: StreamCorruptedException sce = new StreamCorruptedException(t.getMessage()); aoqi@0: sce.initCause(t) ; aoqi@0: throw sce ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void skipCustomUsingFVD(ValueMember[] fields, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender) aoqi@0: throws InvalidClassException, StreamCorruptedException, aoqi@0: ClassNotFoundException, IOException aoqi@0: { aoqi@0: readFormatVersion(); aoqi@0: boolean calledDefaultWriteObject = readBoolean(); aoqi@0: aoqi@0: if (calledDefaultWriteObject) aoqi@0: throwAwayData(fields, sender); aoqi@0: aoqi@0: if (getStreamFormatVersion() == 2) { aoqi@0: aoqi@0: ((ValueInputStream)getOrbStream()).start_value(); aoqi@0: ((ValueInputStream)getOrbStream()).end_value(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Read the fields of the specified class from the input stream throw data away. aoqi@0: * This must handle same switch logic as above. aoqi@0: */ aoqi@0: private void throwAwayData(ValueMember[] fields, aoqi@0: com.sun.org.omg.SendingContext.CodeBase sender) aoqi@0: throws InvalidClassException, StreamCorruptedException, msheppar@984: ClassNotFoundException, IOException { msheppar@984: aoqi@0: for (int i = 0; i < fields.length; ++i) { aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: switch (fields[i].type.kind().value()) { aoqi@0: case TCKind._tk_octet: aoqi@0: orbStream.read_octet(); aoqi@0: break; aoqi@0: case TCKind._tk_boolean: aoqi@0: orbStream.read_boolean(); aoqi@0: break; aoqi@0: case TCKind._tk_char: aoqi@0: // Backwards compatibility. Older Sun ORBs sent aoqi@0: // _tk_char even though they read and wrote wchars aoqi@0: // correctly. aoqi@0: // aoqi@0: // Fall through to the _tk_wchar case. aoqi@0: case TCKind._tk_wchar: aoqi@0: orbStream.read_wchar(); aoqi@0: break; aoqi@0: case TCKind._tk_short: aoqi@0: orbStream.read_short(); aoqi@0: break; aoqi@0: case TCKind._tk_long: aoqi@0: orbStream.read_long(); aoqi@0: break; aoqi@0: case TCKind._tk_longlong: aoqi@0: orbStream.read_longlong(); aoqi@0: break; aoqi@0: case TCKind._tk_float: aoqi@0: orbStream.read_float(); aoqi@0: break; aoqi@0: case TCKind._tk_double: aoqi@0: orbStream.read_double(); aoqi@0: break; aoqi@0: case TCKind._tk_value: aoqi@0: case TCKind._tk_objref: aoqi@0: case TCKind._tk_value_box: aoqi@0: Class type = null; aoqi@0: String id = fields[i].id; aoqi@0: aoqi@0: try { aoqi@0: type = vhandler.getClassFromType(id); aoqi@0: } aoqi@0: catch(ClassNotFoundException cnfe){ aoqi@0: // Make sure type = null aoqi@0: type = null; aoqi@0: } aoqi@0: String signature = null; aoqi@0: if (type != null) aoqi@0: signature = ValueUtility.getSignature(fields[i]); aoqi@0: aoqi@0: // Read value aoqi@0: try { aoqi@0: if ((signature != null) && ( signature.equals("Ljava/lang/Object;") || aoqi@0: signature.equals("Ljava/io/Serializable;") || aoqi@0: signature.equals("Ljava/io/Externalizable;")) ) { aoqi@0: javax.rmi.CORBA.Util.readAny(orbStream); aoqi@0: } aoqi@0: else { aoqi@0: // Decide what method call to make based on the type. aoqi@0: // aoqi@0: // NOTE : Since FullValueDescription does not allow us aoqi@0: // to ask whether something is an interface we do not aoqi@0: // have the ability to optimize this check. aoqi@0: aoqi@0: int callType = ValueHandlerImpl.kValueType; aoqi@0: aoqi@0: if (!vhandler.isSequence(id)) { aoqi@0: FullValueDescription fieldFVD = sender.meta(fields[i].id); aoqi@0: if (kRemoteTypeCode == fields[i].type) { aoqi@0: aoqi@0: // RMI Object reference... aoqi@0: callType = ValueHandlerImpl.kRemoteType; aoqi@0: } else if (fieldFVD.is_abstract) { aoqi@0: // RMI Abstract Object reference... aoqi@0: aoqi@0: callType = ValueHandlerImpl.kAbstractType; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Now that we have used the FVD of the field to determine the proper course aoqi@0: // of action, it is ok to use the type (Class) from this point forward since aoqi@0: // the rep. id for this read will also follow on the wire. aoqi@0: aoqi@0: switch (callType) { aoqi@0: case ValueHandlerImpl.kRemoteType: aoqi@0: orbStream.read_Object(); aoqi@0: break; aoqi@0: case ValueHandlerImpl.kAbstractType: aoqi@0: orbStream.read_abstract_interface(); aoqi@0: break; aoqi@0: case ValueHandlerImpl.kValueType: aoqi@0: if (type != null) { aoqi@0: orbStream.read_value(type); aoqi@0: } else { aoqi@0: orbStream.read_value(); aoqi@0: } aoqi@0: break; aoqi@0: default: aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new StreamCorruptedException("Unknown callType: " aoqi@0: + callType); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: catch(IndirectionException cdrie) { aoqi@0: // Since we are throwing this away, don't bother handling recursion. aoqi@0: continue; aoqi@0: } aoqi@0: aoqi@0: break; aoqi@0: default: aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new StreamCorruptedException("Unknown kind: " aoqi@0: + fields[i].type.kind().value()); aoqi@0: aoqi@0: } aoqi@0: } catch (IllegalArgumentException e) { aoqi@0: /* This case should never happen. If the field types aoqi@0: are not the same, InvalidClassException is raised when aoqi@0: matching the local class to the serialized ObjectStreamClass. */ aoqi@0: // XXX I18N, logging needed. aoqi@0: ClassCastException cce = new ClassCastException("Assigning instance of class " + aoqi@0: fields[i].id + " to field " + currentClassDesc.getName() + aoqi@0: '#' + fields[i].name); aoqi@0: cce.initCause(e) ; aoqi@0: throw cce ; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: msheppar@984: private static void setObjectField(Object o, Class c, String fieldName, Object v) { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; aoqi@0: Class fieldCl = fld.getType(); aoqi@0: if(v != null && !fieldCl.isInstance(v)) { aoqi@0: throw new Exception(); aoqi@0: } aoqi@0: long key = bridge.objectFieldOffset( fld ) ; aoqi@0: bridge.putObject( o, key, v ) ; aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { msheppar@984: throw utilWrapper.errorSetObjectField( e, fieldName, msheppar@984: o.toString(), msheppar@984: v.toString() ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetObjectField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: v.toString() ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static void setBooleanField(Object o, Class c, String fieldName, boolean v) aoqi@0: { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; msheppar@984: if ((fld != null) && (fld.getType() == Boolean.TYPE)) { msheppar@984: long key = bridge.objectFieldOffset( fld ) ; msheppar@984: bridge.putBoolean( o, key, v ) ; msheppar@984: } else { msheppar@984: throw new InvalidObjectException("Field Type mismatch"); msheppar@984: } aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { aoqi@0: throw utilWrapper.errorSetBooleanField( e, fieldName, aoqi@0: o.toString(), aoqi@0: new Boolean(v) ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetBooleanField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: new Boolean(v) ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static void setByteField(Object o, Class c, String fieldName, byte v) aoqi@0: { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; msheppar@984: if ((fld != null) && (fld.getType() == Byte.TYPE)) { msheppar@984: long key = bridge.objectFieldOffset( fld ) ; msheppar@984: bridge.putByte( o, key, v ) ; msheppar@984: } else { msheppar@984: throw new InvalidObjectException("Field Type mismatch"); msheppar@984: } aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { msheppar@984: throw utilWrapper.errorSetByteField( e, fieldName, msheppar@984: o.toString(), msheppar@984: new Byte(v) ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetByteField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: new Byte(v) ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static void setCharField(Object o, Class c, String fieldName, char v) aoqi@0: { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; msheppar@984: if ((fld != null) && (fld.getType() == Character.TYPE)) { msheppar@984: long key = bridge.objectFieldOffset( fld ) ; msheppar@984: bridge.putChar( o, key, v ) ; msheppar@984: } else { msheppar@984: throw new InvalidObjectException("Field Type mismatch"); msheppar@984: } aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { msheppar@984: throw utilWrapper.errorSetCharField( e, fieldName, msheppar@984: o.toString(), msheppar@984: new Character(v) ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetCharField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: new Character(v) ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static void setShortField(Object o, Class c, String fieldName, short v) aoqi@0: { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; msheppar@984: if ((fld != null) && (fld.getType() == Short.TYPE)) { msheppar@984: long key = bridge.objectFieldOffset( fld ) ; msheppar@984: bridge.putShort( o, key, v ) ; msheppar@984: } else { msheppar@984: throw new InvalidObjectException("Field Type mismatch"); msheppar@984: } aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { aoqi@0: throw utilWrapper.errorSetShortField( e, fieldName, aoqi@0: o.toString(), aoqi@0: new Short(v) ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetShortField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: new Short(v) ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static void setIntField(Object o, Class c, String fieldName, int v) aoqi@0: { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; msheppar@984: if ((fld != null) && (fld.getType() == Integer.TYPE)) { msheppar@984: long key = bridge.objectFieldOffset( fld ) ; msheppar@984: bridge.putInt( o, key, v ) ; msheppar@984: } else { msheppar@984: throw new InvalidObjectException("Field Type mismatch"); msheppar@984: } aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { msheppar@984: throw utilWrapper.errorSetIntField( e, fieldName, msheppar@984: o.toString(), msheppar@984: new Integer(v) ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetIntField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: new Integer(v) ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static void setLongField(Object o, Class c, String fieldName, long v) aoqi@0: { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; msheppar@984: if ((fld != null) && (fld.getType() == Long.TYPE)) { msheppar@984: long key = bridge.objectFieldOffset( fld ) ; msheppar@984: bridge.putLong( o, key, v ) ; msheppar@984: } else { msheppar@984: throw new InvalidObjectException("Field Type mismatch"); msheppar@984: } aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { msheppar@984: throw utilWrapper.errorSetLongField( e, fieldName, msheppar@984: o.toString(), msheppar@984: new Long(v) ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetLongField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: new Long(v) ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static void setFloatField(Object o, Class c, String fieldName, float v) aoqi@0: { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; msheppar@984: if ((fld != null) && (fld.getType() == Float.TYPE)) { msheppar@984: long key = bridge.objectFieldOffset( fld ) ; msheppar@984: bridge.putFloat( o, key, v ) ; msheppar@984: } else { msheppar@984: throw new InvalidObjectException("Field Type mismatch"); msheppar@984: } aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { msheppar@984: throw utilWrapper.errorSetFloatField( e, fieldName, msheppar@984: o.toString(), msheppar@984: new Float(v) ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetFloatField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: new Float(v) ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static void setDoubleField(Object o, Class c, String fieldName, double v) aoqi@0: { aoqi@0: try { aoqi@0: Field fld = c.getDeclaredField( fieldName ) ; msheppar@984: if ((fld != null) && (fld.getType() == Double.TYPE)) { msheppar@984: long key = bridge.objectFieldOffset( fld ) ; msheppar@984: bridge.putDouble( o, key, v ) ; msheppar@984: } else { msheppar@984: throw new InvalidObjectException("Field Type mismatch"); msheppar@984: } aoqi@0: } catch (Exception e) { msheppar@984: if (o != null) { msheppar@984: throw utilWrapper.errorSetDoubleField( e, fieldName, msheppar@984: o.toString(), msheppar@984: new Double(v) ) ; msheppar@984: } else { msheppar@984: throw utilWrapper.errorSetDoubleField( e, fieldName, msheppar@984: "null " + c.getName() + " object", msheppar@984: new Double(v) ) ; msheppar@984: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * This class maintains a map of stream position to aoqi@0: * an Object currently being deserialized. It is used aoqi@0: * to handle the cases where the are indirections to aoqi@0: * an object on the recursion stack. The CDR level aoqi@0: * handles indirections to objects previously seen aoqi@0: * (and completely deserialized) in the stream. aoqi@0: */ aoqi@0: static class ActiveRecursionManager aoqi@0: { aoqi@0: private Map offsetToObjectMap; aoqi@0: aoqi@0: public ActiveRecursionManager() { aoqi@0: // A hash map is unsynchronized and allows aoqi@0: // null values aoqi@0: offsetToObjectMap = new HashMap(); aoqi@0: } aoqi@0: aoqi@0: // Called right after allocating a new object. aoqi@0: // Offset is the starting position in the stream aoqi@0: // of the object. aoqi@0: public void addObject(int offset, Object value) { aoqi@0: offsetToObjectMap.put(new Integer(offset), value); aoqi@0: } aoqi@0: aoqi@0: // If the given starting position doesn't refer aoqi@0: // to the beginning of an object currently being aoqi@0: // deserialized, this throws an IOException. aoqi@0: // Otherwise, it returns a reference to the aoqi@0: // object. aoqi@0: public Object getObject(int offset) throws IOException { aoqi@0: Integer position = new Integer(offset); aoqi@0: aoqi@0: if (!offsetToObjectMap.containsKey(position)) aoqi@0: // XXX I18N, logging needed. aoqi@0: throw new IOException("Invalid indirection to offset " aoqi@0: + offset); aoqi@0: aoqi@0: return offsetToObjectMap.get(position); aoqi@0: } aoqi@0: aoqi@0: // Called when an object has been completely aoqi@0: // deserialized, so it should no longer be in aoqi@0: // this mapping. The CDR level can handle aoqi@0: // further indirections. aoqi@0: public void removeObject(int offset) { aoqi@0: offsetToObjectMap.remove(new Integer(offset)); aoqi@0: } aoqi@0: aoqi@0: // If the given offset doesn't map to an Object, aoqi@0: // then it isn't an indirection to an object aoqi@0: // currently being deserialized. aoqi@0: public boolean containsObject(int offset) { aoqi@0: return offsetToObjectMap.containsKey(new Integer(offset)); aoqi@0: } aoqi@0: } aoqi@0: }