Java tutorial
/* * $Id$ * -------------------------------------------------------------------------------------- * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.transport.jms.xa; import org.mule.api.transaction.Transaction; import org.mule.config.i18n.CoreMessages; import org.mule.transaction.IllegalTransactionStateException; import org.mule.transaction.TransactionCoordination; import org.mule.transaction.XaTransaction; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.QueueReceiver; import javax.jms.QueueSender; import javax.jms.Session; import javax.jms.TopicPublisher; import javax.jms.TopicSubscriber; import javax.jms.XAQueueSession; import javax.jms.XASession; import javax.jms.XATopicSession; import javax.transaction.xa.XAResource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class SessionInvocationHandler implements TargetInvocationHandler { protected static final transient Log logger = LogFactory.getLog(SessionInvocationHandler.class); private XASession xaSession; private XAResource xaResource; private volatile boolean enlisted = false; private volatile boolean reuseObject = false; private final Session session; private SessionInvocationHandler(XASession xaSession, Session session, Boolean sameRMOverrideValue) { super(); this.xaSession = xaSession; this.session = session; this.xaResource = new XAResourceWrapper(xaSession.getXAResource(), this, sameRMOverrideValue); } public SessionInvocationHandler(XASession xaSession, Boolean sameRMOverrideValue) throws JMSException { this(xaSession, xaSession.getSession(), sameRMOverrideValue); } public SessionInvocationHandler(XAQueueSession xaSession, Boolean sameRMOverrideValue) throws JMSException { this(xaSession, xaSession.getQueueSession(), sameRMOverrideValue); } public SessionInvocationHandler(XATopicSession xaSession, Boolean sameRMOverrideValue) throws JMSException { this(xaSession, xaSession.getTopicSession(), sameRMOverrideValue); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (logger.isDebugEnabled()) { logger.debug(this + " Invoking " + method); } // processing method from MuleXaObject if (XaTransaction.MuleXaObject.DELIST_METHOD_NAME.equals(method.getName())) { return delist(); } else if (XaTransaction.MuleXaObject.ENLIST_METHOD_NAME.equals(method.getName())) { return enlist(); } else if (XaTransaction.MuleXaObject.SET_REUSE_OBJECT_METHOD_NAME.equals(method.getName())) { reuseObject = (Boolean) args[0]; return null; } else if (XaTransaction.MuleXaObject.IS_REUSE_OBJECT_METHOD_NAME.equals(method.getName())) { return reuseObject; } else if (XaTransaction.MuleXaObject.GET_TARGET_OBJECT_METHOD_NAME.equals(method.getName())) { return getTargetObject(); } else if (XaTransaction.MuleXaObject.CLOSE_METHOD_NAME.equals(method.getName())) { // some jms implementation need both sessions closed, some not try { session.close(); xaSession.close(); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Closing the session and the xaSession failed", ex); } } return null; } Object result = method.invoke(session, args); if (result instanceof TopicSubscriber) { result = Proxy.newProxyInstance(Session.class.getClassLoader(), new Class[] { TopicSubscriber.class }, new ConsumerProducerInvocationHandler(this, result)); } else if (result instanceof QueueReceiver) { result = Proxy.newProxyInstance(Session.class.getClassLoader(), new Class[] { QueueReceiver.class }, new ConsumerProducerInvocationHandler(this, result)); } else if (result instanceof MessageConsumer) { result = Proxy.newProxyInstance(Session.class.getClassLoader(), new Class[] { MessageConsumer.class }, new ConsumerProducerInvocationHandler(this, result)); } else if (result instanceof TopicPublisher) { result = Proxy.newProxyInstance(Session.class.getClassLoader(), new Class[] { TopicPublisher.class }, new ConsumerProducerInvocationHandler(this, result)); } else if (result instanceof QueueSender) { result = Proxy.newProxyInstance(Session.class.getClassLoader(), new Class[] { QueueSender.class }, new ConsumerProducerInvocationHandler(this, result)); } else if (result instanceof MessageProducer) { result = Proxy.newProxyInstance(Session.class.getClassLoader(), new Class[] { MessageProducer.class }, new ConsumerProducerInvocationHandler(this, result)); } return result; } public boolean enlist() throws Exception { if (isEnlisted()) { return false; } if (logger.isDebugEnabled()) { logger.debug("Enlistment request: " + this); } Transaction transaction = TransactionCoordination.getInstance().getTransaction(); if (transaction == null) { throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable()); } if (!(transaction instanceof XaTransaction)) { throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction)); } if (!isEnlisted()) { if (logger.isDebugEnabled()) { logger.debug("Enlisting resource " + xaResource + " in xa transaction " + transaction); } enlisted = ((XaTransaction) transaction).enlistResource(xaResource); } return enlisted; } public boolean delist() throws Exception { if (!isEnlisted()) { return false; } if (logger.isDebugEnabled()) { logger.debug("Delistment request: " + this); } Transaction transaction = TransactionCoordination.getInstance().getTransaction(); if (transaction == null) { throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable()); } if (!(transaction instanceof XaTransaction)) { throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction)); } if (isEnlisted()) { if (logger.isDebugEnabled()) { logger.debug("Delisting resource " + xaResource + " in xa transaction " + transaction); } enlisted = !((XaTransaction) transaction).delistResource(xaResource, XAResource.TMSUCCESS); } return !isEnlisted(); } public boolean isEnlisted() { return enlisted; } public void setEnlisted(boolean enlisted) { this.enlisted = enlisted; } public Object getTargetObject() { return xaSession; } public XAResource getXAResource() { return xaResource; } }