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