]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.security.core/src/org/argeo/osgi/transaction/simple/SimpleTransactionManager.java
Continue framework clean up.
[lgpl/argeo-commons.git] / org.argeo.security.core / src / org / argeo / osgi / transaction / simple / SimpleTransactionManager.java
diff --git a/org.argeo.security.core/src/org/argeo/osgi/transaction/simple/SimpleTransactionManager.java b/org.argeo.security.core/src/org/argeo/osgi/transaction/simple/SimpleTransactionManager.java
new file mode 100644 (file)
index 0000000..696f0c0
--- /dev/null
@@ -0,0 +1,173 @@
+package org.argeo.osgi.transaction.simple;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.UserTransaction;
+import javax.transaction.xa.Xid;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class SimpleTransactionManager implements TransactionManager, UserTransaction {
+       private final static Log log = LogFactory.getLog(SimpleTransactionManager.class);
+
+       private ThreadLocal<SimpleTransaction> current = new ThreadLocal<SimpleTransaction>();
+
+       private Map<Xid, SimpleTransaction> knownTransactions = Collections
+                       .synchronizedMap(new HashMap<Xid, SimpleTransaction>());
+       private SyncRegistry syncRegistry = new SyncRegistry();
+
+       @Override
+       public void begin() throws NotSupportedException, SystemException {
+               if (getCurrent() != null)
+                       throw new NotSupportedException("Nested transactions are not supported");
+               SimpleTransaction transaction = new SimpleTransaction(this);
+               knownTransactions.put(transaction.getXid(), transaction);
+               current.set(transaction);
+               if (log.isDebugEnabled())
+                       log.debug("STARTED    " + transaction.getXid());
+       }
+
+       @Override
+       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();
+       }
+
+       @Override
+       public int getStatus() throws SystemException {
+               if (getCurrent() == null)
+                       return Status.STATUS_NO_TRANSACTION;
+               return getTransaction().getStatus();
+       }
+
+       @Override
+       public Transaction getTransaction() throws SystemException {
+               return getCurrent();
+       }
+
+       protected SimpleTransaction getCurrent() throws SystemException {
+               SimpleTransaction transaction = current.get();
+               if (transaction == null)
+                       return null;
+               int status = transaction.getStatus();
+               if (Status.STATUS_COMMITTED == status || Status.STATUS_ROLLEDBACK == status) {
+                       current.remove();
+                       return null;
+               }
+               return transaction;
+       }
+
+       void unregister(Xid xid) {
+               knownTransactions.remove(xid);
+       }
+
+       @Override
+       public void resume(Transaction tobj) throws InvalidTransactionException, IllegalStateException, SystemException {
+               if (getCurrent() != null)
+                       throw new IllegalStateException("Transaction " + current.get() + " already registered");
+               current.set((SimpleTransaction) tobj);
+       }
+
+       @Override
+       public void rollback() throws IllegalStateException, SecurityException, SystemException {
+               if (getCurrent() == null)
+                       throw new IllegalStateException("No transaction registered with the current thread.");
+               getCurrent().rollback();
+       }
+
+       @Override
+       public void setRollbackOnly() throws IllegalStateException, SystemException {
+               if (getCurrent() == null)
+                       throw new IllegalStateException("No transaction registered with the current thread.");
+               getCurrent().setRollbackOnly();
+       }
+
+       @Override
+       public void setTransactionTimeout(int seconds) throws SystemException {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       public Transaction suspend() throws SystemException {
+               Transaction 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 RuntimeException("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 RuntimeException("Cannot get status", e);
+                       }
+               }
+
+               @Override
+               public boolean getRollbackOnly() {
+                       try {
+                               return getStatus() == Status.STATUS_MARKED_ROLLBACK;
+                       } catch (SystemException e) {
+                               throw new RuntimeException("Cannot get status", e);
+                       }
+               }
+
+               @Override
+               public void setRollbackOnly() {
+                       try {
+                               getCurrent().setRollbackOnly();
+                       } catch (Exception e) {
+                               throw new RuntimeException("Cannot set rollback only", e);
+                       }
+               }
+
+       }
+}