001/*
002 * Copyright 2002-2014 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.jms.connection;
018
019import javax.jms.Connection;
020import javax.jms.ConnectionFactory;
021import javax.jms.JMSException;
022import javax.jms.QueueConnection;
023import javax.jms.QueueConnectionFactory;
024import javax.jms.TopicConnection;
025import javax.jms.TopicConnectionFactory;
026
027import org.springframework.beans.factory.InitializingBean;
028import org.springframework.util.Assert;
029
030/**
031 * {@link javax.jms.ConnectionFactory} implementation that delegates all calls
032 * to a given target {@link javax.jms.ConnectionFactory}, adapting specific
033 * {@code create(Queue/Topic)Connection} calls to the target ConnectionFactory
034 * if necessary (e.g. when running JMS 1.0.2 API based code against a generic
035 * JMS 1.1 ConnectionFactory, such as ActiveMQ's PooledConnectionFactory).
036 *
037 * <p>This class allows for being subclassed, with subclasses overriding only
038 * those methods (such as {@link #createConnection()}) that should not simply
039 * delegate to the target ConnectionFactory.
040 *
041 * <p>Can also be defined as-is, wrapping a specific target ConnectionFactory,
042 * using the "shouldStopConnections" flag to indicate whether Connections
043 * obtained from the target factory are supposed to be stopped before closed.
044 * The latter may be necessary for some connection pools that simply return
045 * released connections to the pool, not stopping them while they sit in the pool.
046 *
047 * @author Juergen Hoeller
048 * @since 2.0.2
049 * @see #createConnection()
050 * @see #setShouldStopConnections
051 * @see ConnectionFactoryUtils#releaseConnection
052 */
053public class DelegatingConnectionFactory
054                implements SmartConnectionFactory, QueueConnectionFactory, TopicConnectionFactory, InitializingBean {
055
056        private ConnectionFactory targetConnectionFactory;
057
058        private boolean shouldStopConnections = false;
059
060
061        /**
062         * Set the target ConnectionFactory that this ConnectionFactory should delegate to.
063         */
064        public void setTargetConnectionFactory(ConnectionFactory targetConnectionFactory) {
065                Assert.notNull(targetConnectionFactory, "'targetConnectionFactory' must not be null");
066                this.targetConnectionFactory = targetConnectionFactory;
067        }
068
069        /**
070         * Return the target ConnectionFactory that this ConnectionFactory delegates to.
071         */
072        public ConnectionFactory getTargetConnectionFactory() {
073                return this.targetConnectionFactory;
074        }
075
076        /**
077         * Indicate whether Connections obtained from the target factory are supposed
078         * to be stopped before closed ("true") or simply closed ("false").
079         * An extra stop call may be necessary for some connection pools that simply return
080         * released connections to the pool, not stopping them while they sit in the pool.
081         * <p>Default is "false", simply closing Connections.
082         * @see ConnectionFactoryUtils#releaseConnection
083         */
084        public void setShouldStopConnections(boolean shouldStopConnections) {
085                this.shouldStopConnections = shouldStopConnections;
086        }
087
088        @Override
089        public void afterPropertiesSet() {
090                if (getTargetConnectionFactory() == null) {
091                        throw new IllegalArgumentException("'targetConnectionFactory' is required");
092                }
093        }
094
095
096        @Override
097        public Connection createConnection() throws JMSException {
098                return getTargetConnectionFactory().createConnection();
099        }
100
101        @Override
102        public Connection createConnection(String username, String password) throws JMSException {
103                return getTargetConnectionFactory().createConnection(username, password);
104        }
105
106        @Override
107        public QueueConnection createQueueConnection() throws JMSException {
108                ConnectionFactory cf = getTargetConnectionFactory();
109                if (cf instanceof QueueConnectionFactory) {
110                        return ((QueueConnectionFactory) cf).createQueueConnection();
111                }
112                else {
113                        Connection con = cf.createConnection();
114                        if (!(con instanceof QueueConnection)) {
115                                throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a QueueConnectionFactory");
116                        }
117                        return (QueueConnection) con;
118                }
119        }
120
121        @Override
122        public QueueConnection createQueueConnection(String username, String password) throws JMSException {
123                ConnectionFactory cf = getTargetConnectionFactory();
124                if (cf instanceof QueueConnectionFactory) {
125                        return ((QueueConnectionFactory) cf).createQueueConnection(username, password);
126                }
127                else {
128                        Connection con = cf.createConnection(username, password);
129                        if (!(con instanceof QueueConnection)) {
130                                throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a QueueConnectionFactory");
131                        }
132                        return (QueueConnection) con;
133                }
134        }
135
136        @Override
137        public TopicConnection createTopicConnection() throws JMSException {
138                ConnectionFactory cf = getTargetConnectionFactory();
139                if (cf instanceof TopicConnectionFactory) {
140                        return ((TopicConnectionFactory) cf).createTopicConnection();
141                }
142                else {
143                        Connection con = cf.createConnection();
144                        if (!(con instanceof TopicConnection)) {
145                                throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a TopicConnectionFactory");
146                        }
147                        return (TopicConnection) con;
148                }
149        }
150
151        @Override
152        public TopicConnection createTopicConnection(String username, String password) throws JMSException {
153                ConnectionFactory cf = getTargetConnectionFactory();
154                if (cf instanceof TopicConnectionFactory) {
155                        return ((TopicConnectionFactory) cf).createTopicConnection(username, password);
156                }
157                else {
158                        Connection con = cf.createConnection(username, password);
159                        if (!(con instanceof TopicConnection)) {
160                                throw new javax.jms.IllegalStateException("'targetConnectionFactory' is not a TopicConnectionFactory");
161                        }
162                        return (TopicConnection) con;
163                }
164        }
165
166        @Override
167        public boolean shouldStop(Connection con) {
168                return this.shouldStopConnections;
169        }
170
171}