com.mirth.connect.connectors.jms.xa.ConnectionFactoryWrapper.java Source code

Java tutorial

Introduction

Here is the source code for com.mirth.connect.connectors.jms.xa.ConnectionFactoryWrapper.java

Source

/*
 * Copyright (c) SymphonySoft Limited. All rights reserved.
 * http://www.symphonysoft.com
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE-MULE.txt file.
 */

package com.mirth.connect.connectors.jms.xa;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.XAConnection;
import javax.jms.XAConnectionFactory;
import javax.jms.XAQueueConnection;
import javax.jms.XAQueueConnectionFactory;
import javax.jms.XAQueueSession;
import javax.jms.XASession;
import javax.jms.XATopicConnection;
import javax.jms.XATopicConnectionFactory;
import javax.jms.XATopicSession;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Guillaume Nodet
 * @version $Revision: 1.4 $
 */
public class ConnectionFactoryWrapper implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory {

    protected Object factory;
    protected TransactionManager tm;
    protected static transient Log logger = LogFactory.getLog(ConnectionFactoryWrapper.class);

    public ConnectionFactoryWrapper(Object factory, TransactionManager tm) {
        this.factory = factory;
        this.tm = tm;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.jms.ConnectionFactory#createConnection()
     */
    public Connection createConnection() throws JMSException {
        XAConnection xac = ((XAConnectionFactory) factory).createXAConnection();
        Connection proxy = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(),
                new Class[] { Connection.class }, new ConnectionInvocationHandler(xac));
        return proxy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.jms.ConnectionFactory#createConnection(java.lang.String,
     *      java.lang.String)
     */
    public Connection createConnection(String username, String password) throws JMSException {
        XAConnection xac = ((XAConnectionFactory) factory).createXAConnection(username, password);
        Connection proxy = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(),
                new Class[] { Connection.class }, new ConnectionInvocationHandler(xac));
        return proxy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.jms.QueueConnectionFactory#createQueueConnection()
     */
    public QueueConnection createQueueConnection() throws JMSException {
        XAQueueConnection xaqc = ((XAQueueConnectionFactory) factory).createXAQueueConnection();
        QueueConnection proxy = (QueueConnection) Proxy.newProxyInstance(Connection.class.getClassLoader(),
                new Class[] { QueueConnection.class }, new ConnectionInvocationHandler(xaqc));
        return proxy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.jms.QueueConnectionFactory#createQueueConnection(java.lang.String,
     *      java.lang.String)
     */
    public QueueConnection createQueueConnection(String username, String password) throws JMSException {
        XAQueueConnection xaqc = ((XAQueueConnectionFactory) factory).createXAQueueConnection(username, password);
        QueueConnection proxy = (QueueConnection) Proxy.newProxyInstance(Connection.class.getClassLoader(),
                new Class[] { QueueConnection.class }, new ConnectionInvocationHandler(xaqc));
        return proxy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.jms.TopicConnectionFactory#createTopicConnection()
     */
    public TopicConnection createTopicConnection() throws JMSException {
        XATopicConnection xatc = ((XATopicConnectionFactory) factory).createXATopicConnection();
        TopicConnection proxy = (TopicConnection) Proxy.newProxyInstance(Connection.class.getClassLoader(),
                new Class[] { TopicConnection.class }, new ConnectionInvocationHandler(xatc));
        return proxy;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.jms.TopicConnectionFactory#createTopicConnection(java.lang.String,
     *      java.lang.String)
     */
    public TopicConnection createTopicConnection(String username, String password) throws JMSException {
        XATopicConnection xatc = ((XATopicConnectionFactory) factory).createXATopicConnection(username, password);
        TopicConnection proxy = (TopicConnection) Proxy.newProxyInstance(Connection.class.getClassLoader(),
                new Class[] { TopicConnection.class }, new ConnectionInvocationHandler(xatc));
        return proxy;
    }

    protected class ConnectionInvocationHandler implements InvocationHandler {

        private Object xac;

        public ConnectionInvocationHandler(Object xac) {
            this.xac = xac;
        }

        /*
         * (non-Javadoc)
         * 
         * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
         *      java.lang.reflect.Method, java.lang.Object[])
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking " + method);
            }
            if (method.getName().equals("createSession")) {
                XASession xas = ((XAConnection) xac).createXASession();
                return (Session) Proxy.newProxyInstance(Session.class.getClassLoader(),
                        new Class[] { Session.class },
                        new SessionInvocationHandler(xas.getSession(), xas.getXAResource()));
            } else if (method.getName().equals("createQueueSession")) {
                XAQueueSession xaqs = ((XAQueueConnection) xac).createXAQueueSession();
                return (Session) Proxy.newProxyInstance(Session.class.getClassLoader(),
                        new Class[] { QueueSession.class },
                        new SessionInvocationHandler(xaqs.getQueueSession(), xaqs.getXAResource()));
            } else if (method.getName().equals("createTopicSession")) {
                XATopicSession xats = ((XATopicConnection) xac).createXATopicSession();
                return (Session) Proxy.newProxyInstance(Session.class.getClassLoader(),
                        new Class[] { TopicSession.class },
                        new SessionInvocationHandler(xats.getTopicSession(), xats.getXAResource()));
            } else {
                return method.invoke(xac, args);
            }
        }

        protected class SessionInvocationHandler implements InvocationHandler {

            private Object session;
            private Object xares;
            private Transaction tx;

            public SessionInvocationHandler(Object session, Object xares) {
                this.session = session;
                this.xares = xares;
            }

            /*
             * (non-Javadoc)
             * 
             * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
             *      java.lang.reflect.Method, java.lang.Object[])
             */
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (logger.isDebugEnabled()) {
                    logger.debug("Invoking " + method);
                }
                Object result = method.invoke(session, args);
                if (result instanceof MessageConsumer) {
                    result = Proxy.newProxyInstance(Session.class.getClassLoader(),
                            new Class[] { MessageConsumer.class }, new ConsumerProducerInvocationHandler(result));
                } else if (result instanceof MessageProducer) {
                    result = Proxy.newProxyInstance(Session.class.getClassLoader(),
                            new Class[] { MessageProducer.class }, new ConsumerProducerInvocationHandler(result));
                }
                return result;
            }

            protected void enlist() throws Exception {
                if (logger.isDebugEnabled()) {
                    logger.debug("Enlistment request: " + this);
                }
                if (tx == null && tm != null) {
                    tx = tm.getTransaction();
                    if (tx != null) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Enlisting resource in xa transaction: " + xares);
                        }
                        XAResource xares = (XAResource) Proxy.newProxyInstance(XAResource.class.getClassLoader(),
                                new Class[] { XAResource.class }, new XAResourceInvocationHandler());
                        tx.enlistResource(xares);
                    }
                }
            }

            protected class XAResourceInvocationHandler implements InvocationHandler {

                /*
                 * (non-Javadoc)
                 * 
                 * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
                 *      java.lang.reflect.Method, java.lang.Object[])
                 */
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    try {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Invoking " + method);
                        }
                        if (method.getName().equals("end")) {
                            tx = null;
                        }
                        return method.invoke(xares, args);
                    } catch (InvocationTargetException e) {
                        throw e.getCause();
                    }
                }
            }

            protected class ConsumerProducerInvocationHandler implements InvocationHandler {

                private Object target;

                public ConsumerProducerInvocationHandler(Object target) {
                    this.target = target;
                }

                /*
                 * (non-Javadoc)
                 * 
                 * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
                 *      java.lang.reflect.Method, java.lang.Object[])
                 */
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Invoking " + method);
                    }
                    if (!method.getName().equals("close")) {
                        enlist();
                    }
                    return method.invoke(target, args);
                }
            }

        }
    }

}