in yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueReader.java [1445:1650]
public void readValueAny(Any any, TypeCode tc) {
//
// In constrast to other complex types, valuetypes and value boxes
// in Anys cannot simply be "remarshalled". The reason is that
// indirection may occur across multiple Any values in the same
// stream. Therefore, if possible, we should attempt to construct
// the values using a factory so that any shared values will be
// handled correctly.
//
// If a factory cannot be found, we should still remarshal.
// However, if an indirection is encountered which refers to
// a value we were unable to construct, an exception will be
// raised.
//
org.apache.yoko.orb.CORBA.Any obAny = null;
try {
obAny = (org.apache.yoko.orb.CORBA.Any) any;
} catch (ClassCastException ex) {
//
// Any may have been created by a foreign ORB
//
}
final TypeCode origTC = org.apache.yoko.orb.CORBA.TypeCode._OB_getOrigType(tc);
if (logger.isLoggable(Level.FINE))
logger.fine(String.format(
"Reading an Any value of kind=%d from position 0x%x",
origTC.kind().value(), buf_.pos_));
//
// Check if the Any contains an abstract interface
//
if (origTC.kind() == TCKind.tk_abstract_interface) {
final boolean b = in_.read_boolean();
if (b) {
logger.fine("Reading an object reference for an abstract interface");
//
// The abstract interface represents an object reference
//
any.insert_Object(in_.read_Object(), tc);
return;
} else {
logger.fine("Reading an object value for an abstract interface");
//
// The abstract interface represents a valuetype. The
// readValue() method will raise an exception if an
// instance of the valuetype could not be created.
// We cannot remarshal in this case because we don't
// have a TypeCode for the valuetype.
//
any.insert_Value(readValue(), tc);
return;
}
}
//
// If the TypeCode's repository ID is that of CORBA::ValueBase,
// then we try to create an instance. The Any could contain a
// valuetype *or* a boxed valuetype.
//
// If creation fails, we cannot remarshal the value, since
// CORBA::ValueBase is not a truncatable base type, and we
// have no other TypeCode information. Truncating to
// CORBA::ValueBase doesn't seem very useful anyway.
//
try {
final String id = origTC.id();
if (logger.isLoggable(Level.FINE))
logger.fine(String.format("Reading an Any value of id=\"%s\"", id));
if ("IDL:omg.org/CORBA/ValueBase:1.0".equals(id)) {
any.insert_Value(readValue(), tc);
return;
}
} catch (BadKind ex) {
Assert._OB_assert(ex);
}
//
// At this point, the Any contains a valuetype or a boxed valuetype,
// and we have a TypeCode that can be used for remarshalling.
//
//
// Save some state so that we can restore things prior to
// remarshalling
//
final int startPos = buf_.pos_;
final ChunkState startState = new ChunkState(chunkState_);
//
// No need to worry about truncation for boxed valuetypes
//
if (origTC.kind() == TCKind.tk_value_box) {
try {
any.insert_Value(readValue(tc.id()), tc);
return;
} catch (MARSHAL ex) {
//
// Creation failed - restore our state and try remarshalling
//
buf_.pos_ = startPos;
chunkState_.copyFrom(startState);
final Buffer buf = new Buffer();
final OutputStream out = new OutputStream(buf);
out._OB_ORBInstance(orbInstance_);
remarshalValue(origTC, out);
final InputStream in = (InputStream) out.create_input_stream();
Assert._OB_assert(obAny != null);
obAny.replace(tc, in);
return;
} catch (BadKind ex) {
Assert._OB_assert(ex);
}
} else {
//
// Read valuetype header tag
//
final Header h = new Header();
h.tag = in_.read_long();
if (logger.isLoggable(Level.FINE))
logger.fine(String.format("Read tag value 0x%08x", h.tag));
//
// Check tag for special cases
//
if (h.tag == 0) {
any.insert_Value(null, tc);
return;
}
if ((h.tag != -1) && (h.tag < 0x7fffff00)) {
throw new MARSHAL("Illegal valuetype tag 0x" + Integer.toHexString(h.tag));
}
//
// Try to create an instance of the valuetype using a factory
//
final FactoryCreationStrategy strategy = new FactoryCreationStrategy(this, in_, null);
try {
if (h.tag == -1) {
//
// TODO: The TypeCode may not necessarily reflect
// the one that was used for the indirected value
// (i.e., the value may have been truncated).
// Fixing this probably requires maintaining a
// map of stream position to TypeCode.
//
logger.fine("Handling a value type indirection value");
any.insert_Value(readIndirection(strategy), tc);
return;
} else {
initHeader(h);
final StringHolder idH = new StringHolder();
final Serializable vb = strategy.create(h, idH);
if (logger.isLoggable(Level.FINE))
logger.fine(String.format("Obtained a value of type \"%s\"", vb.getClass().getName()));
skipChunk();
//
// Find the TypeCode for the repository ID that was
// used to instantiate the valuetype. Three things
// can happen:
//
// 1) The TypeCode is equal to tc.
//
// 2) The TypeCode is null. In this case, the instance
// is of a more-derived type than tc, so the best
// we can do is to use tc.
//
// 3) The TypeCode is a base type of tc. In this case,
// the valuetype was truncated.
//
TypeCode t = null;
if (idH.value != null) {
t = findTypeCode(idH.value, tc);
}
if (t != null) {
any.insert_Value(vb, t);
} else {
any.insert_Value(vb, tc);
}
return;
}
} catch (MARSHAL ex) {
logger.log(Level.FINE, "Marshaling exception occurred, attempting to remarshal", ex);
//
// Creation failed - restore our state and try remarshalling
//
buf_.pos_ = startPos;
chunkState_.copyFrom(startState);
final Buffer buf = new Buffer();
final OutputStream out = new OutputStream(buf);
out._OB_ORBInstance(orbInstance_);
final TypeCode t = remarshalValue(origTC, out);
final InputStream in = (InputStream) out.create_input_stream();
Assert._OB_assert(obAny != null);
obAny.replace(t, in);
return;
}
}
Assert._OB_assert(false); // should never reach this point
}