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 java.io.Serializable;
020    import java.util.Iterator;
021    import java.util.concurrent.CopyOnWriteArrayList;
022    
023    import javax.jms.BytesMessage;
024    import javax.jms.Destination;
025    import javax.jms.JMSException;
026    import javax.jms.MapMessage;
027    import javax.jms.Message;
028    import javax.jms.MessageConsumer;
029    import javax.jms.MessageListener;
030    import javax.jms.MessageProducer;
031    import javax.jms.ObjectMessage;
032    import javax.jms.Queue;
033    import javax.jms.QueueBrowser;
034    import javax.jms.QueueReceiver;
035    import javax.jms.QueueSender;
036    import javax.jms.QueueSession;
037    import javax.jms.StreamMessage;
038    import javax.jms.TemporaryQueue;
039    import javax.jms.TemporaryTopic;
040    import javax.jms.TextMessage;
041    import javax.jms.Topic;
042    import javax.jms.TopicPublisher;
043    import javax.jms.TopicSession;
044    import javax.jms.TopicSubscriber;
045    
046    import org.apache.activemq.ActiveMQMessageProducer;
047    import org.apache.activemq.ActiveMQQueueSender;
048    import org.apache.activemq.ActiveMQSession;
049    import org.apache.activemq.ActiveMQTopicPublisher;
050    import org.apache.activemq.AlreadyClosedException;
051    import org.apache.commons.logging.Log;
052    import org.apache.commons.logging.LogFactory;
053    
054    /**
055     * @version $Revision: 1.1 $
056     */
057    public class PooledSession implements TopicSession, QueueSession {
058        private static final transient Log LOG = LogFactory.getLog(PooledSession.class);
059    
060        private ActiveMQSession session;
061        private SessionPool sessionPool;
062        private ActiveMQMessageProducer messageProducer;
063        private ActiveMQQueueSender queueSender;
064        private ActiveMQTopicPublisher topicPublisher;
065        private boolean transactional = true;
066        private boolean ignoreClose;
067    
068        private final CopyOnWriteArrayList<MessageConsumer> consumers = new CopyOnWriteArrayList<MessageConsumer>();
069        private final CopyOnWriteArrayList<QueueBrowser> browsers = new CopyOnWriteArrayList<QueueBrowser>();
070    
071        public PooledSession(ActiveMQSession aSession, SessionPool sessionPool) {
072            this.session = aSession;
073            this.sessionPool = sessionPool;
074            this.transactional = session.isTransacted();
075        }
076    
077        protected boolean isIgnoreClose() {
078            return ignoreClose;
079        }
080    
081        protected void setIgnoreClose(boolean ignoreClose) {
082            this.ignoreClose = ignoreClose;
083        }
084    
085        public void close() throws JMSException {
086            if (!ignoreClose) {
087                // TODO a cleaner way to reset??
088    
089                // lets reset the session
090                getSession().setMessageListener(null);
091    
092                // Close any consumers and browsers that may have been created.
093                for (Iterator<MessageConsumer> iter = consumers.iterator(); iter.hasNext();) {
094                    MessageConsumer consumer = iter.next();
095                    consumer.close();
096                }
097                consumers.clear();
098    
099                for (Iterator<QueueBrowser> iter = browsers.iterator(); iter.hasNext();) {
100                    QueueBrowser browser = iter.next();
101                    browser.close();
102                }
103                browsers.clear();
104    
105                // maybe do a rollback?
106                if (transactional) {
107                    try {
108                        getSession().rollback();
109                    } catch (JMSException e) {
110                        LOG.warn("Caught exception trying rollback() when putting session back into the pool: " + e, e);
111    
112                        // lets close the session and not put the session back into
113                        // the pool
114                        try {
115                            session.close();
116                        } catch (JMSException e1) {
117                            LOG.trace("Ignoring exception as discarding session: " + e1, e1);
118                        }
119                        session = null;
120                        return;
121                    }
122                }
123    
124                sessionPool.returnSession(this);
125            }
126        }
127    
128        public void commit() throws JMSException {
129            getSession().commit();
130        }
131    
132        public BytesMessage createBytesMessage() throws JMSException {
133            return getSession().createBytesMessage();
134        }
135    
136        public MapMessage createMapMessage() throws JMSException {
137            return getSession().createMapMessage();
138        }
139    
140        public Message createMessage() throws JMSException {
141            return getSession().createMessage();
142        }
143    
144        public ObjectMessage createObjectMessage() throws JMSException {
145            return getSession().createObjectMessage();
146        }
147    
148        public ObjectMessage createObjectMessage(Serializable serializable) throws JMSException {
149            return getSession().createObjectMessage(serializable);
150        }
151    
152        public Queue createQueue(String s) throws JMSException {
153            return getSession().createQueue(s);
154        }
155    
156        public StreamMessage createStreamMessage() throws JMSException {
157            return getSession().createStreamMessage();
158        }
159    
160        public TemporaryQueue createTemporaryQueue() throws JMSException {
161            return getSession().createTemporaryQueue();
162        }
163    
164        public TemporaryTopic createTemporaryTopic() throws JMSException {
165            return getSession().createTemporaryTopic();
166        }
167    
168        public void unsubscribe(String s) throws JMSException {
169            getSession().unsubscribe(s);
170        }
171    
172        public TextMessage createTextMessage() throws JMSException {
173            return getSession().createTextMessage();
174        }
175    
176        public TextMessage createTextMessage(String s) throws JMSException {
177            return getSession().createTextMessage(s);
178        }
179    
180        public Topic createTopic(String s) throws JMSException {
181            return getSession().createTopic(s);
182        }
183    
184        public int getAcknowledgeMode() throws JMSException {
185            return getSession().getAcknowledgeMode();
186        }
187    
188        public boolean getTransacted() throws JMSException {
189            return getSession().getTransacted();
190        }
191    
192        public void recover() throws JMSException {
193            getSession().recover();
194        }
195    
196        public void rollback() throws JMSException {
197            getSession().rollback();
198        }
199    
200        public void run() {
201            if (session != null) {
202                session.run();
203            }
204        }
205    
206        // Consumer related methods
207        // -------------------------------------------------------------------------
208        public QueueBrowser createBrowser(Queue queue) throws JMSException {
209            return addQueueBrowser(getSession().createBrowser(queue));
210        }
211    
212        public QueueBrowser createBrowser(Queue queue, String selector) throws JMSException {
213            return addQueueBrowser(getSession().createBrowser(queue, selector));
214        }
215    
216        public MessageConsumer createConsumer(Destination destination) throws JMSException {
217            return addConsumer(getSession().createConsumer(destination));
218        }
219    
220        public MessageConsumer createConsumer(Destination destination, String selector) throws JMSException {
221            return addConsumer(getSession().createConsumer(destination, selector));
222        }
223    
224        public MessageConsumer createConsumer(Destination destination, String selector, boolean noLocal) throws JMSException {
225            return addConsumer(getSession().createConsumer(destination, selector, noLocal));
226        }
227    
228        public TopicSubscriber createDurableSubscriber(Topic topic, String selector) throws JMSException {
229            return addTopicSubscriber(getSession().createDurableSubscriber(topic, selector));
230        }
231    
232        public TopicSubscriber createDurableSubscriber(Topic topic, String name, String selector, boolean noLocal) throws JMSException {
233            return addTopicSubscriber(getSession().createDurableSubscriber(topic, name, selector, noLocal));
234        }
235    
236        public MessageListener getMessageListener() throws JMSException {
237            return getSession().getMessageListener();
238        }
239    
240        public void setMessageListener(MessageListener messageListener) throws JMSException {
241            getSession().setMessageListener(messageListener);
242        }
243    
244        public TopicSubscriber createSubscriber(Topic topic) throws JMSException {
245            return addTopicSubscriber(getSession().createSubscriber(topic));
246        }
247    
248        public TopicSubscriber createSubscriber(Topic topic, String selector, boolean local) throws JMSException {
249            return addTopicSubscriber(getSession().createSubscriber(topic, selector, local));
250        }
251    
252        public QueueReceiver createReceiver(Queue queue) throws JMSException {
253            return addQueueReceiver(getSession().createReceiver(queue));
254        }
255    
256        public QueueReceiver createReceiver(Queue queue, String selector) throws JMSException {
257            return addQueueReceiver(getSession().createReceiver(queue, selector));
258        }
259    
260        // Producer related methods
261        // -------------------------------------------------------------------------
262        public MessageProducer createProducer(Destination destination) throws JMSException {
263            return new PooledProducer(getMessageProducer(), destination);
264        }
265    
266        public QueueSender createSender(Queue queue) throws JMSException {
267            return new PooledQueueSender(getQueueSender(), queue);
268        }
269    
270        public TopicPublisher createPublisher(Topic topic) throws JMSException {
271            return new PooledTopicPublisher(getTopicPublisher(), topic);
272        }
273    
274        // Implementation methods
275        // -------------------------------------------------------------------------
276        protected ActiveMQSession getSession() throws AlreadyClosedException {
277            if (session == null) {
278                throw new AlreadyClosedException("The session has already been closed");
279            }
280            return session;
281        }
282    
283        public ActiveMQMessageProducer getMessageProducer() throws JMSException {
284            if (messageProducer == null) {
285                messageProducer = (ActiveMQMessageProducer)getSession().createProducer(null);
286            }
287            return messageProducer;
288        }
289    
290        public ActiveMQQueueSender getQueueSender() throws JMSException {
291            if (queueSender == null) {
292                queueSender = (ActiveMQQueueSender)getSession().createSender(null);
293            }
294            return queueSender;
295        }
296    
297        public ActiveMQTopicPublisher getTopicPublisher() throws JMSException {
298            if (topicPublisher == null) {
299                topicPublisher = (ActiveMQTopicPublisher)getSession().createPublisher(null);
300            }
301            return topicPublisher;
302        }
303    
304        private QueueBrowser addQueueBrowser(QueueBrowser browser) {
305            browsers.add(browser);
306            return browser;
307        }
308    
309        private MessageConsumer addConsumer(MessageConsumer consumer) {
310            consumers.add(consumer);
311            return consumer;
312        }
313    
314        private TopicSubscriber addTopicSubscriber(TopicSubscriber subscriber) {
315            consumers.add(subscriber);
316            return subscriber;
317        }
318    
319        private QueueReceiver addQueueReceiver(QueueReceiver receiver) {
320            consumers.add(receiver);
321            return receiver;
322        }
323    
324        public String toString() {
325            return "PooledSession { " + session + " }";
326        }
327    }