1. /*
  2. * @(#)CDREncapsCodec.java 1.19 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.interceptors;
  8. import org.omg.CORBA.Any;
  9. import org.omg.CORBA.ORB;
  10. import org.omg.CORBA.TypeCode;
  11. import org.omg.CORBA.LocalObject;
  12. import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  13. import com.sun.corba.se.spi.logging.CORBALogDomains;
  14. import com.sun.corba.se.impl.corba.AnyImpl;
  15. import com.sun.corba.se.impl.encoding.EncapsInputStream;
  16. import com.sun.corba.se.impl.encoding.EncapsOutputStream;
  17. import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  18. import org.omg.IOP.Codec;
  19. import org.omg.IOP.CodecPackage.FormatMismatch;
  20. import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
  21. import org.omg.IOP.CodecPackage.TypeMismatch;
  22. /**
  23. * CDREncapsCodec is an implementation of Codec, as described
  24. * in orbos/99-12-02, that supports CDR encapsulation version 1.0, 1.1, and
  25. * 1.2.
  26. */
  27. public final class CDREncapsCodec
  28. extends org.omg.CORBA.LocalObject
  29. implements Codec
  30. {
  31. // The ORB that created the factory this codec was created from
  32. private ORB orb;
  33. ORBUtilSystemException wrapper;
  34. // The GIOP version we are encoding for
  35. private GIOPVersion giopVersion;
  36. /*
  37. *******************************************************************
  38. * NOTE: CDREncapsCodec must remain immutable! This is so that we
  39. * can pre-create CDREncapsCodecs for each version of GIOP in
  40. * CodecFactoryImpl.
  41. *******************************************************************/
  42. /**
  43. * Creates a new codec implementation. Uses the given ORB to create
  44. * CDRInputStreams when necessary.
  45. *
  46. * @param orb The ORB to use to create a CDRInputStream or CDROutputStream
  47. * @param major The major version of GIOP we are encoding for
  48. * @param minor The minor version of GIOP we are encoding for
  49. */
  50. public CDREncapsCodec( ORB orb, int major, int minor ) {
  51. this.orb = orb;
  52. wrapper = ORBUtilSystemException.get(
  53. (com.sun.corba.se.spi.orb.ORB)orb, CORBALogDomains.RPC_PROTOCOL ) ;
  54. giopVersion = GIOPVersion.getInstance( (byte)major, (byte)minor );
  55. }
  56. /**
  57. * Convert the given any into a CDR encapsulated octet sequence
  58. */
  59. public byte[] encode( Any data )
  60. throws InvalidTypeForEncoding
  61. {
  62. if ( data == null )
  63. throw wrapper.nullParam() ;
  64. return encodeImpl( data, true );
  65. }
  66. /**
  67. * Decode the given octet sequence into an any based on a CDR
  68. * encapsulated octet sequence.
  69. */
  70. public Any decode ( byte[] data )
  71. throws FormatMismatch
  72. {
  73. if( data == null )
  74. throw wrapper.nullParam() ;
  75. return decodeImpl( data, null );
  76. }
  77. /**
  78. * Convert the given any into a CDR encapsulated octet sequence. Only
  79. * the data is stored. The type code is not.
  80. */
  81. public byte[] encode_value( Any data )
  82. throws InvalidTypeForEncoding
  83. {
  84. if( data == null )
  85. throw wrapper.nullParam() ;
  86. return encodeImpl( data, false );
  87. }
  88. /**
  89. * Decode the given octet sequence into an any based on a CDR
  90. * encapsulated octet sequence. The type code is expected not to appear
  91. * in the octet sequence, and the given type code is used instead.
  92. */
  93. public Any decode_value( byte[] data, TypeCode tc )
  94. throws FormatMismatch, TypeMismatch
  95. {
  96. if( data == null )
  97. throw wrapper.nullParam() ;
  98. if( tc == null )
  99. throw wrapper.nullParam() ;
  100. return decodeImpl( data, tc );
  101. }
  102. /**
  103. * Convert the given any into a CDR encapsulated octet sequence.
  104. * If sendTypeCode is true, the type code is sent with the message, as in
  105. * a standard encapsulation. If it is false, only the data is sent.
  106. * Either way, the endian type is sent as the first part of the message.
  107. */
  108. private byte[] encodeImpl( Any data, boolean sendTypeCode )
  109. throws InvalidTypeForEncoding
  110. {
  111. if( data == null )
  112. throw wrapper.nullParam() ;
  113. // _REVISIT_ Note that InvalidTypeForEncoding is never thrown in
  114. // the body of this method. This is due to the fact that CDR*Stream
  115. // will never throw an exception if the encoding is invalid. To
  116. // fix this, the CDROutputStream must know the version of GIOP it
  117. // is encoding for and it must check to ensure that, for example,
  118. // wstring cannot be encoded in GIOP 1.0.
  119. //
  120. // As part of the GIOP 1.2 work, the CDRInput and OutputStream will
  121. // be versioned. This can be handled once this work is complete.
  122. // Create output stream with default endianness.
  123. EncapsOutputStream cdrOut = new EncapsOutputStream(
  124. (com.sun.corba.se.spi.orb.ORB)orb, giopVersion );
  125. // This is an encapsulation, so put out the endian:
  126. cdrOut.putEndian();
  127. // Sometimes encode type code:
  128. if( sendTypeCode ) {
  129. cdrOut.write_TypeCode( data.type() );
  130. }
  131. // Encode value and return.
  132. data.write_value( cdrOut );
  133. return cdrOut.toByteArray();
  134. }
  135. /**
  136. * Decode the given octet sequence into an any based on a CDR
  137. * encapsulated octet sequence. If the type code is null, it is
  138. * expected to appear in the octet sequence. Otherwise, the given
  139. * type code is used.
  140. */
  141. private Any decodeImpl( byte[] data, TypeCode tc )
  142. throws FormatMismatch
  143. {
  144. if( data == null )
  145. throw wrapper.nullParam() ;
  146. AnyImpl any = null; // return value
  147. // _REVISIT_ Currently there is no way for us to distinguish between
  148. // a FormatMismatch and a TypeMismatch because we cannot get this
  149. // information from the CDRInputStream. If a RuntimeException occurs,
  150. // it is turned into a FormatMismatch exception.
  151. try {
  152. EncapsInputStream cdrIn = new EncapsInputStream( orb, data,
  153. data.length, giopVersion );
  154. cdrIn.consumeEndian();
  155. // If type code not specified, read it from octet stream:
  156. if( tc == null ) {
  157. tc = cdrIn.read_TypeCode();
  158. }
  159. // Create a new Any object:
  160. any = new AnyImpl( (com.sun.corba.se.spi.orb.ORB)orb );
  161. any.read_value( cdrIn, tc );
  162. }
  163. catch( RuntimeException e ) {
  164. // See above note.
  165. throw new FormatMismatch();
  166. }
  167. return any;
  168. }
  169. }