CDREncapsCodec.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.corba.se.impl.interceptors; 27 28import org.omg.CORBA.Any; 29import org.omg.CORBA.ORB; 30import org.omg.CORBA.TypeCode; 31import org.omg.CORBA.LocalObject; 32 33import com.sun.corba.se.spi.ior.iiop.GIOPVersion; 34import com.sun.corba.se.spi.logging.CORBALogDomains; 35 36import sun.corba.EncapsInputStreamFactory; 37 38import com.sun.corba.se.impl.corba.AnyImpl; 39import com.sun.corba.se.impl.encoding.EncapsInputStream; 40import com.sun.corba.se.impl.encoding.EncapsOutputStream; 41import com.sun.corba.se.impl.logging.ORBUtilSystemException; 42 43import org.omg.IOP.Codec; 44import org.omg.IOP.CodecPackage.FormatMismatch; 45import org.omg.IOP.CodecPackage.InvalidTypeForEncoding; 46import org.omg.IOP.CodecPackage.TypeMismatch; 47 48/** 49 * CDREncapsCodec is an implementation of Codec, as described 50 * in orbos/99-12-02, that supports CDR encapsulation version 1.0, 1.1, and 51 * 1.2. 52 */ 53public final class CDREncapsCodec 54 extends org.omg.CORBA.LocalObject 55 implements Codec 56{ 57 // The ORB that created the factory this codec was created from 58 private ORB orb; 59 ORBUtilSystemException wrapper; 60 61 // The GIOP version we are encoding for 62 private GIOPVersion giopVersion; 63 64 /* 65 ******************************************************************* 66 * NOTE: CDREncapsCodec must remain immutable! This is so that we 67 * can pre-create CDREncapsCodecs for each version of GIOP in 68 * CodecFactoryImpl. 69 *******************************************************************/ 70 71 /** 72 * Creates a new codec implementation. Uses the given ORB to create 73 * CDRInputStreams when necessary. 74 * 75 * @param orb The ORB to use to create a CDRInputStream or CDROutputStream 76 * @param major The major version of GIOP we are encoding for 77 * @param minor The minor version of GIOP we are encoding for 78 */ 79 public CDREncapsCodec( ORB orb, int major, int minor ) { 80 this.orb = orb; 81 wrapper = ORBUtilSystemException.get( 82 (com.sun.corba.se.spi.orb.ORB)orb, CORBALogDomains.RPC_PROTOCOL ) ; 83 84 giopVersion = GIOPVersion.getInstance( (byte)major, (byte)minor ); 85 } 86 87 /** 88 * Convert the given any into a CDR encapsulated octet sequence 89 */ 90 public byte[] encode( Any data ) 91 throws InvalidTypeForEncoding 92 { 93 if ( data == null ) 94 throw wrapper.nullParam() ; 95 return encodeImpl( data, true ); 96 } 97 98 /** 99 * Decode the given octet sequence into an any based on a CDR 100 * encapsulated octet sequence. 101 */ 102 public Any decode ( byte[] data ) 103 throws FormatMismatch 104 { 105 if( data == null ) 106 throw wrapper.nullParam() ; 107 return decodeImpl( data, null ); 108 } 109 110 /** 111 * Convert the given any into a CDR encapsulated octet sequence. Only 112 * the data is stored. The type code is not. 113 */ 114 public byte[] encode_value( Any data ) 115 throws InvalidTypeForEncoding 116 { 117 if( data == null ) 118 throw wrapper.nullParam() ; 119 return encodeImpl( data, false ); 120 } 121 122 /** 123 * Decode the given octet sequence into an any based on a CDR 124 * encapsulated octet sequence. The type code is expected not to appear 125 * in the octet sequence, and the given type code is used instead. 126 */ 127 public Any decode_value( byte[] data, TypeCode tc ) 128 throws FormatMismatch, TypeMismatch 129 { 130 if( data == null ) 131 throw wrapper.nullParam() ; 132 if( tc == null ) 133 throw wrapper.nullParam() ; 134 return decodeImpl( data, tc ); 135 } 136 137 /** 138 * Convert the given any into a CDR encapsulated octet sequence. 139 * If sendTypeCode is true, the type code is sent with the message, as in 140 * a standard encapsulation. If it is false, only the data is sent. 141 * Either way, the endian type is sent as the first part of the message. 142 */ 143 private byte[] encodeImpl( Any data, boolean sendTypeCode ) 144 throws InvalidTypeForEncoding 145 { 146 if( data == null ) 147 throw wrapper.nullParam() ; 148 149 // _REVISIT_ Note that InvalidTypeForEncoding is never thrown in 150 // the body of this method. This is due to the fact that CDR*Stream 151 // will never throw an exception if the encoding is invalid. To 152 // fix this, the CDROutputStream must know the version of GIOP it 153 // is encoding for and it must check to ensure that, for example, 154 // wstring cannot be encoded in GIOP 1.0. 155 // 156 // As part of the GIOP 1.2 work, the CDRInput and OutputStream will 157 // be versioned. This can be handled once this work is complete. 158 159 // Create output stream with default endianness. 160 EncapsOutputStream cdrOut = 161 sun.corba.OutputStreamFactory.newEncapsOutputStream( 162 (com.sun.corba.se.spi.orb.ORB)orb, giopVersion ); 163 164 // This is an encapsulation, so put out the endian: 165 cdrOut.putEndian(); 166 167 // Sometimes encode type code: 168 if( sendTypeCode ) { 169 cdrOut.write_TypeCode( data.type() ); 170 } 171 172 // Encode value and return. 173 data.write_value( cdrOut ); 174 175 return cdrOut.toByteArray(); 176 } 177 178 /** 179 * Decode the given octet sequence into an any based on a CDR 180 * encapsulated octet sequence. If the type code is null, it is 181 * expected to appear in the octet sequence. Otherwise, the given 182 * type code is used. 183 */ 184 private Any decodeImpl( byte[] data, TypeCode tc ) 185 throws FormatMismatch 186 { 187 if( data == null ) 188 throw wrapper.nullParam() ; 189 190 AnyImpl any = null; // return value 191 192 // _REVISIT_ Currently there is no way for us to distinguish between 193 // a FormatMismatch and a TypeMismatch because we cannot get this 194 // information from the CDRInputStream. If a RuntimeException occurs, 195 // it is turned into a FormatMismatch exception. 196 197 try { 198 EncapsInputStream cdrIn = EncapsInputStreamFactory.newEncapsInputStream( orb, data, 199 data.length, giopVersion ); 200 201 202 cdrIn.consumeEndian(); 203 204 // If type code not specified, read it from octet stream: 205 if( tc == null ) { 206 tc = cdrIn.read_TypeCode(); 207 } 208 209 // Create a new Any object: 210 any = new AnyImpl( (com.sun.corba.se.spi.orb.ORB)orb ); 211 any.read_value( cdrIn, tc ); 212 } 213 catch( RuntimeException e ) { 214 // See above note. 215 throw new FormatMismatch(); 216 } 217 218 return any; 219 } 220} 221