alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (CDROutputStream_1_2.java)

This example Java source code file (CDROutputStream_1_2.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

cdroutputstream_1_1, cdroutputstream_1_2, corba, giopversion

The CDROutputStream_1_2.java Java example source code

/*
 * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.corba.se.impl.encoding;

import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.CompletionStatus;
import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
import com.sun.corba.se.impl.encoding.CodeSetConversion;
import com.sun.corba.se.impl.orbutil.ORBConstants;

public class CDROutputStream_1_2 extends CDROutputStream_1_1
{
    // There's a situation with chunking with fragmentation
    // in which the alignment for a primitive value is needed
    // to fill fragment N, but the primitive won't fit so
    // must go into fragment N + 1.  The behavior is the same
    // as that for specialChunks.
    //
    // Unfortunately, given the current code, we can't reuse
    // specialChunk.  If you wrap each of the following
    // write calls with handleSpecialChunkBegin/End, you
    // will lose your state because the primitive calls will
    // change the variables, etc.
    //
    // All of the CDR code should be rewritten moving chunking
    // to a different level, perhaps in the buffer managers.
    // We want to move to a compositional model rather than
    // using inheritance.
    //
    // Note that in the grow case, chunks are _NOT_ closed
    // at grow points, now.
    //
    // **** NOTE ****
    // Since we will not support valuetypes with GIOP 1.1, that
    // also means we do not support chunking there.
    //
    protected boolean primitiveAcrossFragmentedChunk = false;

    // Used in chunking.  Here's how this works:
    //
    // When chunking and writing an array of primitives, a string, or a
    // wstring, _AND_ it won't fit in the buffer do the following.  (As
    // you can see, this is a very "special" chunk.)
    //
    //     1.  Write the length of the chunk including the array length
    //     2.  Set specialChunk to true
    // 3 applies to ALL chunking:
    //     3.  In grow, if we need to fragment and specialChunk is false
    //               a) call end_block
    //               b) fragment
    // Now back to the array only case:
    //     [write the data]
    //     4.  if specialChunk is true
    //               a) Close the chunk
    //               b) Set specialChunk to false

    protected boolean specialChunk = false;

    // Indicates whether the header should be padded. In GIOP 1.2 and above, the
    // body must be aligned on a 8-octet boundary, and so the header needs to be
    // padded appropriately. However, if there is no body to a request or reply
    // message, there is no need to pad the header, in the unfragmented case.
    private boolean headerPadding;

    protected void handleSpecialChunkBegin(int requiredSize)
    {
        // If we're chunking and the item won't fit in the buffer
        if (inBlock && requiredSize + bbwi.position() > bbwi.buflen) {

            // Duplicating some code from end_block.  Compute
            // and write the total chunk length.

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

            //write_long(oldSize - blockSizeIndex);
            writeLongWithoutAlign((oldSize - blockSizeIndex) + requiredSize);
            bbwi.position(oldSize);

            // Set the special flag so we don't end the chunk when
            // we fragment
            specialChunk = true;
        }
    }

    protected void handleSpecialChunkEnd()
    {
        // If we're in a chunk and the item spanned fragments
        if (inBlock && specialChunk) {

            // This is unnecessary, but I just want to show that
            // we're done with the current chunk.  (the end_block
            // call is inappropriate here)
            inBlock = false;
            blockSizeIndex = -1;
            blockSizePosition = -1;

            // Start a new chunk since we fragmented during the item.
            // Thus, no one can go back to add more to the chunk length
            start_block();

            // Now turn off the flag so we go back to the normal
            // behavior of closing a chunk when we fragment and
            // reopening afterwards.
            specialChunk = false;
        }
    }

    // Called after writing primitives
    private void checkPrimitiveAcrossFragmentedChunk()
    {
        if (primitiveAcrossFragmentedChunk) {
            primitiveAcrossFragmentedChunk = false;

            inBlock = false;

            // It would be nice to have a StreamPosition
            // abstraction if we could avoid allocation
            // overhead.
            blockSizeIndex = -1;
            blockSizePosition = -1;

            // Start a new chunk
            start_block();
        }
    }


    public void write_octet(byte x) {
        super.write_octet(x);
        checkPrimitiveAcrossFragmentedChunk();
    }

    public void write_short(short x) {
        super.write_short(x);
        checkPrimitiveAcrossFragmentedChunk();
    }

    public void write_long(int x) {
        super.write_long(x);
        checkPrimitiveAcrossFragmentedChunk();
    }

    public void write_longlong(long x) {
        super.write_longlong(x);
        checkPrimitiveAcrossFragmentedChunk();
    }

    // Called by RequestMessage_1_2 or ReplyMessage_1_2 classes only.
    void setHeaderPadding(boolean headerPadding) {
        this.headerPadding = headerPadding;
    }

    protected void alignAndReserve(int align, int n) {

        // headerPadding bit is set by the write operation of RequestMessage_1_2
        // or ReplyMessage_1_2 classes. When set, the very first body write
        // operation (from the stub code) would trigger an alignAndReserve
        // method call, that would in turn add the appropriate header padding,
        // such that the body is aligned on a 8-octet boundary. The padding
        // is required for GIOP versions 1.2 and above, only if body is present.
        if (headerPadding == true) {
            headerPadding = false;
            alignOnBoundary(ORBConstants.GIOP_12_MSG_BODY_ALIGNMENT);
        }

        // In GIOP 1.2, we always end fragments at our
        // fragment size, which is an "evenly divisible
        // 8 byte boundary" (aka divisible by 16).  A fragment can
        // end with appropriate alignment padding, but no padding
        // is needed with respect to the next GIOP fragment
        // header since it ends on an 8 byte boundary.

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

        if (bbwi.position() + n  > bbwi.buflen)
            grow(align, n);
    }

    protected void grow(int align, int n) {

        // Save the current size for possible post-fragmentation calculation
        int oldSize = bbwi.position();

        // See notes where specialChunk is defined, as well as the
        // above notes for primitiveAcrossFragmentedChunk.
        //
        // If we're writing a primitive and chunking, we need to update
        // the chunk length to include the length of the primitive (unless
        // this complexity is handled by specialChunk).
        //
        // Note that this is wasted processing in the grow case, but that
        // we don't actually close the chunk in that case.
        boolean handleChunk = (inBlock && !specialChunk);
        if (handleChunk) {
            int oldIndex = bbwi.position();

            bbwi.position(blockSizeIndex - 4);

            writeLongWithoutAlign((oldIndex - blockSizeIndex) + n);

            bbwi.position(oldIndex);
        }

        bbwi.needed = n;
        bufferManagerWrite.overflow(bbwi);

        // At this point, if we fragmented, we should have a ByteBufferWithInfo
        // with the fragment header already marshalled.  The buflen and position
        // should be updated accordingly, and the fragmented flag should be set.

        // Note that fragmented is only true in the streaming and collect cases.
        if (bbwi.fragmented) {

            // Clear the flag
            bbwi.fragmented = false;

            // Update fragmentOffset so indirections work properly.
            // At this point, oldSize is the entire length of the
            // previous buffer.  bbwi.position() is the length of the
            // fragment header of this buffer.
            fragmentOffset += (oldSize - bbwi.position());

            // We just fragmented, and need to signal that we should
            // start a new chunk after writing the primitive.
            if (handleChunk)
                primitiveAcrossFragmentedChunk = true;

        }
    }

    public GIOPVersion getGIOPVersion() {
        return GIOPVersion.V1_2;
    }

    public void write_wchar(char x)
    {
        // In GIOP 1.2, a wchar is encoded as an unsigned octet length
        // followed by the octets of the converted wchar.  This is good,
        // but it causes problems with our chunking code.  We don't
        // want that octet to get put in a different chunk at the end
        // of the previous fragment.
        //
        // Ensure that this won't happen by overriding write_wchar_array
        // and doing our own handleSpecialChunkBegin/End here.
        CodeSetConversion.CTBConverter converter = getWCharConverter();

        converter.convert(x);

        handleSpecialChunkBegin(1 + converter.getNumBytes());

        write_octet((byte)converter.getNumBytes());

        byte[] result = converter.getBytes();

        // Write the bytes without messing with chunking
        // See CDROutputStream_1_0
        internalWriteOctetArray(result, 0, converter.getNumBytes());

        handleSpecialChunkEnd();
    }

    public void write_wchar_array(char[] value, int offset, int length)
    {
        if (value == null) {
            throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
        }

        CodeSetConversion.CTBConverter converter = getWCharConverter();

        // Unfortunately, because of chunking, we have to convert the
        // entire char[] to a byte[] array first so we can know how
        // many bytes we're writing ahead of time.  You can't split
        // an array of primitives into multiple chunks.
        int totalNumBytes = 0;

        // Remember that every wchar starts with an octet telling
        // its length.  The buffer size is an upper bound estimate.
        int maxLength = (int)Math.ceil(converter.getMaxBytesPerChar() * length);
        byte[] buffer = new byte[maxLength + length];

        for (int i = 0; i < length; i++) {
            // Convert one wchar
            converter.convert(value[offset + i]);

            // Make sure to add the octet length
            buffer[totalNumBytes++] = (byte)converter.getNumBytes();

            // Copy it into our buffer
            System.arraycopy(converter.getBytes(), 0,
                             buffer, totalNumBytes,
                             converter.getNumBytes());

            totalNumBytes += converter.getNumBytes();
        }

        // Now that we know the total length, we can deal with chunking.
        // Note that we don't have to worry about alignment since they're
        // just octets.
        handleSpecialChunkBegin(totalNumBytes);

        // Must use totalNumBytes rather than buffer.length since the
        // buffer.length is only the upper bound estimate.
        internalWriteOctetArray(buffer, 0, totalNumBytes);

        handleSpecialChunkEnd();
    }

    public void write_wstring(String value) {
        if (value == null) {
            throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
        }

        // In GIOP 1.2, wstrings are not terminated by a null.  The
        // length is the number of octets in the converted format.
        // A zero length string is represented with the 4 byte length
        // value of 0.
        if (value.length() == 0) {
            write_long(0);
            return;
        }

        CodeSetConversion.CTBConverter converter = getWCharConverter();

        converter.convert(value);

        handleSpecialChunkBegin(computeAlignment(4) + 4 + converter.getNumBytes());

        write_long(converter.getNumBytes());

        // Write the octet array without tampering with chunking
        internalWriteOctetArray(converter.getBytes(), 0, converter.getNumBytes());

        handleSpecialChunkEnd();
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java CDROutputStream_1_2.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.