001    /** 
002     * Licensed under the Apache License, Version 2.0 (the "License"); 
003     * you may not use this file except in compliance with the License. 
004     * You may obtain a copy of the License at 
005     * 
006     * http://www.apache.org/licenses/LICENSE-2.0
007     * 
008     * Unless required by applicable law or agreed to in writing, software
009     * distributed under the License is distributed on an "AS IS" BASIS, 
010     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
011     * See the License for the specific language governing permissions and 
012     * limitations under the License. 
013     * 
014     **/
015    package org.jencks.pool;
016    
017    import java.io.Serializable;
018    
019    import javax.jms.XASession;
020    import javax.jms.TopicSession;
021    import javax.jms.QueueSession;
022    import javax.jms.JMSException;
023    import javax.jms.BytesMessage;
024    import javax.jms.MapMessage;
025    import javax.jms.Message;
026    import javax.jms.ObjectMessage;
027    import javax.jms.Queue;
028    import javax.jms.StreamMessage;
029    import javax.jms.TemporaryQueue;
030    import javax.jms.TemporaryTopic;
031    import javax.jms.TextMessage;
032    import javax.jms.Topic;
033    import javax.jms.QueueBrowser;
034    import javax.jms.MessageConsumer;
035    import javax.jms.Destination;
036    import javax.jms.TopicSubscriber;
037    import javax.jms.MessageListener;
038    import javax.jms.QueueReceiver;
039    import javax.jms.MessageProducer;
040    import javax.jms.QueueSender;
041    import javax.jms.TopicPublisher;
042    import javax.jms.Session;
043    import javax.transaction.xa.XAResource;
044    
045    import org.apache.commons.pool.ObjectPool;
046    import org.apache.commons.logging.Log;
047    import org.apache.commons.logging.LogFactory;
048    
049    public class PooledSpringXASession implements TopicSession, QueueSession, XASession
050    {
051      private static final Log log = LogFactory.getLog(PooledSpringXASession.class);
052      
053      private XASession session;
054      private ObjectPool sessionPool;
055      private MessageProducer messageProducer;
056      private QueueSender queueSender;
057      private TopicPublisher topicPublisher;
058      private boolean ignoreClose;
059    
060      public PooledSpringXASession(final XASession session, final ObjectPool sessionPool)
061      {
062        this.session = session;
063        this.sessionPool = sessionPool;
064        this.ignoreClose = false;
065      }
066    
067      public boolean getIgnoreClose()
068      {
069        return this.ignoreClose;
070      }
071    
072      public void setIgnoreClose(final boolean ignoreClose)
073      {
074        this.ignoreClose = ignoreClose;
075      }
076    
077      /**
078       * If the Session goes into an unstable (unusable) state, then we want to
079       * close it down and permanently remove it from the pool.
080       */
081      public void destroyAndRemoveFromPool()
082      {
083        try {
084          sessionPool.invalidateObject(this);
085        } catch (Throwable t) {
086          log.warn("Unable to remove invalidated JMS Session from the pool due to the following exception.  Will ignore the exception and continue.", t);
087        }
088      }
089    
090    
091      public void close() throws JMSException
092      {
093        if(log.isDebugEnabled()) log.debug("---->>>>> PooledSpringXASession.close() called");
094        // If we are associated with a transaction, then we will let
095        // PooledSpringXAConnection's transaction synchronization handle closing
096        // us at the end of the transaction.
097        if(!getIgnoreClose()) {
098          if(log.isDebugEnabled()) log.debug("---->>>>> ignoreClose = false, so returning session pool...");
099          // TODO a cleaner way to reset??
100    
101          // lets reset the session
102          getActualSession().setMessageListener(null);
103    
104          try {
105            sessionPool.returnObject(this);
106          }
107          catch (Exception e) {
108            final JMSException jmsException = new JMSException("Failed to return session to pool: " + e);
109            jmsException.initCause(e);
110            throw jmsException;
111          }
112        } else if(log.isDebugEnabled()) {
113          log.debug("---->>>>> ignoreClose IS TRUE!  KEEPING SESSION OPEN!");
114        }
115      }
116    
117      public void commit() throws JMSException
118      {
119        throw new JMSException("Cannot commit() inside XASession");
120      }
121    
122      public BytesMessage createBytesMessage() throws JMSException
123      {
124        return getActualSession().createBytesMessage();
125      }
126    
127      public MapMessage createMapMessage() throws JMSException
128      {
129        return getActualSession().createMapMessage();
130      }
131    
132      public Message createMessage() throws JMSException
133      {
134        return getActualSession().createMessage();
135      }
136    
137      public ObjectMessage createObjectMessage() throws JMSException
138      {
139        return getActualSession().createObjectMessage();
140      }
141    
142      public ObjectMessage createObjectMessage(Serializable serializable)
143          throws JMSException
144      {
145        return getActualSession().createObjectMessage(serializable);
146      }
147    
148      public Queue createQueue(String s) throws JMSException
149      {
150        return getActualSession().createQueue(s);
151      }
152    
153      public StreamMessage createStreamMessage() throws JMSException
154      {
155        return getActualSession().createStreamMessage();
156      }
157    
158      public TemporaryQueue createTemporaryQueue() throws JMSException
159      {
160        return getActualSession().createTemporaryQueue();
161      }
162    
163      public TemporaryTopic createTemporaryTopic() throws JMSException
164      {
165        return getActualSession().createTemporaryTopic();
166      }
167    
168      public void unsubscribe(String s) throws JMSException
169      {
170        getActualSession().unsubscribe(s);
171      }
172    
173      public TextMessage createTextMessage() throws JMSException
174      {
175        return getActualSession().createTextMessage();
176      }
177    
178      public TextMessage createTextMessage(String s) throws JMSException
179      {
180        return getActualSession().createTextMessage(s);
181      }
182    
183      public Topic createTopic(String s) throws JMSException
184      {
185        return getActualSession().createTopic(s);
186      }
187    
188      public int getAcknowledgeMode() throws JMSException
189      {
190        return getActualSession().getAcknowledgeMode();
191      }
192    
193      public boolean getTransacted() throws JMSException
194      {
195        return true;
196      }
197    
198      public void recover() throws JMSException
199      {
200        getActualSession().recover();
201      }
202    
203      public void rollback() throws JMSException
204      {
205        throw new JMSException("Cannot rollback() inside XASession");
206      }
207    
208      public void run()
209      {
210        if (session != null) {
211          session.run();
212        }
213      }
214    
215      public XAResource getXAResource()
216      {
217        try {
218          return getActualSession().getXAResource();
219        } catch(Exception e) {
220          throw new RuntimeException(e);
221        }
222      }
223    
224      public Session getSession() throws JMSException
225      {
226        return this;
227      }
228    
229    
230      // Consumer related methods
231      //-------------------------------------------------------------------------
232      public QueueBrowser createBrowser(Queue queue) throws JMSException
233      {
234        return getActualSession().createBrowser(queue);
235      }
236    
237      public QueueBrowser createBrowser(Queue queue, String selector)
238          throws JMSException
239      {
240        return getActualSession().createBrowser(queue, selector);
241      }
242    
243      public MessageConsumer createConsumer(Destination destination)
244          throws JMSException
245      {
246        return getActualSession().createConsumer(destination);
247      }
248    
249      public MessageConsumer createConsumer(Destination destination,
250                                            String selector) throws JMSException
251      {
252        return getActualSession().createConsumer(destination, selector);
253      }
254    
255      public MessageConsumer createConsumer(Destination destination,
256                                            String selector, boolean noLocal)
257          throws JMSException
258      {
259        return getActualSession().createConsumer(destination, selector, noLocal);
260      }
261    
262      public TopicSubscriber createDurableSubscriber(Topic topic, String selector)
263          throws JMSException
264      {
265        return getActualSession().createDurableSubscriber(topic, selector);
266      }
267    
268      public TopicSubscriber createDurableSubscriber(Topic topic, String name,
269                                                     String selector,
270                                                     boolean noLocal)
271          throws JMSException
272      {
273        return getActualSession().createDurableSubscriber(topic, name, selector, noLocal);
274      }
275    
276      public MessageListener getMessageListener() throws JMSException
277      {
278        return getActualSession().getMessageListener();
279      }
280    
281      public void setMessageListener(MessageListener messageListener)
282          throws JMSException
283      {
284        getActualSession().setMessageListener(messageListener);
285      }
286    
287      public TopicSubscriber createSubscriber(Topic topic) throws JMSException
288      {
289        return ((TopicSession)getActualSession()).createSubscriber(topic);
290      }
291    
292      public TopicSubscriber createSubscriber(Topic topic, String selector,
293                                              boolean local) throws JMSException
294      {
295        return ((TopicSession)getActualSession()).createSubscriber(topic, selector, local);
296      }
297    
298      public QueueReceiver createReceiver(Queue queue) throws JMSException
299      {
300        return ((QueueSession)getActualSession()).createReceiver(queue);
301      }
302    
303      public QueueReceiver createReceiver(Queue queue, String selector)
304          throws JMSException
305      {
306        return ((QueueSession)getActualSession()).createReceiver(queue, selector);
307      }
308    
309    
310      // Producer related methods
311      //-------------------------------------------------------------------------
312      public MessageProducer createProducer(Destination destination)
313          throws JMSException
314      {
315        return new PooledProducer(getMessageProducer(), destination);
316      }
317    
318      public QueueSender createSender(Queue queue) throws JMSException
319      {
320        return new PooledQueueSender(getQueueSender(), queue);
321      }
322    
323      public TopicPublisher createPublisher(Topic topic) throws JMSException
324      {
325        return new PooledTopicPublisher(getTopicPublisher(), topic);
326      }
327    
328      // Implementation methods
329      //-------------------------------------------------------------------------
330      public XASession getActualSession() throws JMSException
331      {
332        if (this.session == null) {
333          throw new JMSException("The session has already been closed");
334        }
335        return this.session;
336      }
337    
338      public MessageProducer getMessageProducer() throws JMSException
339      {
340        if (this.messageProducer == null) {
341          this.messageProducer = getActualSession().createProducer(null);
342        }
343        return this.messageProducer;
344      }
345    
346      public QueueSender getQueueSender() throws JMSException
347      {
348        if (this.queueSender == null) {
349          this.queueSender = ((QueueSession)getActualSession()).createSender(null);
350        }
351        return this.queueSender;
352      }
353    
354      public TopicPublisher getTopicPublisher() throws JMSException
355      {
356        if (this.topicPublisher == null) {
357          this.topicPublisher = ((TopicSession)getActualSession()).createPublisher(null);
358        }
359        return this.topicPublisher;
360      }
361    
362    }