public void readValueAny()

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
    }