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          &nbs