X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Ftransaction%2Fsimple%2FSimpleTransactionManager.java;fp=org.argeo.security.core%2Fsrc%2Forg%2Fargeo%2Fosgi%2Ftransaction%2Fsimple%2FSimpleTransactionManager.java;h=696f0c0993a05f593533173b80cfba6109f59d14;hb=50077824250f3a7f5c092d0a5ce28a171287ac7c;hp=0000000000000000000000000000000000000000;hpb=3400a80f88b418c598bf30f27b13ce1360902376;p=lgpl%2Fargeo-commons.git 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 index 000000000..696f0c099 --- /dev/null +++ b/org.argeo.security.core/src/org/argeo/osgi/transaction/simple/SimpleTransactionManager.java @@ -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 current = new ThreadLocal(); + + private Map knownTransactions = Collections + .synchronizedMap(new HashMap()); + 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); + } + } + + } +}