1 21 22 package com.rift.coad.util.transaction; 24 25 import java.util.Iterator ; 27 import java.util.Map ; 28 import java.util.LinkedHashMap ; 29 import java.util.Vector ; 30 import java.util.HashMap ; 31 import java.util.concurrent.ConcurrentHashMap ; 32 import javax.naming.Context ; 33 import javax.naming.InitialContext ; 34 import javax.transaction.xa.XAException ; 35 import javax.transaction.xa.XAResource ; 36 import javax.transaction.xa.Xid ; 37 38 import org.apache.log4j.Logger; 40 41 import com.rift.coad.lib.configuration.Configuration; 43 import com.rift.coad.lib.configuration.ConfigurationFactory; 44 import com.rift.coad.util.lock.LockRef; 45 import com.rift.coad.util.lock.ObjectLockFactory; 46 47 53 public class TransactionManager implements XAResource { 54 55 59 public class Transaction { 60 61 private Xid xid = null; 63 private Map transactionEntries = new LinkedHashMap (); 64 private Vector transactionQueue = new Vector (); 65 66 71 public Transaction(Xid xid) { 72 this.xid = xid; 73 } 74 75 76 84 public void addResource(XAResource xaResource, boolean writeLock) throws 85 TransactionException { 86 try { 87 LockRef lockRef = (LockRef)transactionEntries.get(xaResource); 88 int flags = XAResource.TMRESUME; 89 if (lockRef == null) { 90 if (writeLock) { 91 lockRef = ObjectLockFactory.getInstance().acquireWriteLock( 92 xaResource,xid,ObjectLockFactory.WAIT_ON_NAMED); 93 } else { 94 lockRef = ObjectLockFactory.getInstance().acquireReadLock( 95 xaResource,xid); 96 } 97 transactionEntries.put(xaResource,lockRef); 98 transactionQueue.add(xaResource); 99 flags = XAResource.TMJOIN; 100 } else if (writeLock && (lockRef.getLockType() == LockRef.READ)) { 101 throw new TransactionException("Lock Conflict: There is a " + 102 "read lock in place on this object."); 103 } else if (!writeLock && (lockRef.getLockType() == LockRef.WRITE)) { 104 throw new TransactionException("Lock Conflict: There is a " + 105 "write lock in place on this object."); 106 } 107 xaResource.start(xid,flags); 108 } catch (TransactionException ex) { 109 throw ex; 110 } catch (Exception ex) { 111 log.error("Failed to add a new resource : " + ex.getMessage(), 112 ex); 113 throw new TransactionException( 114 "Failed to add a new resource : " + ex.getMessage(),ex); 115 } 116 } 117 118 119 126 public void commit(boolean onePhase) throws TransactionException { 127 try { 128 for (int index = 0; index < transactionQueue.size(); index++) { 129 Object ref = transactionQueue.get(index); 130 if (ref instanceof XAResource ) { 131 ((XAResource )ref).commit(xid,onePhase); 132 } 133 } 134 for (int index = 0; index < transactionQueue.size(); index++) { 135 LockRef lockRef = (LockRef)transactionEntries.get( 136 transactionQueue.get(index)); 137 lockRef.release(); 138 } 139 140 } catch (Exception ex) { 141 log.error("Failed to commit the resource transaction : " + 142 ex.getMessage(),ex); 143 throw new TransactionException( 144 "Failed to commit the resource transaction : " + 145 ex.getMessage(),ex); 146 } 147 } 148 149 150 155 public void forget() throws TransactionException { 156 try { 157 for (int index = 0; index < transactionQueue.size(); index++) { 158 Object ref = transactionQueue.get(index); 159 if (ref instanceof XAResource ) { 160 ((XAResource )ref).forget(xid); 161 } 162 } 163 for (int index = 0; index < transactionQueue.size(); index++) { 164 LockRef lockRef = (LockRef)transactionEntries.get( 165 transactionQueue.get(index)); 166 lockRef.release(); 167 } 168 169 } catch (Exception ex) { 170 log.error("Failed to forget the resource transaction: " 171 + ex.getMessage(),ex); 172 throw new TransactionException( 173 "Failed to forget the resource transaction : " + 174 ex.getMessage(),ex); 175 } 176 } 177 178 179 185 public void rollback() throws TransactionException { 186 try { 187 for (int index = 0; index < transactionQueue.size(); index++) { 188 int pos = transactionQueue.size() - (index + 1); 189 Object ref = transactionQueue.get(pos); 190 if (ref instanceof XAResource ) { 191 ((XAResource )ref).rollback(xid); 192 } 193 } 194 for (int index = 0; index < transactionQueue.size(); index++) { 195 int pos = transactionQueue.size() - (index + 1); 196 LockRef lockRef = (LockRef)transactionEntries.get( 197 transactionQueue.get(pos)); 198 lockRef.release(); 199 } 200 201 } catch (Exception ex) { 202 log.error("Failed to forget the resource transaction: " 203 + ex.getMessage(),ex); 204 throw new TransactionException( 205 "Failed to forget the resource transaction : " + 206 ex.getMessage(),ex); 207 } 208 } 209 } 210 211 private final static String TIMEOUT = "transaction_timeout"; 213 private final static long DEFAULT_TIMEOUT = 180000; 214 215 protected static Logger log = 217 Logger.getLogger(TransactionManager.class.getName()); 218 219 private static Map singletonMap = new HashMap (); 221 222 private Context context = null; 224 private int timeout = 0; 225 private javax.transaction.TransactionManager jtaTransManager = null; 226 private ThreadLocal threadXID = new ThreadLocal (); 227 private Map transactions = new ConcurrentHashMap (); 228 229 230 233 private TransactionManager() throws TransactionException { 234 try { 235 context = new InitialContext (); 236 jtaTransManager = (javax.transaction.TransactionManager )context. 237 lookup("java:comp/TransactionManager"); 238 Configuration config = ConfigurationFactory.getInstance().getConfig( 239 this.getClass()); 240 timeout = (int)config.getLong(TIMEOUT,DEFAULT_TIMEOUT); 241 } catch (Exception ex) { 242 log.error("Failed to log init the transaction manager because : " + 243 ex.getMessage(),ex); 244 throw new TransactionException( 245 "Failed to log init the transaction manager because : " + 246 ex.getMessage(),ex); 247 } 248 } 249 250 251 257 public synchronized static void init() throws TransactionException { 258 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 259 if (!singletonMap.containsKey(loader)) { 260 singletonMap.put(loader,new TransactionManager()); 261 } 262 } 263 264 265 270 public synchronized static TransactionManager getInstance() throws 271 TransactionException { 272 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 273 TransactionManager singleton = null; 274 if (singletonMap.containsKey(loader)) { 275 singleton = (TransactionManager)singletonMap.get(loader); 276 } else { 277 throw new TransactionException("There is no transaction manager " + 278 "for this class loader"); 279 } 280 return singleton; 281 } 282 283 284 290 public synchronized static void fin() throws TransactionException { 291 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 292 if (singletonMap.containsKey(loader)) { 293 singletonMap.remove(loader); 294 } 295 } 296 297 298 306 public void bindResource(XAResource xaResource, boolean writeLock) throws 307 TransactionException { 308 try { 309 jtaTransManager.getTransaction().enlistResource(this); 310 Xid currentTransactionId = (Xid )threadXID.get(); 311 Transaction transaction = (Transaction)transactions.get( 312 currentTransactionId); 313 if (transaction == null) { 314 transaction = new Transaction(currentTransactionId); 315 transactions.put(currentTransactionId,transaction); 316 } 317 transaction.addResource(xaResource,writeLock); 318 } catch (Exception ex) { 319 log.error("Failed to bind the resource to the transaction " + 320 "manager : " + ex.getMessage(),ex); 321 throw new TransactionException( 322 "Failed to bind the resource to the transaction " + 323 "manager : " + ex.getMessage(),ex); 324 } 325 } 326 327 328 336 public void commit(Xid xid, boolean onePhase) throws XAException { 337 try { 338 Transaction transaction = (Transaction)transactions.get(xid); 339 if (transaction != null) { 340 transaction.commit(onePhase); 341 transactions.remove(xid); 342 } 343 } catch (Exception ex) { 344 log.error("Failed to commit the transaction :" + ex.getMessage(),ex); 345 throw new XAException ("Failed to commit the transaction :" + 346 ex.getMessage()); 347 } 348 } 349 350 351 358 public void end(Xid xid, int flags) throws XAException { 359 } 360 361 362 368 public void forget(Xid xid) throws XAException { 369 try { 370 Transaction transaction = (Transaction)transactions.get(xid); 371 if (transaction != null) { 372 transaction.forget(); 373 transactions.remove(xid); 374 } 375 } catch (Exception ex) { 376 log.error("Failed to forget the transaction :" + ex.getMessage(),ex); 377 throw new XAException ("Failed to forget the transaction :" + 378 ex.getMessage()); 379 } 380 } 381 382 383 389 public int getTransactionTimeout() throws XAException { 390 return timeout; 391 } 392 393 394 402 public boolean isSameRM(XAResource xAResource) throws XAException { 403 return this == xAResource; 404 } 405 406 407 414 public int prepare(Xid xid) throws XAException { 415 return XAResource.XA_OK; 416 } 417 418 419 427 public Xid [] recover(int flags) throws XAException { 428 return null; 429 } 430 431 432 438 public void rollback(Xid xid) throws XAException { 439 try { 440 Transaction transaction = (Transaction)transactions.get(xid); 441 if (transaction != null) { 442 transaction.rollback(); 443 transactions.remove(xid); 444 } 445 } catch (Exception ex) { 446 log.error("Failed to rollback the transaction :" + 447 ex.getMessage(),ex); 448 throw new XAException ("Failed to rollback the transaction :" + 449 ex.getMessage()); 450 } 451 } 452 453 454 461 public boolean setTransactionTimeout(int transactionTimeout) throws 462 XAException { 463 this.timeout = transactionTimeout; 464 return true; 465 } 466 467 468 475 public void start(Xid xid, int flags) throws XAException { 476 threadXID.set(xid); 477 } 478 479 480 } 481 | Popular Tags |