KickJava   Java API By Example, From Geeks To Geeks.

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


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.*;
24 import java.util.*;
25
26 import org.apache.avalon.framework.configuration.*;
27
28 import org.jacorb.ir.RepositoryID;
29 import org.jacorb.orb.giop.CodeSet;
30 import org.jacorb.util.ValueHandler;
31 import org.jacorb.util.ObjectUtil;
32
33 import org.omg.CORBA.BAD_PARAM JavaDoc;
34 import org.omg.CORBA.CODESET_INCOMPATIBLE JavaDoc;
35 import org.omg.CORBA.MARSHAL JavaDoc;
36 import org.omg.CORBA.NO_IMPLEMENT JavaDoc;
37 import org.omg.CORBA.INTERNAL JavaDoc;
38 import org.omg.CORBA.TCKind JavaDoc;
39 import org.omg.CORBA.TypeCodePackage.BadKind JavaDoc;
40 import org.omg.CORBA.TypeCodePackage.Bounds JavaDoc;
41 import org.omg.IOP.IOR JavaDoc;
42 import org.omg.IOP.IORHelper JavaDoc;
43 import org.omg.IOP.TaggedProfile JavaDoc;
44
45 /**
46  * @author Gerald Brose, 1999
47  * @version $Id: CDROutputStream.java,v 1.100 2005/04/23 13:07:29 phil.mesnier Exp $
48  *
49  * A stream for CDR marshalling.
50  *
51  */

52
53 public class CDROutputStream
54     extends org.omg.CORBA_2_3.portable.OutputStream JavaDoc
55 {
56     private final static IOR JavaDoc null_ior = new IOR JavaDoc("", new TaggedProfile JavaDoc[0]);
57
58     /** needed for alignment purposes */
59     private int index;
60
61     /** the current write position in the buffer */
62     private int pos;
63
64     /** the number of bytes that will only make up the final buffer
65         size, but that have not yet been written */

66     private int deferred_writes;
67
68     private BufferManager bufMgr;
69     protected byte[] buffer;
70
71     private boolean closed;
72
73     /* character encoding code sets for char and wchar, default ISO8859_1 */
74     private int codeSet = CodeSet.getTCSDefault();
75     private int codeSetW= CodeSet.getTCSWDefault();
76
77     private int encaps_start = -1;
78
79     /**
80      * <code>encaps_stack</code> is used to store encapsulations. Do NOT
81      * access this variable directly. It is initialized on demand. Use the
82      * method {@link #getEncapsStack() getEncapsStack()}
83      */

84     private Stack encaps_stack;
85
86     /**
87      * <code>recursiveTCMap</code> is used to remember the original TCs for a
88      * given ID that is used in a recursive/repeated TC. Do NOT access this
89      * variable directly. It is initialised on demand. Use the method
90      * {@link #getRecursiveTCMap() getRecursiveTCMap()}
91      */

92     private Map recursiveTCMap;
93
94     /**
95      * <code>valueMap</code> is used to maps all value objects that have
96      * already been written to this stream to their position within the
97      * buffer. The position is stored as a java.lang.Integer. Do NOT access
98      * this variable directly. It is initialised on demand. Use the method
99      * {@link #getValueMap() getValueMap()}
100      */

101     private Map valueMap;
102
103     /**
104      * <code>repIdMap</code> is used to map all repository ids that have already
105      * been written to this stream to their position within the buffer. The
106      * position is stored as a java.lang.Integer. Do NOT access this variable
107      * directly. It is initialised on demand. Use the method
108      * {@link #getRepIdMap() getRepIdMap()}
109      */

110     private Map repIdMap;
111
112     /**
113      * <code>codebaseMap</code> is used to maps all codebase strings that have
114      * already been written to this stream to their position within the buffer.
115      * The position is stored as a java.lang.Integer. Do NOT access this variable
116      * directly. It is initialised on demand. Use the method
117      * {@link #getCodebaseMap() getCodebaseMap()}
118      */

119     private Map codebaseMap;
120
121     /**
122      * <code>cachedTypecodes</code> is used to cache compacted typecodes when
123      * writing to the stream. This variable is initialised on demand.
124      */

125     private Map cachedTypecodes;
126
127     /** Remembers the starting position of the current chunk. */
128     private int chunk_size_tag_pos = -1; // -1 means we're not within a chunk
129
private int chunk_size_tag_index;
130     private int chunk_octets_pos;
131
132     /** Nesting level of chunked valuetypes */
133     private int valueNestingLevel = 0;
134
135     /** Nesting level of calls write_value_internal */
136     private int writeValueNestingLevel = 0;
137
138     /** True if write_value_internal called writeReplace */
139     private boolean writeReplaceCalled = false;
140     
141     private List deferredArrayQueue = new ArrayList();
142
143     private org.omg.CORBA.ORB JavaDoc orb = null;
144
145     protected int giop_minor = 2;
146
147     /** The chunking flag is either 0 (no chunking) or 0x00000008 (chunking),
148         to be bitwise or'ed into value tags. */

149     private int chunkingFlag = 0;
150
151     /** configurable properties */
152     private boolean useBOM = false;
153     private boolean chunkCustomRmiValuetypes = false;
154     private int compactTypeCodes = 0;
155     private boolean useIndirection = true;
156
157     /**
158      * This stream is self-configuring, i.e. configure() is private
159      * and only called from the constructor
160      */

161
162     private void configure(Configuration configuration)
163         throws ConfigurationException
164     {
165         useBOM =
166             configuration.getAttribute("jacorb.use_bom","off").equals("on");
167
168         chunkCustomRmiValuetypes =
169             configuration.getAttribute("jacorb.interop.chunk_custom_rmi_valuetypes","off").equals("on");
170         compactTypeCodes =
171             configuration.getAttributeAsInteger("jacorb.compactTypecodes", 0);
172
173         useIndirection =
174            !( configuration.getAttribute("jacorb.interop.indirection_encoding_disable","off").equals("on"));
175     }
176
177     private static class DeferredWriteFrame
178     {
179         public int write_pos = 0;
180         public int start = 0;
181         public int length = 0;
182         public byte[] buf = null;
183
184         public DeferredWriteFrame( int write_pos, int start,
185                                    int length, byte[] buf )
186         {
187             this.write_pos = write_pos;
188             this.start = start;
189             this.length = length;
190             this.buf = buf;
191         }
192     }
193
194
195     /**
196      * OutputStreams created using the empty constructor are used for
197      * in memory marshaling, but do not use the ORB's output buffer
198      * manager. A stream created with this c'tor is not explicitly
199      * configured, i.e. it will use default configuration only
200      */

201
202     public CDROutputStream()
203     {
204         bufMgr = BufferManager.getInstance(); // the BufferManager will be configured by now!
205
buffer = bufMgr.getPreferredMemoryBuffer();
206     }
207
208     /**
209      * OutputStreams created using this constructor
210      * are used also for in memory marshaling, but do use the
211      * ORB's output buffer manager
212      */

213     public CDROutputStream(final org.omg.CORBA.ORB JavaDoc orb)
214     {
215         this();
216         if (orb != null )
217         {
218             this.orb = orb;
219             try
220             {
221                 configure(((org.jacorb.orb.ORB)orb).getConfiguration());
222             }
223             catch( ConfigurationException ce )
224             {
225                 throw new INTERNAL JavaDoc("ConfigurationException: " + ce.getMessage());
226             }
227         }
228     }
229
230     /**
231      * Class constructor setting the buffer size for the message and
232      * the character encoding sets. A stream created with this c'tor
233      * is not explicitly configured, i.e. it will use default
234      * configuration only!
235      */

236
237     public CDROutputStream(final byte[] buf)
238     {
239         bufMgr = BufferManager.getInstance();
240         buffer = buf;
241     }
242
243     public org.omg.CORBA.ORB JavaDoc orb()
244     {
245         if (orb == null)
246             orb = org.omg.CORBA.ORB.init();
247         return orb;
248     }
249
250
251     /**
252      * <code>getEncapsStack</code> is used to initialize encaps_stack
253      * on demand.
254      *
255      * @return a <code>Stack</code> value
256      */

257     private Stack getEncapsStack()
258     {
259         if (encaps_stack == null)
260         {
261             encaps_stack = new Stack();
262         }
263         return encaps_stack;
264     }
265
266
267     /**
268      * Gets the Map that is used to store recursive TypeCodes.
269      *
270      * @return a <code>Map</code> value
271      */

272     private Map getRecursiveTCMap()
273     {
274         if (recursiveTCMap == null)
275         {
276             recursiveTCMap = new HashMap();
277         }
278         return recursiveTCMap;
279     }
280
281
282     /**
283      * Gets the Map that is used to detect reference sharing when
284      * marshaling valuetype instances.
285      *
286      * @return a <code>Map</code> value
287      */

288     private Map getValueMap()
289     {
290         if (valueMap == null)
291         {
292             valueMap = ObjectUtil.createIdentityHashMap();
293         }
294         return valueMap;
295     }
296
297
298     /**
299      * Gets the Map that is used to implement indirections for RepositoryIDs.
300      *
301      * @return a <code>Map</code> value
302      */

303     private Map getRepIdMap()
304     {
305         if (repIdMap == null)
306         {
307             repIdMap = new HashMap();
308         }
309         return repIdMap;
310     }
311
312     /**
313      * Gets the Map that is used to implement indirections for Codebase
314      * specifications.
315      *
316      * @return a <code>Map</code> value
317      */

318     private Map getCodebaseMap()
319     {
320         if (codebaseMap == null)
321         {
322             codebaseMap = new HashMap();
323         }
324         return codebaseMap;
325     }
326
327
328     /**
329      * write the contents of this CDR stream to the output stream,
330      * includes all deferred writes (e.g., for byte arrays)...
331      * called by, e.g. GIOPConnection to write directly to the
332      * wire.
333      */

334
335     public void write( OutputStream out, int start, int length )
336         throws IOException
337     {
338         int write_idx = start;
339         int read_idx = start;
340
341         // needed to calculate the actual read position in the
342
// current buffer,
343
int skip_count = 0;
344
345         int list_idx = 0;
346
347         DeferredWriteFrame next_frame = null;
348
349         if( deferredArrayQueue != null && deferredArrayQueue.size() > 0 )
350         {
351             // find the first frame that falls within the current window,
352
// i.e. that need s to be written
353
next_frame = (DeferredWriteFrame)deferredArrayQueue.get( list_idx++ );
354
355             // skip all frames beginning before the current start pos, but
356
// record their length
357
while( next_frame.write_pos < start && list_idx < deferredArrayQueue.size() )
358             {
359                 skip_count += next_frame.length;
360                 next_frame = (DeferredWriteFrame)deferredArrayQueue.get( list_idx++ );
361             }
362
363             // skip
364
if( next_frame.write_pos < start && list_idx >= deferredArrayQueue.size() )
365             {
366                 skip_count += next_frame.length;
367                 next_frame = null;
368             }
369         }
370
371         while( write_idx < start + length )
372         {
373
374             if( next_frame != null && write_idx == next_frame.write_pos )
375             {
376                 if ( ! (next_frame.length <= start + length - write_idx))
377                 {
378                     throw new MARSHAL JavaDoc ("Deferred array does not fit");
379                 }
380
381                 // write a frame, i.e. a byte array
382
out.write( next_frame.buf, next_frame.start, next_frame.length );
383
384                 // advance
385
write_idx += next_frame.length;
386
387                 // clear the fram variable...
388
next_frame = null;
389
390                 // and look up the next frame
391
if( deferredArrayQueue != null &&
392                     list_idx < deferredArrayQueue.size() )
393                 {
394                     next_frame = (DeferredWriteFrame)deferredArrayQueue.get( list_idx++ );
395                     if( next_frame.write_pos > start + length )
396                     {
397                         // unset, frame is beyond our current reach
398
next_frame = null;
399                     }
400                 }
401             }
402
403             if( write_idx < start + length )
404             {
405                 // write data that was previously marshaled
406

407                 int write_now =
408                 Math.min( start + length,
409                           ( next_frame != null ? next_frame.write_pos : start + length ));
410
411                 write_now -= write_idx; // calculate length
412

413                 //
414
out.write( buffer, read_idx-skip_count , write_now );
415
416                 // advance
417
read_idx += write_now;
418                 write_idx += write_now;
419             }
420         }
421     }
422
423     public void setCodeSet(final int codeSet, final int codeSetWide)
424     {
425         this.codeSet = codeSet;
426         this.codeSetW = codeSetWide;
427     }
428
429     public void setGIOPMinor(final int giop_minor)
430     {
431         this.giop_minor = giop_minor;
432     }
433
434     public int getGIOPMinor()
435     {
436         return giop_minor;
437     }
438
439     public void close()
440     {
441         // Don't need to call super.close as super is noop.
442
if( closed )
443         {
444             return;
445         }
446
447         bufMgr.returnBuffer( buffer, true );
448
449         buffer = null;
450         closed = true;
451         if (deferredArrayQueue != null)
452         {
453             deferredArrayQueue.clear();
454         }
455         deferred_writes = 0;
456     }
457
458     /**
459      * This version of check does both array length checking and
460      * data type alignment. It is a convenience method.
461      */

462     private final void check(final int i, final int align)
463     {
464         int remainder = align - (index % align);
465
466         check (i + remainder);
467
468         if (remainder != align)
469         {
470             // Clear padding. Allowing for possible buffer end.
471
int topad = Math.min (buffer.length - pos, 8);
472             int j = 0;
473             switch (topad)
474             {
475                 case 8:
476                 buffer[pos + j++] = (byte)0;
477                 case 7:
478                 buffer[pos + j++] = (byte)0;
479                 case 6:
480                 buffer[pos + j++] = (byte)0;
481                 case 5:
482                 buffer[pos + j++] = (byte)0;
483                 case 4:
484                 buffer[pos + j++] = (byte)0;
485                 case 3:
486                 buffer[pos + j++] = (byte)0;
487                 case 2:
488                 buffer[pos + j++] = (byte)0;
489                 case 1:
490                 buffer[pos + j++] = (byte)0;
491             }
492
493             index += remainder;
494             pos += remainder;
495         }
496     }
497
498     /**
499      * check whether the current buffer is big enough to receive
500      * i more bytes. If it isn't, get a bigger buffer.
501      */

502
503     private final void check(final int i)
504     {
505         byte [] new_buf;
506
507         if (buffer == null || (pos + i + 2) > buffer.length)
508         {
509             new_buf = bufMgr.getBuffer( pos+i+2, true);
510
511             if (buffer != null)
512             {
513                 System.arraycopy(buffer,0,new_buf,0,pos);
514             }
515             // Change buffer size so return the old one.
516
bufMgr.returnBuffer (buffer, true);
517
518             buffer = new_buf;
519             new_buf = null;
520         }
521     }
522
523     private final static void _write4int
524        (final byte[] buf, final int _pos, final int value)
525     {
526         buf[_pos] = (byte)((value >> 24) & 0xFF);
527         buf[_pos+1] = (byte)((value >> 16) & 0xFF);
528         buf[_pos+2] = (byte)((value >> 8) & 0xFF);
529         buf[_pos+3] = (byte) (value & 0xFF);
530     }
531
532     /**
533      * Start a CDR encapsulation. All subsequent writes
534      * will place data in the encapsulation until
535      * endEncapsulation is called. This will write
536      * the size of the encapsulation.
537      */

538
539     public final void beginEncapsulation()
540     {
541         // align to the next four byte boundary
542
// as a preparation for writing the size
543
// integer (which we don't know before the
544
// encapsulation is closed)
545

546         check(8,4);
547
548         // leave 4 bytes for the encaps. size that
549
// is to be written later
550

551         pos += 4;
552         index += 4;
553
554         /* Because encapsulations can be nested, we need to
555            remember the beginnning of the enclosing
556            encapsulation (or -1 if we are in the outermost encapsulation)
557            Also, remember the current index and the indirection maps because
558            we need to restore these when closing the encapsulation */

559
560         getEncapsStack().push
561         (
562             new EncapsInfo(index, encaps_start,
563                            getValueMap(),
564                            getRepIdMap(),
565                            getCodebaseMap())
566         );
567
568         // set up new indirection maps for this encapsulation
569

570         valueMap = ObjectUtil.createIdentityHashMap();
571         repIdMap = new HashMap();
572         codebaseMap = new HashMap();
573
574         // the start of this encapsulation
575

576         encaps_start = pos;
577         beginEncapsulatedArray();
578     }
579
580     /**
581      * Can be used locally for data type conversions
582      * without preceeding call to beginEncapsulation, i.e.
583      * without a leading long that indicates the size.
584      */

585
586     public final void beginEncapsulatedArray()
587     {
588         /* set the index for alignment to 0, i.e. align relative to the
589            beginning of the encapsulation */

590         resetIndex();
591
592         // byte_order flag set to FALSE
593

594         buffer[pos++] = 0;
595         index++;
596     }
597
598     /**
599      * Terminate the encapsulation by writing its length
600      * to its beginning.
601      */

602
603     public final void endEncapsulation()
604     {
605         if( encaps_start == -1 )
606             throw new MARSHAL JavaDoc("Too many end-of-encapsulations");
607         if( encaps_stack == null )
608         {
609             throw new MARSHAL JavaDoc("Internal Error - closeEncapsulation failed");
610         }
611
612         // determine the size of this encapsulation
613

614         int encaps_size = pos - encaps_start;
615
616         // insert the size integer into the appropriate place
617

618         buffer[encaps_start -4 ] = (byte)((encaps_size >>> 24) & 0xFF);
619         buffer[encaps_start -3 ] = (byte)((encaps_size >>> 16) & 0xFF);
620         buffer[encaps_start -2 ] = (byte)((encaps_size >>> 8) & 0xFF);
621         buffer[encaps_start -1 ] = (byte)(encaps_size & 0xFF);
622
623         /* restore index and encaps_start information and indirection maps */
624
625         EncapsInfo ei = (EncapsInfo)getEncapsStack().pop();
626         encaps_start = ei.start;
627         index = ei.index + encaps_size;
628         valueMap = ei.valueMap;
629         repIdMap = ei.repIdMap;
630         codebaseMap = ei.codebaseMap;
631     }
632
633     public byte[] getBufferCopy()
634     {
635         ByteArrayOutputStream bos =
636             new ByteArrayOutputStream();
637
638         try
639         {
640             write( bos, 0, size());
641         }
642         catch( IOException io )
643         {
644             // Debug.output(1, io );
645
}
646
647         return bos.toByteArray();
648     }
649
650     private void resetIndex()
651     {
652         index = 0;
653     }
654
655     public int size()
656     {
657         return pos + deferred_writes;
658     }
659
660     public void reset()
661     {
662         if (deferredArrayQueue != null)
663         {
664             deferredArrayQueue.clear();
665         }
666         pos = 0;
667         deferred_writes = 0;
668         index = 0;
669     }
670
671     protected void finalize() throws Throwable JavaDoc
672     {
673         try
674         {
675             bufMgr.returnBuffer( buffer, true );
676         }
677         finally
678         {
679             super.finalize();
680         }
681     }
682
683     public final void skip(final int step)
684     {
685         pos += step;
686         index += step;
687     }
688
689     public final void reduceSize(final int amount)
690     {
691         pos -= amount;
692     }
693
694     /**
695      * Add <tt>amount</tt> empty space
696      */

697
698     public final void increaseSize(final int amount)
699     {
700         pos += amount;
701
702         check( amount );
703     }
704
705     public void setBuffer(final byte[] b)
706     {
707         bufMgr.returnBuffer( buffer, true );
708
709         buffer = b;
710
711         reset();
712     }
713
714     // For appligator
715

716     public void setBufferWithoutReset (byte[] b, int size)
717     {
718         close();
719         buffer = b;
720         pos = size;
721     }
722
723     /**************************************************
724      * The following operations are from OutputStream *
725      **************************************************/

726
727     public org.omg.CORBA.portable.InputStream JavaDoc create_input_stream()
728     {
729         if (deferred_writes > 0)
730         {
731             ByteArrayOutputStream baos = new ByteArrayOutputStream(index + 1);
732             try
733             {
734                 write(baos, 0, index);
735             }
736             catch (IOException e)
737             {
738                 throw new MARSHAL JavaDoc(e.toString());
739             }
740             return new CDRInputStream(orb, baos.toByteArray());
741         }
742         else
743         {
744             byte[] result = new byte[index + 1];
745             System.arraycopy(buffer, 0, result, 0, result.length);
746             return new CDRInputStream(orb, result);
747         }
748     }
749
750     public final void write_any(final org.omg.CORBA.Any JavaDoc value)
751     {
752         write_TypeCode( value.type() );
753         value.write_value( this ) ;
754     }
755
756     public final void write_boolean(final boolean value)
757     {
758         check(1);
759
760         if( value )
761             buffer[pos++] = 1;
762         else
763             buffer[pos++] = 0;
764         index++;
765     }
766
767     public final void write_boolean_array
768        (final boolean[] value, final int offset, final int length)
769     {
770         if (value != null )
771         {
772             //no alignment necessary
773
check(length);
774
775             for( int i = offset; i < offset+length; i++ )
776             {
777                 if( value[i] )
778                     buffer[pos++] = 1;
779                 else
780                     buffer[pos++] = 0;
781             }
782             index += length;
783         }
784     }
785
786
787     /**
788      * Writes char according to specified encoding.
789      */

790     public final void write_char(final char c)
791     {
792         check( 1 );
793
794         int too_large_mask =
795             (codeSet == CodeSet.ISO8859_1)?
796         0xFF00 : //ISO8859-1
797
0xFF80; //UTF-8
798

799         if( (c & too_large_mask) != 0 )//Are there any 1s in the MSB?
800
{
801             throw new org.omg.CORBA.DATA_CONVERSION JavaDoc(
802                 "char (" + c +
803                 ") out of range for " +
804                 CodeSet.csName( codeSet) );
805         }
806
807         index++;
808         buffer[ pos++ ] = (byte) c;
809     }
810
811     public final void write_char_array
812        (final char[] value, final int offset, final int length)
813     {
814         if( value == null )
815             throw new MARSHAL JavaDoc( "Null References" );
816
817         //no alignment necessary
818
check( length );
819
820         int too_large_mask =
821             (codeSet == CodeSet.ISO8859_1)?
822         0xFF00 : //ISO8859-1
823
0xFF80; //UTF-8
824

825
826         for( int i = offset; i < offset+length; i++)
827         {
828             if( (value[i] & too_large_mask) != 0 )
829             {
830                 throw new MARSHAL JavaDoc("char (" + value[i] +
831                                   ") out of range for " +
832                                   CodeSet.csName( codeSet ));
833             }
834
835             buffer[ pos++ ] = (byte) value[i];
836         }
837
838         index += length;
839     }
840
841     public final void write_string(final String JavaDoc s)
842     {
843         if( s == null )
844         {
845             throw new MARSHAL JavaDoc("Null References");
846         }
847
848         // size indicator ulong + length in chars( i.e. bytes for type char)
849
// incl. terminating NUL char
850
int size = 4 + s.length() + 1;
851         check( size, 4 );
852
853         int sizepos = pos;
854         pos += 4;
855         index += 4;
856
857         char ch;
858         for (int i = 0; i < s.length(); i++)
859             write_char_i(s.charAt(i),false,false, codeSet);
860
861         buffer[ pos++ ] = (byte) 0; //terminating NUL char
862
index ++;
863         size = pos - (sizepos + 4); // compute translated size
864
_write4int( buffer,sizepos,size);
865     }
866
867     public final void write_wchar(final char c)
868     {
869         check(3);
870         write_char_i (c, useBOM, true, codeSetW);//with length indicator
871
}
872
873     // Used by both write_wchar/wstring and write_string
874
private final void write_char_i (final char c,
875                                      final boolean write_bom,
876                                      final boolean write_length_indicator,
877                                      final int cs)
878     {
879         // alignment/check must happen prior to calling.
880
switch( cs )
881         {
882             case CodeSet.ISO8859_1 :
883             {
884                 buffer[pos++] = (byte) c;
885                 index ++;
886                 break;
887             }
888             case CodeSet.UTF8 :
889             {
890                 if( c <= 0x007F )
891                 {
892                     if( giop_minor == 2 && write_length_indicator )
893                     {
894                         //the chars length in bytes
895
write_octet( (byte) 1 );
896                     }
897
898                     buffer[ pos++ ] = (byte) c;
899                     index++;
900                 }
901                 else if( c > 0x07FF )
902                 {
903                     if( giop_minor == 2 && write_length_indicator )
904                     {
905                         //the chars length in bytes
906
write_octet( (byte) 3 );
907                     }
908
909                     buffer[pos++]=(byte)(0xE0 | ((c >> 12) & 0x0F));
910                     buffer[pos++]=(byte)(0x80 | ((c >> 6) & 0x3F));
911                     buffer[pos++]=(byte)(0x80 | ((c >> 0) & 0x3F));
912
913                     index += 3;
914                 }
915                 else
916                 {
917                     if( giop_minor == 2 && write_length_indicator )
918                     {
919                         //the chars length in bytes
920
write_octet( (byte) 2 );
921                     }
922
923                     buffer[pos++]=(byte)(0xC0 | ((c >> 6) & 0x1F));
924                     buffer[pos++]=(byte)(0x80 | ((c >> 0) & 0x3F));
925
926                     index += 2;
927                 }
928                 break;
929             }
930             case CodeSet.UTF16 :
931             {
932                 if( giop_minor == 2 )
933                 {
934                     if( write_length_indicator )
935                     {
936                         //the chars length in bytes
937
write_octet( (byte) 2 );
938                     }
939
940                     if( write_bom )
941                     {
942                         //big endian encoding
943
buffer[ pos++ ] = (byte) 0xFE;
944                         buffer[ pos++ ] = (byte) 0xFF;
945
946                         index += 2;
947                     }
948
949                     //write unaligned
950
buffer[pos++] = (byte)((c >> 8) & 0xFF);
951                     buffer[pos++] = (byte) (c & 0xFF);
952                     index += 2;
953                 }
954                 else
955                 {
956                     //UTF-16 char is treated as an ushort (write aligned)
957
write_short( (short) c );
958                 }
959
960                 break;
961             }
962             default :
963             {
964                 throw new CODESET_INCOMPATIBLE JavaDoc("Bad codeset: " + codeSet);
965             }
966         }
967     }
968
969     public final void write_wchar_array
970        (final char[] value, final int offset, final int length)
971     {
972         if( value == null )
973             throw new MARSHAL JavaDoc("Null References");
974
975         check( length * 3 );
976
977         for( int i = offset; i < offset+length; i++)
978             write_wchar( value[i] );
979     }
980
981     public final void write_wstring(final String JavaDoc s)
982     {
983         if( s == null )
984         {
985             throw new MARSHAL JavaDoc("Null References");
986         }
987
988         //size ulong + no of bytes per char (max 3 if UTF-8) +
989
//terminating NUL
990
check( 4 + s.length() * 3 + 3, 4);
991
992         int startPos = pos; // store position for length indicator
993
pos += 4;
994         index += 4; // reserve for length indicator
995

996         //the byte order marker
997
if( giop_minor == 2 && useBOM && s.length() > 0)
998         {
999             //big endian encoding
1000
buffer[ pos++ ] = (byte) 0xFE;
1001            buffer[ pos++ ] = (byte) 0xFF;
1002
1003            index += 2;
1004        }
1005
1006        // write characters in current wide encoding, add null terminator
1007
for( int i = 0; i < s.length(); i++ )
1008        {
1009            write_char_i( s.charAt(i), false, false, codeSetW ); //no BOM
1010
}
1011
1012        if( giop_minor < 2 )
1013        {
1014            //terminating NUL char
1015
write_char_i( (char)0, false, false, codeSetW ); //no BOM
1016
}
1017
1018        int str_size = 0;
1019        if( giop_minor == 2 )
1020        {
1021            //size in bytes (without the size ulong)
1022
str_size = pos - startPos - 4;
1023        }
1024        else
1025        {
1026            if( codeSetW == CodeSet.UTF8 )
1027            {
1028                //size in bytes (without the size ulong)
1029
str_size = pos - startPos - 4;
1030            }
1031            else if( codeSetW == CodeSet.UTF16 )
1032            {
1033                //size in chars (+ NUL char)
1034
str_size = s.length() + 1;
1035            }
1036        }
1037
1038        // write length indicator
1039
_write4int( buffer, startPos, str_size );
1040    }
1041
1042    public final void write_double(final double value)
1043    {
1044        write_longlong (Double.doubleToLongBits (value));
1045    }
1046
1047    public final void write_double_array
1048       (final double[] value, final int offset, final int length)
1049    {
1050        //if nothing has to be written, return, and especially DON'T
1051
//ALIGN
1052
if( length == 0 )
1053        {
1054            return;
1055        }
1056
1057        /* align to 8 byte boundary */
1058
1059        check(7 + length*8, 8);
1060
1061        if( value != null )
1062        {
1063            for( int i = offset; i < offset+length; i++ )
1064            {
1065                long d = Double.doubleToLongBits(value[i]);
1066                buffer[pos] = (byte)((d >>> 56) & 0xFF);
1067                buffer[pos+1] = (byte)((d >>> 48) & 0xFF);
1068                buffer[pos+2] = (byte)((d >>> 40) & 0xFF);
1069                buffer[pos+3] = (byte)((d >>> 32) & 0xFF);
1070                buffer[pos+4] = (byte)((d >>> 24) & 0xFF);
1071                buffer[pos+5] = (byte)((d >>> 16) & 0xFF);
1072                buffer[pos+6] = (byte)((d >>> 8) & 0xFF);
1073                buffer[pos+7] = (byte) (d & 0xFF);
1074                pos += 8;
1075            }
1076            index += 8*length;
1077        }
1078    }
1079
1080    public final void write_fixed(final java.math.BigDecimal JavaDoc value)
1081    {
1082        //#ifjdk 1.2
1083
String JavaDoc v = value.unscaledValue().toString();
1084        //#else
1085
//# String v = value.movePointRight(value.scale()).toString();
1086
//#endif
1087
byte [] representation;
1088        int b, c;
1089
1090        // Strip off any leading '-' from value to encode
1091

1092        if (v.startsWith ("-"))
1093        {
1094            v = v.substring (1);
1095        }
1096
1097        if( (v.length() %2) == 0)
1098        {
1099            representation = new byte[ v.length()/2 +1];
1100            representation[0] = 0x00;
1101
1102            for( int i = 0; i < v.length(); i++ )
1103            {
1104                c = Character.digit(v.charAt(i), 10);
1105                b = representation[(1 + i)/2] << 4;
1106                b |= c;
1107                representation[(1 + i)/2] = (byte)b;
1108            }
1109        }
1110        else
1111        {
1112            representation = new byte[ (v.length()+1) /2];
1113            for( int i = 0; i < v.length(); i++ )
1114            {
1115                c = Character.digit(v.charAt(i), 10);
1116                b = representation[i/2] << 4;
1117                b |= c;
1118                representation[i/2] = (byte)b;
1119            }
1120        }
1121        b = representation[representation.length-1] << 4;
1122
1123        representation[representation.length-1] =
1124            (byte)((value.signum() < 0 )? (b | 0xD) : (b | 0xC));
1125
1126        check(representation.length);
1127        System.arraycopy(representation,0,buffer,pos,representation.length);
1128        index += representation.length;
1129        pos += representation.length;
1130
1131    }
1132
1133    public final void write_float(final float value)
1134    {
1135        write_long(Float.floatToIntBits(value));
1136    }
1137
1138    public final void write_float_array
1139       (final float[] value, final int offset, final int length)
1140    {
1141        //if nothing has to be written, return, and especially DON'T
1142
//ALIGN
1143
if( length == 0 )
1144        {
1145            return;
1146        }
1147
1148        /* align to 4 byte boundary */
1149
1150        check(3 + length*4,4);
1151
1152        if( value != null )
1153        {
1154            for( int i = offset; i < offset+length; i++ )
1155            {
1156                _write4int(buffer,pos, Float.floatToIntBits( value[i] ));
1157                pos += 4;
1158            }
1159            index += 4*length;
1160        }
1161    }
1162
1163    public final void write_long(final int value)
1164    {
1165        check(7,4);
1166
1167        _write4int(buffer,pos,value);
1168
1169        pos += 4; index += 4;
1170    }
1171
1172    public final void write_long_array
1173       (final int[] value, final int offset, final int length)
1174    {
1175        //if nothing has to be written, return, and especially DON'T
1176
//ALIGN
1177
if( length == 0 )
1178        {
1179            return;
1180        }
1181
1182        /* align to 4 byte boundary */
1183
1184        check(3 + length*4,4);
1185
1186
1187        int remainder = 4 - (index % 4);
1188        if (remainder != 4)
1189        {
1190            index += remainder;
1191            pos+=remainder;
1192        }
1193
1194        if( value != null )
1195        {
1196            for( int i = offset; i < offset+length; i++ )
1197            {
1198                _write4int(buffer,pos,value[i]);
1199                pos += 4;
1200            }
1201            index += 4*length;
1202        }
1203    }
1204
1205    public final void write_longlong(final long value)
1206    {
1207        check(15,8);
1208
1209        buffer[pos] = (byte)((value >>> 56) & 0xFF);
1210        buffer[pos+1] = (byte)((value >>> 48) & 0xFF);
1211        buffer[pos+2] = (byte)((value >>> 40) & 0xFF);
1212        buffer[pos+3] = (byte)((value >>> 32) & 0xFF);
1213        buffer[pos+4] = (byte)((value >>> 24) & 0xFF);
1214        buffer[pos+5] = (byte)((value >>> 16) & 0xFF);
1215        buffer[pos+6] = (byte)((value >>> 8) & 0xFF);
1216        buffer[pos+7] = (byte)(value & 0xFF);
1217
1218        index += 8;
1219        pos += 8;
1220    }
1221
1222    public final void write_longlong_array
1223       (final long[] value, final int offset, final int length)
1224    {
1225        //if nothing has to be written, return, and especially DON'T
1226
//ALIGN
1227
if( length == 0 )
1228        {
1229            return;
1230        }
1231
1232        check(7 + length*8,8);
1233
1234        if( value != null )
1235        {
1236            for( int i = offset; i < offset+length; i++ )
1237            {
1238                buffer[pos] = (byte)((value[i] >>> 56) & 0xFF);
1239                buffer[pos+1] = (byte)((value[i] >>> 48) & 0xFF);
1240                buffer[pos+2] = (byte)((value[i] >>> 40) & 0xFF);
1241                buffer[pos+3] = (byte)((value[i] >>> 32) & 0xFF);
1242                buffer[pos+4] = (byte)((value[i] >>> 24) & 0xFF);
1243                buffer[pos+5] = (byte)((value[i] >>> 16) & 0xFF);
1244                buffer[pos+6] = (byte)((value[i] >>> 8) & 0xFF);
1245                buffer[pos+7] = (byte) (value[i] & 0xFF);
1246                pos += 8;
1247            }
1248            index += 8*length;
1249        }
1250    }
1251
1252    public void write_Object(final org.omg.CORBA.Object JavaDoc value)
1253    {
1254
1255        if( value == null )
1256        {
1257            IORHelper.write(this, null_ior );
1258        }
1259        else
1260        {
1261            if( value instanceof org.omg.CORBA.LocalObject JavaDoc )
1262                throw new MARSHAL JavaDoc("Attempt to serialize a locality-constrained object.");
1263            org.omg.CORBA.portable.ObjectImpl JavaDoc obj =
1264                (org.omg.CORBA.portable.ObjectImpl JavaDoc)value;
1265            IORHelper.write(this, ((Delegate)obj._get_delegate()).getIOR() );
1266        }
1267    }
1268
1269    ////////////////////////////////////////////// NEW!
1270
public void write_IOR(final IOR JavaDoc ior)
1271    {
1272        if( ior == null )
1273        {
1274            IORHelper.write(this, null_ior );
1275        }
1276        else
1277        {
1278            IORHelper.write(this, ior);
1279        }
1280    }
1281    ////////////////////////////////////////////// NEW!
1282

1283    public final void write_octet(final byte value)
1284    {
1285        check(1);
1286        index++;
1287        buffer[pos++] = value;
1288    }
1289
1290    public final void write_octet_array( final byte[] value,
1291                                         final int offset,
1292                                         final int length)
1293    {
1294        if( value != null )
1295        {
1296            if( length > 4000 )
1297            {
1298                deferredArrayQueue.add( new DeferredWriteFrame( index, offset, length, value ));
1299                index += length;
1300                deferred_writes += length;
1301            }
1302            else
1303            {
1304                check(length);
1305                System.arraycopy(value,offset,buffer,pos,length);
1306                index += length;
1307                pos += length;
1308            }
1309        }
1310    }
1311
1312    public final void write_Principal(final org.omg.CORBA.Principal JavaDoc value)
1313    {
1314        throw new NO_IMPLEMENT JavaDoc ("Principal deprecated");
1315    }
1316
1317    public final void write_short(final short value)
1318    {
1319        check(3,2);
1320
1321        buffer[pos] = (byte)((value >> 8) & 0xFF);
1322        buffer[pos+1] = (byte)(value & 0xFF);
1323        index += 2; pos+=2;
1324    }
1325
1326    public final void write_short_array
1327       (final short[] value, final int offset, final int length)
1328    {
1329        //if nothing has to be written, return, and especially DON'T
1330
//ALIGN
1331
if( length == 0 )
1332        {
1333            return;
1334        }
1335
1336        /* align to 2-byte boundary */
1337
1338        check(2*length + 3);
1339
1340        int remainder = 2 - (index % 2);
1341        if (remainder != 2)
1342        {
1343            index += remainder;
1344            pos+=remainder;
1345        }
1346
1347        if( value != null )
1348        {
1349            for( int i = offset; i < offset+length; i++ )
1350            {
1351                buffer[pos] = (byte)((value[i] >>> 8) & 0xFF);
1352                buffer[pos+1] = (byte)( value[i] & 0xFF);
1353                pos += 2;
1354            }
1355            index += 2*length;
1356        }
1357    }
1358
1359    public final void write_TypeCode (org.omg.CORBA.TypeCode JavaDoc value)
1360    {
1361        String JavaDoc id = null;
1362        org.omg.CORBA.TypeCode JavaDoc cached = null;
1363
1364        try
1365        {
1366            // Get the id for this typecode.
1367
id = value.id();
1368        }
1369        // Masking on purpose as only determining whether to cache here.
1370
catch (BadKind JavaDoc e)
1371        {
1372        }
1373
1374        if (compactTypeCodes > 0 && id != null)
1375        {
1376            if (cachedTypecodes == null)
1377            {
1378                cachedTypecodes = new HashMap();
1379            }
1380            else
1381            {
1382                // We may previously have already compacted and cached this
1383
// typecode.
1384
cached = (org.omg.CORBA.TypeCode JavaDoc)cachedTypecodes.get (id);
1385            }
1386            // If we don't have a cached value get the compact form and
1387
// cache it.
1388
if (cached == null)
1389            {
1390                value = value.get_compact_typecode();
1391                cachedTypecodes.put (id, value);
1392            }
1393            else
1394            {
1395                value = cached;
1396            }
1397        }
1398        write_TypeCode (value, null);
1399    }
1400
1401    private final void writeRecursiveTypeCode
1402       (final org.omg.CORBA.TypeCode JavaDoc value, final Map tcMap) throws BadKind JavaDoc
1403    {
1404        write_long( -1 ); // recursion marker
1405
int negative_offset =
1406            ((Integer JavaDoc) tcMap.get( value.id())).intValue() - size() - 4;
1407
1408        write_long( negative_offset );
1409    }
1410
1411    private final void write_TypeCode
1412       (final org.omg.CORBA.TypeCode JavaDoc value, Map tcMap)
1413    {
1414        if (value == null)
1415        {
1416            throw new BAD_PARAM JavaDoc("TypeCode is null");
1417        }
1418
1419        int _kind = value.kind().value();
1420        int _mc; // member count
1421

1422        try
1423        {
1424            if( TypeCode.isRecursive(value) &&
1425                tcMap != null &&
1426                tcMap.containsKey( value.id()) )
1427            {
1428                writeRecursiveTypeCode( value, tcMap );
1429            }
1430            else
1431            {
1432                // regular TypeCodes
1433
switch( _kind )
1434                {
1435                    case 0:
1436                    case 1:
1437                    case 2:
1438                    case 3:
1439                    case 4:
1440                    case 5:
1441                    case 6:
1442                    case 7:
1443                    case 8:
1444                    case 9:
1445                    case 10:
1446                    case 11:
1447                    case 12:
1448                    case 13:
1449                    case 23:
1450                    case 24:
1451                    case 25:
1452                    case 26:
1453                    write_long( _kind );
1454                    break;
1455                    case TCKind._tk_objref:
1456                    write_long( _kind );
1457                    beginEncapsulation();
1458                    write_string( value.id() );
1459                    write_string( value.name() );
1460                    endEncapsulation();
1461                    break;
1462                    case TCKind._tk_struct:
1463                    case TCKind._tk_except:
1464                    if (useIndirection && tcMap != null &&
1465                        tcMap.containsKey (value.id()))
1466                    {
1467                        writeRecursiveTypeCode( value, tcMap );
1468                    }
1469                    else
1470                    {
1471                        write_long( _kind );
1472                        if (tcMap == null)
1473                        {
1474                            tcMap = new HashMap();
1475                        }
1476                        tcMap.put( value.id(), new Integer JavaDoc( pos ) );
1477                        getRecursiveTCMap().put( value.id(), value );
1478
1479                        beginEncapsulation();
1480                        write_string(value.id());
1481                        write_string(value.name());
1482                        _mc = value.member_count();
1483                        write_long(_mc);
1484                        for( int i = 0; i < _mc; i++)
1485                        {
1486                            write_string( value.member_name(i) );
1487                            write_TypeCode( value.member_type(i), tcMap );
1488                        }
1489                        endEncapsulation();
1490                    }
1491                    break;
1492                    case TCKind._tk_enum:
1493                    if (useIndirection && tcMap != null &&
1494                        tcMap.containsKey (value.id()))
1495                    {
1496                        writeRecursiveTypeCode( value, tcMap );
1497                    }
1498                    else
1499                    {
1500                        write_long( _kind );
1501                        if (tcMap == null)
1502                        {
1503                            tcMap = new HashMap();
1504                        }
1505                        tcMap.put( value.id(), new Integer JavaDoc( pos ) );
1506                        getRecursiveTCMap().put( value.id(), value );
1507
1508                        beginEncapsulation();
1509                        write_string( value.id());
1510                        write_string( value.name());
1511                        _mc = value.member_count();
1512                        write_long(_mc);
1513                        for( int i = 0; i < _mc; i++)
1514                        {
1515                            write_string( value.member_name(i) );
1516                        }
1517                        endEncapsulation();
1518                    }
1519                    break;
1520                    case TCKind._tk_union:
1521                    if (useIndirection && tcMap != null &&
1522                        tcMap.containsKey (value.id()))
1523                    {
1524                        writeRecursiveTypeCode( value, tcMap );
1525                    }
1526                    else
1527                    {
1528                        write_long( _kind );
1529                        if (tcMap == null)
1530                        {
1531                            tcMap = new HashMap();
1532                        }
1533                        tcMap.put( value.id(), new Integer JavaDoc( pos ) );
1534                        getRecursiveTCMap().put( value.id() , value );
1535
1536                        beginEncapsulation();
1537                        write_string( value.id() );
1538                        write_string( value.name() );
1539
1540                        write_TypeCode( value.discriminator_type());
1541                        write_long( value.default_index());
1542                        _mc = value.member_count();
1543                        write_long(_mc);
1544                        for( int i = 0; i < _mc; i++)
1545                        {
1546                            if( i == value.default_index() )
1547                            {
1548                                write_octet((byte)0);
1549                            }
1550                            else
1551                            {
1552                                value.member_label(i).write_value( this );
1553                            }
1554                            write_string( value.member_name(i));
1555                            write_TypeCode( value.member_type(i), tcMap );
1556                        }
1557                        endEncapsulation();
1558                    }
1559                    break;
1560                    case TCKind._tk_wstring:
1561                    case TCKind._tk_string:
1562                    write_long( _kind );
1563                    write_long(value.length());
1564                    break;
1565                    case TCKind._tk_fixed:
1566                    write_long( _kind );
1567                    write_ushort( value.fixed_digits() );
1568                    write_short( value.fixed_scale() );
1569                    break;
1570                    case TCKind._tk_array:
1571                    case TCKind._tk_sequence:
1572                    write_long( _kind );
1573                    beginEncapsulation();
1574                    write_TypeCode( value.content_type(), tcMap);
1575                    write_long(value.length());
1576                    endEncapsulation();
1577                    break;
1578                    case TCKind._tk_alias:
1579                    if (useIndirection && tcMap != null &&
1580                        tcMap.containsKey (value.id()))
1581                    {
1582                        writeRecursiveTypeCode( value, tcMap );
1583                    }
1584                    else
1585                    {
1586                        write_long( _kind );
1587                        if (tcMap == null)
1588                        {
1589                            tcMap = new HashMap();
1590                        }
1591                        tcMap.put( value.id(), new Integer JavaDoc( pos ) );
1592                        getRecursiveTCMap().put( value.id(), value );
1593
1594                        beginEncapsulation();
1595                        write_string(value.id());
1596                        write_string(value.name());
1597                        write_TypeCode( value.content_type(), tcMap);
1598                        endEncapsulation();
1599                    }
1600                    break;
1601                    case TCKind._tk_value:
1602                    if (useIndirection && tcMap != null &&
1603                        tcMap.containsKey (value.id()))
1604                    {
1605                        writeRecursiveTypeCode( value, tcMap );
1606                    }
1607                    else
1608                    {
1609                        write_long( _kind );
1610                        if (tcMap == null)
1611                        {
1612                            tcMap = new HashMap();
1613                        }
1614                        tcMap.put( value.id(), new Integer JavaDoc( pos ) );
1615                        getRecursiveTCMap().put( value.id(), value );
1616
1617                        beginEncapsulation();
1618                        write_string(value.id());
1619                        write_string(value.name());
1620                        write_short( value.type_modifier() );
1621                        org.omg.CORBA.TypeCode JavaDoc base = value.concrete_base_type();
1622                        if (base != null)
1623                            write_TypeCode(base, tcMap);
1624                        else
1625                            write_long (TCKind._tk_null);
1626                        _mc = value.member_count();
1627                        write_long(_mc);
1628                        for( int i = 0; i < _mc; i++)
1629                        {
1630                            write_string( value.member_name(i) );
1631                            write_TypeCode( value.member_type(i), tcMap );
1632                            write_short( value.member_visibility(i) );
1633                        }
1634                        endEncapsulation();
1635                    }
1636                    break;
1637                    case TCKind._tk_value_box:
1638                    if (useIndirection && tcMap != null &&
1639                        tcMap.containsKey (value.id()))
1640                    {
1641                        writeRecursiveTypeCode( value, tcMap );
1642                    }
1643                    else
1644                    {
1645                        write_long( _kind );
1646                        if (tcMap == null)
1647                        {
1648                            tcMap = new HashMap();
1649                        }
1650                        tcMap.put( value.id(), new Integer JavaDoc( pos ) );
1651                        getRecursiveTCMap().put( value.id(), value );
1652
1653                        beginEncapsulation();
1654                        write_string(value.id());
1655                        write_string(value.name());
1656                        write_TypeCode( value.content_type(), tcMap);
1657                        endEncapsulation();
1658                    }
1659                    break;
1660                    case TCKind._tk_abstract_interface:
1661                    if (useIndirection && tcMap != null &&
1662                        tcMap.containsKey (value.id()))
1663                    {
1664                        writeRecursiveTypeCode( value, tcMap );
1665                    }
1666                    else
1667                    {
1668                        write_long( _kind );
1669                        if (tcMap == null)
1670                        {
1671                            tcMap = new HashMap();
1672                        }
1673                        tcMap.put( value.id(), new Integer JavaDoc( pos ) );
1674                        getRecursiveTCMap().put( value.id(), value );
1675
1676                        beginEncapsulation();
1677                        write_string(value.id());
1678                        write_string(value.name());
1679                        endEncapsulation();
1680                    }
1681                    break;
1682                    default:
1683                    throw new MARSHAL JavaDoc ("Cannot handle TypeCode with kind: " + _kind);
1684                }
1685            }
1686        }
1687        catch (BadKind JavaDoc ex)
1688        {
1689            throw new MARSHAL JavaDoc
1690                ("When processing TypeCode with kind: " + _kind + " caught " + ex);
1691        }
1692        catch (Bounds JavaDoc ex)
1693        {
1694            throw new MARSHAL JavaDoc
1695                ("When processing TypeCode with kind: " + _kind + " caught " + ex);
1696        }
1697    }
1698
1699    public final void write_ulong(final int value)
1700    {
1701        write_long (value);
1702    }
1703
1704    public final void write_ulong_array
1705       (final int[] value, final int offset, final int length)
1706    {
1707        write_long_array (value, offset, length);
1708    }
1709
1710    public final void write_ulonglong(final long value)
1711    {
1712        write_longlong (value);
1713    }
1714
1715    public final void write_ulonglong_array
1716       (final long[] value, final int offset, final int length)
1717    {
1718        write_longlong_array (value, offset, length);
1719    }
1720
1721    public final void write_ushort(final short value)
1722    {
1723        write_short (value);
1724    }
1725
1726    public final void write_ushort_array
1727       (final short[] value, final int offset, final int length)
1728    {
1729        write_short_array (value, offset, length);
1730    }
1731
1732    /**
1733     * Reads a value of the type indicated by <code>tc</code> from the
1734     * InputStream <code>in</code> and remarshals it to this CDROutputStream.
1735     * Called from Any.
1736     */

1737    public final void write_value ( final org.omg.CORBA.TypeCode JavaDoc tc,
1738                                    final org.omg.CORBA.portable.InputStream JavaDoc in )
1739    {
1740        if (tc == null)
1741        {
1742            throw new BAD_PARAM JavaDoc("TypeCode is null");
1743        }
1744
1745        int kind = tc.kind().value();
1746
1747        try
1748        {
1749            switch (kind)
1750            {
1751                case TCKind._tk_null:
1752                case TCKind._tk_void:
1753                break;
1754                case TCKind._tk_boolean:
1755                write_boolean( in.read_boolean());
1756                break;
1757                case TCKind._tk_char:
1758                write_char( in.read_char());
1759                break;
1760                case TCKind._tk_wchar:
1761                write_wchar( in.read_wchar());
1762                break;
1763                case TCKind._tk_octet:
1764                write_octet( in.read_octet());
1765                break;
1766                case TCKind._tk_short:
1767                write_short( in.read_short());
1768                break;
1769                case TCKind._tk_ushort:
1770                write_ushort(in.read_ushort());
1771                break;
1772                case TCKind._tk_long:
1773                write_long( in.read_long());
1774                break;
1775                case TCKind._tk_ulong:
1776                write_ulong( in.read_ulong());
1777                break;
1778                case TCKind._tk_float:
1779                write_float( in.read_float());
1780                break;
1781                case TCKind._tk_double:
1782                write_double(in.read_double());
1783                break;
1784                case TCKind._tk_longlong:
1785                write_longlong(in.read_longlong());
1786                break;
1787                case TCKind._tk_ulonglong:
1788                write_ulonglong( in.read_ulonglong());
1789                break;
1790                case TCKind._tk_any:
1791                write_any( in.read_any());
1792                break;
1793                case TCKind._tk_TypeCode:
1794                write_TypeCode(in.read_TypeCode());
1795                break;
1796                case TCKind._tk_Principal:
1797                throw new NO_IMPLEMENT JavaDoc ("Principal deprecated");
1798                case TCKind._tk_objref:
1799                write_Object( in.read_Object());
1800                break;
1801                case TCKind._tk_string:
1802                write_string( in.read_string());
1803                break;
1804                case TCKind._tk_wstring:
1805                write_wstring( in.read_wstring());
1806                break;
1807                case TCKind._tk_fixed:
1808                write_fixed (in.read_fixed());
1809                break;
1810                case TCKind._tk_array:
1811                {
1812                    int length = tc.length();
1813                    if( tc.content_type().kind().value() == TCKind._tk_octet )
1814                    {
1815                        check( length );
1816                        in.read_octet_array( buffer, pos, length);
1817                        index+= length;
1818                        pos += length;
1819                    }
1820                    else
1821                    {
1822                        for( int i = 0; i < length; i++ )
1823                            write_value( tc.content_type(), in );
1824                    }
1825                    break;
1826                }
1827                case TCKind._tk_sequence:
1828                {
1829                    int len = in.read_long();
1830                    write_long(len);
1831
1832                    org.omg.CORBA.TypeCode JavaDoc content_tc = tc.content_type();
1833                    for( int i = 0; i < len; i++ )
1834                        write_value( content_tc, in );
1835
1836                    break;
1837                }
1838                case TCKind._tk_except:
1839                write_string( in.read_string());
1840                // don't break, fall through to ...
1841
case TCKind._tk_struct:
1842                {
1843                    for( int i = 0; i < tc.member_count(); i++)
1844                        write_value( tc.member_type(i), in );
1845                    break;
1846                }
1847                case TCKind._tk_enum:
1848                {
1849                    write_long( in.read_long() );
1850                    break;
1851                }
1852                case TCKind._tk_union:
1853                {
1854                    org.omg.CORBA.TypeCode JavaDoc disc =
1855                        (org.omg.CORBA.TypeCode JavaDoc) tc.discriminator_type();
1856                    disc = TypeCode.originalType(disc);
1857                    int def_idx = tc.default_index();
1858                    int member_idx = -1;
1859
1860                    switch( disc.kind().value() )
1861                    {
1862                        case TCKind._tk_short:
1863                        {
1864                            short s = in.read_short();
1865                            write_short(s);
1866                            for(int i = 0 ; i < tc.member_count() ; i++)
1867                            {
1868                                if(i != def_idx)
1869                                {
1870                                    if(s == tc.member_label(i).extract_short())
1871                                    {
1872                                        member_idx = i;
1873                                        break;
1874                                    }
1875                                }
1876                            }
1877                            break;
1878                        }
1879                        case TCKind._tk_ushort:
1880                        {
1881                            short s = in.read_ushort();
1882                            write_ushort(s);
1883                            for(int i = 0 ; i < tc.member_count() ; i++)
1884                            {
1885                                if(i != def_idx)
1886                                {
1887                                    if(s == tc.member_label(i).extract_ushort())
1888                                    {
1889                                        member_idx = i;
1890                                        break;
1891                                    }
1892                                }
1893                            }
1894                            break;
1895                        }
1896                        case TCKind._tk_long:
1897                        {
1898                            int s = in.read_long();
1899                            write_long(s);
1900                            for(int i = 0 ; i < tc.member_count() ; i++)
1901                            {
1902                                if(i != def_idx)
1903                                {
1904                                    if(s == tc.member_label(i).extract_long())
1905                                    {
1906                                        member_idx = i;
1907                                        break;
1908                                    }
1909                                }
1910                            }
1911                            break;
1912                        }
1913                        case TCKind._tk_ulong:
1914                        {
1915                            int s = in.read_ulong();
1916                            write_ulong(s);
1917                            for(int i = 0 ; i < tc.member_count() ; i++)
1918                            {
1919                                if(i != def_idx)
1920                                {
1921                                    if(s == tc.member_label(i).extract_ulong())
1922                                    {
1923                                        member_idx = i;
1924                                        break;
1925                                    }
1926                                }
1927                            }
1928                            break;
1929                        }
1930                        case TCKind._tk_longlong:
1931                        {
1932                            long s = in.read_longlong();
1933                            write_longlong(s);
1934                            for(int i = 0 ; i < tc.member_count() ; i++)
1935                            {
1936                                if(i != def_idx)
1937                                {
1938                                    if(s == tc.member_label(i).extract_longlong())
1939                                    {
1940                                        member_idx = i;
1941                                        break;
1942                                    }
1943                                }
1944                            }
1945                            break;
1946                        }
1947                        case TCKind._tk_ulonglong:
1948                        {
1949                            long s = in.read_ulonglong();
1950                            write_ulonglong(s);
1951                            for(int i = 0 ; i < tc.member_count() ; i++)
1952                            {
1953                                if(i != def_idx)
1954                                {
1955                                    if(s == tc.member_label(i).extract_ulonglong())
1956                                    {
1957                                        member_idx = i;
1958                                        break;
1959                                    }
1960                                }
1961                            }
1962                            break;
1963                        }
1964                        case TCKind._tk_boolean:
1965                        {
1966                            boolean s = in.read_boolean();
1967                            write_boolean(s);
1968                            for(int i = 0 ; i < tc.member_count() ; i++)
1969                            {
1970                                if(i != def_idx)
1971                                {
1972                                    if(s == tc.member_label(i).extract_boolean())
1973                                    {
1974                                        member_idx = i;
1975                                        break;
1976                                    }
1977                                }
1978                            }
1979                            break;
1980                        }
1981                        case TCKind._tk_enum:
1982                        {
1983                            int s = in.read_long();
1984                            write_long(s);
1985                            for( int i = 0 ; i < tc.member_count(); i++ )
1986                            {
1987                                if( i != def_idx)
1988                                {
1989                                    int label =
1990                                    tc.member_label(i).create_input_stream().read_long();
1991                                    /* we have to use the any's input
1992                                        stream because enums are not
1993                                        inserted as longs */

1994
1995                                    if( s == label)
1996                                    {
1997                                        member_idx = i;
1998                                        break;
1999                                    }
2000                                }
2001                            }
2002                            break;
2003                        }
2004                        case TCKind._tk_char:
2005                        {
2006                            char s = in.read_char();
2007                            write_char(s);
2008                            for(int i = 0 ; i < tc.member_count() ; i++)
2009                            {
2010                                if(i != def_idx)
2011                                {
2012                                    if(s == tc.member_label(i).extract_char())
2013                                    {
2014                                        member_idx = i;
2015                                        break;
2016                                    }
2017                                }
2018                            }
2019                            break;
2020                        }
2021                        default:
2022                        throw new MARSHAL JavaDoc("Invalid union discriminator type: " + disc);
2023                    }
2024
2025                    // write the member or default value, if any
2026
// (if the union has no explicit default but the
2027
// the case labels do not cover the range of
2028
// possible discriminator values, there may be
2029
// several "implicit defaults" without associated
2030
// union values.
2031

2032                    if( member_idx != -1 )
2033                    {
2034                        write_value( tc.member_type( member_idx ), in );
2035                    }
2036                    else if( def_idx != -1 )
2037                    {
2038                        write_value( tc.member_type( def_idx ), in );
2039                    }
2040                    break;
2041                }
2042                case TCKind._tk_alias:
2043                {
2044                    write_value( tc.content_type(), in );
2045                    break;
2046                }
2047                case TCKind._tk_value_box:
2048                {
2049                    String JavaDoc id = tc.id();
2050                    org.omg.CORBA.portable.BoxedValueHelper JavaDoc helper =
2051                        ((org.jacorb.orb.ORB)orb).getBoxedValueHelper(id);
2052                    if (helper == null)
2053                        throw new RuntimeException JavaDoc
2054                            ("No BoxedValueHelper for id " + id);
2055                    java.io.Serializable JavaDoc value =
2056                        ((org.omg.CORBA_2_3.portable.InputStream JavaDoc)in).read_value(helper);
2057                    write_value (value, helper);
2058                    break;
2059                }
2060                case 0xffffffff:
2061                {
2062                    org.omg.CORBA.TypeCode JavaDoc _tc =
2063                        (org.omg.CORBA.TypeCode JavaDoc)( getRecursiveTCMap().get( tc.id() ) );
2064                    if( _tc == null )
2065                    {
2066                        throw new MARSHAL JavaDoc("Recursive TypeCode not found for " + tc.id());
2067                    }
2068                    write_value( _tc , in );
2069                    break;
2070                }
2071                default:
2072                throw new MARSHAL JavaDoc("Cannot handle TypeCode with kind " + kind);
2073            }
2074        }
2075        catch (BadKind JavaDoc ex)
2076        {
2077            throw new MARSHAL JavaDoc
2078                ("When processing TypeCode with kind: " + kind + " caught " + ex);
2079        }
2080        catch (Bounds JavaDoc ex)
2081        {
2082            throw new MARSHAL JavaDoc
2083                ("When processing TypeCode with kind: " + kind + " caught " + ex);
2084        }
2085    }
2086
2087    /**
2088     * Writes the serialized state of `value' to this stream.
2089     */

2090
2091    public void write_value(final java.io.Serializable JavaDoc value)
2092    {
2093        if (!write_special_value (value))
2094            write_value_internal (value,
2095                                  ValueHandler.getRMIRepositoryID (value.getClass()));
2096    }
2097
2098    public void write_value(final java.io.Serializable JavaDoc value,
2099                             final org.omg.CORBA.portable.BoxedValueHelper JavaDoc factory)
2100    {
2101        if (!write_special_value (value))
2102        {
2103            check(7,4);
2104            getValueMap().put (value, new Integer JavaDoc(pos));
2105            write_previous_chunk_size();
2106            if ((value instanceof org.omg.CORBA.portable.IDLEntity JavaDoc) ||
2107                (value instanceof java.lang.String JavaDoc))
2108                write_long (0x7fffff00 | chunkingFlag);
2109            else
2110            {
2111                // repository id is required for RMI: types
2112
write_long (0x7fffff02 | chunkingFlag);
2113                write_repository_id (RepositoryID.repId (value.getClass()));
2114            }
2115            start_chunk();
2116            factory.write_value (this, value);
2117            end_chunk();
2118        }
2119    }
2120
2121    public void write_value(final java.io.Serializable JavaDoc value,
2122                             final java.lang.Class JavaDoc clz)
2123    {
2124        if (!write_special_value (value))
2125        {
2126            Class JavaDoc c = value.getClass();
2127            String JavaDoc repId = ValueHandler.getRMIRepositoryID(c);
2128            if (c == clz && !repId.startsWith("RMI:"))
2129                // the repository id is required for "RMI:" valuetypes
2130
write_value_internal (value, null);
2131            else if (clz.isInstance (value))
2132                write_value_internal (value, repId);
2133            else
2134                throw new BAD_PARAM JavaDoc();
2135        }
2136    }
2137
2138    public void write_value(final java.io.Serializable JavaDoc value,
2139                             final String JavaDoc repository_id)
2140    {
2141        if (!write_special_value (value))
2142            write_value_internal (value, repository_id);
2143    }
2144
2145    /**
2146     * If `value' is null, or has already been written to this stream,
2147     * then this method writes that information to the stream and returns
2148     * true, otherwise does nothing and returns false.
2149     */

2150    private boolean write_special_value(final java.io.Serializable JavaDoc value)
2151    {
2152        if (value == null)
2153        {
2154            // null tag
2155
write_long (0x00000000);
2156            return true;
2157        }
2158        else
2159        {
2160            Integer JavaDoc index = (Integer JavaDoc)getValueMap().get (value);
2161            if (index != null)
2162            {
2163
2164                // value has already been written -- make an indirection
2165
write_long (0xffffffff);
2166                write_long (index.intValue() - size());
2167                return true;
2168            }
2169            else
2170                return false;
2171        }
2172    }
2173
2174    /**
2175     * Writes `repository_id' to this stream, perhaps via indirection.
2176     */

2177    private void write_repository_id(final String JavaDoc repository_id)
2178    {
2179        Integer JavaDoc _index = (Integer JavaDoc)getRepIdMap().get (repository_id);
2180        if ( _index == null)
2181        {
2182            // a new repository id -- write it
2183

2184            // first make sure the pos we're about to remember is
2185
// a correctly aligned one, i.e., the actual writing position
2186
int remainder = 4 - (index % 4);
2187            if ( remainder != 4 )
2188            {
2189                index += remainder;
2190                pos += remainder;
2191            }
2192
2193            getRepIdMap().put (repository_id, new Integer JavaDoc(pos));
2194            write_string (repository_id);
2195        }
2196        else
2197        {
2198            // a previously written repository id -- make an indirection
2199
write_long (0xffffffff);
2200            write_long (_index.intValue() - size());
2201        }
2202    }
2203
2204    /**
2205     * Writes `codebase' to this stream, perhaps via indirection.
2206     */

2207    private void write_codebase(final String JavaDoc codebase)
2208    {
2209        Integer JavaDoc _index = null;
2210        if (codebaseMap == null)
2211        {
2212            codebaseMap = new HashMap();
2213        }
2214        else
2215        {
2216            _index = (Integer JavaDoc)getCodebaseMap().get (codebase);
2217        }
2218        if ( _index == null)
2219        {
2220            // a new codebase -- write it#
2221

2222            // first make sure the pos we're about to remember is
2223
// a correctly aligned one
2224
int remainder = 4 - (index % 4);
2225            if ( remainder != 4 )
2226            {
2227                index += remainder;
2228                pos += remainder;
2229            }
2230
2231            getCodebaseMap().put (codebase, new Integer JavaDoc(pos));
2232            write_string (codebase);
2233        }
2234        else
2235        {
2236            // a previously written codebase -- make an indirection
2237
write_long (0xffffffff);
2238            write_long (_index.intValue() - size());
2239        }
2240    }
2241
2242    /**
2243     * Writes to this stream a value header with the specified `repository_id'
2244     * and no codebase string.
2245     */

2246    private void write_value_header(final String JavaDoc[] repository_ids)
2247    {
2248        write_previous_chunk_size();
2249        if (repository_ids != null)
2250        {
2251            if( repository_ids.length > 1 )
2252            {
2253                // truncatable value type, must use chunking!
2254

2255                chunkingFlag = 0x00000008;
2256                write_long (0x7fffff06 | chunkingFlag);
2257                write_long( repository_ids.length );
2258                for( int i = 0; i < repository_ids.length; i++ )
2259                {
2260                    write_repository_id (repository_ids[i]);
2261                }
2262            }
2263            else
2264            {
2265                write_long (0x7fffff02 | chunkingFlag);
2266                write_repository_id (repository_ids[0]);
2267            }
2268        }
2269        else
2270            write_long (0x7fffff00 | chunkingFlag);
2271    }
2272
2273    /**
2274     * Writes to this stream a value header with the specified `repository_id'.
2275     * and `codebase' string.
2276     */

2277
2278    private void write_value_header
2279       (final String JavaDoc[] repository_ids, final String JavaDoc codebase)
2280    {
2281        if (codebase != null)
2282        {
2283            write_previous_chunk_size();
2284            if ( repository_ids != null )
2285            {
2286                if( repository_ids.length > 1 )
2287                {
2288                    // truncatable value type, must use chunking!
2289

2290                    chunkingFlag = 0x00000008;
2291                    write_long (0x7fffff07 | chunkingFlag);
2292                    write_codebase(codebase);
2293                    write_long( repository_ids.length );
2294
2295                    for( int i = 0; i < repository_ids.length; i++ )
2296                    {
2297                        write_repository_id (repository_ids[i]);
2298                    }
2299                }
2300                else
2301                {
2302                    write_long (0x7fffff03 | chunkingFlag);
2303                    write_codebase(codebase);
2304                    write_repository_id (repository_ids[0]);
2305                }
2306            }
2307            else
2308            {
2309                write_long (0x7fffff01 | chunkingFlag);
2310                write_codebase(codebase);
2311            }
2312        }
2313        else
2314            write_value_header (repository_ids);
2315    }
2316
2317    /**
2318     * This method does the actual work of writing `value' to this
2319     * stream. If `repository_id' is non-null, then it is used as
2320     * the type information for `value' (possibly via indirection).
2321     * If `repository_id' is null, `value' is written without
2322     * type information.
2323     * Note: This method does not check for the special cases covered
2324     * by write_special_value().
2325     */

2326    private void write_value_internal(final java.io.Serializable JavaDoc value,
2327                                       final String JavaDoc repository_id)
2328    {
2329        check(7,4);
2330        getValueMap().put(value, new Integer JavaDoc(pos));
2331
2332        if (value.getClass() == String JavaDoc.class)
2333        {
2334            // special handling for strings required according to spec
2335
String JavaDoc[] repository_ids =
2336                (repository_id == null) ? null : new String JavaDoc[]{ repository_id };
2337            write_value_header(repository_ids);
2338            start_chunk();
2339            write_wstring((String JavaDoc)value);
2340            end_chunk();
2341        }
2342        else if (value.getClass() == Class JavaDoc.class)
2343        {
2344            String JavaDoc[] repository_ids = new String JavaDoc[] {
2345                    ValueHandler.getRMIRepositoryID(javax.rmi.CORBA.ClassDesc JavaDoc.class)
2346            };
2347            write_value_header(repository_ids);
2348            start_chunk();
2349            write_value(ValueHandler.getCodebase((Class JavaDoc)value));
2350            write_value(ValueHandler.getRMIRepositoryID((Class JavaDoc)value));
2351            end_chunk();
2352        }
2353        else if (value instanceof org.omg.CORBA.portable.StreamableValue JavaDoc)
2354        {
2355            org.omg.CORBA.portable.StreamableValue JavaDoc streamable =
2356                (org.omg.CORBA.portable.StreamableValue JavaDoc)value;
2357
2358            write_value_header( streamable._truncatable_ids() );
2359            start_chunk();
2360            ((org.omg.CORBA.portable.StreamableValue JavaDoc)value)._write(this);
2361            end_chunk();
2362        }
2363        else
2364        {
2365            String JavaDoc[] repository_ids =
2366                (repository_id == null) ? null : new String JavaDoc[]{ repository_id };
2367            Class JavaDoc cls = value.getClass();
2368            String JavaDoc codebase = ValueHandler.getCodebase(cls);
2369            if (value instanceof org.omg.CORBA.portable.IDLEntity JavaDoc)
2370            {
2371                java.lang.reflect.Method JavaDoc writeMethod = null;
2372                if (cls != org.omg.CORBA.Any JavaDoc.class)
2373                {
2374                    String JavaDoc helperClassName = cls.getName() + "Helper";
2375
2376                    try
2377                    {
2378                        Class JavaDoc helperClass =
2379                        cls.getClassLoader().loadClass(helperClassName);
2380                        Class JavaDoc[] paramTypes =
2381                            { org.omg.CORBA.portable.OutputStream JavaDoc.class, cls };
2382                        writeMethod = helperClass.getMethod("write", paramTypes);
2383                    }
2384                    catch (ClassNotFoundException JavaDoc e)
2385                    {
2386                        throw new MARSHAL JavaDoc("Error loading class " + helperClassName
2387                                          + ": " + e);
2388                    }
2389                    catch (NoSuchMethodException JavaDoc e)
2390                    {
2391                        throw new MARSHAL JavaDoc("No write method in helper class "
2392                                          + helperClassName + ": " + e);
2393                    }
2394                }
2395                write_value_header( repository_ids, codebase );
2396                start_chunk();
2397                if (writeMethod == null)
2398                {
2399                    write_any((org.omg.CORBA.Any JavaDoc)value);
2400                }
2401                else
2402                {
2403                    try
2404                    {
2405                        writeMethod.invoke(null, new Object JavaDoc[] { this, value });
2406                    }
2407                    catch (IllegalAccessException JavaDoc e)
2408                    {
2409                        throw new MARSHAL JavaDoc("Internal error: " + e);
2410                    }
2411                    catch (java.lang.reflect.InvocationTargetException JavaDoc e)
2412                    {
2413                        throw new MARSHAL JavaDoc("Exception marshaling IDLEntity: "
2414                                          + e.getTargetException());
2415                    }
2416                }
2417                end_chunk();
2418
2419            }
2420            else
2421            {
2422                try
2423                {
2424                    writeValueNestingLevel++;
2425                    if (chunkCustomRmiValuetypes
2426                        && ValueHandler.isCustomMarshaled(cls))
2427                        chunkingFlag = 0x00000008;
2428                    write_value_header( repository_ids, codebase );
2429                    start_chunk();
2430                    if (!writeReplaceCalled)
2431                    {
2432                        // writeReplace must be called only once for this value
2433
java.io.Serializable JavaDoc newValue =
2434                            ValueHandler.writeReplace(value);
2435                        writeReplaceCalled = true; // won't call it again
2436

2437                        if (newValue != value)
2438                        {
2439                            // look at the new value
2440
Integer JavaDoc index = (Integer JavaDoc)getValueMap().get(newValue);
2441                            if (index != null)
2442                            {
2443                                // previously marshaled value -- make an indirection
2444
write_long (0xffffffff);
2445                                write_long (index.intValue() - size());
2446                            }
2447                            else if (value instanceof org.omg.CORBA.Object JavaDoc)
2448                            {
2449                                write_Object((org.omg.CORBA.Object JavaDoc)newValue);
2450                            }
2451                            else
2452                            {
2453                                ValueHandler.writeValue(this, newValue);
2454                            }
2455                        }
2456                        else
2457                        {
2458                            // writeReplace did't make a difference
2459
ValueHandler.writeValue(this, value);
2460                        }
2461                    }
2462                    else
2463                    {
2464                        // Skip writeReplace call
2465
// (writeReplace was already called for this value)
2466
ValueHandler.writeValue(this, value);
2467                    }
2468                    end_chunk();
2469                }
2470                finally
2471                {
2472                    if (--writeValueNestingLevel == 0)
2473                        writeReplaceCalled = false;
2474                }
2475            }
2476        }
2477    }
2478
2479    /**
2480     * start a new chunk, end any previously started chunk (no nesting!)
2481     */

2482
2483    private void start_chunk()
2484    {
2485        if (chunkingFlag > 0)
2486        {
2487            write_previous_chunk_size();
2488            valueNestingLevel++;
2489            skip_chunk_size_tag();
2490        }
2491    }
2492
2493    private void end_chunk()
2494    {
2495        if (chunkingFlag > 0)
2496        {
2497            write_previous_chunk_size();
2498            write_long(-valueNestingLevel);
2499            if ( --valueNestingLevel == 0 )
2500            {
2501                // ending chunk for outermost value
2502
chunkingFlag = 0;
2503            }
2504            else
2505            {
2506                // start continuation chunk for outer value
2507
skip_chunk_size_tag();
2508            }
2509        }
2510    }
2511
2512
2513    /**
2514     * writes the chunk size to the header of the previous chunk
2515     */

2516    private void write_previous_chunk_size()
2517    {
2518        if( chunk_size_tag_pos != -1 )
2519        {
2520            if ( pos == chunk_octets_pos)
2521            {
2522                // empty chunk: erase chunk size tag
2523
pos = chunk_size_tag_pos; // the tag will be overwritten
2524
index = chunk_size_tag_index; // by subsequent data
2525
}
2526            else
2527            {
2528                // go to the beginning of the chunk and write the size tag
2529

2530                // check(7, 4); // DO NOT align to a 4-byte boundary
2531

2532                int current_pos = pos;
2533                int current_idx = index;
2534
2535                pos = chunk_size_tag_pos;
2536                index = chunk_size_tag_index;
2537                write_long( current_pos - chunk_octets_pos );
2538
2539                pos = current_pos;
2540                index = current_idx;
2541
2542            }
2543            chunk_size_tag_pos = -1; // no chunk is currently open
2544
}
2545    }
2546
2547    private void skip_chunk_size_tag()
2548    {
2549        // remember where we are right now,
2550
chunk_size_tag_pos = pos;
2551        chunk_size_tag_index = index;
2552
2553        // insert four bytes here as a place-holder
2554
write_long( 0 ); // need to go back later and write the actual size
2555

2556        // remember starting position of chunk data
2557
chunk_octets_pos = pos;
2558    }
2559
2560    /**
2561     * Writes an abstract interface to this stream. The abstract interface is
2562     * written as a union with a boolean discriminator, which is true if the
2563     * union contains a CORBA object reference, or false if the union contains
2564     * a value.
2565     */

2566    public void write_abstract_interface(final java.lang.Object JavaDoc object)
2567    {
2568        if (object instanceof org.omg.CORBA.Object JavaDoc)
2569        {
2570            write_boolean(true);
2571            write_Object((org.omg.CORBA.Object JavaDoc)object);
2572        }
2573        else
2574        {
2575            write_boolean(false);
2576            write_value((java.io.Serializable JavaDoc)object);
2577        }
2578    }
2579}
2580
Popular Tags