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