Wed, 22 Jun 2016 18:25:00 +0100
8146975: NullPointerException in IIOPInputStream.inputClassFields
Reviewed-by: chegar, rriggs, coffeys
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 if (!currentClassDesc.forClass().isAssignableFrom(
571 currentObject.getClass())) {
572 throw new IOException("Object Type mismatch");
573 }
575 // The array will be null unless fields were retrieved
576 // remotely because of a serializable version difference.
577 // Bug fix for 4365188. See the definition of
578 // defaultReadObjectFVDMembers for more information.
579 if (defaultReadObjectFVDMembers != null &&
580 defaultReadObjectFVDMembers.length > 0) {
582 // WARNING: Be very careful! What if some of
583 // these fields actually have to do this, too?
584 // This works because the defaultReadObjectFVDMembers
585 // reference is passed to inputClassFields, but
586 // there is no guarantee that
587 // defaultReadObjectFVDMembers will point to the
588 // same array after calling inputClassFields.
590 // Use the remote fields to unmarshal.
591 inputClassFields(currentObject,
592 currentClass,
593 currentClassDesc,
594 defaultReadObjectFVDMembers,
595 cbSender);
597 } else {
599 // Use the local fields to unmarshal.
600 ObjectStreamField[] fields =
601 currentClassDesc.getFieldsNoCopy();
602 if (fields.length > 0) {
603 inputClassFields(currentObject, currentClass, fields, cbSender);
604 }
605 }
606 }
607 catch(NotActiveException nae)
608 {
609 bridge.throwException( nae ) ;
610 }
611 catch(IOException ioe)
612 {
613 bridge.throwException( ioe ) ;
614 }
615 catch(ClassNotFoundException cnfe)
616 {
617 bridge.throwException( cnfe ) ;
618 }
620 }
622 /**
623 * Override the actions of the final method "enableResolveObject()"
624 * in ObjectInputStream.
625 * @since JDK1.1.6
626 *
627 * Enable the stream to allow objects read from the stream to be replaced.
628 * If the stream is a trusted class it is allowed to enable replacment.
629 * Trusted classes are those classes with a classLoader equals null. <p>
630 *
631 * When enabled the resolveObject method is called for every object
632 * being deserialized.
633 *
634 * @exception SecurityException The classloader of this stream object is non-null.
635 * @since JDK1.1
636 */
637 public final boolean enableResolveObjectDelegate(boolean enable)
638 /* throws SecurityException */
639 {
640 return false;
641 }
643 // The following three methods allow the implementing orbStream
644 // to provide mark/reset behavior as defined in java.io.InputStream.
646 public final void mark(int readAheadLimit) {
647 orbStream.mark(readAheadLimit);
648 }
650 public final boolean markSupported() {
651 return orbStream.markSupported();
652 }
654 public final void reset() throws IOException {
655 try {
656 orbStream.reset();
657 } catch (Error e) {
658 IOException err = new IOException(e.getMessage());
659 err.initCause(e) ;
660 throw err ;
661 }
662 }
664 public final int available() throws IOException{
665 return 0; // unreliable
666 }
668 public final void close() throws IOException{
669 // no op
670 }
672 public final int read() throws IOException{
673 try{
674 readObjectState.readData(this);
676 return (orbStream.read_octet() << 0) & 0x000000FF;
677 } catch (MARSHAL marshalException) {
678 if (marshalException.minor
679 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
680 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
681 return -1;
682 }
684 throw marshalException;
685 } catch(Error e) {
686 IOException exc = new IOException(e.getMessage());
687 exc.initCause(e) ;
688 throw exc ;
689 }
690 }
692 public final int read(byte data[], int offset, int length) throws IOException{
693 try{
694 readObjectState.readData(this);
696 orbStream.read_octet_array(data, offset, length);
697 return length;
698 } catch (MARSHAL marshalException) {
699 if (marshalException.minor
700 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
701 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
702 return -1;
703 }
705 throw marshalException;
706 } catch(Error e) {
707 IOException exc = new IOException(e.getMessage());
708 exc.initCause(e) ;
709 throw exc ;
710 }
712 }
714 public final boolean readBoolean() throws IOException{
715 try{
716 readObjectState.readData(this);
718 return orbStream.read_boolean();
719 } catch (MARSHAL marshalException) {
720 handleOptionalDataMarshalException(marshalException, false);
721 throw marshalException;
723 } catch(Error e) {
724 IOException exc = new IOException(e.getMessage());
725 exc.initCause(e);
726 throw exc ;
727 }
728 }
730 public final byte readByte() throws IOException{
731 try{
732 readObjectState.readData(this);
734 return orbStream.read_octet();
735 } catch (MARSHAL marshalException) {
736 handleOptionalDataMarshalException(marshalException, false);
737 throw marshalException;
739 } catch(Error e) {
740 IOException exc = new IOException(e.getMessage());
741 exc.initCause(e);
742 throw exc ;
743 }
744 }
746 public final char readChar() throws IOException{
747 try{
748 readObjectState.readData(this);
750 return orbStream.read_wchar();
751 } catch (MARSHAL marshalException) {
752 handleOptionalDataMarshalException(marshalException, false);
753 throw marshalException;
755 } catch(Error e) {
756 IOException exc = new IOException(e.getMessage());
757 exc.initCause(e);
758 throw exc ;
759 }
760 }
762 public final double readDouble() throws IOException{
763 try{
764 readObjectState.readData(this);
766 return orbStream.read_double();
767 } catch (MARSHAL marshalException) {
768 handleOptionalDataMarshalException(marshalException, false);
769 throw marshalException;
770 } catch(Error e) {
771 IOException exc = new IOException(e.getMessage());
772 exc.initCause(e);
773 throw exc ;
774 }
775 }
777 public final float readFloat() throws IOException{
778 try{
779 readObjectState.readData(this);
781 return orbStream.read_float();
782 } catch (MARSHAL marshalException) {
783 handleOptionalDataMarshalException(marshalException, false);
784 throw marshalException;
785 } catch(Error e) {
786 IOException exc = new IOException(e.getMessage());
787 exc.initCause(e);
788 throw exc ;
789 }
790 }
792 public final void readFully(byte data[]) throws IOException{
793 // d11623 : implement readFully, required for serializing some core classes
795 readFully(data, 0, data.length);
796 }
798 public final void readFully(byte data[], int offset, int size) throws IOException{
799 // d11623 : implement readFully, required for serializing some core classes
800 try{
801 readObjectState.readData(this);
803 orbStream.read_octet_array(data, offset, size);
804 } catch (MARSHAL marshalException) {
805 handleOptionalDataMarshalException(marshalException, false);
807 throw marshalException;
808 } catch(Error e) {
809 IOException exc = new IOException(e.getMessage());
810 exc.initCause(e);
811 throw exc ;
812 }
813 }
815 public final int readInt() throws IOException{
816 try{
817 readObjectState.readData(this);
819 return orbStream.read_long();
820 } catch (MARSHAL marshalException) {
821 handleOptionalDataMarshalException(marshalException, false);
822 throw marshalException;
823 } catch(Error e) {
824 IOException exc = new IOException(e.getMessage());
825 exc.initCause(e);
826 throw exc ;
827 }
828 }
830 public final String readLine() throws IOException{
831 // XXX I18N, logging needed.
832 throw new IOException("Method readLine not supported");
833 }
835 public final long readLong() throws IOException{
836 try{
837 readObjectState.readData(this);
839 return orbStream.read_longlong();
840 } catch (MARSHAL marshalException) {
841 handleOptionalDataMarshalException(marshalException, false);
842 throw marshalException;
843 } catch(Error e) {
844 IOException exc = new IOException(e.getMessage());
845 exc.initCause(e);
846 throw exc ;
847 }
848 }
850 public final short readShort() throws IOException{
851 try{
852 readObjectState.readData(this);
854 return orbStream.read_short();
855 } catch (MARSHAL marshalException) {
856 handleOptionalDataMarshalException(marshalException, false);
857 throw marshalException;
858 } catch(Error e) {
859 IOException exc = new IOException(e.getMessage());
860 exc.initCause(e);
861 throw exc ;
862 }
863 }
865 protected final void readStreamHeader() throws IOException, StreamCorruptedException{
866 // no op
867 }
869 public final int readUnsignedByte() throws IOException{
870 try{
871 readObjectState.readData(this);
873 return (orbStream.read_octet() << 0) & 0x000000FF;
874 } catch (MARSHAL marshalException) {
875 handleOptionalDataMarshalException(marshalException, false);
876 throw marshalException;
877 } catch(Error e) {
878 IOException exc = new IOException(e.getMessage());
879 exc.initCause(e);
880 throw exc ;
881 }
882 }
884 public final int readUnsignedShort() throws IOException{
885 try{
886 readObjectState.readData(this);
888 return (orbStream.read_ushort() << 0) & 0x0000FFFF;
889 } catch (MARSHAL marshalException) {
890 handleOptionalDataMarshalException(marshalException, false);
891 throw marshalException;
892 } catch(Error e) {
893 IOException exc = new IOException(e.getMessage());
894 exc.initCause(e);
895 throw exc ;
896 }
897 }
899 /**
900 * Helper method for correcting the Kestrel bug 4367783 (dealing
901 * with larger than 8-bit chars). The old behavior is preserved
902 * in orbutil.IIOPInputStream_1_3 in order to interoperate with
903 * our legacy ORBs.
904 */
905 protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream)
906 {
907 return stream.read_wstring();
908 }
910 public final String readUTF() throws IOException{
911 try{
912 readObjectState.readData(this);
914 return internalReadUTF(orbStream);
915 } catch (MARSHAL marshalException) {
916 handleOptionalDataMarshalException(marshalException, false);
917 throw marshalException;
918 } catch(Error e) {
919 IOException exc = new IOException(e.getMessage());
920 exc.initCause(e);
921 throw exc ;
922 }
923 }
925 // If the ORB stream detects an incompatibility between what's
926 // on the wire and what our Serializable's readObject wants,
927 // it throws a MARSHAL exception with a specific minor code.
928 // This is rethrown to the readObject as an OptionalDataException.
929 // So far in RMI-IIOP, this process isn't specific enough to
930 // tell the readObject how much data is available, so we always
931 // set the OptionalDataException's EOF marker to true.
932 private void handleOptionalDataMarshalException(MARSHAL marshalException,
933 boolean objectRead)
934 throws IOException {
936 // Java Object Serialization spec 3.4: "If the readObject method
937 // of the class attempts to read more data than is present in the
938 // optional part of the stream for this class, the stream will
939 // return -1 for bytewise reads, throw an EOFException for
940 // primitive data reads, or throw an OptionalDataException
941 // with the eof field set to true for object reads."
942 if (marshalException.minor
943 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
945 IOException result;
947 if (!objectRead)
948 result = new EOFException("No more optional data");
949 else
950 result = createOptionalDataException();
952 result.initCause(marshalException);
954 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
956 throw result;
957 }
958 }
960 public final synchronized void registerValidation(ObjectInputValidation obj,
961 int prio)
962 throws NotActiveException, InvalidObjectException{
963 // XXX I18N, logging needed.
964 throw new Error("Method registerValidation not supported");
965 }
967 protected final Class resolveClass(ObjectStreamClass v)
968 throws IOException, ClassNotFoundException{
969 // XXX I18N, logging needed.
970 throw new IOException("Method resolveClass not supported");
971 }
973 protected final Object resolveObject(Object obj) throws IOException{
974 // XXX I18N, logging needed.
975 throw new IOException("Method resolveObject not supported");
976 }
978 public final int skipBytes(int len) throws IOException{
979 try{
980 readObjectState.readData(this);
982 byte buf[] = new byte[len];
983 orbStream.read_octet_array(buf, 0, len);
984 return len;
985 } catch (MARSHAL marshalException) {
986 handleOptionalDataMarshalException(marshalException, false);
988 throw marshalException;
989 } catch(Error e) {
990 IOException exc = new IOException(e.getMessage());
991 exc.initCause(e) ;
992 throw exc ;
993 }
994 }
996 private synchronized Object inputObject(Class clz,
997 String repositoryID,
998 com.sun.org.omg.SendingContext.CodeBase sender,
999 int offset)
1000 throws IOException, ClassNotFoundException
1001 {
1003 /*
1004 * Get the descriptor and then class of the incoming object.
1005 */
1007 currentClassDesc = ObjectStreamClass.lookup(clz);
1008 currentClass = currentClassDesc.forClass();
1009 //currentClassDesc.setClass(currentClass);
1010 if (currentClass == null)
1011 // XXX I18N, logging needed.
1012 throw new ClassNotFoundException(currentClassDesc.getName());
1014 try {
1015 /* If Externalizable,
1016 * Create an instance and tell it to read its data.
1017 * else,
1018 * Handle it as a serializable class.
1019 */
1020 if (Enum.class.isAssignableFrom( clz )) {
1021 int ordinal = orbStream.read_long() ;
1022 String value = (String)orbStream.read_value( String.class ) ;
1023 return Enum.valueOf( clz, value ) ;
1024 } else if (currentClassDesc.isExternalizable()) {
1025 try {
1026 currentObject = (currentClass == null) ?
1027 null : currentClassDesc.newInstance();
1028 if (currentObject != null) {
1030 // Store this object and its beginning position
1031 // since there might be indirections to it while
1032 // it's been unmarshalled.
1033 activeRecursionMgr.addObject(offset, currentObject);
1035 // Read format version
1036 readFormatVersion();
1038 Externalizable ext = (Externalizable)currentObject;
1039 ext.readExternal(this);
1040 }
1041 } catch (InvocationTargetException e) {
1042 InvalidClassException exc = new InvalidClassException(
1043 currentClass.getName(),
1044 "InvocationTargetException accessing no-arg constructor");
1045 exc.initCause( e ) ;
1046 throw exc ;
1047 } catch (UnsupportedOperationException e) {
1048 InvalidClassException exc = new InvalidClassException(
1049 currentClass.getName(),
1050 "UnsupportedOperationException accessing no-arg constructor");
1051 exc.initCause( e ) ;
1052 throw exc ;
1053 } catch (InstantiationException e) {
1054 InvalidClassException exc = new InvalidClassException(
1055 currentClass.getName(),
1056 "InstantiationException accessing no-arg constructor");
1057 exc.initCause( e ) ;
1058 throw exc ;
1059 }
1060 } // end : if (currentClassDesc.isExternalizable())
1061 else {
1062 /* Count number of classes and descriptors we might have
1063 * to work on.
1064 */
1066 ObjectStreamClass currdesc = currentClassDesc;
1067 Class currclass = currentClass;
1069 int spBase = spClass; // current top of stack
1071 if (currentClass.getName().equals("java.lang.String")) {
1072 return this.readUTF();
1073 }
1074 /* The object's classes should be processed from supertype to subtype
1075 * Push all the clases of the current object onto a stack.
1076 * Note that only the serializable classes are represented
1077 * in the descriptor list.
1078 *
1079 * Handle versioning where one or more supertypes of
1080 * have been inserted or removed. The stack will
1081 * contain pairs of descriptors and the corresponding
1082 * class. If the object has a class that did not occur in
1083 * the original the descriptor will be null. If the
1084 * original object had a descriptor for a class not
1085 * present in the local hierarchy of the object the class will be
1086 * null.
1087 *
1088 */
1090 /*
1091 * This is your basic diff pattern, made simpler
1092 * because reordering is not allowed.
1093 */
1094 // sun.4296963 ibm.11861
1095 // d11861 we should stop when we find the highest serializable class
1096 // We need this so that when we allocate the new object below, we
1097 // can call the constructor of the non-serializable superclass.
1098 // Note that in the JRMP variant of this code the
1099 // ObjectStreamClass.lookup() method handles this, but we've put
1100 // this fix here rather than change lookup because the new behaviour
1101 // is needed in other cases.
1103 for (currdesc = currentClassDesc, currclass = currentClass;
1104 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
1105 currdesc = currdesc.getSuperclass()) {
1107 /*
1108 * Search the classes to see if the class of this
1109 * descriptor appears further up the hierarchy. Until
1110 * it's found assume its an inserted class. If it's
1111 * not found, its the descriptor's class that has been
1112 * removed.
1113 */
1114 Class cc = currdesc.forClass();
1115 Class cl;
1116 for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
1117 if (cc == cl) {
1118 // found a superclass that matches this descriptor
1119 break;
1120 } else {
1121 /* Ignore a class that doesn't match. No
1122 * action is needed since it is already
1123 * initialized.
1124 */
1125 }
1126 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
1127 /* Test if there is room for this new entry.
1128 * If not, double the size of the arrays and copy the contents.
1129 */
1130 spClass++;
1131 if (spClass >= classes.length) {
1132 int newlen = classes.length * 2;
1133 Class[] newclasses = new Class[newlen];
1134 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
1136 System.arraycopy(classes, 0,
1137 newclasses, 0,
1138 classes.length);
1139 System.arraycopy(classdesc, 0,
1140 newclassdesc, 0,
1141 classes.length);
1143 classes = newclasses;
1144 classdesc = newclassdesc;
1145 }
1147 if (cl == null) {
1148 /* Class not found corresponding to this descriptor.
1149 * Pop off all the extra classes pushed.
1150 * Push the descriptor and a null class.
1151 */
1152 classdesc[spClass] = currdesc;
1153 classes[spClass] = null;
1154 } else {
1155 /* Current class descriptor matches current class.
1156 * Some classes may have been inserted.
1157 * Record the match and advance the class, continue
1158 * with the next descriptor.
1159 */
1160 classdesc[spClass] = currdesc;
1161 classes[spClass] = cl;
1162 currclass = cl.getSuperclass();
1163 }
1164 } // end : for (currdesc = currentClassDesc, currclass = currentClass;
1166 /* Allocate a new object. The object is only constructed
1167 * above the highest serializable class and is set to
1168 * default values for all more specialized classes.
1169 */
1170 try {
1171 currentObject = (currentClass == null) ?
1172 null : currentClassDesc.newInstance() ;
1174 // Store this object and its beginning position
1175 // since there might be indirections to it while
1176 // it's been unmarshalled.
1177 activeRecursionMgr.addObject(offset, currentObject);
1178 } catch (InvocationTargetException e) {
1179 InvalidClassException exc = new InvalidClassException(
1180 currentClass.getName(),
1181 "InvocationTargetException accessing no-arg constructor");
1182 exc.initCause( e ) ;
1183 throw exc ;
1184 } catch (UnsupportedOperationException e) {
1185 InvalidClassException exc = new InvalidClassException(
1186 currentClass.getName(),
1187 "UnsupportedOperationException accessing no-arg constructor");
1188 exc.initCause( e ) ;
1189 throw exc ;
1190 } catch (InstantiationException e) {
1191 InvalidClassException exc = new InvalidClassException(
1192 currentClass.getName(),
1193 "InstantiationException accessing no-arg constructor");
1194 exc.initCause( e ) ;
1195 throw exc ;
1196 }
1198 /*
1199 * For all the pushed descriptors and classes.
1200 * if the class has its own writeObject and readObject methods
1201 * call the readObject method
1202 * else
1203 * invoke the defaultReadObject method
1204 */
1205 try {
1206 for (spClass = spClass; spClass > spBase; spClass--) {
1207 /*
1208 * Set current descriptor and corresponding class
1209 */
1210 currentClassDesc = classdesc[spClass];
1211 currentClass = classes[spClass];
1212 if (classes[spClass] != null) {
1213 /* Read the data from the stream described by the
1214 * descriptor and store into the matching class.
1215 */
1217 ReadObjectState oldState = readObjectState;
1218 setState(DEFAULT_STATE);
1220 try {
1222 // Changed since invokeObjectReader no longer does this.
1223 if (currentClassDesc.hasWriteObject()) {
1225 // Read format version
1226 readFormatVersion();
1228 // Read defaultWriteObject indicator
1229 boolean calledDefaultWriteObject = readBoolean();
1231 readObjectState.beginUnmarshalCustomValue(this,
1232 calledDefaultWriteObject,
1233 (currentClassDesc.readObjectMethod
1234 != null));
1235 } else {
1236 if (currentClassDesc.hasReadObject())
1237 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
1238 }
1240 if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) ||
1241 readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) {
1243 // Error case of no readObject and didn't call
1244 // defaultWriteObject handled in default state
1246 ObjectStreamField[] fields =
1247 currentClassDesc.getFieldsNoCopy();
1248 if (fields.length > 0) {
1249 inputClassFields(currentObject, currentClass, fields, sender);
1250 }
1251 }
1253 if (currentClassDesc.hasWriteObject())
1254 readObjectState.endUnmarshalCustomValue(this);
1256 } finally {
1257 setState(oldState);
1258 }
1260 } else {
1262 // _REVISIT_ : Can we ever get here?
1263 /* No local class for this descriptor,
1264 * Skip over the data for this class.
1265 * like defaultReadObject with a null currentObject.
1266 * The code will read the values but discard them.
1267 */
1268 ObjectStreamField[] fields =
1269 currentClassDesc.getFieldsNoCopy();
1270 if (fields.length > 0) {
1271 inputClassFields(null, currentClass, fields, sender);
1272 }
1274 }
1276 }
1277 } finally {
1278 // Make sure we exit at the same stack level as when we started.
1279 spClass = spBase;
1280 }
1281 }
1282 } finally {
1283 // We've completed deserializing this object. Any
1284 // future indirections will be handled correctly at the
1285 // CDR level. The ActiveRecursionManager only deals with
1286 // objects currently being deserialized.
1287 activeRecursionMgr.removeObject(offset);
1288 }
1290 return currentObject;
1291 }
1293 // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
1294 // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable
1295 // classes!
1296 private Vector getOrderedDescriptions(String repositoryID,
1297 com.sun.org.omg.SendingContext.CodeBase sender) {
1298 Vector descs = new Vector();
1300 if (sender == null) {
1301 return descs;
1302 }
1304 FullValueDescription aFVD = sender.meta(repositoryID);
1305 while (aFVD != null) {
1306 descs.insertElementAt(aFVD, 0);
1307 if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
1308 aFVD = sender.meta(aFVD.base_value);
1309 }
1310 else return descs;
1311 }
1313 return descs;
1314 }
1316 /**
1317 * This input method uses FullValueDescriptions retrieved from the sender's runtime to
1318 * read in the data. This method is capable of throwing out data not applicable to client's fields.
1319 * This method handles instances where the reader has a class not sent by the sender, the sender sent
1320 * a class not present on the reader, and/or the reader's class does not match the sender's class.
1321 *
1322 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
1323 * indicates custom marsahling than the local type is used to read the data off the wire. However,
1324 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
1325 * a form of custom marshaling.
1326 *
1327 */
1328 private synchronized Object inputObjectUsingFVD(Class clz,
1329 String repositoryID,
1330 com.sun.org.omg.SendingContext.CodeBase sender,
1331 int offset)
1332 throws IOException, ClassNotFoundException
1333 {
1334 int spBase = spClass; // current top of stack
1335 try{
1337 /*
1338 * Get the descriptor and then class of the incoming object.
1339 */
1341 ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
1342 Class currclass = currentClass = clz;
1344 /* If Externalizable,
1345 * Create an instance and tell it to read its data.
1346 * else,
1347 * Handle it as a serializable class.
1348 */
1349 if (currentClassDesc.isExternalizable()) {
1350 try {
1351 currentObject = (currentClass == null) ?
1352 null : currentClassDesc.newInstance();
1353 if (currentObject != null) {
1354 // Store this object and its beginning position
1355 // since there might be indirections to it while
1356 // it's been unmarshalled.
1357 activeRecursionMgr.addObject(offset, currentObject);
1359 // Read format version
1360 readFormatVersion();
1362 Externalizable ext = (Externalizable)currentObject;
1363 ext.readExternal(this);
1364 }
1365 } catch (InvocationTargetException e) {
1366 InvalidClassException exc = new InvalidClassException(
1367 currentClass.getName(),
1368 "InvocationTargetException accessing no-arg constructor");
1369 exc.initCause( e ) ;
1370 throw exc ;
1371 } catch (UnsupportedOperationException e) {
1372 InvalidClassException exc = new InvalidClassException(
1373 currentClass.getName(),
1374 "UnsupportedOperationException accessing no-arg constructor");
1375 exc.initCause( e ) ;
1376 throw exc ;
1377 } catch (InstantiationException e) {
1378 InvalidClassException exc = new InvalidClassException(
1379 currentClass.getName(),
1380 "InstantiationException accessing no-arg constructor");
1381 exc.initCause( e ) ;
1382 throw exc ;
1383 }
1384 } else {
1385 /*
1386 * This is your basic diff pattern, made simpler
1387 * because reordering is not allowed.
1388 */
1389 for (currdesc = currentClassDesc, currclass = currentClass;
1390 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
1392 currdesc = currdesc.getSuperclass()) {
1394 /*
1395 * Search the classes to see if the class of this
1396 * descriptor appears further up the hierarchy. Until
1397 * it's found assume its an inserted class. If it's
1398 * not found, its the descriptor's class that has been
1399 * removed.
1400 */
1401 Class cc = currdesc.forClass();
1402 Class cl;
1403 for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
1404 if (cc == cl) {
1405 // found a superclass that matches this descriptor
1406 break;
1407 } else {
1408 /* Ignore a class that doesn't match. No
1409 * action is needed since it is already
1410 * initialized.
1411 */
1412 }
1413 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
1414 /* Test if there is room for this new entry.
1415 * If not, double the size of the arrays and copy the contents.
1416 */
1417 spClass++;
1418 if (spClass >= classes.length) {
1419 int newlen = classes.length * 2;
1420 Class[] newclasses = new Class[newlen];
1421 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
1423 System.arraycopy(classes, 0,
1424 newclasses, 0,
1425 classes.length);
1426 System.arraycopy(classdesc, 0,
1427 newclassdesc, 0,
1428 classes.length);
1430 classes = newclasses;
1431 classdesc = newclassdesc;
1432 }
1434 if (cl == null) {
1435 /* Class not found corresponding to this descriptor.
1436 * Pop off all the extra classes pushed.
1437 * Push the descriptor and a null class.
1438 */
1439 classdesc[spClass] = currdesc;
1440 classes[spClass] = null;
1441 } else {
1442 /* Current class descriptor matches current class.
1443 * Some classes may have been inserted.
1444 * Record the match and advance the class, continue
1445 * with the next descriptor.
1446 */
1447 classdesc[spClass] = currdesc;
1448 classes[spClass] = cl;
1449 currclass = cl.getSuperclass();
1450 }
1451 } // end : for (currdesc = currentClassDesc, currclass = currentClass;
1453 /* Allocate a new object.
1454 */
1455 try {
1456 currentObject = (currentClass == null) ?
1457 null : currentClassDesc.newInstance();
1459 // Store this object and its beginning position
1460 // since there might be indirections to it while
1461 // it's been unmarshalled.
1462 activeRecursionMgr.addObject(offset, currentObject);
1463 } catch (InvocationTargetException e) {
1464 InvalidClassException exc = new InvalidClassException(
1465 currentClass.getName(),
1466 "InvocationTargetException accessing no-arg constructor");
1467 exc.initCause( e ) ;
1468 throw exc ;
1469 } catch (UnsupportedOperationException e) {
1470 InvalidClassException exc = new InvalidClassException(
1471 currentClass.getName(),
1472 "UnsupportedOperationException accessing no-arg constructor");
1473 exc.initCause( e ) ;
1474 throw exc ;
1475 } catch (InstantiationException e) {
1476 InvalidClassException exc = new InvalidClassException(
1477 currentClass.getName(),
1478 "InstantiationException accessing no-arg constructor");
1479 exc.initCause( e ) ;
1480 throw exc ;
1481 }
1483 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
1485 while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
1486 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1487 // d4365188: backward compatability
1488 String repIDForFVD = vhandler.getClassName(fvd.id);
1489 String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
1491 while ((spClass > spBase) &&
1492 (!repIDForFVD.equals(repIDForClass))) {
1493 int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
1494 if (pos != -1) {
1495 spClass = pos;
1496 currclass = currentClass = classes[spClass];
1497 repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
1498 }
1499 else { // Read and throw away one level of the fvdslist
1501 // This seems to mean that the sender had a superclass that
1502 // we don't have
1504 if (fvd.is_custom) {
1506 readFormatVersion();
1507 boolean calledDefaultWriteObject = readBoolean();
1509 if (calledDefaultWriteObject)
1510 inputClassFields(null, null, null, fvd.members, sender);
1512 if (getStreamFormatVersion() == 2) {
1514 ((ValueInputStream)getOrbStream()).start_value();
1515 ((ValueInputStream)getOrbStream()).end_value();
1516 }
1518 // WARNING: If stream format version is 1 and there's
1519 // optional data, we'll get some form of exception down
1520 // the line or data corruption.
1522 } else {
1524 inputClassFields(null, currentClass, null, fvd.members, sender);
1525 }
1527 if (fvdsList.hasMoreElements()){
1528 fvd = (FullValueDescription)fvdsList.nextElement();
1529 repIDForFVD = vhandler.getClassName(fvd.id);
1530 }
1531 else return currentObject;
1532 }
1533 }
1535 currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
1537 if (!repIDForClass.equals("java.lang.Object")) {
1539 // If the sender used custom marshaling, then it should have put
1540 // the two bytes on the wire indicating stream format version
1541 // and whether or not the writeObject method called
1542 // defaultWriteObject/writeFields.
1544 ReadObjectState oldState = readObjectState;
1545 setState(DEFAULT_STATE);
1547 try {
1549 if (fvd.is_custom) {
1551 // Read format version
1552 readFormatVersion();
1554 // Read defaultWriteObject indicator
1555 boolean calledDefaultWriteObject = readBoolean();
1557 readObjectState.beginUnmarshalCustomValue(this,
1558 calledDefaultWriteObject,
1559 (currentClassDesc.readObjectMethod
1560 != null));
1561 }
1563 boolean usedReadObject = false;
1565 // Always use readObject if it exists, and fall back to default
1566 // unmarshaling if it doesn't.
1567 try {
1569 if (!fvd.is_custom && currentClassDesc.hasReadObject())
1570 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
1572 // See the definition of defaultReadObjectFVDMembers
1573 // for more information. This concerns making sure
1574 // we use the remote FVD's members in defaultReadObject.
1575 defaultReadObjectFVDMembers = fvd.members;
1576 usedReadObject = invokeObjectReader(currentClassDesc,
1577 currentObject,
1578 currentClass);
1580 } finally {
1581 defaultReadObjectFVDMembers = null;
1582 }
1584 // Note that the !usedReadObject !calledDefaultWriteObject
1585 // case is handled by the beginUnmarshalCustomValue method
1586 // of the default state
1587 if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT)
1588 inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
1590 if (fvd.is_custom)
1591 readObjectState.endUnmarshalCustomValue(this);
1593 } finally {
1594 setState(oldState);
1595 }
1597 currclass = currentClass = classes[--spClass];
1599 } else {
1601 // The remaining hierarchy of the local class does not match the sender's FVD.
1602 // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate
1603 // custom marshaling, throw MARSHAL error.
1604 inputClassFields(null, currentClass, null, fvd.members, sender);
1606 while (fvdsList.hasMoreElements()){
1607 fvd = (FullValueDescription)fvdsList.nextElement();
1609 if (fvd.is_custom)
1610 skipCustomUsingFVD(fvd.members, sender);
1611 else
1612 inputClassFields(null, currentClass, null, fvd.members, sender);
1613 }
1615 }
1617 } // end : while(fvdsList.hasMoreElements())
1618 while (fvdsList.hasMoreElements()){
1620 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1621 if (fvd.is_custom)
1622 skipCustomUsingFVD(fvd.members, sender);
1623 else
1624 throwAwayData(fvd.members, sender);
1625 }
1626 }
1628 return currentObject;
1629 }
1630 finally {
1631 // Make sure we exit at the same stack level as when we started.
1632 spClass = spBase;
1634 // We've completed deserializing this object. Any
1635 // future indirections will be handled correctly at the
1636 // CDR level. The ActiveRecursionManager only deals with
1637 // objects currently being deserialized.
1638 activeRecursionMgr.removeObject(offset);
1639 }
1641 }
1643 /**
1644 * This input method uses FullValueDescriptions retrieved from the sender's runtime to
1645 * read in the data. This method is capable of throwing out data not applicable to client's fields.
1646 *
1647 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
1648 * indicates custom marsahling than the local type is used to read the data off the wire. However,
1649 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
1650 * a form of custom marshaling.
1651 *
1652 */
1653 private Object skipObjectUsingFVD(String repositoryID,
1654 com.sun.org.omg.SendingContext.CodeBase sender)
1655 throws IOException, ClassNotFoundException
1656 {
1658 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
1660 while(fvdsList.hasMoreElements()) {
1661 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1662 String repIDForFVD = vhandler.getClassName(fvd.id);
1664 if (!repIDForFVD.equals("java.lang.Object")) {
1665 if (fvd.is_custom) {
1667 readFormatVersion();
1669 boolean calledDefaultWriteObject = readBoolean();
1671 if (calledDefaultWriteObject)
1672 inputClassFields(null, null, null, fvd.members, sender);
1674 if (getStreamFormatVersion() == 2) {
1676 ((ValueInputStream)getOrbStream()).start_value();
1677 ((ValueInputStream)getOrbStream()).end_value();
1678 }
1680 // WARNING: If stream format version is 1 and there's
1681 // optional data, we'll get some form of exception down
1682 // the line.
1684 } else {
1685 // Use default marshaling
1686 inputClassFields(null, null, null, fvd.members, sender);
1687 }
1688 }
1690 } // end : while(fvdsList.hasMoreElements())
1691 return null;
1693 }
1695 ///////////////////
1697 private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){
1699 for (int i = _spClass; i > _spBase; i--){
1700 if (classname.equals(classes[i].getName())) {
1701 return i;
1702 }
1703 }
1705 return -1;
1706 }
1708 /*
1709 * Invoke the readObject method if present. Assumes that in the case of custom
1710 * marshaling, the format version and defaultWriteObject indicator were already
1711 * removed.
1712 */
1713 private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass)
1714 throws InvalidClassException, StreamCorruptedException,
1715 ClassNotFoundException, IOException
1716 {
1717 if (osc.readObjectMethod == null) {
1718 return false;
1719 }
1721 try {
1722 osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
1723 return true;
1724 } catch (InvocationTargetException e) {
1725 Throwable t = e.getTargetException();
1726 if (t instanceof ClassNotFoundException)
1727 throw (ClassNotFoundException)t;
1728 else if (t instanceof IOException)
1729 throw (IOException)t;
1730 else if (t instanceof RuntimeException)
1731 throw (RuntimeException) t;
1732 else if (t instanceof Error)
1733 throw (Error) t;
1734 else
1735 // XXX I18N, logging needed.
1736 throw new Error("internal error");
1737 } catch (IllegalAccessException e) {
1738 return false;
1739 }
1740 }
1742 /*
1743 * Reset the stream to be just like it was after the constructor.
1744 */
1745 private void resetStream() throws IOException {
1747 if (classes == null)
1748 classes = new Class[20];
1749 else {
1750 for (int i = 0; i < classes.length; i++)
1751 classes[i] = null;
1752 }
1753 if (classdesc == null)
1754 classdesc = new ObjectStreamClass[20];
1755 else {
1756 for (int i = 0; i < classdesc.length; i++)
1757 classdesc[i] = null;
1758 }
1759 spClass = 0;
1761 if (callbacks != null)
1762 callbacks.setSize(0); // discard any pending callbacks
1763 }
1765 /**
1766 * Factored out of inputClassFields This reads a primitive value and sets it
1767 * in the field of o described by the ObjectStreamField field.
1768 *
1769 * Note that reflection cannot be used here, because reflection cannot be used
1770 * to set final fields.
1771 */
1772 private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field)
1773 throws InvalidClassException, IOException {
1775 try {
1776 switch (field.getTypeCode()) {
1777 case 'B':
1778 byte byteValue = orbStream.read_octet();
1779 if (field.getField() != null) {
1780 bridge.putByte( o, field.getFieldID(), byteValue ) ;
1781 //reflective code: field.getField().setByte( o, byteValue ) ;
1782 }
1783 break;
1784 case 'Z':
1785 boolean booleanValue = orbStream.read_boolean();
1786 if (field.getField() != null) {
1787 bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
1788 //reflective code: field.getField().setBoolean( o, booleanValue ) ;
1789 }
1790 break;
1791 case 'C':
1792 char charValue = orbStream.read_wchar();
1793 if (field.getField() != null) {
1794 bridge.putChar( o, field.getFieldID(), charValue ) ;
1795 //reflective code: field.getField().setChar( o, charValue ) ;
1796 }
1797 break;
1798 case 'S':
1799 short shortValue = orbStream.read_short();
1800 if (field.getField() != null) {
1801 bridge.putShort( o, field.getFieldID(), shortValue ) ;
1802 //reflective code: field.getField().setShort( o, shortValue ) ;
1803 }
1804 break;
1805 case 'I':
1806 int intValue = orbStream.read_long();
1807 if (field.getField() != null) {
1808 bridge.putInt( o, field.getFieldID(), intValue ) ;
1809 //reflective code: field.getField().setInt( o, intValue ) ;
1810 }
1811 break;
1812 case 'J':
1813 long longValue = orbStream.read_longlong();
1814 if (field.getField() != null) {
1815 bridge.putLong( o, field.getFieldID(), longValue ) ;
1816 //reflective code: field.getField().setLong( o, longValue ) ;
1817 }
1818 break;
1819 case 'F' :
1820 float floatValue = orbStream.read_float();
1821 if (field.getField() != null) {
1822 bridge.putFloat( o, field.getFieldID(), floatValue ) ;
1823 //reflective code: field.getField().setFloat( o, floatValue ) ;
1824 }
1825 break;
1826 case 'D' :
1827 double doubleValue = orbStream.read_double();
1828 if (field.getField() != null) {
1829 bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
1830 //reflective code: field.getField().setDouble( o, doubleValue ) ;
1831 }
1832 break;
1833 default:
1834 // XXX I18N, logging needed.
1835 throw new InvalidClassException(cl.getName());
1836 }
1837 } catch (IllegalArgumentException e) {
1838 /* This case should never happen. If the field types
1839 are not the same, InvalidClassException is raised when
1840 matching the local class to the serialized ObjectStreamClass. */
1841 ClassCastException cce = new ClassCastException("Assigning instance of class " +
1842 field.getType().getName() +
1843 " to field " +
1844 currentClassDesc.getName() + '#' +
1845 field.getField().getName());
1846 cce.initCause( e ) ;
1847 throw cce ;
1848 }
1849 }
1851 private Object inputObjectField(org.omg.CORBA.ValueMember field,
1852 com.sun.org.omg.SendingContext.CodeBase sender)
1853 throws IndirectionException, ClassNotFoundException, IOException,
1854 StreamCorruptedException {
1856 Object objectValue = null;
1857 Class type = null;
1858 String id = field.id;
1860 try {
1861 type = vhandler.getClassFromType(id);
1862 } catch(ClassNotFoundException cnfe) {
1863 // Make sure type = null
1864 type = null;
1865 }
1867 String signature = null;
1868 if (type != null)
1869 signature = ValueUtility.getSignature(field);
1871 if (signature != null && (signature.equals("Ljava/lang/Object;") ||
1872 signature.equals("Ljava/io/Serializable;") ||
1873 signature.equals("Ljava/io/Externalizable;"))) {
1874 objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
1875 } else {
1876 // Decide what method call to make based on the type. If
1877 // it is a type for which we need to load a stub, convert
1878 // the type to the correct stub type.
1879 //
1880 // NOTE : Since FullValueDescription does not allow us
1881 // to ask whether something is an interface we do not
1882 // have the ability to optimize this check.
1884 int callType = ValueHandlerImpl.kValueType;
1886 if (!vhandler.isSequence(id)) {
1888 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
1890 // RMI Object reference...
1891 callType = ValueHandlerImpl.kRemoteType;
1893 } else {
1895 // REVISIT. If we don't have the local class,
1896 // we should probably verify that it's an RMI type,
1897 // query the remote FVD, and use is_abstract.
1898 // Our FVD seems to get NullPointerExceptions for any
1899 // non-RMI types.
1901 // This uses the local class in the same way as
1902 // inputObjectField(ObjectStreamField) does. REVISIT
1903 // inputObjectField(ObjectStreamField)'s loadStubClass
1904 // logic. Assumption is that the given type cannot
1905 // evolve to become a CORBA abstract interface or
1906 // a RMI abstract interface.
1908 if (type != null && type.isInterface() &&
1909 (vhandler.isAbstractBase(type) ||
1910 ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
1912 callType = ValueHandlerImpl.kAbstractType;
1913 }
1914 }
1915 }
1917 // Now that we have used the FVD of the field to determine the proper course
1918 // of action, it is ok to use the type (Class) from this point forward since
1919 // the rep. id for this read will also follow on the wire.
1921 switch (callType) {
1922 case ValueHandlerImpl.kRemoteType:
1923 if (type != null)
1924 objectValue = Utility.readObjectAndNarrow(orbStream, type);
1925 else
1926 objectValue = orbStream.read_Object();
1927 break;
1928 case ValueHandlerImpl.kAbstractType:
1929 if (type != null)
1930 objectValue = Utility.readAbstractAndNarrow(orbStream, type);
1931 else
1932 objectValue = orbStream.read_abstract_interface();
1933 break;
1934 case ValueHandlerImpl.kValueType:
1935 if (type != null)
1936 objectValue = orbStream.read_value(type);
1937 else
1938 objectValue = orbStream.read_value();
1939 break;
1940 default:
1941 // XXX I18N, logging needed.
1942 throw new StreamCorruptedException("Unknown callType: " + callType);
1943 }
1944 }
1946 return objectValue;
1947 }
1949 /**
1950 * Factored out of inputClassFields and reused in
1951 * inputCurrentClassFieldsForReadFields.
1952 *
1953 * Reads the field (which of an Object type as opposed to a primitive)
1954 * described by ObjectStreamField field and returns it.
1955 */
1956 private Object inputObjectField(ObjectStreamField field)
1957 throws InvalidClassException, StreamCorruptedException,
1958 ClassNotFoundException, IndirectionException, IOException {
1960 if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
1961 return javax.rmi.CORBA.Util.readAny(orbStream);
1962 }
1964 Object objectValue = null;
1966 // fields have an API to provide the actual class
1967 // corresponding to the data type
1968 // Class type = osc.forClass();
1969 Class fieldType = field.getType();
1970 Class actualType = fieldType; // This may change if stub loaded.
1972 // Decide what method call to make based on the fieldType. If
1973 // it is a type for which we need to load a stub, convert
1974 // the type to the correct stub type.
1976 int callType = ValueHandlerImpl.kValueType;
1977 boolean narrow = false;
1979 if (fieldType.isInterface()) {
1980 boolean loadStubClass = false;
1982 if (java.rmi.Remote.class.isAssignableFrom(fieldType)) {
1984 // RMI Object reference...
1985 callType = ValueHandlerImpl.kRemoteType;
1987 } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){
1989 // IDL Object reference...
1990 callType = ValueHandlerImpl.kRemoteType;
1991 loadStubClass = true;
1993 } else if (vhandler.isAbstractBase(fieldType)) {
1994 // IDL Abstract Object reference...
1996 callType = ValueHandlerImpl.kAbstractType;
1997 loadStubClass = true;
1998 } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
1999 // RMI Abstract Object reference...
2001 callType = ValueHandlerImpl.kAbstractType;
2002 }
2004 if (loadStubClass) {
2005 try {
2006 String codebase = Util.getCodebase(fieldType);
2007 String repID = vhandler.createForAnyType(fieldType);
2008 Class stubType =
2009 Utility.loadStubClass(repID, codebase, fieldType);
2010 actualType = stubType;
2011 } catch (ClassNotFoundException e) {
2012 narrow = true;
2013 }
2014 } else {
2015 narrow = true;
2016 }
2017 }
2019 switch (callType) {
2020 case ValueHandlerImpl.kRemoteType:
2021 if (!narrow)
2022 objectValue = (Object)orbStream.read_Object(actualType);
2023 else
2024 objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
2025 break;
2026 case ValueHandlerImpl.kAbstractType:
2027 if (!narrow)
2028 objectValue = (Object)orbStream.read_abstract_interface(actualType);
2029 else
2030 objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
2031 break;
2032 case ValueHandlerImpl.kValueType:
2033 objectValue = (Object)orbStream.read_value(actualType);
2034 break;
2035 default:
2036 // XXX I18N, logging needed.
2037 throw new StreamCorruptedException("Unknown callType: " + callType);
2038 }
2040 return objectValue;
2041 }
2043 private final boolean mustUseRemoteValueMembers() {
2044 return defaultReadObjectFVDMembers != null;
2045 }
2047 void readFields(java.util.Map fieldToValueMap)
2048 throws InvalidClassException, StreamCorruptedException,
2049 ClassNotFoundException, IOException {
2051 if (mustUseRemoteValueMembers()) {
2052 inputRemoteMembersForReadFields(fieldToValueMap);
2053 } else
2054 inputCurrentClassFieldsForReadFields(fieldToValueMap);
2055 }
2057 private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
2058 throws InvalidClassException, StreamCorruptedException,
2059 ClassNotFoundException, IOException {
2061 // Must have this local variable since defaultReadObjectFVDMembers
2062 // may get mangled by recursion.
2063 ValueMember fields[] = defaultReadObjectFVDMembers;
2065 try {
2067 for (int i = 0; i < fields.length; i++) {
2069 switch (fields[i].type.kind().value()) {
2071 case TCKind._tk_octet:
2072 byte byteValue = orbStream.read_octet();
2073 fieldToValueMap.put(fields[i].name, new Byte(byteValue));
2074 break;
2075 case TCKind._tk_boolean:
2076 boolean booleanValue = orbStream.read_boolean();
2077 fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
2078 break;
2079 case TCKind._tk_char:
2080 // Backwards compatibility. Older Sun ORBs sent
2081 // _tk_char even though they read and wrote wchars
2082 // correctly.
2083 //
2084 // Fall through to the _tk_wchar case.
2085 case TCKind._tk_wchar:
2086 char charValue = orbStream.read_wchar();
2087 fieldToValueMap.put(fields[i].name, new Character(charValue));
2088 break;
2089 case TCKind._tk_short:
2090 short shortValue = orbStream.read_short();
2091 fieldToValueMap.put(fields[i].name, new Short(shortValue));
2092 break;
2093 case TCKind._tk_long:
2094 int intValue = orbStream.read_long();
2095 fieldToValueMap.put(fields[i].name, new Integer(intValue));
2096 break;
2097 case TCKind._tk_longlong:
2098 long longValue = orbStream.read_longlong();
2099 fieldToValueMap.put(fields[i].name, new Long(longValue));
2100 break;
2101 case TCKind._tk_float:
2102 float floatValue = orbStream.read_float();
2103 fieldToValueMap.put(fields[i].name, new Float(floatValue));
2104 break;
2105 case TCKind._tk_double:
2106 double doubleValue = orbStream.read_double();
2107 fieldToValueMap.put(fields[i].name, new Double(doubleValue));
2108 break;
2109 case TCKind._tk_value:
2110 case TCKind._tk_objref:
2111 case TCKind._tk_value_box:
2112 Object objectValue = null;
2113 try {
2114 objectValue = inputObjectField(fields[i],
2115 cbSender);
2117 } catch (IndirectionException cdrie) {
2118 // The CDR stream had never seen the given offset before,
2119 // so check the recursion manager (it will throw an
2120 // IOException if it doesn't have a reference, either).
2121 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2122 }
2124 fieldToValueMap.put(fields[i].name, objectValue);
2125 break;
2126 default:
2127 // XXX I18N, logging needed.
2128 throw new StreamCorruptedException("Unknown kind: "
2129 + fields[i].type.kind().value());
2130 }
2131 }
2132 } catch (Throwable t) {
2133 StreamCorruptedException result = new StreamCorruptedException(t.getMessage());
2134 result.initCause(t);
2135 throw result;
2136 }
2137 }
2139 /**
2140 * Called from InputStreamHook.
2141 *
2142 * Reads the fields of the current class (could be the ones
2143 * queried from the remote FVD) and puts them in
2144 * the given Map, name to value. Wraps primitives in the
2145 * corresponding java.lang Objects.
2146 */
2147 private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
2148 throws InvalidClassException, StreamCorruptedException,
2149 ClassNotFoundException, IOException {
2151 ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
2153 int primFields = fields.length - currentClassDesc.objFields;
2155 // Handle the primitives first
2156 for (int i = 0; i < primFields; ++i) {
2158 switch (fields[i].getTypeCode()) {
2159 case 'B':
2160 byte byteValue = orbStream.read_octet();
2161 fieldToValueMap.put(fields[i].getName(),
2162 new Byte(byteValue));
2163 break;
2164 case 'Z':
2165 boolean booleanValue = orbStream.read_boolean();
2166 fieldToValueMap.put(fields[i].getName(),
2167 new Boolean(booleanValue));
2168 break;
2169 case 'C':
2170 char charValue = orbStream.read_wchar();
2171 fieldToValueMap.put(fields[i].getName(),
2172 new Character(charValue));
2173 break;
2174 case 'S':
2175 short shortValue = orbStream.read_short();
2176 fieldToValueMap.put(fields[i].getName(),
2177 new Short(shortValue));
2178 break;
2179 case 'I':
2180 int intValue = orbStream.read_long();
2181 fieldToValueMap.put(fields[i].getName(),
2182 new Integer(intValue));
2183 break;
2184 case 'J':
2185 long longValue = orbStream.read_longlong();
2186 fieldToValueMap.put(fields[i].getName(),
2187 new Long(longValue));
2188 break;
2189 case 'F' :
2190 float floatValue = orbStream.read_float();
2191 fieldToValueMap.put(fields[i].getName(),
2192 new Float(floatValue));
2193 break;
2194 case 'D' :
2195 double doubleValue = orbStream.read_double();
2196 fieldToValueMap.put(fields[i].getName(),
2197 new Double(doubleValue));
2198 break;
2199 default:
2200 // XXX I18N, logging needed.
2201 throw new InvalidClassException(currentClassDesc.getName());
2202 }
2203 }
2205 /* Read and set object fields from the input stream. */
2206 if (currentClassDesc.objFields > 0) {
2207 for (int i = primFields; i < fields.length; i++) {
2208 Object objectValue = null;
2209 try {
2210 objectValue = inputObjectField(fields[i]);
2211 } catch(IndirectionException cdrie) {
2212 // The CDR stream had never seen the given offset before,
2213 // so check the recursion manager (it will throw an
2214 // IOException if it doesn't have a reference, either).
2215 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2216 }
2218 fieldToValueMap.put(fields[i].getName(), objectValue);
2219 }
2220 }
2221 }
2223 /*
2224 * Read the fields of the specified class from the input stream and set
2225 * the values of the fields in the specified object. If the specified
2226 * object is null, just consume the fields without setting any values. If
2227 * any ObjectStreamField does not have a reflected Field, don't try to set
2228 * that field in the object.
2229 *
2230 * REVISIT -- This code doesn't do what the comment says to when
2231 * getField() is null!
2232 */
2233 private void inputClassFields(Object o, final Class<?> cl,
2234 ObjectStreamField[] fields,
2235 com.sun.org.omg.SendingContext.CodeBase sender)
2236 throws InvalidClassException, StreamCorruptedException,
2237 ClassNotFoundException, IOException
2238 {
2240 int primFields = fields.length - currentClassDesc.objFields;
2242 if (o != null) {
2243 for (int i = 0; i < primFields; ++i) {
2244 inputPrimitiveField(o, cl, fields[i]);
2245 }
2246 }
2248 /* Read and set object fields from the input stream. */
2249 if (currentClassDesc.objFields > 0) {
2250 for (int i = primFields; i < fields.length; i++) {
2251 Object objectValue = null;
2253 try {
2254 objectValue = inputObjectField(fields[i]);
2255 } catch(IndirectionException cdrie) {
2256 // The CDR stream had never seen the given offset before,
2257 // so check the recursion manager (it will throw an
2258 // IOException if it doesn't have a reference, either).
2259 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2260 }
2262 if ((o == null) || (fields[i].getField() == null)) {
2263 continue;
2264 }
2266 try {
2267 Class<?> fieldCl = fields[i].getClazz();
2268 if ((objectValue != null)
2269 && (!fieldCl.isAssignableFrom(
2270 objectValue.getClass()))) {
2271 throw new IllegalArgumentException("Field mismatch");
2272 }
2273 Field declaredClassField = null;
2274 final String inputStreamFieldName = fields[i].getName();
2275 try {
2276 declaredClassField = getDeclaredField( cl, inputStreamFieldName);
2277 } catch (PrivilegedActionException paEx) {
2278 throw new IllegalArgumentException(
2279 (NoSuchFieldException) paEx.getException());
2280 } catch (SecurityException secEx) {
2281 throw new IllegalArgumentException(secEx);
2282 } catch (NullPointerException npEx) {
2283 continue;
2284 } catch (NoSuchFieldException e) {
2285 continue;
2286 }
2288 if (declaredClassField == null) {
2289 continue;
2290 }
2291 Class<?> declaredFieldClass = declaredClassField.getType();
2293 // check input field type is a declared field type
2294 // input field is a subclass of the declared field
2295 if (!declaredFieldClass.isAssignableFrom(fieldCl)) {
2296 throw new IllegalArgumentException(
2297 "Field Type mismatch");
2298 }
2299 if (objectValue != null && !fieldCl.isInstance(objectValue)) {
2300 throw new IllegalArgumentException();
2301 }
2302 bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
2303 // reflective code: fields[i].getField().set( o, objectValue ) ;
2304 } catch (IllegalArgumentException iaEx) {
2305 String objectValueClassName = "null";
2306 String currentClassDescClassName = "null";
2307 String fieldName = "null";
2308 if (objectValue != null) {
2309 objectValueClassName = objectValue.getClass().getName();
2310 }
2311 if (currentClassDesc != null) {
2312 currentClassDescClassName = currentClassDesc.getName();
2313 }
2314 if (fields[i] != null && fields[i].getField() != null) {
2315 fieldName = fields[i].getField().getName();
2316 }
2317 ClassCastException ccEx = new ClassCastException(
2318 "Assigning instance of class " + objectValueClassName
2319 + " to field " + currentClassDescClassName + '#' + fieldName);
2320 ccEx.initCause( iaEx ) ;
2321 throw ccEx ;
2322 }
2323 } // end : for loop
2324 }
2325 }
2327 /*
2328 * Read the fields of the specified class from the input stream and set
2329 * the values of the fields in the specified object. If the specified
2330 * object is null, just consume the fields without setting any values. If
2331 * any ObjectStreamField does not have a reflected Field, don't try to set
2332 * that field in the object.
2333 */
2334 private void inputClassFields(Object o, Class cl,
2335 ObjectStreamClass osc,
2336 ValueMember[] fields,
2337 com.sun.org.omg.SendingContext.CodeBase sender)
2338 throws InvalidClassException, StreamCorruptedException,
2339 ClassNotFoundException, IOException
2340 {
2341 try{
2342 for (int i = 0; i < fields.length; ++i) {
2343 try {
2344 switch (fields[i].type.kind().value()) {
2345 case TCKind._tk_octet:
2346 byte byteValue = orbStream.read_octet();
2347 if ((o != null) && osc.hasField(fields[i]))
2348 setByteField(o, cl, fields[i].name, byteValue);
2349 break;
2350 case TCKind._tk_boolean:
2351 boolean booleanValue = orbStream.read_boolean();
2352 if ((o != null) && osc.hasField(fields[i]))
2353 setBooleanField(o, cl, fields[i].name, booleanValue);
2354 break;
2355 case TCKind._tk_char:
2356 // Backwards compatibility. Older Sun ORBs sent
2357 // _tk_char even though they read and wrote wchars
2358 // correctly.
2359 //
2360 // Fall through to the _tk_wchar case.
2361 case TCKind._tk_wchar:
2362 char charValue = orbStream.read_wchar();
2363 if ((o != null) && osc.hasField(fields[i]))
2364 setCharField(o, cl, fields[i].name, charValue);
2365 break;
2366 case TCKind._tk_short:
2367 short shortValue = orbStream.read_short();
2368 if ((o != null) && osc.hasField(fields[i]))
2369 setShortField(o, cl, fields[i].name, shortValue);
2370 break;
2371 case TCKind._tk_long:
2372 int intValue = orbStream.read_long();
2373 if ((o != null) && osc.hasField(fields[i]))
2374 setIntField(o, cl, fields[i].name, intValue);
2375 break;
2376 case TCKind._tk_longlong:
2377 long longValue = orbStream.read_longlong();
2378 if ((o != null) && osc.hasField(fields[i]))
2379 setLongField(o, cl, fields[i].name, longValue);
2380 break;
2381 case TCKind._tk_float:
2382 float floatValue = orbStream.read_float();
2383 if ((o != null) && osc.hasField(fields[i]))
2384 setFloatField(o, cl, fields[i].name, floatValue);
2385 break;
2386 case TCKind._tk_double:
2387 double doubleValue = orbStream.read_double();
2388 if ((o != null) && osc.hasField(fields[i]))
2389 setDoubleField(o, cl, fields[i].name, doubleValue);
2390 break;
2391 case TCKind._tk_value:
2392 case TCKind._tk_objref:
2393 case TCKind._tk_value_box:
2394 Object objectValue = null;
2395 try {
2396 objectValue = inputObjectField(fields[i], sender);
2397 } catch (IndirectionException cdrie) {
2398 // The CDR stream had never seen the given offset before,
2399 // so check the recursion manager (it will throw an
2400 // IOException if it doesn't have a reference, either).
2401 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2402 }
2404 if (o == null)
2405 continue;
2406 try {
2407 if (osc.hasField(fields[i])){
2408 setObjectField(o,
2409 cl,
2410 fields[i].name,
2411 objectValue);
2412 } else {
2413 // REVISIT. Convert to a log message.
2414 // This is a normal case when fields have
2415 // been added as part of evolution, but
2416 // silently skipping can make it hard to
2417 // debug if there's an error
2418 // System.out.println("**** warning, not setting field: "
2419 // + fields[i].name
2420 // + " since not on class "
2421 // + osc.getName());
2423 }
2424 } catch (IllegalArgumentException e) {
2425 // XXX I18N, logging needed.
2426 ClassCastException cce = new ClassCastException("Assigning instance of class " +
2427 objectValue.getClass().getName() + " to field " + fields[i].name);
2428 cce.initCause(e) ;
2429 throw cce ;
2430 }
2431 break;
2432 default:
2433 // XXX I18N, logging needed.
2434 throw new StreamCorruptedException("Unknown kind: "
2435 + fields[i].type.kind().value());
2436 }
2437 } catch (IllegalArgumentException e) {
2438 /* This case should never happen. If the field types
2439 are not the same, InvalidClassException is raised when
2440 matching the local class to the serialized ObjectStreamClass. */
2441 // XXX I18N, logging needed.
2442 ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id +
2443 " to field " + currentClassDesc.getName() + '#' + fields[i].name);
2444 cce.initCause( e ) ;
2445 throw cce ;
2446 }
2447 }
2448 } catch(Throwable t){
2449 // XXX I18N, logging needed.
2450 StreamCorruptedException sce = new StreamCorruptedException(t.getMessage());
2451 sce.initCause(t) ;
2452 throw sce ;
2453 }
2454 }
2456 private void skipCustomUsingFVD(ValueMember[] fields,
2457 com.sun.org.omg.SendingContext.CodeBase sender)
2458 throws InvalidClassException, StreamCorruptedException,
2459 ClassNotFoundException, IOException
2460 {
2461 readFormatVersion();
2462 boolean calledDefaultWriteObject = readBoolean();
2464 if (calledDefaultWriteObject)
2465 throwAwayData(fields, sender);
2467 if (getStreamFormatVersion() == 2) {
2469 ((ValueInputStream)getOrbStream()).start_value();
2470 ((ValueInputStream)getOrbStream()).end_value();
2471 }
2472 }
2474 /*
2475 * Read the fields of the specified class from the input stream throw data away.
2476 * This must handle same switch logic as above.
2477 */
2478 private void throwAwayData(ValueMember[] fields,
2479 com.sun.org.omg.SendingContext.CodeBase sender)
2480 throws InvalidClassException, StreamCorruptedException,
2481 ClassNotFoundException, IOException {
2483 for (int i = 0; i < fields.length; ++i) {
2485 try {
2487 switch (fields[i].type.kind().value()) {
2488 case TCKind._tk_octet:
2489 orbStream.read_octet();
2490 break;
2491 case TCKind._tk_boolean:
2492 orbStream.read_boolean();
2493 break;
2494 case TCKind._tk_char:
2495 // Backwards compatibility. Older Sun ORBs sent
2496 // _tk_char even though they read and wrote wchars
2497 // correctly.
2498 //
2499 // Fall through to the _tk_wchar case.
2500 case TCKind._tk_wchar:
2501 orbStream.read_wchar();
2502 break;
2503 case TCKind._tk_short:
2504 orbStream.read_short();
2505 break;
2506 case TCKind._tk_long:
2507 orbStream.read_long();
2508 break;
2509 case TCKind._tk_longlong:
2510 orbStream.read_longlong();
2511 break;
2512 case TCKind._tk_float:
2513 orbStream.read_float();
2514 break;
2515 case TCKind._tk_double:
2516 orbStream.read_double();
2517 break;
2518 case TCKind._tk_value:
2519 case TCKind._tk_objref:
2520 case TCKind._tk_value_box:
2521 Class type = null;
2522 String id = fields[i].id;
2524 try {
2525 type = vhandler.getClassFromType(id);
2526 }
2527 catch(ClassNotFoundException cnfe){
2528 // Make sure type = null
2529 type = null;
2530 }
2531 String signature = null;
2532 if (type != null)
2533 signature = ValueUtility.getSignature(fields[i]);
2535 // Read value
2536 try {
2537 if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
2538 signature.equals("Ljava/io/Serializable;") ||
2539 signature.equals("Ljava/io/Externalizable;")) ) {
2540 javax.rmi.CORBA.Util.readAny(orbStream);
2541 }
2542 else {
2543 // Decide what method call to make based on the type.
2544 //
2545 // NOTE : Since FullValueDescription does not allow us
2546 // to ask whether something is an interface we do not
2547 // have the ability to optimize this check.
2549 int callType = ValueHandlerImpl.kValueType;
2551 if (!vhandler.isSequence(id)) {
2552 FullValueDescription fieldFVD = sender.meta(fields[i].id);
2553 if (kRemoteTypeCode == fields[i].type) {
2555 // RMI Object reference...
2556 callType = ValueHandlerImpl.kRemoteType;
2557 } else if (fieldFVD.is_abstract) {
2558 // RMI Abstract Object reference...
2560 callType = ValueHandlerImpl.kAbstractType;
2561 }
2562 }
2564 // Now that we have used the FVD of the field to determine the proper course
2565 // of action, it is ok to use the type (Class) from this point forward since
2566 // the rep. id for this read will also follow on the wire.
2568 switch (callType) {
2569 case ValueHandlerImpl.kRemoteType:
2570 orbStream.read_Object();
2571 break;
2572 case ValueHandlerImpl.kAbstractType:
2573 orbStream.read_abstract_interface();
2574 break;
2575 case ValueHandlerImpl.kValueType:
2576 if (type != null) {
2577 orbStream.read_value(type);
2578 } else {
2579 orbStream.read_value();
2580 }
2581 break;
2582 default:
2583 // XXX I18N, logging needed.
2584 throw new StreamCorruptedException("Unknown callType: "
2585 + callType);
2586 }
2587 }
2589 }
2590 catch(IndirectionException cdrie) {
2591 // Since we are throwing this away, don't bother handling recursion.
2592 continue;
2593 }
2595 break;
2596 default:
2597 // XXX I18N, logging needed.
2598 throw new StreamCorruptedException("Unknown kind: "
2599 + fields[i].type.kind().value());
2601 }
2602 } catch (IllegalArgumentException e) {
2603 /* This case should never happen. If the field types
2604 are not the same, InvalidClassException is raised when
2605 matching the local class to the serialized ObjectStreamClass. */
2606 // XXX I18N, logging needed.
2607 ClassCastException cce = new ClassCastException("Assigning instance of class " +
2608 fields[i].id + " to field " + currentClassDesc.getName() +
2609 '#' + fields[i].name);
2610 cce.initCause(e) ;
2611 throw cce ;
2612 }
2613 }
2615 }
2617 private static void setObjectField(Object o, Class<?> c, String fieldName, Object v) {
2618 try {
2619 Field fld = getDeclaredField( c, fieldName ) ;
2620 Class fieldCl = fld.getType();
2621 if(v != null && !fieldCl.isInstance(v)) {
2622 throw new Exception();
2623 }
2624 long key = bridge.objectFieldOffset( fld ) ;
2625 bridge.putObject( o, key, v ) ;
2626 } catch (Exception e) {
2627 if (o != null) {
2628 throw utilWrapper.errorSetObjectField( e, fieldName,
2629 o.toString(),
2630 v.toString() ) ;
2631 } else {
2632 throw utilWrapper.errorSetObjectField( e, fieldName,
2633 "null " + c.getName() + " object",
2634 v.toString() ) ;
2635 }
2636 }
2637 }
2639 private static void setBooleanField(Object o, Class<?> c, String fieldName, boolean v)
2640 {
2641 try {
2642 Field fld = getDeclaredField( c, fieldName ) ;
2643 if ((fld != null) && (fld.getType() == Boolean.TYPE)) {
2644 long key = bridge.objectFieldOffset( fld ) ;
2645 bridge.putBoolean( o, key, v ) ;
2646 } else {
2647 throw new InvalidObjectException("Field Type mismatch");
2648 }
2649 } catch (Exception e) {
2650 if (o != null) {
2651 throw utilWrapper.errorSetBooleanField( e, fieldName,
2652 o.toString(),
2653 new Boolean(v) ) ;
2654 } else {
2655 throw utilWrapper.errorSetBooleanField( e, fieldName,
2656 "null " + c.getName() + " object",
2657 new Boolean(v) ) ;
2658 }
2659 }
2660 }
2662 private static void setByteField(Object o, Class<?> c, String fieldName, byte v)
2663 {
2664 try {
2665 Field fld = getDeclaredField( c, fieldName ) ;
2666 if ((fld != null) && (fld.getType() == Byte.TYPE)) {
2667 long key = bridge.objectFieldOffset( fld ) ;
2668 bridge.putByte( o, key, v ) ;
2669 } else {
2670 throw new InvalidObjectException("Field Type mismatch");
2671 }
2672 } catch (Exception e) {
2673 if (o != null) {
2674 throw utilWrapper.errorSetByteField( e, fieldName,
2675 o.toString(),
2676 new Byte(v) ) ;
2677 } else {
2678 throw utilWrapper.errorSetByteField( e, fieldName,
2679 "null " + c.getName() + " object",
2680 new Byte(v) ) ;
2681 }
2682 }
2683 }
2685 private static void setCharField(Object o, Class<?> c, String fieldName, char v)
2686 {
2687 try {
2688 Field fld = getDeclaredField( c, fieldName ) ;
2689 if ((fld != null) && (fld.getType() == Character.TYPE)) {
2690 long key = bridge.objectFieldOffset( fld ) ;
2691 bridge.putChar( o, key, v ) ;
2692 } else {
2693 throw new InvalidObjectException("Field Type mismatch");
2694 }
2695 } catch (Exception e) {
2696 if (o != null) {
2697 throw utilWrapper.errorSetCharField( e, fieldName,
2698 o.toString(),
2699 new Character(v) ) ;
2700 } else {
2701 throw utilWrapper.errorSetCharField( e, fieldName,
2702 "null " + c.getName() + " object",
2703 new Character(v) ) ;
2704 }
2705 }
2706 }
2708 private static void setShortField(Object o, Class<?> c, String fieldName, short v)
2709 {
2710 try {
2711 Field fld = getDeclaredField( c, fieldName ) ;
2712 if ((fld != null) && (fld.getType() == Short.TYPE)) {
2713 long key = bridge.objectFieldOffset( fld ) ;
2714 bridge.putShort( o, key, v ) ;
2715 } else {
2716 throw new InvalidObjectException("Field Type mismatch");
2717 }
2718 } catch (Exception e) {
2719 if (o != null) {
2720 throw utilWrapper.errorSetShortField( e, fieldName,
2721 o.toString(),
2722 new Short(v) ) ;
2723 } else {
2724 throw utilWrapper.errorSetShortField( e, fieldName,
2725 "null " + c.getName() + " object",
2726 new Short(v) ) ;
2727 }
2728 }
2729 }
2731 private static void setIntField(Object o, final Class<?> c, final String fieldName, int v)
2732 {
2733 try {
2734 Field fld = getDeclaredField( c, fieldName ) ;
2735 if ((fld != null) && (fld.getType() == Integer.TYPE)) {
2736 long key = bridge.objectFieldOffset( fld ) ;
2737 bridge.putInt( o, key, v ) ;
2738 } else {
2739 throw new InvalidObjectException("Field Type mismatch");
2740 }
2741 } catch (Exception e) {
2742 if (o != null) {
2743 throw utilWrapper.errorSetIntField( e, fieldName,
2744 o.toString(),
2745 new Integer(v) ) ;
2746 } else {
2747 throw utilWrapper.errorSetIntField( e, fieldName,
2748 "null " + c.getName() + " object",
2749 new Integer(v) ) ;
2750 }
2751 }
2752 }
2754 private static void setLongField(Object o, Class<?> c, String fieldName, long v)
2755 {
2756 try {
2757 Field fld = getDeclaredField( c, fieldName ) ;
2758 if ((fld != null) && (fld.getType() == Long.TYPE)) {
2759 long key = bridge.objectFieldOffset( fld ) ;
2760 bridge.putLong( o, key, v ) ;
2761 } else {
2762 throw new InvalidObjectException("Field Type mismatch");
2763 }
2764 } catch (Exception e) {
2765 if (o != null) {
2766 throw utilWrapper.errorSetLongField( e, fieldName,
2767 o.toString(),
2768 new Long(v) ) ;
2769 } else {
2770 throw utilWrapper.errorSetLongField( e, fieldName,
2771 "null " + c.getName() + " object",
2772 new Long(v) ) ;
2773 }
2774 }
2775 }
2777 private static void setFloatField(Object o, Class<?> c, String fieldName, float v)
2778 {
2779 try {
2780 Field fld = getDeclaredField( c, fieldName ) ;
2781 if ((fld != null) && (fld.getType() == Float.TYPE)) {
2782 long key = bridge.objectFieldOffset( fld ) ;
2783 bridge.putFloat( o, key, v ) ;
2784 } else {
2785 throw new InvalidObjectException("Field Type mismatch");
2786 }
2787 } catch (Exception e) {
2788 if (o != null) {
2789 throw utilWrapper.errorSetFloatField( e, fieldName,
2790 o.toString(),
2791 new Float(v) ) ;
2792 } else {
2793 throw utilWrapper.errorSetFloatField( e, fieldName,
2794 "null " + c.getName() + " object",
2795 new Float(v) ) ;
2796 }
2797 }
2798 }
2800 private static void setDoubleField(Object o, Class<?> c, String fieldName, double v)
2801 {
2802 try {
2803 Field fld = getDeclaredField(c, fieldName ) ;
2804 if ((fld != null) && (fld.getType() == Double.TYPE)) {
2805 long key = bridge.objectFieldOffset( fld ) ;
2806 bridge.putDouble( o, key, v ) ;
2807 } else {
2808 throw new InvalidObjectException("Field Type mismatch");
2809 }
2810 } catch (Exception e) {
2811 if (o != null) {
2812 throw utilWrapper.errorSetDoubleField( e, fieldName,
2813 o.toString(),
2814 new Double(v) ) ;
2815 } else {
2816 throw utilWrapper.errorSetDoubleField( e, fieldName,
2817 "null " + c.getName() + " object",
2818 new Double(v) ) ;
2819 }
2820 }
2821 }
2824 private static Field getDeclaredField(final Class<?> c,
2825 final String fieldName)
2826 throws PrivilegedActionException, NoSuchFieldException, SecurityException {
2827 if (System.getSecurityManager() == null) {
2828 return c.getDeclaredField(fieldName);
2829 } else {
2830 return AccessController
2831 .doPrivileged(new PrivilegedExceptionAction<Field>() {
2832 public Field run()
2833 throws NoSuchFieldException {
2834 return c.getDeclaredField(fieldName);
2835 }
2836 });
2837 }
2838 }
2840 /**
2841 * This class maintains a map of stream position to
2842 * an Object currently being deserialized. It is used
2843 * to handle the cases where the are indirections to
2844 * an object on the recursion stack. The CDR level
2845 * handles indirections to objects previously seen
2846 * (and completely deserialized) in the stream.
2847 */
2848 static class ActiveRecursionManager
2849 {
2850 private Map<Integer, Object> offsetToObjectMap;
2852 public ActiveRecursionManager() {
2853 // A hash map is unsynchronized and allows
2854 // null values
2855 offsetToObjectMap = new HashMap<>();
2856 }
2858 // Called right after allocating a new object.
2859 // Offset is the starting position in the stream
2860 // of the object.
2861 public void addObject(int offset, Object value) {
2862 offsetToObjectMap.put(new Integer(offset), value);
2863 }
2865 // If the given starting position doesn't refer
2866 // to the beginning of an object currently being
2867 // deserialized, this throws an IOException.
2868 // Otherwise, it returns a reference to the
2869 // object.
2870 public Object getObject(int offset) throws IOException {
2871 Integer position = new Integer(offset);
2873 if (!offsetToObjectMap.containsKey(position))
2874 // XXX I18N, logging needed.
2875 throw new IOException("Invalid indirection to offset "
2876 + offset);
2878 return offsetToObjectMap.get(position);
2879 }
2881 // Called when an object has been completely
2882 // deserialized, so it should no longer be in
2883 // this mapping. The CDR level can handle
2884 // further indirections.
2885 public void removeObject(int offset) {
2886 offsetToObjectMap.remove(new Integer(offset));
2887 }
2889 // If the given offset doesn't map to an Object,
2890 // then it isn't an indirection to an object
2891 // currently being deserialized.
2892 public boolean containsObject(int offset) {
2893 return offsetToObjectMap.containsKey(new Integer(offset));
2894 }
2895 }
2896 }