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.pool;
018    
019    import javax.jms.ConnectionFactory;
020    import javax.transaction.TransactionManager;
021    
022    import org.apache.commons.logging.Log;
023    import org.apache.commons.logging.LogFactory;
024    import org.apache.commons.pool.ObjectPoolFactory;
025    import org.springframework.beans.factory.FactoryBean;
026    import org.springframework.beans.factory.InitializingBean;
027    import org.springframework.beans.factory.DisposableBean;
028    
029    /**
030     * Simple factory bean used to create a jencks connection pool.
031     * Depending on the properties set, it will create a simple pool,
032     * a transaction aware connection pool, or a jca aware connection pool.
033     *
034     * <pre class="code">
035     * <bean id="pooledConnectionFactory" class="javax.script.ScriptEngineFactory.PooledConnectionFactoryFactoryBean">
036     *   <property name="connectionFactory" ref="connectionFactory" />
037     *   <property name="transactionManager" ref="transactionManager" />
038     *   <property name="resourceName" value="ResourceName" />
039     * </bean>
040     * </pre>
041     *
042     * The <code>resourceName</code> property should be used along with the {@link ActiveMQResourceManager} and have
043     * the same value than its <code>resourceName</code> property. This will make sure the transaction manager
044     * maps correctly the connection factory to the recovery process.
045     *
046     */
047    public class PooledConnectionFactoryBean implements FactoryBean, InitializingBean, DisposableBean {
048    
049        private static final Log LOGGER = LogFactory.getLog(PooledConnectionFactoryBean.class);
050    
051        private PooledConnectionFactory pooledConnectionFactory;
052        private ConnectionFactory connectionFactory;
053        private int maxConnections = 1;
054        private int maximumActive = 500;
055        private Object transactionManager;
056        private String resourceName;
057        private ObjectPoolFactory poolFactory;
058    
059        public Object getObject() throws Exception {
060            return pooledConnectionFactory;
061        }
062    
063        public Class getObjectType() {
064            return ConnectionFactory.class;
065        }
066    
067        public boolean isSingleton() {
068            return true;
069        }
070    
071        public int getMaxConnections() {
072            return maxConnections;
073        }
074    
075        public void setMaxConnections(int maxConnections) {
076            this.maxConnections = maxConnections;
077        }
078    
079        public int getMaximumActive() {
080            return maximumActive;
081        }
082    
083        public void setMaximumActive(int maximumActive) {
084            this.maximumActive = maximumActive;
085        }
086    
087        public Object getTransactionManager() {
088            return transactionManager;
089        }
090    
091        public void setTransactionManager(Object transactionManager) {
092            this.transactionManager = transactionManager;
093        }
094    
095        public String getResourceName() {
096            return resourceName;
097        }
098    
099        public void setResourceName(String resourceName) {
100            this.resourceName = resourceName;
101        }
102    
103        public ConnectionFactory getConnectionFactory() {
104            return connectionFactory;
105        }
106    
107        public void setConnectionFactory(ConnectionFactory connectionFactory) {
108            this.connectionFactory = connectionFactory;
109        }
110    
111        public ObjectPoolFactory getPoolFactory() {
112            return poolFactory;
113        }
114    
115        public void setPoolFactory(ObjectPoolFactory poolFactory) {
116            this.poolFactory = poolFactory;
117        }
118    
119        public void afterPropertiesSet() throws Exception {
120            if (pooledConnectionFactory == null && transactionManager != null && resourceName != null) {
121                try {
122                    LOGGER.debug("Trying to build a JcaPooledConnectionFactory");
123                    JcaPooledConnectionFactory f = new JcaPooledConnectionFactory();
124                    f.setName(resourceName);
125                    f.setTransactionManager((TransactionManager) transactionManager);
126                    f.setMaxConnections(maxConnections);
127                    f.setMaximumActive(maximumActive);
128                    f.setConnectionFactory(connectionFactory);
129                    f.setPoolFactory(poolFactory);
130                    this.pooledConnectionFactory = f;
131                } catch (Throwable t) {
132                    LOGGER.debug("Could not create JCA enabled connection factory: " + t, t);
133                }
134            }
135            if (pooledConnectionFactory == null && transactionManager != null) {
136                try {
137                    LOGGER.debug("Trying to build a XaPooledConnectionFactory");
138                    XaPooledConnectionFactory f = new XaPooledConnectionFactory();
139                    f.setTransactionManager((TransactionManager) transactionManager);
140                    f.setMaxConnections(maxConnections);
141                    f.setMaximumActive(maximumActive);
142                    f.setConnectionFactory(connectionFactory);
143                    f.setPoolFactory(poolFactory);
144                    this.pooledConnectionFactory = f;
145                } catch (Throwable t) {
146                    LOGGER.debug("Could not create XA enabled connection factory: " + t, t);
147                }
148            }
149            if (pooledConnectionFactory == null) {
150                try {
151                    LOGGER.debug("Trying to build a PooledConnectionFactory");
152                    PooledConnectionFactory f = new PooledConnectionFactory();
153                    f.setMaxConnections(maxConnections);
154                    f.setMaximumActive(maximumActive);
155                    f.setConnectionFactory(connectionFactory);
156                    f.setPoolFactory(poolFactory);
157                    this.pooledConnectionFactory = f;
158                } catch (Throwable t) {
159                    LOGGER.debug("Could not create pooled connection factory: " + t, t);
160                }
161            }
162            if (pooledConnectionFactory == null) {
163                throw new IllegalStateException("Unable to create pooled connection factory.  Enable DEBUG log level for more informations");
164            }
165        }
166    
167        public void destroy() throws Exception {
168            if (pooledConnectionFactory != null) {
169                pooledConnectionFactory.stop();
170                pooledConnectionFactory = null;
171            }
172        }
173    }