Package org.mule.transport.jms.activemq

Source Code of org.mule.transport.jms.activemq.ActiveMQJmsConnector

/*
* 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.activemq;

import org.mule.api.MuleContext;
import org.mule.transport.ConnectException;
import org.mule.transport.jms.JmsConnector;
import org.mule.util.ClassUtils;
import org.mule.util.proxy.TargetInvocationHandler;

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;

/**
* ActiveMQ 4.x-specific JMS connector.
*/
public class ActiveMQJmsConnector extends JmsConnector
{
    public static final String ACTIVEMQ_CONNECTION_FACTORY_CLASS = "org.apache.activemq.ActiveMQConnectionFactory";
    public static final String DEFAULT_BROKER_URL = "vm://localhost?broker.persistent=false&broker.useJmx=false";

    private String brokerURL = DEFAULT_BROKER_URL;

    /**
     * Constructs a new ActiveMQJmsConnector.
     */
    public ActiveMQJmsConnector(MuleContext context)
    {
        super(context);
        setEagerConsumer(false);
        // TODO MULE-1409 better support for ActiveMQ 4.x temp destinations
    }

    protected ConnectionFactory getDefaultConnectionFactory() throws Exception
    {
        ConnectionFactory connectionFactory = (ConnectionFactory)
                ClassUtils.instanciateClass(ACTIVEMQ_CONNECTION_FACTORY_CLASS, getBrokerURL());
        applyVendorSpecificConnectionFactoryProperties(connectionFactory);
        return connectionFactory;
    }

    protected void applyVendorSpecificConnectionFactoryProperties(ConnectionFactory connectionFactory)
    {
        try
        {
            Method getRedeliveryPolicyMethod = connectionFactory.getClass().getMethod("getRedeliveryPolicy");
            Object redeliveryPolicy = getRedeliveryPolicyMethod.invoke(connectionFactory);
            Method setMaximumRedeliveriesMethod = redeliveryPolicy.getClass().getMethod("setMaximumRedeliveries", Integer.TYPE);
            int maxRedelivery = getMaxRedelivery();
            if (maxRedelivery != REDELIVERY_IGNORE )
            {
                // redelivery = deliveryCount - 1, but AMQ is considering the first delivery attempt as a redelivery (wrong!). adjust for it
                maxRedelivery++;
            }
            setMaximumRedeliveriesMethod.invoke(redeliveryPolicy, maxRedelivery);
        }
        catch (Exception e)
        {
            logger.error("Can not set MaxRedelivery parameter to RedeliveryPolicy " + e);
        }
    }

    /**
     * Will additionally try to cleanup the ActiveMq connection, otherwise there's a deadlock on shutdown.
     */
    protected void doDisconnect() throws Exception
    {
        try
        {
            Connection connection = getConnection();
            if (connection == null)
            {
                return;
            }

            final Class clazz = connection.getClass();
            Method cleanupMethod = null;
            if (Proxy.isProxyClass(clazz))
            {
                InvocationHandler invocationHandler = Proxy.getInvocationHandler(connection);

                // When using caching-connection-factory, the connections are proxy objects that do nothing on the
                // close and stop methods so that they remain open when returning to the cache. In that case, we don't
                // need to do any custom cleanup, as the connections will be closed when destroying the cache. The
                // type of the invocation handler for these connections is SharedConnectionInvocationHandler.

                if (invocationHandler instanceof TargetInvocationHandler)
                {
                    // this is really an XA connection, bypass the java.lang.reflect.Proxy as it
                    // can't delegate to non-interfaced methods (like proprietary 'cleanup' one)
                    // TODO check if CGlib will manage to enhance the AMQ connection class,
                    // there are no final methods, but a number of private ones, though
                    TargetInvocationHandler targetInvocationHandler = (TargetInvocationHandler) invocationHandler;
                    connection = (Connection) targetInvocationHandler.getTargetObject();
                    Class realConnectionClass = connection.getClass();
                    cleanupMethod = realConnectionClass.getMethod("cleanup", (Class[])null);
                }
                else
                {
                    if (logger.isDebugEnabled())
                    {
                        logger.debug(String.format("InvocationHandler of the JMS connection proxy is of type %s, not doing " +
                                                   "any extra cleanup", invocationHandler.getClass().getName()));
                    }
                }
            }
            else
            {
                cleanupMethod = clazz.getMethod("cleanup", (Class[])null);
            }

            try
            {
                if (cleanupMethod != null)
                {
                    cleanupMethod.invoke(connection, (Object[])null);
                }
            }
            catch (InvocationTargetException ex)
            {
                logger.warn("Exception cleaning up JMS connection: " + ex.getMessage());       
            }
            finally
            {
                try
                {
                    connection.close();
                }
                catch (JMSException ex)
                {
                    logger.warn("Exception closing JMS connection: " + ex.getMessage());
                }
            }
        }
        catch (Exception e)
        {
            throw new ConnectException(e, this);
        }
        finally
        {
            //Is this necessary? It causes a NPE in certain situations
            setConnection(null);
        }
    }

    public String getBrokerURL()
    {
        return brokerURL;
    }

    public void setBrokerURL(String brokerURL)
    {
        this.brokerURL = brokerURL;
    }
}
TOP

Related Classes of org.mule.transport.jms.activemq.ActiveMQJmsConnector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.