/*
 * Copyright (c) 2000, 2013, 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.interceptors;

import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.LocalObject;

import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
import com.sun.corba.se.spi.logging.CORBALogDomains;

import sun.corba.EncapsInputStreamFactory;

import com.sun.corba.se.impl.corba.AnyImpl;
import com.sun.corba.se.impl.encoding.EncapsInputStream;
import com.sun.corba.se.impl.encoding.EncapsOutputStream;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;

import org.omg.IOP.Codec;
import org.omg.IOP.CodecPackage.FormatMismatch;
import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
import org.omg.IOP.CodecPackage.TypeMismatch;

/**
 * CDREncapsCodec is an implementation of Codec, as described
 * in orbos/99-12-02, that supports CDR encapsulation version 1.0, 1.1, and
 * 1.2.
 */
public final class CDREncapsCodec
    extends org.omg.CORBA.LocalObject
    implements Codec
{
    // The ORB that created the factory this codec was created from
    private ORB orb;
    ORBUtilSystemException wrapper;

    // The GIOP version we are encoding for
    private GIOPVersion giopVersion;

    /*
     *******************************************************************
     * NOTE: CDREncapsCodec must remain immutable!  This is so that we
     * can pre-create CDREncapsCodecs for each version of GIOP in
     * CodecFactoryImpl.
     *******************************************************************/

    /**
     * Creates a new codec implementation.  Uses the given ORB to create
     * CDRInputStreams when necessary.
     *
     * @param orb The ORB to use to create a CDRInputStream or CDROutputStream
     * @param major The major version of GIOP we are encoding for
     * @param minor The minor version of GIOP we are encoding for
     */
    public CDREncapsCodec( ORB orb, int major, int minor ) {
        this.orb = orb;
        wrapper = ORBUtilSystemException.get(
            (com.sun.corba.se.spi.orb.ORB)orb, CORBALogDomains.RPC_PROTOCOL ) ;

        giopVersion = GIOPVersion.getInstance( (byte)major, (byte)minor );
    }

    /**
     * Convert the given any into a CDR encapsulated octet sequence
     */
    public byte[] encode( Any data )
        throws InvalidTypeForEncoding
    {
        if ( data == null )
            throw wrapper.nullParam() ;
        return encodeImpl( data, true );
    }

    /**
     * Decode the given octet sequence into an any based on a CDR
     * encapsulated octet sequence.
     */
    public Any decode ( byte[] data )
        throws FormatMismatch
    {
        if( data == null )
            throw wrapper.nullParam() ;
        return decodeImpl( data, null );
    }

    /**
     * Convert the given any into a CDR encapsulated octet sequence.  Only
     * the data is stored.  The type code is not.
     */
    public byte[] encode_value( Any data )
        throws InvalidTypeForEncoding
    {
        if( data == null )
            throw wrapper.nullParam() ;
        return encodeImpl( data, false );
    }

    /**
     * Decode the given octet sequence into an any based on a CDR
     * encapsulated octet sequence.  The type code is expected not to appear
     * in the octet sequence, and the given type code is used instead.
     */
    public Any decode_value( byte[] data, TypeCode tc )
        throws FormatMismatch, TypeMismatch
    {
        if( data == null )
            throw wrapper.nullParam() ;
        if( tc == null )
            throw  wrapper.nullParam() ;
        return decodeImpl( data, tc );
    }

    /**
     * Convert the given any into a CDR encapsulated octet sequence.
     * If sendTypeCode is true, the type code is sent with the message, as in
     * a standard encapsulation.  If it is false, only the data is sent.
     * Either way, the endian type is sent as the first part of the message.
     */
    private byte[] encodeImpl( Any data, boolean sendTypeCode )
        throws InvalidTypeForEncoding
    {
        if( data == null )
            throw wrapper.nullParam() ;

        // _REVISIT_ Note that InvalidTypeForEncoding is never thrown in
        // the body of this method.  This is due to the fact that CDR*Stream
        // will never throw an exception if the encoding is invalid.  To
        // fix this, the CDROutputStream must know the version of GIOP it
        // is encoding for and it must check to ensure that, for example,
        // wstring cannot be encoded in GIOP 1.0.
        //
        // As part of the GIOP 1.2 work, the CDRInput and OutputStream will
        // be versioned.  This can be handled once this work is complete.

        // Create output stream with default endianness.
        EncapsOutputStream cdrOut =
            sun.corba.OutputStreamFactory.newEncapsOutputStream(
            (com.sun.corba.se.spi.orb.ORB)orb, giopVersion );

        // This is an encapsulation, so put out the endian:
        cdrOut.putEndian();

        // Sometimes encode type code:
        if( sendTypeCode ) {
            cdrOut.write_TypeCode( data.type() );
        }

        // Encode value and return.
        data.write_value( cdrOut );

        return cdrOut.toByteArray();
    }

    /**
     * Decode the given octet sequence into an any based on a CDR
     * encapsulated octet sequence.  If the type code is null, it is
     * expected to appear in the octet sequence.  Otherwise, the given
     * type code is used.
     */
    private Any decodeImpl( byte[] data, TypeCode tc )
        throws FormatMismatch
    {
        if( data == null )
            throw wrapper.nullParam() ;

        AnyImpl any = null;  // return value

        // _REVISIT_ Currently there is no way for us to distinguish between
        // a FormatMismatch and a TypeMismatch because we cannot get this
        // information from the CDRInputStream.  If a RuntimeException occurs,
        // it is turned into a FormatMismatch exception.

        try {
            EncapsInputStream cdrIn = EncapsInputStreamFactory.newEncapsInputStream( orb, data,
                    data.length, giopVersion );


            cdrIn.consumeEndian();

            // If type code not specified, read it from octet stream:
            if( tc == null ) {
                tc = cdrIn.read_TypeCode();
            }

            // Create a new Any object:
            any = new AnyImpl( (com.sun.corba.se.spi.orb.ORB)orb );
            any.read_value( cdrIn, tc );
        }
        catch( RuntimeException e ) {
            // See above note.
            throw new FormatMismatch();
        }

        return any;
    }
}
