summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/gnu/CORBA/CDR/Vio.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/CORBA/CDR/Vio.java')
-rw-r--r--libjava/classpath/gnu/CORBA/CDR/Vio.java1459
1 files changed, 1088 insertions, 371 deletions
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
OpenPOWER on IntegriCloud