1   /*
2    * $Id: VmXATransactionTestCase.java 10490 2008-01-23 17:54:20Z akuzmin $
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.transport.vm.functional;
11  
12  import org.mule.api.MuleMessage;
13  import org.mule.module.client.MuleClient;
14  import org.mule.tck.FunctionalTestCase;
15  import org.mule.transaction.TransactionCoordination;
16  import org.mule.transaction.XaTransaction;
17  import org.mule.util.ClassUtils;
18  
19  import java.lang.reflect.Field;
20  import java.lang.reflect.Method;
21  import java.util.Iterator;
22  import java.util.Map;
23  
24  import javax.transaction.Transaction;
25  import javax.transaction.xa.XAException;
26  import javax.transaction.xa.XAResource;
27  import javax.transaction.xa.Xid;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  public class VmXATransactionTestCase extends FunctionalTestCase
33  {
34      protected static final Log logger = LogFactory.getLog(VmTransactionTestCase.class);
35      protected static volatile boolean success = true;
36      protected static volatile boolean wouldBeDisabled = false;
37  
38      protected String getConfigResources()
39      {
40          return "vm-xa-transaction.xml";
41      }
42  
43      public void testTransactionQueueEventsTrue() throws Exception
44      {
45  
46          MuleClient client = new MuleClient();
47          client.dispatch("vm://in", "TEST", null);
48          MuleMessage message = client.request("vm://out", 10000);
49          assertNotNull(message);
50          if (wouldBeDisabled)
51          {
52              throw new IllegalStateException("Test is wrong, and must be disabled");
53          }
54          assertTrue(success);
55  
56      }
57  
58      public static class TestComponent
59      {
60  
61          public Object process(Object a) throws Exception
62          {
63              success = checkTransaction(TransactionCoordination.getInstance().getTransaction());
64              return a;
65          }
66  
67          private boolean checkTransaction(org.mule.api.transaction.Transaction transaction) throws Exception
68          {
69              if (!(transaction instanceof XaTransaction))
70              {
71                  return false;
72              }
73              Transaction tx = ((XaTransaction) transaction).getTransaction();
74              //add test resource
75              TestResource testResource = new TestResource();
76              transaction.bindResource("TestReource", testResource);
77              tx.enlistResource(testResource);
78  
79              Field field = transaction.getClass().getDeclaredField("resources");
80              field.setAccessible(true);
81              Map resources = (Map) field.get(transaction);
82              if (resources == null)
83              {
84                  return false;
85              }
86              logger.debug("Mule XATransaction :: registered " + resources.size());
87  
88              Iterator i = resources.entrySet().iterator();
89              boolean result = true;
90              while (i.hasNext())
91              {
92                  Map.Entry entry = (Map.Entry) i.next();
93                  XAResource xaResource = getXAResource(entry.getValue());
94                  logger.debug("XAResource " + xaResource);
95                  boolean enlisted = isXAResourceEnlisted(tx, xaResource);
96                  result = result && enlisted;
97                  if (xaResource instanceof TestResource)
98                  {
99                      logger.debug("Check status for TestResource " + enlisted);
100                     if (!enlisted)
101                     {
102                         wouldBeDisabled = true;
103                         throw new IllegalStateException("Test is wrong, and must be disabled");
104                     }
105                 }
106             }
107 
108             return result;
109         }
110 
111         private boolean isXAResourceEnlisted(Transaction transaction, XAResource xaResource)
112         {
113             if (transaction instanceof
114                     com.arjuna.ats.jta.transaction.Transaction)
115             {
116                 com.arjuna.ats.jta.transaction.Transaction tx = (com.arjuna.ats.jta.transaction.Transaction) transaction;
117 
118                 int state = tx.getXAResourceState(xaResource);
119                 return (state == 0);
120             }
121             return false;
122         }
123 
124         private XAResource getXAResource(Object resource) throws Exception
125         {
126             if (resource instanceof XAResource)
127             {
128                 return (XAResource) resource;
129             }
130             Method method = resource.getClass().getMethod("getXAResource", null);
131             return (XAResource) method.invoke(resource, ClassUtils.NO_ARGS);
132         }
133 
134 
135     }
136 
137     public static class TestResource implements XAResource
138     {
139 
140         public void commit(Xid id, boolean onePhase) throws XAException
141         {
142             logger.debug("XA_COMMIT[" + id + "]");
143         }
144 
145         public void end(Xid xid, int flags) throws XAException
146         {
147             logger.debug("XA_END[" + xid + "] Flags=" + flags);
148         }
149 
150         public void forget(Xid xid) throws XAException
151         {
152             logger.debug("XA_FORGET[" + xid + "]");
153         }
154 
155         public int getTransactionTimeout() throws XAException
156         {
157             return (_timeout);
158         }
159 
160         public boolean isSameRM(XAResource xares) throws XAException
161         {
162             return (xares.equals(this));
163         }
164 
165         public int prepare(Xid xid) throws XAException
166         {
167             logger.debug("XA_PREPARE[" + xid + "]");
168 
169             return (XA_OK);
170         }
171 
172         public Xid[] recover(int flag) throws XAException
173         {
174             logger.debug("RECOVER[" + flag + "]");
175             return (null);
176         }
177 
178         public void rollback(Xid xid) throws XAException
179         {
180             logger.debug("XA_ROLLBACK[" + xid + "]");
181         }
182 
183         public boolean setTransactionTimeout(int seconds) throws XAException
184         {
185             _timeout = seconds;
186             return (true);
187         }
188 
189         public void start(Xid xid, int flags) throws XAException
190         {
191             logger.debug("XA_START[" + xid + "] Flags=" + flags);
192         }
193 
194         protected int _timeout = 0;
195     }
196 
197 
198 }