--- a/corba/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java Wed Jul 05 17:23:18 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2721 +0,0 @@
-/*
- * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/*
- * Licensed Materials - Property of IBM
- * RMI-IIOP v1.0
- * Copyright IBM Corp. 1998 1999 All Rights Reserved
- *
- */
-
-package com.sun.corba.se.impl.io;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.StreamCorruptedException;
-import java.io.ObjectInputValidation;
-import java.io.NotActiveException;
-import java.io.InvalidObjectException;
-import java.io.InvalidClassException;
-import java.io.DataInputStream;
-import java.io.OptionalDataException;
-import java.io.WriteAbortedException;
-import java.io.Externalizable;
-import java.io.EOFException;
-import java.lang.reflect.*;
-import java.util.Vector;
-import java.util.Stack;
-import java.util.Hashtable;
-import java.util.Enumeration;
-
-import sun.corba.Bridge ;
-
-import java.security.AccessController ;
-import java.security.PrivilegedAction ;
-
-import com.sun.corba.se.impl.io.ObjectStreamClass;
-import com.sun.corba.se.impl.util.Utility;
-
-import org.omg.CORBA.portable.ValueInputStream;
-
-import org.omg.CORBA.ValueMember;
-import org.omg.CORBA.SystemException;
-import org.omg.CORBA.TCKind;
-import org.omg.CORBA.ORB;
-import org.omg.CORBA.CompletionStatus;
-import org.omg.CORBA.portable.IndirectionException;
-import org.omg.CORBA.MARSHAL;
-import org.omg.CORBA.TypeCode;
-
-import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
-import com.sun.org.omg.SendingContext.CodeBase;
-
-import javax.rmi.PortableRemoteObject;
-import javax.rmi.CORBA.Util;
-import javax.rmi.CORBA.ValueHandler;
-
-import java.security.*;
-import java.util.*;
-
-import com.sun.corba.se.impl.orbutil.ObjectUtility ;
-import com.sun.corba.se.impl.logging.OMGSystemException ;
-import com.sun.corba.se.impl.logging.UtilSystemException ;
-
-import com.sun.corba.se.spi.logging.CORBALogDomains ;
-
-/**
- * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization
- * input semantics.
- *
- * @author Stephen Lewallen
- * @since JDK1.1.6
- */
-
-public class IIOPInputStream
- extends com.sun.corba.se.impl.io.InputStreamHook
-{
- private static Bridge bridge =
- (Bridge)AccessController.doPrivileged(
- new PrivilegedAction() {
- public Object run() {
- return Bridge.get() ;
- }
- }
- ) ;
-
- private static OMGSystemException omgWrapper = OMGSystemException.get(
- CORBALogDomains.RPC_ENCODING ) ;
- private static UtilSystemException utilWrapper = UtilSystemException.get(
- CORBALogDomains.RPC_ENCODING ) ;
-
- // Necessary to pass the appropriate fields into the
- // defaultReadObjectDelegate method (which takes no
- // parameters since it's called from
- // java.io.ObjectInpuStream defaultReadObject()
- // which we can't change).
- //
- // This is only used in the case where the fields had
- // to be obtained remotely because of a serializable
- // version difference. Set in inputObjectUsingFVD.
- // Part of serialization evolution fixes for Ladybird,
- // bug 4365188.
- private ValueMember defaultReadObjectFVDMembers[] = null;
-
- private org.omg.CORBA_2_3.portable.InputStream orbStream;
-
- private CodeBase cbSender;
-
- private ValueHandlerImpl vhandler; //d4365188
-
- private Object currentObject = null;
-
- private ObjectStreamClass currentClassDesc = null;
-
- private Class currentClass = null;
-
- private int recursionDepth = 0;
-
- private int simpleReadDepth = 0;
-
- // The ActiveRecursionManager replaces the old RecursionManager which
- // used to record how many recursions were made, and resolve them after
- // an object was completely deserialized.
- //
- // That created problems (as in bug 4414154) because when custom
- // unmarshaling in readObject, there can be recursive references
- // to one of the objects currently being unmarshaled, and the
- // passive recursion system failed.
- ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager();
-
- private IOException abortIOException = null;
-
- /* Remember the first exception that stopped this stream. */
- private ClassNotFoundException abortClassNotFoundException = null;
-
- /* Vector of validation callback objects
- * The vector is created as needed. The vector is maintained in
- * order of highest (first) priority to lowest
- */
- private Vector callbacks;
-
- // Serialization machinery fields
- /* Arrays used to keep track of classes and ObjectStreamClasses
- * as they are being merged; used in inputObject.
- * spClass is the stack pointer for both. */
- ObjectStreamClass[] classdesc;
- Class[] classes;
- int spClass;
-
- private static final String kEmptyStr = "";
-
- // TCKind TypeCodes used in FVD inputClassFields
- //public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref);
- //public static final TypeCode kValueTypeCode = new TypeCodeImpl(TCKind._tk_value);
- // removed TypeCodeImpl dependency
- public static final TypeCode kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref);
- public static final TypeCode kValueTypeCode = ORB.init().get_primitive_tc(TCKind.tk_value);
-
- // TESTING CODE - useFVDOnly should be made final before FCS in order to
- // optimize out the check.
- private static final boolean useFVDOnly = false;
-
- private byte streamFormatVersion;
-
- // Since java.io.OptionalDataException's constructors are
- // package private, but we need to throw it in some special
- // cases, we try to do it by reflection.
- private static final Constructor OPT_DATA_EXCEPTION_CTOR;
-
- private Object[] readObjectArgList = { this } ;
-
- static {
- OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor();
- }
-
- // Grab the OptionalDataException boolean ctor and make
- // it accessible. Note that any exceptions
- // will be wrapped in ExceptionInInitializerErrors.
- private static Constructor getOptDataExceptionCtor() {
-
- try {
-
- Constructor result =
-
- (Constructor) AccessController.doPrivileged(
- new PrivilegedExceptionAction() {
- public java.lang.Object run()
- throws NoSuchMethodException,
- SecurityException {
-
- Constructor boolCtor
- = OptionalDataException.class.getDeclaredConstructor(
- new Class[] {
- Boolean.TYPE });
-
- boolCtor.setAccessible(true);
-
- return boolCtor;
- }});
-
- if (result == null)
- // XXX I18N, logging needed.
- throw new Error("Unable to find OptionalDataException constructor");
-
- return result;
-
- } catch (Exception ex) {
- // XXX I18N, logging needed.
- throw new ExceptionInInitializerError(ex);
- }
- }
-
- // Create a new OptionalDataException with the EOF marker
- // set to true. See handleOptionalDataMarshalException.
- private OptionalDataException createOptionalDataException() {
- try {
- OptionalDataException result
- = (OptionalDataException)
- OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] {
- Boolean.TRUE });
-
- if (result == null)
- // XXX I18N, logging needed.
- throw new Error("Created null OptionalDataException");
-
- return result;
-
- } catch (Exception ex) {
- // XXX I18N, logging needed.
- throw new Error("Couldn't create OptionalDataException", ex);
- }
- }
-
- // Return the stream format version currently being used
- // to deserialize an object
- protected byte getStreamFormatVersion() {
- return streamFormatVersion;
- }
-
- // At the beginning of data sent by a writeObject or
- // writeExternal method there is a byte telling the
- // reader the stream format version.
- private void readFormatVersion() throws IOException {
-
- streamFormatVersion = orbStream.read_octet();
-
- if (streamFormatVersion < 1 ||
- streamFormatVersion > vhandler.getMaximumStreamFormatVersion()) {
- SystemException sysex = omgWrapper.unsupportedFormatVersion(
- CompletionStatus.COMPLETED_MAYBE);
- // XXX I18N? Logging for IOException?
- IOException result = new IOException("Unsupported format version: "
- + streamFormatVersion);
- result.initCause( sysex ) ;
- throw result ;
- }
-
- if (streamFormatVersion == 2) {
- if (!(orbStream instanceof ValueInputStream)) {
- SystemException sysex = omgWrapper.notAValueinputstream(
- CompletionStatus.COMPLETED_MAYBE);
- // XXX I18N? Logging for IOException?
- IOException result = new IOException("Not a ValueInputStream");
- result.initCause( sysex ) ;
- throw result;
- }
- }
- }
-
- public static void setTestFVDFlag(boolean val){
- // useFVDOnly = val;
- }
-
- /**
- * Dummy constructor; passes upper stream a dummy stream;
- **/
- public IIOPInputStream()
- throws java.io.IOException {
- super();
- resetStream();
- }
-
- public final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) {
- orbStream = os;
- }
-
- public final org.omg.CORBA_2_3.portable.InputStream getOrbStream() {
- return orbStream;
- }
-
- //added setSender and getSender
- public final void setSender(CodeBase cb) {
- cbSender = cb;
- }
-
- public final CodeBase getSender() {
- return cbSender;
- }
-
- // 4365188 this is added to enable backward compatability w/ wrong
- // rep-ids
- public final void setValueHandler(ValueHandler vh) {
- vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh;
- }
-
- public final ValueHandler getValueHandler() {
- return (javax.rmi.CORBA.ValueHandler) vhandler;
- }
-
- public final void increaseRecursionDepth(){
- recursionDepth++;
- }
-
- public final int decreaseRecursionDepth(){
- return --recursionDepth;
- }
-
- /**
- * Override the actions of the final method "readObject()"
- * in ObjectInputStream.
- * @since JDK1.1.6
- *
- * Read an object from the ObjectInputStream.
- * The class of the object, the signature of the class, and the values
- * of the non-transient and non-static fields of the class and all
- * of its supertypes are read. Default deserializing for a class can be
- * overriden using the writeObject and readObject methods.
- * Objects referenced by this object are read transitively so
- * that a complete equivalent graph of objects is reconstructed by readObject. <p>
- *
- * The root object is completly restored when all of its fields
- * and the objects it references are completely restored. At this
- * point the object validation callbacks are executed in order
- * based on their registered priorities. The callbacks are
- * registered by objects (in the readObject special methods)
- * as they are individually restored.
- *
- * Exceptions are thrown for problems with the InputStream and for classes
- * that should not be deserialized. All exceptions are fatal to the
- * InputStream and leave it in an indeterminate state; it is up to the caller
- * to ignore or recover the stream state.
- * @exception java.lang.ClassNotFoundException Class of a serialized object
- * cannot be found.
- * @exception InvalidClassException Something is wrong with a class used by
- * serialization.
- * @exception StreamCorruptedException Control information in the
- * stream is inconsistent.
- * @exception OptionalDataException Primitive data was found in the
- * stream instead of objects.
- * @exception IOException Any of the usual Input/Output related exceptions.
- * @since JDK1.1
- */
- public final Object readObjectDelegate() throws IOException
- {
- try {
-
- readObjectState.readData(this);
-
- return orbStream.read_abstract_interface();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, true);
- throw marshalException;
- } catch(IndirectionException cdrie)
- {
- // The CDR stream had never seen the given offset before,
- // so check the recursion manager (it will throw an
- // IOException if it doesn't have a reference, either).
- return activeRecursionMgr.getObject(cdrie.offset);
- }
- }
-
- final Object simpleReadObject(Class clz,
- String repositoryID,
- com.sun.org.omg.SendingContext.CodeBase sender,
- int offset)
- /* throws OptionalDataException, ClassNotFoundException, IOException */
- {
-
- /* Save the current state and get ready to read an object. */
- Object prevObject = currentObject;
- ObjectStreamClass prevClassDesc = currentClassDesc;
- Class prevClass = currentClass;
- byte oldStreamFormatVersion = streamFormatVersion;
-
- simpleReadDepth++; // Entering
- Object obj = null;
-
- /*
- * Check for reset, handle it before reading an object.
- */
- try {
- // d4365188: backward compatability
- if (vhandler.useFullValueDescription(clz, repositoryID)) {
- obj = inputObjectUsingFVD(clz, repositoryID, sender, offset);
- } else {
- obj = inputObject(clz, repositoryID, sender, offset);
- }
-
- obj = currentClassDesc.readResolve(obj);
- }
- catch(ClassNotFoundException cnfe)
- {
- bridge.throwException( cnfe ) ;
- return null;
- }
- catch(IOException ioe)
- {
- // System.out.println("CLZ = " + clz + "; " + ioe.toString());
- bridge.throwException(ioe) ;
- return null;
- }
- finally {
- simpleReadDepth --;
- currentObject = prevObject;
- currentClassDesc = prevClassDesc;
- currentClass = prevClass;
- streamFormatVersion = oldStreamFormatVersion;
- }
-
-
- /* Check for thrown exceptions and re-throw them, clearing them if
- * this is the last recursive call .
- */
- IOException exIOE = abortIOException;
- if (simpleReadDepth == 0)
- abortIOException = null;
- if (exIOE != null){
- bridge.throwException( exIOE ) ;
- return null;
- }
-
-
- ClassNotFoundException exCNF = abortClassNotFoundException;
- if (simpleReadDepth == 0)
- abortClassNotFoundException = null;
- if (exCNF != null) {
- bridge.throwException( exCNF ) ;
- return null;
- }
-
- return obj;
- }
-
- public final void simpleSkipObject(String repositoryID,
- com.sun.org.omg.SendingContext.CodeBase sender)
- /* throws OptionalDataException, ClassNotFoundException, IOException */
- {
-
- /* Save the current state and get ready to read an object. */
- Object prevObject = currentObject;
- ObjectStreamClass prevClassDesc = currentClassDesc;
- Class prevClass = currentClass;
- byte oldStreamFormatVersion = streamFormatVersion;
-
- simpleReadDepth++; // Entering
- Object obj = null;
-
- /*
- * Check for reset, handle it before reading an object.
- */
- try {
- skipObjectUsingFVD(repositoryID, sender);
- }
- catch(ClassNotFoundException cnfe)
- {
- bridge.throwException( cnfe ) ;
- return;
- }
- catch(IOException ioe)
- {
- bridge.throwException( ioe ) ;
- return;
- }
- finally {
- simpleReadDepth --;
- streamFormatVersion = oldStreamFormatVersion;
- currentObject = prevObject;
- currentClassDesc = prevClassDesc;
- currentClass = prevClass;
- }
-
-
- /* Check for thrown exceptions and re-throw them, clearing them if
- * this is the last recursive call .
- */
- IOException exIOE = abortIOException;
- if (simpleReadDepth == 0)
- abortIOException = null;
- if (exIOE != null){
- bridge.throwException( exIOE ) ;
- return;
- }
-
-
- ClassNotFoundException exCNF = abortClassNotFoundException;
- if (simpleReadDepth == 0)
- abortClassNotFoundException = null;
- if (exCNF != null) {
- bridge.throwException( exCNF ) ;
- return;
- }
-
- return;
- }
- /////////////////
-
- /**
- * This method is called by trusted subclasses of ObjectOutputStream
- * that constructed ObjectOutputStream using the
- * protected no-arg constructor. The subclass is expected to provide
- * an override method with the modifier "final".
- *
- * @return the Object read from the stream.
- *
- * @see #ObjectInputStream()
- * @see #readObject
- * @since JDK 1.2
- */
- protected final Object readObjectOverride()
- throws OptionalDataException, ClassNotFoundException, IOException
- {
- return readObjectDelegate();
- }
-
- /**
- * Override the actions of the final method "defaultReadObject()"
- * in ObjectInputStream.
- * @since JDK1.1.6
- *
- * Read the non-static and non-transient fields of the current class
- * from this stream. This may only be called from the readObject method
- * of the class being deserialized. It will throw the NotActiveException
- * if it is called otherwise.
- *
- * @exception java.lang.ClassNotFoundException if the class of a serialized
- * object could not be found.
- * @exception IOException if an I/O error occurs.
- * @exception NotActiveException if the stream is not currently reading
- * objects.
- * @since JDK1.1
- */
- public final void defaultReadObjectDelegate()
- /* throws IOException, ClassNotFoundException, NotActiveException */
- {
- try {
- if (currentObject == null || currentClassDesc == null)
- // XXX I18N, logging needed.
- throw new NotActiveException("defaultReadObjectDelegate");
-
- // The array will be null unless fields were retrieved
- // remotely because of a serializable version difference.
- // Bug fix for 4365188. See the definition of
- // defaultReadObjectFVDMembers for more information.
- if (defaultReadObjectFVDMembers != null &&
- defaultReadObjectFVDMembers.length > 0) {
-
- // WARNING: Be very careful! What if some of
- // these fields actually have to do this, too?
- // This works because the defaultReadObjectFVDMembers
- // reference is passed to inputClassFields, but
- // there is no guarantee that
- // defaultReadObjectFVDMembers will point to the
- // same array after calling inputClassFields.
-
- // Use the remote fields to unmarshal.
- inputClassFields(currentObject,
- currentClass,
- currentClassDesc,
- defaultReadObjectFVDMembers,
- cbSender);
-
- } else {
-
- // Use the local fields to unmarshal.
- ObjectStreamField[] fields =
- currentClassDesc.getFieldsNoCopy();
- if (fields.length > 0) {
- inputClassFields(currentObject, currentClass, fields, cbSender);
- }
- }
- }
- catch(NotActiveException nae)
- {
- bridge.throwException( nae ) ;
- }
- catch(IOException ioe)
- {
- bridge.throwException( ioe ) ;
- }
- catch(ClassNotFoundException cnfe)
- {
- bridge.throwException( cnfe ) ;
- }
-
- }
-
- /**
- * Override the actions of the final method "enableResolveObject()"
- * in ObjectInputStream.
- * @since JDK1.1.6
- *
- * Enable the stream to allow objects read from the stream to be replaced.
- * If the stream is a trusted class it is allowed to enable replacment.
- * Trusted classes are those classes with a classLoader equals null. <p>
- *
- * When enabled the resolveObject method is called for every object
- * being deserialized.
- *
- * @exception SecurityException The classloader of this stream object is non-null.
- * @since JDK1.1
- */
- public final boolean enableResolveObjectDelegate(boolean enable)
- /* throws SecurityException */
- {
- return false;
- }
-
- // The following three methods allow the implementing orbStream
- // to provide mark/reset behavior as defined in java.io.InputStream.
-
- public final void mark(int readAheadLimit) {
- orbStream.mark(readAheadLimit);
- }
-
- public final boolean markSupported() {
- return orbStream.markSupported();
- }
-
- public final void reset() throws IOException {
- try {
- orbStream.reset();
- } catch (Error e) {
- IOException err = new IOException(e.getMessage());
- err.initCause(e) ;
- throw err ;
- }
- }
-
- public final int available() throws IOException{
- return 0; // unreliable
- }
-
- public final void close() throws IOException{
- // no op
- }
-
- public final int read() throws IOException{
- try{
- readObjectState.readData(this);
-
- return (orbStream.read_octet() << 0) & 0x000000FF;
- } catch (MARSHAL marshalException) {
- if (marshalException.minor
- == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
- setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
- return -1;
- }
-
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e) ;
- throw exc ;
- }
- }
-
- public final int read(byte data[], int offset, int length) throws IOException{
- try{
- readObjectState.readData(this);
-
- orbStream.read_octet_array(data, offset, length);
- return length;
- } catch (MARSHAL marshalException) {
- if (marshalException.minor
- == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
- setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
- return -1;
- }
-
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e) ;
- throw exc ;
- }
-
- }
-
- public final boolean readBoolean() throws IOException{
- try{
- readObjectState.readData(this);
-
- return orbStream.read_boolean();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
-
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final byte readByte() throws IOException{
- try{
- readObjectState.readData(this);
-
- return orbStream.read_octet();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
-
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final char readChar() throws IOException{
- try{
- readObjectState.readData(this);
-
- return orbStream.read_wchar();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
-
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final double readDouble() throws IOException{
- try{
- readObjectState.readData(this);
-
- return orbStream.read_double();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final float readFloat() throws IOException{
- try{
- readObjectState.readData(this);
-
- return orbStream.read_float();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final void readFully(byte data[]) throws IOException{
-// d11623 : implement readFully, required for serializing some core classes
-
- readFully(data, 0, data.length);
- }
-
- public final void readFully(byte data[], int offset, int size) throws IOException{
-// d11623 : implement readFully, required for serializing some core classes
- try{
- readObjectState.readData(this);
-
- orbStream.read_octet_array(data, offset, size);
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
-
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final int readInt() throws IOException{
- try{
- readObjectState.readData(this);
-
- return orbStream.read_long();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final String readLine() throws IOException{
- // XXX I18N, logging needed.
- throw new IOException("Method readLine not supported");
- }
-
- public final long readLong() throws IOException{
- try{
- readObjectState.readData(this);
-
- return orbStream.read_longlong();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final short readShort() throws IOException{
- try{
- readObjectState.readData(this);
-
- return orbStream.read_short();
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- protected final void readStreamHeader() throws IOException, StreamCorruptedException{
- // no op
- }
-
- public final int readUnsignedByte() throws IOException{
- try{
- readObjectState.readData(this);
-
- return (orbStream.read_octet() << 0) & 0x000000FF;
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- public final int readUnsignedShort() throws IOException{
- try{
- readObjectState.readData(this);
-
- return (orbStream.read_ushort() << 0) & 0x0000FFFF;
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- /**
- * Helper method for correcting the Kestrel bug 4367783 (dealing
- * with larger than 8-bit chars). The old behavior is preserved
- * in orbutil.IIOPInputStream_1_3 in order to interoperate with
- * our legacy ORBs.
- */
- protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream)
- {
- return stream.read_wstring();
- }
-
- public final String readUTF() throws IOException{
- try{
- readObjectState.readData(this);
-
- return internalReadUTF(orbStream);
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e);
- throw exc ;
- }
- }
-
- // If the ORB stream detects an incompatibility between what's
- // on the wire and what our Serializable's readObject wants,
- // it throws a MARSHAL exception with a specific minor code.
- // This is rethrown to the readObject as an OptionalDataException.
- // So far in RMI-IIOP, this process isn't specific enough to
- // tell the readObject how much data is available, so we always
- // set the OptionalDataException's EOF marker to true.
- private void handleOptionalDataMarshalException(MARSHAL marshalException,
- boolean objectRead)
- throws IOException {
-
- // Java Object Serialization spec 3.4: "If the readObject method
- // of the class attempts to read more data than is present in the
- // optional part of the stream for this class, the stream will
- // return -1 for bytewise reads, throw an EOFException for
- // primitive data reads, or throw an OptionalDataException
- // with the eof field set to true for object reads."
- if (marshalException.minor
- == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
-
- IOException result;
-
- if (!objectRead)
- result = new EOFException("No more optional data");
- else
- result = createOptionalDataException();
-
- result.initCause(marshalException);
-
- setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
-
- throw result;
- }
- }
-
- public final synchronized void registerValidation(ObjectInputValidation obj,
- int prio)
- throws NotActiveException, InvalidObjectException{
- // XXX I18N, logging needed.
- throw new Error("Method registerValidation not supported");
- }
-
- protected final Class resolveClass(ObjectStreamClass v)
- throws IOException, ClassNotFoundException{
- // XXX I18N, logging needed.
- throw new IOException("Method resolveClass not supported");
- }
-
- protected final Object resolveObject(Object obj) throws IOException{
- // XXX I18N, logging needed.
- throw new IOException("Method resolveObject not supported");
- }
-
- public final int skipBytes(int len) throws IOException{
- try{
- readObjectState.readData(this);
-
- byte buf[] = new byte[len];
- orbStream.read_octet_array(buf, 0, len);
- return len;
- } catch (MARSHAL marshalException) {
- handleOptionalDataMarshalException(marshalException, false);
-
- throw marshalException;
- } catch(Error e) {
- IOException exc = new IOException(e.getMessage());
- exc.initCause(e) ;
- throw exc ;
- }
- }
-
- private Object inputObject(Class clz,
- String repositoryID,
- com.sun.org.omg.SendingContext.CodeBase sender,
- int offset)
- throws IOException, ClassNotFoundException
- {
-
- /*
- * Get the descriptor and then class of the incoming object.
- */
-
- currentClassDesc = ObjectStreamClass.lookup(clz);
- currentClass = currentClassDesc.forClass();
- //currentClassDesc.setClass(currentClass);
- if (currentClass == null)
- // XXX I18N, logging needed.
- throw new ClassNotFoundException(currentClassDesc.getName());
-
- try {
- /* If Externalizable,
- * Create an instance and tell it to read its data.
- * else,
- * Handle it as a serializable class.
- */
- if (currentClassDesc.isExternalizable()) {
- try {
- currentObject = (currentClass == null) ?
- null : currentClassDesc.newInstance();
- if (currentObject != null) {
-
- // Store this object and its beginning position
- // since there might be indirections to it while
- // it's been unmarshalled.
- activeRecursionMgr.addObject(offset, currentObject);
-
- // Read format version
- readFormatVersion();
-
- Externalizable ext = (Externalizable)currentObject;
- ext.readExternal(this);
- }
- } catch (InvocationTargetException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "InvocationTargetException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- } catch (UnsupportedOperationException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "UnsupportedOperationException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- } catch (InstantiationException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "InstantiationException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- }
- } // end : if (currentClassDesc.isExternalizable())
- else {
- /* Count number of classes and descriptors we might have
- * to work on.
- */
-
- ObjectStreamClass currdesc = currentClassDesc;
- Class currclass = currentClass;
-
- int spBase = spClass; // current top of stack
-
- /* The object's classes should be processed from supertype to subtype
- * Push all the clases of the current object onto a stack.
- * Note that only the serializable classes are represented
- * in the descriptor list.
- *
- * Handle versioning where one or more supertypes of
- * have been inserted or removed. The stack will
- * contain pairs of descriptors and the corresponding
- * class. If the object has a class that did not occur in
- * the original the descriptor will be null. If the
- * original object had a descriptor for a class not
- * present in the local hierarchy of the object the class will be
- * null.
- *
- */
-
- /*
- * This is your basic diff pattern, made simpler
- * because reordering is not allowed.
- */
- // sun.4296963 ibm.11861
- // d11861 we should stop when we find the highest serializable class
- // We need this so that when we allocate the new object below, we
- // can call the constructor of the non-serializable superclass.
- // Note that in the JRMP variant of this code the
- // ObjectStreamClass.lookup() method handles this, but we've put
- // this fix here rather than change lookup because the new behaviour
- // is needed in other cases.
-
- for (currdesc = currentClassDesc, currclass = currentClass;
- currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
- currdesc = currdesc.getSuperclass()) {
-
- /*
- * Search the classes to see if the class of this
- * descriptor appears further up the hierarchy. Until
- * it's found assume its an inserted class. If it's
- * not found, its the descriptor's class that has been
- * removed.
- */
- Class cc = currdesc.forClass();
- Class cl;
- for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
- if (cc == cl) {
- // found a superclass that matches this descriptor
- break;
- } else {
- /* Ignore a class that doesn't match. No
- * action is needed since it is already
- * initialized.
- */
- }
- } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
- /* Test if there is room for this new entry.
- * If not, double the size of the arrays and copy the contents.
- */
- spClass++;
- if (spClass >= classes.length) {
- int newlen = classes.length * 2;
- Class[] newclasses = new Class[newlen];
- ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
-
- System.arraycopy(classes, 0,
- newclasses, 0,
- classes.length);
- System.arraycopy(classdesc, 0,
- newclassdesc, 0,
- classes.length);
-
- classes = newclasses;
- classdesc = newclassdesc;
- }
-
- if (cl == null) {
- /* Class not found corresponding to this descriptor.
- * Pop off all the extra classes pushed.
- * Push the descriptor and a null class.
- */
- classdesc[spClass] = currdesc;
- classes[spClass] = null;
- } else {
- /* Current class descriptor matches current class.
- * Some classes may have been inserted.
- * Record the match and advance the class, continue
- * with the next descriptor.
- */
- classdesc[spClass] = currdesc;
- classes[spClass] = cl;
- currclass = cl.getSuperclass();
- }
- } // end : for (currdesc = currentClassDesc, currclass = currentClass;
-
- /* Allocate a new object. The object is only constructed
- * above the highest serializable class and is set to
- * default values for all more specialized classes.
- */
- try {
- currentObject = (currentClass == null) ?
- null : currentClassDesc.newInstance() ;
-
- // Store this object and its beginning position
- // since there might be indirections to it while
- // it's been unmarshalled.
- activeRecursionMgr.addObject(offset, currentObject);
- } catch (InvocationTargetException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "InvocationTargetException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- } catch (UnsupportedOperationException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "UnsupportedOperationException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- } catch (InstantiationException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "InstantiationException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- }
-
- /*
- * For all the pushed descriptors and classes.
- * if the class has its own writeObject and readObject methods
- * call the readObject method
- * else
- * invoke the defaultReadObject method
- */
- try {
- for (spClass = spClass; spClass > spBase; spClass--) {
- /*
- * Set current descriptor and corresponding class
- */
- currentClassDesc = classdesc[spClass];
- currentClass = classes[spClass];
- if (classes[spClass] != null) {
- /* Read the data from the stream described by the
- * descriptor and store into the matching class.
- */
-
- ReadObjectState oldState = readObjectState;
- setState(DEFAULT_STATE);
-
- try {
-
- // Changed since invokeObjectReader no longer does this.
- if (currentClassDesc.hasWriteObject()) {
-
- // Read format version
- readFormatVersion();
-
- // Read defaultWriteObject indicator
- boolean calledDefaultWriteObject = readBoolean();
-
- readObjectState.beginUnmarshalCustomValue(this,
- calledDefaultWriteObject,
- (currentClassDesc.readObjectMethod
- != null));
- } else {
- if (currentClassDesc.hasReadObject())
- setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
- }
-
- if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) ||
- readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) {
-
- // Error case of no readObject and didn't call
- // defaultWriteObject handled in default state
-
- ObjectStreamField[] fields =
- currentClassDesc.getFieldsNoCopy();
- if (fields.length > 0) {
- inputClassFields(currentObject, currentClass, fields, sender);
- }
- }
-
- if (currentClassDesc.hasWriteObject())
- readObjectState.endUnmarshalCustomValue(this);
-
- } finally {
- setState(oldState);
- }
-
- } else {
-
- // _REVISIT_ : Can we ever get here?
- /* No local class for this descriptor,
- * Skip over the data for this class.
- * like defaultReadObject with a null currentObject.
- * The code will read the values but discard them.
- */
- ObjectStreamField[] fields =
- currentClassDesc.getFieldsNoCopy();
- if (fields.length > 0) {
- inputClassFields(null, currentClass, fields, sender);
- }
-
- }
-
- }
- } finally {
- // Make sure we exit at the same stack level as when we started.
- spClass = spBase;
- }
- }
- } finally {
- // We've completed deserializing this object. Any
- // future indirections will be handled correctly at the
- // CDR level. The ActiveRecursionManager only deals with
- // objects currently being deserialized.
- activeRecursionMgr.removeObject(offset);
- }
-
- return currentObject;
- }
-
- // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
- // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable
- // classes!
- private Vector getOrderedDescriptions(String repositoryID,
- com.sun.org.omg.SendingContext.CodeBase sender) {
- Vector descs = new Vector();
-
- if (sender == null) {
- return descs;
- }
-
- FullValueDescription aFVD = sender.meta(repositoryID);
- while (aFVD != null) {
- descs.insertElementAt(aFVD, 0);
- if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
- aFVD = sender.meta(aFVD.base_value);
- }
- else return descs;
- }
-
- return descs;
- }
-
- /**
- * This input method uses FullValueDescriptions retrieved from the sender's runtime to
- * read in the data. This method is capable of throwing out data not applicable to client's fields.
- * This method handles instances where the reader has a class not sent by the sender, the sender sent
- * a class not present on the reader, and/or the reader's class does not match the sender's class.
- *
- * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
- * indicates custom marsahling than the local type is used to read the data off the wire. However,
- * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
- * a form of custom marshaling.
- *
- */
- private Object inputObjectUsingFVD(Class clz,
- String repositoryID,
- com.sun.org.omg.SendingContext.CodeBase sender,
- int offset)
- throws IOException, ClassNotFoundException
- {
- int spBase = spClass; // current top of stack
- try{
-
- /*
- * Get the descriptor and then class of the incoming object.
- */
-
- ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
- Class currclass = currentClass = clz;
-
- /* If Externalizable,
- * Create an instance and tell it to read its data.
- * else,
- * Handle it as a serializable class.
- */
- if (currentClassDesc.isExternalizable()) {
- try {
- currentObject = (currentClass == null) ?
- null : currentClassDesc.newInstance();
- if (currentObject != null) {
- // Store this object and its beginning position
- // since there might be indirections to it while
- // it's been unmarshalled.
- activeRecursionMgr.addObject(offset, currentObject);
-
- // Read format version
- readFormatVersion();
-
- Externalizable ext = (Externalizable)currentObject;
- ext.readExternal(this);
- }
- } catch (InvocationTargetException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "InvocationTargetException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- } catch (UnsupportedOperationException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "UnsupportedOperationException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- } catch (InstantiationException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "InstantiationException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- }
- } else {
- /*
- * This is your basic diff pattern, made simpler
- * because reordering is not allowed.
- */
- for (currdesc = currentClassDesc, currclass = currentClass;
- currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
-
- currdesc = currdesc.getSuperclass()) {
-
- /*
- * Search the classes to see if the class of this
- * descriptor appears further up the hierarchy. Until
- * it's found assume its an inserted class. If it's
- * not found, its the descriptor's class that has been
- * removed.
- */
- Class cc = currdesc.forClass();
- Class cl;
- for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
- if (cc == cl) {
- // found a superclass that matches this descriptor
- break;
- } else {
- /* Ignore a class that doesn't match. No
- * action is needed since it is already
- * initialized.
- */
- }
- } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
- /* Test if there is room for this new entry.
- * If not, double the size of the arrays and copy the contents.
- */
- spClass++;
- if (spClass >= classes.length) {
- int newlen = classes.length * 2;
- Class[] newclasses = new Class[newlen];
- ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
-
- System.arraycopy(classes, 0,
- newclasses, 0,
- classes.length);
- System.arraycopy(classdesc, 0,
- newclassdesc, 0,
- classes.length);
-
- classes = newclasses;
- classdesc = newclassdesc;
- }
-
- if (cl == null) {
- /* Class not found corresponding to this descriptor.
- * Pop off all the extra classes pushed.
- * Push the descriptor and a null class.
- */
- classdesc[spClass] = currdesc;
- classes[spClass] = null;
- } else {
- /* Current class descriptor matches current class.
- * Some classes may have been inserted.
- * Record the match and advance the class, continue
- * with the next descriptor.
- */
- classdesc[spClass] = currdesc;
- classes[spClass] = cl;
- currclass = cl.getSuperclass();
- }
- } // end : for (currdesc = currentClassDesc, currclass = currentClass;
-
- /* Allocate a new object.
- */
- try {
- currentObject = (currentClass == null) ?
- null : currentClassDesc.newInstance();
-
- // Store this object and its beginning position
- // since there might be indirections to it while
- // it's been unmarshalled.
- activeRecursionMgr.addObject(offset, currentObject);
- } catch (InvocationTargetException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "InvocationTargetException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- } catch (UnsupportedOperationException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "UnsupportedOperationException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- } catch (InstantiationException e) {
- InvalidClassException exc = new InvalidClassException(
- currentClass.getName(),
- "InstantiationException accessing no-arg constructor");
- exc.initCause( e ) ;
- throw exc ;
- }
-
- Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
-
- while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
- FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
- // d4365188: backward compatability
- String repIDForFVD = vhandler.getClassName(fvd.id);
- String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
-
- while ((spClass > spBase) &&
- (!repIDForFVD.equals(repIDForClass))) {
- int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
- if (pos != -1) {
- spClass = pos;
- currclass = currentClass = classes[spClass];
- repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
- }
- else { // Read and throw away one level of the fvdslist
-
- // This seems to mean that the sender had a superclass that
- // we don't have
-
- if (fvd.is_custom) {
-
- readFormatVersion();
- boolean calledDefaultWriteObject = readBoolean();
-
- if (calledDefaultWriteObject)
- inputClassFields(null, null, null, fvd.members, sender);
-
- if (getStreamFormatVersion() == 2) {
-
- ((ValueInputStream)getOrbStream()).start_value();
- ((ValueInputStream)getOrbStream()).end_value();
- }
-
- // WARNING: If stream format version is 1 and there's
- // optional data, we'll get some form of exception down
- // the line or data corruption.
-
- } else {
-
- inputClassFields(null, currentClass, null, fvd.members, sender);
- }
-
- if (fvdsList.hasMoreElements()){
- fvd = (FullValueDescription)fvdsList.nextElement();
- repIDForFVD = vhandler.getClassName(fvd.id);
- }
- else return currentObject;
- }
- }
-
- currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
-
- if (!repIDForClass.equals("java.lang.Object")) {
-
- // If the sender used custom marshaling, then it should have put
- // the two bytes on the wire indicating stream format version
- // and whether or not the writeObject method called
- // defaultWriteObject/writeFields.
-
- ReadObjectState oldState = readObjectState;
- setState(DEFAULT_STATE);
-
- try {
-
- if (fvd.is_custom) {
-
- // Read format version
- readFormatVersion();
-
- // Read defaultWriteObject indicator
- boolean calledDefaultWriteObject = readBoolean();
-
- readObjectState.beginUnmarshalCustomValue(this,
- calledDefaultWriteObject,
- (currentClassDesc.readObjectMethod
- != null));
- }
-
- boolean usedReadObject = false;
-
- // Always use readObject if it exists, and fall back to default
- // unmarshaling if it doesn't.
- try {
-
- if (!fvd.is_custom && currentClassDesc.hasReadObject())
- setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
-
- // See the definition of defaultReadObjectFVDMembers
- // for more information. This concerns making sure
- // we use the remote FVD's members in defaultReadObject.
- defaultReadObjectFVDMembers = fvd.members;
- usedReadObject = invokeObjectReader(currentClassDesc,
- currentObject,
- currentClass);
-
- } finally {
- defaultReadObjectFVDMembers = null;
- }
-
- // Note that the !usedReadObject !calledDefaultWriteObject
- // case is handled by the beginUnmarshalCustomValue method
- // of the default state
- if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT)
- inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
-
- if (fvd.is_custom)
- readObjectState.endUnmarshalCustomValue(this);
-
- } finally {
- setState(oldState);
- }
-
- currclass = currentClass = classes[--spClass];
-
- } else {
-
- // The remaining hierarchy of the local class does not match the sender's FVD.
- // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate
- // custom marshaling, throw MARSHAL error.
- inputClassFields(null, currentClass, null, fvd.members, sender);
-
- while (fvdsList.hasMoreElements()){
- fvd = (FullValueDescription)fvdsList.nextElement();
-
- if (fvd.is_custom)
- skipCustomUsingFVD(fvd.members, sender);
- else
- inputClassFields(null, currentClass, null, fvd.members, sender);
- }
-
- }
-
- } // end : while(fvdsList.hasMoreElements())
- while (fvdsList.hasMoreElements()){
-
- FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
- if (fvd.is_custom)
- skipCustomUsingFVD(fvd.members, sender);
- else
- throwAwayData(fvd.members, sender);
- }
- }
-
- return currentObject;
- }
- finally {
- // Make sure we exit at the same stack level as when we started.
- spClass = spBase;
-
- // We've completed deserializing this object. Any
- // future indirections will be handled correctly at the
- // CDR level. The ActiveRecursionManager only deals with
- // objects currently being deserialized.
- activeRecursionMgr.removeObject(offset);
- }
-
- }
-
- /**
- * This input method uses FullValueDescriptions retrieved from the sender's runtime to
- * read in the data. This method is capable of throwing out data not applicable to client's fields.
- *
- * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
- * indicates custom marsahling than the local type is used to read the data off the wire. However,
- * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
- * a form of custom marshaling.
- *
- */
- private Object skipObjectUsingFVD(String repositoryID,
- com.sun.org.omg.SendingContext.CodeBase sender)
- throws IOException, ClassNotFoundException
- {
-
- Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
-
- while(fvdsList.hasMoreElements()) {
- FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
- String repIDForFVD = vhandler.getClassName(fvd.id);
-
- if (!repIDForFVD.equals("java.lang.Object")) {
- if (fvd.is_custom) {
-
- readFormatVersion();
-
- boolean calledDefaultWriteObject = readBoolean();
-
- if (calledDefaultWriteObject)
- inputClassFields(null, null, null, fvd.members, sender);
-
- if (getStreamFormatVersion() == 2) {
-
- ((ValueInputStream)getOrbStream()).start_value();
- ((ValueInputStream)getOrbStream()).end_value();
- }
-
- // WARNING: If stream format version is 1 and there's
- // optional data, we'll get some form of exception down
- // the line.
-
- } else {
- // Use default marshaling
- inputClassFields(null, null, null, fvd.members, sender);
- }
- }
-
- } // end : while(fvdsList.hasMoreElements())
- return null;
-
- }
-
- ///////////////////
-
- private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){
-
- for (int i = _spClass; i > _spBase; i--){
- if (classname.equals(classes[i].getName())) {
- return i;
- }
- }
-
- return -1;
- }
-
- /*
- * Invoke the readObject method if present. Assumes that in the case of custom
- * marshaling, the format version and defaultWriteObject indicator were already
- * removed.
- */
- private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IOException
- {
- if (osc.readObjectMethod == null) {
- return false;
- }
-
- try {
- osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
- return true;
- } catch (InvocationTargetException e) {
- Throwable t = e.getTargetException();
- if (t instanceof ClassNotFoundException)
- throw (ClassNotFoundException)t;
- else if (t instanceof IOException)
- throw (IOException)t;
- else if (t instanceof RuntimeException)
- throw (RuntimeException) t;
- else if (t instanceof Error)
- throw (Error) t;
- else
- // XXX I18N, logging needed.
- throw new Error("internal error");
- } catch (IllegalAccessException e) {
- return false;
- }
- }
-
- /*
- * Reset the stream to be just like it was after the constructor.
- */
- private void resetStream() throws IOException {
-
- if (classes == null)
- classes = new Class[20];
- else {
- for (int i = 0; i < classes.length; i++)
- classes[i] = null;
- }
- if (classdesc == null)
- classdesc = new ObjectStreamClass[20];
- else {
- for (int i = 0; i < classdesc.length; i++)
- classdesc[i] = null;
- }
- spClass = 0;
-
- if (callbacks != null)
- callbacks.setSize(0); // discard any pending callbacks
- }
-
- /**
- * Factored out of inputClassFields This reads a primitive value and sets it
- * in the field of o described by the ObjectStreamField field.
- *
- * Note that reflection cannot be used here, because reflection cannot be used
- * to set final fields.
- */
- private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field)
- throws InvalidClassException, IOException {
-
- try {
- switch (field.getTypeCode()) {
- case 'B':
- byte byteValue = orbStream.read_octet();
- bridge.putByte( o, field.getFieldID(), byteValue ) ;
- //reflective code: field.getField().setByte( o, byteValue ) ;
- break;
- case 'Z':
- boolean booleanValue = orbStream.read_boolean();
- bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
- //reflective code: field.getField().setBoolean( o, booleanValue ) ;
- break;
- case 'C':
- char charValue = orbStream.read_wchar();
- bridge.putChar( o, field.getFieldID(), charValue ) ;
- //reflective code: field.getField().setChar( o, charValue ) ;
- break;
- case 'S':
- short shortValue = orbStream.read_short();
- bridge.putShort( o, field.getFieldID(), shortValue ) ;
- //reflective code: field.getField().setShort( o, shortValue ) ;
- break;
- case 'I':
- int intValue = orbStream.read_long();
- bridge.putInt( o, field.getFieldID(), intValue ) ;
- //reflective code: field.getField().setInt( o, intValue ) ;
- break;
- case 'J':
- long longValue = orbStream.read_longlong();
- bridge.putLong( o, field.getFieldID(), longValue ) ;
- //reflective code: field.getField().setLong( o, longValue ) ;
- break;
- case 'F' :
- float floatValue = orbStream.read_float();
- bridge.putFloat( o, field.getFieldID(), floatValue ) ;
- //reflective code: field.getField().setFloat( o, floatValue ) ;
- break;
- case 'D' :
- double doubleValue = orbStream.read_double();
- bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
- //reflective code: field.getField().setDouble( o, doubleValue ) ;
- break;
- default:
- // XXX I18N, logging needed.
- throw new InvalidClassException(cl.getName());
- }
- } catch (IllegalArgumentException e) {
- /* This case should never happen. If the field types
- are not the same, InvalidClassException is raised when
- matching the local class to the serialized ObjectStreamClass. */
- ClassCastException cce = new ClassCastException("Assigning instance of class " +
- field.getType().getName() +
- " to field " +
- currentClassDesc.getName() + '#' +
- field.getField().getName());
- cce.initCause( e ) ;
- throw cce ;
- }
- }
-
- private Object inputObjectField(org.omg.CORBA.ValueMember field,
- com.sun.org.omg.SendingContext.CodeBase sender)
- throws IndirectionException, ClassNotFoundException, IOException,
- StreamCorruptedException {
-
- Object objectValue = null;
- Class type = null;
- String id = field.id;
-
- try {
- type = vhandler.getClassFromType(id);
- } catch(ClassNotFoundException cnfe) {
- // Make sure type = null
- type = null;
- }
-
- String signature = null;
- if (type != null)
- signature = ValueUtility.getSignature(field);
-
- if (signature != null && (signature.equals("Ljava/lang/Object;") ||
- signature.equals("Ljava/io/Serializable;") ||
- signature.equals("Ljava/io/Externalizable;"))) {
- objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
- } else {
- // Decide what method call to make based on the type. If
- // it is a type for which we need to load a stub, convert
- // the type to the correct stub type.
- //
- // NOTE : Since FullValueDescription does not allow us
- // to ask whether something is an interface we do not
- // have the ability to optimize this check.
-
- int callType = ValueHandlerImpl.kValueType;
-
- if (!vhandler.isSequence(id)) {
-
- if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
-
- // RMI Object reference...
- callType = ValueHandlerImpl.kRemoteType;
-
- } else {
-
- // REVISIT. If we don't have the local class,
- // we should probably verify that it's an RMI type,
- // query the remote FVD, and use is_abstract.
- // Our FVD seems to get NullPointerExceptions for any
- // non-RMI types.
-
- // This uses the local class in the same way as
- // inputObjectField(ObjectStreamField) does. REVISIT
- // inputObjectField(ObjectStreamField)'s loadStubClass
- // logic. Assumption is that the given type cannot
- // evolve to become a CORBA abstract interface or
- // a RMI abstract interface.
-
- if (type != null && type.isInterface() &&
- (vhandler.isAbstractBase(type) ||
- ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
-
- callType = ValueHandlerImpl.kAbstractType;
- }
- }
- }
-
- // Now that we have used the FVD of the field to determine the proper course
- // of action, it is ok to use the type (Class) from this point forward since
- // the rep. id for this read will also follow on the wire.
-
- switch (callType) {
- case ValueHandlerImpl.kRemoteType:
- if (type != null)
- objectValue = Utility.readObjectAndNarrow(orbStream, type);
- else
- objectValue = orbStream.read_Object();
- break;
- case ValueHandlerImpl.kAbstractType:
- if (type != null)
- objectValue = Utility.readAbstractAndNarrow(orbStream, type);
- else
- objectValue = orbStream.read_abstract_interface();
- break;
- case ValueHandlerImpl.kValueType:
- if (type != null)
- objectValue = orbStream.read_value(type);
- else
- objectValue = orbStream.read_value();
- break;
- default:
- // XXX I18N, logging needed.
- throw new StreamCorruptedException("Unknown callType: " + callType);
- }
- }
-
- return objectValue;
- }
-
- /**
- * Factored out of inputClassFields and reused in
- * inputCurrentClassFieldsForReadFields.
- *
- * Reads the field (which of an Object type as opposed to a primitive)
- * described by ObjectStreamField field and returns it.
- */
- private Object inputObjectField(ObjectStreamField field)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IndirectionException, IOException {
-
- if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
- return javax.rmi.CORBA.Util.readAny(orbStream);
- }
-
- Object objectValue = null;
-
- // fields have an API to provide the actual class
- // corresponding to the data type
- // Class type = osc.forClass();
- Class fieldType = field.getType();
- Class actualType = fieldType; // This may change if stub loaded.
-
- // Decide what method call to make based on the fieldType. If
- // it is a type for which we need to load a stub, convert
- // the type to the correct stub type.
-
- int callType = ValueHandlerImpl.kValueType;
- boolean narrow = false;
-
- if (fieldType.isInterface()) {
- boolean loadStubClass = false;
-
- if (java.rmi.Remote.class.isAssignableFrom(fieldType)) {
-
- // RMI Object reference...
- callType = ValueHandlerImpl.kRemoteType;
-
- } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){
-
- // IDL Object reference...
- callType = ValueHandlerImpl.kRemoteType;
- loadStubClass = true;
-
- } else if (vhandler.isAbstractBase(fieldType)) {
- // IDL Abstract Object reference...
-
- callType = ValueHandlerImpl.kAbstractType;
- loadStubClass = true;
- } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
- // RMI Abstract Object reference...
-
- callType = ValueHandlerImpl.kAbstractType;
- }
-
- if (loadStubClass) {
- try {
- String codebase = Util.getCodebase(fieldType);
- String repID = vhandler.createForAnyType(fieldType);
- Class stubType =
- Utility.loadStubClass(repID, codebase, fieldType);
- actualType = stubType;
- } catch (ClassNotFoundException e) {
- narrow = true;
- }
- } else {
- narrow = true;
- }
- }
-
- switch (callType) {
- case ValueHandlerImpl.kRemoteType:
- if (!narrow)
- objectValue = (Object)orbStream.read_Object(actualType);
- else
- objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
- break;
- case ValueHandlerImpl.kAbstractType:
- if (!narrow)
- objectValue = (Object)orbStream.read_abstract_interface(actualType);
- else
- objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
- break;
- case ValueHandlerImpl.kValueType:
- objectValue = (Object)orbStream.read_value(actualType);
- break;
- default:
- // XXX I18N, logging needed.
- throw new StreamCorruptedException("Unknown callType: " + callType);
- }
-
- return objectValue;
- }
-
- private final boolean mustUseRemoteValueMembers() {
- return defaultReadObjectFVDMembers != null;
- }
-
- void readFields(java.util.Map fieldToValueMap)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IOException {
-
- if (mustUseRemoteValueMembers()) {
- inputRemoteMembersForReadFields(fieldToValueMap);
- } else
- inputCurrentClassFieldsForReadFields(fieldToValueMap);
- }
-
- private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IOException {
-
- // Must have this local variable since defaultReadObjectFVDMembers
- // may get mangled by recursion.
- ValueMember fields[] = defaultReadObjectFVDMembers;
-
- try {
-
- for (int i = 0; i < fields.length; i++) {
-
- switch (fields[i].type.kind().value()) {
-
- case TCKind._tk_octet:
- byte byteValue = orbStream.read_octet();
- fieldToValueMap.put(fields[i].name, new Byte(byteValue));
- break;
- case TCKind._tk_boolean:
- boolean booleanValue = orbStream.read_boolean();
- fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
- break;
- case TCKind._tk_char:
- // Backwards compatibility. Older Sun ORBs sent
- // _tk_char even though they read and wrote wchars
- // correctly.
- //
- // Fall through to the _tk_wchar case.
- case TCKind._tk_wchar:
- char charValue = orbStream.read_wchar();
- fieldToValueMap.put(fields[i].name, new Character(charValue));
- break;
- case TCKind._tk_short:
- short shortValue = orbStream.read_short();
- fieldToValueMap.put(fields[i].name, new Short(shortValue));
- break;
- case TCKind._tk_long:
- int intValue = orbStream.read_long();
- fieldToValueMap.put(fields[i].name, new Integer(intValue));
- break;
- case TCKind._tk_longlong:
- long longValue = orbStream.read_longlong();
- fieldToValueMap.put(fields[i].name, new Long(longValue));
- break;
- case TCKind._tk_float:
- float floatValue = orbStream.read_float();
- fieldToValueMap.put(fields[i].name, new Float(floatValue));
- break;
- case TCKind._tk_double:
- double doubleValue = orbStream.read_double();
- fieldToValueMap.put(fields[i].name, new Double(doubleValue));
- break;
- case TCKind._tk_value:
- case TCKind._tk_objref:
- case TCKind._tk_value_box:
- Object objectValue = null;
- try {
- objectValue = inputObjectField(fields[i],
- cbSender);
-
- } catch (IndirectionException cdrie) {
- // The CDR stream had never seen the given offset before,
- // so check the recursion manager (it will throw an
- // IOException if it doesn't have a reference, either).
- objectValue = activeRecursionMgr.getObject(cdrie.offset);
- }
-
- fieldToValueMap.put(fields[i].name, objectValue);
- break;
- default:
- // XXX I18N, logging needed.
- throw new StreamCorruptedException("Unknown kind: "
- + fields[i].type.kind().value());
- }
- }
- } catch (Throwable t) {
- StreamCorruptedException result = new StreamCorruptedException(t.getMessage());
- result.initCause(t);
- throw result;
- }
- }
-
- /**
- * Called from InputStreamHook.
- *
- * Reads the fields of the current class (could be the ones
- * queried from the remote FVD) and puts them in
- * the given Map, name to value. Wraps primitives in the
- * corresponding java.lang Objects.
- */
- private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IOException {
-
- ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
-
- int primFields = fields.length - currentClassDesc.objFields;
-
- // Handle the primitives first
- for (int i = 0; i < primFields; ++i) {
-
- switch (fields[i].getTypeCode()) {
- case 'B':
- byte byteValue = orbStream.read_octet();
- fieldToValueMap.put(fields[i].getName(),
- new Byte(byteValue));
- break;
- case 'Z':
- boolean booleanValue = orbStream.read_boolean();
- fieldToValueMap.put(fields[i].getName(),
- new Boolean(booleanValue));
- break;
- case 'C':
- char charValue = orbStream.read_wchar();
- fieldToValueMap.put(fields[i].getName(),
- new Character(charValue));
- break;
- case 'S':
- short shortValue = orbStream.read_short();
- fieldToValueMap.put(fields[i].getName(),
- new Short(shortValue));
- break;
- case 'I':
- int intValue = orbStream.read_long();
- fieldToValueMap.put(fields[i].getName(),
- new Integer(intValue));
- break;
- case 'J':
- long longValue = orbStream.read_longlong();
- fieldToValueMap.put(fields[i].getName(),
- new Long(longValue));
- break;
- case 'F' :
- float floatValue = orbStream.read_float();
- fieldToValueMap.put(fields[i].getName(),
- new Float(floatValue));
- break;
- case 'D' :
- double doubleValue = orbStream.read_double();
- fieldToValueMap.put(fields[i].getName(),
- new Double(doubleValue));
- break;
- default:
- // XXX I18N, logging needed.
- throw new InvalidClassException(currentClassDesc.getName());
- }
- }
-
- /* Read and set object fields from the input stream. */
- if (currentClassDesc.objFields > 0) {
- for (int i = primFields; i < fields.length; i++) {
- Object objectValue = null;
- try {
- objectValue = inputObjectField(fields[i]);
- } catch(IndirectionException cdrie) {
- // The CDR stream had never seen the given offset before,
- // so check the recursion manager (it will throw an
- // IOException if it doesn't have a reference, either).
- objectValue = activeRecursionMgr.getObject(cdrie.offset);
- }
-
- fieldToValueMap.put(fields[i].getName(), objectValue);
- }
- }
- }
-
- /*
- * Read the fields of the specified class from the input stream and set
- * the values of the fields in the specified object. If the specified
- * object is null, just consume the fields without setting any values. If
- * any ObjectStreamField does not have a reflected Field, don't try to set
- * that field in the object.
- *
- * REVISIT -- This code doesn't do what the comment says to when
- * getField() is null!
- */
- private void inputClassFields(Object o, Class cl,
- ObjectStreamField[] fields,
- com.sun.org.omg.SendingContext.CodeBase sender)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IOException
- {
-
- int primFields = fields.length - currentClassDesc.objFields;
-
- if (o != null) {
- for (int i = 0; i < primFields; ++i) {
- if (fields[i].getField() == null)
- continue;
-
- inputPrimitiveField(o, cl, fields[i]);
- }
- }
-
- /* Read and set object fields from the input stream. */
- if (currentClassDesc.objFields > 0) {
- for (int i = primFields; i < fields.length; i++) {
- Object objectValue = null;
-
- try {
- objectValue = inputObjectField(fields[i]);
- } catch(IndirectionException cdrie) {
- // The CDR stream had never seen the given offset before,
- // so check the recursion manager (it will throw an
- // IOException if it doesn't have a reference, either).
- objectValue = activeRecursionMgr.getObject(cdrie.offset);
- }
-
- if ((o == null) || (fields[i].getField() == null)) {
- continue;
- }
-
- try {
- bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
- // reflective code: fields[i].getField().set( o, objectValue ) ;
- } catch (IllegalArgumentException e) {
- ClassCastException exc = new ClassCastException("Assigning instance of class " +
- objectValue.getClass().getName() +
- " to field " +
- currentClassDesc.getName() +
- '#' +
- fields[i].getField().getName());
- exc.initCause( e ) ;
- throw exc ;
- }
- } // end : for loop
- }
- }
-
- /*
- * Read the fields of the specified class from the input stream and set
- * the values of the fields in the specified object. If the specified
- * object is null, just consume the fields without setting any values. If
- * any ObjectStreamField does not have a reflected Field, don't try to set
- * that field in the object.
- */
- private void inputClassFields(Object o, Class cl,
- ObjectStreamClass osc,
- ValueMember[] fields,
- com.sun.org.omg.SendingContext.CodeBase sender)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IOException
- {
- try{
- for (int i = 0; i < fields.length; ++i) {
- try {
- switch (fields[i].type.kind().value()) {
- case TCKind._tk_octet:
- byte byteValue = orbStream.read_octet();
- if ((o != null) && osc.hasField(fields[i]))
- setByteField(o, cl, fields[i].name, byteValue);
- break;
- case TCKind._tk_boolean:
- boolean booleanValue = orbStream.read_boolean();
- if ((o != null) && osc.hasField(fields[i]))
- setBooleanField(o, cl, fields[i].name, booleanValue);
- break;
- case TCKind._tk_char:
- // Backwards compatibility. Older Sun ORBs sent
- // _tk_char even though they read and wrote wchars
- // correctly.
- //
- // Fall through to the _tk_wchar case.
- case TCKind._tk_wchar:
- char charValue = orbStream.read_wchar();
- if ((o != null) && osc.hasField(fields[i]))
- setCharField(o, cl, fields[i].name, charValue);
- break;
- case TCKind._tk_short:
- short shortValue = orbStream.read_short();
- if ((o != null) && osc.hasField(fields[i]))
- setShortField(o, cl, fields[i].name, shortValue);
- break;
- case TCKind._tk_long:
- int intValue = orbStream.read_long();
- if ((o != null) && osc.hasField(fields[i]))
- setIntField(o, cl, fields[i].name, intValue);
- break;
- case TCKind._tk_longlong:
- long longValue = orbStream.read_longlong();
- if ((o != null) && osc.hasField(fields[i]))
- setLongField(o, cl, fields[i].name, longValue);
- break;
- case TCKind._tk_float:
- float floatValue = orbStream.read_float();
- if ((o != null) && osc.hasField(fields[i]))
- setFloatField(o, cl, fields[i].name, floatValue);
- break;
- case TCKind._tk_double:
- double doubleValue = orbStream.read_double();
- if ((o != null) && osc.hasField(fields[i]))
- setDoubleField(o, cl, fields[i].name, doubleValue);
- break;
- case TCKind._tk_value:
- case TCKind._tk_objref:
- case TCKind._tk_value_box:
- Object objectValue = null;
- try {
- objectValue = inputObjectField(fields[i], sender);
- } catch (IndirectionException cdrie) {
- // The CDR stream had never seen the given offset before,
- // so check the recursion manager (it will throw an
- // IOException if it doesn't have a reference, either).
- objectValue = activeRecursionMgr.getObject(cdrie.offset);
- }
-
- if (o == null)
- continue;
- try {
- if (osc.hasField(fields[i])){
- setObjectField(o,
- cl,
- fields[i].name,
- objectValue);
- } else {
- // REVISIT. Convert to a log message.
- // This is a normal case when fields have
- // been added as part of evolution, but
- // silently skipping can make it hard to
- // debug if there's an error
-// System.out.println("**** warning, not setting field: "
-// + fields[i].name
-// + " since not on class "
-// + osc.getName());
-
- }
- } catch (IllegalArgumentException e) {
- // XXX I18N, logging needed.
- ClassCastException cce = new ClassCastException("Assigning instance of class " +
- objectValue.getClass().getName() + " to field " + fields[i].name);
- cce.initCause(e) ;
- throw cce ;
- }
- break;
- default:
- // XXX I18N, logging needed.
- throw new StreamCorruptedException("Unknown kind: "
- + fields[i].type.kind().value());
- }
- } catch (IllegalArgumentException e) {
- /* This case should never happen. If the field types
- are not the same, InvalidClassException is raised when
- matching the local class to the serialized ObjectStreamClass. */
- // XXX I18N, logging needed.
- ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id +
- " to field " + currentClassDesc.getName() + '#' + fields[i].name);
- cce.initCause( e ) ;
- throw cce ;
- }
- }
- } catch(Throwable t){
- // XXX I18N, logging needed.
- StreamCorruptedException sce = new StreamCorruptedException(t.getMessage());
- sce.initCause(t) ;
- throw sce ;
- }
- }
-
- private void skipCustomUsingFVD(ValueMember[] fields,
- com.sun.org.omg.SendingContext.CodeBase sender)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IOException
- {
- readFormatVersion();
- boolean calledDefaultWriteObject = readBoolean();
-
- if (calledDefaultWriteObject)
- throwAwayData(fields, sender);
-
- if (getStreamFormatVersion() == 2) {
-
- ((ValueInputStream)getOrbStream()).start_value();
- ((ValueInputStream)getOrbStream()).end_value();
- }
- }
-
- /*
- * Read the fields of the specified class from the input stream throw data away.
- * This must handle same switch logic as above.
- */
- private void throwAwayData(ValueMember[] fields,
- com.sun.org.omg.SendingContext.CodeBase sender)
- throws InvalidClassException, StreamCorruptedException,
- ClassNotFoundException, IOException
- {
- for (int i = 0; i < fields.length; ++i) {
-
- try {
-
- switch (fields[i].type.kind().value()) {
- case TCKind._tk_octet:
- orbStream.read_octet();
- break;
- case TCKind._tk_boolean:
- orbStream.read_boolean();
- break;
- case TCKind._tk_char:
- // Backwards compatibility. Older Sun ORBs sent
- // _tk_char even though they read and wrote wchars
- // correctly.
- //
- // Fall through to the _tk_wchar case.
- case TCKind._tk_wchar:
- orbStream.read_wchar();
- break;
- case TCKind._tk_short:
- orbStream.read_short();
- break;
- case TCKind._tk_long:
- orbStream.read_long();
- break;
- case TCKind._tk_longlong:
- orbStream.read_longlong();
- break;
- case TCKind._tk_float:
- orbStream.read_float();
- break;
- case TCKind._tk_double:
- orbStream.read_double();
- break;
- case TCKind._tk_value:
- case TCKind._tk_objref:
- case TCKind._tk_value_box:
- Class type = null;
- String id = fields[i].id;
-
- try {
- type = vhandler.getClassFromType(id);
- }
- catch(ClassNotFoundException cnfe){
- // Make sure type = null
- type = null;
- }
- String signature = null;
- if (type != null)
- signature = ValueUtility.getSignature(fields[i]);
-
- // Read value
- try {
- if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
- signature.equals("Ljava/io/Serializable;") ||
- signature.equals("Ljava/io/Externalizable;")) ) {
- javax.rmi.CORBA.Util.readAny(orbStream);
- }
- else {
- // Decide what method call to make based on the type.
- //
- // NOTE : Since FullValueDescription does not allow us
- // to ask whether something is an interface we do not
- // have the ability to optimize this check.
-
- int callType = ValueHandlerImpl.kValueType;
-
- if (!vhandler.isSequence(id)) {
- FullValueDescription fieldFVD = sender.meta(fields[i].id);
- if (kRemoteTypeCode == fields[i].type) {
-
- // RMI Object reference...
- callType = ValueHandlerImpl.kRemoteType;
- } else if (fieldFVD.is_abstract) {
- // RMI Abstract Object reference...
-
- callType = ValueHandlerImpl.kAbstractType;
- }
- }
-
- // Now that we have used the FVD of the field to determine the proper course
- // of action, it is ok to use the type (Class) from this point forward since
- // the rep. id for this read will also follow on the wire.
-
- switch (callType) {
- case ValueHandlerImpl.kRemoteType:
- orbStream.read_Object();
- break;
- case ValueHandlerImpl.kAbstractType:
- orbStream.read_abstract_interface();
- break;
- case ValueHandlerImpl.kValueType:
- if (type != null) {
- orbStream.read_value(type);
- } else {
- orbStream.read_value();
- }
- break;
- default:
- // XXX I18N, logging needed.
- throw new StreamCorruptedException("Unknown callType: "
- + callType);
- }
- }
-
- }
- catch(IndirectionException cdrie) {
- // Since we are throwing this away, don't bother handling recursion.
- continue;
- }
-
- break;
- default:
- // XXX I18N, logging needed.
- throw new StreamCorruptedException("Unknown kind: "
- + fields[i].type.kind().value());
-
- }
- } catch (IllegalArgumentException e) {
- /* This case should never happen. If the field types
- are not the same, InvalidClassException is raised when
- matching the local class to the serialized ObjectStreamClass. */
- // XXX I18N, logging needed.
- ClassCastException cce = new ClassCastException("Assigning instance of class " +
- fields[i].id + " to field " + currentClassDesc.getName() +
- '#' + fields[i].name);
- cce.initCause(e) ;
- throw cce ;
- }
- }
-
- }
-
- private static void setObjectField(Object o, Class c, String fieldName, Object v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putObject( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetObjectField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- ObjectUtility.compactObjectToString( v )) ;
- }
- }
-
- private static void setBooleanField(Object o, Class c, String fieldName, boolean v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putBoolean( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetBooleanField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- new Boolean(v) ) ;
- }
- }
-
- private static void setByteField(Object o, Class c, String fieldName, byte v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putByte( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetByteField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- new Byte(v) ) ;
- }
- }
-
- private static void setCharField(Object o, Class c, String fieldName, char v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putChar( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetCharField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- new Character(v) ) ;
- }
- }
-
- private static void setShortField(Object o, Class c, String fieldName, short v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putShort( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetShortField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- new Short(v) ) ;
- }
- }
-
- private static void setIntField(Object o, Class c, String fieldName, int v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putInt( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetIntField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- new Integer(v) ) ;
- }
- }
-
- private static void setLongField(Object o, Class c, String fieldName, long v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putLong( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetLongField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- new Long(v) ) ;
- }
- }
-
- private static void setFloatField(Object o, Class c, String fieldName, float v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putFloat( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetFloatField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- new Float(v) ) ;
- }
- }
-
- private static void setDoubleField(Object o, Class c, String fieldName, double v)
- {
- try {
- Field fld = c.getDeclaredField( fieldName ) ;
- long key = bridge.objectFieldOffset( fld ) ;
- bridge.putDouble( o, key, v ) ;
- } catch (Exception e) {
- throw utilWrapper.errorSetDoubleField( e, fieldName,
- ObjectUtility.compactObjectToString( o ),
- new Double(v) ) ;
- }
- }
-
- /**
- * This class maintains a map of stream position to
- * an Object currently being deserialized. It is used
- * to handle the cases where the are indirections to
- * an object on the recursion stack. The CDR level
- * handles indirections to objects previously seen
- * (and completely deserialized) in the stream.
- */
- static class ActiveRecursionManager
- {
- private Map offsetToObjectMap;
-
- public ActiveRecursionManager() {
- // A hash map is unsynchronized and allows
- // null values
- offsetToObjectMap = new HashMap();
- }
-
- // Called right after allocating a new object.
- // Offset is the starting position in the stream
- // of the object.
- public void addObject(int offset, Object value) {
- offsetToObjectMap.put(new Integer(offset), value);
- }
-
- // If the given starting position doesn't refer
- // to the beginning of an object currently being
- // deserialized, this throws an IOException.
- // Otherwise, it returns a reference to the
- // object.
- public Object getObject(int offset) throws IOException {
- Integer position = new Integer(offset);
-
- if (!offsetToObjectMap.containsKey(position))
- // XXX I18N, logging needed.
- throw new IOException("Invalid indirection to offset "
- + offset);
-
- return offsetToObjectMap.get(position);
- }
-
- // Called when an object has been completely
- // deserialized, so it should no longer be in
- // this mapping. The CDR level can handle
- // further indirections.
- public void removeObject(int offset) {
- offsetToObjectMap.remove(new Integer(offset));
- }
-
- // If the given offset doesn't map to an Object,
- // then it isn't an indirection to an object
- // currently being deserialized.
- public boolean containsObject(int offset) {
- return offsetToObjectMap.containsKey(new Integer(offset));
- }
- }
-}
--- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java Wed Jul 05 17:23:18 2017 +0200
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java Fri Sep 24 22:42:14 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,103 +50,8 @@
import java.math.BigDecimal ;
public final class ObjectUtility {
- private boolean useToString ;
- private boolean isIndenting ;
- private int initialLevel ;
- private int increment ;
- private ClassMap classToPrinter = new ClassMap() ;
-
- private static ObjectUtility standard = new ObjectUtility( false, true,
- 0, 4 ) ;
- private static ObjectUtility compact = new ObjectUtility( true, false,
- 0, 4 ) ;
-
- private ObjectUtility( boolean useToString, boolean isIndenting,
- int initialLevel, int increment )
- {
- this.useToString = useToString ;
- this.isIndenting = isIndenting ;
- this.initialLevel = initialLevel ;
- this.increment = increment ;
- classToPrinter.put( Properties.class, propertiesPrinter ) ;
- classToPrinter.put( Collection.class, collectionPrinter ) ;
- classToPrinter.put( Map.class, mapPrinter ) ;
- }
-
- /** Construct an Utility instance with the desired objectToString
- * behavior.
- */
- public static ObjectUtility make( boolean useToString, boolean isIndenting,
- int initialLevel, int increment )
- {
- return new ObjectUtility( useToString, isIndenting, initialLevel,
- increment ) ;
- }
-
- /** Construct an Utility instance with the desired objectToString
- * behavior.
- */
- public static ObjectUtility make( boolean useToString, boolean isIndenting )
- {
- return new ObjectUtility( useToString, isIndenting, 0, 4 ) ;
- }
-
- /** Get the standard Utility object that supports objectToString with
- * indented display and no use of toString() methods.
- */
- public static ObjectUtility make()
- {
- return standard ;
- }
+ private ObjectUtility() {}
- /** A convenience method that gives the default behavior: use indenting
- * to display the object's structure and do not use built-in toString
- * methods.
- */
- public static String defaultObjectToString( java.lang.Object object )
- {
- return standard.objectToString( object ) ;
- }
-
- public static String compactObjectToString( java.lang.Object object )
- {
- return compact.objectToString( object ) ;
- }
-
- /** objectToString handles display of arbitrary objects. It correctly
- * handles objects whose elements form an arbitrary graph. It uses
- * reflection to display the contents of any kind of object.
- * An object's toString() method may optionally be used, but the default
- * is to ignore all toString() methods except for those defined for
- * primitive types, primitive type wrappers, and strings.
- */
- public String objectToString(java.lang.Object obj)
- {
- IdentityHashMap printed = new IdentityHashMap() ;
- ObjectWriter result = ObjectWriter.make( isIndenting, initialLevel,
- increment ) ;
- objectToStringHelper( printed, result, obj ) ;
- return result.toString() ;
- }
-
- // Perform a deep structural equality comparison of the two objects.
- // This handles all arrays, maps, and sets specially, otherwise
- // it just calls the object's equals() method.
- public static boolean equals( java.lang.Object obj1, java.lang.Object obj2 )
- {
- // Set of pairs of objects that have been (or are being) considered for
- // equality. Such pairs are presumed to be equals. If they are not,
- // this will be detected eventually and the equals method will return
- // false.
- Set considered = new HashSet() ;
-
- // Map that gives the corresponding component of obj2 for a component
- // of obj1. This is used to check for the same aliasing and use of
- // equal objects in both objects.
- Map counterpart = new IdentityHashMap() ;
-
- return equalsHelper( counterpart, considered, obj1, obj2 ) ;
- }
/** If arr1 and arr2 are both arrays of the same component type,
* return an array of that component type that consists of the
@@ -179,544 +84,4 @@
return result ;
}
-//===========================================================================
-// Implementation
-//===========================================================================
-
- private void objectToStringHelper( IdentityHashMap printed,
- ObjectWriter result, java.lang.Object obj)
- {
- if (obj==null) {
- result.append( "null" ) ;
- result.endElement() ;
- } else {
- Class cls = obj.getClass() ;
- result.startObject( obj ) ;
-
- if (printed.keySet().contains( obj )) {
- result.endObject( "*VISITED*" ) ;
- } else {
- printed.put( obj, null ) ;
-
- if (mustUseToString(cls)) {
- result.endObject( obj.toString() ) ;
- } else {
- // First, handle any classes that have special printer
- // methods defined. This is useful when the class
- // overrides toString with something that
- // is not sufficiently detailed.
- ObjectPrinter printer = (ObjectPrinter)(classToPrinter.get(
- cls )) ;
- if (printer != null) {
- printer.print( printed, result, obj ) ;
- result.endObject() ;
- } else {
- Class compClass = cls.getComponentType() ;
-
- if (compClass == null)
- // handleObject always calls endObject
- handleObject( printed, result, obj ) ;
- else {
- handleArray( printed, result, obj ) ;
- result.endObject() ;
- }
- }
- }
- }
- }
- }
-
- private static interface ObjectPrinter {
- void print( IdentityHashMap printed, ObjectWriter buff,
- java.lang.Object obj ) ;
- }
-
- private ObjectPrinter propertiesPrinter = new ObjectPrinter() {
- public void print( IdentityHashMap printed, ObjectWriter buff,
- java.lang.Object obj )
- {
- if (!(obj instanceof Properties))
- throw new Error() ;
-
- Properties props = (Properties)obj ;
- Enumeration keys = props.propertyNames() ;
- while (keys.hasMoreElements()) {
- String key = (String)(keys.nextElement()) ;
- String value = props.getProperty( key ) ;
- buff.startElement() ;
- buff.append( key ) ;
- buff.append( "=" ) ;
- buff.append( value ) ;
- buff.endElement() ;
- }
- }
- } ;
-
- private ObjectPrinter collectionPrinter = new ObjectPrinter() {
- public void print( IdentityHashMap printed, ObjectWriter buff,
- java.lang.Object obj )
- {
- if (!(obj instanceof Collection))
- throw new Error() ;
-
- Collection coll = (Collection)obj ;
- Iterator iter = coll.iterator() ;
- while (iter.hasNext()) {
- java.lang.Object element = iter.next() ;
- buff.startElement() ;
- objectToStringHelper( printed, buff, element ) ;
- buff.endElement() ;
- }
- }
- } ;
-
- private ObjectPrinter mapPrinter = new ObjectPrinter() {
- public void print( IdentityHashMap printed, ObjectWriter buff,
- java.lang.Object obj )
- {
- if (!(obj instanceof Map))
- throw new Error() ;
-
- Map map = (Map)obj ;
- Iterator iter = map.entrySet().iterator() ;
- while (iter.hasNext()) {
- Entry entry = (Entry)(iter.next()) ;
- buff.startElement() ;
- objectToStringHelper( printed, buff, entry.getKey() ) ;
- buff.append( "=>" ) ;
- objectToStringHelper( printed, buff, entry.getValue() ) ;
- buff.endElement() ;
- }
- }
- } ;
-
- private static class ClassMap {
- ArrayList data ;
-
- public ClassMap()
- {
- data = new ArrayList() ;
- }
-
- /** Return the first element of the ClassMap that is assignable to cls.
- * The order is determined by the order in which the put method was
- * called. Returns null if there is no match.
- */
- public java.lang.Object get( Class cls )
- {
- Iterator iter = data.iterator() ;
- while (iter.hasNext()) {
- java.lang.Object[] arr = (java.lang.Object[])(iter.next()) ;
- Class key = (Class)(arr[0]) ;
- if (key.isAssignableFrom( cls ))
- return arr[1] ;
- }
-
- return null ;
- }
-
- /** Add obj to the map with key cls. Note that order matters,
- * as the first match is returned.
- */
- public void put( Class cls, java.lang.Object obj )
- {
- java.lang.Object[] pair = { cls, obj } ;
- data.add( pair ) ;
- }
- }
-
- private boolean mustUseToString( Class cls )
- {
- // These probably never occur
- if (cls.isPrimitive())
- return true ;
-
- // We must use toString for all primitive wrappers, since
- // otherwise the code recurses endlessly (access value field
- // inside Integer, returns another Integer through reflection).
- if ((cls == Integer.class) ||
- (cls == BigInteger.class) ||
- (cls == BigDecimal.class) ||
- (cls == String.class) ||
- (cls == StringBuffer.class) ||
- (cls == Long.class) ||
- (cls == Short.class) ||
- (cls == Byte.class) ||
- (cls == Character.class) ||
- (cls == Float.class) ||
- (cls == Double.class) ||
- (cls == Boolean.class))
- return true ;
-
- if (useToString) {
- try {
- cls.getDeclaredMethod( "toString", (Class[])null ) ;
- return true ;
- } catch (Exception exc) {
- return false ;
- }
- }
-
- return false ;
- }
-
- private void handleObject( IdentityHashMap printed, ObjectWriter result,
- java.lang.Object obj )
- {
- Class cls = obj.getClass() ;
-
- try {
- Field[] fields;
- SecurityManager security = System.getSecurityManager();
- if (security != null && !Modifier.isPublic(cls.getModifiers())) {
- fields = new Field[0];
- } else {
- fields = cls.getDeclaredFields();
- }
-
- for (int ctr=0; ctr<fields.length; ctr++ ) {
- final Field fld = fields[ctr] ;
- int modifiers = fld.getModifiers() ;
-
- // Do not display field if it is static, since these fields
- // are always the same for every instances. This could
- // be made configurable, but I don't think it is
- // useful to do so.
- if (!Modifier.isStatic( modifiers )) {
- if (security != null) {
- if (!Modifier.isPublic(modifiers))
- continue;
- }
- result.startElement() ;
- result.append( fld.getName() ) ;
- result.append( ":" ) ;
-
- try {
- // Make sure that we can read the field if it is
- // not public
- AccessController.doPrivileged( new PrivilegedAction() {
- public Object run() {
- fld.setAccessible( true ) ;
- return null ;
- }
- } ) ;
-
- java.lang.Object value = fld.get( obj ) ;
- objectToStringHelper( printed, result, value ) ;
- } catch (Exception exc2) {
- result.append( "???" ) ;
- }
-
- result.endElement() ;
- }
- }
-
- result.endObject() ;
- } catch (Exception exc2) {
- result.endObject( obj.toString() ) ;
- }
- }
-
- private void handleArray( IdentityHashMap printed, ObjectWriter result,
- java.lang.Object obj )
- {
- Class compClass = obj.getClass().getComponentType() ;
- if (compClass == boolean.class) {
- boolean[] arr = (boolean[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- result.append( arr[ctr] ) ;
- result.endElement() ;
- }
- } else if (compClass == byte.class) {
- byte[] arr = (byte[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- result.append( arr[ctr] ) ;
- result.endElement() ;
- }
- } else if (compClass == short.class) {
- short[] arr = (short[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- result.append( arr[ctr] ) ;
- result.endElement() ;
- }
- } else if (compClass == int.class) {
- int[] arr = (int[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- result.append( arr[ctr] ) ;
- result.endElement() ;
- }
- } else if (compClass == long.class) {
- long[] arr = (long[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- result.append( arr[ctr] ) ;
- result.endElement() ;
- }
- } else if (compClass == char.class) {
- char[] arr = (char[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- result.append( arr[ctr] ) ;
- result.endElement() ;
- }
- } else if (compClass == float.class) {
- float[] arr = (float[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- result.append( arr[ctr] ) ;
- result.endElement() ;
- }
- } else if (compClass == double.class) {
- double[] arr = (double[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- result.append( arr[ctr] ) ;
- result.endElement() ;
- }
- } else { // array of object
- java.lang.Object[] arr = (java.lang.Object[])obj ;
- for (int ctr=0; ctr<arr.length; ctr++) {
- result.startElement() ;
- objectToStringHelper( printed, result, arr[ctr] ) ;
- result.endElement() ;
- }
- }
- }
-
- private static class Pair
- {
- private java.lang.Object obj1 ;
- private java.lang.Object obj2 ;
-
- Pair( java.lang.Object obj1, java.lang.Object obj2 )
- {
- this.obj1 = obj1 ;
- this.obj2 = obj2 ;
- }
-
- public boolean equals( java.lang.Object obj )
- {
- if (!(obj instanceof Pair))
- return false ;
-
- Pair other = (Pair)obj ;
- return other.obj1 == obj1 && other.obj2 == obj2 ;
- }
-
- public int hashCode()
- {
- return System.identityHashCode( obj1 ) ^
- System.identityHashCode( obj2 ) ;
- }
- }
-
- private static boolean equalsHelper( Map counterpart, Set considered,
- java.lang.Object obj1, java.lang.Object obj2 )
- {
- if ((obj1 == null) || (obj2 == null))
- return obj1 == obj2 ;
-
- java.lang.Object other2 = counterpart.get( obj1 ) ;
- if (other2 == null) {
- other2 = obj2 ;
- counterpart.put( obj1, other2 ) ;
- }
-
- if (obj1 == other2)
- return true ;
-
- if (obj2 != other2)
- return false ;
-
- Pair pair = new Pair( obj1, obj2 ) ;
- if (considered.contains( pair ))
- return true ;
- else
- considered.add( pair ) ;
-
- if (obj1 instanceof java.lang.Object[] &&
- obj2 instanceof java.lang.Object[])
- return equalArrays( counterpart, considered,
- (java.lang.Object[])obj1, (java.lang.Object[])obj2 ) ;
- else if (obj1 instanceof Map && obj2 instanceof Map)
- return equalMaps( counterpart, considered,
- (Map)obj1, (Map)obj2 ) ;
- else if (obj1 instanceof Set && obj2 instanceof Set)
- return equalSets( counterpart, considered,
- (Set)obj1, (Set)obj2 ) ;
- else if (obj1 instanceof List && obj2 instanceof List)
- return equalLists( counterpart, considered,
- (List)obj1, (List)obj2 ) ;
- else if (obj1 instanceof boolean[] && obj2 instanceof boolean[])
- return Arrays.equals( (boolean[])obj1, (boolean[])obj2 ) ;
- else if (obj1 instanceof byte[] && obj2 instanceof byte[])
- return Arrays.equals( (byte[])obj1, (byte[])obj2 ) ;
- else if (obj1 instanceof char[] && obj2 instanceof char[])
- return Arrays.equals( (char[])obj1, (char[])obj2 ) ;
- else if (obj1 instanceof double[] && obj2 instanceof double[])
- return Arrays.equals( (double[])obj1, (double[])obj2 ) ;
- else if (obj1 instanceof float[] && obj2 instanceof float[])
- return Arrays.equals( (float[])obj1, (float[])obj2 ) ;
- else if (obj1 instanceof int[] && obj2 instanceof int[])
- return Arrays.equals( (int[])obj1, (int[])obj2 ) ;
- else if (obj1 instanceof long[] && obj2 instanceof long[])
- return Arrays.equals( (long[])obj1, (long[])obj2 ) ;
- else {
- Class cls = obj1.getClass() ;
- if (cls != obj2.getClass())
- return obj1.equals( obj2 ) ;
- else
- return equalsObject( counterpart, considered, cls, obj1, obj2 ) ;
- }
- }
-
- private static boolean equalsObject( Map counterpart, Set considered,
- Class cls, java.lang.Object obj1, java.lang.Object obj2 )
- {
- Class objectClass = java.lang.Object.class ;
- if (cls == objectClass)
- return true ;
-
- Class[] equalsTypes = { objectClass } ;
- try {
- Method equalsMethod = cls.getDeclaredMethod( "equals",
- equalsTypes ) ;
- return obj1.equals( obj2 ) ;
- } catch (Exception exc) {
- if (equalsObjectFields( counterpart, considered,
- cls, obj1, obj2 ))
- return equalsObject( counterpart, considered,
- cls.getSuperclass(), obj1, obj2 ) ;
- else
- return false ;
- }
- }
-
- private static boolean equalsObjectFields( Map counterpart, Set considered,
- Class cls, java.lang.Object obj1, java.lang.Object obj2 )
- {
- Field[] fields = cls.getDeclaredFields() ;
- for (int ctr=0; ctr<fields.length; ctr++) {
- try {
- final Field field = fields[ctr] ;
- // Ignore static fields
- if (!Modifier.isStatic( field.getModifiers())) {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- field.setAccessible( true ) ;
- return null ;
- }
- } ) ;
-
- java.lang.Object value1 = field.get( obj1 ) ;
- java.lang.Object value2 = field.get( obj2 ) ;
- if (!equalsHelper( counterpart, considered, value1,
- value2 ))
- return false ;
- }
- } catch (IllegalAccessException exc) {
- return false ;
- }
- }
-
- return true ;
- }
-
- private static boolean equalArrays( Map counterpart, Set considered,
- java.lang.Object[] arr1, java.lang.Object[] arr2 )
- {
- int len = arr1.length ;
- if (len != arr2.length)
- return false ;
-
- for (int ctr = 0; ctr<len; ctr++ )
- if (!equalsHelper( counterpart, considered, arr1[ctr], arr2[ctr] ))
- return false ;
-
- return true ;
- }
-
- private static boolean equalMaps( Map counterpart, Set considered,
- Map map1, Map map2 )
- {
- if (map2.size() != map1.size())
- return false;
-
- try {
- Iterator i = map1.entrySet().iterator();
- while (i.hasNext()) {
- Entry e = (Entry) i.next();
- java.lang.Object key = e.getKey();
- java.lang.Object value = e.getValue();
- if (value == null) {
- if (!(map2.get(key)==null && map2.containsKey(key)))
- return false;
- } else {
- if (!equalsHelper( counterpart, considered,
- value, map2.get(key)))
- return false;
- }
- }
- } catch(ClassCastException unused) {
- return false;
- } catch(NullPointerException unused) {
- return false;
- }
-
- return true;
- }
-
- // Obviously this is an inefficient quadratic algorithm.
- // This is taken pretty directly from AbstractSet and AbstractCollection
- // in the JDK.
- // For HashSet, an O(n) (with a good hash function) algorithm
- // is possible, and likewise TreeSet, since it is
- // ordered, is O(n). But this is not worth the effort here.
- // Note that the inner loop uses equals, not equalsHelper.
- // This is needed because of the searching behavior of this test.
- // However, note that this will NOT correctly handle sets that
- // contain themselves as members, or that have members that reference
- // themselves. These cases will cause infinite regress!
- private static boolean equalSets( Map counterpart, Set considered,
- Set set1, Set set2 )
- {
- if (set1.size() != set2.size())
- return false ;
-
- Iterator e1 = set1.iterator() ;
- while (e1.hasNext()) {
- java.lang.Object obj1 = e1.next() ;
-
- boolean found = false ;
- Iterator e2 = set2.iterator() ;
- while (e2.hasNext() && !found) {
- java.lang.Object obj2 = e2.next() ;
- found = equals( obj1, obj2 ) ;
- }
-
- if (!found)
- return false ;
- }
-
- return true ;
- }
-
- private static boolean equalLists( Map counterpart, Set considered,
- List list1, List list2 )
- {
- ListIterator e1 = list1.listIterator();
- ListIterator e2 = list2.listIterator();
- while(e1.hasNext() && e2.hasNext()) {
- java.lang.Object o1 = e1.next();
- java.lang.Object o2 = e2.next();
- if (!(o1==null ? o2==null : equalsHelper(
- counterpart, considered, o1, o2)))
- return false;
- }
- return !(e1.hasNext() || e2.hasNext());
- }
}