com.facetime.communication.activemq.AmqConsumer.java Source code

Java tutorial

Introduction

Here is the source code for com.facetime.communication.activemq.AmqConsumer.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.facetime.communication.activemq;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.MessageAvailableConsumer;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Represents a messaging client used from inside a web container typically
 * stored inside a HttpSession TODO controls to prevent DOS attacks with users
 * requesting many consumers TODO configure consumers with small prefetch.
 * 
 * @version $Revision: 1.1.1.1 $
 */
public class AmqConsumer implements HttpSessionActivationListener, HttpSessionBindingListener {

    public static final String WEB_CLIENT_ATTRIBUTE = "org.apache.activemq.webclient";
    public static final String CONNECTION_FACTORY_ATTRIBUTE = "org.apache.activemq.connectionFactory";
    public static final String CONNECTION_FACTORY_PREFETCH_PARAM = "org.apache.activemq.connectionFactory.prefetch";
    public static final String CONNECTION_FACTORY_OPTIMIZE_ACK_PARAM = "org.apache.activemq.connectionFactory.optimizeAck";
    public static final String BROKER_URL_INIT_PARAM = "org.apache.activemq.brokerURL";
    public static final String SELECTOR_NAME = "org.apache.activemq.selectorName";

    private static final Log LOG = LogFactory.getLog(AmqConsumer.class);

    /**
     * activemq's broker url
     */
    public static String BROKER_URL = "";

    private static transient ConnectionFactory factory;
    private static transient Connection connection;

    private transient Map<Destination, MessageConsumer> consumers = new HashMap<Destination, MessageConsumer>();

    private transient Session session;
    private transient MessageProducer producer;
    private int deliveryMode = DeliveryMode.NON_PERSISTENT;
    public static String selectorName;

    private final Semaphore semaphore = new Semaphore(1);

    private CamelContext camelContext;
    private ProducerTemplate producerTemplate;

    public AmqConsumer() {
        if (factory == null) {
            throw new IllegalStateException("initContext(ServletContext) not called");
        }
    }

    /**
     * Helper method to get the client for the current session, lazily creating
     * a client if there is none currently
     * 
     * @param request
     *            is the current HTTP request
     * @return the current client or a newly creates
     */
    public static AmqConsumer getWebClient(HttpServletRequest request) {
        HttpSession session = request.getSession(true);
        AmqConsumer client = getWebClient(session);
        if (client == null || client.isClosed()) {
            client = AmqConsumer.createWebClient(request);
            session.setAttribute(WEB_CLIENT_ATTRIBUTE, client);
        }

        return client;
    }

    /**
     * @return the web client for the current HTTP session or null if there is
     *         not a web client created yet
     */
    public static AmqConsumer getWebClient(HttpSession session) {
        return (AmqConsumer) session.getAttribute(WEB_CLIENT_ATTRIBUTE);
    }

    public static void initContext(ServletContext context) {
        initConnectionFactory(context);
        context.setAttribute("webClients", new HashMap<String, AmqConsumer>());
        if (selectorName == null) {
            selectorName = context.getInitParameter(SELECTOR_NAME);
        }
        if (selectorName == null) {
            selectorName = "selector";
        }
    }

    public int getDeliveryMode() {
        return deliveryMode;
    }

    public void setDeliveryMode(int deliveryMode) {
        this.deliveryMode = deliveryMode;
    }

    public synchronized void closeConsumers() {
        for (Iterator<MessageConsumer> it = consumers.values().iterator(); it.hasNext();) {
            MessageConsumer consumer = it.next();
            it.remove();
            try {
                consumer.setMessageListener(null);
                if (consumer instanceof MessageAvailableConsumer) {
                    ((MessageAvailableConsumer) consumer).setAvailableListener(null);
                }
                consumer.close();
            } catch (JMSException e) {
                LOG.debug("caught exception closing consumer", e);
            }
        }
    }

    public synchronized void close() {
        try {
            if (consumers != null) {
                closeConsumers();
            }
            if (producerTemplate != null) {
                producerTemplate.stop();
            }
        } catch (Exception e) {
            LOG.debug("caught exception closing consumer", e);
        } finally {
            producer = null;
            session = null;
            producerTemplate = null;
            if (consumers != null) {
                consumers.clear();
            }
            consumers = null;

        }
    }

    public boolean isClosed() {
        return consumers == null;
    }

    public void send(Destination destination, Message message) throws JMSException {
        getProducer().send(destination, message);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Sent! to destination: " + destination + " message: " + message);
        }
    }

    public void send(Destination destination, Message message, boolean persistent, int priority, long timeToLive)
            throws JMSException {
        int deliveryMode = persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT;
        getProducer().send(destination, message, deliveryMode, priority, timeToLive);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Sent! to destination: " + destination + " message: " + message);
        }
    }

    public Session getSession() throws JMSException {
        if (session == null) {
            session = createSession();
        }
        return session;
    }

    public Connection getConnection() throws JMSException {
        if (connection == null) {
            synchronized (factory) {
                connection = factory.createConnection();
                connection.start();
            }
        }
        return connection;
    }

    protected static synchronized void initConnectionFactory(ServletContext servletContext) {
        if (factory == null) {
            factory = (ConnectionFactory) servletContext.getAttribute(CONNECTION_FACTORY_ATTRIBUTE);
        }
        if (factory == null) {
            String brokerURL = servletContext.getInitParameter(BROKER_URL_INIT_PARAM);

            BROKER_URL = brokerURL;

            LOG.debug("Value of: " + BROKER_URL_INIT_PARAM + " is: " + brokerURL);

            if (brokerURL == null) {
                throw new IllegalStateException(
                        "missing brokerURL (specified via " + BROKER_URL_INIT_PARAM + " init-Param");
            }

            ActiveMQConnectionFactory amqfactory = new ActiveMQConnectionFactory(brokerURL);

            // Set prefetch policy for factory
            if (servletContext.getInitParameter(CONNECTION_FACTORY_PREFETCH_PARAM) != null) {
                int prefetch = Integer.valueOf(servletContext.getInitParameter(CONNECTION_FACTORY_PREFETCH_PARAM))
                        .intValue();
                amqfactory.getPrefetchPolicy().setAll(prefetch);
            }

            // Set optimize acknowledge setting
            if (servletContext.getInitParameter(CONNECTION_FACTORY_OPTIMIZE_ACK_PARAM) != null) {
                boolean optimizeAck = Boolean
                        .valueOf(servletContext.getInitParameter(CONNECTION_FACTORY_OPTIMIZE_ACK_PARAM))
                        .booleanValue();
                amqfactory.setOptimizeAcknowledge(optimizeAck);
            }

            factory = amqfactory;

            servletContext.setAttribute(CONNECTION_FACTORY_ATTRIBUTE, factory);
        }
    }

    public synchronized CamelContext getCamelContext() {
        if (camelContext == null) {
            LOG.debug("Creating camel context");
            camelContext = new DefaultCamelContext();
            // TODO
            // ActiveMQConfiguration conf = new ActiveMQConfiguration();
            // conf.setConnectionFactory(new
            // PooledConnectionFactory((ActiveMQConnectionFactory)factory));
            // ActiveMQComponent component = new ActiveMQComponent(conf);
            // camelContext.addComponent("activemq", component);
        }
        return camelContext;
    }

    public synchronized ProducerTemplate getProducerTemplate() throws Exception {
        if (producerTemplate == null) {
            LOG.debug("Creating producer template");
            producerTemplate = getCamelContext().createProducerTemplate();
            producerTemplate.start();
        }
        return producerTemplate;
    }

    public synchronized MessageProducer getProducer() throws JMSException {
        if (producer == null) {
            producer = getSession().createProducer(null);
            producer.setDeliveryMode(deliveryMode);
        }
        return producer;
    }

    public void setProducer(MessageProducer producer) {
        this.producer = producer;
    }

    public synchronized MessageConsumer getConsumer(Destination destination, String selector) throws JMSException {
        return getConsumer(destination, selector, true);
    }

    public synchronized MessageConsumer getConsumer(Destination destination, String selector, boolean create)
            throws JMSException {
        MessageConsumer consumer = consumers.get(destination);
        if (create && consumer == null) {
            consumer = getSession().createConsumer(destination, selector);
            consumers.put(destination, consumer);
        }
        return consumer;
    }

    public synchronized void closeConsumer(Destination destination) throws JMSException {
        MessageConsumer consumer = consumers.get(destination);
        if (consumer != null) {
            consumers.remove(destination);
            consumer.setMessageListener(null);
            if (consumer instanceof MessageAvailableConsumer) {
                ((MessageAvailableConsumer) consumer).setAvailableListener(null);
            }
            consumer.close();
        }
    }

    public synchronized List<MessageConsumer> getConsumers() {
        return new ArrayList<MessageConsumer>(consumers.values());
    }

    protected Session createSession() throws JMSException {
        return getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
    }

    public Semaphore getSemaphore() {
        return semaphore;
    }

    public void sessionWillPassivate(HttpSessionEvent event) {
        close();
    }

    public void sessionDidActivate(HttpSessionEvent event) {
    }

    public void valueBound(HttpSessionBindingEvent event) {
    }

    public void valueUnbound(HttpSessionBindingEvent event) {
        close();
    }

    protected static AmqConsumer createWebClient(HttpServletRequest request) {
        return new AmqConsumer();
    }

}