Frames | No Frames |
1: /* CdrEncapsCodecImpl.java -- 2: Copyright (C) 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.CORBA; 40: 41: import gnu.CORBA.CDR.BufferredCdrInput; 42: import gnu.CORBA.CDR.BufferedCdrOutput; 43: import gnu.CORBA.CDR.AbstractCdrOutput; 44: 45: import org.omg.CORBA.Any; 46: import org.omg.CORBA.LocalObject; 47: import org.omg.CORBA.MARSHAL; 48: import org.omg.CORBA.ORB; 49: import org.omg.CORBA.TCKind; 50: import org.omg.CORBA.TypeCode; 51: import org.omg.CORBA.UserException; 52: import org.omg.IOP.Codec; 53: import org.omg.IOP.CodecPackage.FormatMismatch; 54: import org.omg.IOP.CodecPackage.InvalidTypeForEncoding; 55: import org.omg.IOP.CodecPackage.TypeMismatch; 56: 57: /** 58: * The local {@link Codec} implementation for ENCODING_CDR_ENCAPS 59: * encoding. This is a local implementation; the remote side should 60: * have its own Codec of this kind. 61: * 62: * 63: * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) 64: */ 65: public class CdrEncapsCodecImpl 66: extends LocalObject 67: implements Codec 68: { 69: /** 70: * Use serialVersionUID for interoperability. 71: */ 72: private static final long serialVersionUID = 1; 73: 74: /** 75: * If set to true, no wide string or wide character is allowed (GIOP 1.0). 76: */ 77: private final boolean noWide; 78: 79: /** 80: * The version of this encoding. 81: */ 82: private final Version version; 83: 84: /** 85: * The associated ORB. 86: */ 87: protected final ORB orb; 88: 89: /** 90: * If true, this Codec writes the record length (as int) in the beginning 91: * of the record. This indicator is part of the formal OMG standard, but it is 92: * missing in Sun's implementation. Both Suns's and this Codec detects 93: * the indicator, if present, but can also decode data where this information 94: * is missing. If the length indicator is missing, the first four bytes in 95: * Suns encoding are equal to 0 (Big Endian marker). 96: */ 97: private boolean lengthIndicator = true; 98: 99: /** 100: * Create an instance of this Codec, encoding following the given version. 101: */ 102: public CdrEncapsCodecImpl(ORB _orb, Version _version) 103: { 104: orb = _orb; 105: version = _version; 106: noWide = version.until_inclusive(1, 0); 107: } 108: 109: /** 110: * Return the array of repository ids for this object. 111: * 112: * @return { "IDL:gnu/CORBA/cdrEnapsCodec:1.0" }, always. 113: */ 114: public String[] _ids() 115: { 116: return new String[] { "IDL:gnu/CORBA/cdrEnapsCodec:1.0" }; 117: } 118: 119: /** 120: * Decode the contents of the byte array into Any. 121: * The byte array may have the optional four byte length indicator 122: * in the beginning. If these four bytes are zero, it is assumed, 123: * that no length indicator is present. 124: */ 125: public Any decode(byte[] them) 126: throws FormatMismatch 127: { 128: BufferredCdrInput input = createInput(them); 129: BufferredCdrInput encapsulation = createEncapsulation(them, input); 130: 131: TypeCode type = encapsulation.read_TypeCode(); 132: 133: try 134: { 135: checkTypePossibility("", type); 136: } 137: catch (InvalidTypeForEncoding ex) 138: { 139: throw new FormatMismatch(ex.getMessage()); 140: } 141: 142: return readAny(type, encapsulation); 143: } 144: 145: private BufferredCdrInput createEncapsulation(byte[] them, BufferredCdrInput input) 146: { 147: BufferredCdrInput encapsulation; 148: 149: if ((them [ 0 ] | them [ 1 ] | them [ 2 ] | them [ 3 ]) == 0) 150: { 151: // Skip that appears to be the always present Big Endian marker. 152: encapsulation = input; 153: input.read_short(); 154: } 155: else 156: encapsulation = input.read_encapsulation(); 157: return encapsulation; 158: } 159: 160: /** {@inheritDoc} */ 161: public byte[] encode(Any that) 162: throws InvalidTypeForEncoding 163: { 164: checkTypePossibility("", that.type()); 165: 166: BufferedCdrOutput output = createOutput(that); 167: 168: // BufferedCdrOutput has internal support for this encoding. 169: AbstractCdrOutput encapsulation = output.createEncapsulation(); 170: 171: try 172: { 173: TypeCodeHelper.write(encapsulation, that.type()); 174: that.write_value(encapsulation); 175: 176: encapsulation.close(); 177: output.close(); 178: } 179: catch (Exception ex) 180: { 181: MARSHAL m = new MARSHAL(); 182: m.minor = Minor.Encapsulation; 183: m.initCause(ex); 184: throw m; 185: } 186: return output.buffer.toByteArray(); 187: } 188: 189: /** 190: * Decode the value, stored in the byte array, into Any, assuming, 191: * that the byte array holds the data structure, defined by the 192: * given typecode. 193: * 194: * The byte array may have the optional four byte length indicator 195: * in the beginning. If these four bytes are zero, it is assumed, 196: * that no length indicator is present. 197: */ 198: public Any decode_value(byte[] them, TypeCode type) 199: throws FormatMismatch, TypeMismatch 200: { 201: try 202: { 203: checkTypePossibility("", type); 204: } 205: catch (InvalidTypeForEncoding ex) 206: { 207: throw new TypeMismatch(ex.getMessage()); 208: } 209: 210: BufferredCdrInput input = createInput(them); 211: BufferredCdrInput encapsulation = createEncapsulation(them, input); 212: return readAny(type, encapsulation); 213: } 214: 215: /** 216: * Read an Any from the given stream. 217: * 218: * @param type a type of the Any to read. 219: * @param input the encapsulation stream. 220: */ 221: private Any readAny(TypeCode type, BufferredCdrInput encapsulation) 222: throws MARSHAL 223: { 224: gnuAny a = new gnuAny(); 225: a.setOrb(orb); 226: 227: // BufferredCdrInput has internal support for this encoding. 228: a.read_value(encapsulation, type); 229: return a; 230: } 231: 232: /** {@inheritDoc} */ 233: public byte[] encode_value(Any that) 234: throws InvalidTypeForEncoding 235: { 236: checkTypePossibility("", that.type()); 237: 238: BufferedCdrOutput output = createOutput(that); 239: 240: AbstractCdrOutput encapsulation = output.createEncapsulation(); 241: 242: try 243: { 244: that.write_value(encapsulation); 245: 246: encapsulation.close(); 247: output.close(); 248: } 249: catch (Exception ex) 250: { 251: MARSHAL m = new MARSHAL(); 252: m.minor = Minor.Encapsulation; 253: m.initCause(ex); 254: throw m; 255: } 256: return output.buffer.toByteArray(); 257: } 258: 259: /** 260: * Create the CDR output stream for writing the given Any. 261: * The BufferedCdrOutput has internal support for encapsulation encodings. 262: * 263: * @param that the Any that will be written. 264: * 265: * @return the stream. 266: * 267: * @throws InvalidTypeForEncoding if that Any cannot be written under the 268: * given version. 269: */ 270: private BufferedCdrOutput createOutput(Any that) 271: throws InvalidTypeForEncoding 272: { 273: BufferedCdrOutput output = new BufferedCdrOutput(); 274: output.setOrb(orb); 275: output.setVersion(version); 276: return output; 277: } 278: 279: /** 280: * Checks if the given type can be encoded. Currently only checks for wide 281: * strings and wide chars for GIOP 1.0. 282: * 283: * @param t a typecode to chek. 284: * 285: * @throws InvalidTypeForEncoding if the typecode is not valid for the given 286: * version. 287: */ 288: private void checkTypePossibility(String name, TypeCode t) 289: throws InvalidTypeForEncoding 290: { 291: if (noWide) 292: { 293: try 294: { 295: int kind = t.kind().value(); 296: 297: if (kind == TCKind._tk_wchar || kind == TCKind._tk_wstring) 298: throw new InvalidTypeForEncoding(name + " wide char in " + 299: version 300: ); 301: else if (kind == TCKind._tk_alias || kind == TCKind._tk_array || 302: kind == TCKind._tk_sequence 303: ) 304: checkTypePossibility("Array member", t.content_type()); 305: 306: else if (kind == TCKind._tk_struct || kind == TCKind._tk_union) 307: { 308: for (int i = 0; i < t.member_count(); i++) 309: { 310: checkTypePossibility(t.member_name(i), t.member_type(i)); 311: } 312: } 313: } 314: catch (UserException ex) 315: { 316: InternalError ierr = new InternalError(); 317: ierr.initCause(ex); 318: throw ierr; 319: } 320: } 321: } 322: 323: /** 324: * Create the CDR input stream for reading the given byte array. 325: * 326: * @param them a byte array to read. 327: * 328: * @return the stream. 329: */ 330: private BufferredCdrInput createInput(byte[] them) 331: { 332: BufferredCdrInput input = new BufferredCdrInput(them); 333: input.setOrb(orb); 334: input.setVersion(version); 335: return input; 336: } 337: 338: /** 339: * Check if the Codec writes the length indicator. 340: */ 341: public boolean hasLengthIndicator() 342: { 343: return lengthIndicator; 344: } 345: 346: /** 347: * Sets if the Codec must write the record length in the beginning of the 348: * array. Encodings both with and without that indicator are understood 349: * both by Suns and this codec, but the OMG specification seems requiring 350: * it. The default behavior is to use the length indicator. 351: * 352: * @param use_lengthIndicator 353: */ 354: public void setUseLengthIndicator(boolean use_lengthIndicator) 355: { 356: lengthIndicator = use_lengthIndicator; 357: } 358: }