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.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", (Class[])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 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
85 {
86 if (logger.isDebugEnabled())
87 {
88 logger.debug("Invoking " + method);
89 }
90 if (underlyingObject.get() == null)
91 {
92 throw new IllegalStateException("Underlying session is null, XASession " + xaSession);
93 }
94
95
96 if (XaTransaction.MuleXaObject.DELIST_METHOD_NAME.equals(method.getName()))
97 {
98 return Boolean.valueOf(delist());
99 }
100 else if (XaTransaction.MuleXaObject.ENLIST_METHOD_NAME.equals(method.getName()))
101 {
102 return Boolean.valueOf(enlist());
103 }
104 else if (XaTransaction.MuleXaObject.SET_REUSE_OBJECT_METHOD_NAME.equals(method.getName()))
105 {
106 reuseObject = ((Boolean) args[0]).booleanValue();
107 return null;
108 }
109 else if (XaTransaction.MuleXaObject.IS_REUSE_OBJECT_METHOD_NAME.equals(method.getName()))
110 {
111 return Boolean.valueOf(reuseObject);
112 }
113 else if (XaTransaction.MuleXaObject.GET_TARGET_OBJECT_METHOD_NAME.equals(method.getName()))
114 {
115 return getTargetObject();
116 }
117 else if (XaTransaction.MuleXaObject.CLOSE_METHOD_NAME.equals(method.getName()))
118 {
119 return SESSION_CLOSE_METHOD.invoke(underlyingObject.get(), args);
120 }
121
122
123 Object result = method.invoke(underlyingObject.get(), args);
124
125 if (result instanceof TopicSubscriber)
126 {
127 result = Proxy.newProxyInstance(Session.class.getClassLoader(),
128 new Class[]{TopicSubscriber.class}, new ConsumerProducerInvocationHandler(this, result));
129 }
130 else if (result instanceof QueueReceiver)
131 {
132 result = Proxy.newProxyInstance(Session.class.getClassLoader(),
133 new Class[]{QueueReceiver.class}, new ConsumerProducerInvocationHandler(this, result));
134 }
135 else if (result instanceof MessageConsumer)
136 {
137 result = Proxy.newProxyInstance(Session.class.getClassLoader(),
138 new Class[]{MessageConsumer.class}, new ConsumerProducerInvocationHandler(this, result));
139 }
140 else if (result instanceof TopicPublisher)
141 {
142 result = Proxy.newProxyInstance(Session.class.getClassLoader(),
143 new Class[]{TopicPublisher.class}, new ConsumerProducerInvocationHandler(this, result));
144 }
145 else if (result instanceof QueueSender)
146 {
147 result = Proxy.newProxyInstance(Session.class.getClassLoader(),
148 new Class[]{QueueSender.class}, new ConsumerProducerInvocationHandler(this, result));
149 }
150 else if (result instanceof MessageProducer)
151 {
152 result = Proxy.newProxyInstance(Session.class.getClassLoader(),
153 new Class[]{MessageProducer.class}, new ConsumerProducerInvocationHandler(this, result));
154 }
155 return result;
156 }
157
158 public boolean enlist() throws Exception
159 {
160 if (isEnlisted())
161 {
162 return false;
163 }
164
165 if (logger.isDebugEnabled())
166 {
167 logger.debug("Enlistment request: " + this);
168 }
169
170 Transaction transaction = TransactionCoordination.getInstance().getTransaction();
171 if (transaction == null)
172 {
173 throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
174 }
175 if (!(transaction instanceof XaTransaction))
176 {
177 throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
178 }
179
180 if (!isEnlisted())
181 {
182 if (logger.isDebugEnabled())
183 {
184 logger.debug("Enlisting resource " + xaResource + " in xa transaction " + transaction);
185 }
186
187 enlisted = ((XaTransaction) transaction).enlistResource(xaResource);
188 }
189
190 return enlisted;
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 Transaction 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 public boolean isEnlisted()
228 {
229 return enlisted;
230 }
231
232 public void setEnlisted(boolean enlisted)
233 {
234 this.enlisted = enlisted;
235 }
236
237 public XASession getTargetObject()
238 {
239 return xaSession;
240 }
241
242 public XAResource getXAResource()
243 {
244 return xaResource;
245 }
246
247 }