1 /* AbstractCdrOutput.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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
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
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. */
39 package gnu.CORBA.CDR;
41 import gnu.CORBA.BigDecimalHelper;
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;
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;
69 import java.io.IOException;
70 import java.io.OutputStreamWriter;
71 import java.io.Serializable;
72 import java.math.BigDecimal;
75 * A simple CORBA CDR (common data representation)
76 * output stream, writing data into the
77 * given {@link java.io.OutputStream}.
79 * The same class also implements the {@link DataInputStream},
80 * providing support for writing the value type objects
81 * in a user defined way.
83 * TODO This class uses 16 bits per Unicode character only, as it was until
86 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
88 public abstract class AbstractCdrOutput
89 extends org.omg.CORBA_2_3.portable.OutputStream
90 implements org.omg.CORBA.DataOutputStream
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.
96 public transient gnuRuntime runtime;
99 * This instance is used to convert primitive data types into the
102 protected AbstractDataOutput b;
105 * The associated orb, if any.
112 protected Version giop = new Version(1, 2);
115 * The code set information.
117 protected CodeSetServiceContext codeset;
120 * The name of the currently used narrow charset.
122 private String narrow_charset;
125 * The name of the currently used wide charset, null if
126 * the native wide charset is used.
128 private String wide_charset;
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.
135 private boolean narrow_native;
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.
142 private boolean wide_native;
145 * If true, the Little Endian encoding is used to write the
146 * data. Otherwise, the Big Endian encoding is used.
148 private boolean little_endian;
151 * The stream whre the data are actually written.
153 private java.io.OutputStream actual_stream;
156 * Creates the stream.
158 * @param writeTo a stream to write CORBA output to.
160 public AbstractCdrOutput(java.io.OutputStream writeTo)
162 setOutputStream(writeTo);
163 setCodeSet(CodeSetServiceContext.STANDARD);
167 * Creates the stream, requiring the subsequent call
168 * of {@link #setOutputStream(java.io.OutputStream)}.
170 public AbstractCdrOutput()
172 setCodeSet(CodeSetServiceContext.STANDARD);
176 * Set the alignment offset, if the index of the first byte in the
177 * stream is different from 0.
179 public abstract void setOffset(int an_offset);
182 * Clone all important settings to another stream.
184 public void cloneSettings(AbstractCdrOutput stream)
186 stream.setBigEndian(!little_endian);
187 stream.setCodeSet(getCodeSet());
188 stream.setVersion(giop);
193 * Set the current code set context.
195 public void setCodeSet(CodeSetServiceContext a_codeset)
197 this.codeset = a_codeset;
198 narrow_charset = CharSets_OSF.getName(codeset.char_data);
199 wide_charset = CharSets_OSF.getName(codeset.wide_char_data);
201 narrow_native = CharSets_OSF.NATIVE_CHARACTER == codeset.char_data;
202 wide_native = CharSets_OSF.NATIVE_WIDE_CHARACTER == codeset.wide_char_data;
206 * Get the current code set context.
208 public CodeSetServiceContext getCodeSet()
214 * Set the orb, associated with this stream.
217 public void setOrb(ORB an_orb)
223 * Set the output stream that receives the CORBA output.
225 * @param writeTo the stream.
227 public void setOutputStream(java.io.OutputStream writeTo)
230 b = new LittleEndianOutputStream(writeTo);
232 b = new BigEndianOutputStream(writeTo);
234 actual_stream = writeTo;
238 * Set the GIOP version. Some data types are written differently
239 * for the different versions. The default version is 1.0 .
241 public void setVersion(Version giop_version)
247 * Specify if the stream should use the Big Endian (usual for java)
248 * or Little Encoding. The default is Big Endian.
250 * @param use_big_endian if true, use Big Endian, if false,
253 public void setBigEndian(boolean use_big_endian)
255 little_endian = !use_big_endian;
256 setOutputStream(actual_stream);
260 * Align the curretn position at the given natural boundary.
262 public abstract void align(int boundary);
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.
270 * It is not allowed to write to the current stream directly
271 * before the encapsulation stream is closed.
273 * The encoding (Big/Little Endian) inside the encapsulated
274 * sequence is the same as used into the parent stream.
276 * @return the encapsulated stream.
278 public AbstractCdrOutput createEncapsulation()
280 return new EncapsulationStream(this, !little_endian);
284 * Return the associated {@link ORB}.
285 * @return the associated {@link ORB} or null is no such is set.
293 * Write a single byte.
294 * @param n byte to write (low 8 bits are written).
296 public void write(int n)
302 catch (IOException ex)
304 Unexpected.error(ex);
309 * Write bytes directly into the underlying stream.
311 public void write(byte[] x)
312 throws java.io.IOException
318 * Write bytes directly into the underlying stream.
320 public void write(byte[] x, int ofs, int len)
321 throws java.io.IOException
323 b.write(x, ofs, len);
327 * Following the specification, this is not implemented.
328 * Override to get the functionality.
330 public void write_Context(Context context, ContextList contexts)
332 throw new NO_IMPLEMENT();
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}.
340 * The null value is written as defined in OMG specification (zero length
341 * string, followed by an empty set of profiles).
343 public void write_Object(org.omg.CORBA.Object x)
346 if (x instanceof IorProvider)
348 ((IorProvider) x).getIor()._write_no_endian(this);
353 IOR.write_null(this);
356 else if (x instanceof ObjectImpl)
358 Delegate d = ((ObjectImpl) x)._get_delegate();
360 if (d instanceof IorProvider)
362 ((IorProvider) d).getIor()._write_no_endian(this);
367 ORB d_orb = d.orb(x);
373 // Either this is not an ObjectImpl or it has the
374 // unexpected delegate. Try to convert via ORBs
375 // object_to_string().
378 IOR ior = IOR.parse(w_orb.object_to_string(x));
379 ior._write_no_endian(this);
383 throw new BAD_OPERATION(
384 "Please set the ORB for this stream, cannot write "
385 + x.getClass().getName());
389 * Write the TypeCode. This implementation delegates functionality
390 * to {@link cdrTypeCode}.
392 * @param x a TypeCode to write.
394 public void write_TypeCode(TypeCode x)
398 TypeCodeHelper.write(this, x);
400 catch (UserException ex)
402 Unexpected.error(ex);
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}
413 * @param x the {@link Any} to write.
415 public void write_any(Any x)
417 Streamable value = x.extract_Streamable();
420 write_TypeCode(x.type());
425 PrimitiveTypeCode p = new PrimitiveTypeCode(TCKind.tk_null);
431 * Writes a single byte, 0 for <code>false</code>,
432 * 1 for <code>true</code>.
434 * @param x the value to write
436 public void write_boolean(boolean x)
442 catch (IOException ex)
444 Unexpected.error(ex);
449 * Writes the boolean array.
455 public void write_boolean_array(boolean[] x, int ofs, int len)
459 for (int i = ofs; i < ofs + len; i++)
461 b.write(x [ i ] ? 1 : 0);
464 catch (IOException ex)
466 Unexpected.error(ex);
471 * Writes the lower byte of the passed parameter.
472 * @param x the char to write
474 * It is effective to write more characters at once.
476 public void write_char(char x)
484 OutputStreamWriter ow =
485 new OutputStreamWriter((OutputStream) b, narrow_charset);
490 catch (IOException ex)
492 Unexpected.error(ex);
497 * Writes the lower bytes of the passed array members.
499 * @param chars an array
500 * @param offset offset
501 * @param length length
503 public void write_char_array(char[] chars, int offset, int length)
509 for (int i = offset; i < offset + length; i++)
511 b.write(chars [ i ]);
516 OutputStreamWriter ow =
517 new OutputStreamWriter((OutputStream) b, narrow_charset);
518 ow.write(chars, offset, length);
522 catch (IOException ex)
524 Unexpected.error(ex);
529 * Writes the double value (IEEE 754 format).
531 public void write_double(double x)
540 Unexpected.error(ex);
545 * Writes the array of double values.
547 public void write_double_array(double[] x, int ofs, int len)
552 for (int i = ofs; i < ofs + len; i++)
554 b.writeDouble(x [ i ]);
557 catch (IOException ex)
559 Unexpected.error(ex);
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.
568 public void write_fixed(BigDecimal fixed)
572 BigDecimalHelper.write(this, fixed);
574 catch (IOException ex)
576 Unexpected.error(ex);
580 Unexpected.error(ex);
585 * Write the float value (IEEE 754 format).
587 public void write_float(float x)
594 catch (IOException ex)
596 Unexpected.error(ex);
601 * Writes an array of the float values.
603 public void write_float_array(float[] x, int ofs, int len)
608 for (int i = ofs; i < ofs + len; i++)
610 b.writeFloat(x [ i ]);
613 catch (IOException ex)
615 Unexpected.error(ex);
620 * Writes the integer value (CORBA long, four bytes, high byte first).
621 * @param x the value to write.
623 public void write_long(int x)
630 catch (IOException ex)
632 Unexpected.error(ex);
637 * Writes the array of integer (CORBA long) values.
643 public void write_long_array(int[] x, int ofs, int len)
648 for (int i = ofs; i < ofs + len; i++)
653 catch (IOException ex)
655 Unexpected.error(ex);
660 * Writes the long (CORBA long long) value, 8 bytes,
663 * @param x the value to write.
665 public void write_longlong(long x)
672 catch (IOException ex)
674 Unexpected.error(ex);
679 * Writes the array of longs (CORBA long longs) values.
685 public void write_longlong_array(long[] x, int ofs, int len)
690 for (int i = ofs; i < ofs + len; i++)
692 b.writeLong(x [ i ]);
695 catch (IOException ex)
697 Unexpected.error(ex);
705 public void write_octet(byte x)
711 catch (IOException ex)
713 Unexpected.error(ex);
718 * Writes the array of bytes (CORBA octets) values.
724 public void write_octet_array(byte[] x, int ofs, int len)
728 b.write(x, ofs, len);
730 catch (IOException ex)
732 Unexpected.error(ex);
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
742 public void write_sequence(byte[] buf)
746 write_long(buf.length);
749 catch (IOException ex)
751 MARSHAL t = new MARSHAL();
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).
764 public void write_sequence(BufferedCdrOutput from)
768 write_long(from.buffer.size());
769 from.buffer.writeTo(this);
771 catch (IOException ex)
773 MARSHAL t = new MARSHAL();
781 * Writes the two byte integer (short), high byte first.
783 * @param x the integer to write.
785 public void write_short(short x)
792 catch (IOException ex)
794 Unexpected.error(ex);
799 * Writes the array of short (two byte integer) values.
805 public void write_short_array(short[] x, int ofs, int len)
810 for (int i = ofs; i < ofs + len; i++)
812 b.writeShort(x [ i ]);
815 catch (IOException ex)
817 Unexpected.error(ex);
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.
826 * The encoding information, if previously set, is taken
827 * into consideration.
829 * @param x the string to write.
831 public void write_string(String x)
835 byte[] ab = x.getBytes(narrow_charset);
836 write_long(ab.length + 1);
839 // write null terminator.
842 catch (IOException ex)
844 Unexpected.error(ex);
849 * Writes the CORBA unsigned long in the same way as CORBA long.
851 public void write_ulong(int x)
857 * Writes the array of CORBA unsigned longs in the same way as
858 * array of ordinary longs.
860 public void write_ulong_array(int[] x, int ofs, int len)
862 write_long_array(x, ofs, len);
866 * Write the unsigned long long in the same way as an ordinary long long.
868 * @param x a value to write.
870 public void write_ulonglong(long x)
876 * Write the array of unsingel long longs in the same way
877 * an an array of the ordinary long longs.
879 public void write_ulonglong_array(long[] x, int ofs, int len)
881 write_longlong_array(x, ofs, len);
885 * Write the unsigned short in the same way as an ordinary short.
887 public void write_ushort(short x)
893 * Write an array of unsigned short integersin the same way
894 * as an array of ordinary short integers.
896 public void write_ushort_array(short[] x, int ofs, int len)
898 write_short_array(x, ofs, len);
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.
905 * The character is always written using the native UTF-16BE charset because
906 * its size under arbitrary encoding is not evident.
908 public void write_wchar(char x)
912 if (giop.until_inclusive(1, 1))
920 OutputStreamWriter ow = new OutputStreamWriter(
921 (OutputStream) b, wide_charset);
926 else if (wide_native)
933 String encoded = new String(new char[] { x });
934 byte[] bytes = encoded.getBytes(wide_charset);
935 b.write(bytes.length + 2);
939 catch (IOException ex)
941 Unexpected.error(ex);
946 * Write the array of wide chars.
948 * @param chars the array of wide chars
949 * @param offset offset
950 * @param length length
952 * The char array is always written using the native UTF-16BE charset because
953 * the character size under arbitrary encoding is not evident.
955 public void write_wchar_array(char[] chars, int offset, int length)
959 if (giop.until_inclusive(1, 1))
964 for (int i = offset; i < offset + length; i++)
966 b.writeShort(chars [ i ]);
971 OutputStreamWriter ow =
972 new OutputStreamWriter((OutputStream) b, wide_charset);
973 ow.write(chars, offset, length);
977 catch (IOException ex)
979 Unexpected.error(ex);
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
989 * @param x the string to write.
991 public void write_wstring(String x)
995 if (giop.since_inclusive(1, 2))
997 byte[] bytes = x.getBytes(wide_charset);
998 write_sequence(bytes);
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);
1006 for (int i = 0; i < x.length(); i++)
1008 b.writeShort(x.charAt(i));
1011 // Write null terminator.
1015 catch (IOException ex)
1017 Unexpected.error(ex);
1021 /** {@inheritDoc} */
1022 public void write_any_array(Any[] anys, int offset, int length)
1024 for (int i = offset; i < offset + length; i++)
1026 write_any(anys [ i ]);
1030 public String[] _truncatable_ids()
1032 /**@todo Implement this org.omg.CORBA.portable.ValueBase abstract method*/
1033 throw new java.lang.UnsupportedOperationException("Method _truncatable_ids() not yet implemented.");
1036 /** {@inheritDoc} */
1037 public void write_Abstract(java.lang.Object value)
1039 write_abstract_interface(value);
1042 /** {@inheritDoc} */
1043 public void write_Value(Serializable value)