Source for gnu.CORBA.CDR.AbstractCdrOutput

   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:    */
 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:    */
 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:    */
 179:   public abstract void setOffset(int an_offset);
 180: 
 181:   /**
 182:    * Clone all important settings to another stream.
 183:    */
 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:    */
 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:    */
 208:   public CodeSetServiceContext getCodeSet()
 209:   {
 210:     return codeset;
 211:   }
 212: 
 213:   /**
 214:    * Set the orb, associated with this stream.
 215:    * @param an_orb
 216:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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} */
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: 
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} */
1037:   public void write_Abstract(java.lang.Object value)
1038:   {
1039:     write_abstract_interface(value);
1040:   }
1041: 
1042:   /** {@inheritDoc} */
1043:   public void write_Value(Serializable value)
1044:   {
1045:     write_value(value);
1046:   }
1047: }