KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > orb > CDRInputStream


1 package org.jacorb.orb;
2
3 /*
4  * JacORB - a free Java ORB
5  *
6  * Copyright (C) 1997-2004 Gerald Brose.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */

22
23 import java.io.IOException JavaDoc;
24 import java.util.*;
25
26 import org.apache.avalon.framework.configuration.*;
27 import org.apache.avalon.framework.logger.*;
28
29 import org.jacorb.orb.giop.CodeSet;
30 import org.jacorb.util.ValueHandler;
31 import org.jacorb.ir.RepositoryID;
32
33 import org.omg.CORBA.BAD_PARAM JavaDoc;
34 import org.omg.CORBA.INTERNAL JavaDoc;
35 import org.omg.CORBA.MARSHAL JavaDoc;
36 import org.omg.CORBA.NO_IMPLEMENT JavaDoc;
37 import org.omg.CORBA.StructMember JavaDoc;
38 import org.omg.CORBA.TCKind JavaDoc;
39 import org.omg.CORBA.UnionMember JavaDoc;
40 import org.omg.CORBA.ValueMember JavaDoc;
41 import org.omg.CORBA.portable.IDLEntity JavaDoc;
42 import org.omg.CORBA.TypeCodePackage.BadKind JavaDoc;
43 import org.omg.CORBA.TypeCodePackage.Bounds JavaDoc;
44
45 /**
46  * Read CDR encoded data
47  *
48  * @author Gerald Brose, FU Berlin
49  * $Id: CDRInputStream.java,v 1.89 2005/04/23 13:07:29 phil.mesnier Exp $
50  */

51
52 public class CDRInputStream
53     extends org.omg.CORBA_2_3.portable.InputStream JavaDoc
54 {
55     /**
56      * <code>uniqueValue</code> is used to fill in a value for empty
57      * member names.
58      */

59     private int uniqueValue;
60
61     /**
62      * <code>encaps_stack</code> is used to saving/restoring
63      * encapsulation information. Do NOT access this variable directly.
64      * It is initialized on demand. Use the method {@link #getEncapsStack()}
65      */

66     private Stack encaps_stack;
67
68     /**
69      * <code>recursiveTCMap</code> is used to to remember the original
70      * TCs for a given ID that is used in a recursive/repeated TC. Do
71      * NOT access this variable directly. It is initialized on demand.
72      * Use the method {@link #getRecursiveTCMap()}
73      */

74     private Map recursiveTCMap;
75
76     /**
77      * <code>cachedTypecodes</code> stores a mapping of ID/Typecode to
78      * speed reading from the stream. Do NOT access this variable directly. It
79      * is initialized on demand. Use the methods
80      * {@link #getCachedTypecode(String id)} and
81      * {@link #putCachedTypecode(String id, org.omg.CORBA.TypeCode result)}
82      * Skip amount is
83      * skip (size - ((pos - start_pos) - 4 - 4));
84      * EncapsulationSize -
85      * ( PositionAfterReadingId - start_pos
86      * - 4 [Size] - 4 [KindSize] ) = RemainingSizeToSkip
87      */

88     private Map cachedTypecodes;
89
90     /** indexes to support mark/reset */
91     private int marked_pos;
92     private int marked_index;
93
94     private boolean closed;
95
96     /** configurable properties */
97     private Logger logger;
98     private boolean useBOM;
99     private boolean cometInteropFix;
100     private boolean laxBooleanEncoding;
101     private boolean cacheTypecodes;
102
103     /* character encoding code sets for char and wchar, default ISO8859_1 */
104     private int codeSet = CodeSet.getTCSDefault();
105     private int codeSetW = CodeSet.getTCSWDefault();
106     protected int giop_minor = 2; // needed to determine size in chars
107

108     /**
109      * <code>valueMap</code> maps indices within the buffer
110      * (java.lang.Integer) to the values that appear at these indices. Do
111      * NOT access this variable directly. It is initialized on demand.
112      * Use the method {@link #getValueMap()}
113      */

114     private Map valueMap;
115
116     /**
117      * Index of the current IDL value that is being unmarshalled.
118      * This is kept here so that when the value object has been
119      * created, the value factory can immediately store it into this
120      * stream's valueMap by calling `register_value()'.
121      */

122     private int currentValueIndex;
123
124     /**
125      * <code>repIdMap</code> maps indices within the buffer
126      * (java.lang.Integer) to repository ids that appear at these indices.
127      * Do NOT access this variable directly. It is initialized on demand.
128      * Use the method {@link #getRepIdMap()}
129      */

130     private Map repIdMap;
131
132     /**
133      * <code>codebaseMap</code> maps indices within the buffer
134      * (java.lang.Integer) to codebase strings that appear at these indices.
135      * Do NOT access this variable directly. It is initialized on demand.
136      * Use the method {@link #getCodebaseMap()}
137      */

138     private Map codebaseMap;
139
140     public boolean littleEndian = false;
141
142     /** indices into the actual buffer */
143     protected byte[] buffer = null;
144     protected int pos = 0;
145     protected int index = 0;
146
147     /** Last value tag read had the chunking bit on */
148     private boolean chunkedValue = false;
149
150     /** Nesting level of chunked valuetypes */
151     private int valueNestingLevel = 0;
152
153     /** Ending position of the current chunk */
154     private int chunk_end_pos = -1; // -1 means we're not within a chunk
155

156
157     /**
158      * for this stream to be able to return a live object reference, a
159      * full ORB (not the Singleton!) must be known. If this stream is
160      * used only to demarshal base type data, the Singleton is enough
161      */

162     private org.omg.CORBA.ORB JavaDoc orb = null;
163
164     public CDRInputStream(final org.omg.CORBA.ORB JavaDoc orb, final byte[] buf)
165     {
166         buffer = buf;
167         // orb may be null!
168
if (orb != null)
169         {
170             this.orb = orb;
171             // orb may be the singleton!
172
if (orb instanceof org.jacorb.orb.ORB)
173             {
174                 try
175                 {
176
177                     configure(((org.jacorb.orb.ORB)orb).getConfiguration());
178                 }
179                 catch( ConfigurationException ce )
180                 {
181                     throw new INTERNAL JavaDoc("ConfigurationException: " + ce.getMessage());
182                 }
183             }
184         }
185         else
186             this.orb = org.omg.CORBA.ORB.init();
187     }
188
189     public CDRInputStream(final org.omg.CORBA.ORB JavaDoc orb,
190                           final byte[] buf,
191                           final boolean littleEndian )
192     {
193         this( orb, buf );
194         this.littleEndian = littleEndian;
195     }
196
197
198     /**
199      * This stream is self-configuring, i.e. configure() is private
200      * and only called from the constructors.
201      */

202
203     private void configure(Configuration configuration)
204         throws ConfigurationException
205     {
206         logger =
207             ((org.jacorb.config.Configuration)configuration).getNamedLogger("jacorb.orb.cdr");
208
209         useBOM =
210             configuration.getAttribute("jacorb.use_bom","off").equals("on");
211         cometInteropFix =
212             configuration.getAttribute("jacorb.interop.comet","off").equals("on");
213         laxBooleanEncoding =
214             configuration.getAttribute("jacorb.interop.lax_boolean_encoding","off").equals("on");
215         cacheTypecodes =
216             configuration.getAttribute("jacorb.cacheTypecodes","off").equals("on");
217     }
218
219
220
221
222     /**
223      * <code>getEncapsStack</code> is used to initialize encaps_stack
224      * on demand.
225      *
226      * @return a <code>Stack</code> value
227      */

228     private Stack getEncapsStack()
229     {
230         if (encaps_stack == null)
231         {
232             encaps_stack = new Stack();
233         }
234         return encaps_stack;
235     }
236
237
238     /**
239      * Gets the Map that keeps track of recursive TypeCodes.
240      *
241      * @return a <code>Map</code> value
242      */

243     private Map getRecursiveTCMap()
244     {
245         if (recursiveTCMap == null)
246         {
247             recursiveTCMap = new HashMap();
248         }
249         return recursiveTCMap;
250     }
251
252
253     /**
254      * Gets the Map that is used to demarshal shared valuetype instances.
255      *
256      * @return a <code>Map</code> value
257      */

258     private Map getValueMap()
259     {
260         if (valueMap == null)
261         {
262             // Unlike the valueMap in CDROutputStream, this one
263
// does need to be an equality-based HashMap.
264
valueMap = new HashMap();
265         }
266         return valueMap;
267     }
268
269
270     /**
271      * Gets the Map that is used to implement indirections for RepositoryIDs.
272      *
273      * @return a <code>Map</code> value
274      */

275     private Map getRepIdMap()
276     {
277         if (repIdMap == null)
278         {
279             repIdMap = new HashMap();
280         }
281         return repIdMap;
282     }
283
284
285     /**
286      * Gets the Map that is used to implement sharing for codebase
287      * specifications.
288      *
289      * @return a <code>Map</code> value
290      */

291     private Map getCodebaseMap()
292     {
293         if (codebaseMap == null)
294         {
295             codebaseMap = new HashMap();
296         }
297         return codebaseMap;
298     }
299
300
301     /**
302      * <code>getCachedTypecode</code> to retrieve a value from cachedTypecodes.
303      * It may initialize the value on demand.
304      *
305      * @param id a <code>String</code> value
306      * @return a <code>org.omg.CORBA.TypeCode</code> value, possibly null.
307      */

308     private org.omg.CORBA.TypeCode JavaDoc getCachedTypecode( String JavaDoc id )
309     {
310         org.omg.CORBA.TypeCode JavaDoc result = null;
311
312         if ( cacheTypecodes )
313         {
314             if ( cachedTypecodes == null )
315             {
316                 cachedTypecodes = new HashMap();
317             }
318             else
319             {
320                 result = ( org.omg.CORBA.TypeCode JavaDoc )cachedTypecodes.get( id );
321             }
322         }
323         return result;
324     }
325
326
327     /**
328      * <code>putCachedTypecode</code> is used to store typecodes within the
329      * cachedTypecodes. It will only do it cacheTypecodes is on.
330      *
331      * @param id a <code>String</code> value
332      * @param result an <code>org.omg.CORBA.TypeCode</code> value
333      */

334     private void putCachedTypecode( String JavaDoc id, org.omg.CORBA.TypeCode JavaDoc result)
335     {
336         if ( cacheTypecodes )
337         {
338             // By definition get/put should be paired so cachedTypecodes should
339
// never be null here.
340
cachedTypecodes.put (id, result);
341         }
342     }
343
344
345     public void setGIOPMinor(final int giop_minor )
346     {
347         this.giop_minor = giop_minor;
348     }
349
350     public int getGIOPMinor()
351     {
352         return giop_minor;
353     }
354
355     public void close()
356         throws IOException JavaDoc
357     {
358         // Don't need to call super.close as super is noop.
359
if( closed )
360         {
361             return;
362         }
363
364         BufferManager.getInstance().returnBuffer(buffer);
365
366         encaps_stack = null;
367         recursiveTCMap = null;
368         closed = true;
369     }
370
371     public org.omg.CORBA.ORB JavaDoc orb()
372     {
373         if (orb == null) orb = org.omg.CORBA.ORB.init(new String JavaDoc[]{}, null);
374         return orb;
375     }
376
377     public void setCodeSet(final int codeSet, final int codeSetWide)
378     {
379         this.codeSet = codeSet;
380         this.codeSetW = codeSetWide;
381     }
382
383     private static final int _read4int
384        (final boolean _littleEndian, final byte[] _buffer, final int _pos)
385     {
386         if (_littleEndian)
387             return (((_buffer[_pos+3] & 0xff) << 24) +
388                     ((_buffer[_pos+2] & 0xff) << 16) +
389                     ((_buffer[_pos+1] & 0xff) << 8) +
390                     ((_buffer[_pos] & 0xff) << 0));
391         else
392             return (((_buffer[_pos] & 0xff) << 24) +
393                     ((_buffer[_pos+1] & 0xff) << 16) +
394                     ((_buffer[_pos+2] & 0xff) << 8) +
395                     ((_buffer[_pos+3] & 0xff) << 0));
396     }
397
398     private static final short _read2int
399        (final boolean _littleEndian, final byte[] _buffer, final int _pos)
400     {
401         if (_littleEndian)
402             return (short)(((_buffer[_pos+1] & 0xff) << 8) +
403                             ((_buffer[_pos] & 0xff) << 0));
404         else
405             return (short)(((_buffer[_pos ] & 0xff) << 8) +
406                            ((_buffer[_pos + 1] & 0xff) << 0));
407     }
408
409     private final int _read_long()
410     {
411         int result;
412
413         result = _read4int (littleEndian, buffer, pos);
414
415         index += 4;
416         pos += 4;
417         return result;
418     }
419
420     private final long _read_longlong()
421     {
422         if (littleEndian)
423         {
424             return ((long) _read_long() & 0xFFFFFFFFL) + ((long) _read_long() << 32);
425         }
426         else
427         {
428             return ((long) _read_long() << 32) + ((long) _read_long() & 0xFFFFFFFFL);
429         }
430     }
431
432     private final void handle_chunking()
433     {
434         int remainder = 4 - (index % 4);
435         int aligned_pos = (remainder != 4) ? pos + remainder : pos;
436
437         if (chunk_end_pos >= pos && chunk_end_pos <= aligned_pos)
438         {
439             chunk_end_pos = -1;
440             int saved_pos = pos;
441             int saved_index = index;
442             int tag = read_long();
443
444             if (tag < 0) {
445
446                 // tag is an end tag
447

448                 if ( ! (-tag <= valueNestingLevel))
449                 {
450                     throw new INTERNAL JavaDoc
451                     (
452                         "received end tag " + tag +
453                         " with value nesting level " +
454                         valueNestingLevel
455                     );
456                 }
457                 valueNestingLevel = - tag;
458                 valueNestingLevel--;
459
460                 if (valueNestingLevel > 0)
461                 {
462                     chunk_end_pos = pos;
463                     handle_chunking();
464                 }
465             }
466             else if (tag < 0x7fffff00)
467             {
468                 // tag is the chunk size tag of another chunk
469

470                 chunk_end_pos = pos + tag;
471             }
472             else // (tag >= 0x7fffff00)
473
{
474                 // tag is the value tag of a nested value
475

476                 pos = saved_pos; // "unread" the value tag
477
index = saved_index;
478             }
479         }
480     }
481
482     protected final void skip(final int distance)
483     {
484         pos += distance;
485         index += distance;
486     }
487
488     /**
489      * close a CDR encapsulation and
490      * restore index and byte order information
491      */

492
493     public final void closeEncapsulation()
494     {
495         if (encaps_stack == null)
496         {
497             throw new MARSHAL JavaDoc( "Internal Error - closeEncapsulation failed" );
498         }
499
500         EncapsInfo ei = (EncapsInfo)encaps_stack.pop();
501         littleEndian = ei.littleEndian;
502         int size = ei.size;
503         int start = ei.start;
504
505         if( pos < start + size )
506             pos = start + size;
507
508         index = ei.index + size;
509     }
510
511     /**
512      * open a CDR encapsulation and
513      * restore index and byte order information
514      */

515
516     public final int openEncapsulation()
517     {
518         boolean old_endian = littleEndian;
519         int _pos = pos;
520         int size = read_long();
521
522         // Check if size looks sane. If not try changing byte order.
523
// This is a specific fix for interoperability with the Iona
524
// Comet COM/CORBA bridge that has problems with size marshalling.
525

526         if (cometInteropFix && ((size < 0) || (size > buffer.length)))
527         {
528             int temp =
529             (
530                 ((size >> 24) & 0x000000FF) +
531                 ((size >> 8) & 0x0000FF00) +
532                 ((size << 8) & 0x00FF0000) +
533                 ((size << 24) & 0xFF000000)
534             );
535
536             if (logger.isDebugEnabled())
537             {
538                 logger.debug("Size of CDR encapsulation larger than buffer, swapping byte order\n" +
539                              "Size of CDR encapsulation was " + size + ", is now " + temp);
540             }
541
542             size = temp;
543         }
544         /* save current index plus size of the encapsulation on the stack.
545            When the encapsulation is closed, this value will be restored as
546            index */

547
548         if (encaps_stack == null)
549         {
550             encaps_stack = new Stack();
551         }
552         encaps_stack.push(new EncapsInfo(old_endian, index, pos, size ));
553
554         openEncapsulatedArray();
555
556         return size;
557     }
558
559     public final void openEncapsulatedArray()
560     {
561         /* reset index to zero, i.e. align relative to the beginning
562            of the encaps. */

563         resetIndex();
564         littleEndian = read_boolean();
565     }
566
567
568     /*
569      * Return a copy of the current buffer. Currently only used by ProxyImpl.
570      *
571      * @return a <code>byte[]</code> value.
572      */

573     public byte[] getBufferCopy()
574     {
575         byte[] result = new byte[buffer.length];
576         System.arraycopy
577         (
578             buffer,
579             0,
580             result,
581             0,
582             buffer.length
583         );
584         return result;
585     }
586
587     /**
588      * Reads the next byte of data from the input stream. The value byte is
589      * returned as an <code>int</code> in the range <code>0</code> to
590      * <code>255</code>. If no byte is available because the end of the stream
591      * has been reached, the value <code>-1</code> is returned.
592      * @return the next byte of data, or <code>-1</code> if the end of the
593      * stream is reached.
594      * @throws java.io.IOException if stream is closed.
595      */

596     public int read()
597         throws java.io.IOException JavaDoc
598     {
599         if( closed )
600             throw new java.io.IOException JavaDoc("Stream already closed!");
601
602         if( available() < 1 )
603             return -1;
604
605         ++index;
606         return buffer[pos++]; // read_index++];
607
}
608
609     /**
610      * @return the number of bytes that can be read (or skipped over) from this
611      * input stream. This is not necessarily the number of 'valid' bytes.
612      */

613     public int available()
614     {
615         return buffer.length - index;
616     }
617
618     /**
619      * Has the effect of read(b, 0, b.length);
620      * @see #read
621      */

622     public int read(final byte[] b)
623         throws java.io.IOException JavaDoc
624     {
625         return read(b, 0, b.length);
626     }
627
628     /**
629      * Performs as described by <code>java.io.InputStream.read(byte[], int, int)</code>,
630      * but never blocks.
631      */

632     public int read(final byte[] b, final int off, final int len)
633         throws java.io.IOException JavaDoc
634     {
635         if( b == null )
636             throw new NullPointerException JavaDoc();
637
638         if( off < 0 ||
639             len < 0 ||
640             off + len > b.length )
641             throw new IndexOutOfBoundsException JavaDoc();
642
643         if( len == 0 )
644             return 0;
645
646         if( available() < 1 )
647             return -1;
648
649         if( closed )
650             throw new java.io.IOException JavaDoc("Stream already closed!");
651
652         int min = ( len < available() ? len : available());
653         System.arraycopy(buffer, index, b, off, min );
654         pos += min;
655         index += min;
656         return min;
657     }
658
659
660     public final org.omg.CORBA.Any JavaDoc read_any()
661     {
662         org.omg.CORBA.TypeCode JavaDoc _tc = read_TypeCode();
663         org.omg.CORBA.Any JavaDoc any = orb.create_any();
664         any.read_value( this, _tc );
665         return any;
666     }
667
668     public final boolean read_boolean()
669     {
670         handle_chunking();
671         index++;
672         byte bb = buffer[pos++];
673
674         if (bb == 0)
675         {
676             return false;
677         }
678         else
679         {
680             if (bb == 1)
681             {
682                 return true;
683             }
684             else
685             {
686                 if (laxBooleanEncoding)
687                 {
688                     // Technically only valid values are 0 (false) and 1 (true)
689
// however some ORBs send values other than 1 for true.
690
return true;
691                 }
692                 else
693                 {
694                     throw new MARSHAL JavaDoc("Unexpected boolean value: " + bb
695                                       + " pos: " + pos + " index: " + index);
696                 }
697             }
698         }
699     }
700
701     /** arrays */
702
703     public final void read_boolean_array
704        (final boolean[] value, final int offset, final int length)
705     {
706         handle_chunking();
707         byte bb;
708         for (int j = offset; j < offset + length; j++)
709         {
710             index++;
711             bb = buffer[pos++];
712             if (bb == 1)
713             {
714                 value[j] = true;
715             }
716             else if (bb == 0)
717             {
718                 value[j] = false;
719             }
720             else
721             {
722                 throw new MARSHAL JavaDoc ("Unexpected boolean value: " + bb
723                                    + " pos: " + pos + " index: " + index);
724             }
725         }
726     }
727
728     public final char read_char()
729     {
730         handle_chunking();
731         index++;
732         return (char)(0xff & buffer[pos++]);
733     }
734
735     public final void read_char_array
736        (final char[] value, final int offset, final int length)
737     {
738         handle_chunking();
739         for (int j = offset; j < offset + length; j++)
740         {
741             index++;
742             value[j] = (char) (0xff & buffer[pos++]);
743         }
744     }
745
746     public final double read_double()
747     {
748         return Double.longBitsToDouble (read_longlong());
749     }
750
751     public final void read_double_array
752        (final double[] value, final int offset, final int length)
753     {
754         if (length == 0)
755             return;
756
757         handle_chunking();
758
759         int remainder = 8 - (index % 8);
760         if (remainder != 8)
761         {
762             index += remainder;
763             pos += remainder;
764         }
765
766         for (int j = offset; j < offset + length; j++)
767         {
768             value[j] = Double.longBitsToDouble (_read_longlong());
769         }
770     }
771
772     public final java.math.BigDecimal JavaDoc read_fixed()
773     {
774         handle_chunking();
775
776         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
777
778         int b = buffer[pos++];
779         int c = b & 0x0F; // second half byte
780
index++;
781
782         while(true)
783         {
784             c = (b & 0xF0) >>> 4;
785             sb.append(c );
786             c = b & 0x0F;
787             if( c == 0xC || c == 0xD )
788                 break;
789             sb.append(c );
790             b = buffer[pos++];
791             index++;
792         }
793
794         java.math.BigDecimal JavaDoc result =
795         new java.math.BigDecimal JavaDoc( new java.math.BigInteger JavaDoc( sb.toString()));
796
797         if( c == 0xD )
798             return result.negate();
799         else
800             return result;
801
802     }
803
804     public final float read_float()
805     {
806         return Float.intBitsToFloat (read_long());
807     }
808
809     public final void read_float_array
810        (final float[] value, final int offset, final int length)
811     {
812         if (length == 0)
813             return;
814
815         handle_chunking();
816
817         int remainder = 4 - (index % 4);
818         if (remainder != 4)
819         {
820             index += remainder;
821             pos += remainder;
822         }
823
824         for (int j = offset; j < offset + length; j++)
825         {
826             value[j] = Float.intBitsToFloat (_read_long());
827         }
828     }
829
830     public final int read_long()
831     {
832         handle_chunking();
833
834         int result;
835
836         int remainder = 4 - (index % 4);
837         if (remainder != 4)
838         {
839             index += remainder;
840             pos += remainder;
841         }
842
843         result = _read4int (littleEndian, buffer, pos);
844
845         index += 4;
846         pos += 4;
847         return result;
848     }
849
850     public final void read_long_array
851        (final int[] value, final int offset, final int length)
852     {
853         if (length == 0)
854             return;
855
856         handle_chunking();
857
858         int remainder = 4 - (index % 4);
859         if (remainder != 4)
860         {
861             index += remainder;
862             pos += remainder;
863         }
864
865         for (int j = offset; j < offset+length; j++)
866         {
867             value[j] = _read4int (littleEndian,buffer,pos);
868             pos += 4;
869         }
870
871         index += 4 * length;
872     }
873
874
875     public final long read_longlong()
876     {
877         handle_chunking();
878
879         int remainder = 8 - (index % 8);
880         if (remainder != 8)
881         {
882             index += remainder;
883             pos += remainder;
884         }
885
886         if (littleEndian)
887         {
888             return ((long) _read_long() & 0xFFFFFFFFL) + ((long) _read_long() << 32);
889         }
890         else
891         {
892             return ((long) _read_long() << 32) + ((long) _read_long() & 0xFFFFFFFFL);
893         }
894     }
895
896     public final void read_longlong_array
897         (final long[] value, final int offset, final int length)
898     {
899         if (length == 0)
900             return;
901
902         handle_chunking();
903
904         int remainder = 8 - (index % 8);
905         if (remainder != 8)
906         {
907             index += remainder;
908             pos += remainder;
909         }
910
911         if (littleEndian)
912         {
913             for(int j=offset; j < offset+length; j++)
914             {
915                 value[j] = ( (long) _read_long() & 0xFFFFFFFFL) +
916                     ((long) _read_long() << 32);
917             }
918         }
919         else
920         {
921             for(int j=offset; j < offset+length; j++)
922             {
923                 value[j] = ((long) _read_long() << 32) +
924                     ((long) _read_long() & 0xFFFFFFFFL);
925             }
926         }
927
928         // Do not need to modify pos and index as use read_long above
929
}
930
931     public final org.omg.CORBA.Object JavaDoc read_Object()
932     {
933         handle_chunking();
934
935         org.omg.IOP.IOR JavaDoc ior = org.omg.IOP.IORHelper.read(this);
936         ParsedIOR pior = new ParsedIOR( ior, (org.jacorb.orb.ORB)orb, logger );
937
938         if( pior.isNull() )
939         {
940             return null;
941         }
942         else
943         {
944             if( !(orb instanceof org.jacorb.orb.ORB))
945             {
946                 throw new MARSHAL JavaDoc( "Cannot use the singleton ORB to receive object references, please initialize a full ORB instead.");
947             }
948             else
949             {
950                 return ((org.jacorb.orb.ORB)orb)._getObject( pior );
951             }
952         }
953     }
954
955     public org.omg.CORBA.Object JavaDoc read_Object(final java.lang.Class JavaDoc clz)
956     {
957         if (org.omg.CORBA.portable.ObjectImpl JavaDoc.class.isAssignableFrom(clz))
958         {
959             org.omg.CORBA.Object JavaDoc obj = read_Object();
960             if (obj instanceof org.omg.CORBA.portable.ObjectImpl JavaDoc)
961             {
962                 org.omg.CORBA.portable.ObjectImpl JavaDoc stub = null;
963                 try
964                 {
965                     stub = (org.omg.CORBA.portable.ObjectImpl JavaDoc)clz.newInstance();
966                 }
967                 catch (InstantiationException JavaDoc e)
968                 {
969                     throw new MARSHAL JavaDoc("Exception in stub instantiation: " + e);
970                 }
971                 catch (IllegalAccessException JavaDoc e)
972                 {
973                     throw new MARSHAL JavaDoc("Exception in stub instantiation: " + e);
974                 }
975                 stub._set_delegate(
976                      ((org.omg.CORBA.portable.ObjectImpl JavaDoc)obj)._get_delegate());
977                 return stub;
978             }
979             else
980             {
981                 return obj;
982             }
983         }
984         else if (clz.isInterface() &&
985                  java.rmi.Remote JavaDoc.class.isAssignableFrom(clz))
986         {
987             return (org.omg.CORBA.Object JavaDoc)
988                 org.jacorb.util.ValueHandler.portableRemoteObject_narrow(
989                                                            read_Object(), clz);
990         }
991         else
992         {
993             return read_Object();
994         }
995     }
996
997     public final byte read_octet()
998     {
999         handle_chunking();
1000        index++;
1001        return buffer[pos++];
1002    }
1003
1004    public final void read_octet_array
1005        (final byte[] value, final int offset, final int length)
1006    {
1007        handle_chunking();
1008        System.arraycopy (buffer,pos,value,offset,length);
1009        index += length;
1010        pos += length;
1011    }
1012
1013    public final org.omg.CORBA.Principal JavaDoc read_Principal()
1014    {
1015        throw new NO_IMPLEMENT JavaDoc ("Principal deprecated");
1016    }
1017
1018    /**
1019     * Read methods for big-endian as well as little endian data input
1020     * contributed by Mark Allerton <MAllerton@img.seagatesoftware.com>
1021     */

1022
1023    public final short read_short()
1024    {
1025        handle_chunking();
1026
1027        int remainder = 2 - (index % 2);
1028        if (remainder != 2)
1029        {
1030            index += remainder;
1031            pos += remainder;
1032        }
1033
1034        short result = _read2int (littleEndian,buffer,pos);
1035        pos += 2;
1036        index += 2;
1037        return result;
1038    }
1039
1040    public final void read_short_array
1041        (final short[] value, final int offset, final int length)
1042    {
1043        if (length == 0)
1044            return;
1045
1046        handle_chunking();
1047
1048        int remainder = 2 - (index % 2);
1049
1050        if (remainder != 2)
1051        {
1052            index += remainder;
1053            pos += remainder;
1054        }
1055
1056        for (int j = offset; j < offset + length; j++)
1057        {
1058            value[j] = _read2int (littleEndian, buffer, pos);
1059            pos += 2;
1060        }
1061
1062        index += length * 2;
1063    }
1064
1065    public final String JavaDoc read_string()
1066    {
1067        String JavaDoc result = null;
1068
1069        handle_chunking();
1070
1071        int remainder = 4 - (index % 4);
1072        if( remainder != 4 )
1073        {
1074            index += remainder;
1075            pos += remainder;
1076        }
1077
1078        // read size (#bytes)
1079
int size = _read4int( littleEndian, buffer, pos);
1080        int start = pos + 4;
1081
1082        index += (size + 4);
1083        pos += (size + 4);
1084        String JavaDoc csname = CodeSet.csName(codeSet);
1085
1086        if ((size > 0) &&
1087            (buffer[ start + size - 1 ] == 0))
1088        {
1089            size --;
1090        }
1091        try {
1092          result = new String JavaDoc (buffer, start, size, csname);
1093        }
1094        catch (java.io.UnsupportedEncodingException JavaDoc ex) {
1095            if (logger != null && logger.isErrorEnabled()) {
1096                logger.error("Charset " + csname + " is unsupported");
1097                result = "";
1098            }
1099        }
1100        return result;
1101    }
1102
1103
1104    public final org.omg.CORBA.TypeCode JavaDoc read_TypeCode()
1105    {
1106        Map tcMap = new HashMap();
1107        org.omg.CORBA.TypeCode JavaDoc result = read_TypeCode( tcMap );
1108        tcMap = null;
1109
1110        return result;
1111    }
1112
1113    private final org.omg.CORBA.TypeCode JavaDoc read_TypeCode(final Map tcMap )
1114    {
1115        String JavaDoc id = null;
1116        String JavaDoc name = null;
1117        int member_count = 0;
1118        int length = 0;
1119        int size = 0;
1120        boolean byteorder = false;
1121        org.omg.CORBA.TypeCode JavaDoc result = null;
1122        org.omg.CORBA.TypeCode JavaDoc content_type = null;
1123        String JavaDoc[] member_names = null;
1124
1125        int kind = read_long();
1126        int start_pos = pos - 4;
1127
1128        if (logger != null && logger.isDebugEnabled())
1129        {
1130            logger.debug("Read Type code of kind " + kind + " at pos: " + start_pos);
1131        }
1132
1133        switch( kind )
1134        {
1135            case TCKind._tk_null:
1136            case TCKind._tk_void:
1137            case TCKind._tk_short:
1138            case TCKind._tk_long:
1139            case TCKind._tk_ushort:
1140            case TCKind._tk_ulong:
1141            case TCKind._tk_float:
1142            case TCKind._tk_double:
1143            case TCKind._tk_boolean:
1144            case TCKind._tk_char:
1145            case TCKind._tk_octet:
1146            case TCKind._tk_any:
1147            case TCKind._tk_TypeCode:
1148            case TCKind._tk_longlong:
1149            case TCKind._tk_ulonglong:
1150            case TCKind._tk_wchar:
1151            case TCKind._tk_Principal:
1152            {
1153                result = orb.get_primitive_tc
1154                    (org.omg.CORBA.TCKind.from_int (kind));
1155                break;
1156            }
1157            case TCKind._tk_objref:
1158            {
1159                size = openEncapsulation();
1160                id = validateID (read_string());
1161                result = getCachedTypecode( id );
1162
1163                if (result != null)
1164                {
1165                    // Skip buffer - see cachedTypecodes for calculation.
1166
skip (size - ((pos - start_pos) - 4 - 4));
1167                }
1168                else
1169                {
1170                    name = validateName (read_string());
1171                    result = orb.create_interface_tc (id, name);
1172                    putCachedTypecode( id, result );
1173                }
1174                closeEncapsulation();
1175                break;
1176            }
1177            case TCKind._tk_struct:
1178            {
1179                size = openEncapsulation();
1180                id = validateID (read_string());
1181                result = getCachedTypecode( id );
1182
1183                if (result != null)
1184                {
1185                    // Skip buffer - see cachedTypecodes for calculation.
1186
skip (size - ((pos - start_pos) - 4 - 4));
1187                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1188                }
1189                else
1190                {
1191                    name = validateName (read_string());
1192                    member_count = read_long();
1193
1194                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1195
1196                    StructMember JavaDoc[] struct_members = new StructMember JavaDoc[member_count];
1197                    for( int i = 0; i < member_count; i++)
1198                    {
1199                        struct_members[i] = new StructMember JavaDoc
1200                        (
1201                            validateMember (read_string()),
1202                            read_TypeCode (tcMap),
1203                            null
1204                        );
1205                    }
1206                    result = orb.create_struct_tc (id, name, struct_members);
1207                    putCachedTypecode( id, result );
1208                }
1209                getRecursiveTCMap().put (id, result);
1210                closeEncapsulation();
1211                break;
1212            }
1213            case TCKind._tk_except:
1214            {
1215                size = openEncapsulation();
1216                id = validateID (read_string());
1217                result = getCachedTypecode( id );
1218
1219                if (result != null)
1220                {
1221                    // Skip buffer - see cachedTypecodes for calculation.
1222
skip (size - ((pos - start_pos) - 4 - 4));
1223                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1224                }
1225                else
1226                {
1227                    name = validateName (read_string());
1228                    member_count = read_long();
1229
1230                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1231
1232                    StructMember JavaDoc[] members = new StructMember JavaDoc[member_count];
1233                    for( int i = 0; i < member_count; i++)
1234                    {
1235                        members[i] = new StructMember JavaDoc
1236                        (
1237                            validateMember (read_string()),
1238                            read_TypeCode(),
1239                            null
1240                        );
1241                    }
1242                    result = orb.create_struct_tc (id, name, members);
1243                    putCachedTypecode( id, result );
1244                }
1245                getRecursiveTCMap().put (id, result);
1246                closeEncapsulation();
1247                break;
1248            }
1249            case TCKind._tk_enum:
1250            {
1251                size = openEncapsulation();
1252                id = validateID (read_string());
1253                result = getCachedTypecode( id );
1254
1255                if (result != null)
1256                {
1257                    skip (size - ((pos - start_pos) - 4 - 4));
1258                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1259                }
1260                else
1261                {
1262                    name = validateName (read_string());
1263                    member_count = read_long();
1264
1265                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1266
1267                    member_names = new String JavaDoc[member_count];
1268                    for( int i = 0; i < member_count; i++)
1269                    {
1270                        member_names[i] = validateMember (read_string());
1271                    }
1272                    result = orb.create_enum_tc (id, name, member_names);
1273                    putCachedTypecode( id, result );
1274                }
1275                getRecursiveTCMap().put (id, result);
1276                closeEncapsulation();
1277                break;
1278            }
1279            case TCKind._tk_union:
1280            {
1281                size = openEncapsulation();
1282                id = validateID (read_string());
1283                result = getCachedTypecode( id );
1284
1285                if (result != null)
1286                {
1287                    // Skip buffer - see cachedTypecodes for calculation.
1288
skip (size - ((pos - start_pos) - 4 - 4));
1289                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1290                }
1291                else
1292                {
1293                    name = validateName (read_string());
1294
1295                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1296
1297                    org.omg.CORBA.TypeCode JavaDoc discriminator_type = read_TypeCode(tcMap);
1298                    // Use the dealiased discriminator type for the label types.
1299
// This works because the JacORB IDL compiler ignores any aliasing
1300
// of label types and only the discriminator type is passed on the
1301
// wire.
1302
org.omg.CORBA.TypeCode JavaDoc orig_disc_type =
1303                    TypeCode.originalType(discriminator_type);
1304
1305                    int default_index = read_long();
1306                    member_count = read_long();
1307
1308                    UnionMember JavaDoc[] union_members = new UnionMember JavaDoc[member_count];
1309                    for( int i = 0; i < member_count; i++)
1310                    {
1311                        org.omg.CORBA.Any JavaDoc label = orb.create_any();
1312
1313                        if( i == default_index )
1314                        {
1315                            // Default discriminator
1316
label.insert_octet( read_octet());
1317                        }
1318                        else
1319                        {
1320                            // use the dealiased discriminator type to construct labels
1321
label.read_value( this, orig_disc_type );
1322                        }
1323
1324                        union_members[i] = new UnionMember JavaDoc
1325                        (
1326                            validateMember (read_string()),
1327                            label,
1328                            read_TypeCode(tcMap),
1329                            null
1330                        );
1331                    }
1332
1333                    result = orb.create_union_tc
1334                        (id, name, discriminator_type, union_members);
1335                    putCachedTypecode( id, result );
1336                }
1337                getRecursiveTCMap().put (id, result);
1338                closeEncapsulation();
1339                break;
1340            }
1341            case TCKind._tk_string:
1342            {
1343                result = orb.create_string_tc(read_long());
1344                break;
1345            }
1346            case TCKind._tk_wstring:
1347            {
1348                result = orb.create_wstring_tc(read_long());
1349                break;
1350            }
1351            case TCKind._tk_fixed:
1352            {
1353                result = orb.create_fixed_tc(read_ushort(), read_short() );
1354                break;
1355            }
1356            case TCKind._tk_array:
1357            {
1358                openEncapsulation();
1359
1360                content_type = read_TypeCode(tcMap);
1361                length = read_long();
1362
1363                closeEncapsulation();
1364                result = orb.create_array_tc(length, content_type);
1365                break;
1366            }
1367            case TCKind._tk_sequence:
1368            {
1369                openEncapsulation();
1370
1371                content_type = read_TypeCode(tcMap);
1372                length = read_long();
1373
1374                closeEncapsulation();
1375
1376                result = orb.create_sequence_tc(length, content_type);
1377                break;
1378            }
1379            case TCKind._tk_alias:
1380            {
1381                size = openEncapsulation();
1382                id = validateID (read_string());
1383                result = getCachedTypecode( id );
1384
1385                if (result != null)
1386                {
1387                    // Skip buffer - see cachedTypecodes for calculation.
1388
skip (size - ((pos - start_pos) - 4 - 4));
1389                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1390                }
1391                else
1392                {
1393                    name = validateName (read_string());
1394
1395                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1396
1397                    content_type = read_TypeCode( tcMap );
1398                    result = orb.create_alias_tc (id, name, content_type );
1399                    putCachedTypecode( id, result );
1400                }
1401                getRecursiveTCMap().put (id , result);
1402                closeEncapsulation();
1403                break;
1404            }
1405            case TCKind._tk_value:
1406            {
1407                size = openEncapsulation();
1408                id = validateID (read_string());
1409                result = getCachedTypecode( id );
1410
1411                if (result != null)
1412                {
1413                    skip (size - ((pos - start_pos) - 4 - 4));
1414                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1415                }
1416                else
1417                {
1418                    name = validateName (read_string());
1419
1420                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1421
1422                    short type_modifier = read_short();
1423                    org.omg.CORBA.TypeCode JavaDoc concrete_base_type = read_TypeCode( tcMap );
1424                    member_count = read_long();
1425                    ValueMember JavaDoc[] vMembers = new ValueMember JavaDoc[member_count];
1426
1427                    for( int i = 0; i < member_count; i++)
1428                    {
1429                        vMembers[i] = new ValueMember JavaDoc
1430                        (
1431                            validateMember (read_string()),
1432                            null, // id
1433
null, // defined_in
1434
null, // version
1435
read_TypeCode (tcMap),
1436                            null, // type_def
1437
read_short()
1438                        );
1439                    }
1440                    result = orb.create_value_tc
1441                        (id, name, type_modifier, concrete_base_type, vMembers);
1442                    putCachedTypecode( id, result );
1443                }
1444                getRecursiveTCMap().put( id , result );
1445                closeEncapsulation();
1446                break;
1447            }
1448            case TCKind._tk_value_box:
1449            {
1450                size = openEncapsulation();
1451                id = validateID (read_string());
1452                result = getCachedTypecode( id );
1453
1454                if (result != null)
1455                {
1456                    // Skip buffer - see cachedTypecodes for calculation.
1457
skip (size - ((pos - start_pos) - 4 - 4));
1458                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1459                }
1460                else
1461                {
1462                    name = validateName (read_string());
1463
1464                    tcMap.put( new Integer JavaDoc( start_pos ), id );
1465
1466                    content_type = read_TypeCode( tcMap );
1467                    result = orb.create_value_box_tc (id, name, content_type);
1468                    putCachedTypecode( id, result );
1469                }
1470                getRecursiveTCMap().put( id , result );
1471                closeEncapsulation();
1472                break;
1473            }
1474            case TCKind._tk_abstract_interface:
1475            {
1476                size = openEncapsulation();
1477                id = validateID (read_string());
1478                result = getCachedTypecode( id );
1479
1480                if (result != null)
1481                {
1482                    // Skip buffer - see cachedTypecodes for calculation.
1483
skip (size - ((pos - start_pos) - 4 - 4));
1484                }
1485                else
1486                {
1487                    name = validateName (read_string());
1488                    result = orb.create_abstract_interface_tc (id, name);
1489                    putCachedTypecode( id, result );
1490                }
1491                closeEncapsulation();
1492                break;
1493            }
1494            case 0xffffffff:
1495            {
1496                /* recursive TC */
1497                int negative_offset = read_long();
1498                String JavaDoc recursiveId =
1499                    (String JavaDoc)tcMap.get( new Integer JavaDoc( pos - 4 + negative_offset ) );
1500
1501                if (recursiveId == null)
1502                {
1503                    throw new INTERNAL JavaDoc
1504                    (
1505                        "No recursive TypeCode! (pos: " +
1506                        (pos - 4 + negative_offset) +
1507                        ")"
1508                    );
1509                }
1510
1511                // look up TypeCode in map to check if it's repeated
1512
org.omg.CORBA.TypeCode JavaDoc rec_tc =
1513                    (org.omg.CORBA.TypeCode JavaDoc)( getRecursiveTCMap().get( recursiveId ) );
1514
1515                if (rec_tc == null)
1516                {
1517                    // TypeCode is not in map so it is recursive
1518
rec_tc = orb.create_recursive_tc( recursiveId );
1519                }
1520
1521                result = rec_tc;
1522                break;
1523            }
1524            default:
1525            {
1526                // error, dump buffer contents for diagnosis
1527
throw new MARSHAL JavaDoc("Cannot handle TypeCode with kind " + kind);
1528            }
1529        }
1530        return result;
1531    }
1532
1533    public final int read_ulong()
1534    {
1535        handle_chunking();
1536
1537        int result;
1538
1539        int remainder = 4 - (index % 4);
1540        if (remainder != 4)
1541        {
1542            index += remainder;
1543            pos += remainder;
1544        }
1545
1546        result = _read4int (littleEndian, buffer, pos);
1547
1548        index += 4;
1549        pos += 4;
1550        return result;
1551    }
1552
1553    public final void read_ulong_array
1554        (final int[] value, final int offset, final int length)
1555    {
1556        if (length == 0)
1557            return;
1558
1559        handle_chunking();
1560
1561        int remainder = 4 - (index % 4);
1562        if (remainder != 4)
1563        {
1564            index += remainder;
1565            pos += remainder;
1566        }
1567
1568        for (int j = offset; j < offset+length; j++)
1569        {
1570            value[j] = _read4int (littleEndian,buffer,pos);
1571            pos += 4;
1572        }
1573
1574        index += 4 * length;
1575    }
1576
1577    public final long read_ulonglong()
1578    {
1579        handle_chunking();
1580
1581        int remainder = 8 - (index % 8);
1582        if (remainder != 8)
1583        {
1584            index += remainder;
1585            pos += remainder;
1586        }
1587
1588        if (littleEndian)
1589        {
1590            return ((long) _read_long() & 0xFFFFFFFFL) + ((long) _read_long() << 32);
1591        }
1592        else
1593        {
1594            return ((long) _read_long() << 32) + ((long) _read_long() & 0xFFFFFFFFL);
1595        }
1596    }
1597
1598    public final void read_ulonglong_array
1599        (final long[] value, final int offset, final int length)
1600    {
1601        if (length == 0)
1602            return;
1603
1604        handle_chunking();
1605
1606        int remainder = 8 - (index % 8);
1607        if (remainder != 8)
1608        {
1609            index += remainder;
1610            pos += remainder;
1611        }
1612
1613        if (littleEndian)
1614        {
1615            for (int j = offset; j < offset+length; j++)
1616            {
1617                value[j] = ( (long) _read_long() & 0xFFFFFFFFL) +
1618                    ((long) _read_long() << 32);
1619            }
1620        }
1621        else
1622        {
1623            for (int j = offset; j < offset+length; j++)
1624            {
1625                value[j] = ((long) _read_long() << 32) +
1626                    ((long) _read_long() & 0xFFFFFFFFL);
1627            }
1628        }
1629
1630        // Do not need to modify pos and index as use read_long above
1631
}
1632
1633    public final short read_ushort()
1634    {
1635        handle_chunking();
1636
1637        int remainder = 2 - (index % 2);
1638        if (remainder != 2)
1639        {
1640            index += remainder;
1641            pos += remainder;
1642        }
1643
1644        short result = _read2int (littleEndian,buffer,pos);
1645        pos += 2;
1646        index += 2;
1647        return result;
1648    }
1649
1650    public final void read_ushort_array
1651        (final short[] value, final int offset, final int length)
1652    {
1653        if (length == 0)
1654            return;
1655
1656        handle_chunking();
1657
1658        int remainder = 2 - (index % 2);
1659
1660        if (remainder != 2)
1661        {
1662            index += remainder;
1663            pos += remainder;
1664        }
1665
1666        for (int j = offset; j < offset + length; j++)
1667        {
1668            value[j] = _read2int (littleEndian, buffer, pos);
1669            pos += 2;
1670        }
1671
1672        index += length * 2;
1673    }
1674
1675    public final char read_wchar()
1676    {
1677        handle_chunking();
1678
1679        if (giop_minor == 2)
1680        {
1681            //ignore size indicator
1682
read_wchar_size();
1683
1684            boolean wchar_little_endian = readBOM();
1685
1686            return read_wchar (wchar_little_endian);
1687        }
1688        else
1689        {
1690            return read_wchar (littleEndian);
1691        }
1692    }
1693
1694    /**
1695     * The number of bytes this char takes. This is actually not
1696     * necessary since the encodings used are either fixed-length
1697     * (UTF-16) or have their length encoded internally (UTF-8).
1698     */

1699    private final int read_wchar_size()
1700    {
1701        index++;
1702
1703        return buffer[ pos++ ];
1704    }
1705
1706
1707    private final char read_wchar(final boolean wchar_little_endian)
1708    {
1709        switch( codeSetW )
1710        {
1711            case CodeSet.UTF8 :
1712            {
1713                if( giop_minor < 2 )
1714                {
1715                    throw new MARSHAL JavaDoc( "GIOP 1." + giop_minor +
1716                                       " only allows 2 Byte encodings for wchar, but the selected TCSW is UTF-8" );
1717                }
1718
1719                short b = (short) (0xff & buffer[pos++]);
1720                index++;
1721
1722                if( (b & 0x80) == 0 )
1723                {
1724                    return (char) b;
1725                }
1726                else if( (b & 0xe0) == 0xc0 )
1727                {
1728                    index++;
1729                    return (char)(((b & 0x1F) << 6) |
1730                                  ((short)buffer[pos++] & 0x3F));
1731                }
1732                else
1733                {
1734                    index += 2;
1735                    short b2 = (short)(0xff & buffer[pos++]);
1736                    return (char)(( ( b & 0x0F) << 12) |
1737                                  ( (b2 & 0x3F) << 6) |
1738                                  ( (short)buffer[pos++] & 0x3F));
1739                }
1740            }
1741            case CodeSet.UTF16 :
1742            {
1743                char c;
1744
1745                if( wchar_little_endian )
1746                {
1747                    c = (char) ( (buffer[ pos++ ] & 0xFF) |
1748                                 (buffer[ pos++ ] << 8) );
1749                }
1750                else
1751                {
1752                    c = (char) ( (buffer[ pos++ ] << 8) |
1753                                 (buffer[ pos++ ] & 0xFF) );
1754                }
1755
1756                index += 2;
1757                return c;
1758            }
1759        }
1760
1761        throw new MARSHAL JavaDoc( "Bad CodeSet: " + codeSetW );
1762    }
1763
1764    /**
1765     * Read the byte order marker indicating the endianess.
1766     *
1767     * @return true for little endianess, false otherwise (including
1768     * no BOM present. In this case, big endianess is assumed per
1769     * spec).
1770     */

1771    private final boolean readBOM()
1772    {
1773        /*
1774          if( !use_BOM )
1775          return false;
1776        */

1777
1778        if( (buffer[ pos ] == (byte) 0xFE) &&
1779            (buffer[ pos + 1 ] == (byte) 0xFF) )
1780        {
1781            //encountering a byte order marker indicating big
1782
//endianess
1783

1784            pos += 2;
1785            index += 2;
1786
1787            return false;
1788        }
1789        else if( (buffer[ pos ] == (byte) 0xFF) &&
1790                 (buffer[ pos + 1 ] == (byte) 0xFE) )
1791        {
1792            //encountering a byte order marker indicating
1793
//little endianess
1794

1795            pos += 2;
1796            index += 2;
1797
1798            return true;
1799        }
1800        else
1801        {
1802            //no BOM so big endian per spec.
1803
return false;
1804        }
1805    }
1806
1807    public final void read_wchar_array
1808        (final char[] value, final int offset, final int length)
1809    {
1810        handle_chunking();
1811        for(int j=offset; j < offset+length; j++)
1812            value[j] = read_wchar(); // inlining later...
1813
}
1814
1815    public final String JavaDoc read_wstring()
1816    {
1817        String JavaDoc result = null;
1818        char buf[] = null;
1819
1820        handle_chunking();
1821
1822        int remainder = 4 - (index % 4);
1823        if( remainder != 4 )
1824        {
1825            index += remainder;
1826            pos += remainder;
1827        }
1828        if( giop_minor == 2 )
1829        {
1830            // read size in bytes
1831
int size = _read4int( littleEndian, buffer, pos);
1832            index += 4;
1833            pos += 4;
1834
1835            if( size == 0 )
1836            {
1837                return "";
1838            }
1839
1840            buf = new char[ size ];
1841
1842            int i = 0;
1843            int endPos = pos + size;
1844
1845            boolean wchar_litte_endian = readBOM();
1846
1847            while( pos < endPos )
1848            {
1849                //ignore size
1850
//read_wchar_size();
1851

1852                buf[ i++ ] = read_wchar( wchar_litte_endian );
1853            }
1854
1855            result = new String JavaDoc( buf, 0, i );
1856        }
1857        else //GIOP 1.1 / 1.0
1858
{
1859            // read size
1860
int size = _read4int( littleEndian, buffer, pos);
1861            index += 4;
1862            pos += 4;
1863            buf = new char[ size ];
1864
1865            int endPos = pos + size;
1866
1867            if( codeSetW == CodeSet.UTF16 )
1868            {
1869                //size is in chars, but char has 2 bytes
1870
endPos += size;
1871            }
1872
1873            int i = 0;
1874
1875            while( pos < endPos )
1876            {
1877                //use the stream-wide endianess
1878
buf[ i++ ] = read_wchar( littleEndian );
1879            }
1880
1881            if( (i != 0) &&
1882                (buf[ i - 1 ] == 0) )
1883            {
1884                //don't return terminating NUL
1885
result = new String JavaDoc( buf, 0, i - 1 );
1886            }
1887            else
1888            {
1889                //doesn't have a terminating NUL. This is actually not
1890
//allowed.
1891
result = new String JavaDoc( buf, 0, i );
1892            }
1893        }
1894        buf = null;
1895        return result;
1896    }
1897
1898    public boolean markSupported()
1899    {
1900        return true;
1901    }
1902
1903    public void mark(final int readLimit)
1904    {
1905        marked_pos = pos;
1906        marked_index = index;
1907    }
1908
1909    public void reset()
1910        throws IOException JavaDoc
1911    {
1912        if( pos < 0 )
1913            throw new MARSHAL JavaDoc("Mark has not been set!");
1914        pos = marked_pos;
1915        index = marked_index;
1916    }
1917
1918    // JacORB-specific
1919

1920    private final void resetIndex()
1921    {
1922        index = 0;
1923    }
1924
1925    public final void setLittleEndian(final boolean b)
1926    {
1927        littleEndian = b;
1928    }
1929
1930    /**
1931     * Reads an instance of the type described by type code <code>tc</code>
1932     * from this CDRInputStream, and remarshals it to the given OutputStream,
1933     * <code>out</code>. Called from Any.
1934     */

1935    final void read_value(final org.omg.CORBA.TypeCode JavaDoc tc,
1936                          final org.omg.CORBA.portable.OutputStream JavaDoc out)
1937    {
1938        if (tc == null)
1939        {
1940            throw new BAD_PARAM JavaDoc("TypeCode is null");
1941        }
1942
1943        int kind = tc.kind().value();
1944
1945        try
1946        {
1947            switch (kind)
1948            {
1949                case TCKind._tk_null:
1950                case TCKind._tk_void:
1951                break;
1952                case TCKind._tk_boolean:
1953                out.write_boolean( read_boolean());
1954                break;
1955                case TCKind._tk_char:
1956                out.write_char( read_char());
1957                break;
1958                case TCKind._tk_wchar:
1959                out.write_wchar( read_wchar());
1960                break;
1961                case TCKind._tk_octet:
1962                out.write_octet( read_octet());
1963                break;
1964                case TCKind._tk_ushort:
1965                out.write_ushort( read_ushort());
1966                break;
1967                case TCKind._tk_short:
1968                out.write_short( read_short());
1969                break;
1970                case TCKind._tk_long:
1971                out.write_long( read_long());
1972                break;
1973                case TCKind._tk_ulong:
1974                out.write_ulong( read_ulong());
1975                break;
1976                case TCKind._tk_float:
1977                out.write_float( read_float());
1978                break;
1979                case TCKind._tk_double:
1980                out.write_double( read_double());
1981                break;
1982                case TCKind._tk_longlong:
1983                out.write_longlong( read_longlong());
1984                break;
1985                case TCKind._tk_ulonglong:
1986                out.write_ulonglong( read_ulonglong());
1987                break;
1988                case TCKind._tk_any:
1989                out.write_any( read_any());
1990                break;
1991                case TCKind._tk_TypeCode:
1992                out.write_TypeCode( read_TypeCode());
1993                break;
1994                case TCKind._tk_Principal:
1995                throw new NO_IMPLEMENT JavaDoc ("Principal deprecated");
1996                case TCKind._tk_objref:
1997                out.write_Object( read_Object());
1998                break;
1999                case TCKind._tk_string:
2000                out.write_string( read_string());
2001                break;
2002                case TCKind._tk_wstring:
2003                out.write_wstring( read_wstring());
2004                break;
2005                case TCKind._tk_fixed:
2006                out.write_fixed (read_fixed());
2007                break;
2008                case TCKind._tk_array:
2009                {
2010                    int length = tc.length();
2011                    for( int i = 0; i < length; i++ )
2012                        read_value( tc.content_type(), out );
2013                    break;
2014                }
2015                case TCKind._tk_sequence:
2016                {
2017                    int len = read_long();
2018                    out.write_long(len);
2019                    for( int i = 0; i < len; i++ )
2020                        read_value( tc.content_type(), out );
2021                    break;
2022                }
2023                case TCKind._tk_except:
2024                out.write_string( read_string());
2025                // don't break, fall through to ...
2026
case TCKind._tk_struct:
2027                {
2028                    for( int i = 0; i < tc.member_count(); i++)
2029                        read_value( tc.member_type(i), out );
2030                    break;
2031                }
2032                case TCKind._tk_enum:
2033                out.write_long( read_long() );
2034                break;
2035                case TCKind._tk_alias:
2036                {
2037                    read_value( tc.content_type(), out );
2038                    break;
2039                }
2040                case TCKind._tk_value_box:
2041                {
2042                    String JavaDoc id = tc.id();
2043                    org.omg.CORBA.portable.BoxedValueHelper JavaDoc helper =
2044                        ((org.jacorb.orb.ORB)orb).getBoxedValueHelper(id);
2045                    if (helper == null)
2046                    {
2047                        throw new MARSHAL JavaDoc ("No BoxedValueHelper for id " + id);
2048                    }
2049                    java.io.Serializable JavaDoc value = read_value(helper);
2050                    ((org.omg.CORBA_2_3.portable.OutputStream JavaDoc)out)
2051                    .write_value(value, helper);
2052                    break;
2053                }
2054                case TCKind._tk_union:
2055                {
2056                    org.omg.CORBA.TypeCode JavaDoc disc = tc.discriminator_type();
2057                    disc = TypeCode.originalType(disc);
2058                    int def_idx = tc.default_index();
2059                    int member_idx = -1;
2060                    switch( disc.kind().value() )
2061                    {
2062                        case TCKind._tk_short:
2063                        {
2064                            short s = read_short();
2065                            out.write_short(s);
2066                            for(int i = 0 ; i < tc.member_count() ; i++)
2067                            {
2068                                if(i != def_idx)
2069                                {
2070                                    if(s == tc.member_label(i).extract_short())
2071                                    {
2072                                        member_idx = i;
2073                                        break;
2074                                    }
2075                                }
2076                            }
2077                            break;
2078                        }
2079
2080                        case TCKind._tk_long:
2081                        {
2082                            int s = read_long();
2083                            out.write_long(s);
2084                            for(int i = 0 ; i < tc.member_count() ; i++)
2085                            {
2086                                if(i != def_idx)
2087                                {
2088                                    if(s == tc.member_label(i).extract_long())
2089                                    {
2090                                        member_idx = i;
2091                                        break;
2092                                    }
2093                                }
2094                            }
2095                            break;
2096                        }
2097                        case TCKind._tk_ushort:
2098                        {
2099                            short s = read_ushort();
2100                            out.write_ushort(s);
2101                            for(int i = 0 ; i < tc.member_count() ; i++)
2102                            {
2103                                if(i != def_idx)
2104                                {
2105                                    if(s == tc.member_label(i).extract_ushort())
2106                                    {
2107                                        member_idx = i;
2108                                        break;
2109                                    }
2110                                }
2111                            }
2112                            break;
2113                        }
2114
2115                        case TCKind._tk_ulong:
2116                        {
2117                            int s = read_ulong();
2118                            out.write_ulong(s);
2119                            for(int i = 0 ; i < tc.member_count() ; i++)
2120                            {
2121                                if(i != def_idx)
2122                                {
2123                                    if(s == tc.member_label(i).extract_ulong())
2124                                    {
2125                                        member_idx = i;
2126                                        break;
2127                                    }
2128                                }
2129                            }
2130                            break;
2131                        }
2132                        case TCKind._tk_longlong:
2133                        {
2134                            long s = read_longlong();
2135                            out.write_longlong(s);
2136                            for(int i = 0 ; i < tc.member_count() ; i++)
2137                            {
2138                                if(i != def_idx)
2139                                {
2140                                    if(s == tc.member_label(i).extract_longlong())
2141                                    {
2142                                        member_idx = i;
2143                                        break;
2144                                    }
2145                                }
2146                            }
2147                            break;
2148                        }
2149                        case TCKind._tk_ulonglong:
2150                        {
2151                            long s = read_ulonglong();
2152                            out.write_ulonglong(s);
2153                            for(int i = 0 ; i < tc.member_count() ; i++)
2154                            {
2155                                if(i != def_idx)
2156                                {
2157                                    if(s == tc.member_label(i).extract_ulonglong())
2158                                    {
2159                                        member_idx = i;
2160                                        break;
2161                                    }
2162                                }
2163                            }
2164                            break;
2165                        }
2166                        case TCKind._tk_char:
2167                        {
2168                            char s = read_char();
2169                            out.write_char(s);
2170                            for(int i = 0 ; i < tc.member_count() ; i++)
2171                            {
2172                                if(i != def_idx)
2173                                {
2174                                    if(s == tc.member_label(i).extract_char())
2175                                    {
2176                                        member_idx = i;
2177                                        break;
2178                                    }
2179                                }
2180                            }
2181                            break;
2182                        }
2183                        case TCKind._tk_boolean:
2184                        {
2185                            boolean b = read_boolean();
2186                            out.write_boolean( b );
2187                            for(int i = 0 ; i < tc.member_count() ; i++)
2188                            {
2189                                if( i != def_idx)
2190                                {
2191                                    if( b == tc.member_label(i).extract_boolean() )
2192                                    {
2193                                        member_idx = i;
2194                                        break;
2195                                    }
2196                                }
2197                            }
2198                            break;
2199                        }
2200                        case TCKind._tk_enum:
2201                        {
2202                            int s = read_long();
2203                            out.write_long(s);
2204                            for( int i = 0 ; i < tc.member_count() ; i++)
2205                            {
2206                                if( i != def_idx)
2207                                {
2208                                    int label =
2209                                    tc.member_label(i).create_input_stream().read_long();
2210                                    if(s == label)
2211                                    {
2212                                        member_idx = i;
2213                                        break;
2214                                    }
2215                                }
2216                            }
2217                            break;
2218                        }
2219                        default:
2220                        throw new MARSHAL JavaDoc("Invalid union discriminator type: " + disc);
2221                    } // switch
2222

2223                    if( member_idx != -1 )
2224                    {
2225                        read_value( tc.member_type( member_idx ), out );
2226                    }
2227                    else if( def_idx != -1 )
2228                    {
2229                        read_value( tc.member_type( def_idx ), out );
2230                    }
2231                    break;
2232                }
2233                case 0xffffffff:
2234                {
2235                    org.omg.CORBA.TypeCode JavaDoc _tc =
2236                        (org.omg.CORBA.TypeCode JavaDoc)(getRecursiveTCMap().get ( tc.id() ));
2237
2238
2239                    if( _tc == null )
2240                    {
2241                        throw new MARSHAL JavaDoc("No recursive TC found for " + tc.id());
2242                    }
2243
2244                    read_value( _tc , out );
2245                    break;
2246                }
2247                default:
2248                throw new MARSHAL JavaDoc("Cannot handle TypeCode with kind " + kind);
2249            }
2250        }
2251        catch (BadKind JavaDoc ex)
2252        {
2253            throw new MARSHAL JavaDoc
2254                ("When processing TypeCode with kind: " + kind + " caught " + ex);
2255        }
2256        catch (Bounds JavaDoc ex)
2257        {
2258            throw new MARSHAL JavaDoc
2259                ("When processing TypeCode with kind: " + kind + " caught " + ex);
2260        }
2261    }
2262
2263
2264    public java.io.Serializable JavaDoc read_value()
2265    {
2266        int tag = read_long();
2267        int start_offset = pos - 4;
2268
2269        if (tag == 0xffffffff)
2270        {
2271            // indirection
2272
return read_indirect_value();
2273        }
2274        else if (tag == 0x00000000)
2275        {
2276            // null tag
2277
return null;
2278        }
2279
2280        String JavaDoc codebase = ((tag & 1) != 0) ? read_codebase() : null;
2281        chunkedValue = ((tag & 8) != 0);
2282
2283        int theTag = tag;
2284        tag = tag & 0xfffffff6;
2285
2286        if (tag == 0x7fffff00)
2287            throw new MARSHAL JavaDoc ("missing value type information");
2288        else if (tag == 0x7fffff02)
2289        {
2290            return read_typed_value(start_offset, codebase);
2291        }
2292        else if (tag == 0x7fffff06)
2293        {
2294            return read_multi_typed_value( start_offset, codebase );
2295        }
2296        else
2297            throw new MARSHAL JavaDoc("unknown value tag: 0x" +
2298                              Integer.toHexString(theTag) + " (offset=0x" +
2299                              Integer.toHexString(start_offset) + ")");
2300    }
2301
2302    /**
2303     * Overrides read_value(java.io.Serializable value) in
2304     * org.omg.CORBA_2_3.portable.InputStream
2305     */

2306
2307    public java.io.Serializable JavaDoc read_value(final String JavaDoc rep_id)
2308    {
2309        int tag = read_long();
2310        int start_offset = pos - 4;
2311
2312        if (tag == 0xffffffff)
2313        {
2314            // indirection
2315
return read_indirect_value();
2316        }
2317        else if (tag == 0x00000000)
2318        {
2319            // null tag
2320
return null;
2321        }
2322
2323        String JavaDoc codebase = ((tag & 1) != 0) ? read_codebase() : null;
2324        chunkedValue = ((tag & 8) != 0);
2325
2326        int theTag = tag;
2327        tag = tag & 0xfffffff6;
2328
2329        if (tag == 0x7fffff00)
2330        {
2331            return read_untyped_value ( new String JavaDoc[]{ rep_id }, start_offset, codebase);
2332        }
2333        else if (tag == 0x7fffff02)
2334        {
2335            return read_typed_value( start_offset, codebase );
2336        }
2337        else if (tag == 0x7fffff06)
2338        {
2339            return read_multi_typed_value( start_offset, codebase );
2340        }
2341        else
2342        {
2343            throw new MARSHAL JavaDoc("unknown value tag: 0x" +
2344                              Integer.toHexString(theTag) + " (offset=0x" +
2345                              Integer.toHexString(start_offset) + ")");
2346        }
2347    }
2348
2349    /**
2350     * Unmarshals a valuetype instance from this stream. The value returned
2351     * is the same value passed in, with all the data unmarshaled
2352     * (IDL-to-Java Mapping 1.2, August 2002, 1.13.1, p. 1-39). The specified
2353     * value is an uninitialized value that is added to the ORB's indirection
2354     * table before unmarshaling (1.21.4.1, p. 1-117).
2355     *
2356     * This method is intended to be called from custom valuetype factories.
2357     * Unlike the other read_value() methods in this class, this method does
2358     * not expect a GIOP value tag nor a repository id in the stream.
2359     *
2360     * Overrides read_value(value) in
2361     * org.omg.CORBA_2_3.portable.InputStream
2362     */

2363
2364    public java.io.Serializable JavaDoc read_value(java.io.Serializable JavaDoc value)
2365    {
2366        if (value instanceof org.omg.CORBA.portable.Streamable JavaDoc)
2367        {
2368            register_value(value);
2369            ((org.omg.CORBA.portable.Streamable JavaDoc)value)._read(this);
2370            return value;
2371        }
2372        else
2373            throw new BAD_PARAM JavaDoc("read_value is only implemented for Streamables");
2374    }
2375
2376    /**
2377     * Overrides read_value(clz) in
2378     * org.omg.CORBA_2_3.portable.InputStream
2379     */

2380
2381    public java.io.Serializable JavaDoc read_value(final java.lang.Class JavaDoc clz)
2382    {
2383        int tag = read_long();
2384        int start_offset = pos - 4;
2385
2386        if (tag == 0xffffffff)
2387        {
2388            // indirection
2389
return read_indirect_value();
2390        }
2391        else if (tag == 0x00000000)
2392        {
2393            // null tag
2394
return null;
2395        }
2396
2397        String JavaDoc codebase = ((tag & 1) != 0) ? read_codebase() : null;
2398        chunkedValue = ((tag & 8) != 0);
2399
2400        int theTag = tag;
2401        tag = tag & 0xfffffff6;
2402
2403        if (tag == 0x7fffff00)
2404        {
2405            return read_untyped_value ( new String JavaDoc[]{ ValueHandler.getRMIRepositoryID(clz) },
2406                                        start_offset, codebase);
2407        }
2408        else if (tag == 0x7fffff02)
2409        {
2410            return read_typed_value(start_offset, codebase);
2411        }
2412        else if (tag == 0x7fffff06)
2413        {
2414            return read_multi_typed_value(start_offset, codebase);
2415        }
2416        else
2417        {
2418            throw new MARSHAL JavaDoc("unknown value tag: 0x" +
2419                              Integer.toHexString(theTag) + " (offset=0x" +
2420                              Integer.toHexString(start_offset) + ")");
2421        }
2422    }
2423
2424    /**
2425     * Overrides read_value(factory) in
2426     * org.omg.CORBA_2_3.portable.InputStream
2427     */

2428
2429
2430    public java.io.Serializable JavaDoc read_value
2431        (final org.omg.CORBA.portable.BoxedValueHelper JavaDoc factory)
2432    {
2433        int tag = read_long();
2434        int start_offset = pos - 4;
2435
2436        if (tag == 0xffffffff)
2437        {
2438            // indirection
2439
return read_indirect_value();
2440        }
2441        else if (tag == 0x00000000)
2442        {
2443            // null tag, explicit representation of null value
2444
return null;
2445        }
2446
2447        String JavaDoc codebase = ((tag & 1) != 0) ? read_codebase() : null;
2448        chunkedValue = ((tag & 8) != 0);
2449
2450        int theTag = tag;
2451        tag = tag & 0xfffffff6;
2452
2453        if (tag == 0x7fffff00)
2454        {
2455            java.io.Serializable JavaDoc result = factory.read_value (this);
2456
2457            if( result != null )
2458            {
2459                getValueMap().put (new Integer JavaDoc(start_offset), result);
2460            }
2461
2462            return result;
2463        }
2464        else if (tag == 0x7fffff02)
2465        {
2466            // Read value according to type information.
2467
// Possible optimization: ignore type info and use factory for
2468
// reading the value anyway, since the type information is
2469
// most likely redundant.
2470
return read_typed_value(start_offset, codebase);
2471        }
2472        else
2473            throw new MARSHAL JavaDoc("unknown value tag: 0x" +
2474                              Integer.toHexString(theTag) + " (offset=0x" +
2475                              Integer.toHexString(start_offset) + ")");
2476    }
2477
2478    /**
2479     * Immediately reads a value from this stream; i.e. without any
2480     * repository id preceding it. The expected type of the value is given
2481     * by `repository_id', and the index at which the value started is
2482     * `index'.
2483     */

2484    private java.io.Serializable JavaDoc read_untyped_value(final String JavaDoc[] repository_ids,
2485                                                     final int index,
2486                                                     final String JavaDoc codebase)
2487    {
2488        java.io.Serializable JavaDoc result = null;
2489
2490        if (chunkedValue || valueNestingLevel > 0)
2491        {
2492            valueNestingLevel++;
2493            int chunk_size_tag = read_long();
2494            chunk_end_pos = pos + chunk_size_tag;
2495        }
2496
2497        for (int r = 0; r < repository_ids.length; r++)
2498        {
2499            if (repository_ids[r].equals("IDL:omg.org/CORBA/WStringValue:1.0"))
2500            {
2501                // special handling of strings, according to spec
2502
result = read_wstring();
2503                break;
2504            }
2505            else if (repository_ids[r].startsWith("RMI:javax.rmi.CORBA.ClassDesc:"))
2506            {
2507                // special handling of java.lang.Class instances
2508
String JavaDoc classCodebase = (String JavaDoc)read_value(String JavaDoc.class);
2509                String JavaDoc reposId = (String JavaDoc)read_value(String JavaDoc.class);
2510                String JavaDoc className =
2511                    org.jacorb.ir.RepositoryID.className(reposId, null);
2512                ClassLoader JavaDoc ctxcl =
2513                    Thread.currentThread().getContextClassLoader();
2514
2515                try
2516                {
2517                    if (ctxcl != null)
2518                    {
2519                        try
2520                        {
2521                            result = ctxcl.loadClass(className);
2522                        }
2523                        catch (ClassNotFoundException JavaDoc cnfe)
2524                        {
2525                            result = ValueHandler.loadClass(className,
2526                                                            classCodebase,
2527                                                            null);
2528                        }
2529                    }
2530                    else
2531                    {
2532                        result = ValueHandler.loadClass(className,
2533                                                        classCodebase,
2534                                                        null);
2535                    }
2536                }
2537                catch (ClassNotFoundException JavaDoc e)
2538                {
2539                    if( r < repository_ids.length-1 )
2540                        continue;
2541                    else
2542                        throw new MARSHAL JavaDoc("class not found: " + className);
2543                }
2544                break;
2545            }
2546            else if (repository_ids[r].startsWith ("IDL:"))
2547            {
2548                org.omg.CORBA.portable.ValueFactory JavaDoc factory =
2549                    ((org.omg.CORBA_2_3.ORB JavaDoc)orb()).lookup_value_factory (repository_ids[r]);
2550
2551                if (factory != null)
2552                {
2553                    currentValueIndex = index;
2554                    result = factory.read_value (this);
2555                    break;
2556                }
2557                else
2558                {
2559                    if( r < repository_ids.length-1 )
2560                        continue;
2561                    else
2562                        throw new MARSHAL JavaDoc ("No factory found for: " + repository_ids[0] );
2563                }
2564            }
2565            else // RMI
2566
{
2567                // Load the value's class, using the context class loader
2568
// of the current thread if possible. Here's Francisco
2569
// Reverbel's <reverbel@ime.usp.br> explanation of why
2570
// this is needed in JBoss:
2571

2572                // "It seems that ValueHandler.loadClass() uses the thread
2573
// context classloader only after it looks for other
2574
// classloaders in the call stack (weird). In some
2575
// situations (when EJBs are undeployed and then
2576
// redeployed) it finds in the call stack a classloader
2577
// used for an undeployed EJB. A value of class Foo is
2578
// then unmarshalled with type
2579
// classloaderOfEJB1:Foo, when the expected type is
2580
// classloaderOfEJB2:Foo. I am getting ClassCastExceptions is this
2581
// situation.
2582
// Explicitly using the thread context class loader in the
2583
// first place solves the problem."
2584

2585                String JavaDoc className =
2586                org.jacorb.ir.RepositoryID.className(repository_ids[r], null);
2587
2588                Class JavaDoc c = null;
2589                //#ifjdk 1.2
2590
ClassLoader JavaDoc ctxcl = Thread.currentThread().getContextClassLoader();
2591                //#else
2592
//# ClassLoader ctxcl = null;
2593
//#endif
2594
try
2595                {
2596                    if (ctxcl != null)
2597                    {
2598                        try
2599                        {
2600                            c = ctxcl.loadClass(className);
2601                        }
2602                        catch (ClassNotFoundException JavaDoc cnfe)
2603                        {
2604                            c = ValueHandler.loadClass(className, codebase, null);
2605                        }
2606                    }
2607                    else
2608                    {
2609                        c = ValueHandler.loadClass(className, codebase, null);
2610                    }
2611
2612                    if (IDLEntity JavaDoc.class.isAssignableFrom(c))
2613                    {
2614                        java.lang.reflect.Method JavaDoc readMethod = null;
2615                        if (c != org.omg.CORBA.Any JavaDoc.class)
2616                        {
2617                            String JavaDoc helperClassName = c.getName() + "Helper";
2618
2619                            try
2620                            {
2621                                Class JavaDoc helperClass =
2622                                c.getClassLoader().loadClass(
2623                                    helperClassName);
2624                                Class JavaDoc[] paramTypes = {
2625                                    org.omg.CORBA.portable.InputStream JavaDoc.class
2626                                };
2627                                readMethod =
2628                                helperClass.getMethod("read", paramTypes);
2629                            }
2630                            catch (ClassNotFoundException JavaDoc e)
2631                            {
2632                                throw new MARSHAL JavaDoc("Error loading class " + helperClassName
2633                                                  + ": " + e);
2634                            }
2635                            catch (NoSuchMethodException JavaDoc e)
2636                            {
2637                                throw new MARSHAL JavaDoc("No read method in helper class "
2638                                                  + helperClassName + ": " + e);
2639                            }
2640                        }
2641
2642                        if (readMethod == null)
2643                        {
2644                            result = read_any();
2645                        }
2646                        else
2647                        {
2648                            try
2649                            {
2650                                result =
2651                                    (java.io.Serializable JavaDoc) readMethod.invoke(
2652                                        null,
2653                                        new java.lang.Object JavaDoc[] { this });
2654                            }
2655                            catch (IllegalAccessException JavaDoc e)
2656                            {
2657                                throw new MARSHAL JavaDoc("Internal error: " + e);
2658                            }
2659                            catch (java.lang.reflect.InvocationTargetException JavaDoc e)
2660                            {
2661                                throw new MARSHAL JavaDoc("Exception unmarshaling IDLEntity: "
2662                                                  + e.getTargetException());
2663                            }
2664                        }
2665                    }
2666                    else
2667                        result = ValueHandler.readValue(this, index, c,
2668                                                        repository_ids[r],
2669                                                        null);
2670                }
2671                catch (ClassNotFoundException JavaDoc e)
2672                {
2673                    if( r < repository_ids.length-1 )
2674                        continue;
2675                    else
2676                        throw new MARSHAL JavaDoc ("class not found: " + className);
2677                }
2678
2679            }
2680        }
2681
2682        // value type instances may be null...
2683
if( result != null )
2684        {
2685            getValueMap().put (new Integer JavaDoc (index), result);
2686        }
2687
2688        return result;
2689    }
2690
2691    /**
2692     * Reads a value with type information, i.e. one that is preceded
2693     * by a single RepositoryID. It is assumed that the tag and the codebase
2694     * of the value have already been read.
2695     */

2696
2697    private java.io.Serializable JavaDoc read_typed_value( final int index,
2698                                                   final String JavaDoc codebase)
2699    {
2700        return read_untyped_value ( new String JavaDoc[]{ read_repository_id() }, index, codebase);
2701    }
2702
2703    /**
2704     * Reads a value with type information, i.e. one that is preceded
2705     * by an array of RepositoryIDs. It is assumed that the tag and the codebase
2706     * of the value have already been read.
2707     */

2708
2709    private java.io.Serializable JavaDoc read_multi_typed_value( final int index,
2710                                                         final String JavaDoc codebase)
2711    {
2712        int id_count = read_long();
2713        String JavaDoc[] ids = new String JavaDoc[ id_count ];
2714
2715        for( int i = 0; i < id_count; i++ )
2716            ids[i] = read_repository_id();
2717
2718        return read_untyped_value (ids, index, codebase);
2719    }
2720
2721
2722    /**
2723     * Reads a RepositoryID from the buffer, either directly or via
2724     * indirection.
2725     */

2726    private String JavaDoc read_repository_id()
2727    {
2728        int tag = read_long();
2729        if (tag == 0xffffffff)
2730        {
2731            // indirection
2732
int index = read_long();
2733            index = index + pos - 4;
2734
2735            String JavaDoc repId = (String JavaDoc)getRepIdMap().get (new Integer JavaDoc(index));
2736            if (repId == null)
2737                throw new MARSHAL JavaDoc("stale RepositoryID indirection");
2738            else
2739                return repId;
2740        }
2741        else
2742        {
2743            // a new id
2744
pos -= 4;
2745            index -= 4;
2746            int start_offset = pos;
2747            String JavaDoc repId = read_string();
2748
2749            getRepIdMap().put (new Integer JavaDoc(start_offset), repId);
2750            return repId;
2751        }
2752    }
2753
2754    /**
2755     * Reads a codebase from the buffer, either directly or via
2756     * indirection.
2757     */

2758    private String JavaDoc read_codebase()
2759    {
2760        int tag = read_long();
2761
2762        if (tag == 0xffffffff)
2763        {
2764            // indirection
2765
int index = read_long();
2766            index = index + pos - 4;
2767            String JavaDoc codebase = (String JavaDoc)getCodebaseMap().get (new Integer JavaDoc(index));
2768            if (codebase == null)
2769                throw
2770                new MARSHAL JavaDoc("stale codebase indirection");
2771            else
2772                return codebase;
2773        }
2774        else
2775        {
2776            // a new codebase string
2777
pos -= 4;
2778            index -= 4;
2779            int start_offset = pos;
2780            String JavaDoc codebase = read_string();
2781            getCodebaseMap().put (new Integer JavaDoc(start_offset), codebase);
2782            return codebase;
2783        }
2784    }
2785
2786    /**
2787     * Reads an indirect value from this stream. It is assumed that the
2788     * value tag (0xffffffff) has already been read.
2789     */

2790    private java.io.Serializable JavaDoc read_indirect_value()
2791    {
2792        // indirection
2793
int index = read_long();
2794        index = index + pos - 4;
2795        java.lang.Object JavaDoc value = getValueMap().get (new Integer JavaDoc(index));
2796        if (value == null) {
2797
2798            // Java to IDL Language Mapping, v1.1, page 1-44:
2799
//
2800
// "The ValueHandler object may receive an IndirectionException
2801
// from the ORB stream. The ORB input stream throws this exception
2802
// when it is called to unmarshal a value encoded as an indirection
2803
// that is in the process of being unmarshaled. This can occur when
2804
// the ORB stream calls the ValueHandler object to unmarshal an RMI
2805
// value whose state contains a recursive reference to itself.
2806
// Because the top-level ValueHandler.readValue call has not yet
2807
// returned a value, the ORB stream's indirection table contains no
2808
// entry for an object with the stream offset specified by the
2809
// indirection tag. This stream offset is returned in the
2810
// exception's offset field."
2811

2812            throw new org.omg.CORBA.portable.IndirectionException JavaDoc (index);
2813        }
2814        else
2815            return (java.io.Serializable JavaDoc)value;
2816    }
2817
2818    private String JavaDoc validateName (String JavaDoc name)
2819    {
2820        if (name != null && name.length() == 0)
2821        {
2822            return null;
2823        }
2824        return name;
2825    }
2826
2827
2828    private String JavaDoc validateMember (String JavaDoc name)
2829    {
2830        if (name == null || name.length() == 0)
2831        {
2832            uniqueValue = (++uniqueValue)%Integer.MAX_VALUE;
2833            return ("DUMMY_NAME_".concat (String.valueOf (uniqueValue)));
2834        }
2835        return name;
2836    }
2837
2838
2839    private String JavaDoc validateID (String JavaDoc id)
2840    {
2841        if (id == null || id.length() == 0)
2842        {
2843            id = "IDL:";
2844        }
2845        return id;
2846    }
2847
2848
2849    /**
2850     * Reads an abstract interface from this stream. The abstract interface
2851     * Reads an abstract interface from this stream. The abstract interface
2852     * appears as a union with a boolean discriminator, which is true if the
2853     * union contains a CORBA object reference, or false if the union contains
2854     * a value.
2855     */

2856
2857    public java.lang.Object JavaDoc read_abstract_interface()
2858    {
2859        return read_boolean() ? (java.lang.Object JavaDoc)read_Object()
2860        : (java.lang.Object JavaDoc)read_value();
2861    }
2862
2863    /**
2864     * Reads an abstract interface from this stream. The abstract interface
2865     * appears as a union with a boolean discriminator, which is true if the
2866     * union contains a CORBA object reference, or false if the union contains
2867     * a value.
2868     */

2869
2870    public java.lang.Object JavaDoc read_abstract_interface(final java.lang.Class JavaDoc clz)
2871    {
2872        return read_boolean() ? (java.lang.Object JavaDoc)read_Object(clz)
2873        : (java.lang.Object JavaDoc)read_value(clz);
2874    }
2875
2876
2877    public int get_pos()
2878    {
2879        return pos;
2880    }
2881
2882    /**
2883     * Stores `value' into this stream's valueMap. This is provided
2884     * as a callback for value factories, so that a value factory can
2885     * store an object into the map before actually reading its state.
2886     * This is essential for unmarshalling recursive values.
2887     */

2888
2889    public void register_value(final java.io.Serializable JavaDoc value)
2890    {
2891        getValueMap().put(new Integer JavaDoc(currentValueIndex), value);
2892    }
2893}
2894
Popular Tags