Massive package refactoring
[lgpl/argeo-commons.git] / org.argeo.api.cms / src / org / argeo / api / cms / transaction / SimpleTransactionManager.java
diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/transaction/SimpleTransactionManager.java b/org.argeo.api.cms/src/org/argeo/api/cms/transaction/SimpleTransactionManager.java
new file mode 100644 (file)
index 0000000..ee99ccb
--- /dev/null
@@ -0,0 +1,214 @@
+package org.argeo.api.cms.transaction;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+/**
+ * Simple implementation of an XA transaction manager.
+ */
+public class SimpleTransactionManager
+// implements TransactionManager, UserTransaction 
+               implements WorkControl, WorkTransaction {
+       private ThreadLocal<SimpleTransaction<Integer>> current = new ThreadLocal<SimpleTransaction<Integer>>();
+
+       private Map<Xid, SimpleTransaction<Integer>> knownTransactions = Collections
+                       .synchronizedMap(new HashMap<Xid, SimpleTransaction<Integer>>());
+       private TransactionStatusAdapter<Integer> tsa = new JtaStatusAdapter();
+//     private SyncRegistry syncRegistry = new SyncRegistry();
+
+       /*
+        * WORK IMPLEMENTATION
+        */
+       @Override
+       public <T> T required(Callable<T> work) {
+               T res;
+               begin();
+               try {
+                       res = work.call();
+                       commit();
+               } catch (Exception e) {
+                       rollback();
+                       throw new SimpleRollbackException(e);
+               }
+               return res;
+       }
+
+       @Override
+       public WorkContext getWorkContext() {
+               return new WorkContext() {
+
+                       @Override
+                       public void registerXAResource(XAResource resource, String recoveryId) {
+                               getTransaction().enlistResource(resource);
+                       }
+               };
+       }
+
+       /*
+        * WORK TRANSACTION IMPLEMENTATION
+        */
+
+       @Override
+       public boolean isNoTransactionStatus() {
+               return tsa.getNoTransactionStatus().equals(getStatus());
+       }
+
+       /*
+        * JTA IMPLEMENTATION
+        */
+
+       public void begin()
+//                     throws NotSupportedException, SystemException 
+       {
+               if (getCurrent() != null)
+                       throw new UnsupportedOperationException("Nested transactions are not supported");
+               SimpleTransaction<Integer> transaction = new SimpleTransaction<Integer>(this, tsa);
+               knownTransactions.put(transaction.getXid(), transaction);
+               current.set(transaction);
+       }
+
+       public void commit()
+//                     throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+//                     SecurityException, IllegalStateException, SystemException 
+       {
+               if (getCurrent() == null)
+                       throw new IllegalStateException("No transaction registered with the current thread.");
+               getCurrent().commit();
+       }
+
+       public int getStatus()
+//                     throws SystemException
+       {
+               if (getCurrent() == null)
+                       return tsa.getNoTransactionStatus();
+               return getTransaction().getStatus();
+       }
+
+       public SimpleTransaction<Integer> getTransaction()
+//                     throws SystemException 
+       {
+               return getCurrent();
+       }
+
+       protected SimpleTransaction<Integer> getCurrent()
+//                     throws SystemException 
+       {
+               SimpleTransaction<Integer> transaction = current.get();
+               if (transaction == null)
+                       return null;
+               Integer status = transaction.getStatus();
+               if (status.equals(tsa.getCommittedStatus()) || status.equals(tsa.getRolledBackStatus())) {
+                       current.remove();
+                       return null;
+               }
+               return transaction;
+       }
+
+       void unregister(Xid xid) {
+               knownTransactions.remove(xid);
+       }
+
+       public void resume(SimpleTransaction<Integer> tobj)
+//                     throws InvalidTransactionException, IllegalStateException, SystemException 
+       {
+               if (getCurrent() != null)
+                       throw new IllegalStateException("Transaction " + current.get() + " already registered");
+               current.set(tobj);
+       }
+
+       public void rollback()
+//                     throws IllegalStateException, SecurityException, SystemException 
+       {
+               if (getCurrent() == null)
+                       throw new IllegalStateException("No transaction registered with the current thread.");
+               getCurrent().rollback();
+       }
+
+       public void setRollbackOnly()
+//                     throws IllegalStateException, SystemException 
+       {
+               if (getCurrent() == null)
+                       throw new IllegalStateException("No transaction registered with the current thread.");
+               getCurrent().setRollbackOnly();
+       }
+
+       public void setTransactionTimeout(int seconds)
+//                     throws SystemException
+       {
+               throw new UnsupportedOperationException();
+       }
+
+       public SimpleTransaction<Integer> suspend()
+//                     throws SystemException
+       {
+               SimpleTransaction<Integer> transaction = getCurrent();
+               current.remove();
+               return transaction;
+       }
+
+//     public TransactionSynchronizationRegistry getTsr() {
+//             return syncRegistry;
+//     }
+//
+//     private class SyncRegistry implements TransactionSynchronizationRegistry {
+//             @Override
+//             public Object getTransactionKey() {
+//                     try {
+//                             SimpleTransaction transaction = getCurrent();
+//                             if (transaction == null)
+//                                     return null;
+//                             return getCurrent().getXid();
+//                     } catch (SystemException e) {
+//                             throw new IllegalStateException("Cannot get transaction key", e);
+//                     }
+//             }
+//
+//             @Override
+//             public void putResource(Object key, Object value) {
+//                     throw new UnsupportedOperationException();
+//             }
+//
+//             @Override
+//             public Object getResource(Object key) {
+//                     throw new UnsupportedOperationException();
+//             }
+//
+//             @Override
+//             public void registerInterposedSynchronization(Synchronization sync) {
+//                     throw new UnsupportedOperationException();
+//             }
+//
+//             @Override
+//             public int getTransactionStatus() {
+//                     try {
+//                             return getStatus();
+//                     } catch (SystemException e) {
+//                             throw new IllegalStateException("Cannot get status", e);
+//                     }
+//             }
+//
+//             @Override
+//             public boolean getRollbackOnly() {
+//                     try {
+//                             return getStatus() == Status.STATUS_MARKED_ROLLBACK;
+//                     } catch (SystemException e) {
+//                             throw new IllegalStateException("Cannot get status", e);
+//                     }
+//             }
+//
+//             @Override
+//             public void setRollbackOnly() {
+//                     try {
+//                             getCurrent().setRollbackOnly();
+//                     } catch (Exception e) {
+//                             throw new IllegalStateException("Cannot set rollback only", e);
+//                     }
+//             }
+//
+//     }
+}