diff options
Diffstat (limited to 'libjava/classpath/gnu/CORBA/CDR')
21 files changed, 8585 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" }; + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/AbstractCdrOutput.java b/libjava/classpath/gnu/CORBA/CDR/AbstractCdrOutput.java new file mode 100644 index 000000000..ab0b982ab --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/AbstractCdrOutput.java @@ -0,0 +1,1047 @@ +/* AbstractCdrOutput.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.IOR; +import gnu.CORBA.IorProvider; +import gnu.CORBA.Minor; +import gnu.CORBA.TypeCodeHelper; +import gnu.CORBA.Unexpected; +import gnu.CORBA.Version; +import gnu.CORBA.GIOP.CharSets_OSF; +import gnu.CORBA.GIOP.CodeSetServiceContext; +import gnu.CORBA.typecodes.PrimitiveTypeCode; + +import org.omg.CORBA.Any; +import org.omg.CORBA.BAD_OPERATION; +import org.omg.CORBA.Context; +import org.omg.CORBA.ContextList; +import org.omg.CORBA.DataInputStream; +import org.omg.CORBA.MARSHAL; +import org.omg.CORBA.NO_IMPLEMENT; +import org.omg.CORBA.ORB; +import org.omg.CORBA.TCKind; +import org.omg.CORBA.TypeCode; +import org.omg.CORBA.UserException; +import org.omg.CORBA.TypeCodePackage.BadKind; +import org.omg.CORBA.portable.Delegate; +import org.omg.CORBA.portable.ObjectImpl; +import org.omg.CORBA.portable.OutputStream; +import org.omg.CORBA.portable.Streamable; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * A simple CORBA CDR (common data representation) + * output stream, writing data into the + * given {@link java.io.OutputStream}. + * + * The same class also implements the {@link DataInputStream}, + * providing support for writing the value type objects + * 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 AbstractCdrOutput + extends org.omg.CORBA_2_3.portable.OutputStream + implements org.omg.CORBA.DataOutputStream +{ + /** + * 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; + + /** + * This instance is used to convert primitive data types into the + * byte sequences. + */ + protected AbstractDataOutput b; + + /** + * 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; + + /** + * The name of the currently used narrow charset. + */ + private String narrow_charset; + + /** + * The name of the currently used wide charset, null if + * the native wide charset is used. + */ + private String wide_charset; + + /** + * 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 Little Endian encoding is used to write the + * data. Otherwise, the Big Endian encoding is used. + */ + private boolean little_endian; + + /** + * The stream whre the data are actually written. + */ + private java.io.OutputStream actual_stream; + + /** + * Creates the stream. + * + * @param writeTo a stream to write CORBA output to. + */ + public AbstractCdrOutput(java.io.OutputStream writeTo) + { + setOutputStream(writeTo); + setCodeSet(CodeSetServiceContext.STANDARD); + } + + /** + * Creates the stream, requiring the subsequent call + * of {@link #setOutputStream(java.io.OutputStream)}. + */ + public AbstractCdrOutput() + { + setCodeSet(CodeSetServiceContext.STANDARD); + } + + /** + * Set the alignment offset, if the index of the first byte in the + * stream is different from 0. + */ + public abstract void setOffset(int an_offset); + + /** + * Clone all important settings to another stream. + */ + public void cloneSettings(AbstractCdrOutput stream) + { + stream.setBigEndian(!little_endian); + stream.setCodeSet(getCodeSet()); + stream.setVersion(giop); + stream.setOrb(orb); + } + + /** + * 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; + } + + /** + * Set the orb, associated with this stream. + * @param an_orb + */ + public void setOrb(ORB an_orb) + { + orb = an_orb; + } + + /** + * Set the output stream that receives the CORBA output. + * + * @param writeTo the stream. + */ + public void setOutputStream(java.io.OutputStream writeTo) + { + if (little_endian) + b = new LittleEndianOutputStream(writeTo); + else + b = new BigEndianOutputStream(writeTo); + + actual_stream = writeTo; + } + + /** + * 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; + } + + /** + * Specify if the stream should use the Big Endian (usual for java) + * or Little Encoding. The default is Big Endian. + * + * @param use_big_endian if true, use Big Endian, if false, + * use Little Endian. + */ + public void setBigEndian(boolean use_big_endian) + { + little_endian = !use_big_endian; + setOutputStream(actual_stream); + } + + /** + * Align the curretn position at the given natural boundary. + */ + public abstract void align(int boundary); + + /** + * Create the encapsulation stream, associated with the current + * stream. The encapsulated stream must be closed. When being + * closed, the encapsulation stream writes its buffer into + * this stream using the CORBA CDR encapsulation rules. + * + * It is not allowed to write to the current stream directly + * before the encapsulation stream is closed. + * + * The encoding (Big/Little Endian) inside the encapsulated + * sequence is the same as used into the parent stream. + * + * @return the encapsulated stream. + */ + public AbstractCdrOutput createEncapsulation() + { + return new EncapsulationStream(this, !little_endian); + } + + /** + * Return the associated {@link ORB}. + * @return the associated {@link ORB} or null is no such is set. + */ + public ORB orb() + { + return orb; + } + + /** + * Write a single byte. + * @param n byte to write (low 8 bits are written). + */ + public void write(int n) + { + try + { + b.write(n); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Write bytes directly into the underlying stream. + */ + public void write(byte[] x) + throws java.io.IOException + { + b.write(x); + } + + /** + * Write bytes directly into the underlying stream. + */ + public void write(byte[] x, int ofs, int len) + throws java.io.IOException + { + b.write(x, ofs, len); + } + + /** + * Following the specification, this is not implemented. + * Override to get the functionality. + */ + public void write_Context(Context context, ContextList contexts) + { + throw new NO_IMPLEMENT(); + } + + /** + * Read the CORBA object. The object is written 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.write_no_endian}. + * + * The null value is written as defined in OMG specification (zero length + * string, followed by an empty set of profiles). + */ + public void write_Object(org.omg.CORBA.Object x) + { + ORB w_orb = orb; + if (x instanceof IorProvider) + { + ((IorProvider) x).getIor()._write_no_endian(this); + return; + } + else if (x == null) + { + IOR.write_null(this); + return; + } + else if (x instanceof ObjectImpl) + { + Delegate d = ((ObjectImpl) x)._get_delegate(); + + if (d instanceof IorProvider) + { + ((IorProvider) d).getIor()._write_no_endian(this); + return; + } + else + { + ORB d_orb = d.orb(x); + if (d_orb != null) + w_orb = d_orb; + } + } + + // Either this is not an ObjectImpl or it has the + // unexpected delegate. Try to convert via ORBs + // object_to_string(). + if (w_orb != null) + { + IOR ior = IOR.parse(w_orb.object_to_string(x)); + ior._write_no_endian(this); + return; + } + else + throw new BAD_OPERATION( + "Please set the ORB for this stream, cannot write " + + x.getClass().getName()); + } + + /** + * Write the TypeCode. This implementation delegates functionality + * to {@link cdrTypeCode}. + * + * @param x a TypeCode to write. + */ + public void write_TypeCode(TypeCode x) + { + try + { + TypeCodeHelper.write(this, x); + } + catch (UserException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes an instance of the CORBA {@link Any}. + * This method writes the typecode, followed + * by value itself. In Any contains null + * (value not set), the {@link TCKind#tk_null} + * is written. + * + * @param x the {@link Any} to write. + */ + public void write_any(Any x) + { + Streamable value = x.extract_Streamable(); + if (value != null) + { + write_TypeCode(x.type()); + value._write(this); + } + else + { + PrimitiveTypeCode p = new PrimitiveTypeCode(TCKind.tk_null); + write_TypeCode(p); + } + } + + /** + * Writes a single byte, 0 for <code>false</code>, + * 1 for <code>true</code>. + * + * @param x the value to write + */ + public void write_boolean(boolean x) + { + try + { + b.write(x ? 1 : 0); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the boolean array. + * + * @param x array + * @param ofs offset + * @param len length. + */ + public void write_boolean_array(boolean[] x, int ofs, int len) + { + try + { + for (int i = ofs; i < ofs + len; i++) + { + b.write(x [ i ] ? 1 : 0); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the lower byte of the passed parameter. + * @param x the char to write + * + * It is effective to write more characters at once. + */ + public void write_char(char x) + { + try + { + if (narrow_native) + b.write(x); + else + { + OutputStreamWriter ow = + new OutputStreamWriter((OutputStream) b, narrow_charset); + ow.write(x); + ow.flush(); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the lower bytes of the passed array members. + * + * @param chars an array + * @param offset offset + * @param length length + */ + public void write_char_array(char[] chars, int offset, int length) + { + try + { + if (narrow_native) + { + for (int i = offset; i < offset + length; i++) + { + b.write(chars [ i ]); + } + } + else + { + OutputStreamWriter ow = + new OutputStreamWriter((OutputStream) b, narrow_charset); + ow.write(chars, offset, length); + ow.flush(); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the double value (IEEE 754 format). + */ + public void write_double(double x) + { + try + { + align(8); + b.writeDouble(x); + } + catch (Exception ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the array of double values. + */ + public void write_double_array(double[] x, int ofs, int len) + { + try + { + align(8); + for (int i = ofs; i < ofs + len; i++) + { + b.writeDouble(x [ i ]); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes CORBA fixed, storing all digits but not the scale. + * The end of the record on <code>fixed</code> can + * be determined from its last byte. + */ + public void write_fixed(BigDecimal fixed) + { + try + { + BigDecimalHelper.write(this, fixed); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + catch (BadKind ex) + { + Unexpected.error(ex); + } + } + + /** + * Write the float value (IEEE 754 format). + */ + public void write_float(float x) + { + try + { + align(4); + b.writeFloat(x); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes an array of the float values. + */ + public void write_float_array(float[] x, int ofs, int len) + { + try + { + align(4); + for (int i = ofs; i < ofs + len; i++) + { + b.writeFloat(x [ i ]); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the integer value (CORBA long, four bytes, high byte first). + * @param x the value to write. + */ + public void write_long(int x) + { + try + { + align(4); + b.writeInt(x); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the array of integer (CORBA long) values. + * + * @param x value + * @param ofs offset + * @param len length + */ + public void write_long_array(int[] x, int ofs, int len) + { + try + { + align(4); + for (int i = ofs; i < ofs + len; i++) + { + b.writeInt(x [ i ]); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the long (CORBA long long) value, 8 bytes, + * high byte first. + * + * @param x the value to write. + */ + public void write_longlong(long x) + { + try + { + align(8); + b.writeLong(x); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the array of longs (CORBA long longs) values. + * + * @param x value + * @param ofs offset + * @param len length + */ + public void write_longlong_array(long[] x, int ofs, int len) + { + try + { + align(8); + for (int i = ofs; i < ofs + len; i++) + { + b.writeLong(x [ i ]); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes this byte. + * @param x + */ + public void write_octet(byte x) + { + try + { + b.writeByte(x); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the array of bytes (CORBA octets) values. + * + * @param x value + * @param ofs offset + * @param len length + */ + public void write_octet_array(byte[] x, int ofs, int len) + { + try + { + b.write(x, ofs, len); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes first the size of array, and then the byte array using + * the {@link java.io.OutputStream#write(byte[]) }. The sequence + * being written is preceeded by the int, representing the array + * length. + */ + public void write_sequence(byte[] buf) + { + try + { + write_long(buf.length); + write(buf); + } + catch (IOException ex) + { + MARSHAL t = new MARSHAL(); + t.minor = Minor.CDR; + t.initCause(ex); + throw t; + } + } + + /** + * Writes the contents of the provided stream. + * The sequence being written is preceeded by the int, + * representing the stream buffer length (the number of + * bytes being subsequently written). + */ + public void write_sequence(BufferedCdrOutput from) + { + try + { + write_long(from.buffer.size()); + from.buffer.writeTo(this); + } + catch (IOException ex) + { + MARSHAL t = new MARSHAL(); + t.minor = Minor.CDR; + t.initCause(ex); + throw t; + } + } + + /** + * Writes the two byte integer (short), high byte first. + * + * @param x the integer to write. + */ + public void write_short(short x) + { + try + { + align(2); + b.writeShort(x); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the array of short (two byte integer) values. + * + * @param x value + * @param ofs offset + * @param len length + */ + public void write_short_array(short[] x, int ofs, int len) + { + try + { + align(2); + for (int i = ofs; i < ofs + len; i++) + { + b.writeShort(x [ i ]); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the string. This implementation first calls + * String.getBytes() and then writes the length of the returned + * array (as CORBA ulong) and the returned array itself. + * + * The encoding information, if previously set, is taken + * into consideration. + * + * @param x the string to write. + */ + public void write_string(String x) + { + try + { + byte[] ab = x.getBytes(narrow_charset); + write_long(ab.length + 1); + write(ab); + + // write null terminator. + write(0); + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the CORBA unsigned long in the same way as CORBA long. + */ + public void write_ulong(int x) + { + write_long(x); + } + + /** + * Writes the array of CORBA unsigned longs in the same way as + * array of ordinary longs. + */ + public void write_ulong_array(int[] x, int ofs, int len) + { + write_long_array(x, ofs, len); + } + + /** + * Write the unsigned long long in the same way as an ordinary long long. + * + * @param x a value to write. + */ + public void write_ulonglong(long x) + { + write_longlong(x); + } + + /** + * Write the array of unsingel long longs in the same way + * an an array of the ordinary long longs. + */ + public void write_ulonglong_array(long[] x, int ofs, int len) + { + write_longlong_array(x, ofs, len); + } + + /** + * Write the unsigned short in the same way as an ordinary short. + */ + public void write_ushort(short x) + { + write_short(x); + } + + /** + * Write an array of unsigned short integersin the same way + * as an array of ordinary short integers. + */ + public void write_ushort_array(short[] x, int ofs, int len) + { + write_short_array(x, ofs, len); + } + + /** + * Writes the character as two byte short integer (Unicode value), high byte + * first. Writes in Big Endian, but never writes the endian indicator. + * + * The character is always written using the native UTF-16BE charset because + * its size under arbitrary encoding is not evident. + */ + public void write_wchar(char x) + { + try + { + if (giop.until_inclusive(1, 1)) + { + align(2); + + if (wide_native) + b.writeShort(x); + else + { + OutputStreamWriter ow = new OutputStreamWriter( + (OutputStream) b, wide_charset); + ow.write(x); + ow.flush(); + } + } + else if (wide_native) + { + b.writeByte(2); + b.writeChar(x); + } + else + { + String encoded = new String(new char[] { x }); + byte[] bytes = encoded.getBytes(wide_charset); + b.write(bytes.length + 2); + b.write(bytes); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Write the array of wide chars. + * + * @param chars the array of wide chars + * @param offset offset + * @param length length + * + * The char array is always written using the native UTF-16BE charset because + * the character size under arbitrary encoding is not evident. + */ + public void write_wchar_array(char[] chars, int offset, int length) + { + try + { + if (giop.until_inclusive(1, 1)) + align(2); + + if (wide_native) + { + for (int i = offset; i < offset + length; i++) + { + b.writeShort(chars [ i ]); + } + } + else + { + OutputStreamWriter ow = + new OutputStreamWriter((OutputStream) b, wide_charset); + ow.write(chars, offset, length); + ow.flush(); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** + * Writes the length of the string in bytes (not characters) and + * then all characters as two byte unicode chars. Adds the + * Big Endian indicator, 0xFFFE, at the beginning and null wide char at + * the end. + * + * @param x the string to write. + */ + public void write_wstring(String x) + { + try + { + if (giop.since_inclusive(1, 2)) + { + byte[] bytes = x.getBytes(wide_charset); + write_sequence(bytes); + } + else + { + // Encoding with null terminator always in UTF-16. + // The wide null terminator needs extra two bytes. + write_long(2 * x.length() + 2); + + for (int i = 0; i < x.length(); i++) + { + b.writeShort(x.charAt(i)); + } + + // Write null terminator. + b.writeShort(0); + } + } + catch (IOException ex) + { + Unexpected.error(ex); + } + } + + /** {@inheritDoc} */ + public void write_any_array(Any[] anys, int offset, int length) + { + for (int i = offset; i < offset + length; i++) + { + write_any(anys [ i ]); + } + } + + public String[] _truncatable_ids() + { + /**@todo Implement this org.omg.CORBA.portable.ValueBase abstract method*/ + throw new java.lang.UnsupportedOperationException("Method _truncatable_ids() not yet implemented."); + } + + /** {@inheritDoc} */ + public void write_Abstract(java.lang.Object value) + { + write_abstract_interface(value); + } + + /** {@inheritDoc} */ + public void write_Value(Serializable value) + { + write_value(value); + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/AbstractDataInput.java b/libjava/classpath/gnu/CORBA/CDR/AbstractDataInput.java new file mode 100644 index 000000000..0ad98bed7 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/AbstractDataInput.java @@ -0,0 +1,392 @@ +/* AbstractDataInput.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 java.io.IOException; + +/** + * Some data input stream that can be either Big or + * Little Endian. + * + * This class reuses code from GNU Classpath DataInputStream. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + * @author Warren Levy (warrenl@cygnus.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public interface AbstractDataInput +{ + /** + * This method reads bytes from the underlying stream into the specified + * byte array buffer. It will attempt to fill the buffer completely, but + * may return a short count if there is insufficient data remaining to be + * read to fill the buffer. + * + * @param b The buffer into which bytes will be read. + * + * @return The actual number of bytes read, or -1 if end of stream reached + * before reading any bytes. + * + * @exception IOException If an error occurs. + */ + int read(byte[] b) + throws IOException; + + /** + * This method reads bytes from the underlying stream into the specified + * byte array buffer. It will attempt to read <code>len</code> bytes and + * will start storing them at position <code>off</code> into the buffer. + * This method can return a short count if there is insufficient data + * remaining to be read to complete the desired read length. + * + * @param b The buffer into which bytes will be read. + * @param off The offset into the buffer to start storing bytes. + * @param len The requested number of bytes to read. + * + * @return The actual number of bytes read, or -1 if end of stream reached + * before reading any bytes. + * + * @exception IOException If an error occurs. + */ + int read(byte[] b, int off, int len) + throws IOException; + + /** + * This method reads a Java boolean value from an input stream. It does + * so by reading a single byte of data. If that byte is zero, then the + * value returned is <code>false</code>. If the byte is non-zero, then + * the value returned is <code>true</code>. + * <p> + * This method can read a <code>boolean</code> written by an object + * implementing the <code>writeBoolean()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>boolean</code> value read + * + * @exception EOFException If end of file is reached before reading + * the boolean + * @exception IOException If any other error occurs + * + * @see DataOutput#writeBoolean + */ + boolean readBoolean() + throws IOException; + + /** + * This method reads a Java byte value from an input stream. The value + * is in the range of -128 to 127. + * <p> + * This method can read a <code>byte</code> written by an object + * implementing the <code>writeByte()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>byte</code> value read + * + * @exception EOFException If end of file is reached before reading the byte + * @exception IOException If any other error occurs + * + * @see DataOutput#writeByte + */ + byte readByte() + throws IOException; + + /** + * This method reads a Java <code>char</code> value from an input stream. + * It operates by reading two bytes from the stream and converting them to + * a single 16-bit Java <code>char</code>. The two bytes are stored most + * significant byte first (i.e., "big endian") regardless of the native + * host byte ordering. + * <p> + * As an example, if <code>byte1</code> and <code>byte2</code> + * represent the first and second byte read from the stream + * respectively, they will be transformed to a <code>char</code> in + * the following manner: + * <p> + * <code>(char)(((byte1 & 0xFF) << 8) | (byte2 & 0xFF)</code> + * <p> + * This method can read a <code>char</code> written by an object + * implementing the <code>writeChar()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>char</code> value read + * + * @exception EOFException If end of file is reached before reading the char + * @exception IOException If any other error occurs + * + * @see DataOutput#writeChar + */ + char readChar() + throws IOException; + + /** + * This method reads a Java double value from an input stream. It operates + * by first reading a <code>long</code> value from the stream by calling the + * <code>readLong()</code> method in this interface, then converts + * that <code>long</code> to a <code>double</code> using the + * <code>longBitsToDouble</code> method in the class + * <code>java.lang.Double</code> + * <p> + * This method can read a <code>double</code> written by an object + * implementing the <code>writeDouble()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>double</code> value read + * + * @exception EOFException If end of file is reached before reading + * the double + * @exception IOException If any other error occurs + * + * @see DataOutput#writeDouble + * @see java.lang.Double#longBitsToDouble + */ + double readDouble() + throws IOException; + + /** + * This method reads a Java float value from an input stream. It + * operates by first reading an <code>int</code> value from the + * stream by calling the <code>readInt()</code> method in this + * interface, then converts that <code>int</code> to a + * <code>float</code> using the <code>intBitsToFloat</code> method + * in the class <code>java.lang.Float</code> + * <p> + * This method can read a <code>float</code> written by an object + * implementing the <code>writeFloat()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>float</code> value read + * + * @exception EOFException If end of file is reached before reading the float + * @exception IOException If any other error occurs + * + * @see DataOutput#writeFloat + * @see java.lang.Float#intBitsToFloat + */ + float readFloat() + throws IOException; + + /** + * This method reads raw bytes into the passed array until the array is + * full. Note that this method blocks until the data is available and + * throws an exception if there is not enough data left in the stream to + * fill the buffer. Note also that zero length buffers are permitted. + * In this case, the method will return immediately without reading any + * bytes from the stream. + * + * @param b The buffer into which to read the data + * + * @exception EOFException If end of file is reached before filling the + * buffer + * @exception IOException If any other error occurs + */ + void readFully(byte[] b) + throws IOException; + + /** + * This method reads a Java <code>int</code> value from an input stream + * It operates by reading four bytes from the stream and converting them to + * a single Java <code>int</code>. The bytes are stored most + * significant byte first (i.e., "big endian") regardless of the native + * host byte ordering. + * <p> + * As an example, if <code>byte1</code> through <code>byte4</code> represent + * the first four bytes read from the stream, they will be + * transformed to an <code>int</code> in the following manner: + * <p> + * <code>(int)(((byte1 & 0xFF) << 24) + ((byte2 & 0xFF) << 16) + + * ((byte3 & 0xFF)<< 8) + (byte4 & 0xFF)))</code> + * <p> + * The value returned is in the range of -2147483648 to 2147483647. + * <p> + * This method can read an <code>int</code> written by an object + * implementing the <code>writeInt()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>int</code> value read + * + * @exception EOFException If end of file is reached before reading the int + * @exception IOException If any other error occurs + * + * @see DataOutput#writeInt + */ + int readInt() + throws IOException; + + /** + * This method reads a Java <code>long</code> value from an input stream + * It operates by reading eight bytes from the stream and converting them to + * a single Java <code>long</code>. The bytes are stored most + * significant byte first (i.e., "big endian") regardless of the native + * host byte ordering. + * <p> + * As an example, if <code>byte1</code> through <code>byte8</code> represent + * the first eight bytes read from the stream, they will be + * transformed to an <code>long</code> in the following manner: + * <p> + * <code>(long)(((byte1 & 0xFF) << 56) + ((byte2 & 0xFF) << 48) + + * ((byte3 & 0xFF) << 40) + ((byte4 & 0xFF) << 32) + + * ((byte5 & 0xFF) << 24) + ((byte6 & 0xFF) << 16) + + * ((byte7 & 0xFF) << 8) + (byte8 & 0xFF))) + * </code> + * <p> + * The value returned is in the range of -9223372036854775808 to + * 9223372036854775807. + * <p> + * This method can read an <code>long</code> written by an object + * implementing the <code>writeLong()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>long</code> value read + * + * @exception EOFException If end of file is reached before reading the long + * @exception IOException If any other error occurs + * + * @see DataOutput#writeLong + */ + long readLong() + throws IOException; + + /** + * This method reads a signed 16-bit value into a Java in from the + * stream. It operates by reading two bytes from the stream and + * converting them to a single 16-bit Java <code>short</code>. The + * two bytes are stored most significant byte first (i.e., "big + * endian") regardless of the native host byte ordering. + * <p> + * As an example, if <code>byte1</code> and <code>byte2</code> + * represent the first and second byte read from the stream + * respectively, they will be transformed to a <code>short</code>. in + * the following manner: + * <p> + * <code>(short)(((byte1 & 0xFF) << 8) | (byte2 & 0xFF))</code> + * <p> + * The value returned is in the range of -32768 to 32767. + * <p> + * This method can read a <code>short</code> written by an object + * implementing the <code>writeShort()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>short</code> value read + * + * @exception EOFException If end of file is reached before reading the value + * @exception IOException If any other error occurs + * + * @see DataOutput#writeShort + */ + short readShort() + throws IOException; + + /** + * This method reads 8 unsigned bits into a Java <code>int</code> + * value from the stream. The value returned is in the range of 0 to + * 255. + * <p> + * This method can read an unsigned byte written by an object + * implementing the <code>writeUnsignedByte()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The unsigned bytes value read as a Java <code>int</code>. + * + * @exception EOFException If end of file is reached before reading the value + * @exception IOException If any other error occurs + * + * @see DataOutput#writeByte + */ + int readUnsignedByte() + throws IOException; + + /** + * This method reads 16 unsigned bits into a Java int value from the stream. + * It operates by reading two bytes from the stream and converting them to + * a single Java <code>int</code> The two bytes are stored most + * significant byte first (i.e., "big endian") regardless of the native + * host byte ordering. + * <p> + * As an example, if <code>byte1</code> and <code>byte2</code> + * represent the first and second byte read from the stream + * respectively, they will be transformed to an <code>int</code> in + * the following manner: + * <p> + * <code>(int)(((byte1 & 0xFF) << 8) + (byte2 & 0xFF))</code> + * <p> + * The value returned is in the range of 0 to 65535. + * <p> + * This method can read an unsigned short written by an object + * implementing the <code>writeUnsignedShort()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The unsigned short value read as a Java <code>int</code> + * + * @exception EOFException If end of file is reached before reading the value + * @exception IOException If any other error occurs + * + * @see DataOutput#writeShort + */ + int readUnsignedShort() + throws IOException; + + /** + * Read a single byte. + * + * @return a byte, extracted from the stream or -1 if + * EOF has been reached. + * @throws IOException + */ + public int read() + throws IOException; + + /** + * This method attempts to skip and discard the specified number of bytes + * in the input stream. It may actually skip fewer bytes than requested. + * This method will not skip any bytes if passed a negative number of bytes + * to skip. + * + * @param n The requested number of bytes to skip. + * + * @return The requested number of bytes to skip. + * + * @exception IOException If an error occurs. + * @specnote The JDK docs claim that this returns the number of bytes + * actually skipped. The JCL claims that this method can throw an + * EOFException. Neither of these appear to be true in the JDK 1.3's + * implementation. This tries to implement the actual JDK behaviour. + */ + int skipBytes(int n) + throws IOException; +} diff --git a/libjava/classpath/gnu/CORBA/CDR/AbstractDataOutput.java b/libjava/classpath/gnu/CORBA/CDR/AbstractDataOutput.java new file mode 100644 index 000000000..e41ec598a --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/AbstractDataOutput.java @@ -0,0 +1,185 @@ +/* AbstractDataOutput.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 java.io.IOException; + +/** + * An abstract data output stream that could write data in either + * Big Endian or Little Endian format. + * + * This class reuses code from GNU Classpath DataOutputStream. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + * @author Warren Levy (warrenl@cygnus.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public interface AbstractDataOutput +{ + /** + * This method flushes any unwritten bytes to the underlying stream. + * + * @exception IOException If an error occurs. + */ + void flush() + throws IOException; + + /** + * This method writes the specified byte (passed as an <code>int</code>) + * to the underlying output stream. + * + * @param value The <code>byte</code> to write, passed as an <code>int</code>. + * + * @exception IOException If an error occurs. + */ + void write(int value) + throws IOException; + + /** + * This method writes <code>len</code> bytes from the specified byte array + * <code>buf</code> starting at position <code>offset</code> into the + * buffer to the underlying output stream. + * + * @param buf The byte array to write from. + * @param offset The index into the byte array to start writing from. + * @param len The number of bytes to write. + * + * @exception IOException If an error occurs. + */ + void write(byte[] buf, int offset, int len) + throws IOException; + + /** + * Write the complete byte array. + * @throws IOException + */ + void write(byte[] buf) + throws IOException; + + /** + * This method writes a Java boolean value to an output stream. If + * <code>value</code> is <code>true</code>, a byte with the value of + * 1 will be written, otherwise a byte with the value of 0 will be + * written. + * + * The value written can be read using the <code>readBoolean</code> + * method in <code>DataInput</code>. + * + * @param value The <code>boolean</code> value to write to the stream + * + * @exception IOException If an error occurs + */ + void writeBoolean(boolean value) + throws IOException; + + /** + * This method writes a Java byte value to an output stream. The + * byte to be written will be in the lowest 8 bits of the + * <code>int</code> value passed. + * + * The value written can be read using the <code>readByte</code> or + * <code>readUnsignedByte</code> methods in <code>DataInput</code>. + * + * @param value The <code>byte</code> to write to the stream, passed as + * the low eight bits of an <code>int</code>. + * + * @exception IOException If an error occurs + */ + void writeByte(int value) + throws IOException; + + /** + * This method writes a Java short value to an output stream. The + * char to be written will be in the lowest 16 bits of the <code>int</code> + * value passed. + * + * @exception IOException If an error occurs + */ + void writeShort(int value) + throws IOException; + + /** + * This method writes a Java char value to an output stream. The + * char to be written will be in the lowest 16 bits of the <code>int</code> + * value passed. + * + * @exception IOException If an error occurs + */ + void writeChar(int value) + throws IOException; + + /** + * This method writes a Java int value to an output stream. + * + * @param value The <code>int</code> value to write to the stream + * + * @exception IOException If an error occurs + */ + void writeInt(int value) + throws IOException; + + /** + * This method writes a Java long value to an output stream. + * + * @param value The <code>long</code> value to write to the stream + * + * @exception IOException If an error occurs + */ + void writeLong(long value) + throws IOException; + + /** + * This method writes a Java <code>float</code> value to the stream. + * @param value The <code>float</code> value to write to the stream + * + * @exception IOException If an error occurs + */ + void writeFloat(float value) + throws IOException; + + /** + * This method writes a Java <code>double</code> value to the stream. + * + * @param value The <code>double</code> value to write to the stream + * + * @exception IOException If an error occurs + */ + void writeDouble(double value) + throws IOException; +} diff --git a/libjava/classpath/gnu/CORBA/CDR/AligningInput.java b/libjava/classpath/gnu/CORBA/CDR/AligningInput.java new file mode 100644 index 000000000..8d438ab06 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/AligningInput.java @@ -0,0 +1,131 @@ +/* AligningInput.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 java.io.ByteArrayInputStream; + +import org.omg.CORBA.BAD_PARAM; + +/** + * The input stream with the possibility to align on the + * word (arbitrary size) boundary. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class AligningInput + extends ByteArrayInputStream +{ + /** + * The alignment offset. + */ + private int offset = 0; + + /** + * Create a stream, reading form the given buffer. + * + * @param a_buffer a buffer to read from. + */ + public AligningInput(byte[] a_buffer) + { + super(a_buffer); + } + + /** + * Set the alignment offset, if the index of the first byte in the + * stream is different from 0. + */ + public void setOffset(int an_offset) + { + offset = an_offset; + } + + /** + * Skip several bytes, aligning the internal pointer on the + * selected boundary. + * + * @throws BAD_PARAM, minor code 0, the alignment is not possible, + * usually due the wrong parameter value. + */ + public void align(int alignment) + { + try + { + int d = (pos + offset) % alignment; + if (d > 0) + { + skip(alignment - d); + } + } + catch (Exception ex) + { + BAD_PARAM p = new BAD_PARAM("Unable to align at " + alignment); + p.initCause(ex); + throw p; + } + } + + /** + * Get the byte buffer, from where the data are read. + */ + public byte[] getBuffer() + { + return buf; + } + + /** + * Get the current position in the buffer. + * + * @return The position in the buffer, taking offset into consideration. + */ + public int getPosition() + { + return pos + offset; + } + + /** + * Jump to the given position, taking offset into consideration. + */ + public void seek(int position) + { + if (position < offset || position > (count+offset)) + throw new ArrayIndexOutOfBoundsException(position + + " is out of valid ["+offset+".." + (count+offset) + "[ range"); + pos = position - offset; + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/AligningOutput.java b/libjava/classpath/gnu/CORBA/CDR/AligningOutput.java new file mode 100644 index 000000000..b0c569ec8 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/AligningOutput.java @@ -0,0 +1,148 @@ +/* AligningOutput.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 java.io.ByteArrayOutputStream; + +import org.omg.CORBA.BAD_PARAM; + +/** + * The input stream with the possibility to align on the + * word (arbitrary size) boundary. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class AligningOutput + extends ByteArrayOutputStream +{ + /** + * The alignment offset. + */ + private int offset = 0; + + /** + * Create a stream with the default intial buffer size. + */ + public AligningOutput() + { + } + + /** + * Create a stream with the given intial buffer size. + */ + public AligningOutput(int initial_size) + { + super(initial_size); + } + + /** + * Set the alignment offset, if the index of the first byte in the + * stream is different from 0. + */ + public void setOffset(int an_offset) + { + offset = an_offset; + } + + /** + * Skip several bytes, aligning the internal pointer on the + * selected boundary. + * + * @throws BAD_PARAM, minor code 0, the alignment is not possible, + * usually due the wrong parameter value. + */ + public void align(int alignment) + { + try + { + int d = (count + offset) % alignment; + if (d > 0) + { + skip(alignment - d); + } + } + catch (Exception ex) + { + BAD_PARAM p = new BAD_PARAM("Unable to align at " + alignment); + p.initCause(ex); + throw p; + } + } + + /** + * Write the specified number of zero bytes. + * + * @param bytes the number of zero bytes to write. + */ + public void skip(int bytes) + { + for (int i = 0; i < bytes; i++) + { + write(0); + } + } + + /** + * Get the current position in the buffer. + * + * @return The position in the buffer, taking offset into consideration. + */ + public int getPosition() + { + return size()+offset; + } + + /** + * Seek to the given position (not in use). + */ + public void seek(int position) + { + count = position - offset; + } + + /** + * Get the buffer without copying it. Use with care. + */ + public byte[] getBuffer() + { + return buf; + } + + +} diff --git a/libjava/classpath/gnu/CORBA/CDR/ArrayValueHelper.java b/libjava/classpath/gnu/CORBA/CDR/ArrayValueHelper.java new file mode 100644 index 000000000..0578f13b8 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/ArrayValueHelper.java @@ -0,0 +1,254 @@ +/* ArrayValueHelper.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.ObjectCreator; + +import org.omg.CORBA.BooleanSeqHelper; +import org.omg.CORBA.CharSeqHelper; +import org.omg.CORBA.DoubleSeqHelper; +import org.omg.CORBA.FloatSeqHelper; +import org.omg.CORBA.LongLongSeqHelper; +import org.omg.CORBA.LongSeqHelper; +import org.omg.CORBA.OctetSeqHelper; +import org.omg.CORBA.ShortSeqHelper; +import org.omg.CORBA.portable.BoxedValueHelper; +import org.omg.CORBA.portable.InputStream; +import org.omg.CORBA.portable.OutputStream; + +import java.io.Serializable; +import java.lang.reflect.Array; +import java.rmi.Remote; + +import javax.rmi.CORBA.Util; +import javax.rmi.CORBA.ValueHandler; + +/** + * Writes arrays as a boxed value types. A single instance is used to write a + * single array. This class is only used with RMI/IIOP, to handle array boxed + * values. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +class ArrayValueHelper + implements BoxedValueHelper +{ + /** + * The value handler (one for all instances). + */ + static ValueHandler handler = Util.createValueHandler(); + + /** + * A class of the array being written. + */ + Class arrayClass; + + /** + * The array component class. + */ + Class component; + + /** + * The array component repository Id. + */ + String componentId; + + /** + * If true, the array members are written as objects rather than as values. + * True for Remotes and CORBA objects. + */ + boolean written_as_object() + { + return org.omg.CORBA.Object.class.isAssignableFrom(component) + || Remote.class.isAssignableFrom(component); + } + + /** + * Creates the instance of the helper to write this specific array class. + */ + ArrayValueHelper(Class an_arrayClass) + { + arrayClass = an_arrayClass; + } + + /** + * Get the array repository Id that will be the RMI repository id. + */ + public String get_id() + { + return ObjectCreator.getRepositoryId(arrayClass); + } + + /** + * Read the array from the input stream. + */ + public Serializable read_value(InputStream input) + { + if (input instanceof HeadlessInput) + { + ((HeadlessInput) input).subsequentCalls = true; + } + + component = arrayClass.getComponentType(); + + if (component.equals(byte.class)) + return OctetSeqHelper.read(input); + else if (component.equals(String.class)) + { + // String array is optimized because this may be frequent. + String[] s = new String[input.read_long()]; + + for (int i = 0; i < s.length; i++) + s[i] = (String) Vio.read(input, Vio.m_StringValueHelper); + return s; + } + else if (component.equals(int.class)) + return LongSeqHelper.read(input); + else if (component.equals(long.class)) + return LongLongSeqHelper.read(input); + else if (component.equals(double.class)) + return DoubleSeqHelper.read(input); + else if (component.equals(float.class)) + return FloatSeqHelper.read(input); + else if (component.equals(boolean.class)) + return BooleanSeqHelper.read(input); + else if (component.equals(short.class)) + return ShortSeqHelper.read(input); + else if (component.equals(char.class)) + return CharSeqHelper.read(input); + else + { + // Read others, use reflection. + int n = input.read_long(); + + gnuValueStream s = null; + + Serializable array = (Serializable) Array.newInstance(component, n); + if (written_as_object()) + for (int i = 0; i < n; i++) + { + gnuRuntime g; + int position; + if (input instanceof gnuValueStream) + { + s = (gnuValueStream) input; + g = s.getRunTime(); + position = s.getPosition(); + } + else + { + g = null; + position = -1; + } + + if (input instanceof HeadlessInput) + ((HeadlessInput) input).subsequentCalls = true; + + Object o = handler.readValue(input, position, component, null, g); + Array.set(array, i, o); + } + else + for (int i = 0; i < n; i++) + Array.set(array, i, Vio.read(input, component)); + return array; + } + } + + /** + * Write the array to the input stream. + */ + public void write_value(OutputStream output, Serializable value) + { + if (output instanceof gnuValueStream) + { + gnuRuntime r = ((gnuValueStream) output).getRunTime(); + if (r != null) + r.target = null; + } + + if (value instanceof byte[]) + OctetSeqHelper.write(output, (byte[]) value); + else if (value instanceof String[]) + { + String[] s = (String[]) value; + output.write_long(s.length); + for (int i = 0; i < s.length; i++) + Vio.write(output, s[i], Vio.m_StringValueHelper); + } + else if (value instanceof int[]) + LongSeqHelper.write(output, (int[]) value); + else if (value instanceof long[]) + LongLongSeqHelper.write(output, (long[]) value); + else if (value instanceof double[]) + DoubleSeqHelper.write(output, (double[]) value); + else if (value instanceof float[]) + FloatSeqHelper.write(output, (float[]) value); + else if (value instanceof boolean[]) + BooleanSeqHelper.write(output, (boolean[]) value); + else if (value instanceof short[]) + ShortSeqHelper.write(output, (short[]) value); + else if (value instanceof char[]) + CharSeqHelper.write(output, (char[]) value); + else + { + // Write others, use reflection. + component = arrayClass.getComponentType(); + + int n = Array.getLength(value); + output.write_long(n); + if (written_as_object()) + for (int i = 0; i < n; i++) + { + Object o = Array.get(value, i); + if (o == null) + output.write_Object(null); + else + // CORBA objects have another notation. + handler.writeValue(output, (Serializable) o); + } + else + { + for (int i = 0; i < n; i++) + Vio.write(output, (Serializable) Array.get(value, i), + component); + } + + } + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/BigEndianInputStream.java b/libjava/classpath/gnu/CORBA/CDR/BigEndianInputStream.java new file mode 100644 index 000000000..5579789a5 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/BigEndianInputStream.java @@ -0,0 +1,61 @@ +/* BigEndianInputStream.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 java.io.DataInputStream; +import java.io.InputStream; + +/** + * As java uses Big Endian by default, this class is directly derived + * form DataInputStream. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class BigEndianInputStream + extends DataInputStream + implements AbstractDataInput +{ + /** + * Delegates to the parent constructor. + */ + public BigEndianInputStream(InputStream in) + { + super(in); + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/BigEndianOutputStream.java b/libjava/classpath/gnu/CORBA/CDR/BigEndianOutputStream.java new file mode 100644 index 000000000..dda14a03a --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/BigEndianOutputStream.java @@ -0,0 +1,62 @@ +/* BigEndianOutputStream.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 java.io.DataOutputStream; +import java.io.OutputStream; + +/** + * A stream to read the data in Big Endian format. This class is + * directly derived from DataOutputStream that uses the Big + * Endian. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class BigEndianOutputStream + extends DataOutputStream + implements AbstractDataOutput +{ + /** + * Delegate functionality to the parent constructor. + */ + public BigEndianOutputStream(OutputStream out) + { + super(out); + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/BufferedCdrOutput.java b/libjava/classpath/gnu/CORBA/CDR/BufferedCdrOutput.java new file mode 100644 index 000000000..ae510b39c --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/BufferedCdrOutput.java @@ -0,0 +1,156 @@ +/* BufferedCdrOutput.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 java.io.ByteArrayOutputStream; + +/** + * A CORBA output stream, writing data into the internal buffer ({@link ByteArrayOutputStream}). + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class BufferedCdrOutput + extends AbstractCdrOutput + implements gnuValueStream +{ + /** + * Use serialVersionUID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * The byte buffer. + */ + public final AligningOutput buffer; + + /** + * Creates the instance with the given initial buffer size. + * + * @param bufSize the buffer size. + */ + public BufferedCdrOutput(int bufSize) + { + buffer = new AligningOutput(bufSize); + setOutputStream(buffer); + } + + /** + * Creates the instance with the default buffer size. + */ + public BufferedCdrOutput() + { + buffer = new AligningOutput(); + setOutputStream(buffer); + } + + /** + * Set the alignment offset, if the index of the first byte in the stream is + * different from 0. + */ + public void setOffset(int an_offset) + { + buffer.setOffset(an_offset); + } + + /** + * Align the curretn position at the given natural boundary. + */ + public void align(int boundary) + { + buffer.align(boundary); + } + + /** + * Return the input stream that reads the previously written values. + */ + public org.omg.CORBA.portable.InputStream create_input_stream() + { + BufferredCdrInput in = new BufferredCdrInput(buffer.toByteArray()); + in.setOrb(orb); + + in.setVersion(giop); + in.setCodeSet(getCodeSet()); + + return in; + } + + /** + * Resets (clears) the buffer. + */ + public void reset() + { + buffer.reset(); + setOutputStream(buffer); + } + + /** + * Get the current position in the buffer. + * + * @return The position in the buffer, taking offset into consideration. + */ + public int getPosition() + { + return buffer.getPosition(); + } + + /** + * Get the associated RunTime. + */ + public gnuRuntime getRunTime() + { + return runtime; + } + + /** + * Replace the instance of RunTime. + */ + public void setRunTime(gnuRuntime a_runtime) + { + runtime = a_runtime; + } + + /** + * Seek to the given position. + */ + public void seek(int position) + { + buffer.seek(position); + } + +} diff --git a/libjava/classpath/gnu/CORBA/CDR/BufferredCdrInput.java b/libjava/classpath/gnu/CORBA/CDR/BufferredCdrInput.java new file mode 100644 index 000000000..accb65a0d --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/BufferredCdrInput.java @@ -0,0 +1,153 @@ +/* BufferredCdrInput.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; + + +/** + * The CDR input stream that reads data from the byte buffer. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class BufferredCdrInput + extends AbstractCdrInput + implements gnuValueStream +{ + /** + * Use serialVersionUID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * The byte array input stream to read data from. + */ + public final AligningInput buffer; + + /** + * Creates the CDR input stream that reads from the given buffer + * array. + * + * @param a_buffer an array to read from. + */ + public BufferredCdrInput(byte[] a_buffer) + { + buffer = new AligningInput(a_buffer); + setInputStream(buffer); + } + + /** + * Set the alignment offset, if the index of the first byte in the + * stream is different from 0. + */ + public void setOffset(int offset) + { + buffer.setOffset(offset); + } + + /** + * Skip several bytes, aligning the internal pointer on the + * selected boundary. + */ + public void align(int alignment) + { + buffer.align(alignment); + } + + /** + * Mark the current position. + * @param ahead + */ + public synchronized void mark(int ahead) + { + buffer.mark(ahead); + } + + /** + * Checks if marking is supported. + * @return + */ + public boolean markSupported() + { + return buffer.markSupported(); + } + + /** + * Resets the stream to the previously marked position. + */ + public void reset() + { + buffer.reset(); + setInputStream(buffer); + } + + /** + * Get the current position in the buffer. + * + * @return The position in the buffer, taking offset into consideration. + */ + public int getPosition() + { + return buffer.getPosition(); + } + + /** + * Jump to the given position, taking offset into consideration. + */ + public void seek(int position) + { + buffer.seek(position); + setInputStream(buffer); + } + + /** + * Get the associated RunTime. + */ + public gnuRuntime getRunTime() + { + return runtime; + } + + /** + * Replace the instance of RunTime. + */ + public void setRunTime(gnuRuntime a_runtime) + { + runtime = a_runtime; + } + +} diff --git a/libjava/classpath/gnu/CORBA/CDR/EncapsulationStream.java b/libjava/classpath/gnu/CORBA/CDR/EncapsulationStream.java new file mode 100644 index 000000000..e42991232 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/EncapsulationStream.java @@ -0,0 +1,147 @@ +/* EncapsulationOutput.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 java.io.IOException; + +/** + * The encapsulated data, as they are defined by CORBA specification. + * This includes the extra 0 byte (Big endian) in the beginning. + * When written to the parent steam, the encapsulated data are preceeded + * by the data length in bytes. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class EncapsulationStream + extends AbstractCdrOutput +{ + /** + * The Big Endian (most siginificant byte first flag). + */ + public static final byte BIG_ENDIAN = 0; + + /** + * The Little Endian (least siginificant byte first flag). + */ + public static final byte LITTLE_ENDIAN = 1; + + /** + * The byte buffer. + */ + public final AligningOutput buffer; + + /** + * The stream, where the data are being encapsulated. + */ + public final org.omg.CORBA.portable.OutputStream parent; + + /** + * Create the EncapsulationOutput with the given parent stream + * and the specified encoding. + */ + public EncapsulationStream(org.omg.CORBA.portable.OutputStream _parent, + boolean use_big_endian) + { + super(); + setBigEndian(use_big_endian); + buffer = new AligningOutput(); + setOutputStream(buffer); + parent = _parent; + write(use_big_endian?BIG_ENDIAN:LITTLE_ENDIAN); + } + + /** + * Set the alignment offset, if the index of the first byte in the + * stream is different from 0. + */ + public void setOffset(int an_offset) + { + buffer.setOffset(an_offset); + } + + /** + * Align the curretn position at the given natural boundary. + */ + public void align(int boundary) + { + buffer.align(boundary); + } + + /** + * Writes the content of the encapsulated output into the parent + * buffer. + */ + public void close() + { + try + { + parent.write_long(buffer.size()); + buffer.writeTo(parent); + } + catch (IOException ex) + { + InternalError err = new InternalError(); + err.initCause(ex); + throw err; + } + } + + /** + * Return the input stream that reads the previously written values. + */ + public org.omg.CORBA.portable.InputStream create_input_stream() + { + BufferredCdrInput in = new BufferredCdrInput(buffer.toByteArray()); + in.setOrb(orb); + + in.setVersion(giop); + in.setCodeSet(getCodeSet()); + + return in; + } + + /** + * Resets (clears) the buffer. + */ + public void reset() + { + buffer.reset(); + setOutputStream(buffer); + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/HeadlessInput.java b/libjava/classpath/gnu/CORBA/CDR/HeadlessInput.java new file mode 100644 index 000000000..5e97c73b8 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/HeadlessInput.java @@ -0,0 +1,749 @@ +/* HeadlessInput.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.Minor; + +import org.omg.CORBA.Any; +import org.omg.CORBA.AnySeqHolder; +import org.omg.CORBA.BooleanSeqHolder; +import org.omg.CORBA.CharSeqHolder; +import org.omg.CORBA.Context; +import org.omg.CORBA.DataInputStream; +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.Principal; +import org.omg.CORBA.ShortSeqHolder; +import org.omg.CORBA.TypeCode; +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.BoxedValueHelper; +import org.omg.CORBA.portable.InputStream; + +import java.io.IOException; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * Substitutes the main stream in factories when the header is already behind. + * Overrides methods that may be invoked from the factory, forcing not to read + * the header if called first time on this stream. + * + * This stream reverts to default behavior if one or more call are made (reading + * value types that are nested fields of the value type). + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class HeadlessInput + extends org.omg.CORBA_2_3.portable.InputStream + implements DataInputStream, gnuValueStream +{ + /** + * Use serialVersionUID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * Indicates that no positional information is available. + */ + static final int NONE = -1; + + /** + * If true, this is not the first call. + */ + public boolean subsequentCalls; + + /** + * The enclosed stream. + */ + final BufferredCdrInput stream; + + /** + * Create an instance, reading from the given buffer. + * + * @param a_stream a stream from where the data will be read. + * @param inheritSettings a stream from that endian and other settings are + * inherited. + */ + public HeadlessInput(BufferredCdrInput a_stream, InputStream inheritSettings) + { + stream = a_stream; + + if (inheritSettings instanceof AbstractCdrInput) + { + AbstractCdrInput t = (AbstractCdrInput) inheritSettings; + t.cloneSettings(stream); + } + else if (stream.orb() == null) + stream.setOrb(inheritSettings.orb()); + + if (inheritSettings instanceof gnuValueStream + && stream.getRunTime() == null) + { + stream.setRunTime(((gnuValueStream) inheritSettings).getRunTime()); + } + } + + /** + * Tries to read using boxed value helper. + */ + public Serializable read_value(BoxedValueHelper helper) + { + if (subsequentCalls) + return stream.read_value(helper); + else + { + subsequentCalls = true; + return helper.read_value(this); + } + } + + /** + * Tries to locate a factory using repository id. + */ + public Serializable read_value(String repository_id) + { + if (subsequentCalls) + return stream.read_value(repository_id); + else + { + subsequentCalls = true; + Serializable value = Vio.readValue(this, NONE, null, + null, repository_id, null, null); + return value; + } + } + + /** + * Try to read when having an unitialised value. + */ + public Serializable read_value(Serializable value) + { + if (subsequentCalls) + return stream.read_value(value); + else + { + subsequentCalls = true; + value = Vio.readValue(this, NONE, value, null, null, + null, null); + return value; + } + } + + /** + * Try to read when having an unitialised value. + */ + public Serializable read_value(Class clz) + { + if (subsequentCalls) + return stream.read_value(clz); + else + { + try + { + subsequentCalls = true; + Serializable value = (Serializable) Vio.instantiateAnyWay(clz); + value = Vio.readValue(this, NONE, value, null, null, + null, null); + return value; + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("Can't read an instance of " + + clz.getName()); + m.minor = Minor.Value; + m.initCause(ex); + throw m; + } + } + } + + /** + * Delegates functionality to the underlying stream. + */ + public int available() + throws IOException + { + return stream.available(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void close() + throws IOException + { + stream.close(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void mark(int readlimit) + { + stream.mark(readlimit); + } + + /** + * Delegates functionality to the underlying stream. + */ + public boolean markSupported() + { + return stream.markSupported(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public ORB orb() + { + return stream.orb(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public Object read_abstract_interface() + { + return stream.read_abstract_interface(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public Object read_abstract_interface(Class clz) + { + return stream.read_abstract_interface(clz); + } + + /** + * Delegates functionality to the underlying stream. + */ + public Any read_any() + { + return stream.read_any(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_boolean_array(boolean[] value, int offset, int length) + { + stream.read_boolean_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public boolean read_boolean() + { + return stream.read_boolean(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_char_array(char[] value, int offset, int length) + { + stream.read_char_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public char read_char() + { + return stream.read_char(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public Context read_Context() + { + return stream.read_Context(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_double_array(double[] value, int offset, int length) + { + stream.read_double_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public double read_double() + { + return stream.read_double(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public BigDecimal read_fixed() + { + return stream.read_fixed(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_float_array(float[] value, int offset, int length) + { + stream.read_float_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public float read_float() + { + return stream.read_float(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_long_array(int[] value, int offset, int length) + { + stream.read_long_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public int read_long() + { + return stream.read_long(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_longlong_array(long[] value, int offset, int length) + { + stream.read_longlong_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public long read_longlong() + { + return stream.read_longlong(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public org.omg.CORBA.Object read_Object() + { + return stream.read_Object(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public org.omg.CORBA.Object read_Object(Class klass) + { + return stream.read_Object(klass); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_octet_array(byte[] value, int offset, int length) + { + stream.read_octet_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public byte read_octet() + { + return stream.read_octet(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public Principal read_Principal() + { + return stream.read_Principal(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_short_array(short[] value, int offset, int length) + { + stream.read_short_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public short read_short() + { + return stream.read_short(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public String read_string() + { + return stream.read_string(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public TypeCode read_TypeCode() + { + return stream.read_TypeCode(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_ulong_array(int[] value, int offset, int length) + { + stream.read_ulong_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public int read_ulong() + { + return stream.read_ulong(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_ulonglong_array(long[] value, int offset, int length) + { + stream.read_ulonglong_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public long read_ulonglong() + { + return stream.read_ulonglong(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_ushort_array(short[] value, int offset, int length) + { + stream.read_ushort_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public short read_ushort() + { + return stream.read_ushort(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public Serializable read_value() + { + return read_value((Serializable) null); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_wchar_array(char[] value, int offset, int length) + { + stream.read_wchar_array(value, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public char read_wchar() + { + return stream.read_wchar(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public String read_wstring() + { + return stream.read_wstring(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public int read() + throws IOException + { + return stream.read(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public int read(byte[] b, int off, int len) + throws IOException + { + return stream.read(b, off, len); + } + + /** + * Delegates functionality to the underlying stream. + */ + public int read(byte[] b) + throws IOException + { + return stream.read(b); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void reset() + throws IOException + { + stream.reset(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public long skip(long n) + throws IOException + { + return stream.skip(n); + } + + /** + * Get a string representation. + */ + public String toString() + { + return "HeadlessInput+" + stream.toString(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public String[] _truncatable_ids() + { + return stream._truncatable_ids(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public Object read_Abstract() + { + return stream.read_Abstract(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_any_array(AnySeqHolder holder, int offset, int length) + { + stream.read_any_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_boolean_array(BooleanSeqHolder holder, int offset, int length) + { + stream.read_boolean_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_char_array(CharSeqHolder holder, int offset, int length) + { + stream.read_char_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_double_array(DoubleSeqHolder holder, int offset, int length) + { + stream.read_double_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_float_array(FloatSeqHolder holder, int offset, int length) + { + stream.read_float_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_long_array(LongSeqHolder holder, int offset, int length) + { + stream.read_long_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_longlong_array(LongLongSeqHolder holder, int offset, + int length) + { + stream.read_longlong_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_octet_array(OctetSeqHolder holder, int offset, int length) + { + stream.read_octet_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_short_array(ShortSeqHolder holder, int offset, int length) + { + stream.read_short_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_ulong_array(ULongSeqHolder holder, int offset, int length) + { + stream.read_ulong_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_ulonglong_array(ULongLongSeqHolder holder, int offset, + int length) + { + stream.read_ulonglong_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_ushort_array(UShortSeqHolder holder, int offset, int length) + { + stream.read_ushort_array(holder, offset, length); + } + + /** + * Delegates functionality to read_value. + */ + public Serializable read_Value() + { + return read_value(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public void read_wchar_array(WCharSeqHolder holder, int offset, int length) + { + stream.read_wchar_array(holder, offset, length); + } + + /** + * Delegates functionality to the underlying stream. + */ + public int getPosition() + { + return stream.getPosition(); + } + + /** + * Delegates functionality to the underlying stream. + */ + public gnuRuntime getRunTime() + { + return stream.runtime; + } + + /** + * Replace the instance of RunTime. + */ + public void setRunTime(gnuRuntime a_runtime) + { + stream.runtime = a_runtime; + } + + /** + * Delegates functionality to the underlying stream. + */ + public void seek(int position) + { + stream.seek(position); + } + +} diff --git a/libjava/classpath/gnu/CORBA/CDR/IDLTypeHelper.java b/libjava/classpath/gnu/CORBA/CDR/IDLTypeHelper.java new file mode 100644 index 000000000..663e04196 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/IDLTypeHelper.java @@ -0,0 +1,169 @@ +/* IDLTypeHelper.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.Minor; + +import org.omg.CORBA.MARSHAL; +import org.omg.CORBA.portable.BoxedValueHelper; +import org.omg.CORBA.portable.InputStream; +import org.omg.CORBA.portable.OutputStream; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +/** + * Handles case when the CORBA IDL type with the known helper is wrapped into + * Value type. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class IDLTypeHelper + implements BoxedValueHelper +{ + /** + * A helper class. + */ + protected Class helper; + + /** + * Argument values for Helper.id(). + */ + static final Object[] ARGS_ID_V = new Object[0]; + + /** + * Argument types for Helper.id()). + */ + static final Class[] ARGS_ID = new Class[0]; + + /** + * Argument types for Helper.read. + */ + static final Class[] ARGS_READ = new Class[] { org.omg.CORBA.portable.InputStream.class }; + + /** + * Create an IDLTypeHelper that works via given helper class. + */ + public IDLTypeHelper(Class a_helperClass) + { + helper = a_helperClass; + } + + /** + * Get the Id, returned by this helper (use reflection). + */ + public String get_id() + { + try + { + Method m = helper.getMethod("id", ARGS_ID); + return (String) m.invoke(null, ARGS_ID_V); + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL(msg() + " id()"); + m.minor = Minor.Boxed; + m.initCause(ex); + throw m; + } + } + + /** + * Read an instance from the stream. + */ + public Serializable read_value(InputStream input) + { + try + { + Method m = helper.getMethod("read", ARGS_READ); + return (Serializable) m.invoke(null, new Object[] { input }); + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL(msg() + " read(..)"); + m.minor = Minor.Boxed; + m.initCause(ex); + throw m; + } + } + + /** + * Write the instance to the stream. + */ + public void write_value(OutputStream output, Serializable value) + { + try + { + Method[] m = helper.getMethods(); + + for (int i = 0; i < m.length; i++) + { + if (m[i].getName().equals("write") + && ((m[i].getModifiers() & Modifier.STATIC) != 0)) + { + Class[] p = m[i].getParameterTypes(); + + if (p.length == 2 && OutputStream.class.isAssignableFrom(p[0]) + && p[1].isAssignableFrom(value.getClass())) + { + m[i].invoke(null, new Object[] { output, value }); + return; + } + } + } + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL(msg() + " write(..)"); + m.minor = Minor.Boxed; + m.initCause(ex); + throw m; + } + } + + /** + * Create the start of message for exceptions. + */ + String msg() + { + return "Failed calling " + helper.getName() + " method: "; + } + +} diff --git a/libjava/classpath/gnu/CORBA/CDR/LittleEndianInputStream.java b/libjava/classpath/gnu/CORBA/CDR/LittleEndianInputStream.java new file mode 100644 index 000000000..93d18fb11 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/LittleEndianInputStream.java @@ -0,0 +1,634 @@ +/* LittleEndianInputStream.java -- + Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation + +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.java.lang.CPStringBuilder; + +import java.io.EOFException; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; + +/** + * This class reads data in the Little Endian format. It reuses + * code from GNU Classpath DataInputStream. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + * @author Warren Levy (warrenl@cygnus.com) + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class LittleEndianInputStream + extends FilterInputStream + implements AbstractDataInput +{ + // Byte buffer, used to make primitive read calls more efficient. + byte[] buf = new byte[ 8 ]; + + /** + * This constructor initializes a new <code>DataInputStream</code> + * to read from the specified subordinate stream. + * + * @param in The subordinate <code>InputStream</code> to read from + */ + public LittleEndianInputStream(InputStream in) + { + super(in); + } + + /** + * This method reads bytes from the underlying stream into the specified + * byte array buffer. It will attempt to fill the buffer completely, but + * may return a short count if there is insufficient data remaining to be + * read to fill the buffer. + * + * @param b The buffer into which bytes will be read. + * + * @return The actual number of bytes read, or -1 if end of stream reached + * before reading any bytes. + * + * @exception IOException If an error occurs. + */ + public int read(byte[] b) + throws IOException + { + return in.read(b, 0, b.length); + } + + /** + * This method reads bytes from the underlying stream into the specified + * byte array buffer. It will attempt to read <code>len</code> bytes and + * will start storing them at position <code>off</code> into the buffer. + * This method can return a short count if there is insufficient data + * remaining to be read to complete the desired read length. + * + * @param b The buffer into which bytes will be read. + * @param off The offset into the buffer to start storing bytes. + * @param len The requested number of bytes to read. + * + * @return The actual number of bytes read, or -1 if end of stream reached + * before reading any bytes. + * + * @exception IOException If an error occurs. + */ + public int read(byte[] b, int off, int len) + throws IOException + { + return in.read(b, off, len); + } + + /** + * This method reads a Java boolean value from an input stream. It does + * so by reading a single byte of data. If that byte is zero, then the + * value returned is <code>false</code>. If the byte is non-zero, then + * the value returned is <code>true</code>. + * <p> + * This method can read a <code>boolean</code> written by an object + * implementing the <code>writeBoolean()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>boolean</code> value read + * + * @exception EOFException If end of file is reached before reading + * the boolean + * @exception IOException If any other error occurs + * + * @see DataOutput#writeBoolean + */ + public boolean readBoolean() + throws IOException + { + return convertToBoolean(in.read()); + } + + /** + * This method reads a Java byte value from an input stream. The value + * is in the range of -128 to 127. + * <p> + * This method can read a <code>byte</code> written by an object + * implementing the <code>writeByte()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>byte</code> value read + * + * @exception EOFException If end of file is reached before reading the byte + * @exception IOException If any other error occurs + * + * @see DataOutput#writeByte + */ + public byte readByte() + throws IOException + { + return convertToByte(in.read()); + } + + /** + * This method reads a Java <code>char</code> value from an input stream. + * It operates by reading two bytes from the stream and converting them to + * a single 16-bit Java <code>char</code>. The two bytes are stored most + * significant byte first (i.e., "big endian") regardless of the native + * host byte ordering. + * <p> + * As an example, if <code>byte1</code> and <code>byte2</code> + * represent the first and second byte read from the stream + * respectively, they will be transformed to a <code>char</code> in + * the following manner: + * <p> + * <code>(char)(((byte1 & 0xFF) << 8) | (byte2 & 0xFF)</code> + * <p> + * This method can read a <code>char</code> written by an object + * implementing the <code>writeChar()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>char</code> value read + * + * @exception EOFException If end of file is reached before reading the char + * @exception IOException If any other error occurs + * + * @see DataOutput#writeChar + */ + public char readChar() + throws IOException + { + readFully(buf, 0, 2); + return convertToChar(buf); + } + + /** + * This method reads a Java double value from an input stream. It operates + * by first reading a <code>long</code> value from the stream by calling the + * <code>readLong()</code> method in this interface, then converts + * that <code>long</code> to a <code>double</code> using the + * <code>longBitsToDouble</code> method in the class + * <code>java.lang.Double</code> + * <p> + * This method can read a <code>double</code> written by an object + * implementing the <code>writeDouble()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>double</code> value read + * + * @exception EOFException If end of file is reached before reading + * the double + * @exception IOException If any other error occurs + * + * @see DataOutput#writeDouble + * @see java.lang.Double#longBitsToDouble + */ + public double readDouble() + throws IOException + { + return Double.longBitsToDouble(readLong()); + } + + /** + * This method reads a Java float value from an input stream. It + * operates by first reading an <code>int</code> value from the + * stream by calling the <code>readInt()</code> method in this + * interface, then converts that <code>int</code> to a + * <code>float</code> using the <code>intBitsToFloat</code> method + * in the class <code>java.lang.Float</code> + * <p> + * This method can read a <code>float</code> written by an object + * implementing the <code>writeFloat()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>float</code> value read + * + * @exception EOFException If end of file is reached before reading the float + * @exception IOException If any other error occurs + * + * @see DataOutput#writeFloat + * @see java.lang.Float#intBitsToFloat + */ + public float readFloat() + throws IOException + { + return Float.intBitsToFloat(readInt()); + } + + /** + * This method reads raw bytes into the passed array until the array is + * full. Note that this method blocks until the data is available and + * throws an exception if there is not enough data left in the stream to + * fill the buffer. Note also that zero length buffers are permitted. + * In this case, the method will return immediately without reading any + * bytes from the stream. + * + * @param b The buffer into which to read the data + * + * @exception EOFException If end of file is reached before filling the + * buffer + * @exception IOException If any other error occurs + */ + public void readFully(byte[] b) + throws IOException + { + readFully(b, 0, b.length); + } + + /** + * This method reads raw bytes into the passed array <code>buf</code> + * starting + * <code>offset</code> bytes into the buffer. The number of bytes read + * will be + * exactly <code>len</code>. Note that this method blocks until the data is + * available and throws an exception if there is not enough data left in + * the stream to read <code>len</code> bytes. Note also that zero length + * buffers are permitted. In this case, the method will return immediately + * without reading any bytes from the stream. + * + * @param buf The buffer into which to read the data + * @param offset The offset into the buffer to start storing data + * @param len The number of bytes to read into the buffer + * + * @exception EOFException If end of file is reached before filling the + * buffer + * @exception IOException If any other error occurs + */ + public void readFully(byte[] buf, int offset, int len) + throws IOException + { + if (len < 0) + throw new IndexOutOfBoundsException("Negative length: " + len); + + while (len > 0) + { + // in.read will block until some data is available. + int numread = in.read(buf, offset, len); + if (numread < 0) + throw new EOFException(); + len -= numread; + offset += numread; + } + } + + /** + * This method reads a Java <code>int</code> value from an input stream + * It operates by reading four bytes from the stream and converting them to + * a single Java <code>int</code>. The bytes are stored most + * significant byte first (i.e., "big endian") regardless of the native + * host byte ordering. + * <p> + * As an example, if <code>byte1</code> through <code>byte4</code> represent + * the first four bytes read from the stream, they will be + * transformed to an <code>int</code> in the following manner: + * <p> + * <code>(int)(((byte1 & 0xFF) << 24) + ((byte2 & 0xFF) << 16) + + * ((byte3 & 0xFF)<< 8) + (byte4 & 0xFF)))</code> + * <p> + * The value returned is in the range of -2147483648 to 2147483647. + * <p> + * This method can read an <code>int</code> written by an object + * implementing the <code>writeInt()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>int</code> value read + * + * @exception EOFException If end of file is reached before reading the int + * @exception IOException If any other error occurs + * + * @see DataOutput#writeInt + */ + public int readInt() + throws IOException + { + readFully(buf, 0, 4); + return convertToInt(buf); + } + + /** + * This method reads the next line of text data from an input + * stream. It operates by reading bytes and converting those bytes + * to <code>char</code> values by treating the byte read as the low + * eight bits of the <code>char</code> and using 0 as the high eight + * bits. Because of this, it does not support the full 16-bit + * Unicode character set. + * <p> + * The reading of bytes ends when either the end of file or a line + * terminator is encountered. The bytes read are then returned as a + * <code>String</code> A line terminator is a byte sequence + * consisting of either <code>\r</code>, <code>\n</code> or + * <code>\r\n</code>. These termination charaters are discarded and + * are not returned as part of the string. + * <p> + * This method can read data that was written by an object implementing the + * <code>writeLine()</code> method in <code>DataOutput</code>. + * + * @return The line read as a <code>String</code> + * + * @exception IOException If an error occurs + * + * @see DataOutput + * + * @deprecated + */ + public String readLine() + throws IOException + { + CPStringBuilder strb = new CPStringBuilder(); + + while (true) + { + int c = in.read(); + if (c == -1) // got an EOF + return strb.length() > 0 ? strb.toString() : null; + if (c == '\r') + { + int next_c = in.read(); + if (next_c != '\n' && next_c != -1) + { + if (!(in instanceof PushbackInputStream)) + in = new PushbackInputStream(in); + ((PushbackInputStream) in).unread(next_c); + } + break; + } + if (c == '\n') + break; + strb.append((char) c); + } + + return strb.length() > 0 ? strb.toString() : ""; + } + + /** + * This method reads a Java <code>long</code> value from an input stream + * It operates by reading eight bytes from the stream and converting them to + * a single Java <code>long</code>. The bytes are stored most + * significant byte first (i.e., "big endian") regardless of the native + * host byte ordering. + * <p> + * As an example, if <code>byte1</code> through <code>byte8</code> represent + * the first eight bytes read from the stream, they will be + * transformed to an <code>long</code> in the following manner: + * <p> + * <code>(long)(((byte1 & 0xFF) << 56) + ((byte2 & 0xFF) << 48) + + * ((byte3 & 0xFF) << 40) + ((byte4 & 0xFF) << 32) + + * ((byte5 & 0xFF) << 24) + ((byte6 & 0xFF) << 16) + + * ((byte7 & 0xFF) << 8) + (byte8 & 0xFF))) + * </code> + * <p> + * The value returned is in the range of -9223372036854775808 to + * 9223372036854775807. + * <p> + * This method can read an <code>long</code> written by an object + * implementing the <code>writeLong()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>long</code> value read + * + * @exception EOFException If end of file is reached before reading the long + * @exception IOException If any other error occurs + * + * @see DataOutput#writeLong + */ + public long readLong() + throws IOException + { + readFully(buf, 0, 8); + return convertToLong(buf); + } + + /** + * This method reads a signed 16-bit value into a Java in from the + * stream. It operates by reading two bytes from the stream and + * converting them to a single 16-bit Java <code>short</code>. The + * two bytes are stored most significant byte first (i.e., "big + * endian") regardless of the native host byte ordering. + * <p> + * As an example, if <code>byte1</code> and <code>byte2</code> + * represent the first and second byte read from the stream + * respectively, they will be transformed to a <code>short</code>. in + * the following manner: + * <p> + * <code>(short)(((byte1 & 0xFF) << 8) | (byte2 & 0xFF))</code> + * <p> + * The value returned is in the range of -32768 to 32767. + * <p> + * This method can read a <code>short</code> written by an object + * implementing the <code>writeShort()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The <code>short</code> value read + * + * @exception EOFException If end of file is reached before reading the value + * @exception IOException If any other error occurs + * + * @see DataOutput#writeShort + */ + public short readShort() + throws IOException + { + readFully(buf, 0, 2); + return convertToShort(buf); + } + + /** + * This method reads 8 unsigned bits into a Java <code>int</code> + * value from the stream. The value returned is in the range of 0 to + * 255. + * <p> + * This method can read an unsigned byte written by an object + * implementing the <code>writeUnsignedByte()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The unsigned bytes value read as a Java <code>int</code>. + * + * @exception EOFException If end of file is reached before reading the value + * @exception IOException If any other error occurs + * + * @see DataOutput#writeByte + */ + public int readUnsignedByte() + throws IOException + { + return convertToUnsignedByte(in.read()); + } + + /** + * This method reads 16 unsigned bits into a Java int value from the stream. + * It operates by reading two bytes from the stream and converting them to + * a single Java <code>int</code> The two bytes are stored most + * significant byte first (i.e., "big endian") regardless of the native + * host byte ordering. + * <p> + * As an example, if <code>byte1</code> and <code>byte2</code> + * represent the first and second byte read from the stream + * respectively, they will be transformed to an <code>int</code> in + * the following manner: + * <p> + * <code>(int)(((byte1 & 0xFF) << 8) + (byte2 & 0xFF))</code> + * <p> + * The value returned is in the range of 0 to 65535. + * <p> + * This method can read an unsigned short written by an object + * implementing the <code>writeUnsignedShort()</code> method in the + * <code>DataOutput</code> interface. + * + * @return The unsigned short value read as a Java <code>int</code> + * + * @exception EOFException If end of file is reached before reading the value + * @exception IOException If any other error occurs + * + * @see DataOutput#writeShort + */ + public int readUnsignedShort() + throws IOException + { + readFully(buf, 0, 2); + return convertToUnsignedShort(buf); + } + + /** + * This method attempts to skip and discard the specified number of bytes + * in the input stream. It may actually skip fewer bytes than requested. + * This method will not skip any bytes if passed a negative number of bytes + * to skip. + * + * @param n The requested number of bytes to skip. + * + * @return The requested number of bytes to skip. + * + * @exception IOException If an error occurs. + * @specnote The JDK docs claim that this returns the number of bytes + * actually skipped. The JCL claims that this method can throw an + * EOFException. Neither of these appear to be true in the JDK 1.3's + * implementation. This tries to implement the actual JDK behaviour. + */ + public int skipBytes(int n) + throws IOException + { + if (n <= 0) + return 0; + try + { + return (int) in.skip(n); + } + catch (EOFException x) + { + // do nothing. + } + return n; + } + + protected boolean convertToBoolean(int b) + throws EOFException + { + if (b < 0) + throw new EOFException(); + + return (b != 0); + } + + protected byte convertToByte(int i) + throws EOFException + { + if (i < 0) + throw new EOFException(); + + return (byte) i; + } + + protected int convertToUnsignedByte(int i) + throws EOFException + { + if (i < 0) + throw new EOFException(); + + return (i & 0xFF); + } + + /** + * Less significant byte first. + */ + protected char convertToChar(byte[] buf) + { + return (char) ((buf [ 1 ] << 8) | (buf [ 0 ] & 0xff)); + } + + /** + * Less significant byte first. + */ + protected short convertToShort(byte[] buf) + { + return (short) ((buf [ 1 ] << 8) | (buf [ 0 ] & 0xff)); + } + + /** + * Less significant byte first. + */ + protected int convertToUnsignedShort(byte[] buf) + { + return (((buf [ 1 ] & 0xff) << 8) | (buf [ 0 ] & 0xff)); + } + + /** + * Less significant byte first. + */ + protected int convertToInt(byte[] buf) + { + return (((buf [ 3 ] & 0xff) << 24) | ((buf [ 2 ] & 0xff) << 16) | + ((buf [ 1 ] & 0xff) << 8) | (buf [ 0 ] & 0xff)); + } + + /** + * Less significant byte first. + */ + protected long convertToLong(byte[] buf) + { + return (((long) (buf [ 7 ] & 0xff) << 56) | + ((long) (buf [ 6 ] & 0xff) << 48) | + ((long) (buf [ 5 ] & 0xff) << 40) | + ((long) (buf [ 4 ] & 0xff) << 32) | + ((long) (buf [ 3 ] & 0xff) << 24) | + ((long) (buf [ 2 ] & 0xff) << 16) | + ((long) (buf [ 1 ] & 0xff) << 8) | ((long) (buf [ 0 ] & 0xff))); + } + + /** + * This should never be called. + * + * @throws InternalError, always. + */ + public String readUTF() + { + throw new InternalError(); + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/LittleEndianOutputStream.java b/libjava/classpath/gnu/CORBA/CDR/LittleEndianOutputStream.java new file mode 100644 index 000000000..f1b8e04b3 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/LittleEndianOutputStream.java @@ -0,0 +1,253 @@ +/* LittleEndianOutputStream.java -- + Copyright (C) 1998, 2001, 2003, 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 java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * This stream writes data in the Little Endian format + * (less significant byte first). This is opposite to the + * usual data presentation in java platform. + * + * This class reuses code from DataOutputStream. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Tom Tromey (tromey@cygnus.com) + */ +public class LittleEndianOutputStream + extends FilterOutputStream + implements AbstractDataOutput +{ + /** + * This method initializes an instance of <code>DataOutputStream</code> to + * write its data to the specified underlying <code>OutputStream</code> + * + * @param out The subordinate <code>OutputStream</code> to which this + * object will write + */ + public LittleEndianOutputStream(OutputStream out) + { + super(out); + } + + /** + * This method flushes any unwritten bytes to the underlying stream. + * + * @exception IOException If an error occurs. + */ + public void flush() + throws IOException + { + out.flush(); + } + + /** + * This method writes the specified byte (passed as an <code>int</code>) + * to the underlying output stream. + * + * @param value The <code>byte</code> to write, passed as an <code>int</code>. + * + * @exception IOException If an error occurs. + */ + public synchronized void write(int value) + throws IOException + { + out.write(value); + } + + /** + * This method writes <code>len</code> bytes from the specified byte array + * <code>buf</code> starting at position <code>offset</code> into the + * buffer to the underlying output stream. + * + * @param buf The byte array to write from. + * @param offset The index into the byte array to start writing from. + * @param len The number of bytes to write. + * + * @exception IOException If an error occurs. + */ + public synchronized void write(byte[] buf, int offset, int len) + throws IOException + { + out.write(buf, offset, len); + } + + /** + * This method writes a Java boolean value to an output stream. If + * <code>value</code> is <code>true</code>, a byte with the value of + * 1 will be written, otherwise a byte with the value of 0 will be + * written. + * + * The value written can be read using the <code>readBoolean</code> + * method in <code>DataInput</code>. + * + * @param value The <code>boolean</code> value to write to the stream + * + * @exception IOException If an error occurs + * + * @see DataInput#readBoolean + */ + public void writeBoolean(boolean value) + throws IOException + { + write(value ? 1 : 0); + } + + /** + * This method writes a Java byte value to an output stream. The + * byte to be written will be in the lowest 8 bits of the + * <code>int</code> value passed. + * + * The value written can be read using the <code>readByte</code> or + * <code>readUnsignedByte</code> methods in <code>DataInput</code>. + * + * @param value The <code>byte</code> to write to the stream, passed as + * the low eight bits of an <code>int</code>. + * + * @exception IOException If an error occurs + * + * @see DataInput#readByte + * @see DataInput#readUnsignedByte + */ + public void writeByte(int value) + throws IOException + { + write(value & 0xff); + } + + /** + * This method writes a Java short value to an output stream. + * + * @param value The <code>short</code> value to write to the stream, + * passed as an <code>int</code>. + * + * @exception IOException If an error occurs + */ + public synchronized void writeShort(int value) + throws IOException + { + write((byte) (0xff & value)); + write((byte) (0xff & (value >> 8))); + } + + /** + * Writes char in Little Endian. + */ + public synchronized void writeChar(int value) + throws IOException + { + write((byte) (0xff & value)); + write((byte) (0xff & (value >> 8))); + } + + /** + * Writes int in Little Endian. + */ + public synchronized void writeInt(int value) + throws IOException + { + write((byte) (0xff & value)); + write((byte) (0xff & (value >> 8))); + write((byte) (0xff & (value >> 16))); + write((byte) (0xff & (value >> 24))); + } + + /** + * Writes long in Little Endian. + */ + public synchronized void writeLong(long value) + throws IOException + { + write((byte) (0xff & value)); + write((byte) (0xff & (value >> 8))); + write((byte) (0xff & (value >> 16))); + write((byte) (0xff & (value >> 24))); + write((byte) (0xff & (value >> 32))); + write((byte) (0xff & (value >> 40))); + write((byte) (0xff & (value >> 48))); + write((byte) (0xff & (value >> 56))); + } + + /** + * This method writes a Java <code>float</code> value to the stream. This + * value is written by first calling the method + * <code>Float.floatToIntBits</code> + * to retrieve an <code>int</code> representing the floating point number, + * then writing this <code>int</code> value to the stream exactly the same + * as the <code>writeInt()</code> method does. + * + * @param value The <code>float</code> value to write to the stream + * + * @exception IOException If an error occurs + * + * @see writeInt + * @see DataInput#readFloat + * @see Float#floatToIntBits + */ + public void writeFloat(float value) + throws IOException + { + writeInt(Float.floatToIntBits(value)); + } + + /** + * This method writes a Java <code>double</code> value to the stream. This + * value is written by first calling the method + * <code>Double.doubleToLongBits</code> + * to retrieve an <code>long</code> representing the floating point number, + * then writing this <code>long</code> value to the stream exactly the same + * as the <code>writeLong()</code> method does. + * + * @param value The <code>double</code> value to write to the stream + * + * @exception IOException If an error occurs + * + * @see writeLong + * @see DataInput#readDouble + * @see Double#doubleToLongBits + */ + public void writeDouble(double value) + throws IOException + { + writeLong(Double.doubleToLongBits(value)); + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/UnknownExceptionCtxHandler.java b/libjava/classpath/gnu/CORBA/CDR/UnknownExceptionCtxHandler.java new file mode 100644 index 000000000..cb36f8c42 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/UnknownExceptionCtxHandler.java @@ -0,0 +1,292 @@ +/* UnknownExceptionCtxHandler.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.Minor; +import gnu.CORBA.ObjectCreator; +import gnu.CORBA.GIOP.ServiceContext; + +import org.omg.CORBA.MARSHAL; +import org.omg.CORBA.NO_IMPLEMENT; +import org.omg.CORBA.StringValueHelper; +import org.omg.CORBA.portable.OutputStream; + +import java.lang.reflect.Constructor; +import java.util.StringTokenizer; + +import javax.rmi.CORBA.Util; + +/** + * Reads the data about an unknown exception from the UnknownExceptionInfo. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class UnknownExceptionCtxHandler + extends Vio +{ + /** + * Encode exception and add its recored to the message service contexts. + */ + public static ServiceContext[] addExceptionContext(ServiceContext[] current, + Throwable exception, Object details) + { + try + { + ServiceContext[] c = new ServiceContext[current.length + 1]; + if (current.length > 0) + System.arraycopy(current, 0, c, 0, current.length); + + BufferedCdrOutput output = new BufferedCdrOutput(); + + if (details instanceof OutputStream) + output.setOrb(((OutputStream) output).orb()); + + if (details instanceof AbstractCdrOutput) + ((AbstractCdrOutput) details).cloneSettings(output); + + write(output, exception); + + ServiceContext xc = new ServiceContext(); + xc.context_id = ServiceContext.UnknownExceptionInfo; + xc.context_data = output.buffer.toByteArray(); + c[current.length] = xc; + return c; + } + catch (Exception ex) + { + ex.printStackTrace(); + return current; + } + } + + /** + * Write data about unknown exception. + */ + public static void write(BufferedCdrOutput output, Throwable t) + { + t.fillInStackTrace(); + output.write_Value(t); + } + + /** + * Read the data about an unknown exception from the UnknownExceptionInfo. + * Following the documentation, this must be just value type, but it seems + * that in Sun's implementation is is not, as starts from 0x0. For value type, + * this would be null. + * + * TODO Implement reading and writing in Sun format, making Classpath IIOP + * interoperable with Sun's implementation. Current inmplementation reads and + * reproduces the exception class type only. + * + * @param input the input stream to read the context (orb and other settings + * are inherited from the main stream that received the message). + * + * @param contexts all service contexts that were present in the message. + * + * @return the Throwable, extracted from context, on null, if this has failed. + */ + public static Throwable read(BufferredCdrInput input, ServiceContext[] contexts) + { + input.mark(Integer.MAX_VALUE); + + int h = input.read_long(); + if (h == 0) + { + // This block reads exception info in the Sun specific format. + // (currently we read the exception name only). + try + { + // We may need to jump back if the value is read via value + // factory. + input.mark(512); + + int value_tag = input.read_long(); + checkTag(value_tag); + + String codebase = null; + String[] ids = null; + String id = null; + + // Check for the agreed null value. + if (value_tag == vt_NULL) + return null; + else if (value_tag == vt_INDIRECTION) + return (Throwable) readIndirection(input); + else + { + // Read the value. + if ((value_tag & vf_CODEBASE) != 0) + { + // The codebase is present. The codebase is a space + // separated list of URLs from where the implementing + // code can be downloaded. + codebase = read_string(input); + } + + if ((value_tag & vf_MULTIPLE_IDS) != 0) + { + // Multiple supported repository ids are present. + ids = read_string_array(input); + } + else if ((value_tag & vf_ID) != 0) + { + // Single supported repository id is present. + id = read_string(input); + } + } + + java.lang.Object ox = createInstance(id, ids, codebase); + + return (Throwable) ox; + } + catch (Exception ex) + { + ex.printStackTrace(); + return null; + } + } + else + { + input.reset(); + // Read as defined in OMG documentation. + return (Throwable) input.read_Value(); + } + } + + /** + * Load exception by name and create the instance. The reason why this is + * different from Vio is because some exceptions have no parameterless + * constructor, but have a constructor with the string parameter instead. + */ + static Object createInstance(String id, String[] ids, String codebase) + { + Object o = _createInstance(id, codebase); + + if (ids != null) + for (int i = 0; i < ids.length && o == null; i++) + o = _createInstance(ids[i], codebase); + return o; + } + + static Object _createInstance(String id, String codebase) + { + if (id == null) + return null; + if (id.equals(StringValueHelper.id())) + return ""; + StringTokenizer st = new StringTokenizer(id, ":"); + + String prefix = st.nextToken(); + if (prefix.equalsIgnoreCase("IDL")) + return ObjectCreator.Idl2Object(id); + else if (prefix.equalsIgnoreCase("RMI")) + { + String className = st.nextToken(); + String hashCode = st.nextToken(); + String sid = null; + if (st.hasMoreElements()) + sid = st.nextToken(); + + try + { + Class objectClass = Util.loadClass(className, codebase, + Vio.class.getClassLoader()); + + String rid = ObjectCreator.getRepositoryId(objectClass); + + if (!rid.equals(id)) + { + // If direct string comparison fails, compare by meaning. + StringTokenizer st2 = new StringTokenizer(rid, ":"); + if (!st2.nextToken().equals("RMI")) + throw new InternalError("RMI format expected: '" + rid + "'"); + if (!st2.nextToken().equals(className)) + throwIt("Class name mismatch", id, rid, null); + + try + { + long h1 = Long.parseLong(hashCode, 16); + long h2 = Long.parseLong(st2.nextToken(), 16); + if (h1 != h2) + throwIt("Hashcode mismatch", id, rid, null); + + if (sid != null && st2.hasMoreTokens()) + { + long s1 = Long.parseLong(hashCode, 16); + long s2 = Long.parseLong(st2.nextToken(), 16); + if (s1 != s2) + throwIt("serialVersionUID mismatch", id, rid, null); + } + } + catch (NumberFormatException e) + { + throwIt("Invalid hashcode or svuid format: ", id, rid, e); + } + } + + // Some RemoteExceptions have no public parameterless constructor, + // but they have constructor taking string as parameter. + try + { + return objectClass.newInstance(); + } + catch (Exception ex) + { + // Try instantiate passing string as parameter. + Constructor c = objectClass.getConstructor(new Class[] { String.class }); + return c.newInstance(new Object[] { "<message unavailable>" }); + } + } + catch (MARSHAL m) + { + m.minor = Minor.Instantiation; + throw m; + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("Unable to instantiate " + id); + m.minor = Minor.Instantiation; + m.initCause(ex); + throw m; + } + } + else + throw new NO_IMPLEMENT("Unsupported prefix " + prefix + ":"); + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/VMVio.java b/libjava/classpath/gnu/CORBA/CDR/VMVio.java new file mode 100644 index 000000000..47a6c0c25 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/VMVio.java @@ -0,0 +1,101 @@ +/* VMVio.java -- Native operations, required by value IO. + 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. */ + +/** + * This is a temporary replacement for the native call that would allocate + * objects without public constructors. The replacement only allocates + * objects with public parameterless constructor and objects with public + * constructor taking string (like some Throwables). + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + * + * TODO FIXME replace by native call like in VMObjectInputStream. + * Required modification of Classpath the build system. + */ + + +package gnu.CORBA.CDR; + +import java.lang.reflect.Constructor; + +public class VMVio +{ + /** + * Allocates a new Object of type clazz but without running the default + * constructor on it. It then calls the given constructor on it. The given + * constructor method comes from the constr_clazz which is a super class of + * the given clazz. + */ + public static Object allocateObject(Class clazz, Class constr_clazz, + Constructor constructor) + throws InstantiationException + { + try + { + Constructor c = clazz.getConstructor(new Class[0]); + c.setAccessible(true); + return c.newInstance(new Object[0]); + } + catch (Exception ex) + { + try + { + Constructor c = clazz.getConstructor(new Class[] { String.class }); + return c.newInstance(new Object[] { "" }); + } + catch (Exception ex2) + { + Constructor c[] = clazz.getConstructors(); + + for (int i = 0; i < c.length; i++) + { + try + { + c[i].setAccessible(true); + Class[] args = c[i].getParameterTypes(); + return c[i].newInstance(new Object[args.length]); + } + catch (Exception ex3) + { + // Try another one. + } + } + } + throw new InstantiationException(clazz.getName()); + } + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/Vio.java b/libjava/classpath/gnu/CORBA/CDR/Vio.java new file mode 100644 index 000000000..1eecb651b --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/Vio.java @@ -0,0 +1,1474 @@ +/* Vio.java -- Value type IO operations. + 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.Minor; +import gnu.CORBA.ObjectCreator; + +import gnu.java.lang.CPStringBuilder; + +import org.omg.CORBA.CustomMarshal; +import org.omg.CORBA.DataInputStream; +import org.omg.CORBA.DataOutputStream; +import org.omg.CORBA.MARSHAL; +import org.omg.CORBA.NO_IMPLEMENT; +import org.omg.CORBA.StringSeqHelper; +import org.omg.CORBA.StringValueHelper; +import org.omg.CORBA.SystemException; +import org.omg.CORBA.WStringValueHelper; +import org.omg.CORBA.portable.BoxedValueHelper; +import org.omg.CORBA.portable.InputStream; +import org.omg.CORBA.portable.OutputStream; +import org.omg.CORBA.portable.Streamable; +import org.omg.CORBA.portable.ValueFactory; + +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.util.StringTokenizer; + +import javax.rmi.CORBA.Util; +import javax.rmi.CORBA.ValueHandler; + +/** + * A specialised class for reading and writing the value types. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public abstract class Vio +{ + /** + * If true, wrap value type data into chunks. This decrease the performance, + * and is not required for interoperability with jdk 1.5, but is left in the + * implementation as the optional mode for solving possible interoperability + * problems with non-Sun CORBA implementations. + * + * The current implementation would accept both single chunk or multiple + * chunks, but will always send a single chunk (if true) or unchunked data (if + * false). + */ + public static boolean USE_CHUNKING = false; + + /** + * The first field in the value record. The last octet may contain additional + * flags (vf_CODEBASE, vf_ID and vf_MULTIPLE_IDS). The tag value is different + * for the indirections (vt_INDIRECTION) and nulls (vt_NULL). + */ + public static final int vt_VALUE_TAG = 0x7fffff00; + + /** + * The value tag flag, indicating that the codebase URL is present in the + * value tag record. + */ + public static final int vf_CODEBASE = 0x1; + + /** + * The value tag flag, indicating that a single repository id is present in + * the value tag record. + */ + public static final int vf_ID = 0x2; + + /** + * The value tag flag, indicating, that there are multiple repository ids + * present in the record. If this flag is set, the flag vf_ID must also be + * set, resulting the value of the least significant byte 0x6. + */ + public static final int vf_MULTIPLE_IDS = 0x4; + + /** + * The value tag flag, indicating the presence of chunking. Each chunk is + * preceeded by a positive int, indicating the number of bytes in the chunk. A + * sequence of chunks is terminated by a non positive int. + */ + public static final int vf_CHUNKING = 0x8; + + /** + * The indirection tag value. Such tag must be followed by the CORBA long, + * indicating the offset in the CORBA message, where the indirected + * information is present. This offset is assumed zero at the position where + * the mentioned CORBA long starts and can refer both forward (positive + * values) and backward (negative values). + */ + public static final int vt_INDIRECTION = 0xffffffff; + + /** + * This tag value means that the value object being transferred is equal to + * null. + */ + public static final int vt_NULL = 0x0; + + /** + * The size of CORBA long (java int). + */ + static final int INT_SIZE = 4; + + /** + * The String value helper (one instance is sufficient). + */ + public static final WStringValueHelper m_StringValueHelper = new WStringValueHelper(); + + /** + * An instance of the value handler. + */ + static ValueHandler handler = Util.createValueHandler(); + + /** + * Read the value base from the given input stream. Determines the required + * class from the repository id. This includes operations that are not + * required when an unitialised instance or at least class of the value type + * is known. Hence it may be faster to use the alternative methods, + * read(InputStream, Class) or read(InputStream, Serializable). + * + * @param input a stream to read from. + * + * @return the loaded value. + * + * @throws MARSHAL if the reading has failed due any reason. + */ + public static Serializable read(InputStream input) + { + return read(input, (String) null); + } + + /** + * Read the value base from the given input stream. Determines the required + * class from the repository id. This includes operations that are not + * required when an unitialised instance or at least class of the value type + * is known. Hence it may be faster to use the alternative methods, + * read(InputStream, Class) or read(InputStream, Serializable). + * + * @param input a stream to read from. + * @param repository_id a repository id of the object being read, may be null. + * + * @return the loaded value. + * + * @throws MARSHAL if the reading has failed due any reason. + */ + public static Serializable read(InputStream input, String repository_id) + { + try + { + final int position = getCurrentPosition(input); + // We may need to jump back if the value is read via value factory. + input.mark(512); + + int value_tag = input.read_long(); + checkTag(value_tag); + + String codebase = null; + String[] ids = null; + String id = repository_id; + + // Check for the agreed null value. + if (value_tag == vt_NULL) + return null; + else if (value_tag == vt_INDIRECTION) + return readIndirection(input); + else + { + // Read the value. + if ((value_tag & vf_CODEBASE) != 0) + { + // The codebase is present. The codebase is a space + // separated list of URLs from where the implementing + // code can be downloaded. + codebase = read_string(input); + } + + if ((value_tag & vf_MULTIPLE_IDS) != 0) + { + // Multiple supported repository ids are present. + ids = read_string_array(input); + } + else if ((value_tag & vf_ID) != 0) + { + // Single supported repository id is present. + id = read_string(input); + } + } + + BoxedValueHelper helper = getHelper(null, id); + // The existing implementing object. + java.lang.Object ox = null; + + if (helper != null) + ox = null; // Helper will care about the instantiating. + else if (id.equals(WStringValueHelper.id())) + helper = m_StringValueHelper; + else + ox = createInstance(id, ids, codebase); + return (Serializable) read_instance(input, position, ox, value_tag, + helper, id, ids, codebase); + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL(); + m.minor = Minor.Value; + m.initCause(ex); + throw m; + } + } + + /** + * Read the value base from the given input stream when the value base class + * is available. Hence there is no need to guess it from the repository id. + * + * @param input a stream to read from. + * @param value_class the class of the value being read. + * + * @return the loaded value. + * + * @throws MARSHAL if the reading has failed due any reason. + */ + public static Serializable read(InputStream input, Class value_class) + { + final int position = getCurrentPosition(input); + + String id = null; + String[] ids = null; + String codebase = null; + + try + { + int value_tag = input.read_long(); + checkTag(value_tag); + + // Check for the agreed null value. + if (value_tag == vt_NULL) + return null; + else if (value_tag == vt_INDIRECTION) + return readIndirection(input); + else + { + // Read the value. + if ((value_tag & vf_CODEBASE) != 0) + { + // The codebase is present. + codebase = read_string(input); + } + + if ((value_tag & vf_MULTIPLE_IDS) != 0) + { + // Multiple supported repository ids are present. + ids = read_string_array(input); + } + else if ((value_tag & vf_ID) != 0) + { + // Single supported repository id is present. + id = read_string(input); + } + } + + BoxedValueHelper vHelper = id != null ? getHelper(value_class, id) + : getHelper(value_class, ids); + + java.lang.Object ox; + + if (vHelper == null) + { + try + { + ox = createInstance(id, ids, codebase); + } + catch (Exception e) + { + ox = null; + } + + if (ox != null) + { + if (value_class != null + && !value_class.isAssignableFrom(ox.getClass())) + { + MARSHAL m = new MARSHAL(ox.getClass() + " is not a " + + value_class.getName()); + m.minor = Minor.ClassCast; + throw m; + } + } + } + else + ox = null; + + ox = read_instance(input, position, ox, value_tag, vHelper, id, ids, + codebase); + return (Serializable) ox; + } + catch (MARSHAL m) + { + throw m; + } + catch (SystemException sysEx) + { + // OK. + throw sysEx; + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("Cant read " + value_class); + m.minor = Minor.Value; + m.initCause(ex); + throw m; + } + } + + /** + * Read the value base from the given input stream when the unitialised + * instance is available. Hence there is no need to guess the class from the + * repository id and then to instantiate an instance. + * + * @param input a stream to read from. + * + * @param value_instance an pre-created instance of the value. If the helper + * is not null, this parameter is ignored an should be null. + * + * @param helper a helper to create an instance and read the object- specific + * part of the record. If the value_instance is used instead, this parameter + * should be null. + * + * @return the loaded value. + * + * @throws MARSHAL if the reading has failed due any reason. + */ + public static Object read(InputStream input, Object value_instance, + BoxedValueHelper helper) + { + final int position = getCurrentPosition(input); + + String id = null; + String[] ids = null; + String codebase = null; + + try + { + int value_tag = input.read_long(); + checkTag(value_tag); + + // Check for the agreed null value. + if (value_tag == vt_NULL) + return null; + else if (value_tag == vt_INDIRECTION) + return readIndirection(input); + else + { + // Read the value. + if ((value_tag & vf_CODEBASE) != 0) + { + // The codebase is present. + codebase = read_string(input); + } + + if ((value_tag & vf_MULTIPLE_IDS) != 0) + { + // Multiple supported repository ids are present. + ids = read_string_array(input); + } + else if ((value_tag & vf_ID) != 0) + { + // Single supported repository id is present. + id = read_string(input); + } + } + + Class value_class = value_instance == null ? null + : value_instance.getClass(); + + if (helper == null) + helper = id != null ? getHelper(value_class, id) : getHelper( + value_class, ids); + + value_instance = read_instance(input, position, value_instance, + value_tag, helper, id, ids, codebase); + return value_instance; + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL(); + m.minor = Minor.Value; + m.initCause(ex); + throw m; + } + } + + /** + * Read using provided boxed value helper. This method expects the full value + * type header, followed by contents, that are delegated to the provided + * helper. It handles null. + * + * @param input the stream to read from. + * @param helper the helper that reads the type-specific part of the content. + * + * @return the value, created by the helper, or null if the header indicates + * that null was previously written. + */ + public static Serializable read(InputStream input, BoxedValueHelper helper) + { + return (Serializable) read(input, null, helper); + } + + /** + * Fill in the instance fields by the data from the input stream. The method + * assumes that the value header, if any, is already behind. The information + * from the stream is stored into the passed ox parameter. + * + * @param input an input stream to read from. + * + * @param value a pre-instantiated value type object, must be either + * Streamable or CustomMarshal. If the helper is used, this parameter is + * ignored and should be null. + * + * @param value_tag the tag that must be read previously. + * @param helper the helper for read object specific part; may be null to read + * in using other methods. + * + * @return the value that was read. + */ + static Object read_instance(InputStream input, final int position, + Object value, int value_tag, BoxedValueHelper helper, String id, + String[] ids, String codebase) + { + if (helper != m_StringValueHelper && id != null) + if (id.equals(StringValueHelper.id())) + { + value = null; + helper = m_StringValueHelper; + } + + try + { + if ((value_tag & vf_CHUNKING) != 0) + { + BufferedCdrOutput output = createBuffer(input, 1024); + // Read the current (not a nested one) value in this spec case. + readNestedValue(value_tag, input, output, -1); + BufferredCdrInput ci = new BufferredCdrInput(output.buffer.getBuffer()); + ci.setRunTime(output.getRunTime()); + + input = new HeadlessInput(ci, input); + } + else + { + if (input instanceof BufferredCdrInput) + { + // Highly probable case. + input = new HeadlessInput((BufferredCdrInput) input, null); + } + else if (input instanceof HeadlessInput) + { + // There is no need to instantiate one more HeadlessInput + // as we can just reset. + ((HeadlessInput) input).subsequentCalls = false; + } + else + { + BufferedCdrOutput bout = new BufferedCdrOutput(); + int c; + while ((c = input.read()) >= 0) + bout.write((byte) c); + input = new HeadlessInput( + (BufferredCdrInput) bout.create_input_stream(), input); + } + } + } + catch (IOException ex) + { + MARSHAL m = new MARSHAL("Unable to read chunks"); + m.minor = Minor.Value; + m.initCause(ex); + throw m; + } + + return readValue(input, position, value, helper, id, ids, codebase); + } + + /** + * Create a buffer, inheriting critical settings from the passed input stream. + */ + private static BufferedCdrOutput createBuffer(InputStream input, int proposed_size) + { + BufferedCdrOutput bout; + bout = new BufferedCdrOutput(2 * proposed_size + 256); + + if (input instanceof BufferredCdrInput) + { + BufferredCdrInput in = (BufferredCdrInput) input; + bout.setBigEndian(in.isBigEndian()); + } + + if (input instanceof gnuValueStream) + bout.setRunTime(((gnuValueStream) input).getRunTime()); + else + bout.setRunTime(new gnuRuntime(null, null)); + return bout; + } + + /** + * Read the chunked nested value from the given input stream, transferring the + * contents to the given output stream. + * + * @param value_tag the value tag of the value being read. + * @param input the input stream from where the remainder of the nested value + * must be read. + * @param output the output stream where the unchunked nested value must be + * copied. + * + * @return the tag that ended the nested value. + */ + public static int readNestedValue(int value_tag, InputStream input, + BufferedCdrOutput output, int level) + throws IOException + { + String id = null; + if (level < -1) + { + // For the first level, this information is already behind. + output.write_long(value_tag - vf_CHUNKING); + + // The nested value should be aways chunked. + if ((value_tag & vf_CHUNKING) == 0) + { + MARSHAL m = new MARSHAL("readNestedValue: must be chunked"); + m.minor = Minor.Chunks; + throw m; + } + else if (value_tag == vt_NULL) + { + MARSHAL m = new MARSHAL("readNestedValue: nul"); + m.minor = Minor.Chunks; + throw m; + } + else if (value_tag == vt_INDIRECTION) + { + MARSHAL m = new MARSHAL("readNestedValue: indirection"); + m.minor = Minor.Chunks; + throw m; + } + else + { + // Read the value. + if ((value_tag & vf_CODEBASE) != 0) + { + String codebase = read_string(input); + write_string(output, codebase); + } + + if ((value_tag & vf_MULTIPLE_IDS) != 0) + { + // Multiple supported repository ids are present. + String[] ids = read_string_array(input); + id = ids[0]; + write_string_array(output, ids); + } + else if ((value_tag & vf_ID) != 0) + { + id = read_string(input); + write_string(output, id); + } + } + } + + int n = -1; + + // Read all chunks. + int chunk_size; + + byte[] r = null; + + while (true) + { + // Read the size of the next chunk or it may also be the + // header of the nested value. + chunk_size = input.read_long(); + + // End of chunk terminator. + if (chunk_size < 0 && chunk_size >= level) + return chunk_size; + else if (chunk_size >= 0x7FFFFF00) + { + int onInput = getCurrentPosition(input) - 4; + int onOutput = output.getPosition(); + output.getRunTime().redirect(onInput, onOutput); + // Value over 0x7FFFFF00 indicates that the nested value + // starts here. Read the nested value, storing it into the output. + // First parameter is actually the value tag. + chunk_size = readNestedValue(chunk_size, input, output, level - 1); + if (chunk_size < 0 && chunk_size >= level) + return chunk_size; + } + else + { + // The chunk follows. + if (r == null || r.length < chunk_size) + r = new byte[chunk_size + 256]; + + n = 0; + while (n < chunk_size) + n += input.read(r, n, chunk_size - n); + output.write(r, 0, n); + } + } + } + + /** + * Read the value (the header must be behind). + */ + public static Serializable readValue(InputStream input, final int position, + Object value, BoxedValueHelper helper, String id, String[] ids, + String codebase) + { + gnuRuntime g; + gnuValueStream c = ((gnuValueStream) input); + if (c.getRunTime() == null) + { + g = new gnuRuntime(codebase, value); + c.setRunTime(g); + } + else + { + g = c.getRunTime(); + g.addCodeBase(codebase); + g.target = (Serializable) value; + } + if (value != null) + g.objectWritten(value, position); + + if (input instanceof HeadlessInput) + ((HeadlessInput) input).subsequentCalls = false; + + boolean ok = true; + + // The user-defined io operations are implemented. + if (value instanceof CustomMarshal) + { + CustomMarshal marsh = (CustomMarshal) value; + marsh.unmarshal((DataInputStream) input); + } + else + // The IDL-generated io operations are implemented. + if (value instanceof Streamable) + { + ((Streamable) value)._read(input); + } + else if (helper != null) + { + // If helper is non-null the value should normally be null. + value = helper.read_value(input); + g.objectWritten(value, position); + } + else + { + ok = false; + ValueFactory factory = null; + org.omg.CORBA_2_3.ORB orb = (org.omg.CORBA_2_3.ORB) input.orb(); + + if (id != null) + factory = orb.lookup_value_factory(id); + + if (factory == null && ids != null) + { + for (int i = 0; i < ids.length && factory == null; i++) + { + factory = orb.lookup_value_factory(ids[i]); + } + } + + if (factory != null) + { + value = factory.read_value((org.omg.CORBA_2_3.portable.InputStream) input); + ok = true; + } + } + + if (!ok && value instanceof Serializable) + // Delegate to ValueHandler + { + if (ids != null && ids.length > 0) + id = ids[0]; + + value = handler.readValue(input, position, value.getClass(), id, g); + ok = true; + } + + if (!ok) + { + if (value != null) + { + MARSHAL m = new MARSHAL(value.getClass().getName() + + " must be Streamable, CustomMarshal or Serializable"); + m.minor = Minor.UnsupportedValue; + throw m; + } + else + { + MARSHAL m = new MARSHAL("Unable to instantiate " + id + ":" + list(ids) + + " helper " + helper); + m.minor = Minor.UnsupportedValue; + throw m; + } + } + else + return (Serializable) value; + } + + /** + * Conveniency method to list ids in exception reports. + */ + static String list(String[] s) + { + if (s == null) + return "null"; + else + { + CPStringBuilder b = new CPStringBuilder("{"); + for (int i = 0; i < s.length; i++) + { + b.append(s[i]); + b.append(" "); + } + b.append("}"); + return b.toString(); + } + } + + /** + * Write the value base into the given stream. + * + * @param output a stream to write to. + * + * @param value a value type object, must be either Streamable or + * CustomMarshal. + * + * @throws MARSHAL if the writing failed due any reason. + */ + public static void write(OutputStream output, Serializable value) + { + // Write null if this is a null value. + if (value == null) + output.write_long(vt_NULL); + else if (value instanceof String) + write(output, value, m_StringValueHelper); + else + write(output, value, value.getClass()); + } + + /** + * Write the value base into the given stream, stating that it is an instance + * of the given class. + * + * @param output a stream to write to. + * + * @param value a value to write. + * + * @throws MARSHAL if the writing failed due any reason. + */ + public static void write(OutputStream output, Serializable value, + Class substitute) + { + // Write null if this is a null value. + if (value == null) + output.write_long(vt_NULL); + else if (value instanceof String || substitute == String.class) + writeString(output, value); + else + { + String vId = ObjectCreator.getRepositoryId(value.getClass()); + if (substitute == null || value.getClass().equals(substitute)) + write_instance(output, value, vId, getHelper(value.getClass(), vId)); + else + { + String vC = ObjectCreator.getRepositoryId(substitute); + String[] ids = new String[] { vId, vC }; + BoxedValueHelper h = getHelper(substitute.getClass(), ids); + // If the helper is available, it is also responsible for + // providing the repository Id. Otherwise, write both + // ids. + if (h == null) + write_instance(output, value, ids, null); + else + write_instance(output, value, h.get_id(), null); + } + } + } + + /** + * Write the value base into the given stream, supplementing it with an array + * of the provided repository ids plus the repository id, derived from the + * passed value. + * + * @param output a stream to write to. + * + * @param value a value to write. + * + * @throws MARSHAL if the writing failed due any reason. + */ + public static void write(OutputStream output, Serializable value, + String[] multiple_ids) + { + // Write null if this is a null value. + if (value == null) + output.write_long(vt_NULL); + else + { + String[] ids = new String[multiple_ids.length + 1]; + ids[0] = ObjectCreator.getRepositoryId(value.getClass()); + System.arraycopy(multiple_ids, 0, ids, 1, multiple_ids.length); + BoxedValueHelper h = getHelper(value.getClass(), ids); + write_instance(output, value, ids, h); + } + } + + /** + * Write value when its repository Id is explicitly given. Only this Id is + * written, the type of value is not taken into consideration. + * + * @param output an output stream to write into. + * @param value a value to write. + * @param id a value repository id. + */ + public static void write(OutputStream output, Serializable value, String id) + { + if (value == null) + output.write_long(vt_NULL); + else + write_instance(output, value, id, getHelper(value.getClass(), id)); + } + + /** + * Write standard value type header, followed by contents, produced by the + * boxed value helper. + * + * @param output the stream to write to. + * @param value the value to write, can be null. + * @param helper the helper that writes the value content if it is not null + * (must be provided for this method). + */ + public static void write(OutputStream output, Serializable value, + BoxedValueHelper helper) + { + if (helper == null) + throw new AssertionError("Helper must be provided"); + if (value == null) + output.write_long(vt_NULL); + else + write_instance(output, value, helper.get_id(), helper); + } + + /** + * Write the parameter that is surely a string and not null. + */ + private static void writeString(OutputStream output, Serializable string) + { + write_instance(output, string, m_StringValueHelper.get_id(), + m_StringValueHelper); + } + + /** + * Write value when its repository Id is explicitly given. Does not handle + * null. + * + * @param output an output stream to write into. + * @param value a value to write. + * @param ids a value repository id (can be either single string or string + * array). + * @param helper a helper, writing object - specifical part. Can be null if + * the value should be written using other methods. + */ + static void write_instance(OutputStream output, Serializable value, + Object ids, BoxedValueHelper helper) + { + gnuValueStream rout = null; + gnuRuntime runtime = null; + + try + { + if (output instanceof gnuValueStream) + { + int position; + rout = (gnuValueStream) output; + runtime = rout.getRunTime(); + + if (runtime == null) + { + runtime = new gnuRuntime(null, value); + rout.setRunTime(runtime); + rout.getRunTime().objectWritten(value, + position = rout.getPosition()); + } + else if (runtime.target == value) + { + if (!writeSelf(output, value)) + throw new InternalError("Recursive helper call for " + + value.getClass().getName()); + return; + } + else + { + position = runtime.isWrittenAt(value); + if (position >= 0) + { + // The object was already written. + output.write_long(vt_INDIRECTION); + output.write_long(position - rout.getPosition()); + // Replacing object write data by indirection reference. + return; + } + else + { + runtime.objectWritten(value, position = rout.getPosition()); + } + } + } + + int value_tag = vt_VALUE_TAG; + + if (ids instanceof String) + value_tag |= vf_ID; + else if (ids instanceof String[]) + // OMG standard requires to set both flags. + value_tag |= vf_MULTIPLE_IDS | vf_ID; + + int chunkSizeLocation; + + OutputStream outObj; + + if (USE_CHUNKING) + { + // Wrap the value being written into one chunk (makes sense only for + // compatibility reasons). + outObj = output; + value_tag |= vf_CHUNKING; + } + else + outObj = output; + + output.write_long(value_tag); + + if ((value_tag & vf_MULTIPLE_IDS) != 0) + write_string_array(output, (String[]) ids); + else if ((value_tag & vf_ID) != 0) + write_string(output, (String) ids); + + if (USE_CHUNKING) + { + // So far, write 0x55555555 instead of the chunk size (alignment may + // take place). + output.write_long(0x55555555); + // If the chunking is involved, the chunk size must be written here. + chunkSizeLocation = rout.getPosition() - INT_SIZE; + } + else + // Not in use for this case. + chunkSizeLocation = -1; + + writeValue(outObj, value, helper); + + if (USE_CHUNKING) + { + // Write the chunk size where the place for it was reserved. + int chunkSize = rout.getPosition() - chunkSizeLocation - INT_SIZE; + int current = rout.getPosition(); + rout.seek(chunkSizeLocation); + output.write_long(chunkSize); + rout.seek(current); + + // The end of record marker. + output.write_long(-1); + } + } + finally + { + if (runtime != null) + runtime.target = null; + } + } + + /** + * Write value (after header). + */ + static void writeValue(OutputStream output, Serializable value, + BoxedValueHelper helper) + { + ((gnuValueStream) output).getRunTime().target = value; + if (helper != null) + helper.write_value(output, value); + else if (!writeSelf(output, value)) + { + // Try to find helper via class loader. + boolean ok = false; + + if (!ok) + { + if (output instanceof BufferedCdrOutput) + { + BufferedCdrOutput b = (BufferedCdrOutput) output; + if (b.runtime == null) + b.runtime = new gnuRuntime(null, value); + } + + handler.writeValue(output, value); + } + } + } + + /** + * Try to write value supposing that it implements self-streamable interfaces. + * Return false if it does not or true on success. + */ + static boolean writeSelf(OutputStream output, Serializable value) + { + // User defined write method is present. + if (value instanceof CustomMarshal) + { + ((CustomMarshal) value).marshal((DataOutputStream) output); + return true; + } + else if (value instanceof Streamable) + { + ((Streamable) value)._write(output); + return true; + } + return false; + } + + /** + * Read the indirection data and return the object that was already written to + * this stream. + * + * @param an_input the input stream, must be BufferredCdrInput. + */ + static Serializable readIndirection(InputStream an_input) + { + if (!(an_input instanceof gnuValueStream)) + throw new NO_IMPLEMENT(gnuValueStream.class.getName() + + " expected as parameter"); + + gnuValueStream in = (gnuValueStream) an_input; + + int current_pos = in.getPosition(); + + int offset = an_input.read_long(); + if (offset > -INT_SIZE) + { + MARSHAL m = new MARSHAL("Indirection tag refers to " + offset + + " (must be less than -" + INT_SIZE + ")"); + m.minor = Minor.Offset; + throw m; + } + + int stored_at = current_pos + offset; + + if (in.getRunTime() == null) + { + MARSHAL m = new MARSHAL(stored_at + " offset " + offset + ": not written"); + m.minor = Minor.Value; + throw m; + } + + return (Serializable) in.getRunTime().isObjectWrittenAt(stored_at, offset); + } + + /** + * Check the passed value tag for correctness. + * + * @param value_tag a tag to check, must be between 0x7fffff00 and 0x7fffffff + * + * @throws MARSHAL if the tag is outside this interval. + */ + static void checkTag(int value_tag) + { + if ((value_tag < 0x7fffff00 || value_tag > 0x7fffffff) + && value_tag != vt_NULL && value_tag != vt_INDIRECTION) + { + MARSHAL m = new MARSHAL("Invalid value record, unsupported header tag: " + + value_tag + " (0x" + Integer.toHexString(value_tag) + ")"); + m.minor = Minor.ValueHeaderTag; + throw m; + } + + if ((value_tag & vf_MULTIPLE_IDS) != 0 && (value_tag & vf_ID) == 0) + { + MARSHAL m = new MARSHAL("Invalid value record header flag combination (0x" + + Integer.toHexString(value_tag) + ")"); + m.minor = Minor.ValueHeaderFlags; + throw m; + } + } + + /** + * Throw MARSHAL. + */ + static void throwIt(String msg, String id1, String id2, Throwable e) + throws MARSHAL + { + MARSHAL m = new MARSHAL(msg + ":'" + id1 + "' versus '" + id2 + "'"); + if (e != null) + m.initCause(e); + m.minor = Minor.Value; + throw m; + } + + /** + * Load class by name and create the instance. + */ + static Object createInstance(String id, String[] ids, String codebase) + { + Object o = null; + + if (id != null) + o = _createInstance(id, codebase); + + if (ids != null) + for (int i = 0; i < ids.length && o == null; i++) + o = _createInstance(ids[i], codebase); + return o; + } + + static Object _createInstance(String id, String codebase) + { + if (id == null) + return null; + if (id.equals(StringValueHelper.id())) + return ""; + StringTokenizer st = new StringTokenizer(id, ":"); + + String prefix = st.nextToken(); + if (prefix.equalsIgnoreCase("IDL")) + return ObjectCreator.Idl2Object(id); + else if (prefix.equalsIgnoreCase("RMI")) + { + String className = st.nextToken(); + String hashCode = st.nextToken(); + String sid = null; + if (st.hasMoreElements()) + sid = st.nextToken(); + + try + { + Class objectClass = Util.loadClass(className, codebase, + Vio.class.getClassLoader()); + + String rid = ObjectCreator.getRepositoryId(objectClass); + + if (!rid.equals(id)) + { + // If direct string comparison fails, compare by meaning. + StringTokenizer st2 = new StringTokenizer(rid, ":"); + if (!st2.nextToken().equals("RMI")) + throw new InternalError("RMI format expected: '" + rid + "'"); + if (!st2.nextToken().equals(className)) + throwIt("Class name mismatch", id, rid, null); + + try + { + long h1 = Long.parseLong(hashCode, 16); + long h2 = Long.parseLong(st2.nextToken(), 16); + if (h1 != h2) + throwIt("Hashcode mismatch", id, rid, null); + + if (sid != null && st2.hasMoreTokens()) + { + long s1 = Long.parseLong(hashCode, 16); + long s2 = Long.parseLong(st2.nextToken(), 16); + if (s1 != s2) + throwIt("serialVersionUID mismatch", id, rid, null); + } + } + catch (NumberFormatException e) + { + throwIt("Invalid hashcode or svuid format: ", id, rid, e); + } + } + + // Low - level instantiation required here. + return instantiateAnyWay(objectClass); + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("Unable to instantiate " + id); + m.minor = Minor.Instantiation; + m.initCause(ex); + throw m; + } + } + else + throw new NO_IMPLEMENT("Unsupported prefix " + prefix + ":"); + } + + /** + * Read string, expecting the probable indirection. + */ + static String read_string(InputStream input) + { + gnuValueStream g = (gnuValueStream) input; + int previous = g.getPosition(); + int l = input.read_long(); + if (l != vt_INDIRECTION) + { + g.seek(previous); + String s = input.read_string(); + if (g.getRunTime() == null) + g.setRunTime(new gnuRuntime(null, null)); + g.getRunTime().singleIdWritten(s, previous); + return s; + } + else + { + gnuRuntime r = g.getRunTime(); + int base = g.getPosition(); + int delta = input.read_long(); + if (r == null) + { + previous = g.getPosition(); + g.seek(base + delta); + String indir = input.read_string(); + g.seek(previous); + return indir; + } + else + { + return (String) r.isObjectWrittenAt(base + delta, delta); + } + } + } + + /** + * Read string array, expecting the probable indirection. + */ + static String[] read_string_array(InputStream input) + { + gnuValueStream g = (gnuValueStream) input; + int previous = g.getPosition(); + int l = input.read_long(); + if (l != vt_INDIRECTION) + { + g.seek(previous); + String[] s = StringSeqHelper.read(input); + if (g.getRunTime() == null) + g.setRunTime(new gnuRuntime(null, null)); + g.getRunTime().objectWritten(s, previous); + return s; + } + else + { + gnuRuntime r = g.getRunTime(); + int base = g.getPosition(); + int delta = input.read_long(); + if (r == null) + { + previous = g.getPosition(); + g.seek(base + delta); + String[] indir = StringSeqHelper.read(input); + g.seek(previous); + return indir; + } + else + { + return (String[]) r.isObjectWrittenAt(base + delta, delta); + } + } + } + + /** + * Write repository Id, probably shared. + */ + static void write_string(OutputStream output, String id) + { + if (output instanceof gnuValueStream) + { + gnuValueStream b = (gnuValueStream) output; + if (b != null) + { + int written = b.getRunTime().idWrittenAt(id); + if (written >= 0) + { + // Reuse existing id record. + output.write_long(vt_INDIRECTION); + int p = b.getPosition(); + output.write_long(written - p); + } + else + { + b.getRunTime().singleIdWritten(id, b.getPosition()); + output.write_string(id); + } + } + } + else + output.write_string(id); + } + + /** + * Write repository Id, probably shared. + */ + static void write_string_array(OutputStream output, String[] ids) + { + if (output instanceof gnuValueStream) + { + gnuValueStream b = (gnuValueStream) output; + if (b != null) + { + int written = b.getRunTime().idWrittenAt(ids); + if (written >= 0) + { + // Reuse existing id record. + output.write_long(vt_INDIRECTION); + int p = b.getPosition(); + output.write_long(written - p); + } + else + { + b.getRunTime().multipleIdsWritten(ids, b.getPosition()); + StringSeqHelper.write(output, ids); + } + } + } + else + StringSeqHelper.write(output, ids); + } + + /** + * Get the helper that could write the given object, or null if no pre-defined + * helper available for this object. + */ + public static BoxedValueHelper getHelper(Class x, Object ids) + { + if (x != null && x.equals(String.class)) + return m_StringValueHelper; + else if (x != null && x.isArray()) + return new ArrayValueHelper(x); + else if (ids instanceof String) + return locateHelper((String) ids); + else if (ids instanceof String[]) + { + String[] ia = (String[]) ids; + BoxedValueHelper h; + for (int i = 0; i < ia.length; i++) + { + h = locateHelper(ia[i]); + if (h != null) + return h; + } + return null; + } + else + return null; + } + + /** + * Get the helper that could write the given object, or null if no pre-defined + * helper available for this object. + */ + public static BoxedValueHelper getHelper(Class x, String id) + { + if (x != null && x.equals(String.class)) + return m_StringValueHelper; + else if (x != null && x.isArray()) + return new ArrayValueHelper(x); + else + return locateHelper(id); + } + + /** + * Try to locate helper from the repository id. + */ + static BoxedValueHelper locateHelper(String id) + { + if (id != null) + { + if (id.equals(m_StringValueHelper.get_id())) + return m_StringValueHelper; + else + // Try to locate helper for IDL type. + if (id.startsWith("IDL:")) + { + try + { + Class helperClass = ObjectCreator.findHelper(id); + if (BoxedValueHelper.class.isAssignableFrom(helperClass)) + return (BoxedValueHelper) helperClass.newInstance(); + else if (helperClass != null) + return new IDLTypeHelper(helperClass); + else + return null; + } + catch (Exception ex) + { + return null; + } + } + } + return null; + } + + /** + * Get the current position. + */ + static int getCurrentPosition(InputStream x) + { + if (x instanceof gnuValueStream) + return ((gnuValueStream) x).getPosition(); + else + return 0; + } + + /** + * Instantiate an instance of this class anyway; also in the case when it has + * no parameterless or any other constructor. The fields will be assigned + * while reading the class from the stream. + * + * @param clazz a class for that the instance should be instantiated. + */ + public static Object instantiateAnyWay(Class clazz) + throws Exception + { + Class first_nonserial = clazz; + + while (Serializable.class.isAssignableFrom(first_nonserial) + || Modifier.isAbstract(first_nonserial.getModifiers())) + first_nonserial = first_nonserial.getSuperclass(); + + final Class local_constructor_class = first_nonserial; + + Constructor constructor = local_constructor_class.getDeclaredConstructor(new Class[0]); + + return VMVio.allocateObject(clazz, constructor.getDeclaringClass(), + constructor); + } +} diff --git a/libjava/classpath/gnu/CORBA/CDR/gnuRuntime.java b/libjava/classpath/gnu/CORBA/CDR/gnuRuntime.java new file mode 100644 index 000000000..1d07094e9 --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/gnuRuntime.java @@ -0,0 +1,338 @@ +/* gnuRuntime.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.Minor; + +import gnu.java.lang.CPStringBuilder; + +import org.omg.CORBA.LocalObject; +import org.omg.CORBA.MARSHAL; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * Our implementation of the sending context runtime. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class gnuRuntime + extends LocalObject + implements org.omg.SendingContext.RunTime +{ + /** + * The data entry about the object that was written. + */ + static class Entry + { + /** + * The stream position, where the object was written. + */ + int at; + + /** + * The object that was written. + */ + Object object; + + public String toString() + { + return object + "[" + at + "] "+object.getClass().getName(); + } + } + + /** + * The instruction that the actual object is stored at different location. + * Used when processing chunked data where positions shifts due removing the + * chunking tags. + */ + static class Redirection + extends Entry + { + public String toString() + { + return "->" + at; + } + } + + /** + * Use serialVersionUID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** + * The history of the written objects, maps object to records. The different + * objects must be treated as different regardless that .equals returns. + */ + private Map sh_objects = new IdentityHashMap(); + + /** + * The written repository Ids that can be shared. + */ + private Map sh_ids = new TreeMap(new Comparator() + { + public int compare(Object a, Object b) + { + if (a instanceof String && b instanceof String) + // Comparing string with string. + return ((String) a).compareTo((String) b); + else if (a instanceof String[] && b instanceof String[]) + { + // Comparing array with array. + String[] sa = (String[]) a; + String[] sb = (String[]) b; + + if (sa.length != sb.length) + return sa.length - sb.length; + else + { + int c; + for (int i = 0; i < sa.length; i++) + { + c = sa[i].compareTo(sb[i]); + if (c != 0) + return c; + } + return 0; + } + } + else + // Comparing string with array. + return a instanceof String ? 1 : -1; + } + }); + + /** + * The history of the written objects, maps positions to records. The + * different objects must be treated as different regardless that .equals + * returns. + */ + private Map positions = new HashMap(); + + /** + * The Codebase. + */ + private String codebase; + + /** + * The pre-created instance of the object being written (avoid + * re-instantiation). + */ + public Serializable target; + + /** + * Create Runtime. + * + * @param a_id a repository Id, if only one Id was specified in the stream. + * @param a_ids a repository Ids, if the multiple Ids were specified in te + * stream. + * @param a_codebase a codebase, if it was specified in the stream. + */ + public gnuRuntime(String a_codebase, Object a_target) + { + if (a_target instanceof Serializable) + target = (Serializable) a_target; + + codebase = a_codebase; + } + + /** + * Mark the given object as written at the given position. + */ + public void objectWritten(Object object, int at) + { + if (object == null || at < 0) + return; // No positional information provided. + if (sh_objects.containsKey(object)) + throw new AssertionError("Repetetive writing of the same object " + + object + " at " + at + dump()); + + Entry e = new Entry(); + e.at = at; + e.object = object; + + sh_objects.put(object, e); + positions.put(new Integer(at), e); + } + + /** + * Check if the object is already written. + * + * @return the position, at that the object is allready written or -1 if it is + * not yet written. + */ + public int isWrittenAt(Object x) + { + Entry e = (Entry) sh_objects.get(x); + return e == null ? -1 : e.at; + } + + /** + * Set redirection, indicating that the object, searched at the p_searched + * position can be actually found at the p_present position. + */ + public void redirect(int p_searched, int p_present) + { + Redirection redirection = new Redirection(); + redirection.at = p_present; + positions.put(new Integer(p_searched), redirection); + } + + /** + * Get the object, written at the given position. This returs both shared + * objects and repository Ids. + * + * @return the position, at that the object is allready written. + * + * @throws MARSHAL if there is no object written at that position. + */ + public Object isObjectWrittenAt(int x, int offset) + { + Entry e = (Entry) positions.get(new Integer(x)); + if (e instanceof Redirection) + return isObjectWrittenAt(e.at, offset); + else if (e != null) + return e.object; + else + { + MARSHAL m = new MARSHAL("No object was written at " + x + + " (offset " + offset + ") r " + this + dump()); + m.minor = Minor.Graph; + throw m; + } + } + + /** + * Mark the given object as written at the given position. + */ + public void singleIdWritten(String id, int at) + { + if (sh_ids.containsKey(id)) + throw new InternalError("Repetetive writing of the same string " + + id + dump()); + + Entry e = new Entry(); + e.at = at; + e.object = id; + + sh_ids.put(id, e); + positions.put(new Integer(at), e); + } + + /** + * Mark the given object as written at the given position. + */ + public void multipleIdsWritten(String[] ids, int at) + { + if (sh_ids.containsKey(ids)) + throw new InternalError("Repetetive writing of the same string " + + ids + dump()); + + Entry e = new Entry(); + e.at = at; + e.object = ids; + + sh_ids.put(ids, e); + positions.put(new Integer(at), e); + } + + /** + * Check if the object is already written. + * + * @return the position, at that the object is allready written or -1 if it is + * not yet written. + */ + public int idWrittenAt(Object x) + { + Entry e = (Entry) sh_ids.get(x); + return e == null ? -1 : e.at; + } + + /** + * Get the codebase. + */ + public String getCodeBase() + { + return codebase; + } + + /** + * Set the codebase, preserving the old value if the passed parameter is null + * and forming the space delimited list if both new and old values are not + * null. + */ + public void addCodeBase(String base) + { + if (base != null) + { + if (codebase == null) + codebase = base; + else + codebase = codebase + " " + base; + } + } + + /** + * Dump all objects that are currently stored. + */ + public String dump() + { + CPStringBuilder b = new CPStringBuilder(" Stream content: \n"); + + // Sort by position. + TreeSet t = new TreeSet(positions.keySet()); + Iterator p = t.iterator(); + + while (p.hasNext()) + { + Object k = p.next(); + b.append(" " + k + ": " + ((Entry) positions.get(k)).toString() + + "\n"); + } + return b.toString(); + } + +} diff --git a/libjava/classpath/gnu/CORBA/CDR/gnuValueStream.java b/libjava/classpath/gnu/CORBA/CDR/gnuValueStream.java new file mode 100644 index 000000000..95d9edb2e --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/gnuValueStream.java @@ -0,0 +1,71 @@ +/* gnuValueStream.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; + +/** + * A stream, implementing this interface, provides methods to get/set a position + * and get the RunTime. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public interface gnuValueStream +{ + /** + * Get the current position in the buffer. + * + * @return The position in the buffer, taking offset into consideration. + */ + public int getPosition(); + + /** + * Jump to the given position, taking offset into consideration. + */ + public void seek(int position); + + /** + * Get the RunTime information. + */ + public gnuRuntime getRunTime(); + + /** + * Replace the instance of RunTime. + */ + public void setRunTime(gnuRuntime a_runtime); + +} |