X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.api.cms%2Fsrc%2Forg%2Fargeo%2Fapi%2Fcms%2Ftransaction%2FWorkingCopyXaResource.java;fp=org.argeo.api.cms%2Fsrc%2Forg%2Fargeo%2Fapi%2Fcms%2Ftransaction%2FWorkingCopyXaResource.java;h=16b08c28755f7975cdd1ce9f1ca6cbe0ee09f3d2;hb=54df376a9c2dd458a82eaa09bfbb718fe699dd0d;hp=0000000000000000000000000000000000000000;hpb=3c1cdc594d954520b14646102b366290bdad58c7;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.api.cms/src/org/argeo/api/cms/transaction/WorkingCopyXaResource.java b/org.argeo.api.cms/src/org/argeo/api/cms/transaction/WorkingCopyXaResource.java new file mode 100644 index 000000000..16b08c287 --- /dev/null +++ b/org.argeo.api.cms/src/org/argeo/api/cms/transaction/WorkingCopyXaResource.java @@ -0,0 +1,138 @@ +package org.argeo.api.cms.transaction; + +import java.util.HashMap; +import java.util.Map; + +import javax.transaction.xa.XAException; +import javax.transaction.xa.XAResource; +import javax.transaction.xa.Xid; + +/** {@link XAResource} for a user directory being edited. */ +public class WorkingCopyXaResource> implements XAResource { + private final WorkingCopyProcessor processor; + + private Map workingCopies = new HashMap(); + private Xid editingXid = null; + private int transactionTimeout = 0; + + public WorkingCopyXaResource(WorkingCopyProcessor processor) { + this.processor = processor; + } + + @Override + public synchronized void start(Xid xid, int flags) throws XAException { + if (editingXid != null) + throw new IllegalStateException("Already editing " + editingXid); + WC wc = workingCopies.put(xid, processor.newWorkingCopy()); + if (wc != null) + throw new IllegalStateException("There is already a working copy for " + xid); + this.editingXid = xid; + } + + @Override + public void end(Xid xid, int flags) throws XAException { + checkXid(xid); + } + + private WC wc(Xid xid) { + return workingCopies.get(xid); + } + + public synchronized WC wc() { + if (editingXid == null) + return null; + WC wc = workingCopies.get(editingXid); + if (wc == null) + throw new IllegalStateException("No working copy found for " + editingXid); + return wc; + } + + private synchronized void cleanUp(Xid xid) { + WC wc = workingCopies.get(xid); + if (wc != null) { + wc.cleanUp(); + workingCopies.remove(xid); + } + editingXid = null; + } + + @Override + public int prepare(Xid xid) throws XAException { + checkXid(xid); + WC wc = wc(xid); + if (wc.noModifications()) + return XA_RDONLY; + try { + processor.prepare(wc); + } catch (Exception e) { + e.printStackTrace(); + throw new XAException(XAException.XAER_RMERR); + } + return XA_OK; + } + + @Override + public void commit(Xid xid, boolean onePhase) throws XAException { + try { + checkXid(xid); + WC wc = wc(xid); + if (wc.noModifications()) + return; + if (onePhase) + processor.prepare(wc); + processor.commit(wc); + } catch (Exception e) { + e.printStackTrace(); + throw new XAException(XAException.XAER_RMERR); + } finally { + cleanUp(xid); + } + } + + @Override + public void rollback(Xid xid) throws XAException { + try { + checkXid(xid); + processor.rollback(wc(xid)); + } catch (Exception e) { + e.printStackTrace(); + throw new XAException(XAException.XAER_RMERR); + } finally { + cleanUp(xid); + } + } + + @Override + public void forget(Xid xid) throws XAException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSameRM(XAResource xares) throws XAException { + return xares == this; + } + + @Override + public Xid[] recover(int flag) throws XAException { + return new Xid[0]; + } + + @Override + public int getTransactionTimeout() throws XAException { + return transactionTimeout; + } + + @Override + public boolean setTransactionTimeout(int seconds) throws XAException { + transactionTimeout = seconds; + return true; + } + + private void checkXid(Xid xid) throws XAException { + if (xid == null) + throw new XAException(XAException.XAER_OUTSIDE); + if (!xid.equals(xid)) + throw new XAException(XAException.XAER_NOTA); + } + +}