View Javadoc

1   /*
2    * $Id: SessionInvocationHandler.java 10468 2008-01-22 21:18:22Z aperepel $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.providers.jms.xa;
11  
12  import org.mule.config.i18n.CoreMessages;
13  import org.mule.transaction.IllegalTransactionStateException;
14  import org.mule.transaction.TransactionCoordination;
15  import org.mule.transaction.XaTransaction;
16  import org.mule.umo.UMOTransaction;
17  
18  import java.lang.ref.Reference;
19  import java.lang.ref.WeakReference;
20  import java.lang.reflect.InvocationHandler;
21  import java.lang.reflect.Method;
22  import java.lang.reflect.Proxy;
23  
24  import javax.jms.JMSException;
25  import javax.jms.MessageConsumer;
26  import javax.jms.MessageProducer;
27  import javax.jms.QueueReceiver;
28  import javax.jms.QueueSender;
29  import javax.jms.Session;
30  import javax.jms.TopicPublisher;
31  import javax.jms.TopicSubscriber;
32  import javax.jms.XAQueueSession;
33  import javax.jms.XASession;
34  import javax.jms.XATopicSession;
35  import javax.transaction.xa.XAResource;
36  
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  public class SessionInvocationHandler implements InvocationHandler
41  {
42      protected static final transient Log logger = LogFactory.getLog(SessionInvocationHandler.class);
43  
44      private XASession xaSession;
45      private XAResource xaResource;
46      private volatile boolean enlisted = false;
47      private volatile boolean reuseObject = false;
48      private final Reference underlyingObject;
49      private static final Method SESSION_CLOSE_METHOD;
50  
51      static
52      {
53          try
54          {
55              SESSION_CLOSE_METHOD = Session.class.getMethod("close", null);
56          }
57          catch (NoSuchMethodException e)
58          {
59              throw new RuntimeException(e);
60          }
61      }
62  
63      public SessionInvocationHandler(XASession xaSession) throws JMSException
64      {
65          this.xaSession = xaSession;
66          underlyingObject = new WeakReference(xaSession.getSession());
67          this.xaResource = new XAResourceWrapper(xaSession.getXAResource(), this);
68      }
69  
70      public SessionInvocationHandler(XAQueueSession xaSession) throws JMSException
71      {
72          this.xaSession = xaSession;
73          underlyingObject = new WeakReference(xaSession.getQueueSession());
74          this.xaResource = new XAResourceWrapper(xaSession.getXAResource(), this);
75      }
76  
77      public SessionInvocationHandler(XATopicSession xaSession) throws JMSException
78      {
79          this.xaSession = xaSession;
80          underlyingObject = new WeakReference(xaSession.getTopicSession());
81          this.xaResource = new XAResourceWrapper(xaSession.getXAResource(), this);
82      }
83  
84      /*
85       * (non-Javadoc)
86       *
87       * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
88       *      java.lang.reflect.Method, java.lang.Object[])
89       */
90      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
91      {
92          if (logger.isDebugEnabled())
93          {
94              logger.debug("Invoking " + method);
95          }
96          if (underlyingObject.get() == null)
97          {
98              throw new IllegalStateException("Underlying session is null, XASession " + xaSession);
99          }
100 
101         // processing method from MuleXaObject
102         if (XaTransaction.MuleXaObject.DELIST_METHOD_NAME.equals(method.getName()))
103         {
104             return Boolean.valueOf(delist());
105         }
106         else if (XaTransaction.MuleXaObject.SET_REUSE_OBJECT_METHOD_NAME.equals(method.getName()))
107         {
108             reuseObject = ((Boolean) args[0]).booleanValue();
109             return null;
110         }
111         else if (XaTransaction.MuleXaObject.IS_REUSE_OBJECT_METHOD_NAME.equals(method.getName()))
112         {
113             return Boolean.valueOf(reuseObject);
114         }
115         else if (XaTransaction.MuleXaObject.GET_TARGET_OBJECT_METHOD_NAME.equals(method.getName()))
116         {
117             return getTargetObject();
118         }
119         else if (XaTransaction.MuleXaObject.CLOSE_METHOD_NAME.equals(method.getName()))
120         {
121             return SESSION_CLOSE_METHOD.invoke(underlyingObject.get(), args);
122         }
123         //close will be directly called on session object
124 
125         Object result = method.invoke(underlyingObject.get(), args);
126 
127         if (result instanceof TopicSubscriber)
128         {
129             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
130                                             new Class[]{TopicSubscriber.class}, new ConsumerProducerInvocationHandler(this, result));
131         }
132         else if (result instanceof QueueReceiver)
133         {
134             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
135                                             new Class[]{QueueReceiver.class}, new ConsumerProducerInvocationHandler(this, result));
136         }
137         else if (result instanceof MessageConsumer)
138         {
139             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
140                                             new Class[]{MessageConsumer.class}, new ConsumerProducerInvocationHandler(this, result));
141         }
142         else if (result instanceof TopicPublisher)
143         {
144             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
145                                             new Class[]{TopicPublisher.class}, new ConsumerProducerInvocationHandler(this, result));
146         }
147         else if (result instanceof QueueSender)
148         {
149             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
150                                             new Class[]{QueueSender.class}, new ConsumerProducerInvocationHandler(this, result));
151         }
152         else if (result instanceof MessageProducer)
153         {
154             result = Proxy.newProxyInstance(Session.class.getClassLoader(),
155                                             new Class[]{MessageProducer.class}, new ConsumerProducerInvocationHandler(this, result));
156         }
157         return result;
158     }
159 
160     protected void enlist() throws Exception
161     {
162         if (isEnlisted())
163         {
164             return;
165         }
166 
167         if (logger.isDebugEnabled())
168         {
169             logger.debug("Enlistment request: " + this);
170         }
171 
172         UMOTransaction transaction = TransactionCoordination.getInstance().getTransaction();
173         if (transaction == null)
174         {
175             throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
176         }
177         if (!(transaction instanceof XaTransaction))
178         {
179             throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
180         }
181 
182         if (!isEnlisted())
183         {
184             if (logger.isDebugEnabled())
185             {
186                 logger.debug("Enlisting resource " + xaResource + " in xa transaction " + transaction);
187             }
188 
189             enlisted = ((XaTransaction) transaction).enlistResource(xaResource);
190         }
191     }
192 
193     public boolean delist() throws Exception
194     {
195         if (!isEnlisted())
196         {
197             return false;
198         }
199 
200         if (logger.isDebugEnabled())
201         {
202             logger.debug("Delistment request: " + this);
203         }
204 
205         UMOTransaction transaction = TransactionCoordination.getInstance().getTransaction();
206         if (transaction == null)
207         {
208             throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
209         }
210         if (!(transaction instanceof XaTransaction))
211         {
212             throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
213         }
214 
215         if (isEnlisted())
216         {
217             if (logger.isDebugEnabled())
218             {
219                 logger.debug("Delisting resource " + xaResource + " in xa transaction " + transaction);
220             }
221 
222             enlisted = !((XaTransaction) transaction).delistResource(xaResource, XAResource.TMSUCCESS);
223         }
224         return !isEnlisted();
225     }
226 
227 
228     public boolean isEnlisted()
229     {
230         return enlisted;
231     }
232 
233     public void setEnlisted(boolean enlisted)
234     {
235         this.enlisted = enlisted;
236     }
237 
238     public XASession getTargetObject()
239     {
240         return xaSession;
241     }
242 
243     public XAResource getXAResource()
244     {
245         return xaResource;
246     }
247 
248 
249 }