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