KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > corba > se > impl > encoding > CDROutputStream_1_0


1 /*
2  * @(#)CDROutputStream_1_0.java 1.114 05/01/04
3  *
4  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

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

15
16 package com.sun.corba.se.impl.encoding;
17
18 import java.io.ByteArrayOutputStream JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.Serializable JavaDoc;
21 import java.io.ByteArrayOutputStream JavaDoc;
22 import java.io.ObjectOutputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.lang.reflect.Method JavaDoc;
25 import java.lang.reflect.InvocationTargetException JavaDoc;
26 import java.math.BigDecimal JavaDoc;
27 import java.nio.ByteBuffer JavaDoc;
28 import java.rmi.Remote JavaDoc;
29 import java.security.AccessController JavaDoc;
30 import java.security.PrivilegedExceptionAction JavaDoc;
31 import java.security.PrivilegedActionException JavaDoc;
32 import java.util.Hashtable JavaDoc;
33 import java.util.Stack JavaDoc;
34
35 import javax.rmi.CORBA.Util JavaDoc;
36 import javax.rmi.CORBA.ValueHandler JavaDoc;
37 import javax.rmi.CORBA.ValueHandlerMultiFormat JavaDoc;
38
39 import org.omg.CORBA.CustomMarshal JavaDoc;
40 import org.omg.CORBA.DataOutputStream JavaDoc;
41 import org.omg.CORBA.TypeCodePackage.BadKind JavaDoc;
42 import org.omg.CORBA.SystemException JavaDoc;
43 import org.omg.CORBA.CompletionStatus JavaDoc;
44 import org.omg.CORBA.Object JavaDoc;
45 import org.omg.CORBA.Principal JavaDoc;
46 import org.omg.CORBA.TypeCode JavaDoc;
47 import org.omg.CORBA.Any JavaDoc;
48 import org.omg.CORBA.VM_CUSTOM JavaDoc;
49 import org.omg.CORBA.VM_TRUNCATABLE JavaDoc;
50 import org.omg.CORBA.VM_NONE JavaDoc;
51 import org.omg.CORBA.portable.IDLEntity JavaDoc;
52 import org.omg.CORBA.portable.CustomValue JavaDoc;
53 import org.omg.CORBA.portable.StreamableValue JavaDoc;
54 import org.omg.CORBA.portable.BoxedValueHelper JavaDoc;
55 import org.omg.CORBA.portable.OutputStream JavaDoc;
56 import org.omg.CORBA.portable.ValueBase JavaDoc;
57
58 import com.sun.org.omg.CORBA.portable.ValueHelper;
59
60 import com.sun.corba.se.pept.protocol.MessageMediator;
61 import com.sun.corba.se.pept.transport.ByteBufferPool;
62
63 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
64 import com.sun.corba.se.spi.ior.IOR;
65 import com.sun.corba.se.spi.ior.IORFactories;
66 import com.sun.corba.se.spi.orb.ORB;
67 import com.sun.corba.se.spi.orb.ORBVersionFactory;
68 import com.sun.corba.se.spi.orb.ORBVersion;
69 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
70 import com.sun.corba.se.spi.logging.CORBALogDomains;
71
72 import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
73 import com.sun.corba.se.impl.encoding.MarshalOutputStream;
74 import com.sun.corba.se.impl.encoding.CodeSetConversion;
75 import com.sun.corba.se.impl.corba.TypeCodeImpl;
76 import com.sun.corba.se.impl.orbutil.CacheTable;
77 import com.sun.corba.se.impl.orbutil.ORBUtility;
78 import com.sun.corba.se.impl.orbutil.RepositoryIdStrings;
79 import com.sun.corba.se.impl.orbutil.RepositoryIdUtility;
80 import com.sun.corba.se.impl.orbutil.RepositoryIdFactory;
81 import com.sun.corba.se.impl.util.Utility;
82 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
83
84 public class CDROutputStream_1_0 extends CDROutputStreamBase
85 {
86     private static final int INDIRECTION_TAG = 0xffffffff;
87
88     protected boolean littleEndian;
89     protected BufferManagerWrite bufferManagerWrite;
90     ByteBufferWithInfo bbwi;
91
92     protected ORB orb;
93     protected ORBUtilSystemException wrapper ;
94
95     protected boolean debug = false;
96     
97     protected int blockSizeIndex = -1;
98     protected int blockSizePosition = 0;
99
100     protected byte streamFormatVersion;
101
102     private static final int DEFAULT_BUFFER_SIZE = 1024;
103     private static final String JavaDoc kWriteMethod = "write";
104
105     // Codebase cache
106
private CacheTable codebaseCache = null;
107
108     // Value cache
109
private CacheTable valueCache = null;
110
111     // Repository ID cache
112
private CacheTable repositoryIdCache = null;
113
114     // Write end flag
115
private int end_flag = 0;
116
117     // Beginning with the resolution to interop issue 3526,
118
// only enclosing chunked valuetypes are taken into account
119
// when computing the nesting level. However, we still need
120
// the old computation around for interoperability with our
121
// older ORBs.
122
private int chunkedValueNestingLevel = 0;
123
124     private boolean mustChunk = false;
125
126     // In block marker
127
protected boolean inBlock = false;
128
129     // Last end tag position
130
private int end_flag_position = 0;
131     private int end_flag_index = 0;
132
133     // ValueHandler
134
private ValueHandler JavaDoc valueHandler = null;
135
136     // Repository ID handlers
137
private RepositoryIdUtility repIdUtil;
138     private RepositoryIdStrings repIdStrs;
139
140     // Code set converters (created when first needed)
141
private CodeSetConversion.CTBConverter charConverter;
142     private CodeSetConversion.CTBConverter wcharConverter;
143     
144     // REVISIT - This should be re-factored so that including whether
145
// to use pool byte buffers or not doesn't need to be known.
146
public void init(org.omg.CORBA.ORB JavaDoc orb,
147                         boolean littleEndian,
148                         BufferManagerWrite bufferManager,
149                         byte streamFormatVersion,
150                         boolean usePooledByteBuffers)
151     {
152         // ORB must not be null. See CDROutputStream constructor.
153
this.orb = (ORB)orb;
154     this.wrapper = ORBUtilSystemException.get( this.orb,
155         CORBALogDomains.RPC_ENCODING ) ;
156     debug = this.orb.transportDebugFlag;
157
158         this.littleEndian = littleEndian;
159         this.bufferManagerWrite = bufferManager;
160         this.bbwi = new ByteBufferWithInfo(orb, bufferManager, usePooledByteBuffers);
161     this.streamFormatVersion = streamFormatVersion;
162
163         createRepositoryIdHandlers();
164     }
165
166     public void init(org.omg.CORBA.ORB JavaDoc orb,
167                         boolean littleEndian,
168                         BufferManagerWrite bufferManager,
169                         byte streamFormatVersion)
170    {
171        init(orb, littleEndian, bufferManager, streamFormatVersion, true);
172    }
173
174     private final void createRepositoryIdHandlers()
175     {
176         if (orb != null) {
177             // Get the appropriate versions based on the ORB version. The
178
// ORB versioning info is only in the core ORB.
179
repIdUtil
180                 = RepositoryIdFactory.getRepIdUtility(orb);
181             repIdStrs
182                 = RepositoryIdFactory.getRepIdStringsFactory(orb);
183         } else {
184             // Get the latest versions
185
repIdUtil = RepositoryIdFactory.getRepIdUtility();
186             repIdStrs = RepositoryIdFactory.getRepIdStringsFactory();
187         }
188     }
189
190     public BufferManagerWrite getBufferManager()
191     {
192     return bufferManagerWrite;
193     }
194
195     public byte[] toByteArray() {
196         byte[] it;
197
198         it = new byte[bbwi.position()];
199
200         // Micro-benchmarks show ByteBuffer.get(int) out perform the bulk
201
// ByteBuffer.get(byte[], offset, length).
202
for (int i = 0; i < bbwi.position(); i++)
203             it[i] = bbwi.byteBuffer.get(i);
204
205         return it;
206     }
207
208     public GIOPVersion getGIOPVersion() {
209         return GIOPVersion.V1_0;
210     }
211
212     // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only.
213
// Illegal for GIOP versions < 1.2.
214
void setHeaderPadding(boolean headerPadding) {
215         throw wrapper.giopVersionError();
216     }
217
218     protected void handleSpecialChunkBegin(int requiredSize)
219     {
220         // No-op for GIOP 1.0
221
}
222
223     protected void handleSpecialChunkEnd()
224     {
225         // No-op for GIOP 1.0
226
}
227
228     protected final int computeAlignment(int align) {
229         if (align > 1) {
230             int incr = bbwi.position() & (align - 1);
231             if (incr != 0)
232                 return align - incr;
233         }
234
235         return 0;
236     }
237
238     protected void alignAndReserve(int align, int n) {
239
240         bbwi.position(bbwi.position() + computeAlignment(align));
241
242         if (bbwi.position() + n > bbwi.buflen)
243             grow(align, n);
244     }
245
246     //
247
// Default implementation of grow. Subclassers may override this.
248
// Always grow the single buffer. This needs to delegate
249
// fragmentation policy for IIOP 1.1.
250
//
251
protected void grow(int align, int n)
252     {
253         bbwi.needed = n;
254
255         bufferManagerWrite.overflow(bbwi);
256     }
257
258     public final void putEndian() throws SystemException JavaDoc {
259         write_boolean(littleEndian);
260     }
261
262     public final boolean littleEndian() {
263         return littleEndian;
264     }
265
266     void freeInternalCaches() {
267     if (codebaseCache != null)
268         codebaseCache.done();
269
270     if (valueCache != null)
271         valueCache.done();
272         
273     if (repositoryIdCache != null)
274         repositoryIdCache.done();
275     }
276
277     // No such type in java
278
public final void write_longdouble(double x)
279     {
280     throw wrapper.longDoubleNotImplemented(
281         CompletionStatus.COMPLETED_MAYBE ) ;
282     }
283
284     public void write_octet(byte x)
285     {
286         // The 'if' stmt is commented out since we need the alignAndReserve to
287
// be called, particularly when the first body byte is written,
288
// to induce header padding to align the body on a 8-octet boundary,
289
// for GIOP versions 1.2 and above. Refer to internalWriteOctetArray()
290
// method that also has a similar change.
291
//if (bbwi.position() + 1 > bbwi.buflen)
292
alignAndReserve(1, 1);
293
294 // REVISIT - Should just use ByteBuffer.put(byte) and let it
295
// increment the ByteBuffer position. This is true
296
// for all write operations in this file.
297

298         bbwi.byteBuffer.put(bbwi.position(), x);
299         bbwi.position(bbwi.position() + 1);
300          
301     }
302
303     public final void write_boolean(boolean x)
304     {
305     write_octet(x? (byte)1:(byte)0);
306     }
307
308     public void write_char(char x)
309     {
310         CodeSetConversion.CTBConverter converter = getCharConverter();
311
312         converter.convert(x);
313
314         // CORBA formal 99-10-07 15.3.1.6: "In the case of multi-byte encodings
315
// of characters, a single instance of the char type may only
316
// hold one octet of any multi-byte character encoding."
317
if (converter.getNumBytes() > 1)
318         throw wrapper.invalidSingleCharCtb(CompletionStatus.COMPLETED_MAYBE);
319
320         write_octet(converter.getBytes()[0]);
321     }
322
323     // These wchar methods are only used when talking to
324
// legacy ORBs, now.
325
private final void writeLittleEndianWchar(char x) {
326         bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
327         bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
328         bbwi.position(bbwi.position() + 2);
329     }
330
331     private final void writeBigEndianWchar(char x) {
332         bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 8) & 0xFF));
333         bbwi.byteBuffer.put(bbwi.position() + 1, (byte)(x & 0xFF));
334         bbwi.position(bbwi.position() + 2);
335     }
336
337     private final void writeLittleEndianShort(short x) {
338         bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
339         bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
340         bbwi.position(bbwi.position() + 2);
341     }
342
343     private final void writeBigEndianShort(short x) {
344         bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 8) & 0xFF));
345         bbwi.byteBuffer.put(bbwi.position() + 1, (byte)(x & 0xFF));
346         bbwi.position(bbwi.position() + 2);
347     }
348
349     private final void writeLittleEndianLong(int x) {
350         bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
351         bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
352         bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 16) & 0xFF));
353         bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 24) & 0xFF));
354         bbwi.position(bbwi.position() + 4);
355     }
356
357     private final void writeBigEndianLong(int x) {
358         bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 24) & 0xFF));
359         bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 16) & 0xFF));
360         bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 8) & 0xFF));
361         bbwi.byteBuffer.put(bbwi.position() + 3, (byte)(x & 0xFF));
362         bbwi.position(bbwi.position() + 4);
363     }
364
365     private final void writeLittleEndianLongLong(long x) {
366         bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
367         bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
368         bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 16) & 0xFF));
369         bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 24) & 0xFF));
370         bbwi.byteBuffer.put(bbwi.position() + 4, (byte)((x >>> 32) & 0xFF));
371         bbwi.byteBuffer.put(bbwi.position() + 5, (byte)((x >>> 40) & 0xFF));
372         bbwi.byteBuffer.put(bbwi.position() + 6, (byte)((x >>> 48) & 0xFF));
373         bbwi.byteBuffer.put(bbwi.position() + 7, (byte)((x >>> 56) & 0xFF));
374         bbwi.position(bbwi.position() + 8);
375     }
376
377     private final void writeBigEndianLongLong(long x) {
378         bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 56) & 0xFF));
379         bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 48) & 0xFF));
380         bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 40) & 0xFF));
381         bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 32) & 0xFF));
382         bbwi.byteBuffer.put(bbwi.position() + 4, (byte)((x >>> 24) & 0xFF));
383         bbwi.byteBuffer.put(bbwi.position() + 5, (byte)((x >>> 16) & 0xFF));
384         bbwi.byteBuffer.put(bbwi.position() + 6, (byte)((x >>> 8) & 0xFF));
385         bbwi.byteBuffer.put(bbwi.position() + 7, (byte)(x & 0xFF));
386         bbwi.position(bbwi.position() + 8);
387     }
388
389     public void write_wchar(char x)
390     {
391         // Don't allow transmission of wchar/wstring data with
392
// foreign ORBs since it's against the spec.
393
if (ORBUtility.isForeignORB(orb)) {
394         throw wrapper.wcharDataInGiop10(CompletionStatus.COMPLETED_MAYBE);
395         }
396
397         // If it's one of our legacy ORBs, do what they did:
398
alignAndReserve(2, 2);
399     
400         if (littleEndian) {
401             writeLittleEndianWchar(x);
402         } else {
403             writeBigEndianWchar(x);
404         }
405     }
406
407     public void write_short(short x)
408     {
409         alignAndReserve(2, 2);
410         
411         if (littleEndian) {
412             writeLittleEndianShort(x);
413         } else {
414             writeBigEndianShort(x);
415         }
416     }
417
418     public final void write_ushort(short x)
419     {
420     write_short(x);
421     }
422
423     public void write_long(int x)
424     {
425         alignAndReserve(4, 4);
426
427         if (littleEndian) {
428             writeLittleEndianLong(x);
429         } else {
430             writeBigEndianLong(x);
431         }
432     }
433
434     public final void write_ulong(int x)
435     {
436     write_long(x);
437     }
438
439     public void write_longlong(long x)
440     {
441         alignAndReserve(8, 8);
442
443         if (littleEndian) {
444             writeLittleEndianLongLong(x);
445         } else {
446             writeBigEndianLongLong(x);
447         }
448     }
449
450     public final void write_ulonglong(long x)
451     {
452     write_longlong(x);
453     }
454
455     public final void write_float(float x)
456     {
457     write_long(Float.floatToIntBits(x));
458     }
459
460     public final void write_double(double x)
461     {
462     write_longlong(Double.doubleToLongBits(x));
463     }
464
465     public void write_string(String JavaDoc value)
466     {
467       writeString(value);
468     }
469
470     protected int writeString(String JavaDoc value)
471     {
472         if (value == null) {
473         throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
474         }
475
476         CodeSetConversion.CTBConverter converter = getCharConverter();
477
478         converter.convert(value);
479
480         // A string is encoded as an unsigned CORBA long for the
481
// number of bytes to follow (including a terminating null).
482
// There is only one octet per character in the string.
483
int len = converter.getNumBytes() + 1;
484
485         handleSpecialChunkBegin(computeAlignment(4) + 4 + len);
486
487         write_long(len);
488         int indirection = get_offset() - 4;
489
490         internalWriteOctetArray(converter.getBytes(), 0, converter.getNumBytes());
491
492         // Write the null ending
493
write_octet((byte)0);
494
495         handleSpecialChunkEnd();
496         return indirection;
497     }
498
499     public void write_wstring(String JavaDoc value)
500     {
501         if (value == null)
502         throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
503
504         // Don't allow transmission of wchar/wstring data with
505
// foreign ORBs since it's against the spec.
506
if (ORBUtility.isForeignORB(orb)) {
507         throw wrapper.wcharDataInGiop10(CompletionStatus.COMPLETED_MAYBE);
508         }
509             
510         // When talking to our legacy ORBs, do what they did:
511
int len = value.length() + 1;
512
513         // This will only have an effect if we're already chunking
514
handleSpecialChunkBegin(4 + (len * 2) + computeAlignment(4));
515
516         write_long(len);
517
518         for (int i = 0; i < len - 1; i++)
519             write_wchar(value.charAt(i));
520
521         // Write the null ending
522
write_short((short)0);
523
524         // This will only have an effect if we're already chunking
525
handleSpecialChunkEnd();
526     }
527
528     // Performs no checks and doesn't tamper with chunking
529
void internalWriteOctetArray(byte[] value, int offset, int length)
530     {
531         int n = offset;
532
533     // This flag forces the alignAndReserve method to be called the
534
// first time an octet is written. This is necessary to ensure
535
// that the body is aligned on an 8-octet boundary. Note the 'if'
536
// condition inside the 'while' loop below. Also, refer to the
537
// write_octet() method that has a similar change.
538
boolean align = true;
539             
540         while (n < length+offset) {
541             int avail;
542             int bytes;
543             int wanted;
544
545             if ((bbwi.position() + 1 > bbwi.buflen) || align) {
546         align = false;
547             alignAndReserve(1, 1);
548         }
549             avail = bbwi.buflen - bbwi.position();
550             wanted = (length + offset) - n;
551             bytes = (wanted < avail) ? wanted : avail;
552             for (int i = 0; i < bytes; i++)
553                 bbwi.byteBuffer.put(bbwi.position() + i, value[n+i]);
554             bbwi.position(bbwi.position() + bytes);
555             n += bytes;
556         }
557     }
558
559     public final void write_octet_array(byte b[], int offset, int length)
560     {
561         if ( b == null )
562         throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
563
564         // This will only have an effect if we're already chunking
565
handleSpecialChunkBegin(length);
566
567         internalWriteOctetArray(b, offset, length);
568
569         // This will only have an effect if we're already chunking
570
handleSpecialChunkEnd();
571     }
572
573     public void write_Principal(Principal JavaDoc p)
574     {
575         write_long(p.name().length);
576         write_octet_array(p.name(), 0, p.name().length);
577     }
578
579     public void write_any(Any JavaDoc any)
580     {
581         if ( any == null )
582         throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
583
584         write_TypeCode(any.type());
585         any.write_value(parent);
586     }
587
588     public void write_TypeCode(TypeCode JavaDoc tc)
589     {
590         if ( tc == null ) {
591         throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
592     }
593         TypeCodeImpl tci;
594         if (tc instanceof TypeCodeImpl) {
595         tci = (TypeCodeImpl)tc;
596     }
597         else {
598         tci = new TypeCodeImpl(orb, tc);
599     }
600
601         tci.write_value((org.omg.CORBA_2_3.portable.OutputStream JavaDoc)parent);
602     }
603  
604     public void write_Object(org.omg.CORBA.Object JavaDoc ref)
605     {
606         if (ref == null) {
607         IOR nullIOR = IORFactories.makeIOR( orb ) ;
608             nullIOR.write(parent);
609             return;
610         }
611         
612         // IDL to Java formal 01-06-06 1.21.4.2
613
if (ref instanceof org.omg.CORBA.LocalObject JavaDoc)
614         throw wrapper.writeLocalObject(CompletionStatus.COMPLETED_MAYBE);
615     
616     IOR ior = ORBUtility.connectAndGetIOR( orb, ref ) ;
617     ior.write(parent);
618     return;
619     }
620
621     // ------------ RMI related methods --------------------------
622

623     public void write_abstract_interface(java.lang.Object JavaDoc obj) {
624     boolean corbaObject = false; // Assume value type.
625
org.omg.CORBA.Object JavaDoc theObject = null;
626         
627     // Is it a CORBA.Object?
628

629     if (obj != null && obj instanceof org.omg.CORBA.Object JavaDoc) {
630             
631         // Yes.
632

633         theObject = (org.omg.CORBA.Object JavaDoc)obj;
634         corbaObject = true;
635     }
636         
637     // Write our flag...
638

639     write_boolean(corbaObject);
640         
641     // Now write out the object...
642

643     if (corbaObject) {
644         write_Object(theObject);
645     } else {
646         try {
647         write_value((java.io.Serializable JavaDoc)obj);
648         } catch(ClassCastException JavaDoc cce) {
649         if (obj instanceof java.io.Serializable JavaDoc)
650             throw cce;
651         else
652                     ORBUtility.throwNotSerializableForCorba(obj.getClass().getName());
653         }
654     }
655     }
656
657     public void write_value(Serializable JavaDoc object, Class JavaDoc clz) {
658
659     write_value(object);
660     }
661
662     private void writeWStringValue(String JavaDoc string) {
663
664         int indirection = writeValueTag(mustChunk, true, null);
665             
666         // Write WStringValue's repository ID
667
write_repositoryId(repIdStrs.getWStringValueRepId());
668             
669         // Add indirection for object to indirection table
670
updateIndirectionTable(indirection, string, string);
671
672         // Write Value chunk
673
if (mustChunk) {
674             start_block();
675             end_flag--;
676             chunkedValueNestingLevel--;
677         } else
678             end_flag--;
679             
680         write_wstring(string);
681         
682         if (mustChunk)
683             end_block();
684             
685         // Write end tag
686
writeEndTag(mustChunk);
687     }
688
689     private void writeArray(Serializable JavaDoc array, Class JavaDoc clazz) {
690
691         if (valueHandler == null)
692             valueHandler = ORBUtility.createValueHandler(orb); //d11638
693

694         // Write value_tag
695
int indirection = writeValueTag(mustChunk, true,
696                     Util.getCodebase(clazz));
697                 
698         // Write repository ID
699
write_repositoryId(repIdStrs.createSequenceRepID(clazz));
700                 
701         // Add indirection for object to indirection table
702
updateIndirectionTable(indirection, array, array);
703                 
704         // Write Value chunk
705
if (mustChunk) {
706             start_block();
707             end_flag--;
708             chunkedValueNestingLevel--;
709         } else
710             end_flag--;
711
712         if (valueHandler instanceof ValueHandlerMultiFormat JavaDoc) {
713             ValueHandlerMultiFormat JavaDoc vh = (ValueHandlerMultiFormat JavaDoc)valueHandler;
714             vh.writeValue(parent, array, streamFormatVersion);
715         } else
716             valueHandler.writeValue(parent, array);
717
718         if (mustChunk)
719             end_block();
720                 
721         // Write end tag
722
writeEndTag(mustChunk);
723     }
724
725     private void writeValueBase(org.omg.CORBA.portable.ValueBase JavaDoc object,
726                                 Class JavaDoc clazz) {
727         // _REVISIT_ could check to see whether chunking really needed
728
mustChunk = true;
729             
730         // Write value_tag
731
int indirection = writeValueTag(true, true, Util.getCodebase(clazz));
732             
733         // Get rep id
734
String JavaDoc repId = ((ValueBase JavaDoc)object)._truncatable_ids()[0];
735             
736         // Write rep id
737
write_repositoryId(repId);
738             
739         // Add indirection for object to indirection table
740
updateIndirectionTable(indirection, object, object);
741         
742         // Write Value chunk
743
start_block();
744         end_flag--;
745         chunkedValueNestingLevel--;
746         writeIDLValue(object, repId);
747         end_block();
748         
749         // Write end tag
750
writeEndTag(true);
751     }
752
753     private void writeRMIIIOPValueType(Serializable JavaDoc object, Class JavaDoc clazz) {
754         if (valueHandler == null)
755             valueHandler = ORBUtility.createValueHandler(orb); //d11638
756

757         Serializable JavaDoc key = object;
758
759         // Allow the ValueHandler to call writeReplace on
760
// the Serializable (if the method is present)
761
object = valueHandler.writeReplace(key);
762         
763         if (object == null) {
764             // Write null tag and return
765
write_long(0);
766             return;
767         }
768         
769         if (object != key) {
770             if (valueCache != null && valueCache.containsKey(object)) {
771                 writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
772                 return;
773             }
774             
775             clazz = object.getClass();
776         }
777
778         if (mustChunk || valueHandler.isCustomMarshaled(clazz)) {
779             mustChunk = true;
780         }
781                 
782         // Write value_tag
783
int indirection = writeValueTag(mustChunk, true, Util.getCodebase(clazz));
784                 
785         // Write rep. id
786
write_repositoryId(repIdStrs.createForJavaType(clazz));
787                 
788         // Add indirection for object to indirection table
789
updateIndirectionTable(indirection, object, key);
790
791         if (mustChunk) {
792             // Write Value chunk
793
end_flag--;
794             chunkedValueNestingLevel--;
795             start_block();
796         } else
797             end_flag--;
798
799         if (valueHandler instanceof ValueHandlerMultiFormat JavaDoc) {
800             ValueHandlerMultiFormat JavaDoc vh = (ValueHandlerMultiFormat JavaDoc)valueHandler;
801             vh.writeValue(parent, object, streamFormatVersion);
802         } else
803             valueHandler.writeValue(parent, object);
804
805         if (mustChunk)
806             end_block();
807                 
808         // Write end tag
809
writeEndTag(mustChunk);
810     }
811     
812     public void write_value(Serializable JavaDoc object, String JavaDoc repository_id) {
813
814     // Handle null references
815
if (object == null) {
816         // Write null tag and return
817
write_long(0);
818         return;
819     }
820
821     // Handle shared references
822
if (valueCache != null && valueCache.containsKey(object)) {
823             writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
824         return;
825     }
826         
827     Class JavaDoc clazz = object.getClass();
828     boolean oldMustChunk = mustChunk;
829
830         if (mustChunk)
831             mustChunk = true;
832
833     if (inBlock)
834         end_block();
835
836     if (clazz.isArray()) {
837             // Handle arrays
838
writeArray(object, clazz);
839     } else if (object instanceof org.omg.CORBA.portable.ValueBase JavaDoc) {
840             // Handle IDL Value types
841
writeValueBase((org.omg.CORBA.portable.ValueBase JavaDoc)object, clazz);
842     } else if (shouldWriteAsIDLEntity(object)) {
843             writeIDLEntity((IDLEntity JavaDoc)object);
844     } else if (object instanceof java.lang.String JavaDoc) {
845             writeWStringValue((String JavaDoc)object);
846     } else if (object instanceof java.lang.Class JavaDoc) {
847             writeClass(repository_id, (Class JavaDoc)object);
848     } else {
849             // RMI-IIOP value type
850
writeRMIIIOPValueType(object, clazz);
851         }
852         
853     mustChunk = oldMustChunk;
854
855     // Check to see if we need to start another block for a
856
// possible outer value
857
if (mustChunk)
858         start_block();
859
860     }
861
862     public void write_value(Serializable JavaDoc object)
863     {
864         write_value(object, (String JavaDoc)null);
865     }
866
867     public void write_value(Serializable JavaDoc object, org.omg.CORBA.portable.BoxedValueHelper JavaDoc factory)
868     {
869         // Handle null references
870
if (object == null) {
871             // Write null tag and return
872
write_long(0);
873             return;
874         }
875         
876         // Handle shared references
877
if ((valueCache != null) && valueCache.containsKey(object)) {
878             writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
879         return;
880     }
881
882     boolean oldMustChunk = mustChunk;
883
884     boolean isCustom = false;
885     if (factory instanceof ValueHelper JavaDoc) {
886         short modifier;
887         try {
888         modifier = ((ValueHelper JavaDoc)factory).get_type().type_modifier();
889         } catch(BadKind JavaDoc ex) { // tk_value_box
890
modifier = VM_NONE.value;
891         }
892         if (object instanceof CustomMarshal JavaDoc &&
893             modifier == VM_CUSTOM.value) {
894         isCustom = true;
895         mustChunk = true;
896         }
897         if (modifier == VM_TRUNCATABLE.value)
898         mustChunk = true;
899     }
900
901     if (mustChunk) {
902             
903         if (inBlock)
904         end_block();
905
906         // Write value_tag
907
int indirection = writeValueTag(true,
908                         orb.getORBData().useRepId(),
909                         Util.getCodebase(object.getClass())
910                        );
911             
912         if (orb.getORBData().useRepId()) {
913         write_repositoryId(factory.get_id());
914         }
915             
916         // Add indirection for object to indirection table
917
updateIndirectionTable(indirection, object, object);
918             
919         // Write Value chunk
920
start_block();
921         end_flag--;
922             chunkedValueNestingLevel--;
923         if (isCustom)
924         ((CustomMarshal JavaDoc)object).marshal(parent);
925         else
926         factory.write_value(parent, object);
927         end_block();
928             
929         // Write end tag
930
writeEndTag(true);
931     }
932     else {
933         // Write value_tag
934
int indirection = writeValueTag(false,
935                         orb.getORBData().useRepId(),
936                         Util.getCodebase(object.getClass())
937                        );
938             
939         if (orb.getORBData().useRepId()) {
940         write_repositoryId(factory.get_id());
941         }
942             
943         // Add indirection for object to indirection table
944
updateIndirectionTable(indirection, object, object);
945             
946         // Write Value chunk
947
end_flag--;
948         // no need to test for custom on the non-chunked path
949
factory.write_value(parent, object);
950             
951         // Write end tag
952
writeEndTag(false);
953     }
954
955     mustChunk = oldMustChunk;
956
957     // Check to see if we need to start another block for a
958
// possible outer value
959
if (mustChunk)
960         start_block();
961
962     }
963     
964     public int get_offset() {
965     return bbwi.position();
966     }
967
968     public void start_block() {
969         if (debug) {
970             dprint("CDROutputStream_1_0 start_block, position" + bbwi.position());
971     }
972
973         //Move inBlock=true to after write_long since write_long might
974
//trigger grow which will lead to erroneous behavior with a
975
//missing blockSizeIndex.
976
//inBlock = true;
977

978     // Save space in the buffer for block size
979
write_long(0);
980
981         //Has to happen after write_long since write_long could
982
//trigger grow which is overridden by supper classes to
983
//depend on inBlock.
984
inBlock = true;
985
986         blockSizePosition = get_offset();
987
988     // Remember where to put the size of the endblock less 4
989
blockSizeIndex = bbwi.position();
990
991         if (debug) {
992             dprint("CDROutputStream_1_0 start_block, blockSizeIndex "
993            + blockSizeIndex);
994     }
995
996     }
997
998     // Utility method which will hopefully decrease chunking complexity
999
// by allowing us to end_block and update chunk lengths without
1000
// calling alignAndReserve. Otherwise, it's possible to get into
1001
// recursive scenarios which lose the chunking state.
1002
protected void writeLongWithoutAlign(int x) {
1003        if (littleEndian) {
1004            writeLittleEndianLong(x);
1005        } else {
1006            writeBigEndianLong(x);
1007        }
1008    }
1009
1010    public void end_block() {
1011        if (debug) {
1012            dprint("CDROutputStream_1_0.java end_block");
1013    }
1014
1015    if (!inBlock)
1016        return;
1017
1018        if (debug) {
1019            dprint("CDROutputStream_1_0.java end_block, in a block");
1020    }
1021
1022    inBlock = false;
1023
1024    // Test to see if the block was of zero length
1025
// If so, remove the block instead of ending it
1026
// (This can happen if the last field written
1027
// in a value was another value)
1028
if (get_offset() == blockSizePosition) {
1029            // Need to assert that blockSizeIndex == bbwi.position()? REVISIT
1030

1031            bbwi.position(bbwi.position() - 4);
1032        blockSizeIndex = -1;
1033            blockSizePosition = -1;
1034        return;
1035    }
1036
1037    int oldSize = bbwi.position();
1038    bbwi.position(blockSizeIndex - 4);
1039
1040        writeLongWithoutAlign(oldSize - blockSizeIndex);
1041
1042    bbwi.position(oldSize);
1043    blockSizeIndex = -1;
1044        blockSizePosition = -1;
1045
1046        // System.out.println(" post end_block: " + get_offset() + " " + bbwi.position());
1047
}
1048    
1049    public org.omg.CORBA.ORB JavaDoc orb()
1050    {
1051        return orb;
1052    }
1053
1054    // ------------ End RMI related methods --------------------------
1055

1056    public final void write_boolean_array(boolean[]value, int offset, int length) {
1057        if ( value == null )
1058        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1059
1060        // This will only have an effect if we're already chunking
1061
handleSpecialChunkBegin(length);
1062
1063        for (int i = 0; i < length; i++)
1064            write_boolean(value[offset + i]);
1065
1066        // This will only have an effect if we're already chunking
1067
handleSpecialChunkEnd();
1068    }
1069
1070    public final void write_char_array(char[]value, int offset, int length) {
1071        if ( value == null )
1072        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1073
1074        // This will only have an effect if we're already chunking
1075
handleSpecialChunkBegin(length);
1076
1077        for (int i = 0; i < length; i++)
1078            write_char(value[offset + i]);
1079
1080        // This will only have an effect if we're already chunking
1081
handleSpecialChunkEnd();
1082    }
1083
1084    public void write_wchar_array(char[]value, int offset, int length) {
1085        if ( value == null )
1086        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1087
1088        // This will only have an effect if we're already chunking
1089
handleSpecialChunkBegin(computeAlignment(2) + (length * 2));
1090
1091        for (int i = 0; i < length; i++)
1092            write_wchar(value[offset + i]);
1093
1094        // This will only have an effect if we're already chunking
1095
handleSpecialChunkEnd();
1096    }
1097
1098    public final void write_short_array(short[]value, int offset, int length) {
1099        if ( value == null )
1100        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1101
1102        // This will only have an effect if we're already chunking
1103
handleSpecialChunkBegin(computeAlignment(2) + (length * 2));
1104
1105        for (int i = 0; i < length; i++)
1106            write_short(value[offset + i]);
1107
1108        // This will only have an effect if we're already chunking
1109
handleSpecialChunkEnd();
1110    }
1111
1112    public final void write_ushort_array(short[]value, int offset, int length) {
1113        write_short_array(value, offset, length);
1114    }
1115
1116    public final void write_long_array(int[]value, int offset, int length) {
1117        if ( value == null )
1118        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1119
1120        // This will only have an effect if we're already chunking
1121
handleSpecialChunkBegin(computeAlignment(4) + (length * 4));
1122
1123        for (int i = 0; i < length; i++)
1124            write_long(value[offset + i]);
1125
1126        // This will only have an effect if we're already chunking
1127
handleSpecialChunkEnd();
1128    }
1129
1130    public final void write_ulong_array(int[]value, int offset, int length) {
1131        write_long_array(value, offset, length);
1132    }
1133
1134    public final void write_longlong_array(long[]value, int offset, int length) {
1135        if ( value == null )
1136        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1137
1138        // This will only have an effect if we're already chunking
1139
handleSpecialChunkBegin(computeAlignment(8) + (length * 8));
1140
1141        for (int i = 0; i < length; i++)
1142            write_longlong(value[offset + i]);
1143
1144        // This will only have an effect if we're already chunking
1145
handleSpecialChunkEnd();
1146    }
1147
1148    public final void write_ulonglong_array(long[]value, int offset, int length) {
1149        write_longlong_array(value, offset, length);
1150    }
1151
1152    public final void write_float_array(float[]value, int offset, int length) {
1153        if ( value == null )
1154        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1155
1156        // This will only have an effect if we're already chunking
1157
handleSpecialChunkBegin(computeAlignment(4) + (length * 4));
1158
1159        for (int i = 0; i < length; i++)
1160            write_float(value[offset + i]);
1161
1162        // This will only have an effect if we're already chunking
1163
handleSpecialChunkEnd();
1164    }
1165
1166    public final void write_double_array(double[]value, int offset, int length) {
1167        if ( value == null )
1168        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1169
1170        // This will only have an effect if we're already chunking
1171
handleSpecialChunkBegin(computeAlignment(8) + (length * 8));
1172
1173        for (int i = 0; i < length; i++)
1174            write_double(value[offset + i]);
1175
1176        // This will only have an effect if we're already chunking
1177
handleSpecialChunkEnd();
1178    }
1179
1180    public void write_string_array(String JavaDoc[] value, int offset, int length) {
1181        if ( value == null )
1182        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1183        
1184        for(int i = 0; i < length; i++)
1185            write_string(value[offset + i]);
1186    }
1187    
1188    public void write_wstring_array(String JavaDoc[] value, int offset, int length) {
1189        if ( value == null )
1190        throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
1191        
1192        for(int i = 0; i < length; i++)
1193            write_wstring(value[offset + i]);
1194    }
1195
1196    public final void write_any_array(org.omg.CORBA.Any JavaDoc value[], int offset, int length)
1197    {
1198        for(int i = 0; i < length; i++)
1199            write_any(value[offset + i]);
1200    }
1201
1202    //--------------------------------------------------------------------//
1203
// CDROutputStream state management.
1204
//
1205

1206    public void writeTo(java.io.OutputStream JavaDoc s)
1207    throws java.io.IOException JavaDoc
1208    {
1209        byte[] tmpBuf = null;
1210
1211        if (bbwi.byteBuffer.hasArray())
1212        {
1213            tmpBuf = bbwi.byteBuffer.array();
1214        }
1215        else
1216        {
1217            int size = bbwi.position();
1218            tmpBuf = new byte[size];
1219            // Micro-benchmarks are showing a loop of ByteBuffer.get(int) is
1220
// faster than ByteBuffer.get(byte[], offset, length)
1221
for (int i = 0; i < size; i++)
1222                tmpBuf[i] = bbwi.byteBuffer.get(i);
1223        }
1224
1225    s.write(tmpBuf, 0, bbwi.position());
1226    }
1227
1228    public void writeOctetSequenceTo(org.omg.CORBA.portable.OutputStream JavaDoc s) {
1229
1230        byte[] buf = null;
1231
1232        if (bbwi.byteBuffer.hasArray())
1233        {
1234            buf = bbwi.byteBuffer.array();
1235        }
1236        else
1237        {
1238            int size = bbwi.position();
1239            buf = new byte[size];
1240            // Micro-benchmarks are showing a loop of ByteBuffer.get(int) is
1241
// faster than ByteBuffer.get(byte[], offset, length)
1242
for (int i = 0; i < size; i++)
1243                buf[i] = bbwi.byteBuffer.get(i);
1244        }
1245
1246        s.write_long(bbwi.position());
1247        s.write_octet_array(buf, 0, bbwi.position());
1248
1249    }
1250
1251    public final int getSize() {
1252        return bbwi.position();
1253    }
1254
1255    public int getIndex() {
1256        return bbwi.position();
1257    }
1258
1259    public boolean isLittleEndian() {
1260        return littleEndian;
1261    }
1262
1263    public void setIndex(int value) {
1264        bbwi.position(value);
1265    }
1266
1267    public ByteBufferWithInfo getByteBufferWithInfo() {
1268        return bbwi;
1269    }
1270
1271    public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
1272        this.bbwi = bbwi;
1273    }
1274
1275    public ByteBuffer JavaDoc getByteBuffer() {
1276        ByteBuffer JavaDoc result = null;;
1277        if (bbwi != null) {
1278            result = bbwi.byteBuffer;
1279        }
1280        return result;
1281    }
1282
1283    public void setByteBuffer(ByteBuffer JavaDoc byteBuffer) {
1284        bbwi.byteBuffer = byteBuffer;
1285    }
1286
1287    private final void updateIndirectionTable(int indirection, java.lang.Object JavaDoc object,
1288                                              java.lang.Object JavaDoc key) {
1289    // int indirection = get_offset();
1290
if (valueCache == null)
1291        valueCache = new CacheTable(orb,true);
1292    valueCache.put(object, indirection);
1293    if (key != object)
1294        valueCache.put(key, indirection);
1295    }
1296
1297    private final void write_repositoryId(String JavaDoc id) {
1298        // Use an indirection if available
1299
if (repositoryIdCache != null && repositoryIdCache.containsKey(id)) {
1300            writeIndirection(INDIRECTION_TAG, repositoryIdCache.getVal(id));
1301        return;
1302        }
1303
1304        // Write it as a string. Note that we have already done the
1305
// special case conversion of non-Latin-1 characters to escaped
1306
// Latin-1 sequences in RepositoryId.
1307

1308        // It's not a good idea to cache them now that we can have
1309
// multiple code sets.
1310
int indirection = writeString(id);
1311
1312        // Add indirection for id to indirection table
1313
if (repositoryIdCache == null)
1314    repositoryIdCache = new CacheTable(orb,true);
1315        repositoryIdCache.put(id, indirection);
1316    }
1317
1318    private void write_codebase(String JavaDoc str, int pos) {
1319        if (codebaseCache != null && codebaseCache.containsKey(str)) {
1320            writeIndirection(INDIRECTION_TAG, codebaseCache.getVal(str));
1321        }
1322        else {
1323        write_string(str);
1324            if (codebaseCache == null)
1325            codebaseCache = new CacheTable(orb,true);
1326            codebaseCache.put(str, pos);
1327        }
1328    }
1329
1330    private final int writeValueTag(boolean chunkIt, boolean useRepId,
1331                    String JavaDoc codebase) {
1332    int indirection = 0;
1333    if (chunkIt && !useRepId){
1334        if (codebase == null) {
1335        write_long(repIdUtil.getStandardRMIChunkedNoRepStrId());
1336        indirection = get_offset() - 4;
1337        } else {
1338        write_long(repIdUtil.getCodeBaseRMIChunkedNoRepStrId());
1339        indirection = get_offset() - 4;
1340        write_codebase(codebase, get_offset());
1341        }
1342    } else if (chunkIt && useRepId){
1343        if (codebase == null) {
1344        write_long(repIdUtil.getStandardRMIChunkedId());
1345        indirection = get_offset() - 4;
1346        } else {
1347        write_long(repIdUtil.getCodeBaseRMIChunkedId());
1348        indirection = get_offset() - 4;
1349        write_codebase(codebase, get_offset());
1350        }
1351    } else if (!chunkIt && !useRepId) {
1352        if (codebase == null) {
1353        write_long(repIdUtil.getStandardRMIUnchunkedNoRepStrId());
1354        indirection = get_offset() - 4;
1355        } else {
1356        write_long(repIdUtil.getCodeBaseRMIUnchunkedNoRepStrId());
1357        indirection = get_offset() - 4;
1358        write_codebase(codebase, get_offset());
1359        }
1360    } else if (!chunkIt && useRepId) {
1361        if (codebase == null) {
1362        write_long(repIdUtil.getStandardRMIUnchunkedId());
1363        indirection = get_offset() - 4;
1364        } else {
1365        write_long(repIdUtil.getCodeBaseRMIUnchunkedId());
1366        indirection = get_offset() - 4;
1367        write_codebase(codebase, get_offset());
1368        }
1369    }
1370        return indirection;
1371    }
1372
1373    private void writeIDLValue(Serializable JavaDoc object, String JavaDoc repID)
1374    {
1375        if (object instanceof StreamableValue JavaDoc) {
1376        ((StreamableValue JavaDoc)object)._write(parent);
1377
1378    } else if (object instanceof CustomValue JavaDoc) {
1379        ((CustomValue JavaDoc)object).marshal(parent);
1380
1381    } else {
1382        BoxedValueHelper JavaDoc helper = Utility.getHelper(object.getClass(), null, repID);
1383        boolean isCustom = false;
1384        if (helper instanceof ValueHelper JavaDoc && object instanceof CustomMarshal JavaDoc) {
1385        try {
1386            if (((ValueHelper JavaDoc)helper).get_type().type_modifier() == VM_CUSTOM.value)
1387                isCustom = true;
1388            } catch(BadKind JavaDoc ex) {
1389            throw wrapper.badTypecodeForCustomValue( CompletionStatus.COMPLETED_MAYBE,
1390            ex ) ;
1391        }
1392        }
1393        if (isCustom)
1394        ((CustomMarshal JavaDoc)object).marshal(parent);
1395        else
1396        helper.write_value(parent, object);
1397    }
1398    }
1399
1400    // Handles end tag compaction...
1401
private void writeEndTag(boolean chunked){
1402        
1403    if (chunked) {
1404        if (get_offset() == end_flag_position) {
1405
1406                if (bbwi.position() == end_flag_index) {
1407
1408                    // We are exactly at the same position and index as the
1409
// end of the last end tag. Thus, we can back up over it
1410
// and compact the tags.
1411
bbwi.position(bbwi.position() - 4);
1412
1413                } else {
1414
1415                    // Special case in which we're at the beginning of a new
1416
// fragment, but the position is the same. We can't back up,
1417
// so we just write the new end tag without compaction. This
1418
// occurs when a value ends and calls start_block to open a
1419
// continuation chunk, but it's called at the very end of
1420
// a fragment.
1421
}
1422            }
1423
1424            writeNestingLevel();
1425
1426            // Remember the last index and position. These are only used when chunking.
1427
end_flag_index = bbwi.position();
1428            end_flag_position = get_offset();
1429
1430            chunkedValueNestingLevel++;
1431        }
1432
1433        // Increment the nesting level
1434
end_flag++;
1435    }
1436
1437    /**
1438     * Handles ORB versioning of the end tag. Should only
1439     * be called if chunking.
1440     *
1441     * If talking to our older ORBs (Standard Extension,
1442     * Kestrel, and Ladybird), write the end flag that takes
1443     * into account all enclosing valuetypes.
1444     *
1445     * If talking a newer or foreign ORB, or if the orb
1446     * instance is null, write the end flag that only takes
1447     * into account the enclosing chunked valuetypes.
1448     */

1449    private void writeNestingLevel() {
1450        if (orb == null ||
1451            ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
1452            ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
1453
1454            write_long(chunkedValueNestingLevel);
1455
1456        } else {
1457            write_long(end_flag);
1458        }
1459    }
1460
1461    private void writeClass(String JavaDoc repository_id, Class JavaDoc clz) {
1462
1463        if (repository_id == null)
1464            repository_id = repIdStrs.getClassDescValueRepId();
1465
1466        // Write value_tag
1467
int indirection = writeValueTag(mustChunk, true, null);
1468        updateIndirectionTable(indirection, clz, clz);
1469                        
1470        write_repositoryId(repository_id);
1471
1472        if (mustChunk) {
1473        // Write Value chunk
1474
start_block();
1475        end_flag--;
1476            chunkedValueNestingLevel--;
1477        } else
1478            end_flag--;
1479
1480        writeClassBody(clz);
1481
1482        if (mustChunk)
1483        end_block();
1484            
1485        // Write end tag
1486
writeEndTag(mustChunk);
1487    }
1488
1489    // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID
1490
// and codebase strings in the wrong order. This handles
1491
// backwards compatibility.
1492
private void writeClassBody(Class JavaDoc clz) {
1493        if (orb == null ||
1494            ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
1495            ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
1496
1497        write_value(Util.getCodebase(clz));
1498        write_value(repIdStrs.createForAnyType(clz));
1499        } else {
1500
1501        write_value(repIdStrs.createForAnyType(clz));
1502        write_value(Util.getCodebase(clz));
1503        }
1504    }
1505
1506    // Casts and returns an Object as a Serializable
1507
// This is required for JDK 1.1 only to avoid VerifyErrors when
1508
// passing arrays as Serializable
1509
// private java.io.Serializable make_serializable(java.lang.Object object)
1510
// {
1511
// return (java.io.Serializable)object;
1512
// }
1513

1514    private boolean shouldWriteAsIDLEntity(Serializable JavaDoc object)
1515    {
1516    return ((object instanceof IDLEntity JavaDoc) && (!(object instanceof ValueBase JavaDoc)) &&
1517        (!(object instanceof org.omg.CORBA.Object JavaDoc)));
1518            
1519    }
1520    
1521    private void writeIDLEntity(IDLEntity JavaDoc object) {
1522
1523    // _REVISIT_ could check to see whether chunking really needed
1524
mustChunk = true;
1525
1526    String JavaDoc repository_id = repIdStrs.createForJavaType(object);
1527    Class JavaDoc clazz = object.getClass();
1528    String JavaDoc codebase = Util.getCodebase(clazz);
1529        
1530    // Write value_tag
1531
int indirection = writeValueTag(true, true, codebase);
1532    updateIndirectionTable(indirection, object, object);
1533        
1534    // Write rep. id
1535
write_repositoryId(repository_id);
1536        
1537    // Write Value chunk
1538
end_flag--;
1539        chunkedValueNestingLevel--;
1540    start_block();
1541
1542    // Write the IDLEntity using reflection
1543
try {
1544            ClassLoader JavaDoc clazzLoader = (clazz == null ? null : clazz.getClassLoader());
1545        final Class JavaDoc helperClass = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
1546                                                   clazzLoader, clazz, clazzLoader);
1547        final Class JavaDoc argTypes[] = {org.omg.CORBA.portable.OutputStream JavaDoc.class, clazz};
1548            // getDeclaredMethod requires RuntimePermission accessDeclaredMembers
1549
// if a different class loader is used (even though the javadoc says otherwise)
1550
Method JavaDoc writeMethod = null;
1551            try {
1552                writeMethod = (Method JavaDoc)AccessController.doPrivileged(
1553                    new PrivilegedExceptionAction JavaDoc() {
1554                        public java.lang.Object JavaDoc run() throws NoSuchMethodException JavaDoc {
1555                            return helperClass.getDeclaredMethod(kWriteMethod, argTypes);
1556                        }
1557                    }
1558                );
1559            } catch (PrivilegedActionException JavaDoc pae) {
1560                // this gets caught below
1561
throw (NoSuchMethodException JavaDoc)pae.getException();
1562            }
1563        java.lang.Object JavaDoc args[] = {parent, object};
1564        writeMethod.invoke(null, args);
1565    } catch (ClassNotFoundException JavaDoc cnfe) {
1566        throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, cnfe ) ;
1567    } catch(NoSuchMethodException JavaDoc nsme) {
1568        throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, nsme ) ;
1569    } catch(IllegalAccessException JavaDoc iae) {
1570        throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, iae ) ;
1571    } catch(InvocationTargetException JavaDoc ite) {
1572        throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, ite ) ;
1573    }
1574    end_block();
1575        
1576    // Write end tag
1577
writeEndTag(true);
1578    }
1579    
1580    /* DataOutputStream methods */
1581
1582    public void write_Abstract (java.lang.Object JavaDoc value) {
1583        write_abstract_interface(value);
1584    }
1585
1586    public void write_Value (java.io.Serializable JavaDoc value) {
1587        write_value(value);
1588    }
1589
1590    // This will stay a custom add-on until the java-rtf issue is resolved.
1591
// Then it should be declared in org.omg.CORBA.portable.OutputStream.
1592
//
1593
// Pads the string representation of bigDecimal with zeros to fit the given
1594
// digits and scale before it gets written to the stream.
1595
public void write_fixed(java.math.BigDecimal JavaDoc bigDecimal, short digits, short scale) {
1596        String JavaDoc string = bigDecimal.toString();
1597        String JavaDoc integerPart;
1598        String JavaDoc fractionPart;
1599        StringBuffer JavaDoc stringBuffer;
1600
1601        // Get rid of the sign
1602
if (string.charAt(0) == '-' || string.charAt(0) == '+') {
1603            string = string.substring(1);
1604        }
1605
1606        // Determine integer and fraction parts
1607
int dotIndex = string.indexOf('.');
1608        if (dotIndex == -1) {
1609            integerPart = string;
1610            fractionPart = null;
1611        } else if (dotIndex == 0 ) {
1612            integerPart = null;
1613            fractionPart = string;
1614        } else {
1615            integerPart = string.substring(0, dotIndex);
1616            fractionPart = string.substring(dotIndex + 1);
1617        }
1618
1619        // Pad both parts with zeros as necessary
1620
stringBuffer = new StringBuffer JavaDoc(digits);
1621        if (fractionPart != null) {
1622            stringBuffer.append(fractionPart);
1623        }
1624        while (stringBuffer.length() < scale) {
1625            stringBuffer.append('0');
1626        }
1627        if (integerPart != null) {
1628            stringBuffer.insert(0, integerPart);
1629        }
1630        while (stringBuffer.length() < digits) {
1631            stringBuffer.insert(0, '0');
1632        }
1633
1634        // This string contains no sign or dot
1635
this.write_fixed(stringBuffer.toString(), bigDecimal.signum());
1636    }
1637
1638    // This method should be remove by the java-rtf issue.
1639
// Right now the scale and digits information of the type code is lost.
1640
public void write_fixed(java.math.BigDecimal JavaDoc bigDecimal) {
1641        // This string might contain sign and/or dot
1642
this.write_fixed(bigDecimal.toString(), bigDecimal.signum());
1643    }
1644
1645    // The string may contain a sign and dot
1646
public void write_fixed(String JavaDoc string, int signum) {
1647        int stringLength = string.length();
1648        // Each octet contains (up to) two decimal digits
1649
byte doubleDigit = 0;
1650        char ch;
1651        byte digit;
1652
1653        // First calculate the length of the string without optional sign and dot
1654
int numDigits = 0;
1655        for (int i=0; i<stringLength; i++) {
1656            ch = string.charAt(i);
1657            if (ch == '-' || ch == '+' || ch == '.')
1658                continue;
1659            numDigits++;
1660        }
1661        for (int i=0; i<stringLength; i++) {
1662            ch = string.charAt(i);
1663            if (ch == '-' || ch == '+' || ch == '.')
1664                continue;
1665            digit = (byte)Character.digit(ch, 10);
1666            if (digit == -1) {
1667        throw wrapper.badDigitInFixed( CompletionStatus.COMPLETED_MAYBE ) ;
1668            }
1669            // If the fixed type has an odd number of decimal digits,
1670
// then the representation begins with the first (most significant) digit.
1671
// Otherwise, this first half-octet is all zero, and the first digit
1672
// is in the second half-octet.
1673
if (numDigits % 2 == 0) {
1674                doubleDigit |= digit;
1675                this.write_octet(doubleDigit);
1676                doubleDigit = 0;
1677            } else {
1678                doubleDigit |= (digit << 4);
1679            }
1680            numDigits--;
1681        }
1682        // The sign configuration, in the last half-octet of the representation,
1683
// is 0xD for negative numbers and 0xC for positive and zero values
1684
if (signum == -1) {
1685            doubleDigit |= 0xd;
1686        } else {
1687            doubleDigit |= 0xc;
1688        }
1689        this.write_octet(doubleDigit);
1690    }
1691
1692    private final static String JavaDoc _id = "IDL:omg.org/CORBA/DataOutputStream:1.0";
1693    private final static String JavaDoc[] _ids = { _id };
1694
1695    public String JavaDoc[] _truncatable_ids() {
1696        if (_ids == null)
1697            return null;
1698
1699        return (String JavaDoc[])_ids.clone();
1700    }
1701
1702    /* for debugging */
1703
1704    public void printBuffer() {
1705        CDROutputStream_1_0.printBuffer(this.bbwi);
1706    }
1707
1708    public static void printBuffer(ByteBufferWithInfo bbwi) {
1709
1710        System.out.println("+++++++ Output Buffer ++++++++");
1711        System.out.println();
1712        System.out.println("Current position: " + bbwi.position());
1713        System.out.println("Total length : " + bbwi.buflen);
1714        System.out.println();
1715
1716        char[] charBuf = new char[16];
1717
1718        try {
1719
1720            for (int i = 0; i < bbwi.position(); i += 16) {
1721                
1722                int j = 0;
1723                
1724                // For every 16 bytes, there is one line
1725
// of output. First, the hex output of
1726
// the 16 bytes with each byte separated
1727
// by a space.
1728
while (j < 16 && j + i < bbwi.position()) {
1729                    int k = bbwi.byteBuffer.get(i + j);
1730                    if (k < 0)
1731                        k = 256 + k;
1732                    String JavaDoc hex = Integer.toHexString(k);
1733                    if (hex.length() == 1)
1734                        hex = "0" + hex;
1735                    System.out.print(hex + " ");
1736                    j++;
1737                }
1738                
1739                // Add any extra spaces to align the
1740
// text column in case we didn't end
1741
// at 16
1742
while (j < 16) {
1743                    System.out.print(" ");
1744                    j++;
1745                }
1746                
1747                // Now output the ASCII equivalents. Non-ASCII
1748
// characters are shown as periods.
1749
int x = 0;
1750
1751                while (x < 16 && x + i < bbwi.position()) {
1752                    if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x)))
1753                        charBuf[x] = (char)bbwi.byteBuffer.get(i + x);
1754                    else
1755                        charBuf[x] = '.';
1756                    x++;
1757                }
1758                System.out.println(new String JavaDoc(charBuf, 0, x));
1759            }
1760        } catch (Throwable JavaDoc t) {
1761            t.printStackTrace();
1762        }
1763        System.out.println("++++++++++++++++++++++++++++++");
1764    }
1765
1766    public void writeIndirection(int tag, int posIndirectedTo)
1767    {
1768        // Must ensure that there are no chunks between the tag
1769
// and the actual indirection value. This isn't talked about
1770
// in the spec, but seems to cause headaches in our code.
1771
// At the very least, this method isolates the indirection code
1772
// that was duplicated so often.
1773

1774        handleSpecialChunkBegin(computeAlignment(4) + 8);
1775
1776        // write indirection tag
1777
write_long(tag);
1778
1779        // write indirection
1780
// Use parent.getRealIndex() so that it can be overridden by TypeCodeOutputStreams
1781
/*
1782        System.out.println("CDROutputStream_1_0 writing indirection pos " + posIndirectedTo +
1783                           " - real index " + parent.getRealIndex(get_offset()) + " = " +
1784                           (posIndirectedTo - parent.getRealIndex(get_offset())));
1785*/

1786        write_long(posIndirectedTo - parent.getRealIndex(get_offset()));
1787
1788        handleSpecialChunkEnd();
1789    }
1790
1791    protected CodeSetConversion.CTBConverter getCharConverter() {
1792        if (charConverter == null)
1793            charConverter = parent.createCharCTBConverter();
1794        
1795        return charConverter;
1796    }
1797
1798    protected CodeSetConversion.CTBConverter getWCharConverter() {
1799        if (wcharConverter == null)
1800            wcharConverter = parent.createWCharCTBConverter();
1801    
1802        return wcharConverter;
1803    }
1804
1805    protected void dprint(String JavaDoc msg) {
1806        if (debug)
1807            ORBUtility.dprint(this, msg);
1808    }
1809
1810    void alignOnBoundary(int octetBoundary) {
1811        alignAndReserve(octetBoundary, 0);
1812    }
1813
1814    public void start_value(String JavaDoc rep_id) {
1815
1816        if (debug) {
1817            dprint("start_value w/ rep id "
1818           + rep_id
1819           + " called at pos "
1820           + get_offset()
1821           + " position "
1822           + bbwi.position());
1823    }
1824
1825    if (inBlock)
1826        end_block();
1827        
1828        // Write value_tag
1829
writeValueTag(true, true, null);
1830                
1831        // Write rep. id
1832
write_repositoryId(rep_id);
1833                
1834        // Write Value chunk
1835
end_flag--;
1836        chunkedValueNestingLevel--;
1837
1838        // Make sure to chunk the custom data
1839
start_block();
1840    }
1841
1842    public void end_value() {
1843
1844        if (debug) {
1845            dprint("end_value called at pos "
1846           + get_offset()
1847           + " position "
1848           + bbwi.position());
1849    }
1850
1851        end_block();
1852
1853        writeEndTag(true);
1854
1855    // Check to see if we need to start another block for a
1856
// possible outer value. Since we're in the stream
1857
// format 2 custom type contained by another custom
1858
// type, mustChunk should always be true.
1859
//
1860
// Here's why we need to open a continuation chunk:
1861
//
1862
// We need to enclose the default data of the
1863
// next subclass down in chunks. There won't be
1864
// an end tag separating the superclass optional
1865
// data and the subclass's default data.
1866

1867        if (debug) {
1868            dprint("mustChunk is " + mustChunk);
1869    }
1870
1871    if (mustChunk) {
1872        start_block();
1873        }
1874    }
1875
1876    public void close() throws IOException JavaDoc
1877    {
1878        // tell BufferManagerWrite to release any ByteBuffers
1879
getBufferManager().close();
1880
1881        // It's possible bbwi.byteBuffer is shared between
1882
// this OutputStream and an InputStream. Thus, we check
1883
// if the Input/Output streams are using the same ByteBuffer.
1884
// If they sharing the same ByteBuffer we need to ensure only
1885
// one of those ByteBuffers are released to the ByteBufferPool.
1886

1887        if (getByteBufferWithInfo() != null && getByteBuffer() != null)
1888        {
1889            int bbHash = System.identityHashCode(bbwi.byteBuffer);
1890            MessageMediator messageMediator = parent.getMessageMediator();
1891            if (messageMediator != null)
1892            {
1893                CDRInputObject inputObj =
1894                               (CDRInputObject)messageMediator.getInputObject();
1895                if (inputObj != null)
1896                {
1897                    ByteBuffer JavaDoc inputBb = inputObj.getByteBuffer();
1898
1899                    int iBbHash = 0;
1900                    if (inputBb != null)
1901                    {
1902                        iBbHash = System.identityHashCode(inputBb);
1903                        if (bbHash == iBbHash) // shared?
1904
{
1905                            // Set InputStream's ByteBuffer and bbwi to null
1906
// so its ByteBuffer cannot be released to the pool
1907
inputObj.setByteBuffer(null);
1908                            inputObj.setByteBufferWithInfo(null);
1909                        }
1910                    }
1911                }
1912            }
1913
1914            // release this stream's ByteBuffer to the pool
1915
ByteBufferPool byteBufferPool = orb.getByteBufferPool();
1916            if (debug)
1917            {
1918                // print address of ByteBuffer being released
1919
int bbAddress = System.identityHashCode(bbwi.byteBuffer);
1920                StringBuffer JavaDoc sb = new StringBuffer JavaDoc(80);
1921                sb.append(".close - releasing ByteBuffer id (");
1922                sb.append(bbAddress).append(") to ByteBufferPool.");
1923                String JavaDoc msg = sb.toString();
1924                dprint(msg);
1925             }
1926             byteBufferPool.releaseByteBuffer(getByteBuffer());
1927             bbwi.byteBuffer = null;
1928             bbwi = null;
1929        }
1930    }
1931}
1932
Popular Tags