1
2
3
4
5
6
7
8
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
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
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 }