KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > corba > se > impl > io > IIOPInputStream


1 /*
2  * @(#)IIOPInputStream.java 1.74 04/06/21
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 /*
8  * Licensed Materials - Property of IBM
9  * RMI-IIOP v1.0
10  * Copyright IBM Corp. 1998 1999 All Rights Reserved
11  *
12  * US Government Users Restricted Rights - Use, duplication or
13  * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
14  */

15
16 package com.sun.corba.se.impl.io;
17
18 import java.io.InputStream JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.StreamCorruptedException JavaDoc;
21 import java.io.ObjectInputValidation JavaDoc;
22 import java.io.NotActiveException JavaDoc;
23 import java.io.InvalidObjectException JavaDoc;
24 import java.io.InvalidClassException JavaDoc;
25 import java.io.DataInputStream JavaDoc;
26 import java.io.OptionalDataException JavaDoc;
27 import java.io.WriteAbortedException JavaDoc;
28 import java.io.Externalizable JavaDoc;
29 import java.io.EOFException JavaDoc;
30 import java.lang.reflect.*;
31 import java.util.Vector JavaDoc;
32 import java.util.Stack JavaDoc;
33 import java.util.Hashtable JavaDoc;
34 import java.util.Enumeration JavaDoc;
35
36 import sun.corba.Bridge ;
37
38 import java.security.AccessController JavaDoc ;
39 import java.security.PrivilegedAction JavaDoc ;
40
41 import com.sun.corba.se.impl.io.ObjectStreamClass;
42 import com.sun.corba.se.impl.util.Utility;
43
44 import org.omg.CORBA.portable.ValueInputStream JavaDoc;
45
46 import org.omg.CORBA.ValueMember JavaDoc;
47 import org.omg.CORBA.SystemException JavaDoc;
48 import org.omg.CORBA.TCKind JavaDoc;
49 import org.omg.CORBA.ORB JavaDoc;
50 import org.omg.CORBA.CompletionStatus JavaDoc;
51 import org.omg.CORBA.portable.IndirectionException JavaDoc;
52 import org.omg.CORBA.MARSHAL JavaDoc;
53 import org.omg.CORBA.TypeCode JavaDoc;
54
55 import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
56 import com.sun.org.omg.SendingContext.CodeBase;
57
58 import javax.rmi.PortableRemoteObject JavaDoc;
59 import javax.rmi.CORBA.Util JavaDoc;
60 import javax.rmi.CORBA.ValueHandler JavaDoc;
61
62 import java.security.*;
63 import java.util.*;
64
65 import com.sun.corba.se.impl.orbutil.ObjectUtility ;
66 import com.sun.corba.se.impl.logging.OMGSystemException ;
67 import com.sun.corba.se.impl.logging.UtilSystemException ;
68
69 import com.sun.corba.se.spi.logging.CORBALogDomains ;
70
71 /**
72  * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization
73  * input semantics.
74  *
75  * @author Stephen Lewallen
76  * @since JDK1.1.6
77  */

78
79 public class IIOPInputStream
80     extends com.sun.corba.se.impl.io.InputStreamHook
81 {
82     private static Bridge bridge =
83     (Bridge)AccessController.doPrivileged(
84         new PrivilegedAction JavaDoc() {
85         public Object JavaDoc run() {
86             return Bridge.get() ;
87         }
88         }
89     ) ;
90
91     private static OMGSystemException omgWrapper = OMGSystemException.get(
92     CORBALogDomains.RPC_ENCODING ) ;
93     private static UtilSystemException utilWrapper = UtilSystemException.get(
94     CORBALogDomains.RPC_ENCODING ) ;
95
96     // Necessary to pass the appropriate fields into the
97
// defaultReadObjectDelegate method (which takes no
98
// parameters since it's called from
99
// java.io.ObjectInpuStream defaultReadObject()
100
// which we can't change).
101
//
102
// This is only used in the case where the fields had
103
// to be obtained remotely because of a serializable
104
// version difference. Set in inputObjectUsingFVD.
105
// Part of serialization evolution fixes for Ladybird,
106
// bug 4365188.
107
private ValueMember JavaDoc defaultReadObjectFVDMembers[] = null;
108
109     private org.omg.CORBA_2_3.portable.InputStream JavaDoc orbStream;
110
111     private CodeBase cbSender;
112
113     private ValueHandlerImpl vhandler; //d4365188
114

115     private Object JavaDoc currentObject = null;
116
117     private ObjectStreamClass currentClassDesc = null;
118
119     private Class JavaDoc currentClass = null;
120
121     private int recursionDepth = 0;
122
123     private int simpleReadDepth = 0;
124
125     // The ActiveRecursionManager replaces the old RecursionManager which
126
// used to record how many recursions were made, and resolve them after
127
// an object was completely deserialized.
128
//
129
// That created problems (as in bug 4414154) because when custom
130
// unmarshaling in readObject, there can be recursive references
131
// to one of the objects currently being unmarshaled, and the
132
// passive recursion system failed.
133
ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager();
134
135     private IOException JavaDoc abortIOException = null;
136
137     /* Remember the first exception that stopped this stream. */
138     private ClassNotFoundException JavaDoc abortClassNotFoundException = null;
139
140     /* Vector of validation callback objects
141      * The vector is created as needed. The vector is maintained in
142      * order of highest (first) priority to lowest
143      */

144     private Vector JavaDoc callbacks;
145
146     // Serialization machinery fields
147
/* Arrays used to keep track of classes and ObjectStreamClasses
148      * as they are being merged; used in inputObject.
149      * spClass is the stack pointer for both. */

150     ObjectStreamClass[] classdesc;
151     Class JavaDoc[] classes;
152     int spClass;
153
154     private static final String JavaDoc kEmptyStr = "";
155
156     // TCKind TypeCodes used in FVD inputClassFields
157
//public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref);
158
//public static final TypeCode kValueTypeCode = new TypeCodeImpl(TCKind._tk_value);
159
// removed TypeCodeImpl dependency
160
public static final TypeCode JavaDoc kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref);
161     public static final TypeCode JavaDoc kValueTypeCode = ORB.init().get_primitive_tc(TCKind.tk_value);
162
163     // TESTING CODE - useFVDOnly should be made final before FCS in order to
164
// optimize out the check.
165
private static final boolean useFVDOnly = false;
166
167     private byte streamFormatVersion;
168
169     // Since java.io.OptionalDataException's constructors are
170
// package private, but we need to throw it in some special
171
// cases, we try to do it by reflection.
172
private static final Constructor OPT_DATA_EXCEPTION_CTOR;
173    
174     private Object JavaDoc[] readObjectArgList = { this } ;
175
176     static {
177         OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor();
178     }
179
180     // Grab the OptionalDataException boolean ctor and make
181
// it accessible. Note that any exceptions
182
// will be wrapped in ExceptionInInitializerErrors.
183
private static Constructor getOptDataExceptionCtor() {
184
185         try {
186
187             Constructor result =
188                 
189                 (Constructor) AccessController.doPrivileged(
190                                     new PrivilegedExceptionAction() {
191                     public java.lang.Object JavaDoc run()
192                         throws NoSuchMethodException JavaDoc,
193                         SecurityException JavaDoc {
194                         
195                         Constructor boolCtor
196                             = OptionalDataException.class.getDeclaredConstructor(
197                                                                new Class JavaDoc[] {
198                                 Boolean.TYPE });
199                         
200                         boolCtor.setAccessible(true);
201                         
202                         return boolCtor;
203                     }});
204             
205             if (result == null)
206         // XXX I18N, logging needed.
207
throw new Error JavaDoc("Unable to find OptionalDataException constructor");
208         
209             return result;
210
211         } catch (Exception JavaDoc ex) {
212         // XXX I18N, logging needed.
213
throw new ExceptionInInitializerError JavaDoc(ex);
214         }
215     }
216
217     // Create a new OptionalDataException with the EOF marker
218
// set to true. See handleOptionalDataMarshalException.
219
private OptionalDataException createOptionalDataException() {
220         try {
221             OptionalDataException result
222                 = (OptionalDataException)
223                    OPT_DATA_EXCEPTION_CTOR.newInstance(new Object JavaDoc[] {
224                        Boolean.TRUE });
225
226             if (result == null)
227         // XXX I18N, logging needed.
228
throw new Error JavaDoc("Created null OptionalDataException");
229
230             return result;
231
232         } catch (Exception JavaDoc ex) {
233         // XXX I18N, logging needed.
234
throw new Error JavaDoc("Couldn't create OptionalDataException", ex);
235         }
236     }
237
238     // Return the stream format version currently being used
239
// to deserialize an object
240
protected byte getStreamFormatVersion() {
241         return streamFormatVersion;
242     }
243
244     // At the beginning of data sent by a writeObject or
245
// writeExternal method there is a byte telling the
246
// reader the stream format version.
247
private void readFormatVersion() throws IOException JavaDoc {
248
249         streamFormatVersion = orbStream.read_octet();
250
251         if (streamFormatVersion < 1 ||
252             streamFormatVersion > vhandler.getMaximumStreamFormatVersion()) {
253         SystemException JavaDoc sysex = omgWrapper.unsupportedFormatVersion(
254             CompletionStatus.COMPLETED_MAYBE);
255         // XXX I18N? Logging for IOException?
256
IOException JavaDoc result = new IOException JavaDoc("Unsupported format version: "
257                                                  + streamFormatVersion);
258         result.initCause( sysex ) ;
259         throw result ;
260         }
261
262         if (streamFormatVersion == 2) {
263             if (!(orbStream instanceof ValueInputStream JavaDoc)) {
264         SystemException JavaDoc sysex = omgWrapper.notAValueinputstream(
265             CompletionStatus.COMPLETED_MAYBE);
266         // XXX I18N? Logging for IOException?
267
IOException JavaDoc result = new IOException JavaDoc("Not a ValueInputStream");
268         result.initCause( sysex ) ;
269         throw result;
270             }
271         }
272     }
273
274     public static void setTestFVDFlag(boolean val){
275     // useFVDOnly = val;
276
}
277
278     /**
279      * Dummy constructor; passes upper stream a dummy stream;
280      **/

281     public IIOPInputStream()
282         throws java.io.IOException JavaDoc {
283         super();
284     resetStream();
285     }
286     
287     public final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream JavaDoc os) {
288         orbStream = os;
289     }
290
291     public final org.omg.CORBA_2_3.portable.InputStream JavaDoc getOrbStream() {
292         return orbStream;
293     }
294
295     //added setSender and getSender
296
public final void setSender(CodeBase cb) {
297         cbSender = cb;
298     }
299
300     public final CodeBase getSender() {
301         return cbSender;
302     }
303
304     // 4365188 this is added to enable backward compatability w/ wrong
305
// rep-ids
306
public final void setValueHandler(ValueHandler JavaDoc vh) {
307         vhandler = (com.sun.corba.se.impl.io.ValueHandlerImpl) vh;
308     }
309
310     public final ValueHandler JavaDoc getValueHandler() {
311     return (javax.rmi.CORBA.ValueHandler JavaDoc) vhandler;
312     }
313     
314     public final void increaseRecursionDepth(){
315     recursionDepth++;
316     }
317
318     public final int decreaseRecursionDepth(){
319     return --recursionDepth;
320     }
321
322     /**
323      * Override the actions of the final method "readObject()"
324      * in ObjectInputStream.
325      * @since JDK1.1.6
326      *
327      * Read an object from the ObjectInputStream.
328      * The class of the object, the signature of the class, and the values
329      * of the non-transient and non-static fields of the class and all
330      * of its supertypes are read. Default deserializing for a class can be
331      * overriden using the writeObject and readObject methods.
332      * Objects referenced by this object are read transitively so
333      * that a complete equivalent graph of objects is reconstructed by readObject. <p>
334      *
335      * The root object is completly restored when all of its fields
336      * and the objects it references are completely restored. At this
337      * point the object validation callbacks are executed in order
338      * based on their registered priorities. The callbacks are
339      * registered by objects (in the readObject special methods)
340      * as they are individually restored.
341      *
342      * Exceptions are thrown for problems with the InputStream and for classes
343      * that should not be deserialized. All exceptions are fatal to the
344      * InputStream and leave it in an indeterminate state; it is up to the caller
345      * to ignore or recover the stream state.
346      * @exception java.lang.ClassNotFoundException Class of a serialized object
347      * cannot be found.
348      * @exception InvalidClassException Something is wrong with a class used by
349      * serialization.
350      * @exception StreamCorruptedException Control information in the
351      * stream is inconsistent.
352      * @exception OptionalDataException Primitive data was found in the
353      * stream instead of objects.
354      * @exception IOException Any of the usual Input/Output related exceptions.
355      * @since JDK1.1
356      */

357     public final Object JavaDoc readObjectDelegate() throws IOException JavaDoc
358     {
359     try {
360
361             readObjectState.readData(this);
362
363             return orbStream.read_abstract_interface();
364         } catch (MARSHAL JavaDoc marshalException) {
365             handleOptionalDataMarshalException(marshalException, true);
366             throw marshalException;
367     } catch(IndirectionException JavaDoc cdrie)
368         {
369                 // The CDR stream had never seen the given offset before,
370
// so check the recursion manager (it will throw an
371
// IOException if it doesn't have a reference, either).
372
return activeRecursionMgr.getObject(cdrie.offset);
373         }
374     }
375
376     final Object JavaDoc simpleReadObject(Class JavaDoc clz,
377                                   String JavaDoc repositoryID,
378                                   com.sun.org.omg.SendingContext.CodeBase sender,
379                                   int offset)
380                      /* throws OptionalDataException, ClassNotFoundException, IOException */
381     {
382
383         /* Save the current state and get ready to read an object. */
384         Object JavaDoc prevObject = currentObject;
385         ObjectStreamClass prevClassDesc = currentClassDesc;
386         Class JavaDoc prevClass = currentClass;
387         byte oldStreamFormatVersion = streamFormatVersion;
388
389         simpleReadDepth++; // Entering
390
Object JavaDoc obj = null;
391
392         /*
393          * Check for reset, handle it before reading an object.
394          */

395         try {
396         // d4365188: backward compatability
397
if (vhandler.useFullValueDescription(clz, repositoryID)) {
398         obj = inputObjectUsingFVD(clz, repositoryID, sender, offset);
399         } else {
400                 obj = inputObject(clz, repositoryID, sender, offset);
401         }
402
403         obj = currentClassDesc.readResolve(obj);
404         }
405         catch(ClassNotFoundException JavaDoc cnfe)
406         {
407         bridge.throwException( cnfe ) ;
408         return null;
409         }
410         catch(IOException JavaDoc ioe)
411         {
412         // System.out.println("CLZ = " + clz + "; " + ioe.toString());
413
bridge.throwException(ioe) ;
414         return null;
415         }
416         finally {
417             simpleReadDepth --;
418             currentObject = prevObject;
419             currentClassDesc = prevClassDesc;
420             currentClass = prevClass;
421             streamFormatVersion = oldStreamFormatVersion;
422         }
423
424
425         /* Check for thrown exceptions and re-throw them, clearing them if
426          * this is the last recursive call .
427          */

428         IOException JavaDoc exIOE = abortIOException;
429         if (simpleReadDepth == 0)
430             abortIOException = null;
431         if (exIOE != null){
432         bridge.throwException( exIOE ) ;
433             return null;
434         }
435
436
437         ClassNotFoundException JavaDoc exCNF = abortClassNotFoundException;
438         if (simpleReadDepth == 0)
439             abortClassNotFoundException = null;
440         if (exCNF != null) {
441         bridge.throwException( exCNF ) ;
442             return null;
443         }
444
445         return obj;
446     }
447
448     public final void simpleSkipObject(String JavaDoc repositoryID,
449                        com.sun.org.omg.SendingContext.CodeBase sender)
450                        /* throws OptionalDataException, ClassNotFoundException, IOException */
451     {
452                 
453         /* Save the current state and get ready to read an object. */
454         Object JavaDoc prevObject = currentObject;
455         ObjectStreamClass prevClassDesc = currentClassDesc;
456         Class JavaDoc prevClass = currentClass;
457         byte oldStreamFormatVersion = streamFormatVersion;
458
459         simpleReadDepth++; // Entering
460
Object JavaDoc obj = null;
461
462         /*
463          * Check for reset, handle it before reading an object.
464          */

465         try {
466         skipObjectUsingFVD(repositoryID, sender);
467         }
468         catch(ClassNotFoundException JavaDoc cnfe)
469         {
470         bridge.throwException( cnfe ) ;
471         return;
472         }
473         catch(IOException JavaDoc ioe)
474         {
475         bridge.throwException( ioe ) ;
476         return;
477         }
478         finally {
479             simpleReadDepth --;
480             streamFormatVersion = oldStreamFormatVersion;
481             currentObject = prevObject;
482             currentClassDesc = prevClassDesc;
483             currentClass = prevClass;
484         }
485
486
487         /* Check for thrown exceptions and re-throw them, clearing them if
488          * this is the last recursive call .
489          */

490         IOException JavaDoc exIOE = abortIOException;
491         if (simpleReadDepth == 0)
492             abortIOException = null;
493         if (exIOE != null){
494         bridge.throwException( exIOE ) ;
495             return;
496         }
497
498
499         ClassNotFoundException JavaDoc exCNF = abortClassNotFoundException;
500         if (simpleReadDepth == 0)
501             abortClassNotFoundException = null;
502         if (exCNF != null) {
503         bridge.throwException( exCNF ) ;
504             return;
505         }
506
507     return;
508     }
509     /////////////////
510

511     /**
512      * This method is called by trusted subclasses of ObjectOutputStream
513      * that constructed ObjectOutputStream using the
514      * protected no-arg constructor. The subclass is expected to provide
515      * an override method with the modifier "final".
516      *
517      * @return the Object read from the stream.
518      *
519      * @see #ObjectInputStream()
520      * @see #readObject
521      * @since JDK 1.2
522      */

523     protected final Object JavaDoc readObjectOverride()
524     throws OptionalDataException, ClassNotFoundException JavaDoc, IOException JavaDoc
525     {
526         return readObjectDelegate();
527     }
528
529     /**
530      * Override the actions of the final method "defaultReadObject()"
531      * in ObjectInputStream.
532      * @since JDK1.1.6
533      *
534      * Read the non-static and non-transient fields of the current class
535      * from this stream. This may only be called from the readObject method
536      * of the class being deserialized. It will throw the NotActiveException
537      * if it is called otherwise.
538      *
539      * @exception java.lang.ClassNotFoundException if the class of a serialized
540      * object could not be found.
541      * @exception IOException if an I/O error occurs.
542      * @exception NotActiveException if the stream is not currently reading
543      * objects.
544      * @since JDK1.1
545      */

546     public final void defaultReadObjectDelegate()
547     /* throws IOException, ClassNotFoundException, NotActiveException */
548     {
549         try {
550         if (currentObject == null || currentClassDesc == null)
551         // XXX I18N, logging needed.
552
throw new NotActiveException JavaDoc("defaultReadObjectDelegate");
553
554             // The array will be null unless fields were retrieved
555
// remotely because of a serializable version difference.
556
// Bug fix for 4365188. See the definition of
557
// defaultReadObjectFVDMembers for more information.
558
if (defaultReadObjectFVDMembers != null &&
559                 defaultReadObjectFVDMembers.length > 0) {
560
561                 // WARNING: Be very careful! What if some of
562
// these fields actually have to do this, too?
563
// This works because the defaultReadObjectFVDMembers
564
// reference is passed to inputClassFields, but
565
// there is no guarantee that
566
// defaultReadObjectFVDMembers will point to the
567
// same array after calling inputClassFields.
568

569                 // Use the remote fields to unmarshal.
570
inputClassFields(currentObject,
571                                  currentClass,
572                                  currentClassDesc,
573                                  defaultReadObjectFVDMembers,
574                                  cbSender);
575
576             } else {
577
578                 // Use the local fields to unmarshal.
579
ObjectStreamField[] fields =
580                     currentClassDesc.getFieldsNoCopy();
581                 if (fields.length > 0) {
582                     inputClassFields(currentObject, currentClass, fields, cbSender);
583                 }
584             }
585         }
586         catch(NotActiveException JavaDoc nae)
587         {
588         bridge.throwException( nae ) ;
589         }
590         catch(IOException JavaDoc ioe)
591         {
592         bridge.throwException( ioe ) ;
593         }
594         catch(ClassNotFoundException JavaDoc cnfe)
595         {
596         bridge.throwException( cnfe ) ;
597         }
598
599     }
600
601     /**
602      * Override the actions of the final method "enableResolveObject()"
603      * in ObjectInputStream.
604      * @since JDK1.1.6
605      *
606      * Enable the stream to allow objects read from the stream to be replaced.
607      * If the stream is a trusted class it is allowed to enable replacment.
608      * Trusted classes are those classes with a classLoader equals null. <p>
609      *
610      * When enabled the resolveObject method is called for every object
611      * being deserialized.
612      *
613      * @exception SecurityException The classloader of this stream object is non-null.
614      * @since JDK1.1
615      */

616     public final boolean enableResolveObjectDelegate(boolean enable)
617     /* throws SecurityException */
618     {
619     return false;
620     }
621
622     // The following three methods allow the implementing orbStream
623
// to provide mark/reset behavior as defined in java.io.InputStream.
624

625     public final void mark(int readAheadLimit) {
626         orbStream.mark(readAheadLimit);
627     }
628     
629     public final boolean markSupported() {
630         return orbStream.markSupported();
631     }
632     
633     public final void reset() throws IOException JavaDoc {
634         try {
635             orbStream.reset();
636         } catch (Error JavaDoc e) {
637             IOException JavaDoc err = new IOException JavaDoc(e.getMessage());
638         err.initCause(e) ;
639         throw err ;
640         }
641     }
642
643     public final int available() throws IOException JavaDoc{
644         return 0; // unreliable
645
}
646
647     public final void close() throws IOException JavaDoc{
648         // no op
649
}
650
651     public final int read() throws IOException JavaDoc{
652         try{
653             readObjectState.readData(this);
654
655             return (orbStream.read_octet() << 0) & 0x000000FF;
656         } catch (MARSHAL JavaDoc marshalException) {
657             if (marshalException.minor
658                 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
659                 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
660                 return -1;
661             }
662
663             throw marshalException;
664         } catch(Error JavaDoc e) {
665         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
666         exc.initCause(e) ;
667         throw exc ;
668     }
669     }
670
671     public final int read(byte data[], int offset, int length) throws IOException JavaDoc{
672         try{
673             readObjectState.readData(this);
674
675             orbStream.read_octet_array(data, offset, length);
676             return length;
677         } catch (MARSHAL JavaDoc marshalException) {
678             if (marshalException.minor
679                 == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
680                 setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
681                 return -1;
682             }
683
684             throw marshalException;
685         } catch(Error JavaDoc e) {
686         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
687         exc.initCause(e) ;
688         throw exc ;
689     }
690
691     }
692
693     public final boolean readBoolean() throws IOException JavaDoc{
694         try{
695             readObjectState.readData(this);
696
697             return orbStream.read_boolean();
698         } catch (MARSHAL JavaDoc marshalException) {
699             handleOptionalDataMarshalException(marshalException, false);
700             throw marshalException;
701
702         } catch(Error JavaDoc e) {
703         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
704         exc.initCause(e);
705         throw exc ;
706     }
707     }
708
709     public final byte readByte() throws IOException JavaDoc{
710         try{
711             readObjectState.readData(this);
712
713             return orbStream.read_octet();
714         } catch (MARSHAL JavaDoc marshalException) {
715             handleOptionalDataMarshalException(marshalException, false);
716             throw marshalException;
717
718         } catch(Error JavaDoc e) {
719         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
720         exc.initCause(e);
721         throw exc ;
722     }
723     }
724
725     public final char readChar() throws IOException JavaDoc{
726         try{
727             readObjectState.readData(this);
728
729             return orbStream.read_wchar();
730         } catch (MARSHAL JavaDoc marshalException) {
731             handleOptionalDataMarshalException(marshalException, false);
732             throw marshalException;
733
734         } catch(Error JavaDoc e) {
735         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
736         exc.initCause(e);
737         throw exc ;
738     }
739     }
740
741     public final double readDouble() throws IOException JavaDoc{
742         try{
743             readObjectState.readData(this);
744
745             return orbStream.read_double();
746         } catch (MARSHAL JavaDoc marshalException) {
747             handleOptionalDataMarshalException(marshalException, false);
748             throw marshalException;
749         } catch(Error JavaDoc e) {
750         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
751         exc.initCause(e);
752         throw exc ;
753     }
754     }
755
756     public final float readFloat() throws IOException JavaDoc{
757         try{
758             readObjectState.readData(this);
759
760             return orbStream.read_float();
761         } catch (MARSHAL JavaDoc marshalException) {
762             handleOptionalDataMarshalException(marshalException, false);
763             throw marshalException;
764         } catch(Error JavaDoc e) {
765         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
766         exc.initCause(e);
767         throw exc ;
768     }
769     }
770
771     public final void readFully(byte data[]) throws IOException JavaDoc{
772 // d11623 : implement readFully, required for serializing some core classes
773

774         readFully(data, 0, data.length);
775     }
776
777     public final void readFully(byte data[], int offset, int size) throws IOException JavaDoc{
778 // d11623 : implement readFully, required for serializing some core classes
779
try{
780             readObjectState.readData(this);
781
782             orbStream.read_octet_array(data, offset, size);
783         } catch (MARSHAL JavaDoc marshalException) {
784             handleOptionalDataMarshalException(marshalException, false);
785             
786             throw marshalException;
787         } catch(Error JavaDoc e) {
788         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
789         exc.initCause(e);
790         throw exc ;
791     }
792     }
793
794     public final int readInt() throws IOException JavaDoc{
795         try{
796             readObjectState.readData(this);
797
798             return orbStream.read_long();
799         } catch (MARSHAL JavaDoc marshalException) {
800             handleOptionalDataMarshalException(marshalException, false);
801             throw marshalException;
802         } catch(Error JavaDoc e) {
803         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
804         exc.initCause(e);
805         throw exc ;
806     }
807     }
808
809     public final String JavaDoc readLine() throws IOException JavaDoc{
810     // XXX I18N, logging needed.
811
throw new IOException JavaDoc("Method readLine not supported");
812     }
813
814     public final long readLong() throws IOException JavaDoc{
815         try{
816             readObjectState.readData(this);
817
818             return orbStream.read_longlong();
819         } catch (MARSHAL JavaDoc marshalException) {
820             handleOptionalDataMarshalException(marshalException, false);
821             throw marshalException;
822         } catch(Error JavaDoc e) {
823         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
824         exc.initCause(e);
825         throw exc ;
826     }
827     }
828
829     public final short readShort() throws IOException JavaDoc{
830         try{
831             readObjectState.readData(this);
832
833             return orbStream.read_short();
834         } catch (MARSHAL JavaDoc marshalException) {
835             handleOptionalDataMarshalException(marshalException, false);
836             throw marshalException;
837         } catch(Error JavaDoc e) {
838         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
839         exc.initCause(e);
840         throw exc ;
841     }
842     }
843
844     protected final void readStreamHeader() throws IOException JavaDoc, StreamCorruptedException JavaDoc{
845         // no op
846
}
847
848     public final int readUnsignedByte() throws IOException JavaDoc{
849         try{
850             readObjectState.readData(this);
851
852             return (orbStream.read_octet() << 0) & 0x000000FF;
853         } catch (MARSHAL JavaDoc marshalException) {
854             handleOptionalDataMarshalException(marshalException, false);
855             throw marshalException;
856     } catch(Error JavaDoc e) {
857         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
858         exc.initCause(e);
859         throw exc ;
860     }
861     }
862
863     public final int readUnsignedShort() throws IOException JavaDoc{
864         try{
865             readObjectState.readData(this);
866
867             return (orbStream.read_ushort() << 0) & 0x0000FFFF;
868         } catch (MARSHAL JavaDoc marshalException) {
869             handleOptionalDataMarshalException(marshalException, false);
870             throw marshalException;
871         } catch(Error JavaDoc e) {
872         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
873         exc.initCause(e);
874         throw exc ;
875     }
876     }
877
878     /**
879      * Helper method for correcting the Kestrel bug 4367783 (dealing
880      * with larger than 8-bit chars). The old behavior is preserved
881      * in orbutil.IIOPInputStream_1_3 in order to interoperate with
882      * our legacy ORBs.
883      */

884     protected String JavaDoc internalReadUTF(org.omg.CORBA.portable.InputStream JavaDoc stream)
885     {
886         return stream.read_wstring();
887     }
888
889     public final String JavaDoc readUTF() throws IOException JavaDoc{
890         try{
891             readObjectState.readData(this);
892
893             return internalReadUTF(orbStream);
894         } catch (MARSHAL JavaDoc marshalException) {
895             handleOptionalDataMarshalException(marshalException, false);
896             throw marshalException;
897         } catch(Error JavaDoc e) {
898         IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
899         exc.initCause(e);
900         throw exc ;
901     }
902     }
903
904     // If the ORB stream detects an incompatibility between what's
905
// on the wire and what our Serializable's readObject wants,
906
// it throws a MARSHAL exception with a specific minor code.
907
// This is rethrown to the readObject as an OptionalDataException.
908
// So far in RMI-IIOP, this process isn't specific enough to
909
// tell the readObject how much data is available, so we always
910
// set the OptionalDataException's EOF marker to true.
911
private void handleOptionalDataMarshalException(MARSHAL JavaDoc marshalException,
912                                                     boolean objectRead)
913         throws IOException JavaDoc {
914
915         // Java Object Serialization spec 3.4: "If the readObject method
916
// of the class attempts to read more data than is present in the
917
// optional part of the stream for this class, the stream will
918
// return -1 for bytewise reads, throw an EOFException for
919
// primitive data reads, or throw an OptionalDataException
920
// with the eof field set to true for object reads."
921
if (marshalException.minor
922             == OMGSystemException.RMIIIOP_OPTIONAL_DATA_INCOMPATIBLE1) {
923
924             IOException JavaDoc result;
925
926             if (!objectRead)
927                 result = new EOFException JavaDoc("No more optional data");
928             else
929                 result = createOptionalDataException();
930
931             result.initCause(marshalException);
932
933             setState(IN_READ_OBJECT_NO_MORE_OPT_DATA);
934
935             throw result;
936         }
937     }
938
939     public final synchronized void registerValidation(ObjectInputValidation JavaDoc obj,
940                               int prio)
941     throws NotActiveException JavaDoc, InvalidObjectException JavaDoc{
942     // XXX I18N, logging needed.
943
throw new Error JavaDoc("Method registerValidation not supported");
944     }
945
946     protected final Class JavaDoc resolveClass(ObjectStreamClass v)
947     throws IOException JavaDoc, ClassNotFoundException JavaDoc{
948     // XXX I18N, logging needed.
949
throw new IOException JavaDoc("Method resolveClass not supported");
950     }
951
952     protected final Object JavaDoc resolveObject(Object JavaDoc obj) throws IOException JavaDoc{
953     // XXX I18N, logging needed.
954
throw new IOException JavaDoc("Method resolveObject not supported");
955     }
956
957     public final int skipBytes(int len) throws IOException JavaDoc{
958         try{
959             readObjectState.readData(this);
960
961             byte buf[] = new byte[len];
962             orbStream.read_octet_array(buf, 0, len);
963             return len;
964         } catch (MARSHAL JavaDoc marshalException) {
965             handleOptionalDataMarshalException(marshalException, false);
966             
967             throw marshalException;
968         } catch(Error JavaDoc e) {
969             IOException JavaDoc exc = new IOException JavaDoc(e.getMessage());
970         exc.initCause(e) ;
971         throw exc ;
972         }
973     }
974
975     private Object JavaDoc inputObject(Class JavaDoc clz,
976                    String JavaDoc repositoryID,
977                    com.sun.org.omg.SendingContext.CodeBase sender,
978                                int offset)
979     throws IOException JavaDoc, ClassNotFoundException JavaDoc
980     {
981
982         /*
983          * Get the descriptor and then class of the incoming object.
984          */

985
986         currentClassDesc = ObjectStreamClass.lookup(clz);
987         currentClass = currentClassDesc.forClass();
988         //currentClassDesc.setClass(currentClass);
989
if (currentClass == null)
990         // XXX I18N, logging needed.
991
throw new ClassNotFoundException JavaDoc(currentClassDesc.getName());
992
993         try {
994             /* If Externalizable,
995              * Create an instance and tell it to read its data.
996              * else,
997              * Handle it as a serializable class.
998              */

999             if (currentClassDesc.isExternalizable()) {
1000                try {
1001                    currentObject = (currentClass == null) ?
1002                        null : currentClassDesc.newInstance();
1003                    if (currentObject != null) {
1004
1005                        // Store this object and its beginning position
1006
// since there might be indirections to it while
1007
// it's been unmarshalled.
1008
activeRecursionMgr.addObject(offset, currentObject);
1009
1010                        // Read format version
1011
readFormatVersion();
1012
1013                        Externalizable JavaDoc ext = (Externalizable JavaDoc)currentObject;
1014                        ext.readExternal(this);
1015        }
1016        } catch (InvocationTargetException e) {
1017        InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1018            currentClass.getName(),
1019            "InvocationTargetException accessing no-arg constructor");
1020        exc.initCause( e ) ;
1021        throw exc ;
1022        } catch (UnsupportedOperationException JavaDoc e) {
1023        InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1024            currentClass.getName(),
1025            "UnsupportedOperationException accessing no-arg constructor");
1026        exc.initCause( e ) ;
1027        throw exc ;
1028            } catch (InstantiationException JavaDoc e) {
1029        InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1030            currentClass.getName(),
1031            "InstantiationException accessing no-arg constructor");
1032        exc.initCause( e ) ;
1033        throw exc ;
1034            }
1035        } // end : if (currentClassDesc.isExternalizable())
1036
else {
1037            /* Count number of classes and descriptors we might have
1038             * to work on.
1039             */

1040
1041            ObjectStreamClass currdesc = currentClassDesc;
1042            Class JavaDoc currclass = currentClass;
1043
1044            int spBase = spClass; // current top of stack
1045

1046            /* The object's classes should be processed from supertype to subtype
1047             * Push all the clases of the current object onto a stack.
1048             * Note that only the serializable classes are represented
1049             * in the descriptor list.
1050             *
1051             * Handle versioning where one or more supertypes of
1052             * have been inserted or removed. The stack will
1053             * contain pairs of descriptors and the corresponding
1054             * class. If the object has a class that did not occur in
1055             * the original the descriptor will be null. If the
1056             * original object had a descriptor for a class not
1057             * present in the local hierarchy of the object the class will be
1058             * null.
1059             *
1060             */

1061
1062            /*
1063             * This is your basic diff pattern, made simpler
1064             * because reordering is not allowed.
1065             */

1066            // sun.4296963 ibm.11861
1067
// d11861 we should stop when we find the highest serializable class
1068
// We need this so that when we allocate the new object below, we
1069
// can call the constructor of the non-serializable superclass.
1070
// Note that in the JRMP variant of this code the
1071
// ObjectStreamClass.lookup() method handles this, but we've put
1072
// this fix here rather than change lookup because the new behaviour
1073
// is needed in other cases.
1074

1075            for (currdesc = currentClassDesc, currclass = currentClass;
1076             currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
1077             currdesc = currdesc.getSuperclass()) {
1078
1079            /*
1080             * Search the classes to see if the class of this
1081             * descriptor appears further up the hierarchy. Until
1082             * it's found assume its an inserted class. If it's
1083             * not found, its the descriptor's class that has been
1084             * removed.
1085             */

1086            Class JavaDoc cc = currdesc.forClass();
1087            Class JavaDoc cl;
1088            for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
1089                if (cc == cl) {
1090                // found a superclass that matches this descriptor
1091
break;
1092                } else {
1093                /* Ignore a class that doesn't match. No
1094                 * action is needed since it is already
1095                 * initialized.
1096                 */

1097                }
1098        } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
1099
/* Test if there is room for this new entry.
1100             * If not, double the size of the arrays and copy the contents.
1101             */

1102            spClass++;
1103            if (spClass >= classes.length) {
1104                int newlen = classes.length * 2;
1105                Class JavaDoc[] newclasses = new Class JavaDoc[newlen];
1106                ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
1107
1108                System.arraycopy(classes, 0,
1109                     newclasses, 0,
1110                     classes.length);
1111                System.arraycopy(classdesc, 0,
1112                         newclassdesc, 0,
1113                         classes.length);
1114
1115                classes = newclasses;
1116                classdesc = newclassdesc;
1117            }
1118
1119            if (cl == null) {
1120                /* Class not found corresponding to this descriptor.
1121                 * Pop off all the extra classes pushed.
1122                 * Push the descriptor and a null class.
1123                 */

1124                classdesc[spClass] = currdesc;
1125                classes[spClass] = null;
1126            } else {
1127            /* Current class descriptor matches current class.
1128                 * Some classes may have been inserted.
1129                 * Record the match and advance the class, continue
1130                 * with the next descriptor.
1131                 */

1132                classdesc[spClass] = currdesc;
1133                classes[spClass] = cl;
1134                currclass = cl.getSuperclass();
1135            }
1136            } // end : for (currdesc = currentClassDesc, currclass = currentClass;
1137

1138            /* Allocate a new object. The object is only constructed
1139             * above the highest serializable class and is set to
1140             * default values for all more specialized classes.
1141             */

1142            try {
1143            currentObject = (currentClass == null) ?
1144            null : currentClassDesc.newInstance() ;
1145
1146                // Store this object and its beginning position
1147
// since there might be indirections to it while
1148
// it's been unmarshalled.
1149
activeRecursionMgr.addObject(offset, currentObject);
1150        } catch (InvocationTargetException e) {
1151        InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1152            currentClass.getName(),
1153            "InvocationTargetException accessing no-arg constructor");
1154        exc.initCause( e ) ;
1155        throw exc ;
1156        } catch (UnsupportedOperationException JavaDoc e) {
1157        InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1158            currentClass.getName(),
1159            "UnsupportedOperationException accessing no-arg constructor");
1160        exc.initCause( e ) ;
1161        throw exc ;
1162            } catch (InstantiationException JavaDoc e) {
1163        InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1164            currentClass.getName(),
1165            "InstantiationException accessing no-arg constructor");
1166        exc.initCause( e ) ;
1167        throw exc ;
1168            }
1169
1170            /*
1171             * For all the pushed descriptors and classes.
1172             * if the class has its own writeObject and readObject methods
1173             * call the readObject method
1174             * else
1175             * invoke the defaultReadObject method
1176             */

1177            try {
1178            for (spClass = spClass; spClass > spBase; spClass--) {
1179                /*
1180                 * Set current descriptor and corresponding class
1181                 */

1182                currentClassDesc = classdesc[spClass];
1183                currentClass = classes[spClass];
1184                if (classes[spClass] != null) {
1185                /* Read the data from the stream described by the
1186                 * descriptor and store into the matching class.
1187                 */

1188
1189                        ReadObjectState oldState = readObjectState;
1190                        setState(DEFAULT_STATE);
1191
1192                        try {
1193
1194                            // Changed since invokeObjectReader no longer does this.
1195
if (currentClassDesc.hasWriteObject()) {
1196
1197                                // Read format version
1198
readFormatVersion();
1199
1200                                // Read defaultWriteObject indicator
1201
boolean calledDefaultWriteObject = readBoolean();
1202
1203                                readObjectState.beginUnmarshalCustomValue(this,
1204                                                                          calledDefaultWriteObject,
1205                                                                          (currentClassDesc.readObjectMethod
1206                                                                           != null));
1207                            } else {
1208                                if (currentClassDesc.hasReadObject())
1209                                    setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
1210                            }
1211
1212                            if (!invokeObjectReader(currentClassDesc, currentObject, currentClass) ||
1213                                readObjectState == IN_READ_OBJECT_DEFAULTS_SENT) {
1214
1215                                // Error case of no readObject and didn't call
1216
// defaultWriteObject handled in default state
1217

1218                ObjectStreamField[] fields =
1219                    currentClassDesc.getFieldsNoCopy();
1220                if (fields.length > 0) {
1221                    inputClassFields(currentObject, currentClass, fields, sender);
1222                }
1223                            }
1224
1225                            if (currentClassDesc.hasWriteObject())
1226                                readObjectState.endUnmarshalCustomValue(this);
1227
1228                        } finally {
1229                            setState(oldState);
1230                        }
1231
1232                } else {
1233
1234            // _REVISIT_ : Can we ever get here?
1235
/* No local class for this descriptor,
1236             * Skip over the data for this class.
1237             * like defaultReadObject with a null currentObject.
1238             * The code will read the values but discard them.
1239             */

1240                ObjectStreamField[] fields =
1241                currentClassDesc.getFieldsNoCopy();
1242                if (fields.length > 0) {
1243                inputClassFields(null, currentClass, fields, sender);
1244                }
1245                        
1246            }
1247                    
1248        }
1249            } finally {
1250                // Make sure we exit at the same stack level as when we started.
1251
spClass = spBase;
1252            }
1253        }
1254        } finally {
1255            // We've completed deserializing this object. Any
1256
// future indirections will be handled correctly at the
1257
// CDR level. The ActiveRecursionManager only deals with
1258
// objects currently being deserialized.
1259
activeRecursionMgr.removeObject(offset);
1260        }
1261        
1262        return currentObject;
1263    }
1264
1265    // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
1266
// repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable
1267
// classes!
1268
private Vector JavaDoc getOrderedDescriptions(String JavaDoc repositoryID,
1269                      com.sun.org.omg.SendingContext.CodeBase sender) {
1270    Vector JavaDoc descs = new Vector JavaDoc();
1271
1272        if (sender == null) {
1273            return descs;
1274        }
1275        
1276    FullValueDescription aFVD = sender.meta(repositoryID);
1277    while (aFVD != null) {
1278        descs.insertElementAt(aFVD, 0);
1279        if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
1280        aFVD = sender.meta(aFVD.base_value);
1281        }
1282        else return descs;
1283    }
1284
1285    return descs;
1286    }
1287
1288    /**
1289     * This input method uses FullValueDescriptions retrieved from the sender's runtime to
1290     * read in the data. This method is capable of throwing out data not applicable to client's fields.
1291     * This method handles instances where the reader has a class not sent by the sender, the sender sent
1292     * a class not present on the reader, and/or the reader's class does not match the sender's class.
1293     *
1294     * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
1295     * indicates custom marsahling than the local type is used to read the data off the wire. However,
1296     * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
1297     * a form of custom marshaling.
1298     *
1299     */

1300    private Object JavaDoc inputObjectUsingFVD(Class JavaDoc clz,
1301                       String JavaDoc repositoryID,
1302                       com.sun.org.omg.SendingContext.CodeBase sender,
1303                                       int offset)
1304    throws IOException JavaDoc, ClassNotFoundException JavaDoc
1305    {
1306    int spBase = spClass; // current top of stack
1307
try{
1308            
1309        /*
1310         * Get the descriptor and then class of the incoming object.
1311         */

1312            
1313        ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
1314        Class JavaDoc currclass = currentClass = clz;
1315            
1316        /* If Externalizable,
1317         * Create an instance and tell it to read its data.
1318         * else,
1319         * Handle it as a serializable class.
1320         */

1321        if (currentClassDesc.isExternalizable()) {
1322        try {
1323            currentObject = (currentClass == null) ?
1324            null : currentClassDesc.newInstance();
1325            if (currentObject != null) {
1326                        // Store this object and its beginning position
1327
// since there might be indirections to it while
1328
// it's been unmarshalled.
1329
activeRecursionMgr.addObject(offset, currentObject);
1330
1331            // Read format version
1332
readFormatVersion();
1333                        
1334            Externalizable JavaDoc ext = (Externalizable JavaDoc)currentObject;
1335            ext.readExternal(this);
1336            }
1337        } catch (InvocationTargetException e) {
1338            InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1339            currentClass.getName(),
1340            "InvocationTargetException accessing no-arg constructor");
1341            exc.initCause( e ) ;
1342            throw exc ;
1343        } catch (UnsupportedOperationException JavaDoc e) {
1344            InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1345            currentClass.getName(),
1346            "UnsupportedOperationException accessing no-arg constructor");
1347            exc.initCause( e ) ;
1348            throw exc ;
1349        } catch (InstantiationException JavaDoc e) {
1350            InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1351            currentClass.getName(),
1352            "InstantiationException accessing no-arg constructor");
1353            exc.initCause( e ) ;
1354            throw exc ;
1355        }
1356        } else {
1357        /*
1358         * This is your basic diff pattern, made simpler
1359         * because reordering is not allowed.
1360         */

1361        for (currdesc = currentClassDesc, currclass = currentClass;
1362             currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
1363
1364             currdesc = currdesc.getSuperclass()) {
1365                    
1366            /*
1367             * Search the classes to see if the class of this
1368             * descriptor appears further up the hierarchy. Until
1369             * it's found assume its an inserted class. If it's
1370             * not found, its the descriptor's class that has been
1371             * removed.
1372             */

1373            Class JavaDoc cc = currdesc.forClass();
1374            Class JavaDoc cl;
1375            for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
1376            if (cc == cl) {
1377                // found a superclass that matches this descriptor
1378
break;
1379            } else {
1380                /* Ignore a class that doesn't match. No
1381                 * action is needed since it is already
1382                 * initialized.
1383                 */

1384            }
1385            } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
1386
/* Test if there is room for this new entry.
1387             * If not, double the size of the arrays and copy the contents.
1388             */

1389            spClass++;
1390            if (spClass >= classes.length) {
1391            int newlen = classes.length * 2;
1392            Class JavaDoc[] newclasses = new Class JavaDoc[newlen];
1393            ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
1394                
1395            System.arraycopy(classes, 0,
1396                     newclasses, 0,
1397                     classes.length);
1398            System.arraycopy(classdesc, 0,
1399                     newclassdesc, 0,
1400                     classes.length);
1401                        
1402            classes = newclasses;
1403            classdesc = newclassdesc;
1404                }
1405
1406            if (cl == null) {
1407            /* Class not found corresponding to this descriptor.
1408             * Pop off all the extra classes pushed.
1409             * Push the descriptor and a null class.
1410             */

1411            classdesc[spClass] = currdesc;
1412            classes[spClass] = null;
1413            } else {
1414            /* Current class descriptor matches current class.
1415             * Some classes may have been inserted.
1416             * Record the match and advance the class, continue
1417             * with the next descriptor.
1418             */

1419            classdesc[spClass] = currdesc;
1420            classes[spClass] = cl;
1421            currclass = cl.getSuperclass();
1422            }
1423        } // end : for (currdesc = currentClassDesc, currclass = currentClass;
1424

1425        /* Allocate a new object.
1426         */

1427        try {
1428            currentObject = (currentClass == null) ?
1429            null : currentClassDesc.newInstance();
1430
1431                    // Store this object and its beginning position
1432
// since there might be indirections to it while
1433
// it's been unmarshalled.
1434
activeRecursionMgr.addObject(offset, currentObject);
1435        } catch (InvocationTargetException e) {
1436            InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1437            currentClass.getName(),
1438            "InvocationTargetException accessing no-arg constructor");
1439            exc.initCause( e ) ;
1440            throw exc ;
1441        } catch (UnsupportedOperationException JavaDoc e) {
1442            InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1443            currentClass.getName(),
1444            "UnsupportedOperationException accessing no-arg constructor");
1445            exc.initCause( e ) ;
1446            throw exc ;
1447        } catch (InstantiationException JavaDoc e) {
1448            InvalidClassException JavaDoc exc = new InvalidClassException JavaDoc(
1449            currentClass.getName(),
1450            "InstantiationException accessing no-arg constructor");
1451            exc.initCause( e ) ;
1452            throw exc ;
1453        }
1454                
1455        Enumeration JavaDoc fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
1456                
1457        while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
1458            FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1459                // d4365188: backward compatability
1460
String JavaDoc repIDForFVD = vhandler.getClassName(fvd.id);
1461            String JavaDoc repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
1462                    
1463            while ((spClass > spBase) &&
1464               (!repIDForFVD.equals(repIDForClass))) {
1465            int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
1466            if (pos != -1) {
1467                spClass = pos;
1468                currclass = currentClass = classes[spClass];
1469                repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
1470            }
1471            else { // Read and throw away one level of the fvdslist
1472

1473                            // This seems to mean that the sender had a superclass that
1474
// we don't have
1475

1476                if (fvd.is_custom) {
1477
1478                                readFormatVersion();
1479                                boolean calledDefaultWriteObject = readBoolean();
1480
1481                                if (calledDefaultWriteObject)
1482                                    inputClassFields(null, null, null, fvd.members, sender);
1483
1484                                if (getStreamFormatVersion() == 2) {
1485
1486                                    ((ValueInputStream JavaDoc)getOrbStream()).start_value();
1487                                    ((ValueInputStream JavaDoc)getOrbStream()).end_value();
1488                                }
1489
1490                                // WARNING: If stream format version is 1 and there's
1491
// optional data, we'll get some form of exception down
1492
// the line or data corruption.
1493

1494                } else {
1495
1496                inputClassFields(null, currentClass, null, fvd.members, sender);
1497                }
1498
1499                if (fvdsList.hasMoreElements()){
1500                fvd = (FullValueDescription)fvdsList.nextElement();
1501                repIDForFVD = vhandler.getClassName(fvd.id);
1502                }
1503                else return currentObject;
1504            }
1505            }
1506
1507            currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
1508
1509            if (!repIDForClass.equals("java.lang.Object")) {
1510
1511                        // If the sender used custom marshaling, then it should have put
1512
// the two bytes on the wire indicating stream format version
1513
// and whether or not the writeObject method called
1514
// defaultWriteObject/writeFields.
1515

1516                        ReadObjectState oldState = readObjectState;
1517                        setState(DEFAULT_STATE);
1518
1519                        try {
1520
1521                            if (fvd.is_custom) {
1522
1523                                // Read format version
1524
readFormatVersion();
1525
1526                                // Read defaultWriteObject indicator
1527
boolean calledDefaultWriteObject = readBoolean();
1528
1529                                readObjectState.beginUnmarshalCustomValue(this,
1530                                                                          calledDefaultWriteObject,
1531                                                                          (currentClassDesc.readObjectMethod
1532                                                                           != null));
1533                            }
1534
1535                            boolean usedReadObject = false;
1536
1537                            // Always use readObject if it exists, and fall back to default
1538
// unmarshaling if it doesn't.
1539
try {
1540
1541                                if (!fvd.is_custom && currentClassDesc.hasReadObject())
1542                                    setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
1543
1544                                // See the definition of defaultReadObjectFVDMembers
1545
// for more information. This concerns making sure
1546
// we use the remote FVD's members in defaultReadObject.
1547
defaultReadObjectFVDMembers = fvd.members;
1548                                usedReadObject = invokeObjectReader(currentClassDesc,
1549                                                                    currentObject,
1550                                                                    currentClass);
1551
1552                            } finally {
1553                                defaultReadObjectFVDMembers = null;
1554                            }
1555
1556                            // Note that the !usedReadObject !calledDefaultWriteObject
1557
// case is handled by the beginUnmarshalCustomValue method
1558
// of the default state
1559
if (!usedReadObject || readObjectState == IN_READ_OBJECT_DEFAULTS_SENT)
1560                                inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
1561
1562                            if (fvd.is_custom)
1563                                readObjectState.endUnmarshalCustomValue(this);
1564
1565                        } finally {
1566                            setState(oldState);
1567                        }
1568                           
1569                        currclass = currentClass = classes[--spClass];
1570
1571            } else {
1572
1573            // The remaining hierarchy of the local class does not match the sender's FVD.
1574
// So, use remaining FVDs to read data off wire. If any remaining FVDs indicate
1575
// custom marshaling, throw MARSHAL error.
1576
inputClassFields(null, currentClass, null, fvd.members, sender);
1577                        
1578            while (fvdsList.hasMoreElements()){
1579                fvd = (FullValueDescription)fvdsList.nextElement();
1580
1581                            if (fvd.is_custom)
1582                                skipCustomUsingFVD(fvd.members, sender);
1583                else
1584                                inputClassFields(null, currentClass, null, fvd.members, sender);
1585            }
1586                        
1587            }
1588                    
1589        } // end : while(fvdsList.hasMoreElements())
1590
while (fvdsList.hasMoreElements()){
1591
1592            FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1593            if (fvd.is_custom)
1594                        skipCustomUsingFVD(fvd.members, sender);
1595            else
1596                        throwAwayData(fvd.members, sender);
1597        }
1598        }
1599            
1600        return currentObject;
1601    }
1602    finally {
1603            // Make sure we exit at the same stack level as when we started.
1604
spClass = spBase;
1605
1606                // We've completed deserializing this object. Any
1607
// future indirections will be handled correctly at the
1608
// CDR level. The ActiveRecursionManager only deals with
1609
// objects currently being deserialized.
1610
activeRecursionMgr.removeObject(offset);
1611            }
1612        
1613        }
1614
1615    /**
1616     * This input method uses FullValueDescriptions retrieved from the sender's runtime to
1617     * read in the data. This method is capable of throwing out data not applicable to client's fields.
1618     *
1619     * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
1620     * indicates custom marsahling than the local type is used to read the data off the wire. However,
1621     * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
1622     * a form of custom marshaling.
1623     *
1624     */

1625    private Object JavaDoc skipObjectUsingFVD(String JavaDoc repositoryID,
1626                      com.sun.org.omg.SendingContext.CodeBase sender)
1627    throws IOException JavaDoc, ClassNotFoundException JavaDoc
1628    {
1629
1630    Enumeration JavaDoc fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
1631        
1632    while(fvdsList.hasMoreElements()) {
1633        FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
1634        String JavaDoc repIDForFVD = vhandler.getClassName(fvd.id);
1635            
1636        if (!repIDForFVD.equals("java.lang.Object")) {
1637        if (fvd.is_custom) {
1638
1639                    readFormatVersion();
1640                        
1641                    boolean calledDefaultWriteObject = readBoolean();
1642                        
1643                    if (calledDefaultWriteObject)
1644                        inputClassFields(null, null, null, fvd.members, sender);
1645
1646                    if (getStreamFormatVersion() == 2) {
1647
1648                        ((ValueInputStream JavaDoc)getOrbStream()).start_value();
1649                        ((ValueInputStream JavaDoc)getOrbStream()).end_value();
1650                    }
1651
1652                    // WARNING: If stream format version is 1 and there's
1653
// optional data, we'll get some form of exception down
1654
// the line.
1655

1656        } else {
1657            // Use default marshaling
1658
inputClassFields(null, null, null, fvd.members, sender);
1659        }
1660        }
1661
1662    } // end : while(fvdsList.hasMoreElements())
1663
return null;
1664        
1665    }
1666
1667    ///////////////////
1668

1669    private int findNextClass(String JavaDoc classname, Class JavaDoc classes[], int _spClass, int _spBase){
1670
1671    for (int i = _spClass; i > _spBase; i--){
1672        if (classname.equals(classes[i].getName())) {
1673        return i;
1674        }
1675    }
1676
1677    return -1;
1678    }
1679
1680    /*
1681     * Invoke the readObject method if present. Assumes that in the case of custom
1682     * marshaling, the format version and defaultWriteObject indicator were already
1683     * removed.
1684     */

1685    private boolean invokeObjectReader(ObjectStreamClass osc, Object JavaDoc obj, Class JavaDoc aclass)
1686    throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
1687           ClassNotFoundException JavaDoc, IOException JavaDoc
1688    {
1689    if (osc.readObjectMethod == null) {
1690        return false;
1691    }
1692
1693    try {
1694        osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
1695        return true;
1696    } catch (InvocationTargetException e) {
1697        Throwable JavaDoc t = e.getTargetException();
1698        if (t instanceof ClassNotFoundException JavaDoc)
1699        throw (ClassNotFoundException JavaDoc)t;
1700        else if (t instanceof IOException JavaDoc)
1701        throw (IOException JavaDoc)t;
1702        else if (t instanceof RuntimeException JavaDoc)
1703        throw (RuntimeException JavaDoc) t;
1704        else if (t instanceof Error JavaDoc)
1705        throw (Error JavaDoc) t;
1706        else
1707        // XXX I18N, logging needed.
1708
throw new Error JavaDoc("internal error");
1709    } catch (IllegalAccessException JavaDoc e) {
1710        return false;
1711    }
1712    }
1713
1714    /*
1715     * Reset the stream to be just like it was after the constructor.
1716     */

1717    private void resetStream() throws IOException JavaDoc {
1718
1719    if (classes == null)
1720        classes = new Class JavaDoc[20];
1721    else {
1722        for (int i = 0; i < classes.length; i++)
1723        classes[i] = null;
1724    }
1725    if (classdesc == null)
1726        classdesc = new ObjectStreamClass[20];
1727    else {
1728        for (int i = 0; i < classdesc.length; i++)
1729        classdesc[i] = null;
1730    }
1731    spClass = 0;
1732
1733    if (callbacks != null)
1734        callbacks.setSize(0); // discard any pending callbacks
1735
}
1736
1737    /**
1738     * Factored out of inputClassFields This reads a primitive value and sets it
1739     * in the field of o described by the ObjectStreamField field.
1740     *
1741     * Note that reflection cannot be used here, because reflection cannot be used
1742     * to set final fields.
1743     */

1744    private void inputPrimitiveField(Object JavaDoc o, Class JavaDoc cl, ObjectStreamField field)
1745        throws InvalidClassException JavaDoc, IOException JavaDoc {
1746
1747        try {
1748            switch (field.getTypeCode()) {
1749                case 'B':
1750                    byte byteValue = orbStream.read_octet();
1751            bridge.putByte( o, field.getFieldID(), byteValue ) ;
1752            //reflective code: field.getField().setByte( o, byteValue ) ;
1753
break;
1754                case 'Z':
1755                    boolean booleanValue = orbStream.read_boolean();
1756            bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
1757            //reflective code: field.getField().setBoolean( o, booleanValue ) ;
1758
break;
1759        case 'C':
1760                    char charValue = orbStream.read_wchar();
1761            bridge.putChar( o, field.getFieldID(), charValue ) ;
1762            //reflective code: field.getField().setChar( o, charValue ) ;
1763
break;
1764        case 'S':
1765                    short shortValue = orbStream.read_short();
1766            bridge.putShort( o, field.getFieldID(), shortValue ) ;
1767            //reflective code: field.getField().setShort( o, shortValue ) ;
1768
break;
1769        case 'I':
1770                    int intValue = orbStream.read_long();
1771            bridge.putInt( o, field.getFieldID(), intValue ) ;
1772            //reflective code: field.getField().setInt( o, intValue ) ;
1773
break;
1774        case 'J':
1775                    long longValue = orbStream.read_longlong();
1776            bridge.putLong( o, field.getFieldID(), longValue ) ;
1777            //reflective code: field.getField().setLong( o, longValue ) ;
1778
break;
1779        case 'F' :
1780                    float floatValue = orbStream.read_float();
1781            bridge.putFloat( o, field.getFieldID(), floatValue ) ;
1782            //reflective code: field.getField().setFloat( o, floatValue ) ;
1783
break;
1784        case 'D' :
1785                    double doubleValue = orbStream.read_double();
1786            bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
1787            //reflective code: field.getField().setDouble( o, doubleValue ) ;
1788
break;
1789        default:
1790            // XXX I18N, logging needed.
1791
throw new InvalidClassException JavaDoc(cl.getName());
1792            }
1793        } catch (IllegalArgumentException JavaDoc e) {
1794            /* This case should never happen. If the field types
1795               are not the same, InvalidClassException is raised when
1796               matching the local class to the serialized ObjectStreamClass. */

1797            ClassCastException JavaDoc cce = new ClassCastException JavaDoc("Assigning instance of class " +
1798                                         field.getType().getName() +
1799                                         " to field " +
1800                                         currentClassDesc.getName() + '#' +
1801                                         field.getField().getName());
1802        cce.initCause( e ) ;
1803        throw cce ;
1804    }
1805     }
1806
1807    private Object JavaDoc inputObjectField(org.omg.CORBA.ValueMember JavaDoc field,
1808                                    com.sun.org.omg.SendingContext.CodeBase sender)
1809        throws IndirectionException JavaDoc, ClassNotFoundException JavaDoc, IOException JavaDoc,
1810               StreamCorruptedException JavaDoc {
1811
1812        Object JavaDoc objectValue = null;
1813        Class JavaDoc type = null;
1814        String JavaDoc id = field.id;
1815                            
1816        try {
1817            type = vhandler.getClassFromType(id);
1818        } catch(ClassNotFoundException JavaDoc cnfe) {
1819            // Make sure type = null
1820
type = null;
1821        }
1822
1823        String JavaDoc signature = null;
1824        if (type != null)
1825            signature = ValueUtility.getSignature(field);
1826                                
1827        if (signature != null && (signature.equals("Ljava/lang/Object;") ||
1828                                  signature.equals("Ljava/io/Serializable;") ||
1829                                  signature.equals("Ljava/io/Externalizable;"))) {
1830            objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
1831        } else {
1832            // Decide what method call to make based on the type. If
1833
// it is a type for which we need to load a stub, convert
1834
// the type to the correct stub type.
1835
//
1836
// NOTE : Since FullValueDescription does not allow us
1837
// to ask whether something is an interface we do not
1838
// have the ability to optimize this check.
1839

1840            int callType = ValueHandlerImpl.kValueType;
1841            
1842            if (!vhandler.isSequence(id)) {
1843
1844                if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
1845
1846                    // RMI Object reference...
1847
callType = ValueHandlerImpl.kRemoteType;
1848                    
1849                } else {
1850
1851                    // REVISIT. If we don't have the local class,
1852
// we should probably verify that it's an RMI type,
1853
// query the remote FVD, and use is_abstract.
1854
// Our FVD seems to get NullPointerExceptions for any
1855
// non-RMI types.
1856

1857                    // This uses the local class in the same way as
1858
// inputObjectField(ObjectStreamField) does. REVISIT
1859
// inputObjectField(ObjectStreamField)'s loadStubClass
1860
// logic. Assumption is that the given type cannot
1861
// evolve to become a CORBA abstract interface or
1862
// a RMI abstract interface.
1863

1864                    if (type != null && type.isInterface() &&
1865                        (vhandler.isAbstractBase(type) ||
1866                         ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
1867                
1868                        callType = ValueHandlerImpl.kAbstractType;
1869                    }
1870                }
1871            }
1872                
1873            // Now that we have used the FVD of the field to determine the proper course
1874
// of action, it is ok to use the type (Class) from this point forward since
1875
// the rep. id for this read will also follow on the wire.
1876

1877            switch (callType) {
1878                case ValueHandlerImpl.kRemoteType:
1879                    if (type != null)
1880                        objectValue = Utility.readObjectAndNarrow(orbStream, type);
1881                    else
1882                        objectValue = orbStream.read_Object();
1883                    break;
1884                case ValueHandlerImpl.kAbstractType:
1885                    if (type != null)
1886                        objectValue = Utility.readAbstractAndNarrow(orbStream, type);
1887                    else
1888                        objectValue = orbStream.read_abstract_interface();
1889                    break;
1890                case ValueHandlerImpl.kValueType:
1891                    if (type != null)
1892                        objectValue = orbStream.read_value(type);
1893                    else
1894                                            objectValue = orbStream.read_value();
1895                    break;
1896                default:
1897            // XXX I18N, logging needed.
1898
throw new StreamCorruptedException JavaDoc("Unknown callType: " + callType);
1899            }
1900        }
1901
1902        return objectValue;
1903    }
1904
1905    /**
1906     * Factored out of inputClassFields and reused in
1907     * inputCurrentClassFieldsForReadFields.
1908     *
1909     * Reads the field (which of an Object type as opposed to a primitive)
1910     * described by ObjectStreamField field and returns it.
1911     */

1912    private Object JavaDoc inputObjectField(ObjectStreamField field)
1913        throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
1914               ClassNotFoundException JavaDoc, IndirectionException JavaDoc, IOException JavaDoc {
1915
1916        if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
1917            return javax.rmi.CORBA.Util.readAny(orbStream);
1918        }
1919
1920        Object JavaDoc objectValue = null;
1921
1922        // fields have an API to provide the actual class
1923
// corresponding to the data type
1924
// Class type = osc.forClass();
1925
Class JavaDoc fieldType = field.getType();
1926    Class JavaDoc actualType = fieldType; // This may change if stub loaded.
1927

1928        // Decide what method call to make based on the fieldType. If
1929
// it is a type for which we need to load a stub, convert
1930
// the type to the correct stub type.
1931

1932        int callType = ValueHandlerImpl.kValueType;
1933        boolean narrow = false;
1934        
1935        if (fieldType.isInterface()) {
1936            boolean loadStubClass = false;
1937            
1938            if (java.rmi.Remote JavaDoc.class.isAssignableFrom(fieldType)) {
1939                
1940                // RMI Object reference...
1941
callType = ValueHandlerImpl.kRemoteType;
1942                
1943            } else if (org.omg.CORBA.Object JavaDoc.class.isAssignableFrom(fieldType)){
1944                
1945                // IDL Object reference...
1946
callType = ValueHandlerImpl.kRemoteType;
1947                loadStubClass = true;
1948                
1949            } else if (vhandler.isAbstractBase(fieldType)) {
1950                // IDL Abstract Object reference...
1951

1952                callType = ValueHandlerImpl.kAbstractType;
1953                loadStubClass = true;
1954            } else if (ObjectStreamClassCorbaExt.isAbstractInterface(fieldType)) {
1955                // RMI Abstract Object reference...
1956

1957                callType = ValueHandlerImpl.kAbstractType;
1958            }
1959            
1960            if (loadStubClass) {
1961                try {
1962                    String JavaDoc codebase = Util.getCodebase(fieldType);
1963                    String JavaDoc repID = vhandler.createForAnyType(fieldType);
1964                    Class JavaDoc stubType =
1965            Utility.loadStubClass(repID, codebase, fieldType);
1966            actualType = stubType;
1967                } catch (ClassNotFoundException JavaDoc e) {
1968                    narrow = true;
1969                }
1970            } else {
1971                narrow = true;
1972            }
1973        }
1974
1975        switch (callType) {
1976            case ValueHandlerImpl.kRemoteType:
1977                if (!narrow)
1978                    objectValue = (Object JavaDoc)orbStream.read_Object(actualType);
1979                else
1980                    objectValue = Utility.readObjectAndNarrow(orbStream, actualType);
1981                break;
1982            case ValueHandlerImpl.kAbstractType:
1983                if (!narrow)
1984                    objectValue = (Object JavaDoc)orbStream.read_abstract_interface(actualType);
1985                else
1986                    objectValue = Utility.readAbstractAndNarrow(orbStream, actualType);
1987                break;
1988            case ValueHandlerImpl.kValueType:
1989                objectValue = (Object JavaDoc)orbStream.read_value(actualType);
1990                break;
1991            default:
1992        // XXX I18N, logging needed.
1993
throw new StreamCorruptedException JavaDoc("Unknown callType: " + callType);
1994        }
1995
1996        return objectValue;
1997    }
1998
1999    private final boolean mustUseRemoteValueMembers() {
2000        return defaultReadObjectFVDMembers != null;
2001    }
2002
2003    void readFields(java.util.Map JavaDoc fieldToValueMap)
2004        throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
2005               ClassNotFoundException JavaDoc, IOException JavaDoc {
2006
2007        if (mustUseRemoteValueMembers()) {
2008            inputRemoteMembersForReadFields(fieldToValueMap);
2009        } else
2010            inputCurrentClassFieldsForReadFields(fieldToValueMap);
2011    }
2012
2013    private final void inputRemoteMembersForReadFields(java.util.Map JavaDoc fieldToValueMap)
2014        throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
2015               ClassNotFoundException JavaDoc, IOException JavaDoc {
2016
2017        // Must have this local variable since defaultReadObjectFVDMembers
2018
// may get mangled by recursion.
2019
ValueMember JavaDoc fields[] = defaultReadObjectFVDMembers;
2020
2021    try {
2022
2023        for (int i = 0; i < fields.length; i++) {
2024
2025                switch (fields[i].type.kind().value()) {
2026
2027                case TCKind._tk_octet:
2028                    byte byteValue = orbStream.read_octet();
2029                    fieldToValueMap.put(fields[i].name, new Byte JavaDoc(byteValue));
2030                    break;
2031                case TCKind._tk_boolean:
2032                    boolean booleanValue = orbStream.read_boolean();
2033                    fieldToValueMap.put(fields[i].name, new Boolean JavaDoc(booleanValue));
2034                    break;
2035                case TCKind._tk_char:
2036                    // Backwards compatibility. Older Sun ORBs sent
2037
// _tk_char even though they read and wrote wchars
2038
// correctly.
2039
//
2040
// Fall through to the _tk_wchar case.
2041
case TCKind._tk_wchar:
2042                    char charValue = orbStream.read_wchar();
2043                    fieldToValueMap.put(fields[i].name, new Character JavaDoc(charValue));
2044                    break;
2045                case TCKind._tk_short:
2046                    short shortValue = orbStream.read_short();
2047                    fieldToValueMap.put(fields[i].name, new Short JavaDoc(shortValue));
2048                    break;
2049                case TCKind._tk_long:
2050                    int intValue = orbStream.read_long();
2051                    fieldToValueMap.put(fields[i].name, new Integer JavaDoc(intValue));
2052                    break;
2053                case TCKind._tk_longlong:
2054                    long longValue = orbStream.read_longlong();
2055                    fieldToValueMap.put(fields[i].name, new Long JavaDoc(longValue));
2056                    break;
2057                case TCKind._tk_float:
2058                    float floatValue = orbStream.read_float();
2059                    fieldToValueMap.put(fields[i].name, new Float JavaDoc(floatValue));
2060                    break;
2061                case TCKind._tk_double:
2062                    double doubleValue = orbStream.read_double();
2063                    fieldToValueMap.put(fields[i].name, new Double JavaDoc(doubleValue));
2064                    break;
2065                case TCKind._tk_value:
2066                case TCKind._tk_objref:
2067                case TCKind._tk_value_box:
2068                    Object JavaDoc objectValue = null;
2069                    try {
2070                        objectValue = inputObjectField(fields[i],
2071                                                       cbSender);
2072
2073                    } catch (IndirectionException JavaDoc cdrie) {
2074                        // The CDR stream had never seen the given offset before,
2075
// so check the recursion manager (it will throw an
2076
// IOException if it doesn't have a reference, either).
2077
objectValue = activeRecursionMgr.getObject(cdrie.offset);
2078                    }
2079
2080                    fieldToValueMap.put(fields[i].name, objectValue);
2081                    break;
2082                default:
2083            // XXX I18N, logging needed.
2084
throw new StreamCorruptedException JavaDoc("Unknown kind: "
2085                                                       + fields[i].type.kind().value());
2086                }
2087            }
2088        } catch (Throwable JavaDoc t) {
2089            StreamCorruptedException JavaDoc result = new StreamCorruptedException JavaDoc(t.getMessage());
2090            result.initCause(t);
2091            throw result;
2092    }
2093    }
2094
2095    /**
2096     * Called from InputStreamHook.
2097     *
2098     * Reads the fields of the current class (could be the ones
2099     * queried from the remote FVD) and puts them in
2100     * the given Map, name to value. Wraps primitives in the
2101     * corresponding java.lang Objects.
2102     */

2103    private final void inputCurrentClassFieldsForReadFields(java.util.Map JavaDoc fieldToValueMap)
2104        throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
2105               ClassNotFoundException JavaDoc, IOException JavaDoc {
2106
2107        ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
2108
2109    int primFields = fields.length - currentClassDesc.objFields;
2110
2111        // Handle the primitives first
2112
for (int i = 0; i < primFields; ++i) {
2113
2114            switch (fields[i].getTypeCode()) {
2115                case 'B':
2116                    byte byteValue = orbStream.read_octet();
2117                    fieldToValueMap.put(fields[i].getName(),
2118                                        new Byte JavaDoc(byteValue));
2119                    break;
2120                case 'Z':
2121                   boolean booleanValue = orbStream.read_boolean();
2122                   fieldToValueMap.put(fields[i].getName(),
2123                                       new Boolean JavaDoc(booleanValue));
2124                   break;
2125        case 'C':
2126                    char charValue = orbStream.read_wchar();
2127                    fieldToValueMap.put(fields[i].getName(),
2128                                        new Character JavaDoc(charValue));
2129                    break;
2130        case 'S':
2131                    short shortValue = orbStream.read_short();
2132                    fieldToValueMap.put(fields[i].getName(),
2133                                        new Short JavaDoc(shortValue));
2134                    break;
2135        case 'I':
2136                    int intValue = orbStream.read_long();
2137                    fieldToValueMap.put(fields[i].getName(),
2138                                        new Integer JavaDoc(intValue));
2139                    break;
2140        case 'J':
2141                    long longValue = orbStream.read_longlong();
2142                    fieldToValueMap.put(fields[i].getName(),
2143                                        new Long JavaDoc(longValue));
2144                    break;
2145        case 'F' :
2146                    float floatValue = orbStream.read_float();
2147                    fieldToValueMap.put(fields[i].getName(),
2148                                        new Float JavaDoc(floatValue));
2149                    break;
2150        case 'D' :
2151                    double doubleValue = orbStream.read_double();
2152                    fieldToValueMap.put(fields[i].getName(),
2153                                        new Double JavaDoc(doubleValue));
2154                    break;
2155        default:
2156            // XXX I18N, logging needed.
2157
throw new InvalidClassException JavaDoc(currentClassDesc.getName());
2158        }
2159    }
2160
2161    /* Read and set object fields from the input stream. */
2162    if (currentClassDesc.objFields > 0) {
2163        for (int i = primFields; i < fields.length; i++) {
2164                Object JavaDoc objectValue = null;
2165                try {
2166                    objectValue = inputObjectField(fields[i]);
2167                } catch(IndirectionException JavaDoc cdrie) {
2168                    // The CDR stream had never seen the given offset before,
2169
// so check the recursion manager (it will throw an
2170
// IOException if it doesn't have a reference, either).
2171
objectValue = activeRecursionMgr.getObject(cdrie.offset);
2172                }
2173
2174                fieldToValueMap.put(fields[i].getName(), objectValue);
2175            }
2176        }
2177    }
2178
2179    /*
2180     * Read the fields of the specified class from the input stream and set
2181     * the values of the fields in the specified object. If the specified
2182     * object is null, just consume the fields without setting any values. If
2183     * any ObjectStreamField does not have a reflected Field, don't try to set
2184     * that field in the object.
2185     *
2186     * REVISIT -- This code doesn't do what the comment says to when
2187     * getField() is null!
2188     */

2189    private void inputClassFields(Object JavaDoc o, Class JavaDoc cl,
2190                  ObjectStreamField[] fields,
2191                  com.sun.org.omg.SendingContext.CodeBase sender)
2192    throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
2193           ClassNotFoundException JavaDoc, IOException JavaDoc
2194    {
2195        
2196    int primFields = fields.length - currentClassDesc.objFields;
2197
2198    if (o != null) {
2199        for (int i = 0; i < primFields; ++i) {
2200        if (fields[i].getField() == null)
2201            continue;
2202
2203                inputPrimitiveField(o, cl, fields[i]);
2204        }
2205    }
2206
2207    /* Read and set object fields from the input stream. */
2208    if (currentClassDesc.objFields > 0) {
2209        for (int i = primFields; i < fields.length; i++) {
2210        Object JavaDoc objectValue = null;
2211
2212                try {
2213                    objectValue = inputObjectField(fields[i]);
2214                } catch(IndirectionException JavaDoc cdrie) {
2215                    // The CDR stream had never seen the given offset before,
2216
// so check the recursion manager (it will throw an
2217
// IOException if it doesn't have a reference, either).
2218
objectValue = activeRecursionMgr.getObject(cdrie.offset);
2219                }
2220
2221        if ((o == null) || (fields[i].getField() == null)) {
2222            continue;
2223        }
2224
2225        try {
2226            bridge.putObject( o, fields[i].getFieldID(), objectValue ) ;
2227            // reflective code: fields[i].getField().set( o, objectValue ) ;
2228
} catch (IllegalArgumentException JavaDoc e) {
2229            ClassCastException JavaDoc exc = new ClassCastException JavaDoc("Assigning instance of class " +
2230                         objectValue.getClass().getName() +
2231                         " to field " +
2232                         currentClassDesc.getName() +
2233                         '#' +
2234                         fields[i].getField().getName());
2235            exc.initCause( e ) ;
2236            throw exc ;
2237        }
2238        } // end : for loop
2239
}
2240    }
2241
2242    /*
2243     * Read the fields of the specified class from the input stream and set
2244     * the values of the fields in the specified object. If the specified
2245     * object is null, just consume the fields without setting any values. If
2246     * any ObjectStreamField does not have a reflected Field, don't try to set
2247     * that field in the object.
2248     */

2249    private void inputClassFields(Object JavaDoc o, Class JavaDoc cl,
2250                  ObjectStreamClass osc,
2251                  ValueMember JavaDoc[] fields,
2252                  com.sun.org.omg.SendingContext.CodeBase sender)
2253    throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
2254           ClassNotFoundException JavaDoc, IOException JavaDoc
2255    {
2256    try{
2257        for (int i = 0; i < fields.length; ++i) {
2258        try {
2259            switch (fields[i].type.kind().value()) {
2260            case TCKind._tk_octet:
2261            byte byteValue = orbStream.read_octet();
2262            if ((o != null) && osc.hasField(fields[i]))
2263            setByteField(o, cl, fields[i].name, byteValue);
2264            break;
2265            case TCKind._tk_boolean:
2266            boolean booleanValue = orbStream.read_boolean();
2267            if ((o != null) && osc.hasField(fields[i]))
2268            setBooleanField(o, cl, fields[i].name, booleanValue);
2269            break;
2270            case TCKind._tk_char:
2271                        // Backwards compatibility. Older Sun ORBs sent
2272
// _tk_char even though they read and wrote wchars
2273
// correctly.
2274
//
2275
// Fall through to the _tk_wchar case.
2276
case TCKind._tk_wchar:
2277            char charValue = orbStream.read_wchar();
2278            if ((o != null) && osc.hasField(fields[i]))
2279            setCharField(o, cl, fields[i].name, charValue);
2280            break;
2281            case TCKind._tk_short:
2282            short shortValue = orbStream.read_short();
2283            if ((o != null) && osc.hasField(fields[i]))
2284            setShortField(o, cl, fields[i].name, shortValue);
2285            break;
2286            case TCKind._tk_long:
2287            int intValue = orbStream.read_long();
2288            if ((o != null) && osc.hasField(fields[i]))
2289            setIntField(o, cl, fields[i].name, intValue);
2290            break;
2291            case TCKind._tk_longlong:
2292            long longValue = orbStream.read_longlong();
2293            if ((o != null) && osc.hasField(fields[i]))
2294            setLongField(o, cl, fields[i].name, longValue);
2295            break;
2296            case TCKind._tk_float:
2297            float floatValue = orbStream.read_float();
2298            if ((o != null) && osc.hasField(fields[i]))
2299            setFloatField(o, cl, fields[i].name, floatValue);
2300            break;
2301            case TCKind._tk_double:
2302            double doubleValue = orbStream.read_double();
2303            if ((o != null) && osc.hasField(fields[i]))
2304            setDoubleField(o, cl, fields[i].name, doubleValue);
2305            break;
2306                    case TCKind._tk_value:
2307            case TCKind._tk_objref:
2308            case TCKind._tk_value_box:
2309                        Object JavaDoc objectValue = null;
2310                        try {
2311                            objectValue = inputObjectField(fields[i], sender);
2312                        } catch (IndirectionException JavaDoc cdrie) {
2313                            // The CDR stream had never seen the given offset before,
2314
// so check the recursion manager (it will throw an
2315
// IOException if it doesn't have a reference, either).
2316
objectValue = activeRecursionMgr.getObject(cdrie.offset);
2317                        }
2318                                
2319            if (o == null)
2320                continue;
2321            try {
2322                if (osc.hasField(fields[i])){
2323                                setObjectField(o,
2324                                               cl,
2325                                               fields[i].name,
2326                                               objectValue);
2327                } else {
2328                                // REVISIT. Convert to a log message.
2329
// This is a normal case when fields have
2330
// been added as part of evolution, but
2331
// silently skipping can make it hard to
2332
// debug if there's an error
2333
// System.out.println("**** warning, not setting field: "
2334
// + fields[i].name
2335
// + " since not on class "
2336
// + osc.getName());
2337

2338                            }
2339            } catch (IllegalArgumentException JavaDoc e) {
2340                // XXX I18N, logging needed.
2341
ClassCastException JavaDoc cce = new ClassCastException JavaDoc("Assigning instance of class " +
2342                objectValue.getClass().getName() + " to field " + fields[i].name);
2343                cce.initCause(e) ;
2344                throw cce ;
2345            }
2346            break;
2347                    default:
2348            // XXX I18N, logging needed.
2349
throw new StreamCorruptedException JavaDoc("Unknown kind: "
2350                                                           + fields[i].type.kind().value());
2351            }
2352        } catch (IllegalArgumentException JavaDoc e) {
2353            /* This case should never happen. If the field types
2354               are not the same, InvalidClassException is raised when
2355               matching the local class to the serialized ObjectStreamClass. */

2356            // XXX I18N, logging needed.
2357
ClassCastException JavaDoc cce = new ClassCastException JavaDoc("Assigning instance of class " + fields[i].id +
2358            " to field " + currentClassDesc.getName() + '#' + fields[i].name);
2359            cce.initCause( e ) ;
2360            throw cce ;
2361        }
2362        }
2363    } catch(Throwable JavaDoc t){
2364        // XXX I18N, logging needed.
2365
StreamCorruptedException JavaDoc sce = new StreamCorruptedException JavaDoc(t.getMessage());
2366        sce.initCause(t) ;
2367        throw sce ;
2368    }
2369    }
2370
2371    private void skipCustomUsingFVD(ValueMember JavaDoc[] fields,
2372                                    com.sun.org.omg.SendingContext.CodeBase sender)
2373                                    throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
2374                                           ClassNotFoundException JavaDoc, IOException JavaDoc
2375    {
2376        readFormatVersion();
2377        boolean calledDefaultWriteObject = readBoolean();
2378
2379        if (calledDefaultWriteObject)
2380            throwAwayData(fields, sender);
2381
2382        if (getStreamFormatVersion() == 2) {
2383            
2384            ((ValueInputStream JavaDoc)getOrbStream()).start_value();
2385            ((ValueInputStream JavaDoc)getOrbStream()).end_value();
2386        }
2387    }
2388    
2389    /*
2390     * Read the fields of the specified class from the input stream throw data away.
2391     * This must handle same switch logic as above.
2392     */

2393    private void throwAwayData(ValueMember JavaDoc[] fields,
2394                   com.sun.org.omg.SendingContext.CodeBase sender)
2395    throws InvalidClassException JavaDoc, StreamCorruptedException JavaDoc,
2396           ClassNotFoundException JavaDoc, IOException JavaDoc
2397    {
2398    for (int i = 0; i < fields.length; ++i) {
2399    
2400        try {
2401                    
2402        switch (fields[i].type.kind().value()) {
2403        case TCKind._tk_octet:
2404            orbStream.read_octet();
2405            break;
2406        case TCKind._tk_boolean:
2407            orbStream.read_boolean();
2408            break;
2409        case TCKind._tk_char:
2410                    // Backwards compatibility. Older Sun ORBs sent
2411
// _tk_char even though they read and wrote wchars
2412
// correctly.
2413
//
2414
// Fall through to the _tk_wchar case.
2415
case TCKind._tk_wchar:
2416            orbStream.read_wchar();
2417            break;
2418        case TCKind._tk_short:
2419            orbStream.read_short();
2420            break;
2421        case TCKind._tk_long:
2422            orbStream.read_long();
2423            break;
2424        case TCKind._tk_longlong:
2425            orbStream.read_longlong();
2426            break;
2427        case TCKind._tk_float:
2428            orbStream.read_float();
2429            break;
2430        case TCKind._tk_double:
2431            orbStream.read_double();
2432            break;
2433                case TCKind._tk_value:
2434        case TCKind._tk_objref:
2435        case TCKind._tk_value_box:
2436            Class JavaDoc type = null;
2437                String JavaDoc id = fields[i].id;
2438
2439            try {
2440            type = vhandler.getClassFromType(id);
2441            }
2442            catch(ClassNotFoundException JavaDoc cnfe){
2443            // Make sure type = null
2444
type = null;
2445            }
2446            String JavaDoc signature = null;
2447            if (type != null)
2448            signature = ValueUtility.getSignature(fields[i]);
2449                                
2450            // Read value
2451
try {
2452            if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
2453                             signature.equals("Ljava/io/Serializable;") ||
2454                             signature.equals("Ljava/io/Externalizable;")) ) {
2455                javax.rmi.CORBA.Util.readAny(orbStream);
2456            }
2457            else {
2458                // Decide what method call to make based on the type.
2459
//
2460
// NOTE : Since FullValueDescription does not allow us
2461
// to ask whether something is an interface we do not
2462
// have the ability to optimize this check.
2463

2464                int callType = ValueHandlerImpl.kValueType;
2465
2466                if (!vhandler.isSequence(id)) {
2467                FullValueDescription fieldFVD = sender.meta(fields[i].id);
2468                if (kRemoteTypeCode == fields[i].type) {
2469
2470                    // RMI Object reference...
2471
callType = ValueHandlerImpl.kRemoteType;
2472                } else if (fieldFVD.is_abstract) {
2473                    // RMI Abstract Object reference...
2474

2475                    callType = ValueHandlerImpl.kAbstractType;
2476                }
2477                }
2478                                        
2479                // Now that we have used the FVD of the field to determine the proper course
2480
// of action, it is ok to use the type (Class) from this point forward since
2481
// the rep. id for this read will also follow on the wire.
2482

2483                switch (callType) {
2484                case ValueHandlerImpl.kRemoteType:
2485                orbStream.read_Object();
2486                break;
2487                case ValueHandlerImpl.kAbstractType:
2488                orbStream.read_abstract_interface();
2489                break;
2490                case ValueHandlerImpl.kValueType:
2491                if (type != null) {
2492                    orbStream.read_value(type);
2493                } else {
2494                    orbStream.read_value();
2495                }
2496                break;
2497                            default:
2498                // XXX I18N, logging needed.
2499
throw new StreamCorruptedException JavaDoc("Unknown callType: "
2500                                                                   + callType);
2501                }
2502            }
2503                                        
2504            }
2505            catch(IndirectionException JavaDoc cdrie) {
2506            // Since we are throwing this away, don't bother handling recursion.
2507
continue;
2508            }
2509                                    
2510            break;
2511                default:
2512            // XXX I18N, logging needed.
2513
throw new StreamCorruptedException JavaDoc("Unknown kind: "
2514                                                       + fields[i].type.kind().value());
2515
2516        }
2517        } catch (IllegalArgumentException JavaDoc e) {
2518        /* This case should never happen. If the field types
2519           are not the same, InvalidClassException is raised when
2520           matching the local class to the serialized ObjectStreamClass. */

2521        // XXX I18N, logging needed.
2522
ClassCastException JavaDoc cce = new ClassCastException JavaDoc("Assigning instance of class " +
2523            fields[i].id + " to field " + currentClassDesc.getName() +
2524            '#' + fields[i].name);
2525        cce.initCause(e) ;
2526        throw cce ;
2527        }
2528    }
2529        
2530    }
2531
2532    private static void setObjectField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, Object JavaDoc v)
2533    {
2534    try {
2535        Field fld = c.getDeclaredField( fieldName ) ;
2536        long key = bridge.objectFieldOffset( fld ) ;
2537        bridge.putObject( o, key, v ) ;
2538    } catch (Exception JavaDoc e) {
2539        throw utilWrapper.errorSetObjectField( e, fieldName,
2540        ObjectUtility.compactObjectToString( o ),
2541        ObjectUtility.compactObjectToString( v )) ;
2542    }
2543    }
2544
2545    private static void setBooleanField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, boolean v)
2546    {
2547    try {
2548        Field fld = c.getDeclaredField( fieldName ) ;
2549        long key = bridge.objectFieldOffset( fld ) ;
2550        bridge.putBoolean( o, key, v ) ;
2551    } catch (Exception JavaDoc e) {
2552        throw utilWrapper.errorSetBooleanField( e, fieldName,
2553        ObjectUtility.compactObjectToString( o ),
2554        new Boolean JavaDoc(v) ) ;
2555    }
2556    }
2557
2558    private static void setByteField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, byte v)
2559    {
2560    try {
2561        Field fld = c.getDeclaredField( fieldName ) ;
2562        long key = bridge.objectFieldOffset( fld ) ;
2563        bridge.putByte( o, key, v ) ;
2564    } catch (Exception JavaDoc e) {
2565        throw utilWrapper.errorSetByteField( e, fieldName,
2566        ObjectUtility.compactObjectToString( o ),
2567        new Byte JavaDoc(v) ) ;
2568    }
2569    }
2570
2571    private static void setCharField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, char v)
2572    {
2573    try {
2574        Field fld = c.getDeclaredField( fieldName ) ;
2575        long key = bridge.objectFieldOffset( fld ) ;
2576        bridge.putChar( o, key, v ) ;
2577    } catch (Exception JavaDoc e) {
2578        throw utilWrapper.errorSetCharField( e, fieldName,
2579        ObjectUtility.compactObjectToString( o ),
2580        new Character JavaDoc(v) ) ;
2581    }
2582    }
2583
2584    private static void setShortField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, short v)
2585    {
2586    try {
2587        Field fld = c.getDeclaredField( fieldName ) ;
2588        long key = bridge.objectFieldOffset( fld ) ;
2589        bridge.putShort( o, key, v ) ;
2590    } catch (Exception JavaDoc e) {
2591        throw utilWrapper.errorSetShortField( e, fieldName,
2592        ObjectUtility.compactObjectToString( o ),
2593        new Short JavaDoc(v) ) ;
2594    }
2595    }
2596
2597    private static void setIntField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, int v)
2598    {
2599    try {
2600        Field fld = c.getDeclaredField( fieldName ) ;
2601        long key = bridge.objectFieldOffset( fld ) ;
2602        bridge.putInt( o, key, v ) ;
2603    } catch (Exception JavaDoc e) {
2604        throw utilWrapper.errorSetIntField( e, fieldName,
2605        ObjectUtility.compactObjectToString( o ),
2606        new Integer JavaDoc(v) ) ;
2607    }
2608    }
2609
2610    private static void setLongField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, long v)
2611    {
2612    try {
2613        Field fld = c.getDeclaredField( fieldName ) ;
2614        long key = bridge.objectFieldOffset( fld ) ;
2615        bridge.putLong( o, key, v ) ;
2616    } catch (Exception JavaDoc e) {
2617        throw utilWrapper.errorSetLongField( e, fieldName,
2618        ObjectUtility.compactObjectToString( o ),
2619        new Long JavaDoc(v) ) ;
2620    }
2621    }
2622
2623    private static void setFloatField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, float v)
2624    {
2625    try {
2626        Field fld = c.getDeclaredField( fieldName ) ;
2627        long key = bridge.objectFieldOffset( fld ) ;
2628        bridge.putFloat( o, key, v ) ;
2629    } catch (Exception JavaDoc e) {
2630        throw utilWrapper.errorSetFloatField( e, fieldName,
2631        ObjectUtility.compactObjectToString( o ),
2632        new Float JavaDoc(v) ) ;
2633    }
2634    }
2635
2636    private static void setDoubleField(Object JavaDoc o, Class JavaDoc c, String JavaDoc fieldName, double v)
2637    {
2638    try {
2639        Field fld = c.getDeclaredField( fieldName ) ;
2640        long key = bridge.objectFieldOffset( fld ) ;
2641        bridge.putDouble( o, key, v ) ;
2642    } catch (Exception JavaDoc e) {
2643        throw utilWrapper.errorSetDoubleField( e, fieldName,
2644        ObjectUtility.compactObjectToString( o ),
2645        new Double JavaDoc(v) ) ;
2646    }
2647    }
2648
2649    /**
2650     * This class maintains a map of stream position to
2651     * an Object currently being deserialized. It is used
2652     * to handle the cases where the are indirections to
2653     * an object on the recursion stack. The CDR level
2654     * handles indirections to objects previously seen
2655     * (and completely deserialized) in the stream.
2656     */

2657    static class ActiveRecursionManager
2658    {
2659        private Map offsetToObjectMap;
2660        
2661        public ActiveRecursionManager() {
2662            // A hash map is unsynchronized and allows
2663
// null values
2664
offsetToObjectMap = new HashMap();
2665        }
2666
2667        // Called right after allocating a new object.
2668
// Offset is the starting position in the stream
2669
// of the object.
2670
public void addObject(int offset, Object JavaDoc value) {
2671            offsetToObjectMap.put(new Integer JavaDoc(offset), value);
2672        }
2673
2674        // If the given starting position doesn't refer
2675
// to the beginning of an object currently being
2676
// deserialized, this throws an IOException.
2677
// Otherwise, it returns a reference to the
2678
// object.
2679
public Object JavaDoc getObject(int offset) throws IOException JavaDoc {
2680            Integer JavaDoc position = new Integer JavaDoc(offset);
2681
2682            if (!offsetToObjectMap.containsKey(position))
2683        // XXX I18N, logging needed.
2684
throw new IOException JavaDoc("Invalid indirection to offset "
2685                                      + offset);
2686
2687            return offsetToObjectMap.get(position);
2688        }
2689        
2690        // Called when an object has been completely
2691
// deserialized, so it should no longer be in
2692
// this mapping. The CDR level can handle
2693
// further indirections.
2694
public void removeObject(int offset) {
2695            offsetToObjectMap.remove(new Integer JavaDoc(offset));
2696        }
2697
2698        // If the given offset doesn't map to an Object,
2699
// then it isn't an indirection to an object
2700
// currently being deserialized.
2701
public boolean containsObject(int offset) {
2702            return offsetToObjectMap.containsKey(new Integer JavaDoc(offset));
2703        }
2704    }
2705}
2706
Popular Tags