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