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     */
017    package org.apache.activemq.camel.component;
018    
019    import java.lang.reflect.Constructor;
020    
021    import javax.jms.ConnectionFactory;
022    
023    import org.apache.activemq.Service;
024    import org.apache.activemq.spring.ActiveMQConnectionFactory;
025    import org.apache.camel.component.jms.JmsConfiguration;
026    import org.springframework.jms.connection.SingleConnectionFactory;
027    import org.springframework.jms.connection.JmsTransactionManager;
028    import org.springframework.jms.core.JmsTemplate;
029    import org.springframework.transaction.PlatformTransactionManager;
030    
031    /**
032     * 
033     */
034    public 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 true so that a single 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 false by default as it 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        protected PlatformTransactionManager createTransactionManager() {
122            JmsTransactionManager answer = new JmsTransactionManager(getConnectionFactory());
123            answer.afterPropertiesSet();
124            return answer;
125        }
126    
127        protected void setActiveMQComponent(ActiveMQComponent activeMQComponent) {
128            this.activeMQComponent = activeMQComponent;
129        }
130    
131        @Override
132        protected ConnectionFactory createConnectionFactory() {
133            ActiveMQConnectionFactory answer = new ActiveMQConnectionFactory();
134            if (userName != null) {
135                answer.setUserName(userName);
136            }
137            if (password != null) {
138                answer.setPassword(password);
139            }
140            if (answer.getBeanName() == null) {
141                answer.setBeanName("Camel");
142            }
143            answer.setBrokerURL(getBrokerURL());
144            if (isUseSingleConnection()) {
145                SingleConnectionFactory scf = new SingleConnectionFactory(answer);
146                if (activeMQComponent != null) {
147                    activeMQComponent.addSingleConnectionFactory(scf);
148                }
149                return scf;
150            }
151            else if (isUsePooledConnection()) {
152                ConnectionFactory pcf = createPooledConnectionFactory(answer);
153                if (activeMQComponent != null) {
154                    activeMQComponent.addPooledConnectionFactoryService((Service) pcf);
155                }
156                return pcf;
157            }
158            else {
159                return answer;
160            }
161        }
162    
163        protected ConnectionFactory createPooledConnectionFactory(ActiveMQConnectionFactory connectionFactory) {
164            // lets not use classes directly to avoid a runtime dependency on commons-pool
165            // for folks not using this option
166            try {
167                Class type = loadClass("org.apache.activemq.pool.PooledConnectionFactory", getClass().getClassLoader());
168                Constructor constructor = type.getConstructor(org.apache.activemq.ActiveMQConnectionFactory.class);
169                return (ConnectionFactory) constructor.newInstance(connectionFactory);
170            }
171            catch (Exception e) {
172                throw new RuntimeException("Failed to instantiate PooledConnectionFactory: " + e, e);
173            }
174        }
175    
176        public static Class<?> loadClass(String name, ClassLoader loader) throws ClassNotFoundException {
177            ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
178            if (contextClassLoader != null) {
179                try {
180                    return contextClassLoader.loadClass(name);
181                }
182                catch (ClassNotFoundException e) {
183                    try {
184                        return loader.loadClass(name);
185                    }
186                    catch (ClassNotFoundException e1) {
187                        throw e1;
188                    }
189                }
190            } else {
191                return loader.loadClass(name);
192            }
193        }
194    }