View Javadoc

1   /*
2    * $Id: SessionInvocationHandler.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  package org.mule.transport.jms.xa;
11  
12  import org.mule.api.transaction.Transaction;
13  import org.mule.config.i18n.CoreMessages;
14  import org.mule.transaction.IllegalTransactionStateException;
15  import org.mule.transaction.TransactionCoordination;
16  import org.mule.transaction.XaTransaction;
17  
18  import java.lang.reflect.Method;
19  import java.lang.reflect.Proxy;
20  
21  import javax.jms.JMSException;
22  import javax.jms.MessageConsumer;
23  import javax.jms.MessageProducer;
24  import javax.jms.QueueReceiver;
25  import javax.jms.QueueSender;
26  import javax.jms.Session;
27  import javax.jms.TopicPublisher;
28  import javax.jms.TopicSubscriber;
29  import javax.jms.XAQueueSession;
30  import javax.jms.XASession;
31  import javax.jms.XATopicSession;
32  import javax.transaction.xa.XAResource;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  public class SessionInvocationHandler implements TargetInvocationHandler
38  {
39      protected static final transient Log logger = LogFactory.getLog(SessionInvocationHandler.class);
40  
41      private XASession xaSession;
42      private XAResource xaResource;
43      private volatile boolean enlisted = false;
44      private volatile boolean reuseObject = false;
45      private final Session session;
46  
47      private SessionInvocationHandler(XASession xaSession, Session session, Boolean sameRMOverrideValue)
48      {
49          super();
50          this.xaSession = xaSession;
51          this.session = session;
52          this.xaResource = new XAResourceWrapper(xaSession.getXAResource(), this, sameRMOverrideValue);
53      }
54      
55      public SessionInvocationHandler(XASession xaSession, Boolean sameRMOverrideValue) throws JMSException
56      {
57          this(xaSession, xaSession.getSession(), sameRMOverrideValue);
58      }
59  
60      public SessionInvocationHandler(XAQueueSession xaSession, Boolean sameRMOverrideValue) throws JMSException
61      {
62          this(xaSession, xaSession.getQueueSession(), sameRMOverrideValue);
63      }
64  
65      public SessionInvocationHandler(XATopicSession xaSession, Boolean sameRMOverrideValue) throws JMSException
66      {
67          this(xaSession, xaSession.getTopicSession(), sameRMOverrideValue);
68      }
69  
70      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
71      {
72          if (logger.isDebugEnabled())
73          {
74              logger.debug(this + " Invoking " + method);
75          }
76  
77          // processing method from MuleXaObject
78          if (XaTransaction.MuleXaObject.DELIST_METHOD_NAME.equals(method.getName()))
79          {
80              return delist();
81          }
82          else if (XaTransaction.MuleXaObject.ENLIST_METHOD_NAME.equals(method.getName()))
83          {
84              return enlist();
85          }
86          else if (XaTransaction.MuleXaObject.SET_REUSE_OBJECT_METHOD_NAME.equals(method.getName()))
87          {
88              reuseObject = (Boolean) args[0];
89              return null;
90          }
91          else if (XaTransaction.MuleXaObject.IS_REUSE_OBJECT_METHOD_NAME.equals(method.getName()))
92          {
93              return reuseObject;
94          }
95          else if (XaTransaction.MuleXaObject.GET_TARGET_OBJECT_METHOD_NAME.equals(method.getName()))
96          {
97              return getTargetObject();
98          }
99          else if (XaTransaction.MuleXaObject.CLOSE_METHOD_NAME.equals(method.getName()))
100         {
101             // some jms implementation need both sessions closed, some not
102             try
103             {
104                 session.close();
105                 xaSession.close();
106             }
107             catch (Exception ex)
108             {
109                 if (logger.isDebugEnabled())
110                 {
111                     logger.debug("Closing the session and the xaSession failed", ex);
112                 }
113             }
114             return null;
115         }
116         
117         Object result = method.invoke(session, args);
118 
119         if (result instanceof TopicSubscriber)
120         {
121             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
122                                             new Class[]{TopicSubscriber.class}, new ConsumerProducerInvocationHandler(this, result));
123         }
124         else if (result instanceof QueueReceiver)
125         {
126             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
127                                             new Class[]{QueueReceiver.class}, new ConsumerProducerInvocationHandler(this, result));
128         }
129         else if (result instanceof MessageConsumer)
130         {
131             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
132                                             new Class[]{MessageConsumer.class}, new ConsumerProducerInvocationHandler(this, result));
133         }
134         else if (result instanceof TopicPublisher)
135         {
136             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
137                                             new Class[]{TopicPublisher.class}, new ConsumerProducerInvocationHandler(this, result));
138         }
139         else if (result instanceof QueueSender)
140         {
141             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
142                                             new Class[]{QueueSender.class}, new ConsumerProducerInvocationHandler(this, result));
143         }
144         else if (result instanceof MessageProducer)
145         {
146             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
147                                             new Class[]{MessageProducer.class}, new ConsumerProducerInvocationHandler(this, result));
148         }
149         return result;
150     }
151 
152     public boolean enlist() throws Exception
153     {
154         if (isEnlisted())
155         {
156             return false;
157         }
158 
159         if (logger.isDebugEnabled())
160         {
161             logger.debug("Enlistment request: " + this);
162         }
163 
164         Transaction transaction = TransactionCoordination.getInstance().getTransaction();
165         if (transaction == null)
166         {
167             throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
168         }
169         if (!(transaction instanceof XaTransaction))
170         {
171             throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
172         }
173 
174         if (!isEnlisted())
175         {
176             if (logger.isDebugEnabled())
177             {
178                 logger.debug("Enlisting resource " + xaResource + " in xa transaction " + transaction);
179             }
180 
181             enlisted = ((XaTransaction) transaction).enlistResource(xaResource);
182         }
183         
184         return enlisted;
185     }
186 
187     public boolean delist() throws Exception
188     {
189         if (!isEnlisted())
190         {
191             return false;
192         }
193 
194         if (logger.isDebugEnabled())
195         {
196             logger.debug("Delistment request: " + this);
197         }
198 
199         Transaction transaction = TransactionCoordination.getInstance().getTransaction();
200         if (transaction == null)
201         {
202             throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
203         }
204         if (!(transaction instanceof XaTransaction))
205         {
206             throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
207         }
208 
209         if (isEnlisted())
210         {
211             if (logger.isDebugEnabled())
212             {
213                 logger.debug("Delisting resource " + xaResource + " in xa transaction " + transaction);
214             }
215 
216             enlisted = !((XaTransaction) transaction).delistResource(xaResource, XAResource.TMSUCCESS);
217         }
218         return !isEnlisted();
219     }
220 
221     public boolean isEnlisted()
222     {
223         return enlisted;
224     }
225 
226     public void setEnlisted(boolean enlisted)
227     {
228         this.enlisted = enlisted;
229     }
230 
231     public Object getTargetObject()
232     {
233         return xaSession;
234     }
235 
236     public XAResource getXAResource()
237     {
238         return xaResource;
239     }
240 
241 }