Tue, 28 Dec 2010 15:52:36 -0800
6962318: Update copyright year
Reviewed-by: xdono
1 /*
2 * Copyright (c) 1998, 2010, 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 public final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) {
304 orbStream = os;
305 }
307 public 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 public final void increaseRecursionDepth(){
331 recursionDepth++;
332 }
334 public 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 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 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 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 public final void defaultReadObjectDelegate()
563 /* throws IOException, ClassNotFoundException, NotActiveException */
564 {
565 try {
566 if (currentObject == null || currentClassDesc == null)
567 // XXX I18N, logging needed.
568 throw new NotActiveException("defaultReadObjectDelegate");
570 // The array will be null unless fields were retrieved
571 // remotely because of a serializable version difference.
572 // Bug fix for 4365188. See the definition of
573 // defaultReadObjectFVDMembers for more information.
574 if (defaultReadObjectFVDMembers != null &&
575 defaultReadObjectFVDMembers.length > 0) {
577 // WARNING: Be very careful! What if some of
578 // these fields actually have to do this, too?
579 // This works because the defaultReadObjectFVDMembers
580 // reference is passed to inputClassFields, but
581 // there is no guarantee that
582 // defaultReadObjectFVDMembers will point to the
583 // same array after calling inputClassFields.
585 // Use the remote fields to unmarshal.
586 inputClassFields(currentObject,
587 currentClass,
588 currentClassDesc,
589 defaultReadObjectFVDMembers,
590 cbSender);
592 } else {
594 // Use the local fields to unmarshal.
595 ObjectStreamField[] fields =
596 currentClassDesc.getFieldsNoCopy();
597 if (fields.length > 0) {
598 inputClassFields(currentObject, currentClass, fields, cbSender);
599 }
600 }
601 }
602 catch(NotActiveException nae)
603 {
604 bridge.throwException( nae ) ;
605 }
606 catch(IOException ioe)
607 {
608 bridge.throwException( ioe ) ;
609 }
610 catch(ClassNotFoundException cnfe)
611 {
612 bridge.throwException( cnfe ) ;
613 }
615 }
617 /**
618 * Override the actions of the final method "enableResolveObject()"
619 * in ObjectInputStream.
620 * @since JDK1.1.6
621 *
622 * Enable the stream to allow objects read from the stream to be replaced.
623 * If the stream is a trusted class it is allowed to enable replacment.
624 * Trusted classes are those classes with a classLoader equals null. <p>
625 *
626 * When enabled the resolveObject method is called for every object
627 * being deserialized.
628 *
629 * @exception SecurityException The classloader of this stream object is non-null.
630 * @since JDK1.1
631 */
632 public final boolean enableResolveObjectDelegate(boolean enable)
633 /* throws SecurityException */
634 {
635 return false;
636 }
638 // The following three methods allow the implementing orbStream
639 // to provide mark/reset behavior as defined in java.io.InputStream.
641 public final void mark(int readAheadLimit) {
642 orbStream.mark(readAheadLimit);
643 }
645 public final boolean markSupported() {
646 return orbStream.markSupported();
647 }
649 public final void reset() throws IOException {
650 try {
651 orbStream.reset();
652 } catch (Error e) {
653 IOException err = new IOException(e.getMessage());
654 err.initCause(e) ;
655 throw err ;
656 }
657 }
659 public final int available() throws IOException{
660 return 0; // unreliable
661 }
663 public final void close() throws IOException{
664 // no op
665 }
667 public final int read() throws IOException{
668 try{
669 readObjectState.readData(this);
671 return (orbStream.read_octet() << 0) & 0x000000FF;
672 } catch (MARSHAL marshalException) {
673 if (marshalException.minor
674 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
675 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
676 return -1;
677 }
679 throw marshalException;
680 } catch(Error e) {
681 IOException exc = new IOException(e.getMessage());
682 exc.initCause(e) ;
683 throw exc ;
684 }
685 }
687 public final int read(byte data[], int offset, int length) throws IOException{
688 try{
689 readObjectState.readData(this);
691 orbStream.read_octet_array(data, offset, length);
692 return length;
693 } catch (MARSHAL marshalException) {
694 if (marshalException.minor
695 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
696 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
697 return -1;
698 }
700 throw marshalException;
701 } catch(Error e) {
702 IOException exc = new IOException(e.getMessage());
703 exc.initCause(e) ;
704 throw exc ;
705 }
707 }
709 public final boolean readBoolean() throws IOException{
710 try{
711 readObjectState.readData(this);
713 return orbStream.read_boolean();
714 } catch (MARSHAL marshalException) {
715 handleOptionalDataMarshalException(marshalException, false);
716 throw marshalException;
718 } catch(Error e) {
719 IOException exc = new IOException(e.getMessage());
720 exc.initCause(e);
721 throw exc ;
722 }
723 }
725 public final byte readByte() throws IOException{
726 try{
727 readObjectState.readData(this);
729 return orbStream.read_octet();
730 } catch (MARSHAL marshalException) {
731 handleOptionalDataMarshalException(marshalException, false);
732 throw marshalException;
734 } catch(Error e) {
735 IOException exc = new IOException(e.getMessage());
736 exc.initCause(e);
737 throw exc ;
738 }
739 }
741 public final char readChar() throws IOException{
742 try{
743 readObjectState.readData(this);
745 return orbStream.read_wchar();
746 } catch (MARSHAL marshalException) {
747 handleOptionalDataMarshalException(marshalException, false);
748 throw marshalException;
750 } catch(Error e) {
751 IOException exc = new IOException(e.getMessage());
752 exc.initCause(e);
753 throw exc ;
754 }
755 }
757 public final double readDouble() throws IOException{
758 try{
759 readObjectState.readData(this);
761 return orbStream.read_double();
762 } catch (MARSHAL marshalException) {
763 handleOptionalDataMarshalException(marshalException, false);
764 throw marshalException;
765 } catch(Error e) {
766 IOException exc = new IOException(e.getMessage());
767 exc.initCause(e);
768 throw exc ;
769 }
770 }
772 public final float readFloat() throws IOException{
773 try{
774 readObjectState.readData(this);
776 return orbStream.read_float();
777 } catch (MARSHAL marshalException) {
778 handleOptionalDataMarshalException(marshalException, false);
779 throw marshalException;
780 } catch(Error e) {
781 IOException exc = new IOException(e.getMessage());
782 exc.initCause(e);
783 throw exc ;
784 }
785 }
787 public final void readFully(byte data[]) throws IOException{
788 // d11623 : implement readFully, required for serializing some core classes
790 readFully(data, 0, data.length);
791 }
793 public final void readFully(byte data[], int offset, int size) throws IOException{
794 // d11623 : implement readFully, required for serializing some core classes
795 try{
796 readObjectState.readData(this);
798 orbStream.read_octet_array(data, offset, size);
799 } catch (MARSHAL marshalException) {
800 handleOptionalDataMarshalException(marshalException, false);
802 throw marshalException;
803 } catch(Error e) {
804 IOException exc = new IOException(e.getMessage());
805 exc.initCause(e);
806 throw exc ;
807 }
808 }
810 public final int readInt() throws IOException{
811 try{
812 readObjectState.readData(this);
814 return orbStream.read_long();
815 } catch (MARSHAL marshalException) {
816 handleOptionalDataMarshalException(marshalException, false);
817 throw marshalException;
818 } catch(Error e) {
819 IOException exc = new IOException(e.getMessage());
820 exc.initCause(e);
821 throw exc ;
822 }
823 }
825 public final String readLine() throws IOException{
826 // XXX I18N, logging needed.
827 throw new IOException("Method readLine not supported");
828 }
830 public final long readLong() throws IOException{
831 try{
832 readObjectState.readData(this);
834 return orbStream.read_longlong();
835 } catch (MARSHAL marshalException) {
836 handleOptionalDataMarshalException(marshalException, false);
837 throw marshalException;
838 } catch(Error e) {
839 IOException exc = new IOException(e.getMessage());
840 exc.initCause(e);
841 throw exc ;
842 }
843 }
845 public final short readShort() throws IOException{
846 try{
847 readObjectState.readData(this);
849 return orbStream.read_short();
850 } catch (MARSHAL marshalException) {
851 handleOptionalDataMarshalException(marshalException, false);
852 throw marshalException;
853 } catch(Error e) {
854 IOException exc = new IOException(e.getMessage());
855 exc.initCause(e);
856 throw exc ;
857 }
858 }
860 protected final void readStreamHeader() throws IOException, StreamCorruptedException{
861 // no op
862 }
864 public final int readUnsignedByte() throws IOException{
865 try{
866 readObjectState.readData(this);
868 return (orbStream.read_octet() << 0) & 0x000000FF;
869 } catch (MARSHAL marshalException) {
870 handleOptionalDataMarshalException(marshalException, false);
871 throw marshalException;
872 } catch(Error e) {
873 IOException exc = new IOException(e.getMessage());
874 exc.initCause(e);
875 throw exc ;
876 }
877 }
879 public final int readUnsignedShort() throws IOException{
880 try{
881 readObjectState.readData(this);
883 return (orbStream.read_ushort() << 0) & 0x0000FFFF;
884 } catch (MARSHAL marshalException) {
885 handleOptionalDataMarshalException(marshalException, false);
886 throw marshalException;
887 } catch(Error e) {
888 IOException exc = new IOException(e.getMessage());
889 exc.initCause(e);
890 throw exc ;
891 }
892 }
894 /**
895 * Helper method for correcting the Kestrel bug 4367783 (dealing
896 * with larger than 8-bit chars). The old behavior is preserved
897 * in orbutil.IIOPInputStream_1_3 in order to interoperate with
898 * our legacy ORBs.
899 */
900 protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream)
901 {
902 return stream.read_wstring();
903 }
905 public final String readUTF() throws IOException{
906 try{
907 readObjectState.readData(this);
909 return internalReadUTF(orbStream);
910 } catch (MARSHAL marshalException) {
911 handleOptionalDataMarshalException(marshalException, false);
912 throw marshalException;
913 } catch(Error e) {
914 IOException exc = new IOException(e.getMessage());
915 exc.initCause(e);
916 throw exc ;
917 }
918 }
920 // If the ORB stream detects an incompatibility between what's
921 // on the wire and what our Serializable's readObject wants,
922 // it throws a MARSHAL exception with a specific minor code.
923 // This is rethrown to the readObject as an OptionalDataException.
924 // So far in RMI-IIOP, this process isn't specific enough to
925 // tell the readObject how much data is available, so we always
926 // set the OptionalDataException's EOF marker to true.
927 private void handleOptionalDataMarshalException(MARSHAL marshalException,
928 boolean objectRead)
929 throws IOException {
931 // Java Object Serialization spec 3.4: "If the readObject method
932 // of the class attempts to read more data than is present in the
933 // optional part of the stream for this class, the stream will
934 // return -1 for bytewise reads, throw an EOFException for
935 // primitive data reads, or throw an OptionalDataException
936 // with the eof field set to true for object reads."
937 if (marshalException.minor
938 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
940 IOException result;
942 if (!objectRead)
943 result = new EOFException("No more optional data");
944 else
945 result = createOptionalDataException();
947 result.initCause(marshalException);
949 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
951 throw result;
952 }
953 }
955 public final synchronized void registerValidation(ObjectInputValidation obj,
956 int prio)
957 throws NotActiveException, InvalidObjectException{
958 // XXX I18N, logging needed.
959 throw new Error("Method registerValidation not supported");
960 }
962 protected final Class resolveClass(ObjectStreamClass v)
963 throws IOException, ClassNotFoundException{
964 // XXX I18N, logging needed.
965 throw new IOException("Method resolveClass not supported");
966 }
968 protected final Object resolveObject(Object obj) throws IOException{
969 // XXX I18N, logging needed.
970 throw new IOException("Method resolveObject not supported");
971 }
973 public final int skipBytes(int len) throws IOException{
974 try{
975 readObjectState.readData(this);
977 byte buf[] = new byte[len];
978 orbStream.read_octet_array(buf, 0, len);
979 return len;
980 } catch (MARSHAL marshalException) {
981 handleOptionalDataMarshalException(marshalException, false);
983 throw marshalException;
984 } catch(Error e) {
985 IOException exc = new IOException(e.getMessage());
986 exc.initCause(e) ;
987 throw exc ;
988 }
989 }
991 private Object inputObject(Class clz,
992 String repositoryID,
993 com.sun.org.omg.SendingContext.CodeBase sender,
994 int offset)
995 throws IOException, ClassNotFoundException
996 {
998 /*
999 * Get the descriptor and then class of the incoming object.
1000 */
1002 currentClassDesc = ObjectStreamClass.lookup(clz);
1003 currentClass = currentClassDesc.forClass();
1004 //currentClassDesc.setClass(currentClass);
1005 if (currentClass == null)
1006 // XXX I18N, logging needed.
1007 throw new ClassNotFoundException(currentClassDesc.getName());
1009 try {
1010 /* If Externalizable,
1011 * Create an instance and tell it to read its data.
1012 * else,
1013 * Handle it as a serializable class.
1014 */
1015 if (Enum.class.isAssignableFrom( clz )) {
1016 int ordinal = orbStream.read_long() ;
1017 String value = (String)orbStream.read_value( String.class ) ;
1018 return Enum.valueOf( clz, value ) ;
1019 } else if (currentClassDesc.isExternalizable()) {
1020 try {
1021 currentObject = (currentClass == null) ?
1022 null : currentClassDesc.newInstance();
1023 if (currentObject != null) {
1025 // Store this object and its beginning position
1026 // since there might be indirections to it while
1027 // it's been unmarshalled.
1028 activeRecursionMgr.addObject(offset, currentObject);
1030 // Read format version
1031 readFormatVersion();
1033 Externalizable ext = (Externalizable)currentObject;
1034 ext.readExternal(this);
1035 }
1036 } catch (InvocationTargetException e) {
1037 InvalidClassException exc = new InvalidClassException(
1038 currentClass.getName(),
1039 "InvocationTargetException accessing no-arg constructor");
1040 exc.initCause( e ) ;
1041 throw exc ;
1042 } catch (UnsupportedOperationException e) {
1043 InvalidClassException exc = new InvalidClassException(
1044 currentClass.getName(),
1045 "UnsupportedOperationException accessing no-arg constructor");
1046 exc.initCause( e ) ;
1047 throw exc ;
1048 } catch (InstantiationException e) {
1049 InvalidClassException exc = new InvalidClassException(
1050 currentClass.getName(),
1051 "InstantiationException accessing no-arg constructor");
1052 exc.initCause( e ) ;
1053 throw exc ;
1054 }
1055 } // end : if (currentClassDesc.isExternalizable())
1056 else {
1057 /* Count number of classes and descriptors we might have
1058 * to work on.
1059 */
1061 ObjectStreamClass currdesc = currentClassDesc;
1062 Class currclass = currentClass;
1064 int spBase = spClass; // current top of stack
1066 /* The object's classes should be processed from supertype to subtype
1067 * Push all the clases of the current object onto a stack.
1068 * Note that only the serializable classes are represented
1069 * in the descriptor list.
1070 *
1071 * Handle versioning where one or more supertypes of
1072 * have been inserted or removed. The stack will
1073 * contain pairs of descriptors and the corresponding
1074 * class. If the object has a class that did not occur in
1075 * the original the descriptor will be null. If the
1076 * original object had a descriptor for a class not
1077 * present in the local hierarchy of the object the class will be
1078 * null.
1079 *
1080 */
1082 /*
1083 * This is your basic diff pattern, made simpler
1084 * because reordering is not allowed.
1085 */
1086 // sun.4296963 ibm.11861
1087 // d11861 we should stop when we find the highest serializable class
1088 // We need this so that when we allocate the new object below, we
1089 // can call the constructor of the non-serializable superclass.
1090 // Note that in the JRMP variant of this code the
1091 // ObjectStreamClass.lookup() method handles this, but we've put
1092 // this fix here rather than change lookup because the new behaviour
1093 // is needed in other cases.
1095 for (currdesc = currentClassDesc, currclass = currentClass;
1096 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
1097 currdesc = currdesc.getSuperclass()) {
1099 /*
1100 * Search the classes to see if the class of this
1101 * descriptor appears further up the hierarchy. Until
1102 * it's found assume its an inserted class. If it's
1103 * not found, its the descriptor's class that has been
1104 * removed.
1105 */
1106 Class cc = currdesc.forClass();
1107 Class cl;
1108 for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
1109 if (cc == cl) {
1110 // found a superclass that matches this descriptor
1111 break;
1112 } else {
1113 /* Ignore a class that doesn't match. No
1114 * action is needed since it is already
1115 * initialized.
1116 */
1117 }
1118 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
1119 /* Test if there is room for this new entry.
1120 * If not, double the size of the arrays and copy the contents.
1121 */
1122 spClass++;
1123 if (spClass >= classes.length) {
1124 int newlen = classes.length * 2;
1125 Class[] newclasses = new Class[newlen];
1126 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
1128 System.arraycopy(classes, 0,
1129 newclasses, 0,
1130 classes.length);
1131 System.arraycopy(classdesc, 0,
1132 newclassdesc, 0,
1133 classes.length);
1135 classes = newclasses;
1136 classdesc = newclassdesc;
1137 }
1139 if (cl == null) {
1140 /* Class not found corresponding to this descriptor.
1141 * Pop off all the extra classes pushed.
1142 * Push the descriptor and a null class.
1143 */
1144 classdesc[spClass] = currdesc;
1145 classes[spClass] = null;
1146 } else {
1147 /* Current class descriptor matches current class.
1148 * Some classes may have been inserted.
1149 * Record the match and advance the class, continue
1150 * with the next descriptor.
1151 */
1152 classdesc[spClass] = currdesc;
1153 classes[spClass] = cl;
1154 currclass = cl.getSuperclass();
1155 }
1156 } // end : for (currdesc = currentClassDesc, currclass = currentClass;
1158 /* Allocate a new object. The object is only constructed
1159 * above the highest serializable class and is set to
1160 * default values for all more specialized classes.
1161 */
1162 try {
1163 currentObject = (currentClass == null) ?
1164 null : currentClassDesc.newInstance() ;
1166 // Store this object and its beginning position
1167 // since there might be indirections to it while
1168 // it's been unmarshalled.
1169 activeRecursionMgr.addObject(offset, currentObject);
1170 } catch (InvocationTargetException e) {
1171 InvalidClassException exc = new InvalidClassException(
1172 currentClass.getName(),
1173 "InvocationTargetException accessing no-arg constructor");
1174 exc.initCause( e ) ;
1175 throw exc ;
1176 } catch (UnsupportedOperationException e) {
1177 InvalidClassException exc = new InvalidClassException(
1178 currentClass.getName(),
1179 "UnsupportedOperationException accessing no-arg constructor");
1180 exc.initCause( e ) ;
1181 throw exc ;
1182 } catch (InstantiationException e) {
1183 InvalidClassException exc = new InvalidClassException(
1184 currentClass.getName(),
1185 "InstantiationException accessing no-arg constructor");
1186 exc.initCause( e ) ;
1187 throw exc ;
1188 }
1190 /*
1191 * For all the pushed descriptors and classes.
1192 * if the class has its own writeObject and readObject methods
1193 * call the readObject method
1194 * else
1195 * invoke the defaultReadObject method
1196 */
1197 try {
1198 for (spClass = spClass; spClass > spBase; spClass--) {
1199 /*
1200 * Set current descriptor and corresponding class
1201 */
1202 currentClassDesc = classdesc[spClass];
1203 currentClass = classes[spClass];
1204 if (classes[spClass] != null) {
1205 /* Read the data from the stream described by the
1206 * descriptor and store into the matching class.
1207 */
1209 ReadObjectState oldState = readObjectState;
1210 setState(DEFAULT_STATE);
1212 try {
1214 // Changed since invokeObjectReader no longer does this.
1215 if (currentClassDesc.hasWriteObject()) {
1217 // Read format version
1218 readFormatVersion();
1220 // Read defaultWriteObject indicator
1221 boolean calledDefaultWriteObject = readBoolean();
1223 readObjectState.beginUnmarshalCustomValue(this,
1224 calledDefaultWriteObject,
1225 (currentClassDesc.readObjectMethod
1226 != null));
1227 } else {
1228 if (currentClassDesc.hasReadObject())
1229 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
1230 }
1232 if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) ||
1233 readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) {
1235 // Error case of no readObject and didn't call
1236 // defaultWriteObject handled in default state
1238 ObjectStreamField[] fields =
1239 currentClassDesc.getFieldsNoCopy();
1240 if (fields.length > 0) {
1241 inputClassFields(currentObject, currentClass, fields, sender);
1242 }
1243 }
1245 if (currentClassDesc.hasWriteObject())
1246 readObjectState.endUnmarshalCustomValue(this);
1248 } finally {
1249 setState(oldState);
1250 }
1252 } else {
1254 // _REVISIT_ : Can we ever get here?
1255 /* No local class for this descriptor,
1256 * Skip over the data for this class.
1257 * like defaultReadObject with a null currentObject.
1258 * The code will read the values but discard them.
1259 */
1260 ObjectStreamField[] fields =
1261 currentClassDesc.getFieldsNoCopy();
1262 if (fields.length > 0) {
1263 inputClassFields(null, currentClass, fields, sender);
1264 }
1266 }
1268 }
1269 } finally {
1270 // Make sure we exit at the same stack level as when we started.
1271 spClass = spBase;
1272 }
1273 }
1274 } finally {
1275 // We've completed deserializing this object. Any
1276 // future indirections will be handled correctly at the
1277 // CDR level. The ActiveRecursionManager only deals with
1278 // objects currently being deserialized.
1279 activeRecursionMgr.removeObject(offset);
1280 }
1282 return currentObject;
1283 }
1285 // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
1286 // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable
1287 // classes!
1288 private Vector getOrderedDescriptions(String repositoryID,
1289 com.sun.org.omg.SendingContext.CodeBase sender) {
1290 Vector descs = new Vector();
1292 if (sender == null) {
1293 return descs;
1294 }
1296 FullValueDescription aFVD = sender.meta(repositoryID);
1297 while (aFVD != null) {
1298 descs.insertElementAt(aFVD, 0);
1299 if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
1300 aFVD = sender.meta(aFVD.base_value);
1301 }
1302 else return descs;
1303 }
1305 return descs;
1306 }
1308 /**
1309 * This input method uses FullValueDescriptions retrieved from the sender's runtime to
1310 * read in the data. This method is capable of throwing out data not applicable to client's fields.
1311 * This method handles instances where the reader has a class not sent by the sender, the sender sent
1312 * a class not present on the reader, and/or the reader's class does not match the sender's class.
1313 *
1314 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
1315 * indicates custom marsahling than the local type is used to read the data off the wire. However,
1316 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
1317 * a form of custom marshaling.
1318 *
1319 */
1320 private Object inputObjectUsingFVD(Class clz,
1321 String repositoryID,
1322 com.sun.org.omg.SendingContext.CodeBase sender,
1323 int offset)
1324 throws IOException, ClassNotFoundException
1325 {
1326 int spBase = spClass; // current top of stack
1327 try{
1329 /*
1330 * Get the descriptor and then class of the incoming object.
1331 */
1333 ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
1334 Class currclass = currentClass = clz;
1336 /* If Externalizable,
1337 * Create an instance and tell it to read its data.
1338 * else,
1339 * Handle it as a serializable class.
1340 */
1341 if (currentClassDesc.isExternalizable()) {
1342 try {
1343 currentObject = (currentClass == null) ?
1344 null : currentClassDesc.newInstance();
1345 if (currentObject != null) {
1346 // Store this object and its beginning position
1347 // since there might be indirections to it while
1348 // it's been unmarshalled.
1349 activeRecursionMgr.addObject(offset, currentObject);
1351 // Read format version
1352 readFormatVersion();
1354 Externalizable ext = (Externalizable)currentObject;
1355 ext.readExternal(this);
1356 }
1357 } catch (InvocationTargetException e) {
1358 InvalidClassException exc = new InvalidClassException(
1359 currentClass.getName(),
1360 "InvocationTargetException accessing no-arg constructor");
1361 exc.initCause( e ) ;
1362 throw exc ;
1363 } catch (UnsupportedOperationException e) {
1364 InvalidClassException exc = new InvalidClassException(
1365 currentClass.getName(),
1366 "UnsupportedOperationException accessing no-arg constructor");
1367 exc.initCause( e ) ;
1368 throw exc ;
1369 } catch (InstantiationException e) {
1370 InvalidClassException exc = new InvalidClassException(
1371 currentClass.getName(),
1372 "InstantiationException accessing no-arg constructor");
1373 exc.initCause( e ) ;
1374 throw exc ;
1375 }
1376 } else {
1377 /*
1378 * This is your basic diff pattern, made simpler
1379 * because reordering is not allowed.
1380 */
1381 for (currdesc = currentClassDesc, currclass = currentClass;
1382 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
1384 currdesc = currdesc.getSuperclass()) {
1386 /*
1387 * Search the classes to see if the class of this
1388 * descriptor appears further up the hierarchy. Until
1389 * it's found assume its an inserted class. If it's
1390 * not found, its the descriptor's class that has been
1391 * removed.
1392 */
1393 Class cc = currdesc.forClass();
1394 Class cl;
1395 for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
1396 if (cc == cl) {
1397 // found a superclass that matches this descriptor
1398 break;
1399 } else {
1400 /* Ignore a class that doesn't match. No
1401 * action is needed since it is already
1402 * initialized.
1403 */
1404 }
1405 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
1406 /* Test if there is room for this new entry.
1407 * If not, double the size of the arrays and copy the contents.
1408 */
1409 spClass++;
1410 if (spClass >= classes.length) {
1411 int newlen = classes.length * 2;
1412 Class[] newclasses = new Class[newlen];
1413 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
1415 System.arraycopy(classes, 0,
1416 newclasses, 0,
1417 classes.length);
1418 System.arraycopy(classdesc, 0,
1419 newclassdesc, 0,
1420 classes.length);
1422 classes = newclasses;
1423 classdesc = newclassdesc;
1424 }
1426 if (cl == null) {
1427 /* Class not found corresponding to this descriptor.
1428 * Pop off all the extra classes pushed.
1429 * Push the descriptor and a null class.
1430 */
1431 classdesc[spClass] = currdesc;
1432 classes[spClass] = null;
1433 } else {
1434 /* Current class descriptor matches current class.
1435 * Some classes may have been inserted.
1436 * Record the match and advance the class, continue
1437 * with the next descriptor.
1438 */
1439 classdesc[spClass] = currdesc;
1440 classes[spClass] = cl;
1441 currclass = cl.getSuperclass();
1442 }
1443 } // end : for (currdesc = currentClassDesc, currclass = currentClass;
1445 /* Allocate a new object.
1446 */
1447 try {
1448 currentObject = (currentClass == null) ?
1449 null : currentClassDesc.newInstance();
1451 // Store this object and its beginning position
1452 // since there might be indirections to it while
1453 // it's been unmarshalled.
1454 activeRecursionMgr.addObject(offset, currentObject);
1455 } catch (InvocationTargetException e) {
1456 InvalidClassException exc = new InvalidClassException(
1457 currentClass.getName(),
1458 "InvocationTargetException accessing no-arg constructor");
1459 exc.initCause( e ) ;
1460 throw exc ;
1461 } catch (UnsupportedOperationException e) {
1462 InvalidClassException exc = new InvalidClassException(
1463 currentClass.getName(),
1464 "UnsupportedOperationException accessing no-arg constructor");
1465 exc.initCause( e ) ;
1466 throw exc ;
1467 } catch (InstantiationException e) {
1468 InvalidClassException exc = new InvalidClassException(
1469 currentClass.getName(),
1470 "InstantiationException accessing no-arg constructor");
1471 exc.initCause( e ) ;
1472 throw exc ;
1473 }
1475 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
1477 while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
1478 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1479 // d4365188: backward compatability
1480 String repIDForFVD = vhandler.getClassName(fvd.id);
1481 String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
1483 while ((spClass > spBase) &&
1484 (!repIDForFVD.equals(repIDForClass))) {
1485 int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
1486 if (pos != -1) {
1487 spClass = pos;
1488 currclass = currentClass = classes[spClass];
1489 repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
1490 }
1491 else { // Read and throw away one level of the fvdslist
1493 // This seems to mean that the sender had a superclass that
1494 // we don't have
1496 if (fvd.is_custom) {
1498 readFormatVersion();
1499 boolean calledDefaultWriteObject = readBoolean();
1501 if (calledDefaultWriteObject)
1502 inputClassFields(null, null, null, fvd.members, sender);
1504 if (getStreamFormatVersion() == 2) {
1506 ((ValueInputStream)getOrbStream()).start_value();
1507 ((ValueInputStream)getOrbStream()).end_value();
1508 }
1510 // WARNING: If stream format version is 1 and there's
1511 // optional data, we'll get some form of exception down
1512 // the line or data corruption.
1514 } else {
1516 inputClassFields(null, currentClass, null, fvd.members, sender);
1517 }
1519 if (fvdsList.hasMoreElements()){
1520 fvd = (FullValueDescription)fvdsList.nextElement();
1521 repIDForFVD = vhandler.getClassName(fvd.id);
1522 }
1523 else return currentObject;
1524 }
1525 }
1527 currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
1529 if (!repIDForClass.equals("java.lang.Object")) {
1531 // If the sender used custom marshaling, then it should have put
1532 // the two bytes on the wire indicating stream format version
1533 // and whether or not the writeObject method called
1534 // defaultWriteObject/writeFields.
1536 ReadObjectState oldState = readObjectState;
1537 setState(DEFAULT_STATE);
1539 try {
1541 if (fvd.is_custom) {
1543 // Read format version
1544 readFormatVersion();
1546 // Read defaultWriteObject indicator
1547 boolean calledDefaultWriteObject = readBoolean();
1549 readObjectState.beginUnmarshalCustomValue(this,
1550 calledDefaultWriteObject,
1551 (currentClassDesc.readObjectMethod
1552 != null));
1553 }
1555 boolean usedReadObject = false;
1557 // Always use readObject if it exists, and fall back to default
1558 // unmarshaling if it doesn't.
1559 try {
1561 if (!fvd.is_custom && currentClassDesc.hasReadObject())
1562 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
1564 // See the definition of defaultReadObjectFVDMembers
1565 // for more information. This concerns making sure
1566 // we use the remote FVD's members in defaultReadObject.
1567 defaultReadObjectFVDMembers = fvd.members;
1568 usedReadObject = invokeObjectReader(currentClassDesc,
1569 currentObject,
1570 currentClass);
1572 } finally {
1573 defaultReadObjectFVDMembers = null;
1574 }
1576 // Note that the !usedReadObject !calledDefaultWriteObject
1577 // case is handled by the beginUnmarshalCustomValue method
1578 // of the default state
1579 if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT)
1580 inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
1582 if (fvd.is_custom)
1583 readObjectState.endUnmarshalCustomValue(this);
1585 } finally {
1586 setState(oldState);
1587 }
1589 currclass = currentClass = classes[--spClass];
1591 } else {
1593 // The remaining hierarchy of the local class does not match the sender's FVD.
1594 // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate
1595 // custom marshaling, throw MARSHAL error.
1596 inputClassFields(null, currentClass, null, fvd.members, sender);
1598 while (fvdsList.hasMoreElements()){
1599 fvd = (FullValueDescription)fvdsList.nextElement();
1601 if (fvd.is_custom)
1602 skipCustomUsingFVD(fvd.members, sender);
1603 else
1604 inputClassFields(null, currentClass, null, fvd.members, sender);
1605 }
1607 }
1609 } // end : while(fvdsList.hasMoreElements())
1610 while (fvdsList.hasMoreElements()){
1612 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1613 if (fvd.is_custom)
1614 skipCustomUsingFVD(fvd.members, sender);
1615 else
1616 throwAwayData(fvd.members, sender);
1617 }
1618 }
1620 return currentObject;
1621 }
1622 finally {
1623 // Make sure we exit at the same stack level as when we started.
1624 spClass = spBase;
1626 // We've completed deserializing this object. Any
1627 // future indirections will be handled correctly at the
1628 // CDR level. The ActiveRecursionManager only deals with
1629 // objects currently being deserialized.
1630 activeRecursionMgr.removeObject(offset);
1631 }
1633 }
1635 /**
1636 * This input method uses FullValueDescriptions retrieved from the sender's runtime to
1637 * read in the data. This method is capable of throwing out data not applicable to client's fields.
1638 *
1639 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
1640 * indicates custom marsahling than the local type is used to read the data off the wire. However,
1641 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
1642 * a form of custom marshaling.
1643 *
1644 */
1645 private Object skipObjectUsingFVD(String repositoryID,
1646 com.sun.org.omg.SendingContext.CodeBase sender)
1647 throws IOException, ClassNotFoundException
1648 {
1650 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
1652 while(fvdsList.hasMoreElements()) {
1653 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1654 String repIDForFVD = vhandler.getClassName(fvd.id);
1656 if (!repIDForFVD.equals("java.lang.Object")) {
1657 if (fvd.is_custom) {
1659 readFormatVersion();
1661 boolean calledDefaultWriteObject = readBoolean();
1663 if (calledDefaultWriteObject)
1664 inputClassFields(null, null, null, fvd.members, sender);
1666 if (getStreamFormatVersion() == 2) {
1668 ((ValueInputStream)getOrbStream()).start_value();
1669 ((ValueInputStream)getOrbStream()).end_value();
1670 }
1672 // WARNING: If stream format version is 1 and there's
1673 // optional data, we'll get some form of exception down
1674 // the line.
1676 } else {
1677 // Use default marshaling
1678 inputClassFields(null, null, null, fvd.members, sender);
1679 }
1680 }
1682 } // end : while(fvdsList.hasMoreElements())
1683 return null;
1685 }
1687 ///////////////////
1689 private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){
1691 for (int i = _spClass; i > _spBase; i--){
1692 if (classname.equals(classes[i].getName())) {
1693 return i;
1694 }
1695 }
1697 return -1;
1698 }
1700 /*
1701 * Invoke the readObject method if present. Assumes that in the case of custom
1702 * marshaling, the format version and defaultWriteObject indicator were already
1703 * removed.
1704 */
1705 private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass)
1706 throws InvalidClassException, StreamCorruptedException,
1707 ClassNotFoundException, IOException
1708 {
1709 if (osc.readObjectMethod == null) {
1710 return false;
1711 }
1713 try {
1714 osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
1715 return true;
1716 } catch (InvocationTargetException e) {
1717 Throwable t = e.getTargetException();
1718 if (t instanceof ClassNotFoundException)
1719 throw (ClassNotFoundException)t;
1720 else if (t instanceof IOException)
1721 throw (IOException)t;
1722 else if (t instanceof RuntimeException)
1723 throw (RuntimeException) t;
1724 else if (t instanceof Error)
1725 throw (Error) t;
1726 else
1727 // XXX I18N, logging needed.
1728 throw new Error("internal error");
1729 } catch (IllegalAccessException e) {
1730 return false;
1731 }
1732 }
1734 /*
1735 * Reset the stream to be just like it was after the constructor.
1736 */
1737 private void resetStream() throws IOException {
1739 if (classes == null)
1740 classes = new Class[20];
1741 else {
1742 for (int i = 0; i < classes.length; i++)
1743 classes[i] = null;
1744 }
1745 if (classdesc == null)
1746 classdesc = new ObjectStreamClass[20];
1747 else {
1748 for (int i = 0; i < classdesc.length; i++)
1749 classdesc[i] = null;
1750 }
1751 spClass = 0;
1753 if (callbacks != null)
1754 callbacks.setSize(0); // discard any pending callbacks
1755 }
1757 /**
1758 * Factored out of inputClassFields This reads a primitive value and sets it
1759 * in the field of o described by the ObjectStreamField field.
1760 *
1761 * Note that reflection cannot be used here, because reflection cannot be used
1762 * to set final fields.
1763 */
1764 private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field)
1765 throws InvalidClassException, IOException {
1767 try {
1768 switch (field.getTypeCode()) {
1769 case 'B':
1770 byte byteValue = orbStream.read_octet();
1771 bridge.putByte( o, field.getFieldID(), byteValue ) ;
1772 //reflective code: field.getField().setByte( o, byteValue ) ;
1773 break;
1774 case 'Z':
1775 boolean booleanValue = orbStream.read_boolean();
1776 bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
1777 //reflective code: field.getField().setBoolean( o, booleanValue ) ;
1778 break;
1779 case 'C':
1780 char charValue = orbStream.read_wchar();
1781 bridge.putChar( o, field.getFieldID(), charValue ) ;
1782 //reflective code: field.getField().setChar( o, charValue ) ;
1783 break;
1784 case 'S':
1785 short shortValue = orbStream.read_short();
1786 bridge.putShort( o, field.getFieldID(), shortValue ) ;
1787 //reflective code: field.getField().setShort( o, shortValue ) ;
1788 break;
1789 case 'I':
1790 int intValue = orbStream.read_long();
1791 bridge.putInt( o, field.getFieldID(), intValue ) ;
1792 //reflective code: field.getField().setInt( o, intValue ) ;
1793 break;
1794 case 'J':
1795 long longValue = orbStream.read_longlong();
1796 bridge.putLong( o, field.getFieldID(), longValue ) ;
1797 //reflective code: field.getField().setLong( o, longValue ) ;
1798 break;
1799 case 'F' :
1800 float floatValue = orbStream.read_float();
1801 bridge.putFloat( o, field.getFieldID(), floatValue ) ;
1802 //reflective code: field.getField().setFloat( o, floatValue ) ;
1803 break;
1804 case 'D' :
1805 double doubleValue = orbStream.read_double();
1806 bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
1807 //reflective code: field.getField().setDouble( o, doubleValue ) ;
1808 break;
1809 default:
1810 // XXX I18N, logging needed.
1811 throw new InvalidClassException(cl.getName());
1812 }
1813 } catch (IllegalArgumentException e) {
1814 /* This case should never happen. If the field types
1815 are not the same, InvalidClassException is raised when
1816 matching the local class to the serialized ObjectStreamClass. */
1817 ClassCastException cce = new ClassCastException("Assigning instance of class " +
1818 field.getType().getName() +
1819 " to field " +
1820 currentClassDesc.getName() + '#' +
1821 field.getField().getName());
1822 cce.initCause( e ) ;
1823 throw cce ;
1824 }
1825 }
1827 private Object inputObjectField(org.omg.CORBA.ValueMember field,
1828 com.sun.org.omg.SendingContext.CodeBase sender)
1829 throws IndirectionException, ClassNotFoundException, IOException,
1830 StreamCorruptedException {
1832 Object objectValue = null;
1833 Class type = null;
1834 String id = field.id;
1836 try {
1837 type = vhandler.getClassFromType(id);
1838 } catch(ClassNotFoundException cnfe) {
1839 // Make sure type = null
1840 type = null;
1841 }
1843 String signature = null;
1844 if (type != null)
1845 signature = ValueUtility.getSignature(field);
1847 if (signature != null && (signature.equals("Ljava/lang/Object;") ||
1848 signature.equals("Ljava/io/Serializable;") ||
1849 signature.equals("Ljava/io/Externalizable;"))) {
1850 objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
1851 } else {
1852 // Decide what method call to make based on the type. If
1853 // it is a type for which we need to load a stub, convert
1854 // the type to the correct stub type.
1855 //
1856 // NOTE : Since FullValueDescription does not allow us
1857 // to ask whether something is an interface we do not
1858 // have the ability to optimize this check.
1860 int callType = ValueHandlerImpl.kValueType;
1862 if (!vhandler.isSequence(id)) {
1864 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
1866 // RMI Object reference...
1867 callType = ValueHandlerImpl.kRemoteType;
1869 } else {
1871 // REVISIT. If we don't have the local class,
1872 // we should probably verify that it's an RMI type,
1873 // query the remote FVD, and use is_abstract.
1874 // Our FVD seems to get NullPointerExceptions for any
1875 // non-RMI types.
1877 // This uses the local class in the same way as
1878 // inputObjectField(ObjectStreamField) does. REVISIT
1879 // inputObjectField(ObjectStreamField)'s loadStubClass
1880 // logic. Assumption is that the given type cannot
1881 // evolve to become a CORBA abstract interface or
1882 // a RMI abstract interface.
1884 if (type != null && type.isInterface() &&
1885 (vhandler.isAbstractBase(type) ||
1886 ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
1888 callType = ValueHandlerImpl.kAbstractType;
1889 }
1890 }
1891 }
1893 // Now that we have used the FVD of the field to determine the proper course
1894 // of action, it is ok to use the type (Class) from this point forward since
1895 // the rep. id for this read will also follow on the wire.
1897 switch (callType) {
1898 case ValueHandlerImpl.kRemoteType:
1899 if (type != null)
1900 objectValue = Utility.readObjectAndNarrow(orbStream, type);
1901 else
1902 objectValue = orbStream.read_Object();
1903 break;
1904 case ValueHandlerImpl.kAbstractType:
1905 if (type != null)
1906 objectValue = Utility.readAbstractAndNarrow(orbStream, type);
1907 else
1908 objectValue = orbStream.read_abstract_interface();
1909 break;
1910 case ValueHandlerImpl.kValueType:
1911 if (type != null)
1912 objectValue = orbStream.read_value(type);
1913 else
1914 objectValue = orbStream.read_value();
1915 break;
1916 default:
1917 // XXX I18N, logging needed.
1918 throw new StreamCorruptedException("Unknown callType: " + callType);
1919 }
1920 }
1922 return objectValue;
1923 }
1925 /**
1926 * Factored out of inputClassFields and reused in
1927 * inputCurrentClassFieldsForReadFields.
1928 *
1929 * Reads the field (which of an Object type as opposed to a primitive)
1930 * described by ObjectStreamField field and returns it.
1931 */
1932 private Object inputObjectField(ObjectStreamField field)
1933 throws InvalidClassException, StreamCorruptedException,
1934 ClassNotFoundException, IndirectionException, IOException {
1936 if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
1937 return javax.rmi.CORBA.Util.readAny(orbStream);
1938 }
1940 Object objectValue = null;
1942 // fields have an API to provide the actual class
1943 // corresponding to the data type
1944 // Class type = osc.forClass();
1945 Class fieldType = field.getType();
1946 Class actualType = fieldType; // This may change if stub loaded.
1948 // Decide what method call to make based on the fieldType. If
1949 // it is a type for which we need to load a stub, convert
1950 // the type to the correct stub type.
1952 int callType = ValueHandlerImpl.kValueType;
1953 boolean narrow = false;
1955 if (fieldType.isInterface()) {
1956 boolean loadStubClass = false;
1958 if (java.rmi.Remote.class.isAssignableFrom(fieldType)) {
1960 // RMI Object reference...
1961 callType = ValueHandlerImpl.kRemoteType;
1963 } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){
1965 // IDL Object reference...
1966 callType = ValueHandlerImpl.kRemoteType;
1967 loadStubClass = true;
1969 } else if (vhandler.isAbstractBase(fieldType)) {
1970 // IDL Abstract Object reference...
1972 callType = ValueHandlerImpl.kAbstractType;
1973 loadStubClass = true;
1974 } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
1975 // RMI Abstract Object reference...
1977 callType = ValueHandlerImpl.kAbstractType;
1978 }
1980 if (loadStubClass) {
1981 try {
1982 String codebase = Util.getCodebase(fieldType);
1983 String repID = vhandler.createForAnyType(fieldType);
1984 Class stubType =
1985 Utility.loadStubClass(repID, codebase, fieldType);
1986 actualType = stubType;
1987 } catch (ClassNotFoundException e) {
1988 narrow = true;
1989 }
1990 } else {
1991 narrow = true;
1992 }
1993 }
1995 switch (callType) {
1996 case ValueHandlerImpl.kRemoteType:
1997 if (!narrow)
1998 objectValue = (Object)orbStream.read_Object(actualType);
1999 else
2000 objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
2001 break;
2002 case ValueHandlerImpl.kAbstractType:
2003 if (!narrow)
2004 objectValue = (Object)orbStream.read_abstract_interface(actualType);
2005 else
2006 objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
2007 break;
2008 case ValueHandlerImpl.kValueType:
2009 objectValue = (Object)orbStream.read_value(actualType);
2010 break;
2011 default:
2012 // XXX I18N, logging needed.
2013 throw new StreamCorruptedException("Unknown callType: " + callType);
2014 }
2016 return objectValue;
2017 }
2019 private final boolean mustUseRemoteValueMembers() {
2020 return defaultReadObjectFVDMembers != null;
2021 }
2023 void readFields(java.util.Map fieldToValueMap)
2024 throws InvalidClassException, StreamCorruptedException,
2025 ClassNotFoundException, IOException {
2027 if (mustUseRemoteValueMembers()) {
2028 inputRemoteMembersForReadFields(fieldToValueMap);
2029 } else
2030 inputCurrentClassFieldsForReadFields(fieldToValueMap);
2031 }
2033 private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
2034 throws InvalidClassException, StreamCorruptedException,
2035 ClassNotFoundException, IOException {
2037 // Must have this local variable since defaultReadObjectFVDMembers
2038 // may get mangled by recursion.
2039 ValueMember fields[] = defaultReadObjectFVDMembers;
2041 try {
2043 for (int i = 0; i < fields.length; i++) {
2045 switch (fields[i].type.kind().value()) {
2047 case TCKind._tk_octet:
2048 byte byteValue = orbStream.read_octet();
2049 fieldToValueMap.put(fields[i].name, new Byte(byteValue));
2050 break;
2051 case TCKind._tk_boolean:
2052 boolean booleanValue = orbStream.read_boolean();
2053 fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
2054 break;
2055 case TCKind._tk_char:
2056 // Backwards compatibility. Older Sun ORBs sent
2057 // _tk_char even though they read and wrote wchars
2058 // correctly.
2059 //
2060 // Fall through to the _tk_wchar case.
2061 case TCKind._tk_wchar:
2062 char charValue = orbStream.read_wchar();
2063 fieldToValueMap.put(fields[i].name, new Character(charValue));
2064 break;
2065 case TCKind._tk_short:
2066 short shortValue = orbStream.read_short();
2067 fieldToValueMap.put(fields[i].name, new Short(shortValue));
2068 break;
2069 case TCKind._tk_long:
2070 int intValue = orbStream.read_long();
2071 fieldToValueMap.put(fields[i].name, new Integer(intValue));
2072 break;
2073 case TCKind._tk_longlong:
2074 long longValue = orbStream.read_longlong();
2075 fieldToValueMap.put(fields[i].name, new Long(longValue));
2076 break;
2077 case TCKind._tk_float:
2078 float floatValue = orbStream.read_float();
2079 fieldToValueMap.put(fields[i].name, new Float(floatValue));
2080 break;
2081 case TCKind._tk_double:
2082 double doubleValue = orbStream.read_double();
2083 fieldToValueMap.put(fields[i].name, new Double(doubleValue));
2084 break;
2085 case TCKind._tk_value:
2086 case TCKind._tk_objref:
2087 case TCKind._tk_value_box:
2088 Object objectValue = null;
2089 try {
2090 objectValue = inputObjectField(fields[i],
2091 cbSender);
2093 } catch (IndirectionException cdrie) {
2094 // The CDR stream had never seen the given offset before,
2095 // so check the recursion manager (it will throw an
2096 // IOException if it doesn't have a reference, either).
2097 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2098 }
2100 fieldToValueMap.put(fields[i].name, objectValue);
2101 break;
2102 default:
2103 // XXX I18N, logging needed.
2104 throw new StreamCorruptedException("Unknown kind: "
2105 + fields[i].type.kind().value());
2106 }
2107 }
2108 } catch (Throwable t) {
2109 StreamCorruptedException result = new StreamCorruptedException(t.getMessage());
2110 result.initCause(t);
2111 throw result;
2112 }
2113 }
2115 /**
2116 * Called from InputStreamHook.
2117 *
2118 * Reads the fields of the current class (could be the ones
2119 * queried from the remote FVD) and puts them in
2120 * the given Map, name to value. Wraps primitives in the
2121 * corresponding java.lang Objects.
2122 */
2123 private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
2124 throws InvalidClassException, StreamCorruptedException,
2125 ClassNotFoundException, IOException {
2127 ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
2129 int primFields = fields.length - currentClassDesc.objFields;
2131 // Handle the primitives first
2132 for (int i = 0; i < primFields; ++i) {
2134 switch (fields[i].getTypeCode()) {
2135 case 'B':
2136 byte byteValue = orbStream.read_octet();
2137 fieldToValueMap.put(fields[i].getName(),
2138 new Byte(byteValue));
2139 break;
2140 case 'Z':
2141 boolean booleanValue = orbStream.read_boolean();
2142 fieldToValueMap.put(fields[i].getName(),
2143 new Boolean(booleanValue));
2144 break;
2145 case 'C':
2146 char charValue = orbStream.read_wchar();
2147 fieldToValueMap.put(fields[i].getName(),
2148 new Character(charValue));
2149 break;
2150 case 'S':
2151 short shortValue = orbStream.read_short();
2152 fieldToValueMap.put(fields[i].getName(),
2153 new Short(shortValue));
2154 break;
2155 case 'I':
2156 int intValue = orbStream.read_long();
2157 fieldToValueMap.put(fields[i].getName(),
2158 new Integer(intValue));
2159 break;
2160 case 'J':
2161 long longValue = orbStream.read_longlong();
2162 fieldToValueMap.put(fields[i].getName(),
2163 new Long(longValue));
2164 break;
2165 case 'F' :
2166 float floatValue = orbStream.read_float();
2167 fieldToValueMap.put(fields[i].getName(),
2168 new Float(floatValue));
2169 break;
2170 case 'D' :
2171 double doubleValue = orbStream.read_double();
2172 fieldToValueMap.put(fields[i].getName(),
2173 new Double(doubleValue));
2174 break;
2175 default:
2176 // XXX I18N, logging needed.
2177 throw new InvalidClassException(currentClassDesc.getName());
2178 }
2179 }
2181 /* Read and set object fields from the input stream. */
2182 if (currentClassDesc.objFields > 0) {
2183 for (int i = primFields; i < fields.length; i++) {
2184 Object objectValue = null;
2185 try {
2186 objectValue = inputObjectField(fields[i]);
2187 } catch(IndirectionException cdrie) {
2188 // The CDR stream had never seen the given offset before,
2189 // so check the recursion manager (it will throw an
2190 // IOException if it doesn't have a reference, either).
2191 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2192 }
2194 fieldToValueMap.put(fields[i].getName(), objectValue);
2195 }
2196 }
2197 }
2199 /*
2200 * Read the fields of the specified class from the input stream and set
2201 * the values of the fields in the specified object. If the specified
2202 * object is null, just consume the fields without setting any values. If
2203 * any ObjectStreamField does not have a reflected Field, don't try to set
2204 * that field in the object.
2205 *
2206 * REVISIT -- This code doesn't do what the comment says to when
2207 * getField() is null!
2208 */
2209 private void inputClassFields(Object o, Class cl,
2210 ObjectStreamField[] fields,
2211 com.sun.org.omg.SendingContext.CodeBase sender)
2212 throws InvalidClassException, StreamCorruptedException,
2213 ClassNotFoundException, IOException
2214 {
2216 int primFields = fields.length - currentClassDesc.objFields;
2218 if (o != null) {
2219 for (int i = 0; i < primFields; ++i) {
2220 if (fields[i].getField() == null)
2221 continue;
2223 inputPrimitiveField(o, cl, fields[i]);
2224 }
2225 }
2227 /* Read and set object fields from the input stream. */
2228 if (currentClassDesc.objFields > 0) {
2229 for (int i = primFields; i < fields.length; i++) {
2230 Object objectValue = null;
2232 try {
2233 objectValue = inputObjectField(fields[i]);
2234 } catch(IndirectionException cdrie) {
2235 // The CDR stream had never seen the given offset before,
2236 // so check the recursion manager (it will throw an
2237 // IOException if it doesn't have a reference, either).
2238 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2239 }
2241 if ((o == null) || (fields[i].getField() == null)) {
2242 continue;
2243 }
2245 try {
2246 bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
2247 // reflective code: fields[i].getField().set( o, objectValue ) ;
2248 } catch (IllegalArgumentException e) {
2249 ClassCastException exc = new ClassCastException("Assigning instance of class " +
2250 objectValue.getClass().getName() +
2251 " to field " +
2252 currentClassDesc.getName() +
2253 '#' +
2254 fields[i].getField().getName());
2255 exc.initCause( e ) ;
2256 throw exc ;
2257 }
2258 } // end : for loop
2259 }
2260 }
2262 /*
2263 * Read the fields of the specified class from the input stream and set
2264 * the values of the fields in the specified object. If the specified
2265 * object is null, just consume the fields without setting any values. If
2266 * any ObjectStreamField does not have a reflected Field, don't try to set
2267 * that field in the object.
2268 */
2269 private void inputClassFields(Object o, Class cl,
2270 ObjectStreamClass osc,
2271 ValueMember[] fields,
2272 com.sun.org.omg.SendingContext.CodeBase sender)
2273 throws InvalidClassException, StreamCorruptedException,
2274 ClassNotFoundException, IOException
2275 {
2276 try{
2277 for (int i = 0; i < fields.length; ++i) {
2278 try {
2279 switch (fields[i].type.kind().value()) {
2280 case TCKind._tk_octet:
2281 byte byteValue = orbStream.read_octet();
2282 if ((o != null) && osc.hasField(fields[i]))
2283 setByteField(o, cl, fields[i].name, byteValue);
2284 break;
2285 case TCKind._tk_boolean:
2286 boolean booleanValue = orbStream.read_boolean();
2287 if ((o != null) && osc.hasField(fields[i]))
2288 setBooleanField(o, cl, fields[i].name, booleanValue);
2289 break;
2290 case TCKind._tk_char:
2291 // Backwards compatibility. Older Sun ORBs sent
2292 // _tk_char even though they read and wrote wchars
2293 // correctly.
2294 //
2295 // Fall through to the _tk_wchar case.
2296 case TCKind._tk_wchar:
2297 char charValue = orbStream.read_wchar();
2298 if ((o != null) && osc.hasField(fields[i]))
2299 setCharField(o, cl, fields[i].name, charValue);
2300 break;
2301 case TCKind._tk_short:
2302 short shortValue = orbStream.read_short();
2303 if ((o != null) && osc.hasField(fields[i]))
2304 setShortField(o, cl, fields[i].name, shortValue);
2305 break;
2306 case TCKind._tk_long:
2307 int intValue = orbStream.read_long();
2308 if ((o != null) && osc.hasField(fields[i]))
2309 setIntField(o, cl, fields[i].name, intValue);
2310 break;
2311 case TCKind._tk_longlong:
2312 long longValue = orbStream.read_longlong();
2313 if ((o != null) && osc.hasField(fields[i]))
2314 setLongField(o, cl, fields[i].name, longValue);
2315 break;
2316 case TCKind._tk_float:
2317 float floatValue = orbStream.read_float();
2318 if ((o != null) && osc.hasField(fields[i]))
2319 setFloatField(o, cl, fields[i].name, floatValue);
2320 break;
2321 case TCKind._tk_double:
2322 double doubleValue = orbStream.read_double();
2323 if ((o != null) && osc.hasField(fields[i]))
2324 setDoubleField(o, cl, fields[i].name, doubleValue);
2325 break;
2326 case TCKind._tk_value:
2327 case TCKind._tk_objref:
2328 case TCKind._tk_value_box:
2329 Object objectValue = null;
2330 try {
2331 objectValue = inputObjectField(fields[i], sender);
2332 } catch (IndirectionException cdrie) {
2333 // The CDR stream had never seen the given offset before,
2334 // so check the recursion manager (it will throw an
2335 // IOException if it doesn't have a reference, either).
2336 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2337 }
2339 if (o == null)
2340 continue;
2341 try {
2342 if (osc.hasField(fields[i])){
2343 setObjectField(o,
2344 cl,
2345 fields[i].name,
2346 objectValue);
2347 } else {
2348 // REVISIT. Convert to a log message.
2349 // This is a normal case when fields have
2350 // been added as part of evolution, but
2351 // silently skipping can make it hard to
2352 // debug if there's an error
2353 // System.out.println("**** warning, not setting field: "
2354 // + fields[i].name
2355 // + " since not on class "
2356 // + osc.getName());
2358 }
2359 } catch (IllegalArgumentException e) {
2360 // XXX I18N, logging needed.
2361 ClassCastException cce = new ClassCastException("Assigning instance of class " +
2362 objectValue.getClass().getName() + " to field " + fields[i].name);
2363 cce.initCause(e) ;
2364 throw cce ;
2365 }
2366 break;
2367 default:
2368 // XXX I18N, logging needed.
2369 throw new StreamCorruptedException("Unknown kind: "
2370 + fields[i].type.kind().value());
2371 }
2372 } catch (IllegalArgumentException e) {
2373 /* This case should never happen. If the field types
2374 are not the same, InvalidClassException is raised when
2375 matching the local class to the serialized ObjectStreamClass. */
2376 // XXX I18N, logging needed.
2377 ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id +
2378 " to field " + currentClassDesc.getName() + '#' + fields[i].name);
2379 cce.initCause( e ) ;
2380 throw cce ;
2381 }
2382 }
2383 } catch(Throwable t){
2384 // XXX I18N, logging needed.
2385 StreamCorruptedException sce = new StreamCorruptedException(t.getMessage());
2386 sce.initCause(t) ;
2387 throw sce ;
2388 }
2389 }
2391 private void skipCustomUsingFVD(ValueMember[] fields,
2392 com.sun.org.omg.SendingContext.CodeBase sender)
2393 throws InvalidClassException, StreamCorruptedException,
2394 ClassNotFoundException, IOException
2395 {
2396 readFormatVersion();
2397 boolean calledDefaultWriteObject = readBoolean();
2399 if (calledDefaultWriteObject)
2400 throwAwayData(fields, sender);
2402 if (getStreamFormatVersion() == 2) {
2404 ((ValueInputStream)getOrbStream()).start_value();
2405 ((ValueInputStream)getOrbStream()).end_value();
2406 }
2407 }
2409 /*
2410 * Read the fields of the specified class from the input stream throw data away.
2411 * This must handle same switch logic as above.
2412 */
2413 private void throwAwayData(ValueMember[] fields,
2414 com.sun.org.omg.SendingContext.CodeBase sender)
2415 throws InvalidClassException, StreamCorruptedException,
2416 ClassNotFoundException, IOException
2417 {
2418 for (int i = 0; i < fields.length; ++i) {
2420 try {
2422 switch (fields[i].type.kind().value()) {
2423 case TCKind._tk_octet:
2424 orbStream.read_octet();
2425 break;
2426 case TCKind._tk_boolean:
2427 orbStream.read_boolean();
2428 break;
2429 case TCKind._tk_char:
2430 // Backwards compatibility. Older Sun ORBs sent
2431 // _tk_char even though they read and wrote wchars
2432 // correctly.
2433 //
2434 // Fall through to the _tk_wchar case.
2435 case TCKind._tk_wchar:
2436 orbStream.read_wchar();
2437 break;
2438 case TCKind._tk_short:
2439 orbStream.read_short();
2440 break;
2441 case TCKind._tk_long:
2442 orbStream.read_long();
2443 break;
2444 case TCKind._tk_longlong:
2445 orbStream.read_longlong();
2446 break;
2447 case TCKind._tk_float:
2448 orbStream.read_float();
2449 break;
2450 case TCKind._tk_double:
2451 orbStream.read_double();
2452 break;
2453 case TCKind._tk_value:
2454 case TCKind._tk_objref:
2455 case TCKind._tk_value_box:
2456 Class type = null;
2457 String id = fields[i].id;
2459 try {
2460 type = vhandler.getClassFromType(id);
2461 }
2462 catch(ClassNotFoundException cnfe){
2463 // Make sure type = null
2464 type = null;
2465 }
2466 String signature = null;
2467 if (type != null)
2468 signature = ValueUtility.getSignature(fields[i]);
2470 // Read value
2471 try {
2472 if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
2473 signature.equals("Ljava/io/Serializable;") ||
2474 signature.equals("Ljava/io/Externalizable;")) ) {
2475 javax.rmi.CORBA.Util.readAny(orbStream);
2476 }
2477 else {
2478 // Decide what method call to make based on the type.
2479 //
2480 // NOTE : Since FullValueDescription does not allow us
2481 // to ask whether something is an interface we do not
2482 // have the ability to optimize this check.
2484 int callType = ValueHandlerImpl.kValueType;
2486 if (!vhandler.isSequence(id)) {
2487 FullValueDescription fieldFVD = sender.meta(fields[i].id);
2488 if (kRemoteTypeCode == fields[i].type) {
2490 // RMI Object reference...
2491 callType = ValueHandlerImpl.kRemoteType;
2492 } else if (fieldFVD.is_abstract) {
2493 // RMI Abstract Object reference...
2495 callType = ValueHandlerImpl.kAbstractType;
2496 }
2497 }
2499 // Now that we have used the FVD of the field to determine the proper course
2500 // of action, it is ok to use the type (Class) from this point forward since
2501 // the rep. id for this read will also follow on the wire.
2503 switch (callType) {
2504 case ValueHandlerImpl.kRemoteType:
2505 orbStream.read_Object();
2506 break;
2507 case ValueHandlerImpl.kAbstractType:
2508 orbStream.read_abstract_interface();
2509 break;
2510 case ValueHandlerImpl.kValueType:
2511 if (type != null) {
2512 orbStream.read_value(type);
2513 } else {
2514 orbStream.read_value();
2515 }
2516 break;
2517 default:
2518 // XXX I18N, logging needed.
2519 throw new StreamCorruptedException("Unknown callType: "
2520 + callType);
2521 }
2522 }
2524 }
2525 catch(IndirectionException cdrie) {
2526 // Since we are throwing this away, don't bother handling recursion.
2527 continue;
2528 }
2530 break;
2531 default:
2532 // XXX I18N, logging needed.
2533 throw new StreamCorruptedException("Unknown kind: "
2534 + fields[i].type.kind().value());
2536 }
2537 } catch (IllegalArgumentException e) {
2538 /* This case should never happen. If the field types
2539 are not the same, InvalidClassException is raised when
2540 matching the local class to the serialized ObjectStreamClass. */
2541 // XXX I18N, logging needed.
2542 ClassCastException cce = new ClassCastException("Assigning instance of class " +
2543 fields[i].id + " to field " + currentClassDesc.getName() +
2544 '#' + fields[i].name);
2545 cce.initCause(e) ;
2546 throw cce ;
2547 }
2548 }
2550 }
2552 private static void setObjectField(Object o, Class c, String fieldName, Object v)
2553 {
2554 try {
2555 Field fld = c.getDeclaredField( fieldName ) ;
2556 long key = bridge.objectFieldOffset( fld ) ;
2557 bridge.putObject( o, key, v ) ;
2558 } catch (Exception e) {
2559 throw utilWrapper.errorSetObjectField( e, fieldName,
2560 o.toString(),
2561 v.toString() ) ;
2562 }
2563 }
2565 private static void setBooleanField(Object o, Class c, String fieldName, boolean v)
2566 {
2567 try {
2568 Field fld = c.getDeclaredField( fieldName ) ;
2569 long key = bridge.objectFieldOffset( fld ) ;
2570 bridge.putBoolean( o, key, v ) ;
2571 } catch (Exception e) {
2572 throw utilWrapper.errorSetBooleanField( e, fieldName,
2573 o.toString(),
2574 new Boolean(v) ) ;
2575 }
2576 }
2578 private static void setByteField(Object o, Class c, String fieldName, byte v)
2579 {
2580 try {
2581 Field fld = c.getDeclaredField( fieldName ) ;
2582 long key = bridge.objectFieldOffset( fld ) ;
2583 bridge.putByte( o, key, v ) ;
2584 } catch (Exception e) {
2585 throw utilWrapper.errorSetByteField( e, fieldName,
2586 o.toString(),
2587 new Byte(v) ) ;
2588 }
2589 }
2591 private static void setCharField(Object o, Class c, String fieldName, char v)
2592 {
2593 try {
2594 Field fld = c.getDeclaredField( fieldName ) ;
2595 long key = bridge.objectFieldOffset( fld ) ;
2596 bridge.putChar( o, key, v ) ;
2597 } catch (Exception e) {
2598 throw utilWrapper.errorSetCharField( e, fieldName,
2599 o.toString(),
2600 new Character(v) ) ;
2601 }
2602 }
2604 private static void setShortField(Object o, Class c, String fieldName, short v)
2605 {
2606 try {
2607 Field fld = c.getDeclaredField( fieldName ) ;
2608 long key = bridge.objectFieldOffset( fld ) ;
2609 bridge.putShort( o, key, v ) ;
2610 } catch (Exception e) {
2611 throw utilWrapper.errorSetShortField( e, fieldName,
2612 o.toString(),
2613 new Short(v) ) ;
2614 }
2615 }
2617 private static void setIntField(Object o, Class c, String fieldName, int v)
2618 {
2619 try {
2620 Field fld = c.getDeclaredField( fieldName ) ;
2621 long key = bridge.objectFieldOffset( fld ) ;
2622 bridge.putInt( o, key, v ) ;
2623 } catch (Exception e) {
2624 throw utilWrapper.errorSetIntField( e, fieldName,
2625 o.toString(),
2626 new Integer(v) ) ;
2627 }
2628 }
2630 private static void setLongField(Object o, Class c, String fieldName, long v)
2631 {
2632 try {
2633 Field fld = c.getDeclaredField( fieldName ) ;
2634 long key = bridge.objectFieldOffset( fld ) ;
2635 bridge.putLong( o, key, v ) ;
2636 } catch (Exception e) {
2637 throw utilWrapper.errorSetLongField( e, fieldName,
2638 o.toString(),
2639 new Long(v) ) ;
2640 }
2641 }
2643 private static void setFloatField(Object o, Class c, String fieldName, float v)
2644 {
2645 try {
2646 Field fld = c.getDeclaredField( fieldName ) ;
2647 long key = bridge.objectFieldOffset( fld ) ;
2648 bridge.putFloat( o, key, v ) ;
2649 } catch (Exception e) {
2650 throw utilWrapper.errorSetFloatField( e, fieldName,
2651 o.toString(),
2652 new Float(v) ) ;
2653 }
2654 }
2656 private static void setDoubleField(Object o, Class c, String fieldName, double v)
2657 {
2658 try {
2659 Field fld = c.getDeclaredField( fieldName ) ;
2660 long key = bridge.objectFieldOffset( fld ) ;
2661 bridge.putDouble( o, key, v ) ;
2662 } catch (Exception e) {
2663 throw utilWrapper.errorSetDoubleField( e, fieldName,
2664 o.toString(),
2665 new Double(v) ) ;
2666 }
2667 }
2669 /**
2670 * This class maintains a map of stream position to
2671 * an Object currently being deserialized. It is used
2672 * to handle the cases where the are indirections to
2673 * an object on the recursion stack. The CDR level
2674 * handles indirections to objects previously seen
2675 * (and completely deserialized) in the stream.
2676 */
2677 static class ActiveRecursionManager
2678 {
2679 private Map offsetToObjectMap;
2681 public ActiveRecursionManager() {
2682 // A hash map is unsynchronized and allows
2683 // null values
2684 offsetToObjectMap = new HashMap();
2685 }
2687 // Called right after allocating a new object.
2688 // Offset is the starting position in the stream
2689 // of the object.
2690 public void addObject(int offset, Object value) {
2691 offsetToObjectMap.put(new Integer(offset), value);
2692 }
2694 // If the given starting position doesn't refer
2695 // to the beginning of an object currently being
2696 // deserialized, this throws an IOException.
2697 // Otherwise, it returns a reference to the
2698 // object.
2699 public Object getObject(int offset) throws IOException {
2700 Integer position = new Integer(offset);
2702 if (!offsetToObjectMap.containsKey(position))
2703 // XXX I18N, logging needed.
2704 throw new IOException("Invalid indirection to offset "
2705 + offset);
2707 return offsetToObjectMap.get(position);
2708 }
2710 // Called when an object has been completely
2711 // deserialized, so it should no longer be in
2712 // this mapping. The CDR level can handle
2713 // further indirections.
2714 public void removeObject(int offset) {
2715 offsetToObjectMap.remove(new Integer(offset));
2716 }
2718 // If the given offset doesn't map to an Object,
2719 // then it isn't an indirection to an object
2720 // currently being deserialized.
2721 public boolean containsObject(int offset) {
2722 return offsetToObjectMap.containsKey(new Integer(offset));
2723 }
2724 }
2725 }