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.annotation.PostConstruct;
020    import javax.annotation.PreDestroy;
021    import javax.jms.ConnectionFactory;
022    import javax.transaction.TransactionManager;
023    
024    import org.slf4j.Logger;
025    import org.slf4j.LoggerFactory;
026    import org.apache.commons.pool.ObjectPoolFactory;
027    import org.springframework.beans.factory.FactoryBean;
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     * @org.apache.xbean.XBean
047     */
048    public class PooledConnectionFactoryBean implements FactoryBean {
049    
050        private static final Logger LOGGER = LoggerFactory.getLogger(PooledConnectionFactoryBean.class);
051    
052        private PooledConnectionFactory pooledConnectionFactory;
053        private ConnectionFactory connectionFactory;
054        private int maxConnections = 1;
055        private int maximumActive = 500;
056        private Object transactionManager;
057        private String resourceName;
058        private ObjectPoolFactory poolFactory;
059    
060        public int getMaxConnections() {
061            return maxConnections;
062        }
063    
064        public void setMaxConnections(int maxConnections) {
065            this.maxConnections = maxConnections;
066        }
067    
068        public int getMaximumActive() {
069            return maximumActive;
070        }
071    
072        public void setMaximumActive(int maximumActive) {
073            this.maximumActive = maximumActive;
074        }
075    
076        public Object getTransactionManager() {
077            return transactionManager;
078        }
079    
080        public void setTransactionManager(Object transactionManager) {
081            this.transactionManager = transactionManager;
082        }
083    
084        public String getResourceName() {
085            return resourceName;
086        }
087    
088        public void setResourceName(String resourceName) {
089            this.resourceName = resourceName;
090        }
091    
092        public ConnectionFactory getConnectionFactory() {
093            return connectionFactory;
094        }
095    
096        public void setConnectionFactory(ConnectionFactory connectionFactory) {
097            this.connectionFactory = connectionFactory;
098        }
099    
100        public ObjectPoolFactory getPoolFactory() {
101            return poolFactory;
102        }
103    
104        public void setPoolFactory(ObjectPoolFactory poolFactory) {
105            this.poolFactory = poolFactory;
106        }
107    
108        /**
109         *
110         * @throws Exception
111         * @org.apache.xbean.InitMethod
112         */
113        @PostConstruct
114        public void afterPropertiesSet() throws Exception {
115            if (pooledConnectionFactory == null && transactionManager != null && resourceName != null) {
116                try {
117                    LOGGER.debug("Trying to build a JcaPooledConnectionFactory");
118                    JcaPooledConnectionFactory f = new JcaPooledConnectionFactory();
119                    f.setName(resourceName);
120                    f.setTransactionManager((TransactionManager) transactionManager);
121                    f.setMaxConnections(maxConnections);
122                    f.setMaximumActive(maximumActive);
123                    f.setConnectionFactory(connectionFactory);
124                    f.setPoolFactory(poolFactory);
125                    this.pooledConnectionFactory = f;
126                } catch (Throwable t) {
127                    LOGGER.debug("Could not create JCA enabled connection factory: " + t, t);
128                }
129            }
130            if (pooledConnectionFactory == null && transactionManager != null) {
131                try {
132                    LOGGER.debug("Trying to build a XaPooledConnectionFactory");
133                    XaPooledConnectionFactory f = new XaPooledConnectionFactory();
134                    f.setTransactionManager((TransactionManager) transactionManager);
135                    f.setMaxConnections(maxConnections);
136                    f.setMaximumActive(maximumActive);
137                    f.setConnectionFactory(connectionFactory);
138                    f.setPoolFactory(poolFactory);
139                    this.pooledConnectionFactory = f;
140                } catch (Throwable t) {
141                    LOGGER.debug("Could not create XA enabled connection factory: " + t, t);
142                }
143            }
144            if (pooledConnectionFactory == null) {
145                try {
146                    LOGGER.debug("Trying to build a PooledConnectionFactory");
147                    PooledConnectionFactory f = new PooledConnectionFactory();
148                    f.setMaxConnections(maxConnections);
149                    f.setMaximumActive(maximumActive);
150                    f.setConnectionFactory(connectionFactory);
151                    f.setPoolFactory(poolFactory);
152                    this.pooledConnectionFactory = f;
153                } catch (Throwable t) {
154                    LOGGER.debug("Could not create pooled connection factory: " + t, t);
155                }
156            }
157            if (pooledConnectionFactory == null) {
158                throw new IllegalStateException("Unable to create pooled connection factory.  Enable DEBUG log level for more informations");
159            }
160        }
161    
162        /**
163         *
164         * @throws Exception
165         * @org.apache.xbean.DestroyMethod
166         */
167        @PreDestroy
168        public void destroy() throws Exception {
169            if (pooledConnectionFactory != null) {
170                pooledConnectionFactory.stop();
171                pooledConnectionFactory = null;
172            }
173        }
174    
175        // FactoryBean methods
176        public Object getObject() throws Exception {
177            return pooledConnectionFactory;
178        }
179    
180        public Class getObjectType() {
181            return ConnectionFactory.class;
182        }
183    
184        public boolean isSingleton() {
185            return true;
186        }
187    }