- /*
- * @(#)CDREncapsCodec.java 1.19 03/12/19
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- 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 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 = new EncapsOutputStream(
- (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 = new EncapsInputStream( 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;
- }
- }