FileDocCategorySizeDatePackage
CDROutputStream_1_0.javaAPI DocJava SE 5 API60370Fri Aug 26 14:54:20 BST 2005com.sun.corba.se.impl.encoding

CDROutputStream_1_0

public class CDROutputStream_1_0 extends CDROutputStreamBase

Fields Summary
private static final int
INDIRECTION_TAG
protected boolean
littleEndian
protected BufferManagerWrite
bufferManagerWrite
com.sun.corba.se.impl.encoding.ByteBufferWithInfo
bbwi
protected com.sun.corba.se.spi.orb.ORB
orb
protected com.sun.corba.se.impl.logging.ORBUtilSystemException
wrapper
protected boolean
debug
protected int
blockSizeIndex
protected int
blockSizePosition
protected byte
streamFormatVersion
private static final int
DEFAULT_BUFFER_SIZE
private static final String
kWriteMethod
private com.sun.corba.se.impl.orbutil.CacheTable
codebaseCache
private com.sun.corba.se.impl.orbutil.CacheTable
valueCache
private com.sun.corba.se.impl.orbutil.CacheTable
repositoryIdCache
private int
end_flag
private int
chunkedValueNestingLevel
private boolean
mustChunk
protected boolean
inBlock
private int
end_flag_position
private int
end_flag_index
private javax.rmi.CORBA.ValueHandler
valueHandler
private com.sun.corba.se.impl.orbutil.RepositoryIdUtility
repIdUtil
private com.sun.corba.se.impl.orbutil.RepositoryIdStrings
repIdStrs
private CodeSetConversion.CTBConverter
charConverter
private CodeSetConversion.CTBConverter
wcharConverter
private static final String
_id
private static final String[]
_ids
Constructors Summary
Methods Summary
public java.lang.String[]_truncatable_ids()


       
        if (_ids == null)
            return null;

        return (String[])_ids.clone();
    
protected voidalignAndReserve(int align, int n)


        bbwi.position(bbwi.position() + computeAlignment(align));

        if (bbwi.position() + n  > bbwi.buflen)
            grow(align, n);
    
voidalignOnBoundary(int octetBoundary)

        alignAndReserve(octetBoundary, 0);
    
public voidclose()

        // tell BufferManagerWrite to release any ByteBuffers
        getBufferManager().close();

        // It's possible bbwi.byteBuffer is shared between
        // this OutputStream and an InputStream. Thus, we check
        // if the Input/Output streams are using the same ByteBuffer.
        // If they sharing the same ByteBuffer we need to ensure only
        // one of those ByteBuffers are released to the ByteBufferPool.

        if (getByteBufferWithInfo() != null && getByteBuffer() != null)
        {
            int bbHash = System.identityHashCode(bbwi.byteBuffer);
            MessageMediator messageMediator = parent.getMessageMediator();
            if (messageMediator != null)
            {
                CDRInputObject inputObj = 
                               (CDRInputObject)messageMediator.getInputObject();
                if (inputObj != null)
                {
                    ByteBuffer inputBb = inputObj.getByteBuffer();

                    int iBbHash = 0;
                    if (inputBb != null)
                    {
                        iBbHash = System.identityHashCode(inputBb);
                        if (bbHash == iBbHash)  // shared?
                        {
                            // Set InputStream's ByteBuffer and bbwi to null
                            // so its ByteBuffer cannot be released to the pool
                            inputObj.setByteBuffer(null);
                            inputObj.setByteBufferWithInfo(null);
                        }
                    }
                }
            }

            // release this stream's ByteBuffer to the pool
            ByteBufferPool byteBufferPool = orb.getByteBufferPool();
            if (debug)
            {
                // print address of ByteBuffer being released
                int bbAddress = System.identityHashCode(bbwi.byteBuffer);
                StringBuffer sb = new StringBuffer(80);
                sb.append(".close - releasing ByteBuffer id (");
                sb.append(bbAddress).append(") to ByteBufferPool.");
                String msg = sb.toString();
                dprint(msg);
             }
             byteBufferPool.releaseByteBuffer(getByteBuffer());
             bbwi.byteBuffer = null;
             bbwi = null;
        }
    
protected final intcomputeAlignment(int align)

        if (align > 1) {
            int incr = bbwi.position() & (align - 1);
            if (incr != 0)
                return align - incr;
        }

        return 0;
    
private final voidcreateRepositoryIdHandlers()

        if (orb != null) {
            // Get the appropriate versions based on the ORB version.  The
            // ORB versioning info is only in the core ORB.
            repIdUtil 
                = RepositoryIdFactory.getRepIdUtility(orb);
            repIdStrs 
                = RepositoryIdFactory.getRepIdStringsFactory(orb);
        } else {
            // Get the latest versions
            repIdUtil = RepositoryIdFactory.getRepIdUtility();
            repIdStrs = RepositoryIdFactory.getRepIdStringsFactory();
        }
    
protected voiddprint(java.lang.String msg)

        if (debug)
            ORBUtility.dprint(this, msg);
    
public voidend_block()

        if (debug) {
            dprint("CDROutputStream_1_0.java end_block");
	}

	if (!inBlock)
	    return;

        if (debug) {
            dprint("CDROutputStream_1_0.java end_block, in a block");
	}

	inBlock = false;

	// Test to see if the block was of zero length
	// If so, remove the block instead of ending it
	// (This can happen if the last field written 
	//  in a value was another value)
	if (get_offset() == blockSizePosition) {
            // Need to assert that blockSizeIndex == bbwi.position()?  REVISIT

            bbwi.position(bbwi.position() - 4);
	    blockSizeIndex = -1;
            blockSizePosition = -1;
	    return;
	}

	int oldSize = bbwi.position();
	bbwi.position(blockSizeIndex - 4);

        writeLongWithoutAlign(oldSize - blockSizeIndex);

	bbwi.position(oldSize);
	blockSizeIndex = -1;
        blockSizePosition = -1;

        // System.out.println("      post end_block: " + get_offset() + " " + bbwi.position());
    
public voidend_value()


        if (debug) {
            dprint("end_value called at pos "
		   + get_offset()
		   + " position "
		   + bbwi.position());
	}

        end_block();

        writeEndTag(true);

	// Check to see if we need to start another block for a
	// possible outer value.  Since we're in the stream
        // format 2 custom type contained by another custom
        // type, mustChunk should always be true.
        //
        // Here's why we need to open a continuation chunk:
        //
        // We need to enclose the default data of the
        // next subclass down in chunks.  There won't be
        // an end tag separating the superclass optional
        // data and the subclass's default data.

        if (debug) {
            dprint("mustChunk is " + mustChunk);
	}

	if (mustChunk) {
	    start_block();
        }
    
voidfreeInternalCaches()

	if (codebaseCache != null)
	    codebaseCache.done();

	if (valueCache != null)
	    valueCache.done();
		
	if (repositoryIdCache != null)
	    repositoryIdCache.done();
    
public BufferManagerWritegetBufferManager()

	return bufferManagerWrite;
    
public java.nio.ByteBuffergetByteBuffer()

        ByteBuffer result = null;;
        if (bbwi != null) {
            result = bbwi.byteBuffer;
        }
        return result;
    
public com.sun.corba.se.impl.encoding.ByteBufferWithInfogetByteBufferWithInfo()

        return bbwi;
    
protected CodeSetConversion.CTBConvertergetCharConverter()

        if (charConverter == null)
            charConverter = parent.createCharCTBConverter();
        
        return charConverter;
    
public com.sun.corba.se.spi.ior.iiop.GIOPVersiongetGIOPVersion()

        return GIOPVersion.V1_0;
    
public intgetIndex()

    	return bbwi.position();
    
public final intgetSize()

    	return bbwi.position();
    
protected CodeSetConversion.CTBConvertergetWCharConverter()

        if (wcharConverter == null)
            wcharConverter = parent.createWCharCTBConverter();
    
        return wcharConverter;
    
public intget_offset()

	return bbwi.position();
    
protected voidgrow(int align, int n)

        bbwi.needed = n;

        bufferManagerWrite.overflow(bbwi);
    
protected voidhandleSpecialChunkBegin(int requiredSize)

        // No-op for GIOP 1.0
    
protected voidhandleSpecialChunkEnd()

        // No-op for GIOP 1.0
    
public voidinit(org.omg.CORBA.ORB orb, boolean littleEndian, BufferManagerWrite bufferManager, byte streamFormatVersion, boolean usePooledByteBuffers)

    
    // REVISIT - This should be re-factored so that including whether
    // to use pool byte buffers or not doesn't need to be known.
       
                         
                         
                         
                         
    
        // ORB must not be null.  See CDROutputStream constructor.
        this.orb = (ORB)orb;
	this.wrapper = ORBUtilSystemException.get( this.orb, 
	    CORBALogDomains.RPC_ENCODING ) ;
	debug = this.orb.transportDebugFlag;

        this.littleEndian = littleEndian;
        this.bufferManagerWrite = bufferManager;
        this.bbwi = new ByteBufferWithInfo(orb, bufferManager, usePooledByteBuffers);
	this.streamFormatVersion = streamFormatVersion;

        createRepositoryIdHandlers();
    
public voidinit(org.omg.CORBA.ORB orb, boolean littleEndian, BufferManagerWrite bufferManager, byte streamFormatVersion)

       init(orb, littleEndian, bufferManager, streamFormatVersion, true);
   
voidinternalWriteOctetArray(byte[] value, int offset, int length)

    	int n = offset;

	// This flag forces the alignAndReserve method to be called the
	// first time an octet is written. This is necessary to ensure
	// that the body is aligned on an 8-octet boundary. Note the 'if'
	// condition inside the 'while' loop below. Also, refer to the
	// write_octet() method that has a similar change.
	boolean align = true;
            
    	while (n < length+offset) {
    	    int avail;
    	    int bytes;
    	    int wanted;

            if ((bbwi.position() + 1 > bbwi.buflen) || align) {
		align = false;
        	alignAndReserve(1, 1);
	    }
    	    avail = bbwi.buflen - bbwi.position();
    	    wanted = (length + offset) - n;
    	    bytes = (wanted < avail) ? wanted : avail;
            for (int i = 0; i < bytes; i++)
                bbwi.byteBuffer.put(bbwi.position() + i, value[n+i]);
    	    bbwi.position(bbwi.position() + bytes);
    	    n += bytes;
    	}
    
public booleanisLittleEndian()

        return littleEndian;
    
public final booleanlittleEndian()

    	return littleEndian;
    
public org.omg.CORBA.ORBorb()

        return orb;    
    
public voidprintBuffer()

        CDROutputStream_1_0.printBuffer(this.bbwi);
    
public static voidprintBuffer(com.sun.corba.se.impl.encoding.ByteBufferWithInfo bbwi)


        System.out.println("+++++++ Output Buffer ++++++++");
        System.out.println();
        System.out.println("Current position: " + bbwi.position());
        System.out.println("Total length : " + bbwi.buflen);
        System.out.println();

        char[] charBuf = new char[16];

        try {

            for (int i = 0; i < bbwi.position(); i += 16) {
                
                int j = 0;
                
                // For every 16 bytes, there is one line
                // of output.  First, the hex output of
                // the 16 bytes with each byte separated
                // by a space.
                while (j < 16 && j + i < bbwi.position()) {
                    int k = bbwi.byteBuffer.get(i + j);
                    if (k < 0)
                        k = 256 + k;
                    String hex = Integer.toHexString(k);
                    if (hex.length() == 1)
                        hex = "0" + hex;
                    System.out.print(hex + " ");
                    j++;
                }
                
                // Add any extra spaces to align the
                // text column in case we didn't end
                // at 16
                while (j < 16) {
                    System.out.print("   ");
                    j++;
                }
                
                // Now output the ASCII equivalents.  Non-ASCII
                // characters are shown as periods.
                int x = 0;

                while (x < 16 && x + i < bbwi.position()) {
                    if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x)))
                        charBuf[x] = (char)bbwi.byteBuffer.get(i + x);
                    else
                        charBuf[x] = '.";
                    x++;
                }
                System.out.println(new String(charBuf, 0, x));
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
        System.out.println("++++++++++++++++++++++++++++++");
    
public final voidputEndian()

    	write_boolean(littleEndian);
    
public voidsetByteBuffer(java.nio.ByteBuffer byteBuffer)

        bbwi.byteBuffer = byteBuffer;
    
public voidsetByteBufferWithInfo(com.sun.corba.se.impl.encoding.ByteBufferWithInfo bbwi)

        this.bbwi = bbwi;
    
voidsetHeaderPadding(boolean headerPadding)

        throw wrapper.giopVersionError();
    
public voidsetIndex(int value)

        bbwi.position(value);
    
private booleanshouldWriteAsIDLEntity(java.io.Serializable object)

	return ((object instanceof IDLEntity) && (!(object instanceof ValueBase)) &&
		(!(object instanceof org.omg.CORBA.Object)));
			
    
public voidstart_block()

        if (debug) {
            dprint("CDROutputStream_1_0 start_block, position" + bbwi.position());
	}

        //Move inBlock=true to after write_long since write_long might
        //trigger grow which will lead to erroneous behavior with a
        //missing blockSizeIndex.
	//inBlock = true;

	// Save space in the buffer for block size
	write_long(0);

        //Has to happen after write_long since write_long could
        //trigger grow which is overridden by supper classes to 
        //depend on inBlock.
        inBlock = true; 

        blockSizePosition = get_offset();

	// Remember where to put the size of the endblock less 4
	blockSizeIndex = bbwi.position();

        if (debug) {
            dprint("CDROutputStream_1_0 start_block, blockSizeIndex " 
		   + blockSizeIndex);
	}

    
public voidstart_value(java.lang.String rep_id)


        if (debug) {
            dprint("start_value w/ rep id "
		   + rep_id
		   + " called at pos "
		   + get_offset() 
		   + " position "
		   + bbwi.position());
	}

	if (inBlock)
	    end_block();
        
        // Write value_tag
        writeValueTag(true, true, null);
				
        // Write rep. id
        write_repositoryId(rep_id);
				
        // Write Value chunk
        end_flag--;
        chunkedValueNestingLevel--;

        // Make sure to chunk the custom data
        start_block();
    
public byte[]toByteArray()

    	byte[] it;

    	it = new byte[bbwi.position()];

        // Micro-benchmarks show ByteBuffer.get(int) out perform the bulk
        // ByteBuffer.get(byte[], offset, length).
        for (int i = 0; i < bbwi.position(); i++)
            it[i] = bbwi.byteBuffer.get(i);

    	return it;
    
private final voidupdateIndirectionTable(int indirection, java.lang.Object object, java.lang.Object key)

	// int indirection = get_offset();
	if (valueCache == null)
	    valueCache = new CacheTable(orb,true);
	valueCache.put(object, indirection);
	if (key != object)
	    valueCache.put(key, indirection);
    
private voidwriteArray(java.io.Serializable array, java.lang.Class clazz)


        if (valueHandler == null)
            valueHandler = ORBUtility.createValueHandler(orb); //d11638

        // Write value_tag
        int indirection = writeValueTag(mustChunk, true,
					Util.getCodebase(clazz));
				
        // Write repository ID
        write_repositoryId(repIdStrs.createSequenceRepID(clazz));
				
        // Add indirection for object to indirection table
        updateIndirectionTable(indirection, array, array);
				
        // Write Value chunk
        if (mustChunk) {
            start_block();
            end_flag--;
            chunkedValueNestingLevel--;
        } else
            end_flag--;

        if (valueHandler instanceof ValueHandlerMultiFormat) {
            ValueHandlerMultiFormat vh = (ValueHandlerMultiFormat)valueHandler;
            vh.writeValue(parent, array, streamFormatVersion);
        } else
            valueHandler.writeValue(parent, array);

        if (mustChunk)
            end_block();
				
        // Write end tag
        writeEndTag(mustChunk);
    
private final voidwriteBigEndianLong(int x)

    	bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 24) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 16) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 8) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 3, (byte)(x & 0xFF));
        bbwi.position(bbwi.position() + 4);
    
private final voidwriteBigEndianLongLong(long x)

    	bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 56) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 48) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 40) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 32) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 4, (byte)((x >>> 24) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 5, (byte)((x >>> 16) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 6, (byte)((x >>> 8) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 7, (byte)(x & 0xFF));
        bbwi.position(bbwi.position() + 8);
    
private final voidwriteBigEndianShort(short x)

    	bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 8) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 1, (byte)(x & 0xFF));
        bbwi.position(bbwi.position() + 2);
    
private final voidwriteBigEndianWchar(char x)

    	bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 8) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 1, (byte)(x & 0xFF));
        bbwi.position(bbwi.position() + 2);
    
private voidwriteClass(java.lang.String repository_id, java.lang.Class clz)


        if (repository_id == null)
            repository_id = repIdStrs.getClassDescValueRepId();

        // Write value_tag
        int indirection = writeValueTag(mustChunk, true, null);
        updateIndirectionTable(indirection, clz, clz);
            			
        write_repositoryId(repository_id);

        if (mustChunk) {
	    // Write Value chunk
	    start_block();
	    end_flag--;
            chunkedValueNestingLevel--;
        } else
            end_flag--;

        writeClassBody(clz);

        if (mustChunk)
	    end_block();
			
        // Write end tag
        writeEndTag(mustChunk);
    
private voidwriteClassBody(java.lang.Class clz)

        if (orb == null ||
            ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
            ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {

	    write_value(Util.getCodebase(clz));
	    write_value(repIdStrs.createForAnyType(clz));
        } else {

	    write_value(repIdStrs.createForAnyType(clz));
	    write_value(Util.getCodebase(clz));
        }
    
private voidwriteEndTag(boolean chunked)

		
	if (chunked) {
	    if (get_offset() == end_flag_position) {

                if (bbwi.position() == end_flag_index) {

                    // We are exactly at the same position and index as the
                    // end of the last end tag.  Thus, we can back up over it
                    // and compact the tags.
                    bbwi.position(bbwi.position() - 4);

                } else {

                    // Special case in which we're at the beginning of a new
                    // fragment, but the position is the same.  We can't back up,
                    // so we just write the new end tag without compaction.  This
                    // occurs when a value ends and calls start_block to open a
                    // continuation chunk, but it's called at the very end of
                    // a fragment.
                }
            }

            writeNestingLevel();

            // Remember the last index and position.  These are only used when chunking.
            end_flag_index = bbwi.position();
            end_flag_position = get_offset();

            chunkedValueNestingLevel++;
        }

        // Increment the nesting level
	end_flag++;
    
private voidwriteIDLEntity(org.omg.CORBA.portable.IDLEntity object)


	// _REVISIT_ could check to see whether chunking really needed 
	mustChunk = true;

	String repository_id = repIdStrs.createForJavaType(object);
	Class clazz = object.getClass();
	String codebase = Util.getCodebase(clazz); 
		
	// Write value_tag
	int indirection = writeValueTag(true, true, codebase);
	updateIndirectionTable(indirection, object, object);
		
	// Write rep. id
	write_repositoryId(repository_id);
		
	// Write Value chunk
	end_flag--;
        chunkedValueNestingLevel--;
	start_block();

	// Write the IDLEntity using reflection 
	try {
            ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader());
	    final Class helperClass = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
                                                   clazzLoader, clazz, clazzLoader);
	    final Class argTypes[] = {org.omg.CORBA.portable.OutputStream.class, clazz};
            // getDeclaredMethod requires RuntimePermission accessDeclaredMembers
            // if a different class loader is used (even though the javadoc says otherwise)
            Method writeMethod = null;
            try {
                writeMethod = (Method)AccessController.doPrivileged(
                    new PrivilegedExceptionAction() {
                        public java.lang.Object run() throws NoSuchMethodException {
                            return helperClass.getDeclaredMethod(kWriteMethod, argTypes);
                        }
                    }
                );
            } catch (PrivilegedActionException pae) {
                // this gets caught below
                throw (NoSuchMethodException)pae.getException();
            }
	    java.lang.Object args[] = {parent, object};
	    writeMethod.invoke(null, args);
	} catch (ClassNotFoundException cnfe) {
	    throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, cnfe ) ;
	} catch(NoSuchMethodException nsme) {
	    throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, nsme ) ;
	} catch(IllegalAccessException iae) {
	    throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, iae ) ;
	} catch(InvocationTargetException ite) {
	    throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, ite ) ;
	}
	end_block();
		
	// Write end tag
	writeEndTag(true);
    
private voidwriteIDLValue(java.io.Serializable object, java.lang.String repID)

    	if (object instanceof StreamableValue) {
	    ((StreamableValue)object)._write(parent);

	} else if (object instanceof CustomValue) {
	    ((CustomValue)object).marshal(parent);

	} else {
	    BoxedValueHelper helper = Utility.getHelper(object.getClass(), null, repID);
	    boolean isCustom = false;
	    if (helper instanceof ValueHelper && object instanceof CustomMarshal) {
		try {
		    if (((ValueHelper)helper).get_type().type_modifier() == VM_CUSTOM.value)
		        isCustom = true;
	        } catch(BadKind ex) {
		    throw wrapper.badTypecodeForCustomValue( CompletionStatus.COMPLETED_MAYBE,
			ex ) ;
		}  
	    }
	    if (isCustom)
		((CustomMarshal)object).marshal(parent);
	    else
		helper.write_value(parent, object);
	}
    
public voidwriteIndirection(int tag, int posIndirectedTo)

        // Must ensure that there are no chunks between the tag
        // and the actual indirection value.  This isn't talked about
        // in the spec, but seems to cause headaches in our code.
        // At the very least, this method isolates the indirection code
        // that was duplicated so often.

        handleSpecialChunkBegin(computeAlignment(4) + 8);

        // write indirection tag
        write_long(tag);

        // write indirection
        // Use parent.getRealIndex() so that it can be overridden by TypeCodeOutputStreams
/*
        System.out.println("CDROutputStream_1_0 writing indirection pos " + posIndirectedTo +
                           " - real index " + parent.getRealIndex(get_offset()) + " = " +
                           (posIndirectedTo - parent.getRealIndex(get_offset())));
*/
        write_long(posIndirectedTo - parent.getRealIndex(get_offset()));

        handleSpecialChunkEnd();
    
private final voidwriteLittleEndianLong(int x)

    	bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 16) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 24) & 0xFF));
        bbwi.position(bbwi.position() + 4);
    
private final voidwriteLittleEndianLongLong(long x)

    	bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 16) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 24) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 4, (byte)((x >>> 32) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 5, (byte)((x >>> 40) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 6, (byte)((x >>> 48) & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 7, (byte)((x >>> 56) & 0xFF));
        bbwi.position(bbwi.position() + 8);
    
private final voidwriteLittleEndianShort(short x)

    	bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
        bbwi.position(bbwi.position() + 2);
    
private final voidwriteLittleEndianWchar(char x)

    	bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
    	bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
        bbwi.position(bbwi.position() + 2);
    
protected voidwriteLongWithoutAlign(int x)

    	if (littleEndian) {
    	    writeLittleEndianLong(x);
    	} else {
    	    writeBigEndianLong(x);
        }
    
private voidwriteNestingLevel()
Handles ORB versioning of the end tag. Should only be called if chunking. If talking to our older ORBs (Standard Extension, Kestrel, and Ladybird), write the end flag that takes into account all enclosing valuetypes. If talking a newer or foreign ORB, or if the orb instance is null, write the end flag that only takes into account the enclosing chunked valuetypes.

        if (orb == null ||
            ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
            ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {

            write_long(chunkedValueNestingLevel);

        } else {
            write_long(end_flag);
        }
    
public voidwriteOctetSequenceTo(org.omg.CORBA.portable.OutputStream s)


        byte[] buf = null;

        if (bbwi.byteBuffer.hasArray())
        {
            buf = bbwi.byteBuffer.array();
        }
        else
        {
            int size = bbwi.position();
            buf = new byte[size];
            // Micro-benchmarks are showing a loop of ByteBuffer.get(int) is
            // faster than ByteBuffer.get(byte[], offset, length)
            for (int i = 0; i < size; i++)
                buf[i] = bbwi.byteBuffer.get(i);
        }

    	s.write_long(bbwi.position());
    	s.write_octet_array(buf, 0, bbwi.position());

    
private voidwriteRMIIIOPValueType(java.io.Serializable object, java.lang.Class clazz)

        if (valueHandler == null)
            valueHandler = ORBUtility.createValueHandler(orb); //d11638

        Serializable key = object;

        // Allow the ValueHandler to call writeReplace on
        // the Serializable (if the method is present)
        object = valueHandler.writeReplace(key);
		
        if (object == null) {
            // Write null tag and return
            write_long(0);
            return;
        }
		
        if (object != key) {
            if (valueCache != null && valueCache.containsKey(object)) {
                writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
                return;
            }
            
            clazz = object.getClass();
        }

        if (mustChunk || valueHandler.isCustomMarshaled(clazz)) {
            mustChunk = true;
        }
				
        // Write value_tag
        int indirection = writeValueTag(mustChunk, true, Util.getCodebase(clazz));
				
        // Write rep. id
        write_repositoryId(repIdStrs.createForJavaType(clazz));
				
        // Add indirection for object to indirection table
        updateIndirectionTable(indirection, object, key);

        if (mustChunk) {
            // Write Value chunk
            end_flag--;
            chunkedValueNestingLevel--;
            start_block();
        } else
            end_flag--;

        if (valueHandler instanceof ValueHandlerMultiFormat) {
            ValueHandlerMultiFormat vh = (ValueHandlerMultiFormat)valueHandler;
            vh.writeValue(parent, object, streamFormatVersion);
        } else
            valueHandler.writeValue(parent, object);

        if (mustChunk)
            end_block();
				
        // Write end tag
        writeEndTag(mustChunk);
    
protected intwriteString(java.lang.String value)

        if (value == null) {
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
        }

        CodeSetConversion.CTBConverter converter = getCharConverter();

        converter.convert(value);

        // A string is encoded as an unsigned CORBA long for the
        // number of bytes to follow (including a terminating null).
        // There is only one octet per character in the string.
    	int len = converter.getNumBytes() + 1;

        handleSpecialChunkBegin(computeAlignment(4) + 4 + len);

        write_long(len);
        int indirection = get_offset() - 4;

        internalWriteOctetArray(converter.getBytes(), 0, converter.getNumBytes());

        // Write the null ending
        write_octet((byte)0);

        handleSpecialChunkEnd();
        return indirection;
    
public voidwriteTo(java.io.OutputStream s)

        byte[] tmpBuf = null;

        if (bbwi.byteBuffer.hasArray())
        {
            tmpBuf = bbwi.byteBuffer.array();
        }
        else
        {
            int size = bbwi.position();
            tmpBuf = new byte[size];
            // Micro-benchmarks are showing a loop of ByteBuffer.get(int) is
            // faster than ByteBuffer.get(byte[], offset, length)
            for (int i = 0; i < size; i++)
                tmpBuf[i] = bbwi.byteBuffer.get(i);
        }

	s.write(tmpBuf, 0, bbwi.position());	
    
private voidwriteValueBase(org.omg.CORBA.portable.ValueBase object, java.lang.Class clazz)

        // _REVISIT_ could check to see whether chunking really needed 
        mustChunk = true;
			
        // Write value_tag
        int indirection = writeValueTag(true, true, Util.getCodebase(clazz));
			
        // Get rep id
        String repId = ((ValueBase)object)._truncatable_ids()[0];
			
        // Write rep id
        write_repositoryId(repId);
			
        // Add indirection for object to indirection table
        updateIndirectionTable(indirection, object, object);
        
        // Write Value chunk
        start_block();
        end_flag--;
        chunkedValueNestingLevel--;
        writeIDLValue(object, repId);
        end_block();
        
        // Write end tag
        writeEndTag(true);
    
private final intwriteValueTag(boolean chunkIt, boolean useRepId, java.lang.String codebase)

	int indirection = 0;
	if (chunkIt && !useRepId){
	    if (codebase == null) {
		write_long(repIdUtil.getStandardRMIChunkedNoRepStrId());
		indirection = get_offset() - 4;
	    } else {			
		write_long(repIdUtil.getCodeBaseRMIChunkedNoRepStrId());
		indirection = get_offset() - 4;
		write_codebase(codebase, get_offset());
	    }
	} else if (chunkIt && useRepId){
	    if (codebase == null) {
		write_long(repIdUtil.getStandardRMIChunkedId());
		indirection = get_offset() - 4;
	    } else {			
		write_long(repIdUtil.getCodeBaseRMIChunkedId());
		indirection = get_offset() - 4;
		write_codebase(codebase, get_offset());
	    }
	} else if (!chunkIt && !useRepId) {
	    if (codebase == null) {
		write_long(repIdUtil.getStandardRMIUnchunkedNoRepStrId());
		indirection = get_offset() - 4;
	    } else {			
		write_long(repIdUtil.getCodeBaseRMIUnchunkedNoRepStrId());
		indirection = get_offset() - 4;
		write_codebase(codebase, get_offset());
	    }
	} else if (!chunkIt && useRepId) {
	    if (codebase == null) {
		write_long(repIdUtil.getStandardRMIUnchunkedId());
		indirection = get_offset() - 4;
	    } else {			
		write_long(repIdUtil.getCodeBaseRMIUnchunkedId());
		indirection = get_offset() - 4;
		write_codebase(codebase, get_offset());
	    }
	}
        return indirection;
    
private voidwriteWStringValue(java.lang.String string)


        int indirection = writeValueTag(mustChunk, true, null);
            
        // Write WStringValue's repository ID
        write_repositoryId(repIdStrs.getWStringValueRepId());
            
        // Add indirection for object to indirection table
        updateIndirectionTable(indirection, string, string);

        // Write Value chunk
        if (mustChunk) {
            start_block();
            end_flag--;
            chunkedValueNestingLevel--;
        } else
            end_flag--;
            
        write_wstring(string);
        
        if (mustChunk)
            end_block();
            
        // Write end tag
        writeEndTag(mustChunk);
    
public voidwrite_Abstract(java.lang.Object value)

        write_abstract_interface(value);
    
public voidwrite_Object(org.omg.CORBA.Object ref)

        if (ref == null) {
	    IOR nullIOR = IORFactories.makeIOR( orb ) ;
            nullIOR.write(parent);
            return;
        }
		
        // IDL to Java formal 01-06-06 1.21.4.2
        if (ref instanceof org.omg.CORBA.LocalObject)
	    throw wrapper.writeLocalObject(CompletionStatus.COMPLETED_MAYBE);
    
	IOR ior = ORBUtility.connectAndGetIOR( orb, ref ) ;
	ior.write(parent);
	return;
    
public voidwrite_Principal(org.omg.CORBA.Principal p)

    	write_long(p.name().length);
    	write_octet_array(p.name(), 0, p.name().length);
    
public voidwrite_TypeCode(org.omg.CORBA.TypeCode tc)

        if ( tc == null ) {
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
	}
        TypeCodeImpl tci;
        if (tc instanceof TypeCodeImpl) {
	    tci = (TypeCodeImpl)tc;
	}
        else {
	    tci = new TypeCodeImpl(orb, tc);
	}

        tci.write_value((org.omg.CORBA_2_3.portable.OutputStream)parent);
    
public voidwrite_Value(java.io.Serializable value)

        write_value(value);
    
public voidwrite_abstract_interface(java.lang.Object obj)

	boolean corbaObject = false; // Assume value type.
	org.omg.CORBA.Object theObject = null;
	    
	// Is it a CORBA.Object?
	    
	if (obj != null && obj instanceof org.omg.CORBA.Object) {
	        
	    // Yes.
	        
	    theObject = (org.omg.CORBA.Object)obj;
	    corbaObject = true;	        
	}
	    
	// Write our flag...
	    
	write_boolean(corbaObject);
	    
	// Now write out the object...
	    
	if (corbaObject) {
	    write_Object(theObject);
	} else {
	    try {
		write_value((java.io.Serializable)obj);
	    } catch(ClassCastException cce) {
		if (obj instanceof java.io.Serializable)
		    throw cce;
		else
                    ORBUtility.throwNotSerializableForCorba(obj.getClass().getName());
	    }
	}
    
public voidwrite_any(org.omg.CORBA.Any any)

        if ( any == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

    	write_TypeCode(any.type());
    	any.write_value(parent);
    
public final voidwrite_any_array(org.omg.CORBA.Any[] value, int offset, int length)

    	for(int i = 0; i < length; i++) 
    	    write_any(value[offset + i]);
    
public final voidwrite_boolean(boolean x)

	write_octet(x? (byte)1:(byte)0);
    
public final voidwrite_boolean_array(boolean[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(length);

        for (int i = 0; i < length; i++)
            write_boolean(value[offset + i]);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
public voidwrite_char(char x)

        CodeSetConversion.CTBConverter converter = getCharConverter();

        converter.convert(x);

        // CORBA formal 99-10-07 15.3.1.6: "In the case of multi-byte encodings
        // of characters, a single instance of the char type may only
        // hold one octet of any multi-byte character encoding."
        if (converter.getNumBytes() > 1)
	    throw wrapper.invalidSingleCharCtb(CompletionStatus.COMPLETED_MAYBE);

        write_octet(converter.getBytes()[0]);
    
public final voidwrite_char_array(char[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(length);

        for (int i = 0; i < length; i++)
            write_char(value[offset + i]);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
private voidwrite_codebase(java.lang.String str, int pos)

        if (codebaseCache != null && codebaseCache.containsKey(str)) {
            writeIndirection(INDIRECTION_TAG, codebaseCache.getVal(str));
        }
        else {
	    write_string(str);
            if (codebaseCache == null)
        	codebaseCache = new CacheTable(orb,true);
            codebaseCache.put(str, pos);
        }
    
public final voidwrite_double(double x)

	write_longlong(Double.doubleToLongBits(x));
    
public final voidwrite_double_array(double[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(computeAlignment(8) + (length * 8));

        for (int i = 0; i < length; i++)
            write_double(value[offset + i]);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
public voidwrite_fixed(java.math.BigDecimal bigDecimal, short digits, short scale)

        String string = bigDecimal.toString();
        String integerPart;
        String fractionPart;
        StringBuffer stringBuffer;

        // Get rid of the sign
        if (string.charAt(0) == '-" || string.charAt(0) == '+") {
            string = string.substring(1);
        }

        // Determine integer and fraction parts
        int dotIndex = string.indexOf('.");
        if (dotIndex == -1) {
            integerPart = string;
            fractionPart = null;
        } else if (dotIndex == 0 ) {
            integerPart = null;
            fractionPart = string;
        } else {
            integerPart = string.substring(0, dotIndex);
            fractionPart = string.substring(dotIndex + 1);
        }

        // Pad both parts with zeros as necessary
        stringBuffer = new StringBuffer(digits);
        if (fractionPart != null) {
            stringBuffer.append(fractionPart);
        }
        while (stringBuffer.length() < scale) {
            stringBuffer.append('0");
        }
        if (integerPart != null) {
            stringBuffer.insert(0, integerPart);
        }
        while (stringBuffer.length() < digits) {
            stringBuffer.insert(0, '0");
        }

        // This string contains no sign or dot
        this.write_fixed(stringBuffer.toString(), bigDecimal.signum());
    
public voidwrite_fixed(java.math.BigDecimal bigDecimal)

        // This string might contain sign and/or dot
        this.write_fixed(bigDecimal.toString(), bigDecimal.signum());
    
public voidwrite_fixed(java.lang.String string, int signum)

        int stringLength = string.length();
        // Each octet contains (up to) two decimal digits
        byte doubleDigit = 0;
        char ch;
        byte digit;

        // First calculate the length of the string without optional sign and dot
        int numDigits = 0;
        for (int i=0; i<stringLength; i++) {
            ch = string.charAt(i);
            if (ch == '-" || ch == '+" || ch == '.")
                continue;
            numDigits++;
        }
        for (int i=0; i<stringLength; i++) {
            ch = string.charAt(i);
            if (ch == '-" || ch == '+" || ch == '.")
                continue;
            digit = (byte)Character.digit(ch, 10);
            if (digit == -1) {
		throw wrapper.badDigitInFixed( CompletionStatus.COMPLETED_MAYBE ) ;
            }
            // If the fixed type has an odd number of decimal digits,
            // then the representation begins with the first (most significant) digit.
            // Otherwise, this first half-octet is all zero, and the first digit
            // is in the second half-octet.
            if (numDigits % 2 == 0) {
                doubleDigit |= digit;
                this.write_octet(doubleDigit);
                doubleDigit = 0;
            } else {
                doubleDigit |= (digit << 4);
            }
            numDigits--;
        }
        // The sign configuration, in the last half-octet of the representation,
        // is 0xD for negative numbers and 0xC for positive and zero values
        if (signum == -1) {
            doubleDigit |= 0xd;
        } else {
            doubleDigit |= 0xc;
        }
        this.write_octet(doubleDigit);
    
public final voidwrite_float(float x)

	write_long(Float.floatToIntBits(x));
    
public final voidwrite_float_array(float[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(computeAlignment(4) + (length * 4));

        for (int i = 0; i < length; i++)
            write_float(value[offset + i]);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
public voidwrite_long(int x)

        alignAndReserve(4, 4);

    	if (littleEndian) {
    	    writeLittleEndianLong(x);
    	} else {
    	    writeBigEndianLong(x);
    	}
    
public final voidwrite_long_array(int[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(computeAlignment(4) + (length * 4));

        for (int i = 0; i < length; i++)
            write_long(value[offset + i]);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
public final voidwrite_longdouble(double x)

	throw wrapper.longDoubleNotImplemented(
	    CompletionStatus.COMPLETED_MAYBE ) ;
    
public voidwrite_longlong(long x)

    	alignAndReserve(8, 8);

    	if (littleEndian) {
    	    writeLittleEndianLongLong(x);
    	} else {
    	    writeBigEndianLongLong(x);
    	}
    
public final voidwrite_longlong_array(long[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(computeAlignment(8) + (length * 8));

        for (int i = 0; i < length; i++)
            write_longlong(value[offset + i]);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
public voidwrite_octet(byte x)

        // The 'if' stmt is commented out since we need the alignAndReserve to
        // be called, particularly when the first body byte is written,
        // to induce header padding to align the body on a 8-octet boundary,
	// for GIOP versions 1.2 and above. Refer to internalWriteOctetArray()
	// method that also has a similar change.
        //if (bbwi.position() + 1 > bbwi.buflen)
            alignAndReserve(1, 1);

//      REVISIT - Should just use ByteBuffer.put(byte) and let it
//                increment the ByteBuffer position. This is true
//                for all write operations in this file.

        bbwi.byteBuffer.put(bbwi.position(), x);
        bbwi.position(bbwi.position() + 1);
         
    
public final voidwrite_octet_array(byte[] b, int offset, int length)

        if ( b == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(length);

        internalWriteOctetArray(b, offset, length);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
private final voidwrite_repositoryId(java.lang.String id)

        // Use an indirection if available
        if (repositoryIdCache != null && repositoryIdCache.containsKey(id)) {
            writeIndirection(INDIRECTION_TAG, repositoryIdCache.getVal(id));
	    return;
        }

        // Write it as a string.  Note that we have already done the
        // special case conversion of non-Latin-1 characters to escaped
        // Latin-1 sequences in RepositoryId.

        // It's not a good idea to cache them now that we can have
        // multiple code sets.
        int indirection = writeString(id);

        // Add indirection for id to indirection table
        if (repositoryIdCache == null)
	repositoryIdCache = new CacheTable(orb,true);
        repositoryIdCache.put(id, indirection);
    
public voidwrite_short(short x)

    	alignAndReserve(2, 2);
    	
    	if (littleEndian) {
    	    writeLittleEndianShort(x);
    	} else {
    	    writeBigEndianShort(x);
    	}
    
public final voidwrite_short_array(short[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(computeAlignment(2) + (length * 2));

        for (int i = 0; i < length; i++)
            write_short(value[offset + i]);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
public voidwrite_string(java.lang.String value)

      writeString(value);
    
public voidwrite_string_array(java.lang.String[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
	    
    	for(int i = 0; i < length; i++)
    	    write_string(value[offset + i]);
    
public final voidwrite_ulong(int x)

	write_long(x);
    
public final voidwrite_ulong_array(int[] value, int offset, int length)

    	write_long_array(value, offset, length);
    
public final voidwrite_ulonglong(long x)

	write_longlong(x);
    
public final voidwrite_ulonglong_array(long[] value, int offset, int length)

    	write_longlong_array(value, offset, length);
    
public final voidwrite_ushort(short x)

	write_short(x);
    
public final voidwrite_ushort_array(short[] value, int offset, int length)

    	write_short_array(value, offset, length);
    
public voidwrite_value(java.io.Serializable object, java.lang.Class clz)


	write_value(object); 
    
public voidwrite_value(java.io.Serializable object, java.lang.String repository_id)


	// Handle null references
	if (object == null) {
	    // Write null tag and return
	    write_long(0);
	    return;
	}

	// Handle shared references
	if (valueCache != null && valueCache.containsKey(object)) {
            writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
	    return;
	} 
		
	Class clazz = object.getClass();
	boolean oldMustChunk = mustChunk;

        if (mustChunk)
            mustChunk = true;

	if (inBlock)
	    end_block();

	if (clazz.isArray()) {
            // Handle arrays
            writeArray(object, clazz);
	} else if (object instanceof org.omg.CORBA.portable.ValueBase) {
            // Handle IDL Value types
            writeValueBase((org.omg.CORBA.portable.ValueBase)object, clazz);
	} else if (shouldWriteAsIDLEntity(object)) {
            writeIDLEntity((IDLEntity)object);
	} else if (object instanceof java.lang.String) {
            writeWStringValue((String)object);
	} else if (object instanceof java.lang.Class) {
            writeClass(repository_id, (Class)object);
	} else {
            // RMI-IIOP value type
            writeRMIIIOPValueType(object, clazz);
        }
		
	mustChunk = oldMustChunk;

	// Check to see if we need to start another block for a
	// possible outer value
	if (mustChunk)
	    start_block();

    
public voidwrite_value(java.io.Serializable object)

        write_value(object, (String)null);
    
public voidwrite_value(java.io.Serializable object, org.omg.CORBA.portable.BoxedValueHelper factory)

        // Handle null references
        if (object == null) {
            // Write null tag and return
            write_long(0);
            return;
        }
        
        // Handle shared references
	if ((valueCache != null) && valueCache.containsKey(object)) {
            writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
	    return;
	} 

	boolean oldMustChunk = mustChunk;

	boolean isCustom = false;
	if (factory instanceof ValueHelper) {
	    short modifier;
	    try {
		modifier = ((ValueHelper)factory).get_type().type_modifier();
	    } catch(BadKind ex) {  // tk_value_box
		modifier = VM_NONE.value;
	    }  
	    if (object instanceof CustomMarshal &&
	        modifier == VM_CUSTOM.value) {
		isCustom = true;
		mustChunk = true;
	    }
	    if (modifier == VM_TRUNCATABLE.value)
		mustChunk = true;
	}

	if (mustChunk) {
			
	    if (inBlock)
		end_block();

	    // Write value_tag
	    int indirection = writeValueTag(true,
					    orb.getORBData().useRepId(),
					    Util.getCodebase(object.getClass())
					   );
			
	    if (orb.getORBData().useRepId()) {
		write_repositoryId(factory.get_id());
	    }
			
	    // Add indirection for object to indirection table
	    updateIndirectionTable(indirection, object, object);
			
	    // Write Value chunk
	    start_block();
	    end_flag--;
            chunkedValueNestingLevel--;
	    if (isCustom)
		((CustomMarshal)object).marshal(parent);
	    else 
		factory.write_value(parent, object);
	    end_block();
			
	    // Write end tag
	    writeEndTag(true);
	}
	else {
	    // Write value_tag
	    int indirection = writeValueTag(false,
					    orb.getORBData().useRepId(),
					    Util.getCodebase(object.getClass())
					   );
			
	    if (orb.getORBData().useRepId()) {
		write_repositoryId(factory.get_id());
	    }
			
	    // Add indirection for object to indirection table
	    updateIndirectionTable(indirection, object, object);
			
	    // Write Value chunk
	    end_flag--;
	    // no need to test for custom on the non-chunked path
	    factory.write_value(parent, object);
			
	    // Write end tag
	    writeEndTag(false);
	}

	mustChunk = oldMustChunk;

	// Check to see if we need to start another block for a
	// possible outer value
	if (mustChunk)
	    start_block();

    
public voidwrite_wchar(char x)

        // Don't allow transmission of wchar/wstring data with
        // foreign ORBs since it's against the spec.
        if (ORBUtility.isForeignORB(orb)) {
	    throw wrapper.wcharDataInGiop10(CompletionStatus.COMPLETED_MAYBE);
        }

        // If it's one of our legacy ORBs, do what they did:
    	alignAndReserve(2, 2);
	
    	if (littleEndian) {
    	    writeLittleEndianWchar(x);
    	} else {
    	    writeBigEndianWchar(x);
    	}
    
public voidwrite_wchar_array(char[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(computeAlignment(2) + (length * 2));

        for (int i = 0; i < length; i++)
            write_wchar(value[offset + i]);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
public voidwrite_wstring(java.lang.String value)

        if (value == null)
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);

        // Don't allow transmission of wchar/wstring data with
        // foreign ORBs since it's against the spec.
        if (ORBUtility.isForeignORB(orb)) {
	    throw wrapper.wcharDataInGiop10(CompletionStatus.COMPLETED_MAYBE);
        }
            
        // When talking to our legacy ORBs, do what they did:
    	int len = value.length() + 1;

        // This will only have an effect if we're already chunking
        handleSpecialChunkBegin(4 + (len * 2) + computeAlignment(4));

        write_long(len);

        for (int i = 0; i < len - 1; i++)
            write_wchar(value.charAt(i));

        // Write the null ending
        write_short((short)0);

        // This will only have an effect if we're already chunking
        handleSpecialChunkEnd();
    
public voidwrite_wstring_array(java.lang.String[] value, int offset, int length)

        if ( value == null )
	    throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
	    
    	for(int i = 0; i < length; i++)
    	    write_wstring(value[offset + i]);