src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java

changeset 1
55540e827aef
child 158
91006f157c46
equal deleted inserted replaced
-1:000000000000 1:55540e827aef
1 /*
2 * Copyright 1998-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 */
31
32 package com.sun.corba.se.impl.io;
33
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;
51
52 import sun.corba.Bridge ;
53
54 import java.security.AccessController ;
55 import java.security.PrivilegedAction ;
56
57 import com.sun.corba.se.impl.io.ObjectStreamClass;
58 import com.sun.corba.se.impl.util.Utility;
59
60 import org.omg.CORBA.portable.ValueInputStream;
61
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;
70
71 import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
72 import com.sun.org.omg.SendingContext.CodeBase;
73
74 import javax.rmi.PortableRemoteObject;
75 import javax.rmi.CORBA.Util;
76 import javax.rmi.CORBA.ValueHandler;
77
78 import java.security.*;
79 import java.util.*;
80
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 ;
84
85 import com.sun.corba.se.spi.logging.CORBALogDomains ;
86
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 */
94
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 ) ;
106
107 private static OMGSystemException omgWrapper = OMGSystemException.get(
108 CORBALogDomains.RPC_ENCODING ) ;
109 private static UtilSystemException utilWrapper = UtilSystemException.get(
110 CORBALogDomains.RPC_ENCODING ) ;
111
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;
124
125 private org.omg.CORBA_2_3.portable.InputStream orbStream;
126
127 private CodeBase cbSender;
128
129 private ValueHandlerImpl vhandler; //d4365188
130
131 private Object currentObject = null;
132
133 private ObjectStreamClass currentClassDesc = null;
134
135 private Class currentClass = null;
136
137 private int recursionDepth = 0;
138
139 private int simpleReadDepth = 0;
140
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();
150
151 private IOException abortIOException = null;
152
153 /* Remember the first exception that stopped this stream. */
154 private ClassNotFoundException abortClassNotFoundException = null;
155
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;
161
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;
169
170 private static final String kEmptyStr = "";
171
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);
178
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;
182
183 private byte streamFormatVersion;
184
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;
189
190 private Object[] readObjectArgList = { this } ;
191
192 static {
193 OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor();
194 }
195
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() {
200
201 try {
202
203 Constructor result =
204
205 (Constructor) AccessController.doPrivileged(
206 new PrivilegedExceptionAction() {
207 public java.lang.Object run()
208 throws NoSuchMethodException,
209 SecurityException {
210
211 Constructor boolCtor
212 = OptionalDataException.class.getDeclaredConstructor(
213 new Class[] {
214 Boolean.TYPE });
215
216 boolCtor.setAccessible(true);
217
218 return boolCtor;
219 }});
220
221 if (result == null)
222 // XXX I18N, logging needed.
223 throw new Error("Unable to find OptionalDataException constructor");
224
225 return result;
226
227 } catch (Exception ex) {
228 // XXX I18N, logging needed.
229 throw new ExceptionInInitializerError(ex);
230 }
231 }
232
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 });
241
242 if (result == null)
243 // XXX I18N, logging needed.
244 throw new Error("Created null OptionalDataException");
245
246 return result;
247
248 } catch (Exception ex) {
249 // XXX I18N, logging needed.
250 throw new Error("Couldn't create OptionalDataException", ex);
251 }
252 }
253
254 // Return the stream format version currently being used
255 // to deserialize an object
256 protected byte getStreamFormatVersion() {
257 return streamFormatVersion;
258 }
259
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 {
264
265 streamFormatVersion = orbStream.read_octet();
266
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 }
277
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 }
289
290 public static void setTestFVDFlag(boolean val){
291 // useFVDOnly = val;
292 }
293
294 /**
295 * Dummy constructor; passes upper stream a dummy stream;
296 **/
297 public IIOPInputStream()
298 throws java.io.IOException {
299 super();
300 resetStream();
301 }
302
303 public final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) {
304 orbStream = os;
305 }
306
307 public final org.omg.CORBA_2_3.portable.InputStream getOrbStream() {
308 return orbStream;
309 }
310
311 //added setSender and getSender
312 public final void setSender(CodeBase cb) {
313 cbSender = cb;
314 }
315
316 public final CodeBase getSender() {
317 return cbSender;
318 }
319
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 }
325
326 public final ValueHandler getValueHandler() {
327 return (javax.rmi.CORBA.ValueHandler) vhandler;
328 }
329
330 public final void increaseRecursionDepth(){
331 recursionDepth++;
332 }
333
334 public final int decreaseRecursionDepth(){
335 return --recursionDepth;
336 }
337
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 {
376
377 readObjectState.readData(this);
378
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 }
391
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 {
398
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;
404
405 simpleReadDepth++; // Entering
406 Object obj = null;
407
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 }
418
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 }
439
440
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 }
451
452
453 ClassNotFoundException exCNF = abortClassNotFoundException;
454 if (simpleReadDepth == 0)
455 abortClassNotFoundException = null;
456 if (exCNF != null) {
457 bridge.throwException( exCNF ) ;
458 return null;
459 }
460
461 return obj;
462 }
463
464 public final void simpleSkipObject(String repositoryID,
465 com.sun.org.omg.SendingContext.CodeBase sender)
466 /* throws OptionalDataException, ClassNotFoundException, IOException */
467 {
468
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;
474
475 simpleReadDepth++; // Entering
476 Object obj = null;
477
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 }
501
502
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 }
513
514
515 ClassNotFoundException exCNF = abortClassNotFoundException;
516 if (simpleReadDepth == 0)
517 abortClassNotFoundException = null;
518 if (exCNF != null) {
519 bridge.throwException( exCNF ) ;
520 return;
521 }
522
523 return;
524 }
525 /////////////////
526
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 }
544
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");
569
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) {
576
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.
584
585 // Use the remote fields to unmarshal.
586 inputClassFields(currentObject,
587 currentClass,
588 currentClassDesc,
589 defaultReadObjectFVDMembers,
590 cbSender);
591
592 } else {
593
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 }
614
615 }
616
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 }
637
638 // The following three methods allow the implementing orbStream
639 // to provide mark/reset behavior as defined in java.io.InputStream.
640
641 public final void mark(int readAheadLimit) {
642 orbStream.mark(readAheadLimit);
643 }
644
645 public final boolean markSupported() {
646 return orbStream.markSupported();
647 }
648
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 }
658
659 public final int available() throws IOException{
660 return 0; // unreliable
661 }
662
663 public final void close() throws IOException{
664 // no op
665 }
666
667 public final int read() throws IOException{
668 try{
669 readObjectState.readData(this);
670
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 }
678
679 throw marshalException;
680 } catch(Error e) {
681 IOException exc = new IOException(e.getMessage());
682 exc.initCause(e) ;
683 throw exc ;
684 }
685 }
686
687 public final int read(byte data[], int offset, int length) throws IOException{
688 try{
689 readObjectState.readData(this);
690
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 }
699
700 throw marshalException;
701 } catch(Error e) {
702 IOException exc = new IOException(e.getMessage());
703 exc.initCause(e) ;
704 throw exc ;
705 }
706
707 }
708
709 public final boolean readBoolean() throws IOException{
710 try{
711 readObjectState.readData(this);
712
713 return orbStream.read_boolean();
714 } catch (MARSHAL marshalException) {
715 handleOptionalDataMarshalException(marshalException, false);
716 throw marshalException;
717
718 } catch(Error e) {
719 IOException exc = new IOException(e.getMessage());
720 exc.initCause(e);
721 throw exc ;
722 }
723 }
724
725 public final byte readByte() throws IOException{
726 try{
727 readObjectState.readData(this);
728
729 return orbStream.read_octet();
730 } catch (MARSHAL marshalException) {
731 handleOptionalDataMarshalException(marshalException, false);
732 throw marshalException;
733
734 } catch(Error e) {
735 IOException exc = new IOException(e.getMessage());
736 exc.initCause(e);
737 throw exc ;
738 }
739 }
740
741 public final char readChar() throws IOException{
742 try{
743 readObjectState.readData(this);
744
745 return orbStream.read_wchar();
746 } catch (MARSHAL marshalException) {
747 handleOptionalDataMarshalException(marshalException, false);
748 throw marshalException;
749
750 } catch(Error e) {
751 IOException exc = new IOException(e.getMessage());
752 exc.initCause(e);
753 throw exc ;
754 }
755 }
756
757 public final double readDouble() throws IOException{
758 try{
759 readObjectState.readData(this);
760
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 }
771
772 public final float readFloat() throws IOException{
773 try{
774 readObjectState.readData(this);
775
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 }
786
787 public final void readFully(byte data[]) throws IOException{
788 // d11623 : implement readFully, required for serializing some core classes
789
790 readFully(data, 0, data.length);
791 }
792
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);
797
798 orbStream.read_octet_array(data, offset, size);
799 } catch (MARSHAL marshalException) {
800 handleOptionalDataMarshalException(marshalException, false);
801
802 throw marshalException;
803 } catch(Error e) {
804 IOException exc = new IOException(e.getMessage());
805 exc.initCause(e);
806 throw exc ;
807 }
808 }
809
810 public final int readInt() throws IOException{
811 try{
812 readObjectState.readData(this);
813
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 }
824
825 public final String readLine() throws IOException{
826 // XXX I18N, logging needed.
827 throw new IOException("Method readLine not supported");
828 }
829
830 public final long readLong() throws IOException{
831 try{
832 readObjectState.readData(this);
833
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 }
844
845 public final short readShort() throws IOException{
846 try{
847 readObjectState.readData(this);
848
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 }
859
860 protected final void readStreamHeader() throws IOException, StreamCorruptedException{
861 // no op
862 }
863
864 public final int readUnsignedByte() throws IOException{
865 try{
866 readObjectState.readData(this);
867
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 }
878
879 public final int readUnsignedShort() throws IOException{
880 try{
881 readObjectState.readData(this);
882
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 }
893
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 }
904
905 public final String readUTF() throws IOException{
906 try{
907 readObjectState.readData(this);
908
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 }
919
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 {
930
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) {
939
940 IOException result;
941
942 if (!objectRead)
943 result = new EOFException("No more optional data");
944 else
945 result = createOptionalDataException();
946
947 result.initCause(marshalException);
948
949 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
950
951 throw result;
952 }
953 }
954
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 }
961
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 }
967
968 protected final Object resolveObject(Object obj) throws IOException{
969 // XXX I18N, logging needed.
970 throw new IOException("Method resolveObject not supported");
971 }
972
973 public final int skipBytes(int len) throws IOException{
974 try{
975 readObjectState.readData(this);
976
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);
982
983 throw marshalException;
984 } catch(Error e) {
985 IOException exc = new IOException(e.getMessage());
986 exc.initCause(e) ;
987 throw exc ;
988 }
989 }
990
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 {
997
998 /*
999 * Get the descriptor and then class of the incoming object.
1000 */
1001
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());
1008
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 (currentClassDesc.isExternalizable()) {
1016 try {
1017 currentObject = (currentClass == null) ?
1018 null : currentClassDesc.newInstance();
1019 if (currentObject != null) {
1020
1021 // Store this object and its beginning position
1022 // since there might be indirections to it while
1023 // it's been unmarshalled.
1024 activeRecursionMgr.addObject(offset, currentObject);
1025
1026 // Read format version
1027 readFormatVersion();
1028
1029 Externalizable ext = (Externalizable)currentObject;
1030 ext.readExternal(this);
1031 }
1032 } catch (InvocationTargetException e) {
1033 InvalidClassException exc = new InvalidClassException(
1034 currentClass.getName(),
1035 "InvocationTargetException accessing no-arg constructor");
1036 exc.initCause( e ) ;
1037 throw exc ;
1038 } catch (UnsupportedOperationException e) {
1039 InvalidClassException exc = new InvalidClassException(
1040 currentClass.getName(),
1041 "UnsupportedOperationException accessing no-arg constructor");
1042 exc.initCause( e ) ;
1043 throw exc ;
1044 } catch (InstantiationException e) {
1045 InvalidClassException exc = new InvalidClassException(
1046 currentClass.getName(),
1047 "InstantiationException accessing no-arg constructor");
1048 exc.initCause( e ) ;
1049 throw exc ;
1050 }
1051 } // end : if (currentClassDesc.isExternalizable())
1052 else {
1053 /* Count number of classes and descriptors we might have
1054 * to work on.
1055 */
1056
1057 ObjectStreamClass currdesc = currentClassDesc;
1058 Class currclass = currentClass;
1059
1060 int spBase = spClass; // current top of stack
1061
1062 /* The object's classes should be processed from supertype to subtype
1063 * Push all the clases of the current object onto a stack.
1064 * Note that only the serializable classes are represented
1065 * in the descriptor list.
1066 *
1067 * Handle versioning where one or more supertypes of
1068 * have been inserted or removed. The stack will
1069 * contain pairs of descriptors and the corresponding
1070 * class. If the object has a class that did not occur in
1071 * the original the descriptor will be null. If the
1072 * original object had a descriptor for a class not
1073 * present in the local hierarchy of the object the class will be
1074 * null.
1075 *
1076 */
1077
1078 /*
1079 * This is your basic diff pattern, made simpler
1080 * because reordering is not allowed.
1081 */
1082 // sun.4296963 ibm.11861
1083 // d11861 we should stop when we find the highest serializable class
1084 // We need this so that when we allocate the new object below, we
1085 // can call the constructor of the non-serializable superclass.
1086 // Note that in the JRMP variant of this code the
1087 // ObjectStreamClass.lookup() method handles this, but we've put
1088 // this fix here rather than change lookup because the new behaviour
1089 // is needed in other cases.
1090
1091 for (currdesc = currentClassDesc, currclass = currentClass;
1092 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
1093 currdesc = currdesc.getSuperclass()) {
1094
1095 /*
1096 * Search the classes to see if the class of this
1097 * descriptor appears further up the hierarchy. Until
1098 * it's found assume its an inserted class. If it's
1099 * not found, its the descriptor's class that has been
1100 * removed.
1101 */
1102 Class cc = currdesc.forClass();
1103 Class cl;
1104 for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
1105 if (cc == cl) {
1106 // found a superclass that matches this descriptor
1107 break;
1108 } else {
1109 /* Ignore a class that doesn't match. No
1110 * action is needed since it is already
1111 * initialized.
1112 */
1113 }
1114 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
1115 /* Test if there is room for this new entry.
1116 * If not, double the size of the arrays and copy the contents.
1117 */
1118 spClass++;
1119 if (spClass >= classes.length) {
1120 int newlen = classes.length * 2;
1121 Class[] newclasses = new Class[newlen];
1122 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
1123
1124 System.arraycopy(classes, 0,
1125 newclasses, 0,
1126 classes.length);
1127 System.arraycopy(classdesc, 0,
1128 newclassdesc, 0,
1129 classes.length);
1130
1131 classes = newclasses;
1132 classdesc = newclassdesc;
1133 }
1134
1135 if (cl == null) {
1136 /* Class not found corresponding to this descriptor.
1137 * Pop off all the extra classes pushed.
1138 * Push the descriptor and a null class.
1139 */
1140 classdesc[spClass] = currdesc;
1141 classes[spClass] = null;
1142 } else {
1143 /* Current class descriptor matches current class.
1144 * Some classes may have been inserted.
1145 * Record the match and advance the class, continue
1146 * with the next descriptor.
1147 */
1148 classdesc[spClass] = currdesc;
1149 classes[spClass] = cl;
1150 currclass = cl.getSuperclass();
1151 }
1152 } // end : for (currdesc = currentClassDesc, currclass = currentClass;
1153
1154 /* Allocate a new object. The object is only constructed
1155 * above the highest serializable class and is set to
1156 * default values for all more specialized classes.
1157 */
1158 try {
1159 currentObject = (currentClass == null) ?
1160 null : currentClassDesc.newInstance() ;
1161
1162 // Store this object and its beginning position
1163 // since there might be indirections to it while
1164 // it's been unmarshalled.
1165 activeRecursionMgr.addObject(offset, currentObject);
1166 } catch (InvocationTargetException e) {
1167 InvalidClassException exc = new InvalidClassException(
1168 currentClass.getName(),
1169 "InvocationTargetException accessing no-arg constructor");
1170 exc.initCause( e ) ;
1171 throw exc ;
1172 } catch (UnsupportedOperationException e) {
1173 InvalidClassException exc = new InvalidClassException(
1174 currentClass.getName(),
1175 "UnsupportedOperationException accessing no-arg constructor");
1176 exc.initCause( e ) ;
1177 throw exc ;
1178 } catch (InstantiationException e) {
1179 InvalidClassException exc = new InvalidClassException(
1180 currentClass.getName(),
1181 "InstantiationException accessing no-arg constructor");
1182 exc.initCause( e ) ;
1183 throw exc ;
1184 }
1185
1186 /*
1187 * For all the pushed descriptors and classes.
1188 * if the class has its own writeObject and readObject methods
1189 * call the readObject method
1190 * else
1191 * invoke the defaultReadObject method
1192 */
1193 try {
1194 for (spClass = spClass; spClass > spBase; spClass--) {
1195 /*
1196 * Set current descriptor and corresponding class
1197 */
1198 currentClassDesc = classdesc[spClass];
1199 currentClass = classes[spClass];
1200 if (classes[spClass] != null) {
1201 /* Read the data from the stream described by the
1202 * descriptor and store into the matching class.
1203 */
1204
1205 ReadObjectState oldState = readObjectState;
1206 setState(DEFAULT_STATE);
1207
1208 try {
1209
1210 // Changed since invokeObjectReader no longer does this.
1211 if (currentClassDesc.hasWriteObject()) {
1212
1213 // Read format version
1214 readFormatVersion();
1215
1216 // Read defaultWriteObject indicator
1217 boolean calledDefaultWriteObject = readBoolean();
1218
1219 readObjectState.beginUnmarshalCustomValue(this,
1220 calledDefaultWriteObject,
1221 (currentClassDesc.readObjectMethod
1222 != null));
1223 } else {
1224 if (currentClassDesc.hasReadObject())
1225 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
1226 }
1227
1228 if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) ||
1229 readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) {
1230
1231 // Error case of no readObject and didn't call
1232 // defaultWriteObject handled in default state
1233
1234 ObjectStreamField[] fields =
1235 currentClassDesc.getFieldsNoCopy();
1236 if (fields.length > 0) {
1237 inputClassFields(currentObject, currentClass, fields, sender);
1238 }
1239 }
1240
1241 if (currentClassDesc.hasWriteObject())
1242 readObjectState.endUnmarshalCustomValue(this);
1243
1244 } finally {
1245 setState(oldState);
1246 }
1247
1248 } else {
1249
1250 // _REVISIT_ : Can we ever get here?
1251 /* No local class for this descriptor,
1252 * Skip over the data for this class.
1253 * like defaultReadObject with a null currentObject.
1254 * The code will read the values but discard them.
1255 */
1256 ObjectStreamField[] fields =
1257 currentClassDesc.getFieldsNoCopy();
1258 if (fields.length > 0) {
1259 inputClassFields(null, currentClass, fields, sender);
1260 }
1261
1262 }
1263
1264 }
1265 } finally {
1266 // Make sure we exit at the same stack level as when we started.
1267 spClass = spBase;
1268 }
1269 }
1270 } finally {
1271 // We've completed deserializing this object. Any
1272 // future indirections will be handled correctly at the
1273 // CDR level. The ActiveRecursionManager only deals with
1274 // objects currently being deserialized.
1275 activeRecursionMgr.removeObject(offset);
1276 }
1277
1278 return currentObject;
1279 }
1280
1281 // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
1282 // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable
1283 // classes!
1284 private Vector getOrderedDescriptions(String repositoryID,
1285 com.sun.org.omg.SendingContext.CodeBase sender) {
1286 Vector descs = new Vector();
1287
1288 if (sender == null) {
1289 return descs;
1290 }
1291
1292 FullValueDescription aFVD = sender.meta(repositoryID);
1293 while (aFVD != null) {
1294 descs.insertElementAt(aFVD, 0);
1295 if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
1296 aFVD = sender.meta(aFVD.base_value);
1297 }
1298 else return descs;
1299 }
1300
1301 return descs;
1302 }
1303
1304 /**
1305 * This input method uses FullValueDescriptions retrieved from the sender's runtime to
1306 * read in the data. This method is capable of throwing out data not applicable to client's fields.
1307 * This method handles instances where the reader has a class not sent by the sender, the sender sent
1308 * a class not present on the reader, and/or the reader's class does not match the sender's class.
1309 *
1310 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
1311 * indicates custom marsahling than the local type is used to read the data off the wire. However,
1312 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
1313 * a form of custom marshaling.
1314 *
1315 */
1316 private Object inputObjectUsingFVD(Class clz,
1317 String repositoryID,
1318 com.sun.org.omg.SendingContext.CodeBase sender,
1319 int offset)
1320 throws IOException, ClassNotFoundException
1321 {
1322 int spBase = spClass; // current top of stack
1323 try{
1324
1325 /*
1326 * Get the descriptor and then class of the incoming object.
1327 */
1328
1329 ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
1330 Class currclass = currentClass = clz;
1331
1332 /* If Externalizable,
1333 * Create an instance and tell it to read its data.
1334 * else,
1335 * Handle it as a serializable class.
1336 */
1337 if (currentClassDesc.isExternalizable()) {
1338 try {
1339 currentObject = (currentClass == null) ?
1340 null : currentClassDesc.newInstance();
1341 if (currentObject != null) {
1342 // Store this object and its beginning position
1343 // since there might be indirections to it while
1344 // it's been unmarshalled.
1345 activeRecursionMgr.addObject(offset, currentObject);
1346
1347 // Read format version
1348 readFormatVersion();
1349
1350 Externalizable ext = (Externalizable)currentObject;
1351 ext.readExternal(this);
1352 }
1353 } catch (InvocationTargetException e) {
1354 InvalidClassException exc = new InvalidClassException(
1355 currentClass.getName(),
1356 "InvocationTargetException accessing no-arg constructor");
1357 exc.initCause( e ) ;
1358 throw exc ;
1359 } catch (UnsupportedOperationException e) {
1360 InvalidClassException exc = new InvalidClassException(
1361 currentClass.getName(),
1362 "UnsupportedOperationException accessing no-arg constructor");
1363 exc.initCause( e ) ;
1364 throw exc ;
1365 } catch (InstantiationException e) {
1366 InvalidClassException exc = new InvalidClassException(
1367 currentClass.getName(),
1368 "InstantiationException accessing no-arg constructor");
1369 exc.initCause( e ) ;
1370 throw exc ;
1371 }
1372 } else {
1373 /*
1374 * This is your basic diff pattern, made simpler
1375 * because reordering is not allowed.
1376 */
1377 for (currdesc = currentClassDesc, currclass = currentClass;
1378 currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
1379
1380 currdesc = currdesc.getSuperclass()) {
1381
1382 /*
1383 * Search the classes to see if the class of this
1384 * descriptor appears further up the hierarchy. Until
1385 * it's found assume its an inserted class. If it's
1386 * not found, its the descriptor's class that has been
1387 * removed.
1388 */
1389 Class cc = currdesc.forClass();
1390 Class cl;
1391 for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
1392 if (cc == cl) {
1393 // found a superclass that matches this descriptor
1394 break;
1395 } else {
1396 /* Ignore a class that doesn't match. No
1397 * action is needed since it is already
1398 * initialized.
1399 */
1400 }
1401 } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
1402 /* Test if there is room for this new entry.
1403 * If not, double the size of the arrays and copy the contents.
1404 */
1405 spClass++;
1406 if (spClass >= classes.length) {
1407 int newlen = classes.length * 2;
1408 Class[] newclasses = new Class[newlen];
1409 ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
1410
1411 System.arraycopy(classes, 0,
1412 newclasses, 0,
1413 classes.length);
1414 System.arraycopy(classdesc, 0,
1415 newclassdesc, 0,
1416 classes.length);
1417
1418 classes = newclasses;
1419 classdesc = newclassdesc;
1420 }
1421
1422 if (cl == null) {
1423 /* Class not found corresponding to this descriptor.
1424 * Pop off all the extra classes pushed.
1425 * Push the descriptor and a null class.
1426 */
1427 classdesc[spClass] = currdesc;
1428 classes[spClass] = null;
1429 } else {
1430 /* Current class descriptor matches current class.
1431 * Some classes may have been inserted.
1432 * Record the match and advance the class, continue
1433 * with the next descriptor.
1434 */
1435 classdesc[spClass] = currdesc;
1436 classes[spClass] = cl;
1437 currclass = cl.getSuperclass();
1438 }
1439 } // end : for (currdesc = currentClassDesc, currclass = currentClass;
1440
1441 /* Allocate a new object.
1442 */
1443 try {
1444 currentObject = (currentClass == null) ?
1445 null : currentClassDesc.newInstance();
1446
1447 // Store this object and its beginning position
1448 // since there might be indirections to it while
1449 // it's been unmarshalled.
1450 activeRecursionMgr.addObject(offset, currentObject);
1451 } catch (InvocationTargetException e) {
1452 InvalidClassException exc = new InvalidClassException(
1453 currentClass.getName(),
1454 "InvocationTargetException accessing no-arg constructor");
1455 exc.initCause( e ) ;
1456 throw exc ;
1457 } catch (UnsupportedOperationException e) {
1458 InvalidClassException exc = new InvalidClassException(
1459 currentClass.getName(),
1460 "UnsupportedOperationException accessing no-arg constructor");
1461 exc.initCause( e ) ;
1462 throw exc ;
1463 } catch (InstantiationException e) {
1464 InvalidClassException exc = new InvalidClassException(
1465 currentClass.getName(),
1466 "InstantiationException accessing no-arg constructor");
1467 exc.initCause( e ) ;
1468 throw exc ;
1469 }
1470
1471 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
1472
1473 while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
1474 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1475 // d4365188: backward compatability
1476 String repIDForFVD = vhandler.getClassName(fvd.id);
1477 String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
1478
1479 while ((spClass > spBase) &&
1480 (!repIDForFVD.equals(repIDForClass))) {
1481 int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
1482 if (pos != -1) {
1483 spClass = pos;
1484 currclass = currentClass = classes[spClass];
1485 repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
1486 }
1487 else { // Read and throw away one level of the fvdslist
1488
1489 // This seems to mean that the sender had a superclass that
1490 // we don't have
1491
1492 if (fvd.is_custom) {
1493
1494 readFormatVersion();
1495 boolean calledDefaultWriteObject = readBoolean();
1496
1497 if (calledDefaultWriteObject)
1498 inputClassFields(null, null, null, fvd.members, sender);
1499
1500 if (getStreamFormatVersion() == 2) {
1501
1502 ((ValueInputStream)getOrbStream()).start_value();
1503 ((ValueInputStream)getOrbStream()).end_value();
1504 }
1505
1506 // WARNING: If stream format version is 1 and there's
1507 // optional data, we'll get some form of exception down
1508 // the line or data corruption.
1509
1510 } else {
1511
1512 inputClassFields(null, currentClass, null, fvd.members, sender);
1513 }
1514
1515 if (fvdsList.hasMoreElements()){
1516 fvd = (FullValueDescription)fvdsList.nextElement();
1517 repIDForFVD = vhandler.getClassName(fvd.id);
1518 }
1519 else return currentObject;
1520 }
1521 }
1522
1523 currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
1524
1525 if (!repIDForClass.equals("java.lang.Object")) {
1526
1527 // If the sender used custom marshaling, then it should have put
1528 // the two bytes on the wire indicating stream format version
1529 // and whether or not the writeObject method called
1530 // defaultWriteObject/writeFields.
1531
1532 ReadObjectState oldState = readObjectState;
1533 setState(DEFAULT_STATE);
1534
1535 try {
1536
1537 if (fvd.is_custom) {
1538
1539 // Read format version
1540 readFormatVersion();
1541
1542 // Read defaultWriteObject indicator
1543 boolean calledDefaultWriteObject = readBoolean();
1544
1545 readObjectState.beginUnmarshalCustomValue(this,
1546 calledDefaultWriteObject,
1547 (currentClassDesc.readObjectMethod
1548 != null));
1549 }
1550
1551 boolean usedReadObject = false;
1552
1553 // Always use readObject if it exists, and fall back to default
1554 // unmarshaling if it doesn't.
1555 try {
1556
1557 if (!fvd.is_custom && currentClassDesc.hasReadObject())
1558 setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
1559
1560 // See the definition of defaultReadObjectFVDMembers
1561 // for more information. This concerns making sure
1562 // we use the remote FVD's members in defaultReadObject.
1563 defaultReadObjectFVDMembers = fvd.members;
1564 usedReadObject = invokeObjectReader(currentClassDesc,
1565 currentObject,
1566 currentClass);
1567
1568 } finally {
1569 defaultReadObjectFVDMembers = null;
1570 }
1571
1572 // Note that the !usedReadObject !calledDefaultWriteObject
1573 // case is handled by the beginUnmarshalCustomValue method
1574 // of the default state
1575 if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT)
1576 inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
1577
1578 if (fvd.is_custom)
1579 readObjectState.endUnmarshalCustomValue(this);
1580
1581 } finally {
1582 setState(oldState);
1583 }
1584
1585 currclass = currentClass = classes[--spClass];
1586
1587 } else {
1588
1589 // The remaining hierarchy of the local class does not match the sender's FVD.
1590 // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate
1591 // custom marshaling, throw MARSHAL error.
1592 inputClassFields(null, currentClass, null, fvd.members, sender);
1593
1594 while (fvdsList.hasMoreElements()){
1595 fvd = (FullValueDescription)fvdsList.nextElement();
1596
1597 if (fvd.is_custom)
1598 skipCustomUsingFVD(fvd.members, sender);
1599 else
1600 inputClassFields(null, currentClass, null, fvd.members, sender);
1601 }
1602
1603 }
1604
1605 } // end : while(fvdsList.hasMoreElements())
1606 while (fvdsList.hasMoreElements()){
1607
1608 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1609 if (fvd.is_custom)
1610 skipCustomUsingFVD(fvd.members, sender);
1611 else
1612 throwAwayData(fvd.members, sender);
1613 }
1614 }
1615
1616 return currentObject;
1617 }
1618 finally {
1619 // Make sure we exit at the same stack level as when we started.
1620 spClass = spBase;
1621
1622 // We've completed deserializing this object. Any
1623 // future indirections will be handled correctly at the
1624 // CDR level. The ActiveRecursionManager only deals with
1625 // objects currently being deserialized.
1626 activeRecursionMgr.removeObject(offset);
1627 }
1628
1629 }
1630
1631 /**
1632 * This input method uses FullValueDescriptions retrieved from the sender's runtime to
1633 * read in the data. This method is capable of throwing out data not applicable to client's fields.
1634 *
1635 * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
1636 * indicates custom marsahling than the local type is used to read the data off the wire. However,
1637 * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
1638 * a form of custom marshaling.
1639 *
1640 */
1641 private Object skipObjectUsingFVD(String repositoryID,
1642 com.sun.org.omg.SendingContext.CodeBase sender)
1643 throws IOException, ClassNotFoundException
1644 {
1645
1646 Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
1647
1648 while(fvdsList.hasMoreElements()) {
1649 FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1650 String repIDForFVD = vhandler.getClassName(fvd.id);
1651
1652 if (!repIDForFVD.equals("java.lang.Object")) {
1653 if (fvd.is_custom) {
1654
1655 readFormatVersion();
1656
1657 boolean calledDefaultWriteObject = readBoolean();
1658
1659 if (calledDefaultWriteObject)
1660 inputClassFields(null, null, null, fvd.members, sender);
1661
1662 if (getStreamFormatVersion() == 2) {
1663
1664 ((ValueInputStream)getOrbStream()).start_value();
1665 ((ValueInputStream)getOrbStream()).end_value();
1666 }
1667
1668 // WARNING: If stream format version is 1 and there's
1669 // optional data, we'll get some form of exception down
1670 // the line.
1671
1672 } else {
1673 // Use default marshaling
1674 inputClassFields(null, null, null, fvd.members, sender);
1675 }
1676 }
1677
1678 } // end : while(fvdsList.hasMoreElements())
1679 return null;
1680
1681 }
1682
1683 ///////////////////
1684
1685 private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){
1686
1687 for (int i = _spClass; i > _spBase; i--){
1688 if (classname.equals(classes[i].getName())) {
1689 return i;
1690 }
1691 }
1692
1693 return -1;
1694 }
1695
1696 /*
1697 * Invoke the readObject method if present. Assumes that in the case of custom
1698 * marshaling, the format version and defaultWriteObject indicator were already
1699 * removed.
1700 */
1701 private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass)
1702 throws InvalidClassException, StreamCorruptedException,
1703 ClassNotFoundException, IOException
1704 {
1705 if (osc.readObjectMethod == null) {
1706 return false;
1707 }
1708
1709 try {
1710 osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
1711 return true;
1712 } catch (InvocationTargetException e) {
1713 Throwable t = e.getTargetException();
1714 if (t instanceof ClassNotFoundException)
1715 throw (ClassNotFoundException)t;
1716 else if (t instanceof IOException)
1717 throw (IOException)t;
1718 else if (t instanceof RuntimeException)
1719 throw (RuntimeException) t;
1720 else if (t instanceof Error)
1721 throw (Error) t;
1722 else
1723 // XXX I18N, logging needed.
1724 throw new Error("internal error");
1725 } catch (IllegalAccessException e) {
1726 return false;
1727 }
1728 }
1729
1730 /*
1731 * Reset the stream to be just like it was after the constructor.
1732 */
1733 private void resetStream() throws IOException {
1734
1735 if (classes == null)
1736 classes = new Class[20];
1737 else {
1738 for (int i = 0; i < classes.length; i++)
1739 classes[i] = null;
1740 }
1741 if (classdesc == null)
1742 classdesc = new ObjectStreamClass[20];
1743 else {
1744 for (int i = 0; i < classdesc.length; i++)
1745 classdesc[i] = null;
1746 }
1747 spClass = 0;
1748
1749 if (callbacks != null)
1750 callbacks.setSize(0); // discard any pending callbacks
1751 }
1752
1753 /**
1754 * Factored out of inputClassFields This reads a primitive value and sets it
1755 * in the field of o described by the ObjectStreamField field.
1756 *
1757 * Note that reflection cannot be used here, because reflection cannot be used
1758 * to set final fields.
1759 */
1760 private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field)
1761 throws InvalidClassException, IOException {
1762
1763 try {
1764 switch (field.getTypeCode()) {
1765 case 'B':
1766 byte byteValue = orbStream.read_octet();
1767 bridge.putByte( o, field.getFieldID(), byteValue ) ;
1768 //reflective code: field.getField().setByte( o, byteValue ) ;
1769 break;
1770 case 'Z':
1771 boolean booleanValue = orbStream.read_boolean();
1772 bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
1773 //reflective code: field.getField().setBoolean( o, booleanValue ) ;
1774 break;
1775 case 'C':
1776 char charValue = orbStream.read_wchar();
1777 bridge.putChar( o, field.getFieldID(), charValue ) ;
1778 //reflective code: field.getField().setChar( o, charValue ) ;
1779 break;
1780 case 'S':
1781 short shortValue = orbStream.read_short();
1782 bridge.putShort( o, field.getFieldID(), shortValue ) ;
1783 //reflective code: field.getField().setShort( o, shortValue ) ;
1784 break;
1785 case 'I':
1786 int intValue = orbStream.read_long();
1787 bridge.putInt( o, field.getFieldID(), intValue ) ;
1788 //reflective code: field.getField().setInt( o, intValue ) ;
1789 break;
1790 case 'J':
1791 long longValue = orbStream.read_longlong();
1792 bridge.putLong( o, field.getFieldID(), longValue ) ;
1793 //reflective code: field.getField().setLong( o, longValue ) ;
1794 break;
1795 case 'F' :
1796 float floatValue = orbStream.read_float();
1797 bridge.putFloat( o, field.getFieldID(), floatValue ) ;
1798 //reflective code: field.getField().setFloat( o, floatValue ) ;
1799 break;
1800 case 'D' :
1801 double doubleValue = orbStream.read_double();
1802 bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
1803 //reflective code: field.getField().setDouble( o, doubleValue ) ;
1804 break;
1805 default:
1806 // XXX I18N, logging needed.
1807 throw new InvalidClassException(cl.getName());
1808 }
1809 } catch (IllegalArgumentException e) {
1810 /* This case should never happen. If the field types
1811 are not the same, InvalidClassException is raised when
1812 matching the local class to the serialized ObjectStreamClass. */
1813 ClassCastException cce = new ClassCastException("Assigning instance of class " +
1814 field.getType().getName() +
1815 " to field " +
1816 currentClassDesc.getName() + '#' +
1817 field.getField().getName());
1818 cce.initCause( e ) ;
1819 throw cce ;
1820 }
1821 }
1822
1823 private Object inputObjectField(org.omg.CORBA.ValueMember field,
1824 com.sun.org.omg.SendingContext.CodeBase sender)
1825 throws IndirectionException, ClassNotFoundException, IOException,
1826 StreamCorruptedException {
1827
1828 Object objectValue = null;
1829 Class type = null;
1830 String id = field.id;
1831
1832 try {
1833 type = vhandler.getClassFromType(id);
1834 } catch(ClassNotFoundException cnfe) {
1835 // Make sure type = null
1836 type = null;
1837 }
1838
1839 String signature = null;
1840 if (type != null)
1841 signature = ValueUtility.getSignature(field);
1842
1843 if (signature != null && (signature.equals("Ljava/lang/Object;") ||
1844 signature.equals("Ljava/io/Serializable;") ||
1845 signature.equals("Ljava/io/Externalizable;"))) {
1846 objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
1847 } else {
1848 // Decide what method call to make based on the type. If
1849 // it is a type for which we need to load a stub, convert
1850 // the type to the correct stub type.
1851 //
1852 // NOTE : Since FullValueDescription does not allow us
1853 // to ask whether something is an interface we do not
1854 // have the ability to optimize this check.
1855
1856 int callType = ValueHandlerImpl.kValueType;
1857
1858 if (!vhandler.isSequence(id)) {
1859
1860 if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
1861
1862 // RMI Object reference...
1863 callType = ValueHandlerImpl.kRemoteType;
1864
1865 } else {
1866
1867 // REVISIT. If we don't have the local class,
1868 // we should probably verify that it's an RMI type,
1869 // query the remote FVD, and use is_abstract.
1870 // Our FVD seems to get NullPointerExceptions for any
1871 // non-RMI types.
1872
1873 // This uses the local class in the same way as
1874 // inputObjectField(ObjectStreamField) does. REVISIT
1875 // inputObjectField(ObjectStreamField)'s loadStubClass
1876 // logic. Assumption is that the given type cannot
1877 // evolve to become a CORBA abstract interface or
1878 // a RMI abstract interface.
1879
1880 if (type != null && type.isInterface() &&
1881 (vhandler.isAbstractBase(type) ||
1882 ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
1883
1884 callType = ValueHandlerImpl.kAbstractType;
1885 }
1886 }
1887 }
1888
1889 // Now that we have used the FVD of the field to determine the proper course
1890 // of action, it is ok to use the type (Class) from this point forward since
1891 // the rep. id for this read will also follow on the wire.
1892
1893 switch (callType) {
1894 case ValueHandlerImpl.kRemoteType:
1895 if (type != null)
1896 objectValue = Utility.readObjectAndNarrow(orbStream, type);
1897 else
1898 objectValue = orbStream.read_Object();
1899 break;
1900 case ValueHandlerImpl.kAbstractType:
1901 if (type != null)
1902 objectValue = Utility.readAbstractAndNarrow(orbStream, type);
1903 else
1904 objectValue = orbStream.read_abstract_interface();
1905 break;
1906 case ValueHandlerImpl.kValueType:
1907 if (type != null)
1908 objectValue = orbStream.read_value(type);
1909 else
1910 objectValue = orbStream.read_value();
1911 break;
1912 default:
1913 // XXX I18N, logging needed.
1914 throw new StreamCorruptedException("Unknown callType: " + callType);
1915 }
1916 }
1917
1918 return objectValue;
1919 }
1920
1921 /**
1922 * Factored out of inputClassFields and reused in
1923 * inputCurrentClassFieldsForReadFields.
1924 *
1925 * Reads the field (which of an Object type as opposed to a primitive)
1926 * described by ObjectStreamField field and returns it.
1927 */
1928 private Object inputObjectField(ObjectStreamField field)
1929 throws InvalidClassException, StreamCorruptedException,
1930 ClassNotFoundException, IndirectionException, IOException {
1931
1932 if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
1933 return javax.rmi.CORBA.Util.readAny(orbStream);
1934 }
1935
1936 Object objectValue = null;
1937
1938 // fields have an API to provide the actual class
1939 // corresponding to the data type
1940 // Class type = osc.forClass();
1941 Class fieldType = field.getType();
1942 Class actualType = fieldType; // This may change if stub loaded.
1943
1944 // Decide what method call to make based on the fieldType. If
1945 // it is a type for which we need to load a stub, convert
1946 // the type to the correct stub type.
1947
1948 int callType = ValueHandlerImpl.kValueType;
1949 boolean narrow = false;
1950
1951 if (fieldType.isInterface()) {
1952 boolean loadStubClass = false;
1953
1954 if (java.rmi.Remote.class.isAssignableFrom(fieldType)) {
1955
1956 // RMI Object reference...
1957 callType = ValueHandlerImpl.kRemoteType;
1958
1959 } else if (org.omg.CORBA.Object.class.isAssignableFrom(fieldType)){
1960
1961 // IDL Object reference...
1962 callType = ValueHandlerImpl.kRemoteType;
1963 loadStubClass = true;
1964
1965 } else if (vhandler.isAbstractBase(fieldType)) {
1966 // IDL Abstract Object reference...
1967
1968 callType = ValueHandlerImpl.kAbstractType;
1969 loadStubClass = true;
1970 } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
1971 // RMI Abstract Object reference...
1972
1973 callType = ValueHandlerImpl.kAbstractType;
1974 }
1975
1976 if (loadStubClass) {
1977 try {
1978 String codebase = Util.getCodebase(fieldType);
1979 String repID = vhandler.createForAnyType(fieldType);
1980 Class stubType =
1981 Utility.loadStubClass(repID, codebase, fieldType);
1982 actualType = stubType;
1983 } catch (ClassNotFoundException e) {
1984 narrow = true;
1985 }
1986 } else {
1987 narrow = true;
1988 }
1989 }
1990
1991 switch (callType) {
1992 case ValueHandlerImpl.kRemoteType:
1993 if (!narrow)
1994 objectValue = (Object)orbStream.read_Object(actualType);
1995 else
1996 objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
1997 break;
1998 case ValueHandlerImpl.kAbstractType:
1999 if (!narrow)
2000 objectValue = (Object)orbStream.read_abstract_interface(actualType);
2001 else
2002 objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
2003 break;
2004 case ValueHandlerImpl.kValueType:
2005 objectValue = (Object)orbStream.read_value(actualType);
2006 break;
2007 default:
2008 // XXX I18N, logging needed.
2009 throw new StreamCorruptedException("Unknown callType: " + callType);
2010 }
2011
2012 return objectValue;
2013 }
2014
2015 private final boolean mustUseRemoteValueMembers() {
2016 return defaultReadObjectFVDMembers != null;
2017 }
2018
2019 void readFields(java.util.Map fieldToValueMap)
2020 throws InvalidClassException, StreamCorruptedException,
2021 ClassNotFoundException, IOException {
2022
2023 if (mustUseRemoteValueMembers()) {
2024 inputRemoteMembersForReadFields(fieldToValueMap);
2025 } else
2026 inputCurrentClassFieldsForReadFields(fieldToValueMap);
2027 }
2028
2029 private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
2030 throws InvalidClassException, StreamCorruptedException,
2031 ClassNotFoundException, IOException {
2032
2033 // Must have this local variable since defaultReadObjectFVDMembers
2034 // may get mangled by recursion.
2035 ValueMember fields[] = defaultReadObjectFVDMembers;
2036
2037 try {
2038
2039 for (int i = 0; i < fields.length; i++) {
2040
2041 switch (fields[i].type.kind().value()) {
2042
2043 case TCKind._tk_octet:
2044 byte byteValue = orbStream.read_octet();
2045 fieldToValueMap.put(fields[i].name, new Byte(byteValue));
2046 break;
2047 case TCKind._tk_boolean:
2048 boolean booleanValue = orbStream.read_boolean();
2049 fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
2050 break;
2051 case TCKind._tk_char:
2052 // Backwards compatibility. Older Sun ORBs sent
2053 // _tk_char even though they read and wrote wchars
2054 // correctly.
2055 //
2056 // Fall through to the _tk_wchar case.
2057 case TCKind._tk_wchar:
2058 char charValue = orbStream.read_wchar();
2059 fieldToValueMap.put(fields[i].name, new Character(charValue));
2060 break;
2061 case TCKind._tk_short:
2062 short shortValue = orbStream.read_short();
2063 fieldToValueMap.put(fields[i].name, new Short(shortValue));
2064 break;
2065 case TCKind._tk_long:
2066 int intValue = orbStream.read_long();
2067 fieldToValueMap.put(fields[i].name, new Integer(intValue));
2068 break;
2069 case TCKind._tk_longlong:
2070 long longValue = orbStream.read_longlong();
2071 fieldToValueMap.put(fields[i].name, new Long(longValue));
2072 break;
2073 case TCKind._tk_float:
2074 float floatValue = orbStream.read_float();
2075 fieldToValueMap.put(fields[i].name, new Float(floatValue));
2076 break;
2077 case TCKind._tk_double:
2078 double doubleValue = orbStream.read_double();
2079 fieldToValueMap.put(fields[i].name, new Double(doubleValue));
2080 break;
2081 case TCKind._tk_value:
2082 case TCKind._tk_objref:
2083 case TCKind._tk_value_box:
2084 Object objectValue = null;
2085 try {
2086 objectValue = inputObjectField(fields[i],
2087 cbSender);
2088
2089 } catch (IndirectionException cdrie) {
2090 // The CDR stream had never seen the given offset before,
2091 // so check the recursion manager (it will throw an
2092 // IOException if it doesn't have a reference, either).
2093 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2094 }
2095
2096 fieldToValueMap.put(fields[i].name, objectValue);
2097 break;
2098 default:
2099 // XXX I18N, logging needed.
2100 throw new StreamCorruptedException("Unknown kind: "
2101 + fields[i].type.kind().value());
2102 }
2103 }
2104 } catch (Throwable t) {
2105 StreamCorruptedException result = new StreamCorruptedException(t.getMessage());
2106 result.initCause(t);
2107 throw result;
2108 }
2109 }
2110
2111 /**
2112 * Called from InputStreamHook.
2113 *
2114 * Reads the fields of the current class (could be the ones
2115 * queried from the remote FVD) and puts them in
2116 * the given Map, name to value. Wraps primitives in the
2117 * corresponding java.lang Objects.
2118 */
2119 private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
2120 throws InvalidClassException, StreamCorruptedException,
2121 ClassNotFoundException, IOException {
2122
2123 ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
2124
2125 int primFields = fields.length - currentClassDesc.objFields;
2126
2127 // Handle the primitives first
2128 for (int i = 0; i < primFields; ++i) {
2129
2130 switch (fields[i].getTypeCode()) {
2131 case 'B':
2132 byte byteValue = orbStream.read_octet();
2133 fieldToValueMap.put(fields[i].getName(),
2134 new Byte(byteValue));
2135 break;
2136 case 'Z':
2137 boolean booleanValue = orbStream.read_boolean();
2138 fieldToValueMap.put(fields[i].getName(),
2139 new Boolean(booleanValue));
2140 break;
2141 case 'C':
2142 char charValue = orbStream.read_wchar();
2143 fieldToValueMap.put(fields[i].getName(),
2144 new Character(charValue));
2145 break;
2146 case 'S':
2147 short shortValue = orbStream.read_short();
2148 fieldToValueMap.put(fields[i].getName(),
2149 new Short(shortValue));
2150 break;
2151 case 'I':
2152 int intValue = orbStream.read_long();
2153 fieldToValueMap.put(fields[i].getName(),
2154 new Integer(intValue));
2155 break;
2156 case 'J':
2157 long longValue = orbStream.read_longlong();
2158 fieldToValueMap.put(fields[i].getName(),
2159 new Long(longValue));
2160 break;
2161 case 'F' :
2162 float floatValue = orbStream.read_float();
2163 fieldToValueMap.put(fields[i].getName(),
2164 new Float(floatValue));
2165 break;
2166 case 'D' :
2167 double doubleValue = orbStream.read_double();
2168 fieldToValueMap.put(fields[i].getName(),
2169 new Double(doubleValue));
2170 break;
2171 default:
2172 // XXX I18N, logging needed.
2173 throw new InvalidClassException(currentClassDesc.getName());
2174 }
2175 }
2176
2177 /* Read and set object fields from the input stream. */
2178 if (currentClassDesc.objFields > 0) {
2179 for (int i = primFields; i < fields.length; i++) {
2180 Object objectValue = null;
2181 try {
2182 objectValue = inputObjectField(fields[i]);
2183 } catch(IndirectionException cdrie) {
2184 // The CDR stream had never seen the given offset before,
2185 // so check the recursion manager (it will throw an
2186 // IOException if it doesn't have a reference, either).
2187 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2188 }
2189
2190 fieldToValueMap.put(fields[i].getName(), objectValue);
2191 }
2192 }
2193 }
2194
2195 /*
2196 * Read the fields of the specified class from the input stream and set
2197 * the values of the fields in the specified object. If the specified
2198 * object is null, just consume the fields without setting any values. If
2199 * any ObjectStreamField does not have a reflected Field, don't try to set
2200 * that field in the object.
2201 *
2202 * REVISIT -- This code doesn't do what the comment says to when
2203 * getField() is null!
2204 */
2205 private void inputClassFields(Object o, Class cl,
2206 ObjectStreamField[] fields,
2207 com.sun.org.omg.SendingContext.CodeBase sender)
2208 throws InvalidClassException, StreamCorruptedException,
2209 ClassNotFoundException, IOException
2210 {
2211
2212 int primFields = fields.length - currentClassDesc.objFields;
2213
2214 if (o != null) {
2215 for (int i = 0; i < primFields; ++i) {
2216 if (fields[i].getField() == null)
2217 continue;
2218
2219 inputPrimitiveField(o, cl, fields[i]);
2220 }
2221 }
2222
2223 /* Read and set object fields from the input stream. */
2224 if (currentClassDesc.objFields > 0) {
2225 for (int i = primFields; i < fields.length; i++) {
2226 Object objectValue = null;
2227
2228 try {
2229 objectValue = inputObjectField(fields[i]);
2230 } catch(IndirectionException cdrie) {
2231 // The CDR stream had never seen the given offset before,
2232 // so check the recursion manager (it will throw an
2233 // IOException if it doesn't have a reference, either).
2234 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2235 }
2236
2237 if ((o == null) || (fields[i].getField() == null)) {
2238 continue;
2239 }
2240
2241 try {
2242 bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
2243 // reflective code: fields[i].getField().set( o, objectValue ) ;
2244 } catch (IllegalArgumentException e) {
2245 ClassCastException exc = new ClassCastException("Assigning instance of class " +
2246 objectValue.getClass().getName() +
2247 " to field " +
2248 currentClassDesc.getName() +
2249 '#' +
2250 fields[i].getField().getName());
2251 exc.initCause( e ) ;
2252 throw exc ;
2253 }
2254 } // end : for loop
2255 }
2256 }
2257
2258 /*
2259 * Read the fields of the specified class from the input stream and set
2260 * the values of the fields in the specified object. If the specified
2261 * object is null, just consume the fields without setting any values. If
2262 * any ObjectStreamField does not have a reflected Field, don't try to set
2263 * that field in the object.
2264 */
2265 private void inputClassFields(Object o, Class cl,
2266 ObjectStreamClass osc,
2267 ValueMember[] fields,
2268 com.sun.org.omg.SendingContext.CodeBase sender)
2269 throws InvalidClassException, StreamCorruptedException,
2270 ClassNotFoundException, IOException
2271 {
2272 try{
2273 for (int i = 0; i < fields.length; ++i) {
2274 try {
2275 switch (fields[i].type.kind().value()) {
2276 case TCKind._tk_octet:
2277 byte byteValue = orbStream.read_octet();
2278 if ((o != null) && osc.hasField(fields[i]))
2279 setByteField(o, cl, fields[i].name, byteValue);
2280 break;
2281 case TCKind._tk_boolean:
2282 boolean booleanValue = orbStream.read_boolean();
2283 if ((o != null) && osc.hasField(fields[i]))
2284 setBooleanField(o, cl, fields[i].name, booleanValue);
2285 break;
2286 case TCKind._tk_char:
2287 // Backwards compatibility. Older Sun ORBs sent
2288 // _tk_char even though they read and wrote wchars
2289 // correctly.
2290 //
2291 // Fall through to the _tk_wchar case.
2292 case TCKind._tk_wchar:
2293 char charValue = orbStream.read_wchar();
2294 if ((o != null) && osc.hasField(fields[i]))
2295 setCharField(o, cl, fields[i].name, charValue);
2296 break;
2297 case TCKind._tk_short:
2298 short shortValue = orbStream.read_short();
2299 if ((o != null) && osc.hasField(fields[i]))
2300 setShortField(o, cl, fields[i].name, shortValue);
2301 break;
2302 case TCKind._tk_long:
2303 int intValue = orbStream.read_long();
2304 if ((o != null) && osc.hasField(fields[i]))
2305 setIntField(o, cl, fields[i].name, intValue);
2306 break;
2307 case TCKind._tk_longlong:
2308 long longValue = orbStream.read_longlong();
2309 if ((o != null) && osc.hasField(fields[i]))
2310 setLongField(o, cl, fields[i].name, longValue);
2311 break;
2312 case TCKind._tk_float:
2313 float floatValue = orbStream.read_float();
2314 if ((o != null) && osc.hasField(fields[i]))
2315 setFloatField(o, cl, fields[i].name, floatValue);
2316 break;
2317 case TCKind._tk_double:
2318 double doubleValue = orbStream.read_double();
2319 if ((o != null) && osc.hasField(fields[i]))
2320 setDoubleField(o, cl, fields[i].name, doubleValue);
2321 break;
2322 case TCKind._tk_value:
2323 case TCKind._tk_objref:
2324 case TCKind._tk_value_box:
2325 Object objectValue = null;
2326 try {
2327 objectValue = inputObjectField(fields[i], sender);
2328 } catch (IndirectionException cdrie) {
2329 // The CDR stream had never seen the given offset before,
2330 // so check the recursion manager (it will throw an
2331 // IOException if it doesn't have a reference, either).
2332 objectValue = activeRecursionMgr.getObject(cdrie.offset);
2333 }
2334
2335 if (o == null)
2336 continue;
2337 try {
2338 if (osc.hasField(fields[i])){
2339 setObjectField(o,
2340 cl,
2341 fields[i].name,
2342 objectValue);
2343 } else {
2344 // REVISIT. Convert to a log message.
2345 // This is a normal case when fields have
2346 // been added as part of evolution, but
2347 // silently skipping can make it hard to
2348 // debug if there's an error
2349 // System.out.println("**** warning, not setting field: "
2350 // + fields[i].name
2351 // + " since not on class "
2352 // + osc.getName());
2353
2354 }
2355 } catch (IllegalArgumentException e) {
2356 // XXX I18N, logging needed.
2357 ClassCastException cce = new ClassCastException("Assigning instance of class " +
2358 objectValue.getClass().getName() + " to field " + fields[i].name);
2359 cce.initCause(e) ;
2360 throw cce ;
2361 }
2362 break;
2363 default:
2364 // XXX I18N, logging needed.
2365 throw new StreamCorruptedException("Unknown kind: "
2366 + fields[i].type.kind().value());
2367 }
2368 } catch (IllegalArgumentException e) {
2369 /* This case should never happen. If the field types
2370 are not the same, InvalidClassException is raised when
2371 matching the local class to the serialized ObjectStreamClass. */
2372 // XXX I18N, logging needed.
2373 ClassCastException cce = new ClassCastException("Assigning instance of class " + fields[i].id +
2374 " to field " + currentClassDesc.getName() + '#' + fields[i].name);
2375 cce.initCause( e ) ;
2376 throw cce ;
2377 }
2378 }
2379 } catch(Throwable t){
2380 // XXX I18N, logging needed.
2381 StreamCorruptedException sce = new StreamCorruptedException(t.getMessage());
2382 sce.initCause(t) ;
2383 throw sce ;
2384 }
2385 }
2386
2387 private void skipCustomUsingFVD(ValueMember[] fields,
2388 com.sun.org.omg.SendingContext.CodeBase sender)
2389 throws InvalidClassException, StreamCorruptedException,
2390 ClassNotFoundException, IOException
2391 {
2392 readFormatVersion();
2393 boolean calledDefaultWriteObject = readBoolean();
2394
2395 if (calledDefaultWriteObject)
2396 throwAwayData(fields, sender);
2397
2398 if (getStreamFormatVersion() == 2) {
2399
2400 ((ValueInputStream)getOrbStream()).start_value();
2401 ((ValueInputStream)getOrbStream()).end_value();
2402 }
2403 }
2404
2405 /*
2406 * Read the fields of the specified class from the input stream throw data away.
2407 * This must handle same switch logic as above.
2408 */
2409 private void throwAwayData(ValueMember[] fields,
2410 com.sun.org.omg.SendingContext.CodeBase sender)
2411 throws InvalidClassException, StreamCorruptedException,
2412 ClassNotFoundException, IOException
2413 {
2414 for (int i = 0; i < fields.length; ++i) {
2415
2416 try {
2417
2418 switch (fields[i].type.kind().value()) {
2419 case TCKind._tk_octet:
2420 orbStream.read_octet();
2421 break;
2422 case TCKind._tk_boolean:
2423 orbStream.read_boolean();
2424 break;
2425 case TCKind._tk_char:
2426 // Backwards compatibility. Older Sun ORBs sent
2427 // _tk_char even though they read and wrote wchars
2428 // correctly.
2429 //
2430 // Fall through to the _tk_wchar case.
2431 case TCKind._tk_wchar:
2432 orbStream.read_wchar();
2433 break;
2434 case TCKind._tk_short:
2435 orbStream.read_short();
2436 break;
2437 case TCKind._tk_long:
2438 orbStream.read_long();
2439 break;
2440 case TCKind._tk_longlong:
2441 orbStream.read_longlong();
2442 break;
2443 case TCKind._tk_float:
2444 orbStream.read_float();
2445 break;
2446 case TCKind._tk_double:
2447 orbStream.read_double();
2448 break;
2449 case TCKind._tk_value:
2450 case TCKind._tk_objref:
2451 case TCKind._tk_value_box:
2452 Class type = null;
2453 String id = fields[i].id;
2454
2455 try {
2456 type = vhandler.getClassFromType(id);
2457 }
2458 catch(ClassNotFoundException cnfe){
2459 // Make sure type = null
2460 type = null;
2461 }
2462 String signature = null;
2463 if (type != null)
2464 signature = ValueUtility.getSignature(fields[i]);
2465
2466 // Read value
2467 try {
2468 if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
2469 signature.equals("Ljava/io/Serializable;") ||
2470 signature.equals("Ljava/io/Externalizable;")) ) {
2471 javax.rmi.CORBA.Util.readAny(orbStream);
2472 }
2473 else {
2474 // Decide what method call to make based on the type.
2475 //
2476 // NOTE : Since FullValueDescription does not allow us
2477 // to ask whether something is an interface we do not
2478 // have the ability to optimize this check.
2479
2480 int callType = ValueHandlerImpl.kValueType;
2481
2482 if (!vhandler.isSequence(id)) {
2483 FullValueDescription fieldFVD = sender.meta(fields[i].id);
2484 if (kRemoteTypeCode == fields[i].type) {
2485
2486 // RMI Object reference...
2487 callType = ValueHandlerImpl.kRemoteType;
2488 } else if (fieldFVD.is_abstract) {
2489 // RMI Abstract Object reference...
2490
2491 callType = ValueHandlerImpl.kAbstractType;
2492 }
2493 }
2494
2495 // Now that we have used the FVD of the field to determine the proper course
2496 // of action, it is ok to use the type (Class) from this point forward since
2497 // the rep. id for this read will also follow on the wire.
2498
2499 switch (callType) {
2500 case ValueHandlerImpl.kRemoteType:
2501 orbStream.read_Object();
2502 break;
2503 case ValueHandlerImpl.kAbstractType:
2504 orbStream.read_abstract_interface();
2505 break;
2506 case ValueHandlerImpl.kValueType:
2507 if (type != null) {
2508 orbStream.read_value(type);
2509 } else {
2510 orbStream.read_value();
2511 }
2512 break;
2513 default:
2514 // XXX I18N, logging needed.
2515 throw new StreamCorruptedException("Unknown callType: "
2516 + callType);
2517 }
2518 }
2519
2520 }
2521 catch(IndirectionException cdrie) {
2522 // Since we are throwing this away, don't bother handling recursion.
2523 continue;
2524 }
2525
2526 break;
2527 default:
2528 // XXX I18N, logging needed.
2529 throw new StreamCorruptedException("Unknown kind: "
2530 + fields[i].type.kind().value());
2531
2532 }
2533 } catch (IllegalArgumentException e) {
2534 /* This case should never happen. If the field types
2535 are not the same, InvalidClassException is raised when
2536 matching the local class to the serialized ObjectStreamClass. */
2537 // XXX I18N, logging needed.
2538 ClassCastException cce = new ClassCastException("Assigning instance of class " +
2539 fields[i].id + " to field " + currentClassDesc.getName() +
2540 '#' + fields[i].name);
2541 cce.initCause(e) ;
2542 throw cce ;
2543 }
2544 }
2545
2546 }
2547
2548 private static void setObjectField(Object o, Class c, String fieldName, Object v)
2549 {
2550 try {
2551 Field fld = c.getDeclaredField( fieldName ) ;
2552 long key = bridge.objectFieldOffset( fld ) ;
2553 bridge.putObject( o, key, v ) ;
2554 } catch (Exception e) {
2555 throw utilWrapper.errorSetObjectField( e, fieldName,
2556 ObjectUtility.compactObjectToString( o ),
2557 ObjectUtility.compactObjectToString( v )) ;
2558 }
2559 }
2560
2561 private static void setBooleanField(Object o, Class c, String fieldName, boolean v)
2562 {
2563 try {
2564 Field fld = c.getDeclaredField( fieldName ) ;
2565 long key = bridge.objectFieldOffset( fld ) ;
2566 bridge.putBoolean( o, key, v ) ;
2567 } catch (Exception e) {
2568 throw utilWrapper.errorSetBooleanField( e, fieldName,
2569 ObjectUtility.compactObjectToString( o ),
2570 new Boolean(v) ) ;
2571 }
2572 }
2573
2574 private static void setByteField(Object o, Class c, String fieldName, byte v)
2575 {
2576 try {
2577 Field fld = c.getDeclaredField( fieldName ) ;
2578 long key = bridge.objectFieldOffset( fld ) ;
2579 bridge.putByte( o, key, v ) ;
2580 } catch (Exception e) {
2581 throw utilWrapper.errorSetByteField( e, fieldName,
2582 ObjectUtility.compactObjectToString( o ),
2583 new Byte(v) ) ;
2584 }
2585 }
2586
2587 private static void setCharField(Object o, Class c, String fieldName, char v)
2588 {
2589 try {
2590 Field fld = c.getDeclaredField( fieldName ) ;
2591 long key = bridge.objectFieldOffset( fld ) ;
2592 bridge.putChar( o, key, v ) ;
2593 } catch (Exception e) {
2594 throw utilWrapper.errorSetCharField( e, fieldName,
2595 ObjectUtility.compactObjectToString( o ),
2596 new Character(v) ) ;
2597 }
2598 }
2599
2600 private static void setShortField(Object o, Class c, String fieldName, short v)
2601 {
2602 try {
2603 Field fld = c.getDeclaredField( fieldName ) ;
2604 long key = bridge.objectFieldOffset( fld ) ;
2605 bridge.putShort( o, key, v ) ;
2606 } catch (Exception e) {
2607 throw utilWrapper.errorSetShortField( e, fieldName,
2608 ObjectUtility.compactObjectToString( o ),
2609 new Short(v) ) ;
2610 }
2611 }
2612
2613 private static void setIntField(Object o, Class c, String fieldName, int v)
2614 {
2615 try {
2616 Field fld = c.getDeclaredField( fieldName ) ;
2617 long key = bridge.objectFieldOffset( fld ) ;
2618 bridge.putInt( o, key, v ) ;
2619 } catch (Exception e) {
2620 throw utilWrapper.errorSetIntField( e, fieldName,
2621 ObjectUtility.compactObjectToString( o ),
2622 new Integer(v) ) ;
2623 }
2624 }
2625
2626 private static void setLongField(Object o, Class c, String fieldName, long v)
2627 {
2628 try {
2629 Field fld = c.getDeclaredField( fieldName ) ;
2630 long key = bridge.objectFieldOffset( fld ) ;
2631 bridge.putLong( o, key, v ) ;
2632 } catch (Exception e) {
2633 throw utilWrapper.errorSetLongField( e, fieldName,
2634 ObjectUtility.compactObjectToString( o ),
2635 new Long(v) ) ;
2636 }
2637 }
2638
2639 private static void setFloatField(Object o, Class c, String fieldName, float v)
2640 {
2641 try {
2642 Field fld = c.getDeclaredField( fieldName ) ;
2643 long key = bridge.objectFieldOffset( fld ) ;
2644 bridge.putFloat( o, key, v ) ;
2645 } catch (Exception e) {
2646 throw utilWrapper.errorSetFloatField( e, fieldName,
2647 ObjectUtility.compactObjectToString( o ),
2648 new Float(v) ) ;
2649 }
2650 }
2651
2652 private static void setDoubleField(Object o, Class c, String fieldName, double v)
2653 {
2654 try {
2655 Field fld = c.getDeclaredField( fieldName ) ;
2656 long key = bridge.objectFieldOffset( fld ) ;
2657 bridge.putDouble( o, key, v ) ;
2658 } catch (Exception e) {
2659 throw utilWrapper.errorSetDoubleField( e, fieldName,
2660 ObjectUtility.compactObjectToString( o ),
2661 new Double(v) ) ;
2662 }
2663 }
2664
2665 /**
2666 * This class maintains a map of stream position to
2667 * an Object currently being deserialized. It is used
2668 * to handle the cases where the are indirections to
2669 * an object on the recursion stack. The CDR level
2670 * handles indirections to objects previously seen
2671 * (and completely deserialized) in the stream.
2672 */
2673 static class ActiveRecursionManager
2674 {
2675 private Map offsetToObjectMap;
2676
2677 public ActiveRecursionManager() {
2678 // A hash map is unsynchronized and allows
2679 // null values
2680 offsetToObjectMap = new HashMap();
2681 }
2682
2683 // Called right after allocating a new object.
2684 // Offset is the starting position in the stream
2685 // of the object.
2686 public void addObject(int offset, Object value) {
2687 offsetToObjectMap.put(new Integer(offset), value);
2688 }
2689
2690 // If the given starting position doesn't refer
2691 // to the beginning of an object currently being
2692 // deserialized, this throws an IOException.
2693 // Otherwise, it returns a reference to the
2694 // object.
2695 public Object getObject(int offset) throws IOException {
2696 Integer position = new Integer(offset);
2697
2698 if (!offsetToObjectMap.containsKey(position))
2699 // XXX I18N, logging needed.
2700 throw new IOException("Invalid indirection to offset "
2701 + offset);
2702
2703 return offsetToObjectMap.get(position);
2704 }
2705
2706 // Called when an object has been completely
2707 // deserialized, so it should no longer be in
2708 // this mapping. The CDR level can handle
2709 // further indirections.
2710 public void removeObject(int offset) {
2711 offsetToObjectMap.remove(new Integer(offset));
2712 }
2713
2714 // If the given offset doesn't map to an Object,
2715 // then it isn't an indirection to an object
2716 // currently being deserialized.
2717 public boolean containsObject(int offset) {
2718 return offsetToObjectMap.containsKey(new Integer(offset));
2719 }
2720 }
2721 }

mercurial