001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.camel.component;
018
019import java.lang.reflect.Constructor;
020
021import javax.jms.ConnectionFactory;
022
023import org.apache.activemq.Service;
024import org.apache.activemq.spring.ActiveMQConnectionFactory;
025import org.apache.camel.component.jms.JmsConfiguration;
026import org.springframework.jms.connection.JmsTransactionManager;
027import org.springframework.jms.connection.SingleConnectionFactory;
028import org.springframework.jms.core.JmsTemplate;
029import org.springframework.transaction.PlatformTransactionManager;
030
031/**
032 *
033 */
034public class ActiveMQConfiguration extends JmsConfiguration {
035    private String brokerURL = ActiveMQConnectionFactory.DEFAULT_BROKER_URL;
036    private boolean useSingleConnection = false;
037    private boolean usePooledConnection = true;
038    private String userName;
039    private String password;
040    private ActiveMQComponent activeMQComponent;
041
042    public ActiveMQConfiguration() {
043    }
044
045    public String getBrokerURL() {
046        return brokerURL;
047    }
048
049    /**
050     * Sets the broker URL to use to connect to ActiveMQ using the
051     * <a href="http://activemq.apache.org/configuring-transports.html">ActiveMQ URI format</a>
052     *
053     * @param brokerURL the URL of the broker.
054     */
055    public void setBrokerURL(String brokerURL) {
056        this.brokerURL = brokerURL;
057    }
058
059    public boolean isUseSingleConnection() {
060        return useSingleConnection;
061    }
062
063    public String getUserName() {
064        return userName;
065    }
066
067    /**
068     * Sets the username to be used to login to ActiveMQ
069     * @param userName
070     */
071    public void setUserName(String userName) {
072        this.userName = userName;
073    }
074
075    public String getPassword() {
076        return password;
077    }
078
079    /**
080     * Sets the password/passcode used to login to ActiveMQ
081     *
082     * @param password
083     */
084    public void setPassword(String password) {
085        this.password = password;
086    }
087
088    /**
089     * Enables or disables whether a Spring {@link SingleConnectionFactory} will be used so that when
090     * messages are sent to ActiveMQ from outside of a message consuming thread, pooling will be used rather
091     * than the default with the Spring {@link JmsTemplate} which will create a new connection, session, producer
092     * for each message then close them all down again.
093     * <p/>
094     * The default value is false and a pooled connection is used by default.
095     *
096     * @param useSingleConnection
097     */
098    public void setUseSingleConnection(boolean useSingleConnection) {
099        this.useSingleConnection = useSingleConnection;
100    }
101
102    public boolean isUsePooledConnection() {
103        return usePooledConnection;
104    }
105
106    /**
107     * Enables or disables whether a PooledConnectionFactory will be used so that when
108     * messages are sent to ActiveMQ from outside of a message consuming thread, pooling will be used rather
109     * than the default with the Spring {@link JmsTemplate} which will create a new connection, session, producer
110     * for each message then close them all down again.
111     * <p/>
112     * The default value is true. Note that this requires an extra dependency on commons-pool.
113     */
114    public void setUsePooledConnection(boolean usePooledConnection) {
115        this.usePooledConnection = usePooledConnection;
116    }
117
118    /**
119     * Factory method to create a default transaction manager if one is not specified
120     */
121    @Override
122    protected PlatformTransactionManager createTransactionManager() {
123        JmsTransactionManager answer = new JmsTransactionManager(getConnectionFactory());
124        answer.afterPropertiesSet();
125        return answer;
126    }
127
128    protected void setActiveMQComponent(ActiveMQComponent activeMQComponent) {
129        this.activeMQComponent = activeMQComponent;
130    }
131
132    @Override
133    protected ConnectionFactory createConnectionFactory() {
134        ActiveMQConnectionFactory answer = new ActiveMQConnectionFactory();
135        if (userName != null) {
136            answer.setUserName(userName);
137        }
138        if (password != null) {
139            answer.setPassword(password);
140        }
141        if (answer.getBeanName() == null) {
142            answer.setBeanName("Camel");
143        }
144        answer.setBrokerURL(getBrokerURL());
145        if (isUseSingleConnection()) {
146            SingleConnectionFactory scf = new SingleConnectionFactory(answer);
147            if (activeMQComponent != null) {
148                activeMQComponent.addSingleConnectionFactory(scf);
149            }
150            return scf;
151        }
152        else if (isUsePooledConnection()) {
153            ConnectionFactory pcf = createPooledConnectionFactory(answer);
154            if (activeMQComponent != null) {
155                activeMQComponent.addPooledConnectionFactoryService((Service) pcf);
156            }
157            return pcf;
158        }
159        else {
160            return answer;
161        }
162    }
163
164    protected ConnectionFactory createPooledConnectionFactory(ActiveMQConnectionFactory connectionFactory) {
165        // lets not use classes directly to avoid a runtime dependency on commons-pool
166        // for folks not using this option
167        try {
168            Class type = loadClass("org.apache.activemq.pool.PooledConnectionFactory", getClass().getClassLoader());
169            Constructor constructor = type.getConstructor(org.apache.activemq.ActiveMQConnectionFactory.class);
170            return (ConnectionFactory) constructor.newInstance(connectionFactory);
171        }
172        catch (Exception e) {
173            throw new RuntimeException("Failed to instantiate PooledConnectionFactory: " + e, e);
174        }
175    }
176
177    public static Class<?> loadClass(String name, ClassLoader loader) throws ClassNotFoundException {
178        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
179        if (contextClassLoader != null) {
180            try {
181                return contextClassLoader.loadClass(name);
182            }
183            catch (ClassNotFoundException e) {
184                try {
185                    return loader.loadClass(name);
186                }
187                catch (ClassNotFoundException e1) {
188                    throw e1;
189                }
190            }
191        } else {
192            return loader.loadClass(name);
193        }
194    }
195}