diff options
| author | mark <mark@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-15 23:20:01 +0000 |
|---|---|---|
| committer | mark <mark@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-15 23:20:01 +0000 |
| commit | 3b3101d8b5ae4f08a16c0b7111da6cad41bbd282 (patch) | |
| tree | a5eb7cf42a51869cc8aa1fad7ad6a90cca47fdd8 /libjava/classpath/gnu/CORBA/CDR | |
| parent | 7e55c49d7d91ef9f09e93c1100119b1ab3652446 (diff) | |
| download | ppe42-gcc-3b3101d8b5ae4f08a16c0b7111da6cad41bbd282.tar.gz ppe42-gcc-3b3101d8b5ae4f08a16c0b7111da6cad41bbd282.zip | |
Imported GNU Classpath 0.19 + gcj-import-20051115.
* sources.am: Regenerated.
* Makefile.in: Likewise.
* scripts/makemake.tcl: Use glob -nocomplain.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@107049 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/classpath/gnu/CORBA/CDR')
22 files changed, 3733 insertions, 961 deletions
diff --git a/libjava/classpath/gnu/CORBA/CDR/cdrInput.java b/libjava/classpath/gnu/CORBA/CDR/AbstractCdrInput.java index 69f9c8c5837..866ec2cc945 100644 --- a/libjava/classpath/gnu/CORBA/CDR/cdrInput.java +++ b/libjava/classpath/gnu/CORBA/CDR/AbstractCdrInput.java @@ -1,4 +1,4 @@ -/* cdrInput.java -- +/* AbstractCdrInput.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,16 +39,17 @@ exception statement from your version. */ package gnu.CORBA.CDR; import gnu.CORBA.BigDecimalHelper; -import gnu.CORBA.Functional_ORB; +import gnu.CORBA.OrbFunctional; import gnu.CORBA.GIOP.CharSets_OSF; -import gnu.CORBA.GIOP.cxCodeSet; +import gnu.CORBA.GIOP.CodeSetServiceContext; import gnu.CORBA.IOR; -import gnu.CORBA.IOR_Delegate; +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.stubFinder; +import gnu.CORBA.StubLocator; import org.omg.CORBA.Any; import org.omg.CORBA.AnySeqHolder; @@ -81,38 +82,44 @@ 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. - * + * 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 cdrInput +public abstract class AbstractCdrInput extends org.omg.CORBA_2_3.portable.InputStream implements org.omg.CORBA.DataInputStream { /** - * 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. + * 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. + * This instance is used to convert primitive data types into the byte + * sequences. */ - protected abstractDataInputStream b; + protected AbstractDataInput b; /** - * The input stream, from where the data are actually - * being read. + * The input stream, from where the data are actually being read. */ protected java.io.InputStream actual_stream; @@ -129,71 +136,68 @@ public abstract class cdrInput /** * The code set information. */ - protected cxCodeSet codeset = cxCodeSet.STANDARD; + protected CodeSetServiceContext codeset = CodeSetServiceContext.STANDARD; /** - * The name of the currently used narrow charset, null if - * the native narrow charset is used. + * 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. + * 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. + * 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. + * 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). + * 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. - * + * Creates the stream. The stream reads Big Endian by default. + * * @param readFrom a stream to read CORBA input from. */ - public cdrInput(java.io.InputStream readFrom) + public AbstractCdrInput(java.io.InputStream readFrom) { setInputStream(readFrom); - setCodeSet(cxCodeSet.STANDARD); + setCodeSet(CodeSetServiceContext.STANDARD); } /** - * Creates the stream, requiring the subsequent call - * of {@link #setInputStream(java.io.InputStream)}. + * Creates the stream, requiring the subsequent call of + * {@link #setInputStream(java.io.InputStream)}. */ - public cdrInput() + public AbstractCdrInput() { - setCodeSet(cxCodeSet.STANDARD); + setCodeSet(CodeSetServiceContext.STANDARD); } /** - * Set the Big Endian or Little Endian encoding. - * The stream reads Big Endian by default. - * - * @param use_little_endian if true, the stream expect - * the multi-byte data in the form "less significant byte - * first" (Little Endian). This is the opposite to the - * java standard (Big Endian). + * Set the Big Endian or Little Endian encoding. The stream reads Big Endian + * by default. + * + * @param use_little_endian if true, the stream expect the multi-byte data in + * the form "less significant byte first" (Little Endian). This is the + * opposite to the java standard (Big Endian). */ public void setBigEndian(boolean use_big_endian) { @@ -202,8 +206,29 @@ public abstract class cdrInput } /** + * Get the used encoding. + * + * @param true for Big Endian, false for Little Endian. + */ + public boolean isBigEndian() + { + return !little_endian; + } + + /** + * Clone all important settings to another stream. + */ + public void cloneSettings(AbstractCdrInput stream) + { + stream.setBigEndian(isBigEndian()); + stream.setCodeSet(getCodeSet()); + stream.setVersion(giop); + stream.setOrb(orb); + } + + /** * Set the input stream that receives the CORBA input. - * + * * @param readFrom the stream. */ public void setInputStream(java.io.InputStream readFrom) @@ -217,13 +242,14 @@ public abstract class cdrInput } /** - * Set the alignment offset, if the index of the first byte in the - * stream is different from 0. + * 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) @@ -232,8 +258,8 @@ public abstract class cdrInput } /** - * Set the GIOP version. Some data types are written differently - * for the different versions. The default version is 1.0 . + * 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) { @@ -246,8 +272,8 @@ public abstract class cdrInput public abstract void align(int boundary); /** - * Reads the CORBA unsigned long (java int), returning the - * value in the sufficiently large java long. + * Reads the CORBA unsigned long (java int), returning the value in the + * sufficiently large java long. */ public long gnu_read_ulong() { @@ -260,6 +286,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -270,8 +297,8 @@ public abstract class cdrInput } /** - * Read the unsigned short integer value and return it as java - * int, sufficiently large to hold all values. + * Read the unsigned short integer value and return it as java int, + * sufficiently large to hold all values. */ public int gnu_read_ushort() { @@ -283,6 +310,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -295,6 +323,7 @@ public abstract class cdrInput /** * Return the associated {@link ORB}. + * * @return the associated {@link ORB} or null is no such is set. */ public ORB orb() @@ -306,7 +335,7 @@ public abstract class cdrInput * Read a single byte directly from the buffer. */ public int read() - throws java.io.IOException + throws java.io.IOException { try { @@ -315,6 +344,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -324,7 +354,7 @@ public abstract class cdrInput * Read bytes directly from the buffer. */ public int read(byte[] x, int ofs, int len) - throws java.io.IOException + throws java.io.IOException { try { @@ -333,6 +363,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -342,7 +373,7 @@ public abstract class cdrInput * Read bytes directly from the buffer. */ public int read(byte[] x) - throws java.io.IOException + throws java.io.IOException { try { @@ -351,24 +382,25 @@ public abstract class cdrInput 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. - * + * 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() @@ -384,41 +416,42 @@ public abstract class cdrInput // 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 Functional_ORB) + if (orb instanceof OrbFunctional) { - Functional_ORB forb = (Functional_ORB) orb; + 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 = stubFinder.search(orb, ior); + ObjectImpl impl = StubLocator.search(orb, ior); try { if (impl._get_delegate() == null) - impl._set_delegate(new IOR_Delegate(orb, ior)); + 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 IOR_Delegate(orb, ior)); + impl._set_delegate(new IorDelegate(orb, ior)); } return impl; } catch (IOException ex) { - BAD_OPERATION bad = new BAD_OPERATION(); + 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. + * Read the type code. The type code format is defined in the CORBA + * documenation. */ public TypeCode read_TypeCode() { @@ -438,9 +471,8 @@ public abstract class cdrInput } /** - * Read the CORBA {@link Any}. This method first reads the - * type code, then delegates the functionality - * to {@link Any#read_value}. + * 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() { @@ -451,8 +483,7 @@ public abstract class cdrInput } /** - * Read the boolean, treating any non zero byte as true, - * zero byte as false. + * Read the boolean, treating any non zero byte as true, zero byte as false. */ public boolean read_boolean() { @@ -463,6 +494,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -481,12 +513,13 @@ public abstract class cdrInput { for (int i = offs; i < offs + len; i++) { - x [ i ] = b.read() == 0 ? false : true; + 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; } @@ -498,8 +531,8 @@ public abstract class cdrInput } /** - * Read a character using narrow charset encoding. Depending form - * which encoding is set, this still can be Unicode or ever wider. + * 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() { @@ -513,6 +546,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -533,18 +567,19 @@ public abstract class cdrInput if (narrow_native) { for (int i = offset; i < offset + length; i++) - x [ i ] = (char) b.read(); + x[i] = (char) b.read(); } else { - InputStreamReader reader = - new InputStreamReader((InputStream) b, narrow_charset); + 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; } @@ -568,6 +603,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -588,12 +624,13 @@ public abstract class cdrInput align(8); for (int i = offs; i < offs + len; i++) { - x [ i ] = b.readDouble(); + x[i] = b.readDouble(); } } catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -605,26 +642,24 @@ public abstract class cdrInput } /** - * 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. + * 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 cdrBufInput read_encapsulation() + public BufferredCdrInput read_encapsulation() { try { int l = read_long(); - byte[] r = new byte[ l ]; + byte[] r = new byte[l]; int n = 0; - reading: - while (n < r.length) + reading: while (n < r.length) { n += read(r, n, r.length - n); } - cdrBufInput capsule = new cdrBufInput(r); + BufferredCdrInput capsule = new BufferredCdrInput(r); capsule.setOrb(orb); int endian = capsule.read_octet(); @@ -639,6 +674,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -650,9 +686,8 @@ public abstract class cdrInput } /** - * 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. + * 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() { @@ -663,6 +698,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -686,6 +722,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -706,12 +743,13 @@ public abstract class cdrInput align(4); for (int i = offs; i < offs + len; i++) { - x [ i ] = b.readFloat(); + x[i] = b.readFloat(); } } catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -735,6 +773,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -755,12 +794,13 @@ public abstract class cdrInput align(4); for (int i = offs; i < offs + len; i++) { - x [ i ] = b.readInt(); + x[i] = b.readInt(); } } catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -783,7 +823,9 @@ public abstract class cdrInput } catch (EOFException ex) { - throw new MARSHAL(UNEXP_EOF); + MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; + throw t; } catch (IOException ex) @@ -802,12 +844,13 @@ public abstract class cdrInput align(8); for (int i = offs; i < offs + len; i++) { - x [ i ] = b.readLong(); + x[i] = b.readLong(); } } catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -830,6 +873,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -852,6 +896,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -863,24 +908,24 @@ public abstract class cdrInput } /** - * Read the length of the byte array as CORBA long and then - * the array itseld. + * 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[] b = new byte[ l ]; + byte[] buf = new byte[l]; if (l > 0) { - read(b); + b.readFully(buf); } - return b; + return buf; } catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -904,6 +949,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -924,12 +970,13 @@ public abstract class cdrInput align(2); for (int i = offs; i < offs + len; i++) { - x [ i ] = b.readShort(); + x[i] = b.readShort(); } } catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -941,21 +988,21 @@ public abstract class cdrInput } /** - * 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. - * + * 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); - int n = b.readInt(); - byte[] s = new byte[ n ]; + n = b.readInt(); + byte[] s = new byte[n]; b.read(s); // Discard the null terminator. @@ -967,19 +1014,26 @@ public abstract class cdrInput 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}. + * Reads the CORBA unsigned long (java int), delegating functionality to + * {@link #read_long}. */ public int read_ulong() { @@ -987,9 +1041,8 @@ public abstract class cdrInput } /** - * Reads the array of CORBA unsigned long (java integer) values, - * delegating functionality to - * {@link #real_long_array}. + * 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) { @@ -997,11 +1050,9 @@ public abstract class cdrInput } /** - * 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. + * 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() { @@ -1009,9 +1060,8 @@ public abstract class cdrInput } /** - * Reads the array of CORBA long long (java long) values, - * delegating functionality to - * {@link #real_longlong_array}. + * 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) { @@ -1019,10 +1069,9 @@ public abstract class cdrInput } /** - * 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. + * 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() { @@ -1030,8 +1079,8 @@ public abstract class cdrInput } /** - * Read an array of unsigned short values, delegating the - * functionality to {@link read_short_array}. + * 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) { @@ -1039,24 +1088,64 @@ public abstract class cdrInput } /** - * Reads the wide character using the encoding, specified in the - * wide_charset. + * 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); + { + align(2); - if (wide_native) - return (char) b.readShort(); + if (wide_native) + return (char) b.readShort(); + else + return (char) new InputStreamReader((InputStream) b, wide_charset).read(); + } else - return (char) new InputStreamReader((InputStream) b, wide_charset).read(); + { + 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; } @@ -1067,8 +1156,8 @@ public abstract class cdrInput } /** - * Read an array of "wide chars", each representing a two byte - * Unicode character, high byte first. + * 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) { @@ -1080,18 +1169,19 @@ public abstract class cdrInput if (wide_native) { for (int i = offset; i < offset + length; i++) - x [ i ] = (char) b.readShort(); + x[i] = (char) b.readShort(); } else { - InputStreamReader reader = - new InputStreamReader((InputStream) b, wide_charset); + 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; } @@ -1103,13 +1193,11 @@ public abstract class cdrInput } /** - * 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}. + * 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() { @@ -1121,7 +1209,7 @@ public abstract class cdrInput align(4); int n = b.readInt(); - byte[] s = new byte[ n ]; + byte[] s = new byte[n]; b.read(s); return new String(s, 0, n, wide_charset); @@ -1129,6 +1217,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -1140,9 +1229,9 @@ public abstract class cdrInput } /** - * 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. + * 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() { @@ -1150,6 +1239,13 @@ public abstract class cdrInput { 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; @@ -1157,26 +1253,30 @@ public abstract class cdrInput // Convert bytes to shorts. n = n / 2; - char[] s = new char[ n ]; + // Empty string. + if (n == 0) + return ""; + + char[] s = new char[n]; for (int i = 0; i < s.length; i++) - s [ i ] = (char) b.readShort(); + s[i] = (char) b.readShort(); // Check for the byte order marker here. - if (s [ 0 ] == 0xFEFF) + if (s[0] == 0xFEFF) { // Big endian encoding - do nothing, but move the pointer // one position forward. p = 1; } - else if (s [ 0 ] == 0xFFFE) + 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 ]); + s[i] = swap(s[i]); } // Discard the null terminator and, if needed, the endian marker. @@ -1186,6 +1286,7 @@ public abstract class cdrInput catch (EOFException ex) { MARSHAL t = new MARSHAL(UNEXP_EOF); + t.minor = Minor.EOF; t.initCause(ex); throw t; } @@ -1213,7 +1314,7 @@ public abstract class cdrInput /** * Set the current code set context. */ - public void setCodeSet(cxCodeSet a_codeset) + public void setCodeSet(CodeSetServiceContext a_codeset) { this.codeset = a_codeset; narrow_charset = CharSets_OSF.getName(codeset.char_data); @@ -1226,7 +1327,7 @@ public abstract class cdrInput /** * Get the current code set context. */ - public cxCodeSet getCodeSet() + public CodeSetServiceContext getCodeSet() { return codeset; } @@ -1235,9 +1336,9 @@ public abstract class cdrInput * 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) @@ -1247,11 +1348,11 @@ public abstract class cdrInput /** * 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} - * + * + * 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() @@ -1260,14 +1361,13 @@ public abstract class cdrInput } /** - * 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). - * + * 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() @@ -1276,10 +1376,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1288,10 +1388,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1300,23 +1400,23 @@ public abstract class cdrInput } /** - * If required, allocate or resize the char array to fit the newly - * read values. - * + * 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 ]; + return new char[offset + length]; else if (holder_value.length < offset + length) { - char[] value = new char[ offset + length ]; + char[] value = new char[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1325,10 +1425,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1337,10 +1437,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1349,23 +1449,22 @@ public abstract class cdrInput } /** - * If required, allocate or resize the int array to fit the newly - * read values. - * + * 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 ]; + return new int[offset + length]; else if (holder_value.length < offset + length) { - int[] value = new int[ offset + length ]; + int[] value = new int[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1374,10 +1473,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1386,23 +1485,23 @@ public abstract class cdrInput } /** - * If required, allocate or resize the float array to fit the newly - * read values. - * + * 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 ]; + return new float[offset + length]; else if (holder_value.length < offset + length) { - float[] value = new float[ offset + length ]; + float[] value = new float[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1411,10 +1510,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1423,23 +1522,23 @@ public abstract class cdrInput } /** - * If required, allocate or resize the double array to fit the newly - * read values. - * + * 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 ]; + return new double[offset + length]; else if (holder_value.length < offset + length) { - double[] value = new double[ offset + length ]; + double[] value = new double[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1448,10 +1547,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1467,23 +1566,23 @@ public abstract class cdrInput } /** - * If required, allocate or resize the short array to fit the newly - * read values. - * + * 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 ]; + return new short[offset + length]; else if (holder_value.length < offset + length) { - short[] value = new short[ offset + length ]; + short[] value = new short[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1492,10 +1591,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1504,23 +1603,23 @@ public abstract class cdrInput } /** - * If required, allocate or resize the byte array to fit the newly - * read values. - * + * 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 ]; + return new byte[offset + length]; else if (holder_value.length < offset + length) { - byte[] value = new byte[ offset + length ]; + byte[] value = new byte[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1529,51 +1628,49 @@ public abstract class cdrInput } /** - * 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. + * 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 - ) + 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. + * 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 - ) + 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. - * + * 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 ]; + return new long[offset + length]; else if (holder_value.length < offset + length) { - long[] value = new long[ offset + length ]; + long[] value = new long[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1582,10 +1679,10 @@ public abstract class cdrInput } /** - * 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. + * 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) { @@ -1594,23 +1691,23 @@ public abstract class cdrInput } /** - * If required, allocate or resize the array of booleans to fit the newly - * read values. - * + * 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 ]; + return new boolean[offset + length]; else if (holder_value.length < offset + length) { - boolean[] value = new boolean[ offset + length ]; + boolean[] value = new boolean[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1619,38 +1716,38 @@ public abstract class cdrInput } /** - * 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. + * 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(); + holder.value[i] = read_any(); } } /** - * If required, allocate or resize the array of Anys to fit the newly - * read values. - * + * 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 ]; + return new Any[offset + length]; else if (holder_value.length < offset + length) { - Any[] value = new Any[ offset + length ]; + Any[] value = new Any[offset + length]; System.arraycopy(holder_value, 0, value, 0, holder_value.length); return value; } @@ -1659,11 +1756,10 @@ public abstract class cdrInput } /** - * 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. + * 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() { diff --git a/libjava/classpath/gnu/CORBA/CDR/cdrOutput.java b/libjava/classpath/gnu/CORBA/CDR/AbstractCdrOutput.java index 85f341c912d..7b4d5ec58ff 100644 --- a/libjava/classpath/gnu/CORBA/CDR/cdrOutput.java +++ b/libjava/classpath/gnu/CORBA/CDR/AbstractCdrOutput.java @@ -1,4 +1,4 @@ -/* cdrOutput.java -- +/* AbstractCdrOutput.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,27 +39,28 @@ exception statement from your version. */ package gnu.CORBA.CDR; import gnu.CORBA.BigDecimalHelper; -import gnu.CORBA.GIOP.CharSets_OSF; -import gnu.CORBA.GIOP.cxCodeSet; -import gnu.CORBA.Poa.gnuServantObject; import gnu.CORBA.IOR; -import gnu.CORBA.Simple_delegate; +import gnu.CORBA.IorProvider; +import gnu.CORBA.Minor; import gnu.CORBA.TypeCodeHelper; import gnu.CORBA.Unexpected; import gnu.CORBA.Version; -import gnu.CORBA.primitiveTypeCode; +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.TypeCodePackage.BadKind; 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; @@ -68,7 +69,6 @@ import org.omg.CORBA.portable.Streamable; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Serializable; - import java.math.BigDecimal; /** @@ -79,18 +79,27 @@ import java.math.BigDecimal; * 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 cdrOutput +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 abstractDataOutputStream b; + protected AbstractDataOutput b; /** * The associated orb, if any. @@ -105,7 +114,7 @@ public abstract class cdrOutput /** * The code set information. */ - protected cxCodeSet codeset; + protected CodeSetServiceContext codeset; /** * The name of the currently used narrow charset. @@ -148,19 +157,19 @@ public abstract class cdrOutput * * @param writeTo a stream to write CORBA output to. */ - public cdrOutput(java.io.OutputStream writeTo) + public AbstractCdrOutput(java.io.OutputStream writeTo) { setOutputStream(writeTo); - setCodeSet(cxCodeSet.STANDARD); + setCodeSet(CodeSetServiceContext.STANDARD); } /** * Creates the stream, requiring the subsequent call * of {@link #setOutputStream(java.io.OutputStream)}. */ - public cdrOutput() + public AbstractCdrOutput() { - setCodeSet(cxCodeSet.STANDARD); + setCodeSet(CodeSetServiceContext.STANDARD); } /** @@ -168,11 +177,22 @@ public abstract class cdrOutput * 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(cxCodeSet a_codeset) + public void setCodeSet(CodeSetServiceContext a_codeset) { this.codeset = a_codeset; narrow_charset = CharSets_OSF.getName(codeset.char_data); @@ -185,7 +205,7 @@ public abstract class cdrOutput /** * Get the current code set context. */ - public cxCodeSet getCodeSet() + public CodeSetServiceContext getCodeSet() { return codeset; } @@ -255,9 +275,9 @@ public abstract class cdrOutput * * @return the encapsulated stream. */ - public cdrOutput createEncapsulation() + public AbstractCdrOutput createEncapsulation() { - return new encapsulatedOutput(this, !little_endian); + return new EncapsulationStream(this, !little_endian); } /** @@ -313,53 +333,56 @@ public abstract class cdrOutput } /** - * 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). - */ + * 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) { - if (x == null) + ORB w_orb = orb; + if (x instanceof IorProvider) { - IOR.write_null(this); + ((IorProvider) x).getIor()._write_no_endian(this); return; } - else if (x instanceof gnuServantObject) + else if (x == null) { - // The ORB may be different if several ORBs coexist - // in the same machine. - gnuServantObject g = (gnuServantObject) x; - IOR ior = g.orb.getLocalIor(x); - ior._write_no_endian(this); + IOR.write_null(this); return; } else if (x instanceof ObjectImpl) { Delegate d = ((ObjectImpl) x)._get_delegate(); - if (d instanceof Simple_delegate) + if (d instanceof IorProvider) { - Simple_delegate ido = (Simple_delegate) d; - ido.getIor()._write_no_endian(this); + ((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 (orb != null) + if (w_orb != null) { - IOR ior = IOR.parse(orb.object_to_string(x)); + 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."); + throw new BAD_OPERATION( + "Please set the ORB for this stream, cannot write " + + x.getClass().getName()); } /** @@ -399,7 +422,7 @@ public abstract class cdrOutput } else { - primitiveTypeCode p = new primitiveTypeCode(TCKind.tk_null); + PrimitiveTypeCode p = new PrimitiveTypeCode(TCKind.tk_null); write_TypeCode(p); } } @@ -726,6 +749,7 @@ public abstract class cdrOutput catch (IOException ex) { MARSHAL t = new MARSHAL(); + t.minor = Minor.CDR; t.initCause(ex); throw t; } @@ -737,7 +761,7 @@ public abstract class cdrOutput * representing the stream buffer length (the number of * bytes being subsequently written). */ - public void write_sequence(cdrBufOutput from) + public void write_sequence(BufferedCdrOutput from) { try { @@ -747,6 +771,7 @@ public abstract class cdrOutput catch (IOException ex) { MARSHAL t = new MARSHAL(); + t.minor = Minor.CDR; t.initCause(ex); throw t; } @@ -874,28 +899,41 @@ public abstract class cdrOutput } /** - * 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. + * 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); + { + align(2); - if (wide_native) - b.writeShort(x); + 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 { - OutputStreamWriter ow = - new OutputStreamWriter((OutputStream) b, wide_charset); - ow.write(x); - ow.flush(); + String encoded = new String(new char[] { x }); + byte[] bytes = encoded.getBytes(wide_charset); + b.write(bytes.length + 2); + b.write(bytes); } } catch (IOException ex) @@ -906,13 +944,13 @@ public abstract class cdrOutput /** * 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. + * + * 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) { @@ -998,12 +1036,12 @@ public abstract class cdrOutput /** {@inheritDoc} */ public void write_Abstract(java.lang.Object value) { - write_Abstract(value); + write_abstract_interface(value); } /** {@inheritDoc} */ public void write_Value(Serializable value) { - write_Value(value); + write_value(value); } }
\ No newline at end of file diff --git a/libjava/classpath/gnu/CORBA/CDR/abstractDataInputStream.java b/libjava/classpath/gnu/CORBA/CDR/AbstractDataInput.java index be926254dd0..4d120fa2c0c 100644 --- a/libjava/classpath/gnu/CORBA/CDR/abstractDataInputStream.java +++ b/libjava/classpath/gnu/CORBA/CDR/AbstractDataInput.java @@ -1,4 +1,4 @@ -/* abstractDataInputStream.java -- +/* AbstractDataInput.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -50,7 +50,7 @@ import java.io.IOException; * @author Warren Levy (warrenl@cygnus.com) * @author Aaron M. Renn (arenn@urbanophile.com) */ -public interface abstractDataInputStream +public interface AbstractDataInput { /** * This method reads bytes from the underlying stream into the specified diff --git a/libjava/classpath/gnu/CORBA/CDR/abstractDataOutputStream.java b/libjava/classpath/gnu/CORBA/CDR/AbstractDataOutput.java index 2f9b8c419fc..e37c0cb7ddd 100644 --- a/libjava/classpath/gnu/CORBA/CDR/abstractDataOutputStream.java +++ b/libjava/classpath/gnu/CORBA/CDR/AbstractDataOutput.java @@ -1,4 +1,4 @@ -/* abstractDataOutputStream.java -- +/* AbstractDataOutput.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -50,7 +50,7 @@ import java.io.IOException; * @author Warren Levy (warrenl@cygnus.com) * @author Aaron M. Renn (arenn@urbanophile.com) */ -public interface abstractDataOutputStream +public interface AbstractDataOutput { /** * This method flushes any unwritten bytes to the underlying stream. diff --git a/libjava/classpath/gnu/CORBA/CDR/aligningInputStream.java b/libjava/classpath/gnu/CORBA/CDR/AligningInput.java index a719b32ee1e..e2710628a52 100644 --- a/libjava/classpath/gnu/CORBA/CDR/aligningInputStream.java +++ b/libjava/classpath/gnu/CORBA/CDR/AligningInput.java @@ -1,4 +1,4 @@ -/* aligningInputStream.java -- +/* AligningInput.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,7 +48,7 @@ import org.omg.CORBA.BAD_PARAM; * * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) */ -public class aligningInputStream +public class AligningInput extends ByteArrayInputStream { /** @@ -61,24 +61,12 @@ public class aligningInputStream * * @param a_buffer a buffer to read from. */ - public aligningInputStream(byte[] a_buffer) + public AligningInput(byte[] a_buffer) { super(a_buffer); } /** - * Create a stream, reading from the given buffer region. - * - * @param a_buffer a buffer to read from. - * @param offset the offset of the region. - * @param length thr length of the region. - */ - public aligningInputStream(byte[] a_buffer, int offset, int length) - { - super(a_buffer, offset, length); - } - - /** * Set the alignment offset, if the index of the first byte in the * stream is different from 0. */ @@ -119,4 +107,25 @@ public class aligningInputStream { 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/aligningOutputStream.java b/libjava/classpath/gnu/CORBA/CDR/AligningOutput.java index 8a682c1fd6d..135f75af6a7 100644 --- a/libjava/classpath/gnu/CORBA/CDR/aligningOutputStream.java +++ b/libjava/classpath/gnu/CORBA/CDR/AligningOutput.java @@ -1,4 +1,4 @@ -/* aligningOutputStream.java -- +/* AligningOutput.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,7 +38,6 @@ exception statement from your version. */ package gnu.CORBA.CDR; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import org.omg.CORBA.BAD_PARAM; @@ -49,7 +48,7 @@ import org.omg.CORBA.BAD_PARAM; * * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) */ -public class aligningOutputStream +public class AligningOutput extends ByteArrayOutputStream { /** @@ -60,14 +59,14 @@ public class aligningOutputStream /** * Create a stream with the default intial buffer size. */ - public aligningOutputStream() + public AligningOutput() { } /** * Create a stream with the given intial buffer size. */ - public aligningOutputStream(int initial_size) + public AligningOutput(int initial_size) { super(initial_size); } @@ -118,4 +117,32 @@ public class aligningOutputStream 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 00000000000..7a4d9c5aa8f --- /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 index bc019396adb..1559d75a41e 100644 --- a/libjava/classpath/gnu/CORBA/CDR/BigEndianInputStream.java +++ b/libjava/classpath/gnu/CORBA/CDR/BigEndianInputStream.java @@ -49,7 +49,7 @@ import java.io.InputStream; */ public class BigEndianInputStream extends DataInputStream - implements abstractDataInputStream + implements AbstractDataInput { /** * Delegates to the parent constructor. diff --git a/libjava/classpath/gnu/CORBA/CDR/BigEndianOutputStream.java b/libjava/classpath/gnu/CORBA/CDR/BigEndianOutputStream.java index e0aa7da773e..7d3b02ec950 100644 --- a/libjava/classpath/gnu/CORBA/CDR/BigEndianOutputStream.java +++ b/libjava/classpath/gnu/CORBA/CDR/BigEndianOutputStream.java @@ -50,7 +50,7 @@ import java.io.OutputStream; */ public class BigEndianOutputStream extends DataOutputStream - implements abstractDataOutputStream + implements AbstractDataOutput { /** * Delegate functionality to the parent constructor. diff --git a/libjava/classpath/gnu/CORBA/CDR/cdrBufOutput.java b/libjava/classpath/gnu/CORBA/CDR/BufferedCdrOutput.java index 47f5f176b39..69bf95beb66 100644 --- a/libjava/classpath/gnu/CORBA/CDR/cdrBufOutput.java +++ b/libjava/classpath/gnu/CORBA/CDR/BufferedCdrOutput.java @@ -1,4 +1,4 @@ -/* cdrBufOutput.java -- +/* BufferedCdrOutput.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,41 +41,47 @@ package gnu.CORBA.CDR; import java.io.ByteArrayOutputStream; /** - * A CORBA output stream, writing data into the internal - * buffer ({@link ByteArrayOutputStream}). - * + * A CORBA output stream, writing data into the internal buffer ({@link ByteArrayOutputStream}). + * * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) */ -public class cdrBufOutput - extends cdrOutput +public class BufferedCdrOutput + extends AbstractCdrOutput + implements gnuValueStream { /** + * Use serialVersionUID for interoperability. + */ + private static final long serialVersionUID = 1; + + /** * The byte buffer. */ - public final aligningOutputStream buffer; + public final AligningOutput buffer; /** * Creates the instance with the given initial buffer size. + * * @param bufSize the buffer size. */ - public cdrBufOutput(int bufSize) + public BufferedCdrOutput(int bufSize) { - buffer = new aligningOutputStream(bufSize); + buffer = new AligningOutput(bufSize); setOutputStream(buffer); } /** * Creates the instance with the default buffer size. */ - public cdrBufOutput() + public BufferedCdrOutput() { - buffer = new aligningOutputStream(); + buffer = new AligningOutput(); setOutputStream(buffer); } /** - * Set the alignment offset, if the index of the first byte in the - * stream is different from 0. + * Set the alignment offset, if the index of the first byte in the stream is + * different from 0. */ public void setOffset(int an_offset) { @@ -95,7 +101,7 @@ public class cdrBufOutput */ public org.omg.CORBA.portable.InputStream create_input_stream() { - cdrBufInput in = new cdrBufInput(buffer.toByteArray()); + BufferredCdrInput in = new BufferredCdrInput(buffer.toByteArray()); in.setOrb(orb); in.setVersion(giop); @@ -112,4 +118,39 @@ public class cdrBufOutput 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/cdrBufInput.java b/libjava/classpath/gnu/CORBA/CDR/BufferredCdrInput.java index 3cab7216c3b..f0159a88dac 100644 --- a/libjava/classpath/gnu/CORBA/CDR/cdrBufInput.java +++ b/libjava/classpath/gnu/CORBA/CDR/BufferredCdrInput.java @@ -1,4 +1,4 @@ -/* cdrBufInput.java -- +/* BufferredCdrInput.java -- Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -43,18 +43,20 @@ package gnu.CORBA.CDR; * The CDR input stream that reads data from the byte buffer. * * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) - * - * TODO character encoding. Now the encoding can be set, but it is ignored. - * If you take this task, scan 'TODO character encoding' for - * relevant places. */ -public class cdrBufInput - extends cdrInput +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 aligningInputStream buffer; + public final AligningInput buffer; /** * Creates the CDR input stream that reads from the given buffer @@ -62,9 +64,9 @@ public class cdrBufInput * * @param a_buffer an array to read from. */ - public cdrBufInput(byte[] a_buffer) + public BufferredCdrInput(byte[] a_buffer) { - buffer = new aligningInputStream(a_buffer); + buffer = new AligningInput(a_buffer); setInputStream(buffer); } @@ -112,4 +114,40 @@ public class cdrBufInput 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/encapsulatedOutput.java b/libjava/classpath/gnu/CORBA/CDR/EncapsulationStream.java index 3350291bc73..4945d9c906a 100644 --- a/libjava/classpath/gnu/CORBA/CDR/encapsulatedOutput.java +++ b/libjava/classpath/gnu/CORBA/CDR/EncapsulationStream.java @@ -48,8 +48,8 @@ import java.io.IOException; * * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) */ -public class encapsulatedOutput - extends cdrOutput +public class EncapsulationStream + extends AbstractCdrOutput { /** * The Big Endian (most siginificant byte first flag). @@ -64,7 +64,7 @@ public class encapsulatedOutput /** * The byte buffer. */ - public final aligningOutputStream buffer; + public final AligningOutput buffer; /** * The stream, where the data are being encapsulated. @@ -75,11 +75,11 @@ public class encapsulatedOutput * Create the EncapsulationOutput with the given parent stream * and the specified encoding. */ - public encapsulatedOutput(org.omg.CORBA.portable.OutputStream _parent, + public EncapsulationStream(org.omg.CORBA.portable.OutputStream _parent, boolean use_big_endian) { super(); - buffer = new aligningOutputStream(); + buffer = new AligningOutput(); setOutputStream(buffer); parent = _parent; write(use_big_endian?BIG_ENDIAN:LITTLE_ENDIAN); @@ -126,7 +126,7 @@ public class encapsulatedOutput */ public org.omg.CORBA.portable.InputStream create_input_stream() { - cdrBufInput in = new cdrBufInput(buffer.toByteArray()); + BufferredCdrInput in = new BufferredCdrInput(buffer.toByteArray()); in.setOrb(orb); in.setVersion(giop); diff --git a/libjava/classpath/gnu/CORBA/CDR/HeadlessInput.java b/libjava/classpath/gnu/CORBA/CDR/HeadlessInput.java new file mode 100644 index 00000000000..0c18dafb195 --- /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_stram 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 = (Serializable) 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 = (Serializable) 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 = (Serializable) 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); + } + +}
\ No newline at end of file diff --git a/libjava/classpath/gnu/CORBA/CDR/IDLTypeHelper.java b/libjava/classpath/gnu/CORBA/CDR/IDLTypeHelper.java new file mode 100644 index 00000000000..3259a48770c --- /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 index b71a9a4f66d..02cfa08ae8e 100644 --- a/libjava/classpath/gnu/CORBA/CDR/LittleEndianInputStream.java +++ b/libjava/classpath/gnu/CORBA/CDR/LittleEndianInputStream.java @@ -55,7 +55,7 @@ import java.io.PushbackInputStream; */ public class LittleEndianInputStream extends FilterInputStream - implements abstractDataInputStream + implements AbstractDataInput { // Byte buffer, used to make primitive read calls more efficient. byte[] buf = new byte[ 8 ]; diff --git a/libjava/classpath/gnu/CORBA/CDR/LittleEndianOutputStream.java b/libjava/classpath/gnu/CORBA/CDR/LittleEndianOutputStream.java index a6d56cfa6d0..6791a82e7c3 100644 --- a/libjava/classpath/gnu/CORBA/CDR/LittleEndianOutputStream.java +++ b/libjava/classpath/gnu/CORBA/CDR/LittleEndianOutputStream.java @@ -55,7 +55,7 @@ import java.io.OutputStream; */ public class LittleEndianOutputStream extends FilterOutputStream - implements abstractDataOutputStream + implements AbstractDataOutput { /** * This method initializes an instance of <code>DataOutputStream</code> to diff --git a/libjava/classpath/gnu/CORBA/CDR/UnknownExceptionCtxHandler.java b/libjava/classpath/gnu/CORBA/CDR/UnknownExceptionCtxHandler.java new file mode 100644 index 00000000000..314dd8eb948 --- /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 00000000000..9b719fd7c50 --- /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 index 0a37132b26f..fd878cb3555 100644 --- a/libjava/classpath/gnu/CORBA/CDR/Vio.java +++ b/libjava/classpath/gnu/CORBA/CDR/Vio.java @@ -1,4 +1,4 @@ -/* gnuValueBaseHelper.java -- +/* Vio.java -- Value type IO operations. Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,6 +38,7 @@ exception statement from your version. */ package gnu.CORBA.CDR; +import gnu.CORBA.Minor; import gnu.CORBA.ObjectCreator; import org.omg.CORBA.CustomMarshal; @@ -46,106 +47,144 @@ 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.ByteArrayOutputStream; import java.io.IOException; import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.util.StringTokenizer; -import java.lang.reflect.Method; +import javax.rmi.CORBA.Util; +import javax.rmi.CORBA.ValueHandler; /** * A specialised class for reading and writing the value types. - * - * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) */ public abstract class Vio { /** - * If true, wrap value type data into chunks. This decrease the - * performance, but is required for the interoperability with - * Sun's CORBA implementation. Chunking may increase the security, - * as there is more control on the number of bytes being transferred. - * + * 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. + * chunks, but will always send a single chunk (if true) or unchunked data (if + * false). */ - public static boolean USE_CHUNKING = true; + 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). + * 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. + * 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. + * 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. + * 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. + * 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). + * 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. + * This tag value means that the value object being transferred is equal to + * null. */ public static final int vt_NULL = 0x0; /** - * 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). - * + * 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. - * + * @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) { - // Explicitly prevent the stream from closing as we may need - // to read the subsequent bytes as well. Stream may be auto-closed - // in its finalizer. + 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 an_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); @@ -154,18 +193,13 @@ public abstract class Vio String codebase = null; String[] ids = null; - String id = null; - - // The existing implementing object. - java.lang.Object ox = null; + String id = repository_id; // Check for the agreed null value. if (value_tag == vt_NULL) return null; else if (value_tag == vt_INDIRECTION) - - // TODO FIXME Implement support for indirections. - throw new NO_IMPLEMENT("Indirections unsupported"); + return readIndirection(input); else { // Read the value. @@ -174,152 +208,173 @@ public abstract class Vio // The codebase is present. The codebase is a space // separated list of URLs from where the implementing // code can be downloaded. - codebase = input.read_string(); + codebase = read_string(input); } if ((value_tag & vf_MULTIPLE_IDS) != 0) { // Multiple supported repository ids are present. - ids = StringSeqHelper.read(input); - for (int i = 0; (i < ids.length) && (ox == null); i++) - { - ox = ObjectCreator.Idl2Object(ids [ i ]); - - if (ox == null) - { - // Try to find the value factory. - ValueFactory f = - ((org.omg.CORBA_2_3.ORB) input.orb()).lookup_value_factory(ids [ i ]); - - if (f != null) - { - // Reset, as the value factory reads from beginning. - input.reset(); - return f.read_value((org.omg.CORBA_2_3.portable.InputStream) input); - } - } - } + ids = read_string_array(input); } else if ((value_tag & vf_ID) != 0) { // Single supported repository id is present. - id = input.read_string(); - ox = ObjectCreator.Idl2Object(id); - - if (ox == null) - { - // Try to find the value factory. - ValueFactory f = - ((org.omg.CORBA_2_3.ORB) input.orb()).lookup_value_factory(id); - - if (f != null) - { - input.reset(); - return f.read_value((org.omg.CORBA_2_3.portable.InputStream) input); - } - } + id = read_string(input); } } - if (ox == null) - throw new MARSHAL("Unable to instantiate the value type"); + 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 - { - read_instance(input, ox, value_tag, null); - return (Serializable) ox; - } + ox = createInstance(id, ids, codebase); + return (Serializable) read_instance(input, position, ox, value_tag, + helper, id, ids, codebase); } catch (Exception ex) { - throw new MARSHAL(ex + ":" + ex.getMessage()); + 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. - * + * 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) { - // Explicitly prevent the stream from closing as we may need - // to read the subsequent bytes as well. Stream may be auto-closed - // in its finalizer. + final int position = getCurrentPosition(input); + + String id = null; + String[] ids = null; + String codebase = null; + try { int value_tag = input.read_long(); checkTag(value_tag); - // The existing implementing object. - java.lang.Object ox = value_class.newInstance(); - // Check for the agreed null value. if (value_tag == vt_NULL) return null; else if (value_tag == vt_INDIRECTION) - - // TODO FIXME Implement support for indirections. - throw new NO_IMPLEMENT("Indirections unsupported"); + return readIndirection(input); else { // Read the value. if ((value_tag & vf_CODEBASE) != 0) { - // The codebase is present, but skip it. - input.read_string(); + // The codebase is present. + codebase = read_string(input); } if ((value_tag & vf_MULTIPLE_IDS) != 0) { - // Multiple supported repository ids are present, but skip them. - StringSeqHelper.read(input); + // Multiple supported repository ids are present. + ids = read_string_array(input); } else if ((value_tag & vf_ID) != 0) { - // Single supported repository id is present, but skip it. - input.read_string(); + // Single supported repository id is present. + id = read_string(input); } } - read_instance(input, ox, value_tag, null); + 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) { - throw new MARSHAL(ex + ":" + ex.getMessage()); + 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. - * + * 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. - * + * + * @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, - Object helper - ) + BoxedValueHelper helper) { + final int position = getCurrentPosition(input); + + String id = null; + String[] ids = null; + String codebase = null; + try { int value_tag = input.read_long(); @@ -329,207 +384,396 @@ public abstract class Vio if (value_tag == vt_NULL) return null; else if (value_tag == vt_INDIRECTION) - - // TODO FIXME Implement support for indirections. - throw new NO_IMPLEMENT("Indirections unsupported"); + return readIndirection(input); else { // Read the value. if ((value_tag & vf_CODEBASE) != 0) { - // The codebase is present, but skip it. - input.read_string(); + // The codebase is present. + codebase = read_string(input); } if ((value_tag & vf_MULTIPLE_IDS) != 0) { - // Multiple supported repository ids are present, but skip them. - StringSeqHelper.read(input); + // Multiple supported repository ids are present. + ids = read_string_array(input); } else if ((value_tag & vf_ID) != 0) { - // Single supported repository id is present, but skip it. - input.read_string(); + // Single supported repository id is present. + id = read_string(input); } } - value_instance = - read_instance(input, value_instance, value_tag, helper); + 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) { - throw new MARSHAL(ex + ":" + ex.getMessage()); + 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. - * + * 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. + * @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, Object helper) + 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. - * + * 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. - * + * 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. - * + * @param helper the helper for read object specific part; may be null to read + * in using other methods. + * * @return the value that was read. */ - private static Object read_instance(InputStream input, Object value, - int value_tag, Object helper - ) + 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) { - ByteArrayOutputStream bout = null; - int n = -1; - - // Read all chunks. - int chunk_size = input.read_long(); - if (chunk_size < 0) - throw new MARSHAL("Invalid first chunk size " + chunk_size); - - byte[] r = new byte[ chunk_size ]; - - while (chunk_size > 0) - { - if (r.length < chunk_size) - r = new byte[ chunk_size + 256 ]; - - n = 0; - reading: - while (n < chunk_size) - n += input.read(r, n, r.length - n); - - // Read the size of the next chunk. - chunk_size = input.read_long(); - - // If the value is non negative, there is more than one chunk. - // Accumulate chunks in the buffer. - // The last chunk (or the only chunk, if only one chunk is - // present) is not written in the buffer. It is stored in the - // array r, avoiding unnecessary buffer operations. - if (chunk_size > 0) - { - bout = new ByteArrayOutputStream(2 * chunk_size); - bout.write(r, 0, chunk_size); - } - } + 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()); - if (bout != null) - { - // More than one chunk was present. - // Add the last chunk. - bout.write(r, 0, n); - input = new noHeaderInput(bout.toByteArray()); - } - else - { - // Only one chunk was present. - input = new noHeaderInput(r); - } + input = new HeadlessInput(ci, input); } else { - if (input instanceof cdrBufInput) + if (input instanceof BufferredCdrInput) { // Highly probable case. - input = - new noHeaderInput(((cdrBufInput) input).buffer.getBuffer()); + 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 { - cdrBufOutput bout = new cdrBufOutput(); + BufferedCdrOutput bout = new BufferedCdrOutput(); int c; while ((c = input.read()) >= 0) bout.write((byte) c); - input = new noHeaderInput(bout.buffer.toByteArray()); + 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; } - // The user-defines io operations are implemented. - if (value instanceof CustomMarshal) + 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) { - CustomMarshal marsh = (CustomMarshal) value; - try + 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) { - marsh.unmarshal((DataInputStream) input); + MARSHAL m = new MARSHAL("readNestedValue: indirection"); + m.minor = Minor.Chunks; + throw m; } - catch (ClassCastException ex) + else { - incorrect_plug_in(ex); + // 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; + reading: 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 instanceof BoxedValueHelper) - value = ((BoxedValueHelper) helper).read_value(input); - else if (helper instanceof ValueFactory) - value = - ((ValueFactory) helper).read_value((org.omg.CORBA_2_3.portable.InputStream) 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(); - // Stating the interfaces that the USER should use. - throw new MARSHAL("The " + value.getClass().getName() + - " must implement either StreamableValue or CustomValue." - ); + if (id != null) + factory = orb.lookup_value_factory(id); - // The negative end of state marker is expected from OMG standard. - // If the chunking is used, this marker is already extracted. - if ((value_tag & vf_CHUNKING) == 0) + 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 { - int eor = input.read_long(); - if (eor >= 0) - throw new MARSHAL("End of state marker has an invalid value " + eor); + if (ids != null && ids.length > 0) + id = ids[0]; + + value = handler.readValue(input, position, value.getClass(), id, g); + ok = true; } - return value; + 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 + { + StringBuffer b = new StringBuffer("{"); + 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) @@ -537,45 +781,82 @@ public abstract class Vio // 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, ObjectCreator.toIDL(value.getClass().getName())); - } - - /** - * Write the value base into the given stream, stating that it is an - * instance of the given class. The written record has no repository - * id and requires to supply a class or initialised instance for reading - * rather than an actual class it is. - * - * This results writing a different repository id. - * - * If the passed value implements the {@link CustomMarshal}, - * the helper uses {@link CustomMarshal#marshal} - * to write the content in a user defined way. Otherwise, - * this implementation initialises the {@link ObjectOutputStream} - * and writes through it. - * + 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 - ) + 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 - write(output, value, ObjectCreator.toIDL(substitute.getName())); + { + 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. - * + * 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. @@ -585,172 +866,608 @@ public abstract class Vio if (value == null) output.write_long(vt_NULL); else - write_instance(output, value, id, null); + write_instance(output, value, id, getHelper(value.getClass(), id)); } /** - * Write standard value type header, followed by contents, produced - * by the boxed value helper. - * + * 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. + * @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, - Object helper - ) + 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 id 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 { - String id; + 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; - if (helper instanceof BoxedValueHelper) - id = ((BoxedValueHelper) helper).get_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 - id = ""; + // Not in use for this case. + chunkSizeLocation = -1; + + writeValue(outObj, value, helper); - write_instance(output, value, id, 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 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 id a value repository id. - * @param helper a helper, writing object - specifica part. Can be null - * if the value should be written unsing other methods. + * Write value (after header). */ - private static void write_instance(OutputStream output, Serializable value, - String id, Object helper - ) + static void writeValue(OutputStream output, Serializable value, + BoxedValueHelper helper) { - // This implementation always writes a single repository id. - // It never writes multiple repository ids and currently does not use - // a codebase. - int value_tag = vt_VALUE_TAG | vf_ID; + ((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; - OutputStream outObj; - cdrBufOutput out = null; + if (!ok) + { + if (output instanceof BufferedCdrOutput) + { + BufferedCdrOutput b = (BufferedCdrOutput) output; + if (b.runtime == null) + b.runtime = new gnuRuntime(null, value); + } - if (USE_CHUNKING) + 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) { - out = new cdrBufOutput(); - out.setOrb(output.orb()); - outObj = out; - value_tag |= vf_CHUNKING; + ((CustomMarshal) value).marshal((DataOutputStream) output); + return true; } - else - outObj = output; + else if (value instanceof Streamable) + { + ((Streamable) value)._write(output); + return true; + } + return false; + } - output.write_long(value_tag); - output.write_string(id); + /** + * 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"); - if (helper instanceof BoxedValueHelper) + gnuValueStream in = (gnuValueStream) an_input; + + int current_pos = in.getPosition(); + + int offset = an_input.read_long(); + if (offset > -INT_SIZE) { - ((BoxedValueHelper) helper).write_value(outObj, value); + MARSHAL m = new MARSHAL("Indirection tag refers to " + offset + + " (must be less than -" + INT_SIZE + ")"); + m.minor = Minor.Offset; + throw m; } - else - // User defince write method is present. - if (value instanceof CustomMarshal) + + 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 { - ((CustomMarshal) value).marshal((DataOutputStream) outObj); + 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 (ClassCastException ex) + catch (Exception ex) { - incorrect_plug_in(ex); + MARSHAL m = new MARSHAL("Unable to instantiate " + id); + m.minor = Minor.Instantiation; + m.initCause(ex); + throw m; } } - else if (value instanceof Streamable) + 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) { - ((Streamable) value)._write(outObj); + 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 { - // Try to find helper via class loader. - boolean ok = false; - try + gnuRuntime r = g.getRunTime(); + int base = g.getPosition(); + int delta = input.read_long(); + if (r == null) { - Class helperClass = Class.forName(ObjectCreator.toHelperName(id)); - - // It will be the helper for the encapsulated boxed value, not the - // for the global boxed value type itself. - Method write = - helperClass.getMethod("write", - new Class[] - { - org.omg.CORBA.portable.OutputStream.class, value.getClass() - } - ); - write.invoke(null, new Object[] { outObj, value }); - ok = true; + previous = g.getPosition(); + g.seek(base + delta); + String indir = input.read_string(); + g.seek(previous); + return indir; } - catch (Exception ex) + else { - ok = false; + return (String) r.isObjectWrittenAt(base + delta, delta); } + } + } - // Stating the interfaces that the USER should use. - if (!ok) - throw new MARSHAL("The " + value.getClass().getName() + - " must implement either StreamableValue" + " or CustomValue." - ); + /** + * 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); + } + } + } - if (USE_CHUNKING) + /** + * Write repository Id, probably shared. + */ + static void write_string(OutputStream output, String id) + { + if (output instanceof gnuValueStream) { - output.write_long(out.buffer.size()); - try + 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) { - out.buffer.writeTo(output); + 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); + } } - catch (IOException ex) + } + 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++) { - MARSHAL m = new MARSHAL(); - m.initCause(ex); - throw m; + h = locateHelper(ia[i]); + if (h != null) + return h; } + return null; } + else + return null; + } - // The end of record marker, required by OMG standard. - output.write_long(-1); + /** + * 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); } /** - * This can be called if the alternative CORBA implementation - * is incorrectly plugged in. - * - * @throws NO_IMPLEMENT, always. + * Try to locate helper from the repository id. */ - static void incorrect_plug_in(Throwable ex) throws NO_IMPLEMENT + static BoxedValueHelper locateHelper(String id) { - NO_IMPLEMENT no = new NO_IMPLEMENT("Incorrect CORBA plug-in"); - no.initCause(ex); - throw no; + 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; } /** - * 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. + * Get the current position. */ - private static final void checkTag(int value_tag) + static int getCurrentPosition(InputStream x) { - if ((value_tag < 0x7fffff00 || value_tag > 0x7fffffff) && - value_tag != vt_NULL && - value_tag != vt_INDIRECTION - ) - throw new MARSHAL("Invalid value record, unsupported header tag: " + - value_tag - ); + 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); } }
\ No newline at end of file diff --git a/libjava/classpath/gnu/CORBA/CDR/gnuRuntime.java b/libjava/classpath/gnu/CORBA/CDR/gnuRuntime.java new file mode 100644 index 00000000000..774c92816ae --- /dev/null +++ b/libjava/classpath/gnu/CORBA/CDR/gnuRuntime.java @@ -0,0 +1,336 @@ +/* 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 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_codabase 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() + { + StringBuffer b = new StringBuffer(" 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 00000000000..663c9901861 --- /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); + +} diff --git a/libjava/classpath/gnu/CORBA/CDR/noHeaderInput.java b/libjava/classpath/gnu/CORBA/CDR/noHeaderInput.java deleted file mode 100644 index 0c787ddc2df..00000000000 --- a/libjava/classpath/gnu/CORBA/CDR/noHeaderInput.java +++ /dev/null @@ -1,166 +0,0 @@ -/* noHeaderInput.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 org.omg.CORBA.CustomMarshal; -import org.omg.CORBA.DataInputStream; -import org.omg.CORBA.MARSHAL; -import org.omg.CORBA.portable.BoxedValueHelper; -import org.omg.CORBA.portable.Streamable; -import org.omg.CORBA.portable.ValueFactory; - -import java.io.Serializable; - -/** - * 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) - */ -class noHeaderInput - extends cdrBufInput - implements DataInputStream -{ - /** - * If true, this is not the first call. - */ - boolean notFirst; - - /** - * Create an instance, reading from the given buffer. - */ - public noHeaderInput(byte[] buffer) - { - super(buffer); - } - - /** - * Read when knowning the class instance. - */ - public Serializable read_value(Class clz) - { - if (notFirst) - return super.read_value(clz); - else - { - try - { - notFirst = true; - return read_value((Serializable) clz.newInstance()); - } - catch (Exception ex) - { - MARSHAL m = new MARSHAL("Unable to create an instance"); - m.initCause(ex); - throw m; - } - } - } - - /** - * Tries to read using boxed value helper. - */ - public Serializable read_value(BoxedValueHelper helper) - { - if (notFirst) - return super.read_value(helper); - else - { - notFirst = true; - return helper.read_value(this); - } - } - - /** - * Tries to locate a factory using repository id. - */ - public Serializable read_value(String repository_id) - { - if (notFirst) - return super.read_value(repository_id); - else - { - notFirst = true; - - ValueFactory factory = - ((org.omg.CORBA_2_3.ORB) orb()).lookup_value_factory(repository_id); - if (factory == null) - throw new MARSHAL("No factory"); - return factory.read_value(this); - } - } - - /** - * Try to read when having an unitialised value. - */ - public Serializable read_value(Serializable value) - { - if (notFirst) - return super.read_value(value); - else - { - notFirst = true; - - // The user-defines io operations are implemented. - if (value instanceof CustomMarshal) - { - CustomMarshal marsh = (CustomMarshal) value; - try - { - marsh.unmarshal((DataInputStream) this); - } - catch (ClassCastException ex) - { - Vio.incorrect_plug_in(ex); - } - } - else - // The IDL-generated io operations are implemented. - if (value instanceof Streamable) - { - ((Streamable) value)._read(this); - } - return value; - } - } -}
\ No newline at end of file |

