diff options
Diffstat (limited to 'libjava/classpath/gnu/CORBA/CDR/AbstractCdrInput.java')
-rw-r--r-- | libjava/classpath/gnu/CORBA/CDR/AbstractCdrInput.java | 1768 |
1 files changed, 1768 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/CORBA/CDR/AbstractCdrInput.java b/libjava/classpath/gnu/CORBA/CDR/AbstractCdrInput.java new file mode 100644 index 000000000..fae16eed9 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/AbstractCdrInput.java @@ -0,0 +1,1768 @@ +/* AbstractCdrInput.java -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.CORBA.CDR; + +import gnu.CORBA.BigDecimalHelper; +import gnu.CORBA.OrbFunctional; +import gnu.CORBA.GIOP.CharSets_OSF; +import gnu.CORBA.GIOP.CodeSetServiceContext; +import gnu.CORBA.IOR; +import gnu.CORBA.IorDelegate; +import gnu.CORBA.Minor; +import gnu.CORBA.TypeCodeHelper; +import gnu.CORBA.Unexpected; +import gnu.CORBA.Version; +import gnu.CORBA.gnuAny; +import gnu.CORBA.StubLocator; + +import org.omg.CORBA.Any; +import org.omg.CORBA.AnySeqHolder; +import org.omg.CORBA.BAD_OPERATION; +import org.omg.CORBA.BooleanSeqHolder; +import org.omg.CORBA.CharSeqHolder; +import org.omg.CORBA.DoubleSeqHolder; +import org.omg.CORBA.FloatSeqHolder; +import org.omg.CORBA.LongLongSeqHolder; +import org.omg.CORBA.LongSeqHolder; +import org.omg.CORBA.MARSHAL; +import org.omg.CORBA.ORB; +import org.omg.CORBA.OctetSeqHolder; +import org.omg.CORBA.ShortSeqHolder; +import org.omg.CORBA.TypeCode; +import org.omg.CORBA.TypeCodePackage.BadKind; +import org.omg.CORBA.TypeCodePackage.Bounds; +import org.omg.CORBA.ULongLongSeqHolder; +import org.omg.CORBA.ULongSeqHolder; +import org.omg.CORBA.UShortSeqHolder; +import org.omg.CORBA.WCharSeqHolder; +import org.omg.CORBA.portable.InputStream; +import org.omg.CORBA.portable.ObjectImpl; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Serializable; + +import java.math.BigDecimal; + +/** + * A simple CORBA CDR (common data representation) input stream, reading data + * from the given {@link java.io.InputStream}. The primitive types are aligned + * on they natural boundaries by implementing the abstract method + * {@link #align(int boundary)}. + * + * The same class also implements {@link org.omg.CORBA.DataInputStream} to read + * the object content in a user defined way. + * + * TODO This class uses 16 bits per Unicode character only, as it was until jdk + * 1.4 inclusive. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public abstract class AbstractCdrInput + extends org.omg.CORBA_2_3.portable.InputStream + implements org.omg.CORBA.DataInputStream +{ + /** + * The runtime, associated with this stream. This field is only used when + * reading and writing value types and filled-in in gnu.CORBA.CDR.Vio. + */ + public transient gnuRuntime runtime; + + /** + * The message, explaining that the exception has been thrown due unexpected + * end of the input stream. This usually happens the server and client + * disagree on communication or data representation rules. + */ + protected static final String UNEXP_EOF = "Unexpected end of stream"; + + /** + * This instance is used to convert primitive data types into the byte + * sequences. + */ + protected AbstractDataInput b; + + /** + * The input stream, from where the data are actually being read. + */ + protected java.io.InputStream actual_stream; + + /** + * The associated orb, if any. + */ + protected ORB orb; + + /** + * The GIOP version. + */ + protected Version giop = new Version(1, 2); + + /** + * The code set information. + */ + protected CodeSetServiceContext codeset = CodeSetServiceContext.STANDARD; + + /** + * The name of the currently used narrow charset, null if the native narrow + * charset is used. + */ + private String narrow_charset = null; + + /** + * The name of the currently used wide charset, null if the native wide + * charset is used. + */ + private String wide_charset = null; + + /** + * True if the native code set is used for narrow characters. If the set is + * native, no the intermediate Reader object is instantiated when writing + * characters. + */ + private boolean narrow_native; + + /** + * True if the native code set is used for wide characters. If the set is + * native, no the intermediate Reader object is instantiated when writing + * characters. + */ + private boolean wide_native; + + /** + * If true, the stream expect the multi-byte data in the form "less + * significant byte first" (Little Endian). This is the opposite to the java + * standard (Big Endian). + */ + private boolean little_endian; + + /** + * Creates the stream. The stream reads Big Endian by default. + * + * @param readFrom a stream to read CORBA input from. + */ + public AbstractCdrInput(java.io.InputStream readFrom) + { + setInputStream(readFrom); + setCodeSet(CodeSetServiceContext.STANDARD); + } + + /** + * Creates the stream, requiring the subsequent call of + * {@link #setInputStream(java.io.InputStream)}. + */ + public AbstractCdrInput() + { + setCodeSet(CodeSetServiceContext.STANDARD); + } + + /** + * Set the Big Endian or Little Endian encoding. The stream reads Big Endian + * by default. + * + * @param use_big_endian if true, the stream expect the multi-byte data in + * the form "most significant byte first" (Big Endian). This is the + * java standard. + */ + public void setBigEndian(boolean use_big_endian) + { + little_endian = !use_big_endian; + setInputStream(actual_stream); + } + + /** + * Get the used encoding. + * + * @return true for Big Endian, false for Little Endian. + */ + public boolean isBigEndian() + { + return !little_endian; + } + + /** + * Clone all important settings to another stream. + */ + public void cloneSettings(AbstractCdrInput stream) + { + stream.setBigEndian(isBigEndian()); + stream.setCodeSet(getCodeSet()); + stream.setVersion(giop); + stream.setOrb(orb); + } + + /** + * Set the input stream that receives the CORBA input. + * + * @param readFrom the stream. + */ + public void setInputStream(java.io.InputStream readFrom) + { + if (little_endian) + b = new LittleEndianInputStream(readFrom); + else + b = new BigEndianInputStream(readFrom); + + actual_stream = readFrom; + } + + /** + * Set the alignment offset, if the index of the first byte in the stream is + * different from 0. + */ + public abstract void setOffset(int offset); + + /** + * Set the orb, associated with this stream. + * + * @param an_orb + */ + public void setOrb(ORB an_orb) + { + orb = an_orb; + } + + /** + * Set the GIOP version. Some data types are written differently for the + * different versions. The default version is 1.0 . + */ + public void setVersion(Version giop_version) + { + giop = giop_version; + } + + /** + * Align the curretn position at the given natural boundary. + */ + public abstract void align(int boundary); + + /** + * Reads the CORBA unsigned long (java int), returning the value in the + * sufficiently large java long. + */ + public long gnu_read_ulong() + { + try + { + long l = b.readInt(); + l &= 0xFFFFFFF; + return l; + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the unsigned short integer value and return it as java int, + * sufficiently large to hold all values. + */ + public int gnu_read_ushort() + { + try + { + align(2); + return b.readUnsignedShort(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Return the associated {@link ORB}. + * + * @return the associated {@link ORB} or null is no such is set. + */ + public ORB orb() + { + return orb; + } + + /** + * Read a single byte directly from the buffer. + */ + public int read() + throws java.io.IOException + { + try + { + return b.read(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + } + + /** + * Read bytes directly from the buffer. + */ + public int read(byte[] x, int ofs, int len) + throws java.io.IOException + { + try + { + return b.read(x, ofs, len); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + } + + /** + * Read bytes directly from the buffer. + */ + public int read(byte[] x) + throws java.io.IOException + { + try + { + return b.read(x); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + } + + /** + * Read the CORBA object. The object to read is represented in the form of the + * plain (not a string-encoded) IOR profile without the heading endian + * indicator. The responsible method for reading such data is + * {@link IOR.read_no_endian}. + * + * The returned object is usually casted into the given type using the .narrow + * method of its helper, despite in some cases the direct cast would also + * work. + * + * The null objects are recognised from the empty profile set. For such + * objects, null is returned. + * + * @return the loaded and constructed object. + */ + public org.omg.CORBA.Object read_Object() + { + try + { + IOR ior = new IOR(); + ior._read_no_endian(this); + + if (ior.Id == null) + return null; + + // Check maybe this is a remote reference to the local object. + // This is only possible if we access the repository of the + // connected object. + if (orb instanceof OrbFunctional) + { + OrbFunctional forb = (OrbFunctional) orb; + org.omg.CORBA.Object local = forb.find_local_object(ior); + if (local != null) + return local; + } + + // Search for the available stubs. + ObjectImpl impl = StubLocator.search(orb, ior); + try + { + if (impl._get_delegate() == null) + impl._set_delegate(new IorDelegate(orb, ior)); + } + catch (BAD_OPERATION ex) + { + // Some colaborants may throw this exception + // in response to the attempt to get the unset delegate. + impl._set_delegate(new IorDelegate(orb, ior)); + } + + return impl; + } + catch (IOException ex) + { + MARSHAL bad = new MARSHAL(); + bad.minor = Minor.IOR; + bad.initCause(ex); + throw bad; + } + } + + /** + * Read the type code. The type code format is defined in the CORBA + * documenation. + */ + public TypeCode read_TypeCode() + { + try + { + return TypeCodeHelper.read(this); + } + + catch (Bounds ex) + { + throw new Unexpected(); + } + catch (BadKind ex) + { + throw new Unexpected(); + } + } + + /** + * Read the CORBA {@link Any}. This method first reads the type code, then + * delegates the functionality to {@link Any#read_value}. + */ + public Any read_any() + { + TypeCode ty = read_TypeCode(); + gnuAny any = new gnuAny(); + any.read_value(this, ty); + return any; + } + + /** + * Read the boolean, treating any non zero byte as true, zero byte as false. + */ + public boolean read_boolean() + { + try + { + return b.read() == 0 ? false : true; + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the array of boolean. + */ + public void read_boolean_array(boolean[] x, int offs, int len) + { + try + { + for (int i = offs; i < offs + len; i++) + { + x[i] = b.read() == 0 ? false : true; + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read a character using narrow charset encoding. Depending form which + * encoding is set, this still can be Unicode or ever wider. + */ + public char read_char() + { + try + { + if (narrow_native) + return (char) b.read(); + else + return (char) new InputStreamReader((InputStream) b, narrow_charset).read(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read a character array, using narrow charset encoding. + */ + public void read_char_array(char[] x, int offset, int length) + { + try + { + if (narrow_native) + { + for (int i = offset; i < offset + length; i++) + x[i] = (char) b.read(); + } + else + { + InputStreamReader reader = new InputStreamReader((InputStream) b, + narrow_charset); + reader.read(x, offset, length); + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the double value, IEEE 754 format. + */ + public double read_double() + { + try + { + align(8); + return b.readDouble(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(); + } + } + + /** + * Read the array of double values, IEEE 754 format. + */ + public void read_double_array(double[] x, int offs, int len) + { + try + { + align(8); + for (int i = offs; i < offs + len; i++) + { + x[i] = b.readDouble(); + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the encapsulated stream. If the encapsulated sequence appears to be in + * the Little endian format, the flag of the returned stream is set to read + * Little endian. + */ + public BufferredCdrInput read_encapsulation() + { + try + { + int l = read_long(); + + byte[] r = new byte[l]; + int n = 0; + while (n < r.length) + { + n += read(r, n, r.length - n); + } + + BufferredCdrInput capsule = new BufferredCdrInput(r); + capsule.setOrb(orb); + + int endian = capsule.read_octet(); + + if (endian != 0) + { + capsule.setBigEndian(false); + } + + return capsule; + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the CORBA fixed (the end of the <code>fixed</code> can be determined + * by its last byte). The scale is always assumed to be zero. + */ + public BigDecimal read_fixed() + { + try + { + return BigDecimalHelper.read(this, 0); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the float value, IEEE 754 format. + */ + public float read_float() + { + try + { + align(4); + return b.readFloat(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read an array of float values, IEEE 754 format. + */ + public void read_float_array(float[] x, int offs, int len) + { + try + { + align(4); + for (int i = offs; i < offs + len; i++) + { + x[i] = b.readFloat(); + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the CORBA long (java int), high byte first. + */ + public int read_long() + { + try + { + align(4); + return b.readInt(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read an array of CORBA longs (java ints). + */ + public void read_long_array(int[] x, int offs, int len) + { + try + { + align(4); + for (int i = offs; i < offs + len; i++) + { + x[i] = b.readInt(); + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the CORBA long long (java long). + */ + public long read_longlong() + { + try + { + align(8); + return b.readLong(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read an array of CORBA long longs (java longs). + */ + public void read_longlong_array(long[] x, int offs, int len) + { + try + { + align(8); + for (int i = offs; i < offs + len; i++) + { + x[i] = b.readLong(); + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read a single byte. + */ + public byte read_octet() + { + try + { + return b.readByte(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the byte array. + */ + public void read_octet_array(byte[] x, int offs, int len) + { + try + { + b.read(x, offs, len); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the length of the byte array as CORBA long and then the array itseld. + */ + public byte[] read_sequence() + { + try + { + int l = read_long(); + byte[] buf = new byte[l]; + if (l > 0) + { + b.readFully(buf); + } + return buf; + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the CORBA short integer. + */ + public short read_short() + { + try + { + align(2); + return b.readShort(); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read the array of CORBA short integer values. + */ + public void read_short_array(short[] x, int offs, int len) + { + try + { + align(2); + for (int i = offs; i < offs + len; i++) + { + x[i] = b.readShort(); + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Read a singe byte string. The method firs reads the byte array and then + * calls a constructor to create a string from this array. The character + * encoding, if previously set, is taken into consideration. + * + * @return a loaded string. + */ + public String read_string() + { + int n = 0; + try + { + align(4); + + n = b.readInt(); + byte[] s = new byte[n]; + b.read(s); + + // Discard the null terminator. + if (narrow_charset == null) + return new String(s, 0, n - 1); + else + return new String(s, 0, n - 1, narrow_charset); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + catch (IOException ex) + { + throw new Unexpected(); + } + catch (NegativeArraySizeException nex) + { + MARSHAL m = new MARSHAL("Input stream broken, got " + n + "(0x" + + Integer.toHexString(n) + ") as a string size"); + m.minor = Minor.Negative; + throw m; + } + } + + /** + * Reads the CORBA unsigned long (java int), delegating functionality to + * {@link #read_long}. + */ + public int read_ulong() + { + return read_long(); + } + + /** + * Reads the array of CORBA unsigned long (java integer) values, delegating + * functionality to {@link #real_long_array}. + */ + public void read_ulong_array(int[] x, int offs, int len) + { + read_long_array(x, offs, len); + } + + /** + * Read the CORBA unsigned long long value, delegating functionality to + * {@link #read_longlong}. There is no way to return values over the limit of + * the java signed long in other way than returning the negative value. + */ + public long read_ulonglong() + { + return read_longlong(); + } + + /** + * Reads the array of CORBA long long (java long) values, delegating + * functionality to {@link #real_longlong_array}. + */ + public void read_ulonglong_array(long[] x, int offs, int len) + { + read_longlong_array(x, offs, len); + } + + /** + * Read the unsigned short integer value. Due strange specification, the + * returned value must be the short type as well, so the the best solution + * seems just to delegete functionality to read_short. + */ + public short read_ushort() + { + return read_short(); + } + + /** + * Read an array of unsigned short values, delegating the functionality to + * {@link read_short_array}. + */ + public void read_ushort_array(short[] x, int offs, int len) + { + read_short_array(x, offs, len); + } + + /** + * Reads the wide character using the encoding, specified in the wide_charset. + */ + public char read_wchar() + { + try + { + if (giop.until_inclusive(1, 1)) + { + align(2); + + if (wide_native) + return (char) b.readShort(); + else + return (char) new InputStreamReader((InputStream) b, wide_charset).read(); + } + else + { + int l = b.read(); + if (l == 2 && wide_native) + return b.readChar(); + else if (l <= 0) + { + MARSHAL m = new MARSHAL("wchar size " + l); + m.minor = Minor.Negative; + throw m; + } + else + { + byte[] bytes = new byte[l]; + b.readFully(bytes); + String cs; + + if (bytes.length > 2 && bytes[0] == 0xFE && bytes[1] == 0xFF) + cs = new String(bytes, 2, bytes.length - 2, wide_charset); + else if (bytes.length > 2 && bytes[0] == 0xFF + && bytes[1] == 0xFE) + { + // Litle endian detected - swap bytes. + byte t; + for (int i = 3; i < bytes.length; i = i + 2) + { + t = bytes[i]; + bytes[i - 1] = bytes[i]; + bytes[i] = t; + } + cs = new String(bytes, 2, bytes.length - 2, wide_charset); + } + else + cs = new String(bytes, wide_charset); + + return cs.charAt(0); + } + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + catch (IOException ex) + { + throw new Unexpected(); + } + } + + /** + * Read an array of "wide chars", each representing a two byte Unicode + * character, high byte first. + */ + public void read_wchar_array(char[] x, int offset, int length) + { + try + { + if (giop.until_inclusive(1, 1)) + align(2); + + if (wide_native) + { + for (int i = offset; i < offset + length; i++) + x[i] = (char) b.readShort(); + } + else + { + InputStreamReader reader = new InputStreamReader((InputStream) b, + wide_charset); + reader.read(x, offset, length); + } + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Reads the string in wide character format (ussually UTF-16, Unicode). Takes + * the currently set charset into consideration. + * + * If the native (UTF-16) encoding is used of the GIOP protocol is before 1.2, + * delegates functionality to "plain" {@link #read_wstring_UTF_16}. + */ + public String read_wstring() + { + // Native encoding or word oriented data. + if (wide_native || giop.until_inclusive(1, 1)) + return read_wstring_UTF_16(); + try + { + align(4); + + int n = b.readInt(); + byte[] s = new byte[n]; + b.read(s); + + return new String(s, 0, n, wide_charset); + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Reads first length of the string and the all characters as an Unicode + * (UTF-16) characters. Mind that GIOP 1.1 has the extra null character at the + * end that must be discarded. + */ + public String read_wstring_UTF_16() + { + try + { + int p = 0; + int n = read_long(); + + if (n<0) + { + MARSHAL m = new MARSHAL("Negative string size"); + m.minor = Minor.Negative; + throw m; + } + + // The null terminator that is no longer present since 1.2 . + int nt = giop.since_inclusive(1, 2) ? 0 : 1; + + // Convert bytes to shorts. + n = n / 2; + + // Empty string. + if (n == 0) + return ""; + + char[] s = new char[n]; + + for (int i = 0; i < s.length; i++) + s[i] = (char) b.readShort(); + + // Check for the byte order marker here. + if (s[0] == 0xFEFF) + { + // Big endian encoding - do nothing, but move the pointer + // one position forward. + p = 1; + } + else if (s[0] == 0xFFFE) + { + // Little endian encoding, swap the bytes and move one + // position forward. + p = 1; + + for (int i = p; i < s.length; i++) + s[i] = swap(s[i]); + } + + // Discard the null terminator and, if needed, the endian marker. + String r = new String(s, p, n - nt - p); + return r; + } + catch (EOFException ex) + { + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + t.initCause(ex); + throw t; + } + + catch (IOException ex) + { + throw new Unexpected(ex); + } + } + + /** + * Swap bytes in the character. + */ + public static char swap(char x) + { + int hi; + int lo; + + lo = x & 0xFF; + hi = (x >> 8) & 0xFF; + + return (char) ((lo << 8) | hi); + } + + /** + * Set the current code set context. + */ + public void setCodeSet(CodeSetServiceContext a_codeset) + { + this.codeset = a_codeset; + narrow_charset = CharSets_OSF.getName(codeset.char_data); + wide_charset = CharSets_OSF.getName(codeset.wide_char_data); + + narrow_native = CharSets_OSF.NATIVE_CHARACTER == codeset.char_data; + wide_native = CharSets_OSF.NATIVE_WIDE_CHARACTER == codeset.wide_char_data; + } + + /** + * Get the current code set context. + */ + public CodeSetServiceContext getCodeSet() + { + return codeset; + } + + /** + * Read the object that is an instance of the given class. The current + * implementation delegates functionality to the parameterless + * {@link readObject()}. + * + * @param klass a class of that this object the instance is. + * + * @return the returned object. + */ + public org.omg.CORBA.Object read_Object(Class klass) + { + return read_Object(); + } + + /** + * Read a value type structure from the stream. + * + * OMG specification states the writing format is outside the scope of GIOP + * definition. This implementation uses java serialization mechanism, calling + * {@link ObjectInputStream#readObject} + * + * @return an value type structure, unmarshaled from the stream + */ + public Serializable read_Value() + { + return read_value(); + } + + /** + * Read the abstract interface. An abstract interface can be either CORBA + * value type or CORBA object and is returned as an abstract java.lang.Object. + * + * As specified in OMG specification, this reads a single boolean and then + * delegates either to {@link #read_Object()} (for false) or to + * {@link #read_Value()} (for true). + * + * @return an abstract interface, unmarshaled from the stream + */ + public java.lang.Object read_Abstract() + { + return read_abstract_interface(); + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_char_array(CharSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_char_array(holder.value, offset, length); + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_wchar_array(WCharSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_wchar_array(holder.value, offset, length); + } + + /** + * If required, allocate or resize the char array to fit the newly read + * values. + * + * @param holder_value the existing char array, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private char[] ensureArray(char[] holder_value, int offset, int length) + { + if (holder_value == null) + return new char[offset + length]; + else if (holder_value.length < offset + length) + { + char[] value = new char[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_ulong_array(ULongSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_ulong_array(holder.value, offset, length); + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_long_array(LongSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_ulong_array(holder.value, offset, length); + } + + /** + * If required, allocate or resize the int array to fit the newly read values. + * + * @param holder_value the existing int array, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private int[] ensureArray(int[] holder_value, int offset, int length) + { + if (holder_value == null) + return new int[offset + length]; + else if (holder_value.length < offset + length) + { + int[] value = new int[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_float_array(FloatSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_float_array(holder.value, offset, length); + } + + /** + * If required, allocate or resize the float array to fit the newly read + * values. + * + * @param holder_value the existing float array, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private float[] ensureArray(float[] holder_value, int offset, int length) + { + if (holder_value == null) + return new float[offset + length]; + else if (holder_value.length < offset + length) + { + float[] value = new float[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_double_array(DoubleSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_double_array(holder.value, offset, length); + } + + /** + * If required, allocate or resize the double array to fit the newly read + * values. + * + * @param holder_value the existing double array, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private double[] ensureArray(double[] holder_value, int offset, int length) + { + if (holder_value == null) + return new double[offset + length]; + else if (holder_value.length < offset + length) + { + double[] value = new double[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_short_array(ShortSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_short_array(holder.value, offset, length); + } + + /** {@inheritDoc} */ + public void read_ushort_array(UShortSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_ushort_array(holder.value, offset, length); + } + + /** + * If required, allocate or resize the short array to fit the newly read + * values. + * + * @param holder_value the existing short array, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private short[] ensureArray(short[] holder_value, int offset, int length) + { + if (holder_value == null) + return new short[offset + length]; + else if (holder_value.length < offset + length) + { + short[] value = new short[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_octet_array(OctetSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_octet_array(holder.value, offset, length); + } + + /** + * If required, allocate or resize the byte array to fit the newly read + * values. + * + * @param holder_value the existing byte array, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private byte[] ensureArray(byte[] holder_value, int offset, int length) + { + if (holder_value == null) + return new byte[offset + length]; + else if (holder_value.length < offset + length) + { + byte[] value = new byte[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_longlong_array(LongLongSeqHolder holder, int offset, + int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_longlong_array(holder.value, offset, length); + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_ulonglong_array(ULongLongSeqHolder holder, int offset, + int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_ulonglong_array(holder.value, offset, length); + } + + /** + * If required, allocate or resize the array of longs to fit the newly read + * values. + * + * @param holder_value the existing array, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private long[] ensureArray(long[] holder_value, int offset, int length) + { + if (holder_value == null) + return new long[offset + length]; + else if (holder_value.length < offset + length) + { + long[] value = new long[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_boolean_array(BooleanSeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + read_boolean_array(holder.value, offset, length); + } + + /** + * If required, allocate or resize the array of booleans to fit the newly read + * values. + * + * @param holder_value the existing array of booleans, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private boolean[] ensureArray(boolean[] holder_value, int offset, int length) + { + if (holder_value == null) + return new boolean[offset + length]; + else if (holder_value.length < offset + length) + { + boolean[] value = new boolean[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * Read an array. In OMG specification is written that if the data does not + * fit into the holder value field, that array must be resized. The + * implementation follows this rule. If the holder value field contains null, + * it is newly instantiated. + */ + public void read_any_array(AnySeqHolder holder, int offset, int length) + { + holder.value = ensureArray(holder.value, offset, length); + for (int i = offset; i < offset + length; i++) + { + holder.value[i] = read_any(); + } + } + + /** + * If required, allocate or resize the array of Anys to fit the newly read + * values. + * + * @param holder_value the existing array of Anys, may be null. + * @param offset the required offset to read. + * @param length the length of the new sequence. + * + * @return the allocated or resized array, same array if no such operations + * are required. + */ + private Any[] ensureArray(Any[] holder_value, int offset, int length) + { + if (holder_value == null) + return new Any[offset + length]; + else if (holder_value.length < offset + length) + { + Any[] value = new Any[offset + length]; + System.arraycopy(holder_value, 0, value, 0, holder_value.length); + return value; + } + else + return holder_value; + } + + /** + * This method is required to represent the DataInputStream as a value type + * object. + * + * @return a single entity "IDL:omg.org/CORBA/DataInputStream:1.0", always. + */ + public String[] _truncatable_ids() + { + return new String[] { "IDL:omg.org/CORBA/DataInputStream:1.0" }; + } +} |