Package org.codehaus.activemq

Source Code of org.codehaus.activemq.ActiveMQConnectionFactory

/**
*
* Copyright 2004 Protique Ltd
*
* Licensed 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 org.codehaus.activemq;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.broker.BrokerConnector;
import org.codehaus.activemq.broker.BrokerContainer;
import org.codehaus.activemq.broker.BrokerContainerFactory;
import org.codehaus.activemq.broker.impl.BrokerClientImpl;
import org.codehaus.activemq.broker.impl.BrokerConnectorImpl;
import org.codehaus.activemq.broker.impl.BrokerContainerFactoryImpl;
import org.codehaus.activemq.jndi.JNDIBaseStorable;
import org.codehaus.activemq.management.JMSStatsImpl;
import org.codehaus.activemq.management.StatsCapable;
import org.codehaus.activemq.message.ActiveMQQueue;
import org.codehaus.activemq.message.ActiveMQTopic;
import org.codehaus.activemq.message.ConnectionInfo;
import org.codehaus.activemq.message.ConsumerInfo;
import org.codehaus.activemq.message.DefaultWireFormat;
import org.codehaus.activemq.message.WireFormat;
import org.codehaus.activemq.service.Service;
import org.codehaus.activemq.transport.TransportChannel;
import org.codehaus.activemq.transport.TransportChannelFactory;
import org.codehaus.activemq.transport.TransportChannelListener;
import org.codehaus.activemq.transport.TransportChannelProvider;
import org.codehaus.activemq.transport.vm.VmTransportChannel;
import org.codehaus.activemq.util.IdGenerator;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.management.j2ee.statistics.Stats;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
* A ConnectionFactory is an an Administed object, and is used for creating
* Connections.
* <p/>
* This class also implements QueueConnectionFactory and TopicConnectionFactory and is an Administered object.
* You can use this connection to create both QueueConnections and TopicConnections.
*
* @version $Revision: 1.29 $
* @see javax.jms.ConnectionFactory
*/
public class ActiveMQConnectionFactory extends JNDIBaseStorable implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory, Service, StatsCapable {

    private static final Log log = LogFactory.getLog(ActiveMQConnectionFactory.class);

    protected static BrokerContainer container;
    private static Map brokers = new HashMap();

    protected String userName;
    protected String password;
    protected String brokerURL;
    protected String clientID;
    private boolean useEmbeddedBroker;
    /* The list of emebeded brokers that this object started */
    private List startedEmbeddedBrokers = new ArrayList();

    private JMSStatsImpl stats = new JMSStatsImpl();
    private WireFormat wireFormat = new DefaultWireFormat();
    private IdGenerator idGenerator = new IdGenerator();
    private int connectionCount;
    private BrokerContainerFactory brokerContainerFactory;

    /**
     * Default Constructor for ActiveMQConnectionFactory
     */
    public ActiveMQConnectionFactory() {
        this.userName = ActiveMQConnection.DEFAULT_USER;
        this.password = ActiveMQConnection.DEFAULT_PASSWORD;
        this.brokerURL = ActiveMQConnection.DEFAULT_URL;
    }

    public ActiveMQConnectionFactory(String brokerURL) {
        this();
        this.brokerURL = brokerURL;
    }

    public ActiveMQConnectionFactory(String userName, String password, String brokerURL) {
        this.userName = userName;
        this.password = password;
        this.brokerURL = brokerURL;
    }

    public Stats getStats() {
        return stats;
    }

    public JMSStatsImpl getFactoryStats() {
        return stats;
    }

    /**
     * @return Returns the brokerURL.
     */
    public String getBrokerURL() {
        return brokerURL;
    }

    /**
     * @param brokerURL The brokerURL to set.
     */
    public void setBrokerURL(String brokerURL) {
        this.brokerURL = brokerURL;
    }

    /**
     * @return Returns the clientID.
     */
    public String getClientID() {
        return clientID;
    }

    /**
     * @param clientID The clientID to set.
     */
    public void setClientID(String clientID) {
        this.clientID = clientID;
    }

    /**
     * @return Returns the password.
     */
    public String getPassword() {
        return password;
    }

    /**
     * @param password The password to set.
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @return Returns the userName.
     */
    public String getUserName() {
        return userName;
    }

    /**
     * @param userName The userName to set.
     */
    public void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * Is an embedded broker used by this connection factory
     *
     * @return true if an embedded broker will be used by this connection factory
     */
    public boolean isUseEmbeddedBroker() {
        return useEmbeddedBroker;
    }

    /**
     * Allows embedded brokers to be associated with a connection factory
     *
     * @param useEmbeddedBroker
     */
    public void setUseEmbeddedBroker(boolean useEmbeddedBroker) {
        this.useEmbeddedBroker = useEmbeddedBroker;
    }

    public WireFormat getWireFormat() {
        return wireFormat;
    }

    /**
     * Allows a custom wire format to be used; otherwise the default Java wire format is used
     * which is designed for minimum size and maximum speed on the Java platform
     *
     * @param wireFormat
     */
    public void setWireFormat(WireFormat wireFormat) {
        this.wireFormat = wireFormat;
    }

    public BrokerContainerFactory getBrokerContainerFactory() {
        if (brokerContainerFactory == null) {
            brokerContainerFactory = new BrokerContainerFactoryImpl();
        }
        return brokerContainerFactory;
    }

    public void setBrokerContainerFactory(BrokerContainerFactory brokerContainerFactory) {
        this.brokerContainerFactory = brokerContainerFactory;
    }

    /**
     * Set the properties that will represent the instance in JNDI
     *
     * @param props
     */
    protected void buildFromProperties(Properties props) {
        this.userName = props.getProperty("userName", this.userName);
        this.password = props.getProperty("password", this.password);
        this.brokerURL = props.getProperty("brokerURL", this.brokerURL);
        this.clientID = props.getProperty("clientID");
        this.useEmbeddedBroker = getBoolean(props, "useEmbeddedBroker");
    }

    /**
     * Initialize the instance from properties stored in JNDI
     *
     * @param props
     */
    protected void populateProperties(Properties props) {
        props.put("userName", this.userName);
        props.put("password", this.password);
        props.put("brokerURL", this.brokerURL);
        if (this.clientID != null) {
            props.put("clientID", this.clientID);
        }
        props.put("useEmbeddedBroker", (useEmbeddedBroker) ? "true" : "false");
    }

    /**
     * Helper method to return the property value as a boolean flag
     */
    protected boolean getBoolean(Properties props, String key) {
        String value = props.getProperty(key);
        return value != null && value.equalsIgnoreCase("true");
    }

    /**
     * Create a JMS Connection
     *
     * @return the JMS Connection
     * @throws JMSException if an error occurs creating the Connection
     */
    public Connection createConnection() throws JMSException {
        return this.createConnection(this.userName, this.password);
    }

    /**
     * @param userName
     * @param password
     * @return the Connection
     * @throws JMSException if an error occurs creating the Connection
     */
    public Connection createConnection(String userName, String password) throws JMSException {
        ActiveMQConnection connection = new ActiveMQConnection(this, userName, password, createTransportChannel(this.brokerURL));
        if (this.clientID != null && this.clientID.length() > 0) {
            connection.setClientID(this.clientID);
        }
        return connection;
    }

    /**
     * Create a JMS QueueConnection
     *
     * @return the JMS QueueConnection
     * @throws JMSException if an error occurs creating the Connection
     */
    public QueueConnection createQueueConnection() throws JMSException {
        return this.createQueueConnection(this.userName, this.password);
    }

    /**
     * @param userName
     * @param password
     * @return the QueueConnection
     * @throws JMSException if an error occurs creating the Connection
     */
    public QueueConnection createQueueConnection(String userName, String password) throws JMSException {
        return (QueueConnection) createConnection(userName, password);
    }

    /**
     * Create a JMS TopicConnection
     *
     * @return the JMS TopicConnection
     * @throws JMSException if an error occurs creating the Connection
     */
    public TopicConnection createTopicConnection() throws JMSException {
        return this.createTopicConnection(this.userName, this.password);
    }

    /**
     * @param userName
     * @param password
     * @return the TopicConnection
     * @throws JMSException if an error occurs creating the Connection
     */
    public TopicConnection createTopicConnection(String userName, String password) throws JMSException {
        return (TopicConnection) createConnection(userName, password);
    }


    public void start() throws JMSException {
    }

    /**
     * A hook to allow any embedded JMS Broker's to be closed down
     *
     * @throws JMSException
     */
    public synchronized void stop() throws JMSException {
        // Stop all embded brokers that we started.
        for (Iterator iter = startedEmbeddedBrokers.iterator(); iter.hasNext();) {
            String uri = (String) iter.next();
            unregisterBroker(uri);
        }
        if (container != null) {
            container.stop();
            container = null;
        }
    }

    /**
     * Factory method to create a TransportChannel from a URL
     */
    protected TransportChannel createTransportChannel(String theURLString) throws JMSException {
        URI uri = createURI(theURLString);

        TransportChannelFactory factory =
                TransportChannelProvider.getFactory(uri);

        BrokerConnector brokerConnector = null;
        boolean created = false;
        boolean embedServer = isUseEmbeddedBroker() || factory.requiresEmbeddedBroker();
        if (embedServer) {
            synchronized (this) {
                brokerConnector = (BrokerConnector) brokers.get(theURLString);
                if (brokerConnector == null) {
                    brokerConnector = createBrokerConnector(theURLString);
                    registerBroker(theURLString, brokerConnector);
                    startedEmbeddedBrokers.add(theURLString);
                    created = true;
                }
            }
        }
        TransportChannel transportChannel = factory.create(getWireFormat(), uri);
        if (embedServer) {
            return ensureServerIsAvailable(uri, transportChannel, brokerConnector, created);
        }
        return transportChannel;
    }

    public static synchronized void registerBroker(String theURLString, BrokerConnector brokerConnector) {
        brokers.put(theURLString, brokerConnector);
    }

    public static synchronized void unregisterBroker(String theURLString) {
        brokers.remove(theURLString);
    }

    protected synchronized BrokerContainer getContainer(String brokerName) throws JMSException {
        if (container == null) {
            container = getBrokerContainerFactory().createBrokerContainer(brokerName);
            container.start();
        }
        return container;
    }

    protected BrokerConnector createBrokerConnector(String url) throws JMSException {
        BrokerConnector brokerConnector;
        brokerConnector = new BrokerConnectorImpl(getContainer(url), url, getWireFormat());
        brokerConnector.start();

        // lets wait a little for the server to startup
        log.info("Embedded JMS Broker has started");
        try {
            Thread.sleep(1000);
        }
        catch (InterruptedException e) {
            System.out.println("Caught: " + e);
            e.printStackTrace();
        }
        return brokerConnector;
    }


    protected TransportChannel ensureServerIsAvailable(URI remoteLocation, TransportChannel channel, BrokerConnector brokerConnector, boolean created) throws JMSException {
        ensureVmServerIsAvailable(channel, brokerConnector);
        if (channel.isMulticast()) {
            return ensureMulticastChannelIsAvailable(remoteLocation, channel, brokerConnector, created);
        }
        return channel;
    }

    private void ensureVmServerIsAvailable(TransportChannel channel, BrokerConnector brokerConnector) throws JMSException {
        if (channel instanceof VmTransportChannel && brokerConnector instanceof TransportChannelListener) {
            TransportChannelListener listener = (TransportChannelListener) brokerConnector;
            VmTransportChannel answer = (VmTransportChannel) channel;

            listener.addClient(answer.createServerSide());
        }
    }

    protected TransportChannel ensureMulticastChannelIsAvailable(URI remoteLocation, TransportChannel channel, BrokerConnector brokerConnector, boolean created) throws JMSException {
        if (created) {
            BrokerConnectorImpl brokerImpl = (BrokerConnectorImpl) brokerConnector;

            BrokerClientImpl client = new BrokerClientImpl();
            client.initialize(brokerImpl, channel);
            channel.start();
            String brokerClientID = createMulticastClientID();
            channel.setClientID(brokerClientID);

            // lets spoof a consumer for topics which will replicate messages
            // over the multicast transport
            ConnectionInfo info = new ConnectionInfo();
            info.setHostName(IdGenerator.getHostName());
            info.setClientId(brokerClientID);
            info.setStarted(true);
            client.consumeConnectionInfo(info);

            ConsumerInfo consumerInfo = new ConsumerInfo();
            consumerInfo.setDestination(new ActiveMQTopic(">"));
            consumerInfo.setNoLocal(true);
            consumerInfo.setClientId(brokerClientID);
            consumerInfo.setConsumerId(idGenerator.generateId());
            consumerInfo.setId(consumerInfo.getConsumerId());
            consumerInfo.setStarted(true);
            client.consumeConsumerInfo(consumerInfo);

            consumerInfo = new ConsumerInfo();
            consumerInfo.setDestination(new ActiveMQQueue(">"));
            consumerInfo.setNoLocal(true);
            consumerInfo.setClientId(brokerClientID);
            consumerInfo.setConsumerId(idGenerator.generateId());
            consumerInfo.setId(consumerInfo.getConsumerId());
            consumerInfo.setStarted(true);
            client.consumeConsumerInfo(consumerInfo);
        }

        // now lets create a VM channel that the JMS client will use
        // to connect to the embedded brokerConnector
        URI localURI = createURI("vm", remoteLocation);
        TransportChannel localChannel = TransportChannelProvider.create(getWireFormat(), localURI);
        ensureVmServerIsAvailable(localChannel, brokerConnector);
        return localChannel;
    }

    /**
     * Creates the clientID for the multicast client (used to dispatch local
     * messages over a multicast bus)
     */
    protected String createMulticastClientID() {
        return idGenerator.generateId();
    }

    protected URI createURI(String protocol, URI uri) throws JMSException {
        try {
            return new URI(protocol, uri.getRawSchemeSpecificPart(), uri.getFragment());
        }
        catch (URISyntaxException e) {
            JMSException jmsEx = new JMSException("the URL string is badly formated:", e.getMessage());
            jmsEx.setLinkedException(e);
            throw jmsEx;

        }
    }

    protected URI createURI(String uri) throws JMSException {
        try {
            if (uri == null) {
                throw new JMSException("The connection URI must be specified!");
            }
            return new URI(uri);
        }
        catch (URISyntaxException e) {
            JMSException jmsEx = new JMSException("the URL string is badly formated:", e.getMessage());
            jmsEx.setLinkedException(e);
            throw jmsEx;

        }
    }

    /**
     * Called when a connection is closed so that we can shut down any embedded brokers cleanly
     *
     * @param connection
     */
    synchronized void onConnectionClose(ActiveMQConnection connection) throws JMSException {
        if (--connectionCount <= 0) {
            // close any broker if we've got one
            stop();
        }

    }

    synchronized void onConnectionCreate(ActiveMQConnection connection) {
        ++connectionCount;
    }

}
TOP

Related Classes of org.codehaus.activemq.ActiveMQConnectionFactory

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.