| /* 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_little_endian 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). |
| */ |
| public void setBigEndian(boolean use_big_endian) |
| { |
| little_endian = !use_big_endian; |
| setInputStream(actual_stream); |
| } |
| |
| /** |
| * Get the used encoding. |
| * |
| * @param 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; |
| reading: 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" }; |
| } |
| } |