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