All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.objectweb.jotm.ots.OTSInterceptor Maven / Gradle / Ivy

There is a newer version: 2.3.1-M1
Show newest version
/*
 * @(#) OTSInterceptor.java	1.0 02/07/15
 *
 * JOTM: Java Open Transaction Manager
 *
 * This module was originally developed by
 *  - INRIA inside the ObjectWeb Consortium(http://www.objectweb.org)
 *
 * The original code and portions created by INRIA are
 * Copyright (C) 2002 - INRIA (www.inria.fr)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * -Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * --------------------------------------------------------------------------
 * $Id: OTSInterceptor.java 903 2008-06-26 08:11:16Z durieuxp $
 * --------------------------------------------------------------------------
 */
package org.objectweb.jotm.ots;

import javax.rmi.PortableRemoteObject;
import javax.transaction.xa.Xid;

import org.omg.CORBA.Any;
import org.omg.CORBA.LocalObject;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TCKind;
import org.omg.CosTransactions.PropagationContext;
import org.omg.CosTransactions.PropagationContextHelper;
import org.omg.CosTransactions.TransIdentity;
import org.omg.CosTransactions.otid_t;
import org.omg.DynamicAny.DynAnyFactory;
import org.omg.DynamicAny.DynAnyFactoryHelper;
import org.omg.IOP.Codec;
import org.omg.IOP.ServiceContext;
import org.omg.PortableInterceptor.ForwardRequest;
import org.omg.PortableInterceptor.ORBInitInfo;
import org.omg.PortableInterceptor.ORBInitInfoPackage.InvalidName;
import org.objectweb.jotm.Coordinator;
import org.objectweb.jotm.InternalTransactionContext;
import org.objectweb.jotm.Terminator;
import org.objectweb.jotm.TransactionContext;
import org.objectweb.jotm.XidImpl;


public abstract class OTSInterceptor extends LocalObject {

    // Used to encode/decode the call
    protected Codec codec;

    // for identifying client or server.
    protected DynAnyFactory dynAnyFactoryS_;

    // Service context identifier
    protected final int TX_CTX_ID = org.omg.IOP.TransactionService.value; //100;

    // ORB instance
    protected static ORB orb = null ;

    /**
     * constructor
     */

    public OTSInterceptor(ORBInitInfo info) {

        // Get the codec factory
        org.omg.IOP.CodecFactory factory = info.codec_factory();
        if(factory == null) throw new RuntimeException();

            // Create codec
            org.omg.IOP.Encoding how = new org.omg.IOP.Encoding();
            how.major_version = 1;
            how.minor_version = 0;
            how.format = org.omg.IOP.ENCODING_CDR_ENCAPS.value;

            try {
                codec = factory.create_codec(how);
            } catch(org.omg.IOP.CodecFactoryPackage.UnknownEncoding ex) {
                throw new RuntimeException();
        }

        if(codec == null) throw new RuntimeException();

            //
            // Get the dynamic any factory
            //
            DynAnyFactory dynAnyFactory = null;
            try {
                org.omg.CORBA.Object obj = info.resolve_initial_references("DynAnyFactory");
                dynAnyFactory = DynAnyFactoryHelper.narrow(obj);
            } catch(InvalidName ex) {
                throw new RuntimeException();
            } catch(org.omg.CORBA.BAD_PARAM ex) {
                throw new RuntimeException();
        }

        dynAnyFactoryS_ = dynAnyFactory;

    } // end constructor

    protected Any create_any() throws org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode{
        org.omg.DynamicAny.DynAny dynAny = dynAnyFactoryS_.create_dyn_any_from_type_code(PropagationContextHelper.type());
        return dynAny.to_any();
    }

    /**
     * Build and returns the CORBA PropagationContext (JTS)
     */
    protected ServiceContext buildCorbaPropagationContext(TransactionContext txCtx) throws ForwardRequest {
        try {

            // Build a new CORBA Propagation context
            // For the moment, JOTM does not implement tx interoperability EJB2.1 ?19.6 and
            // so the fields CosTransactions:Coordinator and CosTransactions:Terminator are set
            // to null in order to generate a 'null transaction ctx'
            // The coordinator/terminator are propagated in the 'implementation_specific_data' field.

            // Get Information of TransactionContext
            Xid xid = txCtx.getXid();
            int timeout = txCtx.getTimeout();
            Coordinator coord = txCtx.getCoordinator();

            // Xid is coded in the otid_t
            byte[] gtrid = xid.getGlobalTransactionId();
            byte[] bqual = xid.getBranchQualifier();
            byte[] tid = new byte[gtrid.length + bqual.length];
            System.arraycopy(bqual, 0, tid, 0, bqual.length);
            System.arraycopy(gtrid, 0, tid, bqual.length, gtrid.length);
            otid_t otid = new otid_t(xid.getFormatId(), bqual.length, tid);

            // current holds only otid_t
            TransIdentity curr = new TransIdentity(null, null, otid);

            // Create the PropagationContext
            PropagationContext pctx =
                new PropagationContext(timeout, curr, new TransIdentity[0], null);

            // In JOTM, the Coordinator and the terminator interface are implemented
            // by the same class : ControlImpl. The stub is propagated to others JOnAS
            // instances in the implementation_specific_data field. It is coded in an Any
            // field
            if (orb==null){
            	// Get ORB instance
            	orb=ORB.init(new String[]{}, null) ;
            }

            Any specific = orb.create_any();
            if (coord != null) {
                // Set the JOTM's coordinator in the 'specific' field
                specific.insert_Object((javax.rmi.CORBA.Stub) PortableRemoteObject.toStub(coord));
                pctx.implementation_specific_data = specific;
            } else {
                // If the coordinator is unknown, set a 'JONAS' pattern
                // to allow the other side to recognize a
                // JOTM context
                specific.insert_string("JOnAS");
                pctx.implementation_specific_data = specific;
            }

            Any pAny = create_any();
            PropagationContextHelper.insert(pAny, pctx);

            // encode the PropagationContext in a service context
            byte[] propagationContextData = codec.encode_value(pAny);
            return new ServiceContext(TX_CTX_ID, propagationContextData);

        } catch (Exception e) {
            throw new ForwardRequest();
        }
    }

    /**
     * decode the Corba Propagation Context and build an internal transaction context
     * @param sCtx ServiceContext
     */
    protected TransactionContext decodeCorbaPropagationContext(ServiceContext sCtx){

        if (sCtx == null) { // no tx ctx

            return null ;
        }
        Xid xid = null;
        int timeout;
        Any specific = null ;

        // try to decode the corba tx context
        try {
            // unmarshall the Propagation Context
            Any pctxAny = codec.decode_value(sCtx.context_data, PropagationContextHelper.type());
            PropagationContext pctx = PropagationContextHelper.extract(pctxAny);

            // get the propagation context values
            specific = pctx.implementation_specific_data;
            otid_t otid = pctx.current.otid;
            timeout = pctx.timeout;
            xid = new XidImpl(otid.formatID, otid.bqual_length, otid.tid);

        } catch (Exception e) { // invalid tx ctx

            return null;
        }

        // JOTM don't be able to detect whether the context is a valid or a null ctx
        // If it isn't a JOTM's context (fail during decoding), it considers it's a null ctx
        boolean isJotmCtx=false;
        Coordinator coord = null;
        Terminator term = null;

        try {
            if ((specific == null) || (specific.type().kind() == TCKind.tk_null) ||
                (specific.type().kind() == TCKind.tk_octet)) {
                	// null ctx or valid ctx but sent from another app server
                	// isJotmCtx=false ;
            } else if (specific.type().kind() == TCKind.tk_string) {
                String pattern = specific.extract_string() ;
                // Here, maybe we have received a JOTM context with an unknown coordinator
                // In this case, a JONAS pattern has been set
                if (pattern.compareTo("JOnAS")==0) {
                    isJotmCtx=true ;
                }

            } else {
                // Last try, it should be a typical JOTM context with the coordinator set in 'specific' field
                coord = (Coordinator) PortableRemoteObject.narrow((java.rmi.Remote) specific.extract_Object(),
                        Coordinator.class);
                term = (Terminator) PortableRemoteObject.narrow((java.rmi.Remote) specific.extract_Object(),
                        Terminator.class);
                isJotmCtx=true ;


            }
        } catch (Exception e) {
            // null ctx or valid ctx but sent from another app server
            // isJotmCtx=false ;
        }

        TransactionContext tCtx = new InternalTransactionContext(timeout, coord, term, xid);
        if ( isJotmCtx == false ) {
            // flag the internal context to indicate the ctx comes from
            // another vendor
            tCtx.setNotJotmCtx();
        }
        return tCtx;
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy