001: package com.mysql.jdbc.jdbc2.optional;
002:
003: import java.sql.SQLException;
004: import java.util.HashMap;
005: import java.util.Map;
006:
007: import javax.sql.XAConnection;
008: import javax.transaction.xa.XAException;
009: import javax.transaction.xa.XAResource;
010: import javax.transaction.xa.Xid;
011:
012: import com.mysql.jdbc.Connection;
013: import com.mysql.jdbc.ConnectionImpl;
014:
015: public class SuspendableXAConnection extends MysqlPooledConnection
016: implements XAConnection, XAResource {
017:
018: public SuspendableXAConnection(ConnectionImpl connection) {
019: super (connection);
020: this .underlyingConnection = connection;
021: }
022:
023: private static final Map XIDS_TO_PHYSICAL_CONNECTIONS = new HashMap();
024:
025: private Xid currentXid;
026:
027: private XAConnection currentXAConnection;
028: private XAResource currentXAResource;
029:
030: private ConnectionImpl underlyingConnection;
031:
032: private static synchronized XAConnection findConnectionForXid(
033: ConnectionImpl connectionToWrap, Xid xid)
034: throws SQLException {
035: // TODO: check for same GTRID, but different BQUALs...MySQL doesn't allow this yet
036:
037: // Note, we don't need to check for XIDs here, because MySQL itself will complain
038: // with a XAER_NOTA if need be.
039:
040: XAConnection conn = (XAConnection) XIDS_TO_PHYSICAL_CONNECTIONS
041: .get(xid);
042:
043: if (conn == null) {
044: conn = new MysqlXAConnection(connectionToWrap,
045: connectionToWrap.getLogXaCommands());
046: }
047:
048: return conn;
049: }
050:
051: private static synchronized void removeXAConnectionMapping(Xid xid) {
052: XIDS_TO_PHYSICAL_CONNECTIONS.remove(xid);
053: }
054:
055: private synchronized void switchToXid(Xid xid) throws XAException {
056: if (xid == null) {
057: throw new XAException();
058: }
059:
060: try {
061: if (!xid.equals(this .currentXid)) {
062: XAConnection toSwitchTo = findConnectionForXid(
063: this .underlyingConnection, xid);
064: this .currentXAConnection = toSwitchTo;
065: this .currentXid = xid;
066: this .currentXAResource = toSwitchTo.getXAResource();
067: }
068: } catch (SQLException sqlEx) {
069: throw new XAException();
070: }
071: }
072:
073: public XAResource getXAResource() throws SQLException {
074: return this ;
075: }
076:
077: public void commit(Xid xid, boolean arg1) throws XAException {
078: switchToXid(xid);
079: this .currentXAResource.commit(xid, arg1);
080: removeXAConnectionMapping(xid);
081: }
082:
083: public void end(Xid xid, int arg1) throws XAException {
084: switchToXid(xid);
085: this .currentXAResource.end(xid, arg1);
086: }
087:
088: public void forget(Xid xid) throws XAException {
089: switchToXid(xid);
090: this .currentXAResource.forget(xid);
091: // remove?
092: removeXAConnectionMapping(xid);
093: }
094:
095: public int getTransactionTimeout() throws XAException {
096: // TODO Auto-generated method stub
097: return 0;
098: }
099:
100: public boolean isSameRM(XAResource xaRes) throws XAException {
101: return xaRes == this ;
102: }
103:
104: public int prepare(Xid xid) throws XAException {
105: switchToXid(xid);
106: return this .currentXAResource.prepare(xid);
107: }
108:
109: public Xid[] recover(int flag) throws XAException {
110: return MysqlXAConnection.recover(this .underlyingConnection,
111: flag);
112: }
113:
114: public void rollback(Xid xid) throws XAException {
115: switchToXid(xid);
116: this .currentXAResource.rollback(xid);
117: removeXAConnectionMapping(xid);
118: }
119:
120: public boolean setTransactionTimeout(int arg0) throws XAException {
121: // TODO Auto-generated method stub
122: return false;
123: }
124:
125: public void start(Xid xid, int arg1) throws XAException {
126: switchToXid(xid);
127:
128: if (arg1 != XAResource.TMJOIN) {
129: this .currentXAResource.start(xid, arg1);
130:
131: return;
132: }
133:
134: //
135: // Emulate join, by using resume on the same physical connection
136: //
137:
138: this .currentXAResource.start(xid, XAResource.TMRESUME);
139: }
140:
141: public synchronized java.sql.Connection getConnection()
142: throws SQLException {
143: if (this .currentXAConnection == null) {
144: return getConnection(false, true);
145: }
146:
147: return this .currentXAConnection.getConnection();
148: }
149:
150: public void close() throws SQLException {
151: if (this.currentXAConnection == null) {
152: super.close();
153: } else {
154: removeXAConnectionMapping(this.currentXid);
155: this.currentXAConnection.close();
156: }
157: }
158: }
|