1 28 29 package org.apache.commons.transaction.util.xa; 30 31 import java.util.HashMap ; 32 import java.util.Map ; 33 34 import javax.transaction.Status ; 35 import javax.transaction.xa.XAException ; 36 import javax.transaction.xa.XAResource ; 37 import javax.transaction.xa.Xid ; 38 39 import org.apache.commons.transaction.util.LoggerFacade; 40 41 44 public abstract class AbstractXAResource implements XAResource , Status { 45 46 private ThreadLocal activeTransactionBranch = new ThreadLocal (); 48 49 private Map suspendedContexts = new HashMap (); 50 private Map activeContexts = new HashMap (); 51 52 public abstract boolean isSameRM(XAResource xares) throws XAException ; 53 54 public abstract Xid [] recover(int flag) throws XAException ; 55 56 protected abstract LoggerFacade getLoggerFacade(); 57 58 protected abstract boolean includeBranchInXid(); 59 60 public void forget(Xid xid) throws XAException { 61 if (getLoggerFacade().isFineEnabled()) { 62 getLoggerFacade().logFine("Forgetting transaction branch " + xid); 63 } 64 TransactionalResource ts = getTransactionalResource(xid); 65 if (ts == null) { 66 throw new XAException (XAException.XAER_NOTA); 67 } 68 setCurrentlyActiveTransactionalResource(null); 69 removeActiveTransactionalResource(xid); 70 removeSuspendedTransactionalResource(xid); 71 } 72 73 public void commit(Xid xid, boolean onePhase) throws XAException { 74 TransactionalResource ts = getTransactionalResource(xid); 75 if (ts == null) { 76 throw new XAException (XAException.XAER_NOTA); 77 } 78 79 if (getLoggerFacade().isFineEnabled()) { 80 getLoggerFacade().logFine("Committing transaction branch " + ts); 81 } 82 83 if (ts.getStatus() == STATUS_MARKED_ROLLBACK) { 84 throw new XAException (XAException.XA_RBROLLBACK); 85 } 86 87 if (ts.getStatus() != STATUS_PREPARED) { 88 if (onePhase) { 89 ts.prepare(); 90 } else { 91 throw new XAException (XAException.XAER_PROTO); 92 } 93 } 94 ts.commit(); 95 setCurrentlyActiveTransactionalResource(null); 96 removeActiveTransactionalResource(xid); 97 removeSuspendedTransactionalResource(xid); 98 } 99 100 public void rollback(Xid xid) throws XAException { 101 TransactionalResource ts = getTransactionalResource(xid); 102 if (ts == null) { 103 throw new XAException (XAException.XAER_NOTA); 104 } 105 106 if (getLoggerFacade().isFineEnabled()) { 107 getLoggerFacade().logFine("Rolling back transaction branch " + ts); 108 } 109 110 ts.rollback(); 111 setCurrentlyActiveTransactionalResource(null); 112 removeActiveTransactionalResource(xid); 113 removeSuspendedTransactionalResource(xid); 114 } 115 116 public int prepare(Xid xid) throws XAException { 117 TransactionalResource ts = getTransactionalResource(xid); 118 if (ts == null) { 119 throw new XAException (XAException.XAER_NOTA); 120 } 121 122 if (getLoggerFacade().isFineEnabled()) { 123 getLoggerFacade().logFine("Preparing transaction branch " + ts); 124 } 125 126 if (ts.getStatus() == STATUS_MARKED_ROLLBACK) { 127 throw new XAException (XAException.XA_RBROLLBACK); 128 } 129 130 int result = ts.prepare(); 131 ts.setStatus(STATUS_PREPARED); 132 return result; 133 } 134 135 public void end(Xid xid, int flags) throws XAException { 136 TransactionalResource ts = getActiveTransactionalResource(xid); 137 if (ts == null) { 138 throw new XAException (XAException.XAER_NOTA); 139 } 140 if (getCurrentlyActiveTransactionalResource() == null) { 141 throw new XAException (XAException.XAER_INVAL); 142 } 143 if (getLoggerFacade().isFineEnabled()) { 144 getLoggerFacade().logFine(new StringBuffer (128) 145 .append("Thread ").append(Thread.currentThread()) 146 .append(flags == TMSUSPEND ? " suspends" : flags == TMFAIL ? " fails" : " ends") 147 .append(" work on behalf of transaction branch ") 148 .append(ts).toString()); 149 } 150 151 switch (flags) { 152 case TMSUSPEND : 153 ts.suspend(); 154 addSuspendedTransactionalResource(xid, ts); 155 removeActiveTransactionalResource(xid); 156 break; 157 case TMFAIL : 158 ts.setStatus(STATUS_MARKED_ROLLBACK); 159 break; 160 case TMSUCCESS : 161 break; 162 } 163 setCurrentlyActiveTransactionalResource(null); 164 } 165 166 public void start(Xid xid, int flags) throws XAException { 167 if (getCurrentlyActiveTransactionalResource() != null) { 168 throw new XAException (XAException.XAER_INVAL); 169 } 170 if (getLoggerFacade().isFineEnabled()) { 171 getLoggerFacade().logFine(new StringBuffer (128) 172 .append("Thread ").append(Thread.currentThread()) 173 .append(flags == TMNOFLAGS ? " starts" : flags == TMJOIN ? " joins" : " resumes") 174 .append(" work on behalf of transaction branch ") 175 .append(xid).toString()); 176 } 177 178 TransactionalResource ts; 179 switch (flags) { 180 case TMNOFLAGS : 182 case TMJOIN : 183 default : 184 try { 185 ts = createTransactionResource(xid); 186 ts.begin(); 187 } catch (Exception e) { 188 getLoggerFacade().logSevere("Could not create new transactional resource", e); 189 throw new XAException (e.getMessage()); 190 } 191 break; 192 case TMRESUME : 193 ts = getSuspendedTransactionalResource(xid); 194 if (ts == null) { 195 throw new XAException (XAException.XAER_NOTA); 196 } 197 ts.resume(); 198 removeSuspendedTransactionalResource(xid); 199 break; 200 } 201 setCurrentlyActiveTransactionalResource(ts); 202 addAcitveTransactionalResource(xid, ts); 203 } 204 205 abstract protected TransactionalResource createTransactionResource(Xid xid) throws Exception ; 206 207 protected TransactionalResource getCurrentlyActiveTransactionalResource() { 208 TransactionalResource context = (TransactionalResource) activeTransactionBranch.get(); 209 return context; 210 } 211 212 protected void setCurrentlyActiveTransactionalResource(TransactionalResource context) { 213 activeTransactionBranch.set(context); 214 } 215 216 protected TransactionalResource getTransactionalResource(Xid xid) { 217 TransactionalResource ts = getActiveTransactionalResource(xid); 218 if (ts != null) return ts; 219 else return getSuspendedTransactionalResource(xid); 220 } 221 protected TransactionalResource getActiveTransactionalResource(Xid xid) { 222 Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); 223 return (TransactionalResource) activeContexts.get(wxid); 224 } 225 226 protected TransactionalResource getSuspendedTransactionalResource(Xid xid) { 227 Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); 228 return (TransactionalResource) suspendedContexts.get(wxid); 229 } 230 231 protected void addAcitveTransactionalResource(Xid xid, TransactionalResource txContext) { 232 Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); 233 activeContexts.put(wxid, txContext); 234 } 235 236 protected void addSuspendedTransactionalResource(Xid xid, TransactionalResource txContext) { 237 Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); 238 suspendedContexts.put(wxid, txContext); 239 } 240 241 protected void removeActiveTransactionalResource(Xid xid) { 242 Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); 243 activeContexts.remove(wxid); 244 } 245 246 protected void removeSuspendedTransactionalResource(Xid xid) { 247 Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); 248 suspendedContexts.remove(wxid); 249 } 250 251 } 252 | Popular Tags |