1 /* AbstractCdrOutput.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.CDR; 40 41 import gnu.CORBA.BigDecimalHelper; 42 import gnu.CORBA.IOR; 43 import gnu.CORBA.IorProvider; 44 import gnu.CORBA.Minor; 45 import gnu.CORBA.TypeCodeHelper; 46 import gnu.CORBA.Unexpected; 47 import gnu.CORBA.Version; 48 import gnu.CORBA.GIOP.CharSets_OSF; 49 import gnu.CORBA.GIOP.CodeSetServiceContext; 50 import gnu.CORBA.typecodes.PrimitiveTypeCode; 51 52 import org.omg.CORBA.Any; 53 import org.omg.CORBA.BAD_OPERATION; 54 import org.omg.CORBA.Context; 55 import org.omg.CORBA.ContextList; 56 import org.omg.CORBA.DataInputStream; 57 import org.omg.CORBA.MARSHAL; 58 import org.omg.CORBA.NO_IMPLEMENT; 59 import org.omg.CORBA.ORB; 60 import org.omg.CORBA.TCKind; 61 import org.omg.CORBA.TypeCode; 62 import org.omg.CORBA.UserException; 63 import org.omg.CORBA.TypeCodePackage.BadKind; 64 import org.omg.CORBA.portable.Delegate; 65 import org.omg.CORBA.portable.ObjectImpl; 66 import org.omg.CORBA.portable.OutputStream; 67 import org.omg.CORBA.portable.Streamable; 68 69 import java.io.IOException; 70 import java.io.OutputStreamWriter; 71 import java.io.Serializable; 72 import java.math.BigDecimal; 73 74 /** 75 * A simple CORBA CDR (common data representation) 76 * output stream, writing data into the 77 * given {@link java.io.OutputStream}. 78 * 79 * The same class also implements the {@link DataInputStream}, 80 * providing support for writing the value type objects 81 * in a user defined way. 82 * 83 * TODO This class uses 16 bits per Unicode character only, as it was until 84 * jdk 1.4 inclusive. 85 * 86 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) 87 */ 88 public abstract class AbstractCdrOutput 89 extends org.omg.CORBA_2_3.portable.OutputStream 90 implements org.omg.CORBA.DataOutputStream 91 { 92 /** 93 * The runtime, associated with this stream. This field is only used when 94 * reading and writing value types and filled-in in gnu.CORBA.CDR.Vio. 95 */ 96 public transient gnuRuntime runtime; 97 98 /** 99 * This instance is used to convert primitive data types into the 100 * byte sequences. 101 */ 102 protected AbstractDataOutput b; 103 104 /** 105 * The associated orb, if any. 106 */ 107 protected ORB orb; 108 109 /** 110 * The GIOP version. 111 */ 112 protected Version giop = new Version(1, 2); 113 114 /** 115 * The code set information. 116 */ 117 protected CodeSetServiceContext codeset; 118 119 /** 120 * The name of the currently used narrow charset. 121 */ 122 private String narrow_charset; 123 124 /** 125 * The name of the currently used wide charset, null if 126 * the native wide charset is used. 127 */ 128 private String wide_charset; 129 130 /** 131 * True if the native code set is used for narrow characters. 132 * If the set is native, no the intermediate Reader object 133 * is instantiated when writing characters. 134 */ 135 private boolean narrow_native; 136 137 /** 138 * True if the native code set is used for wide characters. 139 * If the set is native, no the intermediate Reader object 140 * is instantiated when writing characters. 141 */ 142 private boolean wide_native; 143 144 /** 145 * If true, the Little Endian encoding is used to write the 146 * data. Otherwise, the Big Endian encoding is used. 147 */ 148 private boolean little_endian; 149 150 /** 151 * The stream whre the data are actually written. 152 */ 153 private java.io.OutputStream actual_stream; 154 155 /** 156 * Creates the stream. 157 * 158 * @param writeTo a stream to write CORBA output to. 159 */ AbstractCdrOutput(java.io.OutputStream writeTo)160 public AbstractCdrOutput(java.io.OutputStream writeTo) 161 { 162 setOutputStream(writeTo); 163 setCodeSet(CodeSetServiceContext.STANDARD); 164 } 165 166 /** 167 * Creates the stream, requiring the subsequent call 168 * of {@link #setOutputStream(java.io.OutputStream)}. 169 */ AbstractCdrOutput()170 public AbstractCdrOutput() 171 { 172 setCodeSet(CodeSetServiceContext.STANDARD); 173 } 174 175 /** 176 * Set the alignment offset, if the index of the first byte in the 177 * stream is different from 0. 178 */ setOffset(int an_offset)179 public abstract void setOffset(int an_offset); 180 181 /** 182 * Clone all important settings to another stream. 183 */ cloneSettings(AbstractCdrOutput stream)184 public void cloneSettings(AbstractCdrOutput stream) 185 { 186 stream.setBigEndian(!little_endian); 187 stream.setCodeSet(getCodeSet()); 188 stream.setVersion(giop); 189 stream.setOrb(orb); 190 } 191 192 /** 193 * Set the current code set context. 194 */ setCodeSet(CodeSetServiceContext a_codeset)195 public void setCodeSet(CodeSetServiceContext a_codeset) 196 { 197 this.codeset = a_codeset; 198 narrow_charset = CharSets_OSF.getName(codeset.char_data); 199 wide_charset = CharSets_OSF.getName(codeset.wide_char_data); 200 201 narrow_native = CharSets_OSF.NATIVE_CHARACTER == codeset.char_data; 202 wide_native = CharSets_OSF.NATIVE_WIDE_CHARACTER == codeset.wide_char_data; 203 } 204 205 /** 206 * Get the current code set context. 207 */ getCodeSet()208 public CodeSetServiceContext getCodeSet() 209 { 210 return codeset; 211 } 212 213 /** 214 * Set the orb, associated with this stream. 215 * @param an_orb 216 */ setOrb(ORB an_orb)217 public void setOrb(ORB an_orb) 218 { 219 orb = an_orb; 220 } 221 222 /** 223 * Set the output stream that receives the CORBA output. 224 * 225 * @param writeTo the stream. 226 */ setOutputStream(java.io.OutputStream writeTo)227 public void setOutputStream(java.io.OutputStream writeTo) 228 { 229 if (little_endian) 230 b = new LittleEndianOutputStream(writeTo); 231 else 232 b = new BigEndianOutputStream(writeTo); 233 234 actual_stream = writeTo; 235 } 236 237 /** 238 * Set the GIOP version. Some data types are written differently 239 * for the different versions. The default version is 1.0 . 240 */ setVersion(Version giop_version)241 public void setVersion(Version giop_version) 242 { 243 giop = giop_version; 244 } 245 246 /** 247 * Specify if the stream should use the Big Endian (usual for java) 248 * or Little Encoding. The default is Big Endian. 249 * 250 * @param use_big_endian if true, use Big Endian, if false, 251 * use Little Endian. 252 */ setBigEndian(boolean use_big_endian)253 public void setBigEndian(boolean use_big_endian) 254 { 255 little_endian = !use_big_endian; 256 setOutputStream(actual_stream); 257 } 258 259 /** 260 * Align the curretn position at the given natural boundary. 261 */ align(int boundary)262 public abstract void align(int boundary); 263 264 /** 265 * Create the encapsulation stream, associated with the current 266 * stream. The encapsulated stream must be closed. When being 267 * closed, the encapsulation stream writes its buffer into 268 * this stream using the CORBA CDR encapsulation rules. 269 * 270 * It is not allowed to write to the current stream directly 271 * before the encapsulation stream is closed. 272 * 273 * The encoding (Big/Little Endian) inside the encapsulated 274 * sequence is the same as used into the parent stream. 275 * 276 * @return the encapsulated stream. 277 */ createEncapsulation()278 public AbstractCdrOutput createEncapsulation() 279 { 280 return new EncapsulationStream(this, !little_endian); 281 } 282 283 /** 284 * Return the associated {@link ORB}. 285 * @return the associated {@link ORB} or null is no such is set. 286 */ orb()287 public ORB orb() 288 { 289 return orb; 290 } 291 292 /** 293 * Write a single byte. 294 * @param n byte to write (low 8 bits are written). 295 */ write(int n)296 public void write(int n) 297 { 298 try 299 { 300 b.write(n); 301 } 302 catch (IOException ex) 303 { 304 Unexpected.error(ex); 305 } 306 } 307 308 /** 309 * Write bytes directly into the underlying stream. 310 */ write(byte[] x)311 public void write(byte[] x) 312 throws java.io.IOException 313 { 314 b.write(x); 315 } 316 317 /** 318 * Write bytes directly into the underlying stream. 319 */ write(byte[] x, int ofs, int len)320 public void write(byte[] x, int ofs, int len) 321 throws java.io.IOException 322 { 323 b.write(x, ofs, len); 324 } 325 326 /** 327 * Following the specification, this is not implemented. 328 * Override to get the functionality. 329 */ write_Context(Context context, ContextList contexts)330 public void write_Context(Context context, ContextList contexts) 331 { 332 throw new NO_IMPLEMENT(); 333 } 334 335 /** 336 * Read the CORBA object. The object is written form of the plain (not a 337 * string-encoded) IOR profile without the heading endian indicator. The 338 * responsible method for reading such data is {@link IOR.write_no_endian}. 339 * 340 * The null value is written as defined in OMG specification (zero length 341 * string, followed by an empty set of profiles). 342 */ write_Object(org.omg.CORBA.Object x)343 public void write_Object(org.omg.CORBA.Object x) 344 { 345 ORB w_orb = orb; 346 if (x instanceof IorProvider) 347 { 348 ((IorProvider) x).getIor()._write_no_endian(this); 349 return; 350 } 351 else if (x == null) 352 { 353 IOR.write_null(this); 354 return; 355 } 356 else if (x instanceof ObjectImpl) 357 { 358 Delegate d = ((ObjectImpl) x)._get_delegate(); 359 360 if (d instanceof IorProvider) 361 { 362 ((IorProvider) d).getIor()._write_no_endian(this); 363 return; 364 } 365 else 366 { 367 ORB d_orb = d.orb(x); 368 if (d_orb != null) 369 w_orb = d_orb; 370 } 371 } 372 373 // Either this is not an ObjectImpl or it has the 374 // unexpected delegate. Try to convert via ORBs 375 // object_to_string(). 376 if (w_orb != null) 377 { 378 IOR ior = IOR.parse(w_orb.object_to_string(x)); 379 ior._write_no_endian(this); 380 return; 381 } 382 else 383 throw new BAD_OPERATION( 384 "Please set the ORB for this stream, cannot write " 385 + x.getClass().getName()); 386 } 387 388 /** 389 * Write the TypeCode. This implementation delegates functionality 390 * to {@link cdrTypeCode}. 391 * 392 * @param x a TypeCode to write. 393 */ write_TypeCode(TypeCode x)394 public void write_TypeCode(TypeCode x) 395 { 396 try 397 { 398 TypeCodeHelper.write(this, x); 399 } 400 catch (UserException ex) 401 { 402 Unexpected.error(ex); 403 } 404 } 405 406 /** 407 * Writes an instance of the CORBA {@link Any}. 408 * This method writes the typecode, followed 409 * by value itself. In Any contains null 410 * (value not set), the {@link TCKind#tk_null} 411 * is written. 412 * 413 * @param x the {@link Any} to write. 414 */ write_any(Any x)415 public void write_any(Any x) 416 { 417 Streamable value = x.extract_Streamable(); 418 if (value != null) 419 { 420 write_TypeCode(x.type()); 421 value._write(this); 422 } 423 else 424 { 425 PrimitiveTypeCode p = new PrimitiveTypeCode(TCKind.tk_null); 426 write_TypeCode(p); 427 } 428 } 429 430 /** 431 * Writes a single byte, 0 for <code>false</code>, 432 * 1 for <code>true</code>. 433 * 434 * @param x the value to write 435 */ write_boolean(boolean x)436 public void write_boolean(boolean x) 437 { 438 try 439 { 440 b.write(x ? 1 : 0); 441 } 442 catch (IOException ex) 443 { 444 Unexpected.error(ex); 445 } 446 } 447 448 /** 449 * Writes the boolean array. 450 * 451 * @param x array 452 * @param ofs offset 453 * @param len length. 454 */ write_boolean_array(boolean[] x, int ofs, int len)455 public void write_boolean_array(boolean[] x, int ofs, int len) 456 { 457 try 458 { 459 for (int i = ofs; i < ofs + len; i++) 460 { 461 b.write(x [ i ] ? 1 : 0); 462 } 463 } 464 catch (IOException ex) 465 { 466 Unexpected.error(ex); 467 } 468 } 469 470 /** 471 * Writes the lower byte of the passed parameter. 472 * @param x the char to write 473 * 474 * It is effective to write more characters at once. 475 */ write_char(char x)476 public void write_char(char x) 477 { 478 try 479 { 480 if (narrow_native) 481 b.write(x); 482 else 483 { 484 OutputStreamWriter ow = 485 new OutputStreamWriter((OutputStream) b, narrow_charset); 486 ow.write(x); 487 ow.flush(); 488 } 489 } 490 catch (IOException ex) 491 { 492 Unexpected.error(ex); 493 } 494 } 495 496 /** 497 * Writes the lower bytes of the passed array members. 498 * 499 * @param chars an array 500 * @param offset offset 501 * @param length length 502 */ write_char_array(char[] chars, int offset, int length)503 public void write_char_array(char[] chars, int offset, int length) 504 { 505 try 506 { 507 if (narrow_native) 508 { 509 for (int i = offset; i < offset + length; i++) 510 { 511 b.write(chars [ i ]); 512 } 513 } 514 else 515 { 516 OutputStreamWriter ow = 517 new OutputStreamWriter((OutputStream) b, narrow_charset); 518 ow.write(chars, offset, length); 519 ow.flush(); 520 } 521 } 522 catch (IOException ex) 523 { 524 Unexpected.error(ex); 525 } 526 } 527 528 /** 529 * Writes the double value (IEEE 754 format). 530 */ write_double(double x)531 public void write_double(double x) 532 { 533 try 534 { 535 align(8); 536 b.writeDouble(x); 537 } 538 catch (Exception ex) 539 { 540 Unexpected.error(ex); 541 } 542 } 543 544 /** 545 * Writes the array of double values. 546 */ write_double_array(double[] x, int ofs, int len)547 public void write_double_array(double[] x, int ofs, int len) 548 { 549 try 550 { 551 align(8); 552 for (int i = ofs; i < ofs + len; i++) 553 { 554 b.writeDouble(x [ i ]); 555 } 556 } 557 catch (IOException ex) 558 { 559 Unexpected.error(ex); 560 } 561 } 562 563 /** 564 * Writes CORBA fixed, storing all digits but not the scale. 565 * The end of the record on <code>fixed</code> can 566 * be determined from its last byte. 567 */ write_fixed(BigDecimal fixed)568 public void write_fixed(BigDecimal fixed) 569 { 570 try 571 { 572 BigDecimalHelper.write(this, fixed); 573 } 574 catch (IOException ex) 575 { 576 Unexpected.error(ex); 577 } 578 catch (BadKind ex) 579 { 580 Unexpected.error(ex); 581 } 582 } 583 584 /** 585 * Write the float value (IEEE 754 format). 586 */ write_float(float x)587 public void write_float(float x) 588 { 589 try 590 { 591 align(4); 592 b.writeFloat(x); 593 } 594 catch (IOException ex) 595 { 596 Unexpected.error(ex); 597 } 598 } 599 600 /** 601 * Writes an array of the float values. 602 */ write_float_array(float[] x, int ofs, int len)603 public void write_float_array(float[] x, int ofs, int len) 604 { 605 try 606 { 607 align(4); 608 for (int i = ofs; i < ofs + len; i++) 609 { 610 b.writeFloat(x [ i ]); 611 } 612 } 613 catch (IOException ex) 614 { 615 Unexpected.error(ex); 616 } 617 } 618 619 /** 620 * Writes the integer value (CORBA long, four bytes, high byte first). 621 * @param x the value to write. 622 */ write_long(int x)623 public void write_long(int x) 624 { 625 try 626 { 627 align(4); 628 b.writeInt(x); 629 } 630 catch (IOException ex) 631 { 632 Unexpected.error(ex); 633 } 634 } 635 636 /** 637 * Writes the array of integer (CORBA long) values. 638 * 639 * @param x value 640 * @param ofs offset 641 * @param len length 642 */ write_long_array(int[] x, int ofs, int len)643 public void write_long_array(int[] x, int ofs, int len) 644 { 645 try 646 { 647 align(4); 648 for (int i = ofs; i < ofs + len; i++) 649 { 650 b.writeInt(x [ i ]); 651 } 652 } 653 catch (IOException ex) 654 { 655 Unexpected.error(ex); 656 } 657 } 658 659 /** 660 * Writes the long (CORBA long long) value, 8 bytes, 661 * high byte first. 662 * 663 * @param x the value to write. 664 */ write_longlong(long x)665 public void write_longlong(long x) 666 { 667 try 668 { 669 align(8); 670 b.writeLong(x); 671 } 672 catch (IOException ex) 673 { 674 Unexpected.error(ex); 675 } 676 } 677 678 /** 679 * Writes the array of longs (CORBA long longs) values. 680 * 681 * @param x value 682 * @param ofs offset 683 * @param len length 684 */ write_longlong_array(long[] x, int ofs, int len)685 public void write_longlong_array(long[] x, int ofs, int len) 686 { 687 try 688 { 689 align(8); 690 for (int i = ofs; i < ofs + len; i++) 691 { 692 b.writeLong(x [ i ]); 693 } 694 } 695 catch (IOException ex) 696 { 697 Unexpected.error(ex); 698 } 699 } 700 701 /** 702 * Writes this byte. 703 * @param x 704 */ write_octet(byte x)705 public void write_octet(byte x) 706 { 707 try 708 { 709 b.writeByte(x); 710 } 711 catch (IOException ex) 712 { 713 Unexpected.error(ex); 714 } 715 } 716 717 /** 718 * Writes the array of bytes (CORBA octets) values. 719 * 720 * @param x value 721 * @param ofs offset 722 * @param len length 723 */ write_octet_array(byte[] x, int ofs, int len)724 public void write_octet_array(byte[] x, int ofs, int len) 725 { 726 try 727 { 728 b.write(x, ofs, len); 729 } 730 catch (IOException ex) 731 { 732 Unexpected.error(ex); 733 } 734 } 735 736 /** 737 * Writes first the size of array, and then the byte array using 738 * the {@link java.io.OutputStream#write(byte[]) }. The sequence 739 * being written is preceeded by the int, representing the array 740 * length. 741 */ write_sequence(byte[] buf)742 public void write_sequence(byte[] buf) 743 { 744 try 745 { 746 write_long(buf.length); 747 write(buf); 748 } 749 catch (IOException ex) 750 { 751 MARSHAL t = new MARSHAL(); 752 t.minor = Minor.CDR; 753 t.initCause(ex); 754 throw t; 755 } 756 } 757 758 /** 759 * Writes the contents of the provided stream. 760 * The sequence being written is preceeded by the int, 761 * representing the stream buffer length (the number of 762 * bytes being subsequently written). 763 */ write_sequence(BufferedCdrOutput from)764 public void write_sequence(BufferedCdrOutput from) 765 { 766 try 767 { 768 write_long(from.buffer.size()); 769 from.buffer.writeTo(this); 770 } 771 catch (IOException ex) 772 { 773 MARSHAL t = new MARSHAL(); 774 t.minor = Minor.CDR; 775 t.initCause(ex); 776 throw t; 777 } 778 } 779 780 /** 781 * Writes the two byte integer (short), high byte first. 782 * 783 * @param x the integer to write. 784 */ write_short(short x)785 public void write_short(short x) 786 { 787 try 788 { 789 align(2); 790 b.writeShort(x); 791 } 792 catch (IOException ex) 793 { 794 Unexpected.error(ex); 795 } 796 } 797 798 /** 799 * Writes the array of short (two byte integer) values. 800 * 801 * @param x value 802 * @param ofs offset 803 * @param len length 804 */ write_short_array(short[] x, int ofs, int len)805 public void write_short_array(short[] x, int ofs, int len) 806 { 807 try 808 { 809 align(2); 810 for (int i = ofs; i < ofs + len; i++) 811 { 812 b.writeShort(x [ i ]); 813 } 814 } 815 catch (IOException ex) 816 { 817 Unexpected.error(ex); 818 } 819 } 820 821 /** 822 * Writes the string. This implementation first calls 823 * String.getBytes() and then writes the length of the returned 824 * array (as CORBA ulong) and the returned array itself. 825 * 826 * The encoding information, if previously set, is taken 827 * into consideration. 828 * 829 * @param x the string to write. 830 */ write_string(String x)831 public void write_string(String x) 832 { 833 try 834 { 835 byte[] ab = x.getBytes(narrow_charset); 836 write_long(ab.length + 1); 837 write(ab); 838 839 // write null terminator. 840 write(0); 841 } 842 catch (IOException ex) 843 { 844 Unexpected.error(ex); 845 } 846 } 847 848 /** 849 * Writes the CORBA unsigned long in the same way as CORBA long. 850 */ write_ulong(int x)851 public void write_ulong(int x) 852 { 853 write_long(x); 854 } 855 856 /** 857 * Writes the array of CORBA unsigned longs in the same way as 858 * array of ordinary longs. 859 */ write_ulong_array(int[] x, int ofs, int len)860 public void write_ulong_array(int[] x, int ofs, int len) 861 { 862 write_long_array(x, ofs, len); 863 } 864 865 /** 866 * Write the unsigned long long in the same way as an ordinary long long. 867 * 868 * @param x a value to write. 869 */ write_ulonglong(long x)870 public void write_ulonglong(long x) 871 { 872 write_longlong(x); 873 } 874 875 /** 876 * Write the array of unsingel long longs in the same way 877 * an an array of the ordinary long longs. 878 */ write_ulonglong_array(long[] x, int ofs, int len)879 public void write_ulonglong_array(long[] x, int ofs, int len) 880 { 881 write_longlong_array(x, ofs, len); 882 } 883 884 /** 885 * Write the unsigned short in the same way as an ordinary short. 886 */ write_ushort(short x)887 public void write_ushort(short x) 888 { 889 write_short(x); 890 } 891 892 /** 893 * Write an array of unsigned short integersin the same way 894 * as an array of ordinary short integers. 895 */ write_ushort_array(short[] x, int ofs, int len)896 public void write_ushort_array(short[] x, int ofs, int len) 897 { 898 write_short_array(x, ofs, len); 899 } 900 901 /** 902 * Writes the character as two byte short integer (Unicode value), high byte 903 * first. Writes in Big Endian, but never writes the endian indicator. 904 * 905 * The character is always written using the native UTF-16BE charset because 906 * its size under arbitrary encoding is not evident. 907 */ write_wchar(char x)908 public void write_wchar(char x) 909 { 910 try 911 { 912 if (giop.until_inclusive(1, 1)) 913 { 914 align(2); 915 916 if (wide_native) 917 b.writeShort(x); 918 else 919 { 920 OutputStreamWriter ow = new OutputStreamWriter( 921 (OutputStream) b, wide_charset); 922 ow.write(x); 923 ow.flush(); 924 } 925 } 926 else if (wide_native) 927 { 928 b.writeByte(2); 929 b.writeChar(x); 930 } 931 else 932 { 933 String encoded = new String(new char[] { x }); 934 byte[] bytes = encoded.getBytes(wide_charset); 935 b.write(bytes.length + 2); 936 b.write(bytes); 937 } 938 } 939 catch (IOException ex) 940 { 941 Unexpected.error(ex); 942 } 943 } 944 945 /** 946 * Write the array of wide chars. 947 * 948 * @param chars the array of wide chars 949 * @param offset offset 950 * @param length length 951 * 952 * The char array is always written using the native UTF-16BE charset because 953 * the character size under arbitrary encoding is not evident. 954 */ write_wchar_array(char[] chars, int offset, int length)955 public void write_wchar_array(char[] chars, int offset, int length) 956 { 957 try 958 { 959 if (giop.until_inclusive(1, 1)) 960 align(2); 961 962 if (wide_native) 963 { 964 for (int i = offset; i < offset + length; i++) 965 { 966 b.writeShort(chars [ i ]); 967 } 968 } 969 else 970 { 971 OutputStreamWriter ow = 972 new OutputStreamWriter((OutputStream) b, wide_charset); 973 ow.write(chars, offset, length); 974 ow.flush(); 975 } 976 } 977 catch (IOException ex) 978 { 979 Unexpected.error(ex); 980 } 981 } 982 983 /** 984 * Writes the length of the string in bytes (not characters) and 985 * then all characters as two byte unicode chars. Adds the 986 * Big Endian indicator, 0xFFFE, at the beginning and null wide char at 987 * the end. 988 * 989 * @param x the string to write. 990 */ write_wstring(String x)991 public void write_wstring(String x) 992 { 993 try 994 { 995 if (giop.since_inclusive(1, 2)) 996 { 997 byte[] bytes = x.getBytes(wide_charset); 998 write_sequence(bytes); 999 } 1000 else 1001 { 1002 // Encoding with null terminator always in UTF-16. 1003 // The wide null terminator needs extra two bytes. 1004 write_long(2 * x.length() + 2); 1005 1006 for (int i = 0; i < x.length(); i++) 1007 { 1008 b.writeShort(x.charAt(i)); 1009 } 1010 1011 // Write null terminator. 1012 b.writeShort(0); 1013 } 1014 } 1015 catch (IOException ex) 1016 { 1017 Unexpected.error(ex); 1018 } 1019 } 1020 1021 /** {@inheritDoc} */ write_any_array(Any[] anys, int offset, int length)1022 public void write_any_array(Any[] anys, int offset, int length) 1023 { 1024 for (int i = offset; i < offset + length; i++) 1025 { 1026 write_any(anys [ i ]); 1027 } 1028 } 1029 _truncatable_ids()1030 public String[] _truncatable_ids() 1031 { 1032 /**@todo Implement this org.omg.CORBA.portable.ValueBase abstract method*/ 1033 throw new java.lang.UnsupportedOperationException("Method _truncatable_ids() not yet implemented."); 1034 } 1035 1036 /** {@inheritDoc} */ write_Abstract(java.lang.Object value)1037 public void write_Abstract(java.lang.Object value) 1038 { 1039 write_abstract_interface(value); 1040 } 1041 1042 /** {@inheritDoc} */ write_Value(Serializable value)1043 public void write_Value(Serializable value) 1044 { 1045 write_value(value); 1046 } 1047 } 1048