FileDocCategorySizeDatePackage
InterceptorImpl.javaAPI DocGlassfish v2 API30953Fri May 04 22:36:42 BST 2007com.sun.jts.pi

InterceptorImpl

public class InterceptorImpl extends LocalObject implements ClientRequestInterceptor, ServerRequestInterceptor
This is the implementation of the JTS PI-based client/server interceptor. This will be called during request/reply invocation path.
author
Ram Jeyaraman 11/11/2000, $Author: tcfujii $
version
1.0, $Revision: 1.8 $ on $Date: 2007/05/05 05:36:42 $

Fields Summary
private static final String
name
private static final int
TransactionServiceId
private static final SystemException
SYS_EXC
public static final int
NO_REPLY_SLOT
public static final int
NULL_CTX_SLOT
public static final Integer
PROPER_CTX
public static final Integer
NULL_CTX
public static final Integer
REPLY
public static final Integer
NO_REPLY
public static final String
CLIENT_POLICY_CHECKING
public static final String
INTEROP_MODE
private static com.sun.corba.ee.spi.oa.rfm.ReferenceFactoryManager
rfm
static Logger
_logger
public static final ThreadLocal
otsThreadLocal
private static PropagationContext
nullContext
private static PropagationContext
dummyContext
public static ORB
txOrb
Current
pic
Codec
codec
int[]
slotIds
TSIdentification
tsi
com.sun.corba.ee.impl.txpoa.TSIdentificationImpl
tsiImpl
org.omg.CosTSPortability.Sender
sender
org.omg.CosTSPortability.Receiver
receiver
private boolean
checkPolicy
private boolean
interopMode
Constructors Summary
public InterceptorImpl(Current pic, Codec codec, int[] slotIds, TSIdentification tsi)


    // constructor

          
              
        this.pic = pic;
        this.codec = codec;
        this.slotIds = slotIds;
        this.tsi = tsi;
        this.tsiImpl = (TSIdentificationImpl) tsi;
        if (this.tsiImpl != null) {
            this.sender = this.tsiImpl.getSender();
            this.receiver = this.tsiImpl.getReceiver();
        }

        // check if client side checking is disabled. This allows client side
        // policy checking to be disabled (for testing purposes).
        String prop = System.getProperty(CLIENT_POLICY_CHECKING, "true");
        this.checkPolicy = prop.equals("true");

        // get the transaction interoperability mode.
        prop = System.getProperty(INTEROP_MODE, "true");
        this.interopMode = prop.equals("true");

        if (_logger.isLoggable(Level.FINE))
            _logger.log(Level.FINE, "Transaction INTEROP Mode: " + this.interopMode);

    
Methods Summary
public voiddestroy()

public static java.lang.IntegergetThreadLocalData(int slot)

        Object[] threadLocalState = (Object[]) otsThreadLocal.get();
        // IASRI 4698847 START
        //return (Integer) ((Stack) threadLocalState[slot]).pop();
        return (Integer) ((ArrayListStack) threadLocalState[slot]).pop();
        // IASRI 4698847 END
    
public static booleanisDummyContext(PropagationContext ctx)

        boolean proceed = false;
        try {
            proceed =
                (ctx.implementation_specific_data.extract_boolean() == true);
        } catch (BAD_OPERATION e) {
            return false;
        }
        return (proceed && isNullContext(ctx) && ctx.timeout == -1);
    
public static booleanisEjbAdapterName(java.lang.String[] adapterName)

         boolean result = false ;
	 if (rfm != null)
	     result = rfm.isRfmName( adapterName ) ;
         return result ;
     
public static booleanisNullContext(PropagationContext ctx)

        return (ctx.current.coord == null && ctx.current.term == null);
    
public static booleanisTxCtxtNull()

        Object[] threadLocalState = (Object[]) otsThreadLocal.get();
        // IASRI 4698847 START
        //Stack stack = (Stack) threadLocalState[NULL_CTX_SLOT];
        /*
        if (stack.empty()) {
            return true;
        }
        */
        // return ((Integer) stack.peek() == NULL_CTX); 
        ArrayListStack stack = (ArrayListStack) threadLocalState[NULL_CTX_SLOT];
        return ((Integer) stack.peek() == NULL_CTX);
        // IASRI 4698847 END
    
public java.lang.Stringname()

	return InterceptorImpl.name;
    
private voidprocessServerSendPoint(org.omg.PortableInterceptor.ServerRequestInfo ri, org.omg.CORBA.CompletionStatus completionStatus)


        // clear the null ctx indicator
        getThreadLocalData(NULL_CTX_SLOT);

        // see if a reply ctx needs to be sent.

        Integer no_reply = getThreadLocalData(NO_REPLY_SLOT);

        if (no_reply == NO_REPLY) {
            return;
        }

        // TransactionService is not available.

        if (this.tsiImpl == null || this.receiver == null) {
            if (no_reply == REPLY) {
                // would the TransactionService go down during request
                // processing ? Maybe.
                throw new TRANSACTION_ROLLEDBACK(0, completionStatus);
            }
            return;
        }

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE,"   sending_reply["+ ri.request_id() + "] : " +
                ri.operation() + ", ThreadName : " +
                Thread.currentThread().toString());
        }

        // call the proprietary OTS interceptor.

        PropagationContextHolder ctxh = new PropagationContextHolder();
        receiver.sending_reply(ri.request_id(), ctxh);

        if (ctxh.value == null) {
            // no tx context available. This should not happen since a tx ctx
            // was received.
            throw new TRANSACTION_ROLLEDBACK(0, completionStatus);
        }

        // create the service context and set it in the reply.

        //Any any = ORB.init().create_any();
        Any any = txOrb.create_any();
        PropagationContextHelper.insert(any, ctxh.value);
        byte[] ctxData = null;
        try {
            ctxData = this.codec.encode_value(any);
        } catch (InvalidTypeForEncoding e) {
            throw new INTERNAL(0, completionStatus);
        }
        ServiceContext svc = new ServiceContext(TransactionServiceId, ctxData);
        ri.add_reply_service_context(svc, false);
    
public voidreceive_exception(org.omg.PortableInterceptor.ClientRequestInfo ri)


        // check if a tx svc context was received.

        ServiceContext svc = null;
        try {
            svc = ri.get_reply_service_context(TransactionServiceId);
        } catch (BAD_PARAM e) {
            return; // do nothing (no tx service context in reply).
            // REVISIT Exception replies may not carry a tx context back,
            // as a result checked transaction behaviour will cause the
            // transaction to fail.
        }
	catch(Exception e){
		return;
	}

	if (svc == null) {
	    return;
	}

        // a tx svc context is available.

        // Set up the Environment instance with exception information.
	// The exception can be a SystemException or an UnknownUserException.
	Environment env = new com.sun.corba.ee.impl.corba.EnvironmentImpl();
        SystemException exception = null;
        Any any = ri.received_exception();
        InputStream strm = any.create_input_stream();
        String repId = ri.received_exception_id();
        strm.read_string(); // read repId
        int minorCode = strm.read_long(); // read minorCode
        CompletionStatus completionStatus = // read completionStatus
            CompletionStatus.from_int(strm.read_long());
        if (repId.indexOf("UNKNOWN") != -1) { // user exception ?
	    if (minorCode == 1) { // read minorCode
                // user exception
	    } else { // system exception
                exception = SYS_EXC;
	    }
        } else { // system exception
            exception = SYS_EXC;
        }
	env.exception(exception);

        // check if TransactionService is available.
        if (this.tsiImpl == null || this.sender == null) {
            throw new TRANSACTION_ROLLEDBACK(0, completionStatus);
        }

        // read the propagation context

        try {
            TypeCode typeCode = PropagationContextHelper.type();
            any = this.codec.decode_value(svc.context_data, typeCode);
        } catch (TypeMismatch e) {
            throw new INTERNAL(0, completionStatus);
        } catch (FormatMismatch e) {
            throw new INTERNAL(0, completionStatus);
        }
        PropagationContext ctx = PropagationContextHelper.extract(any);

        // call the OTS proprietary hook.

        try {
	    sender.received_reply(ri.request_id(), ctx, env);
	} catch (org.omg.CORBA.WrongTransaction ex) {
            throw new INVALID_TRANSACTION(0, completionStatus);
	}
    
public voidreceive_other(org.omg.PortableInterceptor.ClientRequestInfo ri)


        // check if a tx svc context was received.

        ServiceContext svc = null;
        try {
            svc = ri.get_reply_service_context(TransactionServiceId);
        } catch (BAD_PARAM e) {
            return; // do nothing (no tx service context in reply).
            // REVISIT If a valid tx context was sent, and none was received
            // back, then the checked transaction behaviour will cause the
            // transaction to fail.
        }

	if (svc == null) {
	    return;
	}
        // a tx svc context is available.

        // check if TransactionService is available.
        if (this.tsiImpl == null || this.sender == null) {
            throw new TRANSACTION_ROLLEDBACK(0, CompletionStatus.COMPLETED_NO);
        }

        // read the propagation context

        Any any = null;
        try {
            TypeCode typeCode = PropagationContextHelper.type();
            any = this.codec.decode_value(svc.context_data, typeCode);
        } catch (TypeMismatch e) {
            throw new INTERNAL(0, CompletionStatus.COMPLETED_NO);
        } catch (FormatMismatch e) {
            throw new INTERNAL(0, CompletionStatus.COMPLETED_NO);
        }
        PropagationContext ctx = PropagationContextHelper.extract(any);

        // Set up the Environment instance with exception information.
	// The exception can be a SystemException or an UnknownUserException.

	Environment env = new EnvironmentImpl();
	env.exception(null);

        // call the OTS proprietary hook.

        try {
	    sender.received_reply(ri.request_id(), ctx, env);
	} catch (org.omg.CORBA.WrongTransaction ex) {
            throw new INVALID_TRANSACTION(0, CompletionStatus.COMPLETED_NO);
	}
    
public voidreceive_reply(org.omg.PortableInterceptor.ClientRequestInfo ri)


        // check if a tx svc context was received.

        ServiceContext svc = null;
        try {
            svc = ri.get_reply_service_context(TransactionServiceId);
        } catch (BAD_PARAM e) {
            return; // do nothing (no tx service context in reply).
            // REVISIT If a valid tx context was sent, and none was received
            // back, then the checked transaction behaviour will cause the
            // transaction to fail.
        }

	if (svc == null) {
	    return;
	}
        // a tx svc context is available.

        // check if TransactionService is available.
        if (this.tsiImpl == null || this.sender == null) {
            throw new TRANSACTION_ROLLEDBACK(0, CompletionStatus.COMPLETED_YES);
        }

        if (_logger.isLoggable(Level.FINE)) {
			_logger.log(Level.FINE,"   received_reply[" + ri.request_id() + "] : " +
	                ri.operation() + ", ThreadName : " +
					Thread.currentThread().toString());
        }

        // read the propagation context

        Any any = null;
        try {
            TypeCode typeCode = PropagationContextHelper.type();
            any = this.codec.decode_value(svc.context_data, typeCode);
        } catch (TypeMismatch e) {
            throw new INTERNAL(0, CompletionStatus.COMPLETED_YES);
        } catch (FormatMismatch e) {
            throw new INTERNAL(0, CompletionStatus.COMPLETED_YES);
        }
        PropagationContext ctx = PropagationContextHelper.extract(any);

        // Set up the Environment instance with exception information.
	// The exception can be a SystemException or an UnknownUserException.

	Environment env = new EnvironmentImpl();
	env.exception(null);

        // call the OTS proprietary hook.

        try {
	    sender.received_reply(ri.request_id(), ctx, env);
	} catch (org.omg.CORBA.WrongTransaction ex) {
            throw new INVALID_TRANSACTION(0, CompletionStatus.COMPLETED_YES);
	}
    
public voidreceive_request(org.omg.PortableInterceptor.ServerRequestInfo ri)

        // do nothing.
    
public voidreceive_request_service_contexts(org.omg.PortableInterceptor.ServerRequestInfo ri)


        // since this could be called on a seperate thread, we need to
        // transfer the svc context to the request PICurrent slots.
        // But for now, since we know that this is called by the same thread
        // as the target, we do not do it. But we should at some point.
        // do policy checking.

        OTSPolicy otsPolicy = null;
        try {
            otsPolicy = (OTSPolicy) ri.get_server_policy(OTS_POLICY_TYPE.value);
        } catch (INV_POLICY e) {
            // ignore. This will be treated as FORBIDS.
        }

        short otsPolicyValue = -1;

        if (otsPolicy == null) {
            // Once J2EE RI moves to POA based policy mechanism, default of
            // FORBIDS shall be used. Until then, we will use ADAPTS.
            //otsPolicyValue = OTSPolicyImpl._FORBIDS.value();
            otsPolicyValue = OTSPolicyImpl._ADAPTS.value();
        } else {
            otsPolicyValue = otsPolicy.value();
        }

        // get the tx contxt, if one was received.

        ServiceContext svc = null;
        try {
            svc = ri.get_request_service_context(TransactionServiceId);
        } catch (BAD_PARAM e) {
            // ignore, svc == null will be handled later.
        }

        // set threadLocal slot to indicate whether tx svc ctxt
        // was received or not. (svc == null) ==> NO_REPLY is true.

        if (svc == null) {
            setThreadLocalData(NO_REPLY_SLOT, NO_REPLY);
        } else {
            setThreadLocalData(NO_REPLY_SLOT, REPLY);
        }

        // initially set the thread local slot to indicate proper ctxt.
        // if the null ctx is received, then it will be set later in the method.
        setThreadLocalData(NULL_CTX_SLOT, PROPER_CTX);

        try {

            // TransactionService is not available.

            if (this.tsiImpl == null || this.receiver == null) {
                if (svc != null || otsPolicyValue == REQUIRES.value) {
                    throw new TRANSACTION_UNAVAILABLE();
                }
                return;
            }

            // TransactionService is available.

            // no tx context was received.
            if (svc == null) {
                if (otsPolicyValue == REQUIRES.value) {
                    throw new TRANSACTION_REQUIRED();
                }
                return;
            }

            // a tx ctx was received.

            // check policy
            if (otsPolicyValue == FORBIDS.value) {
                throw new INVALID_TRANSACTION();
            }

            if (_logger.isLoggable(Level.FINE)) {
				_logger.log(Level.FINE," received_request[" +
                    ri.request_id() + "] : " + ri.operation() +
                    ", ThreadName : " + Thread.currentThread().toString());
            }

            // Create service context.

            // sanity check.
            if (svc.context_id != TransactionServiceId) {
                throw new INVALID_TRANSACTION();
            }

            Any any = null;
            try {
                TypeCode typeCode = PropagationContextHelper.type();
                any = this.codec.decode_value(svc.context_data, typeCode);
            } catch (TypeMismatch e) {
                throw new INTERNAL();
            } catch (FormatMismatch e) {
                throw new INTERNAL();
            }
            PropagationContext ctx = PropagationContextHelper.extract(any);

            // check if a 'dummyContext' is present (local optimization).
            // If so, return.

            if (isDummyContext(ctx)) {
                // do nothing, since it is the same client thread which already
                // has the tx context association.
                // NOTE There is a chance that the 'nullContext' could be mistaken
                // to be a 'dummyContext', which may cause a valid 'nullContext'
                // to be ignored (!). But let's hope there won't be a collision :)

                // no need to send a reply ctx
                getThreadLocalData(NO_REPLY_SLOT); // pop item
                setThreadLocalData(NO_REPLY_SLOT, NO_REPLY); // push item
                return;
            }

            // check if a 'nullContext' was received,
            // and set the threadlocal data appropriately.

            if (isNullContext(ctx)) {
                // indicate a null context
                getThreadLocalData(NULL_CTX_SLOT); // pop item
                setThreadLocalData(NULL_CTX_SLOT, NULL_CTX); // push item
                // no need to send a reply ctx
                getThreadLocalData(NO_REPLY_SLOT); // pop item
                setThreadLocalData(NO_REPLY_SLOT, NO_REPLY); // push item
                return;
            } else if (this.interopMode == false) {
                getThreadLocalData(NULL_CTX_SLOT); // pop item
                setThreadLocalData(NULL_CTX_SLOT, NULL_CTX); // push item
            }

            // call the proprietary hook
            receiver.received_request(ri.request_id(), ctx);

        } catch (RuntimeException r) {
            // The server send point will not be called if the server receive
            // point raises an exception. So, do the cleanup.
            // ie., restore thread local data
            getThreadLocalData(NO_REPLY_SLOT);
            getThreadLocalData(NULL_CTX_SLOT);
            throw r;
        }
    
public voidsend_exception(org.omg.PortableInterceptor.ServerRequestInfo ri)

        Any any = ri.sending_exception();
        InputStream strm = any.create_input_stream();
        strm.read_string(); // repId
        strm.read_long(); // minorCode
        CompletionStatus completionStatus =
            CompletionStatus.from_int(strm.read_long());

        processServerSendPoint(ri, completionStatus);
    
public voidsend_other(org.omg.PortableInterceptor.ServerRequestInfo ri)

        processServerSendPoint(ri, CompletionStatus.COMPLETED_NO);
    
public voidsend_poll(org.omg.PortableInterceptor.ClientRequestInfo ri)

        // do nothing.
    
public voidsend_reply(org.omg.PortableInterceptor.ServerRequestInfo ri)

        processServerSendPoint(ri, CompletionStatus.COMPLETED_YES);
    
public voidsend_request(org.omg.PortableInterceptor.ClientRequestInfo ri)


        // do IOR policy checking.

        TaggedComponent otsComp = null;
        try {
            otsComp = ri.get_effective_component(TAG_OTS_POLICY.value);
        } catch (BAD_PARAM e) {
            // ignore
        }

        short otsPolicyValue = -1;

        if (otsComp == null) {
            // in the case of J2EE RI, all published IORs must have an
            // associated OTS policy component. The only exception being the
            // location forwarded IORs returned by ORBD. Until a time, the ORBD
            // is capable of transcribing the target POA policies into the
            // location forwarded IOR, treat the absence of an OTS policy
            // component as being equivalent to ADAPTS. Once the ORBD is
            // able to support OTS policy components, the absence of an OTS
            // policy component must be treated as FORBIDS.
            otsPolicyValue = OTSPolicyImpl._ADAPTS.value();
        } else {
            // TypeCode typeCode = ORB.init().get_primitive_tc(TCKind.tk_short);
            TypeCode typeCode = txOrb.get_primitive_tc(TCKind.tk_short);
            Any any = null;
            try {
                any = this.codec.decode_value(otsComp.component_data, typeCode);
            } catch (TypeMismatch e) {
                throw new INTERNAL();
            } catch (FormatMismatch e) {
                throw new INTERNAL();
            }
            otsPolicyValue = OTSPolicyValueHelper.extract(any);
        }

        // TransactionService is not available.

        if (this.tsiImpl == null || this.sender == null) {
            if (otsPolicyValue == REQUIRES.value && this.checkPolicy) {
                throw new TRANSACTION_UNAVAILABLE();
            }
            return;
        }

        // TransactionService is available.

        /*
        // Call JTS proprietary interceptor to see if there is a current tx.
        PropagationContextHolder hctx = new PropagationContextHolder();
        sender.sending_request(ri.request_id(), hctx);

        if (hctx.value == null) { // no tx context
            if (otsPolicyValue == REQUIRES.value && this.checkPolicy) {
                throw new TRANSACTION_REQUIRED();
            }
            return;
        }
        */

        // Check to see if there is a current transaction.
        boolean isTxAssociated = CurrentTransaction.isTxAssociated();
        if (!isTxAssociated) { // no tx context
            if (otsPolicyValue == REQUIRES.value && this.checkPolicy) {
                throw new TRANSACTION_REQUIRED();
            }
            return;
        }

        if (_logger.isLoggable(Level.FINE)) {
			_logger.log(Level.FINE," sending_request["+ ri.request_id() + 
					"] : " + ri.operation() + ", ThreadName : " +
                Thread.currentThread().toString());
        }

        // a current tx is available. Create service context.

        if (otsPolicyValue == FORBIDS.value && this.checkPolicy) {
            throw new INVALID_TRANSACTION();
        }

        PropagationContextHolder hctx = new PropagationContextHolder();

        // if target object is co-located, no need to send tx context.
        // This optimization uses a dummy context to flag the local case, so
        // that the server receive point shall ignore the context (after doing
        // appropriate policy checking). The net gain is that the activation of
        // coordinator object is avoided.
        // Note, this currently has issues with respect to checked behavior.
        // Currently, checked behaviour is disabled and shall be reinstated
        // once OTS RTF redrafts the OTS spec based on PI. An issue needs to be
        // filed.
        org.omg.CORBA.Object target = ri.effective_target();
        if ( StubAdapter.isStub(target) && StubAdapter.isLocal(target) ) { 
            // target is local
            // load a dummy context and discard the current tx context.
            hctx.value = dummyContext;
        } else if (this.interopMode == false) { // target is remote
            // load a null context and discard the current tx context.
            hctx.value = nullContext;
        } else {
	    IOR ior = ((com.sun.corba.ee.spi.orb.ORB)txOrb).getIOR( target, false ) ;
	    IIOPProfile prof = ior.getProfile() ;
	    ObjectKeyTemplate oktemp = prof.getObjectKeyTemplate() ;
	    if (oktemp.getORBVersion().equals(ORBVersionFactory.getFOREIGN()))
	    {
                hctx.value = nullContext;
	    } else {
		    /*
	        ObjectAdapterId oaid = oktemp.getObjectAdapterId() ;
	        String[] adapterName = oaid.getAdapterName() ;
	        boolean isEjbCall = isEjbAdapterName(adapterName);
	        if (!isEjbCall) {
                    hctx.value = nullContext;
	        } else {
                    // Call JTS proprietary interceptor to get current tx.
                    sender.sending_request(ri.request_id(), hctx);
	        } */
                sender.sending_request(ri.request_id(), hctx);
	    }
        }

        // add service context.

        //Any any = ORB.init().create_any();
        Any any = txOrb.create_any();
        PropagationContextHelper.insert(any, hctx.value);
        byte[] ctxData = null;
        try {
            ctxData = this.codec.encode_value(any);
        } catch (InvalidTypeForEncoding e) {
            throw new INTERNAL();
        }

        ServiceContext svc = new ServiceContext(TransactionServiceId, ctxData);
        ri.add_request_service_context(svc, false);
    
public static voidsetOrb(org.omg.CORBA.ORB orb)

        txOrb = orb;
        Any any = txOrb.create_any();
        any.insert_boolean(false);
        nullContext = new PropagationContext(
            0,
            new TransIdentity(null, null, new otid_t(0, 0, new byte[0])),
            new TransIdentity[0],
            any);

        any.insert_boolean(true);
        dummyContext = new PropagationContext(
            -1,
            new TransIdentity(null, null, new otid_t(-1, 0, new byte[0])),
            new TransIdentity[0],
            any);
	try {
	    rfm = (ReferenceFactoryManager)orb.resolve_initial_references(
	          ORBConstants.REFERENCE_FACTORY_MANAGER ) ;
	} catch (Exception ex) {
	    _logger.log(Level.WARNING,ex.getMessage(), ex);
	}
    
public voidsetTSIdentification(TSIdentification tsi)


        if (tsi == null) {
            return;
        }

        this.tsi = tsi;
        this.tsiImpl = (TSIdentificationImpl) tsi;
        this.sender = this.tsiImpl.getSender();
        this.receiver = this.tsiImpl.getReceiver();
    
public static voidsetThreadLocalData(int slot, java.lang.Integer data)

        Object[] threadLocalState = (Object[]) otsThreadLocal.get();
        // IASRI 4698847 START
        //((Stack) threadLocalState[slot]).push(data); 
        ((ArrayListStack) threadLocalState[slot]).push(data); 
        // IASRI 4698847 END