View Javadoc
1   package org.argeo.osgi.useradmin;
2   
3   import java.util.HashMap;
4   import java.util.Map;
5   
6   import javax.transaction.xa.XAException;
7   import javax.transaction.xa.XAResource;
8   import javax.transaction.xa.Xid;
9   
10  /** {@link XAResource} for a user directory being edited. */
11  class WcXaResource implements XAResource {
12  	private final AbstractUserDirectory userDirectory;
13  
14  	private Map<Xid, UserDirectoryWorkingCopy> workingCopies = new HashMap<Xid, UserDirectoryWorkingCopy>();
15  	private Xid editingXid = null;
16  	private int transactionTimeout = 0;
17  
18  	public WcXaResource(AbstractUserDirectory userDirectory) {
19  		this.userDirectory = userDirectory;
20  	}
21  
22  	@Override
23  	public synchronized void start(Xid xid, int flags) throws XAException {
24  		if (editingXid != null)
25  			throw new UserDirectoryException("Already editing " + editingXid);
26  		UserDirectoryWorkingCopy wc = workingCopies.put(xid, new UserDirectoryWorkingCopy());
27  		if (wc != null)
28  			throw new UserDirectoryException("There is already a working copy for " + xid);
29  		this.editingXid = xid;
30  	}
31  
32  	@Override
33  	public void end(Xid xid, int flags) throws XAException {
34  		checkXid(xid);
35  	}
36  
37  	private UserDirectoryWorkingCopy wc(Xid xid) {
38  		return workingCopies.get(xid);
39  	}
40  
41  	synchronized UserDirectoryWorkingCopy wc() {
42  		if (editingXid == null)
43  			return null;
44  		UserDirectoryWorkingCopy wc = workingCopies.get(editingXid);
45  		if (wc == null)
46  			throw new UserDirectoryException("No working copy found for " + editingXid);
47  		return wc;
48  	}
49  
50  	private synchronized void cleanUp(Xid xid) {
51  		wc(xid).cleanUp();
52  		workingCopies.remove(xid);
53  		editingXid = null;
54  	}
55  
56  	@Override
57  	public int prepare(Xid xid) throws XAException {
58  		checkXid(xid);
59  		UserDirectoryWorkingCopy wc = wc(xid);
60  		if (wc.noModifications())
61  			return XA_RDONLY;
62  		try {
63  			userDirectory.prepare(wc);
64  		} catch (Exception e) {
65  			throw new XAException(XAException.XAER_RMERR);
66  		}
67  		return XA_OK;
68  	}
69  
70  	@Override
71  	public void commit(Xid xid, boolean onePhase) throws XAException {
72  		try {
73  			checkXid(xid);
74  			UserDirectoryWorkingCopy wc = wc(xid);
75  			if (wc.noModifications())
76  				return;
77  			if (onePhase)
78  				userDirectory.prepare(wc);
79  			userDirectory.commit(wc);
80  		} catch (Exception e) {
81  			throw new XAException(XAException.XAER_RMERR);
82  		} finally {
83  			cleanUp(xid);
84  		}
85  	}
86  
87  	@Override
88  	public void rollback(Xid xid) throws XAException {
89  		try {
90  			checkXid(xid);
91  			userDirectory.rollback(wc(xid));
92  		} catch (Exception e) {
93  			throw new XAException(XAException.XAER_RMERR);
94  		} finally {
95  			cleanUp(xid);
96  		}
97  	}
98  
99  	@Override
100 	public void forget(Xid xid) throws XAException {
101 		throw new UnsupportedOperationException();
102 	}
103 
104 	@Override
105 	public boolean isSameRM(XAResource xares) throws XAException {
106 		return xares == this;
107 	}
108 
109 	@Override
110 	public Xid[] recover(int flag) throws XAException {
111 		return new Xid[0];
112 	}
113 
114 	@Override
115 	public int getTransactionTimeout() throws XAException {
116 		return transactionTimeout;
117 	}
118 
119 	@Override
120 	public boolean setTransactionTimeout(int seconds) throws XAException {
121 		transactionTimeout = seconds;
122 		return true;
123 	}
124 
125 	private void checkXid(Xid xid) throws XAException {
126 		if (xid == null)
127 			throw new XAException(XAException.XAER_OUTSIDE);
128 		if (!xid.equals(xid))
129 			throw new XAException(XAException.XAER_NOTA);
130 	}
131 
132 }