1 28 29 package com.caucho.ejb.xa; 30 31 import com.caucho.amber.manager.AmberConnection; 32 import com.caucho.config.ConfigException; 33 import com.caucho.ejb.EJBExceptionWrapper; 34 import com.caucho.ejb.EnvServerManager; 35 import com.caucho.log.Log; 36 import com.caucho.util.FreeList; 37 import com.caucho.util.L10N; 38 39 import javax.ejb.EJBException ; 40 import javax.naming.InitialContext ; 41 import javax.naming.NamingException ; 42 import javax.transaction.Transaction ; 43 import javax.transaction.TransactionManager ; 44 import javax.transaction.UserTransaction ; 45 import java.util.Hashtable ; 46 import java.util.logging.Level ; 47 import java.util.logging.Logger ; 48 49 54 public class EjbTransactionManager { 55 private static final L10N L = new L10N(EjbTransactionManager.class); 56 private static final Logger log = Log.open(EjbTransactionManager.class); 57 58 public static final int RESIN_DATABASE = 0; 59 public static final int RESIN_READ_ONLY = 1; 60 public static final int RESIN_ROW_LOCKING = 2; 61 62 protected static final ThreadLocal <TransactionContext> _threadTransaction 63 = new ThreadLocal <TransactionContext>(); 64 65 private FreeList<TransactionContext> _freeTransactions 66 = new FreeList<TransactionContext>(64); 67 68 private Hashtable <Transaction ,TransactionContext> _transactionMap 69 = new Hashtable <Transaction ,TransactionContext>(); 70 71 private Hashtable <String ,TransactionContext> _foreignTransactionMap 72 = new Hashtable <String ,TransactionContext>(); 73 74 private final EnvServerManager _ejbManager; 75 76 protected final TransactionManager _transactionManager; 77 protected UserTransaction _userTransaction; 78 79 private int _resinIsolation = -1; 80 private int _jdbcIsolation = -1; 81 82 private long _transactionTimeout = 0; 83 84 private boolean _isClosed; 85 86 89 public EjbTransactionManager(EnvServerManager ejbManager) 90 throws ConfigException 91 { 92 _ejbManager = ejbManager; 93 94 UserTransaction ut = null; 95 TransactionManager tm = null; 96 97 try { 98 InitialContext ic = new InitialContext (); 99 100 ut = (UserTransaction ) ic.lookup("java:comp/UserTransaction"); 101 102 tm = (TransactionManager ) ic.lookup("java:comp/TransactionManager"); 103 } catch (NamingException e) { 104 log.log(Level.WARNING, e.toString(), e); 105 } 106 107 _userTransaction = ut; 108 _transactionManager = tm; 109 110 if (_transactionManager == null) 111 throw new ConfigException(L.l("Can't load TransactionManager.")); 112 } 113 114 117 public EnvServerManager getEJBManager() 118 { 119 return _ejbManager; 120 } 121 122 123 126 public void setResinIsolation(int resinIsolation) 127 { 128 _resinIsolation = resinIsolation; 129 } 130 131 134 public int getResinIsolation() 135 { 136 return _resinIsolation; 137 } 138 139 142 public void setJDBCIsolation(int jdbcIsolation) 143 { 144 _jdbcIsolation = jdbcIsolation; 145 } 146 147 150 public int getJDBCIsolation() 151 { 152 return _jdbcIsolation; 153 } 154 155 158 public long getTransactionTimeout() 159 { 160 return _transactionTimeout; 161 } 162 163 166 public void setTransactionTimeout(long transactionTimeout) 167 { 168 _transactionTimeout = transactionTimeout; 169 } 170 171 void setUserTransaction(UserTransaction userTransaction) 172 { 173 _userTransaction = userTransaction; 174 } 175 176 public UserTransaction getUserTransaction() 177 { 178 return _userTransaction; 179 } 180 181 184 public AmberConnection getAmberConnection() 185 { 186 TransactionContext xaContext = _threadTransaction.get(); 187 188 if (xaContext != null) 189 return xaContext.getAmberConnection(); 190 else 191 throw new IllegalStateException ("can't get transaction outside of context"); 192 } 193 194 public void commitTransaction() 195 throws EJBException 196 { 197 try { 198 if (_transactionManager.getTransaction() != null) 199 _userTransaction.commit(); 200 } catch (Exception e) { 201 throw EJBExceptionWrapper.create(e); 202 } 203 } 204 205 public void rollbackTransaction() 206 throws EJBException 207 { 208 try { 209 _userTransaction.rollback(); 210 } catch (Exception e) { 211 throw EJBExceptionWrapper.create(e); 212 } 213 } 214 215 TransactionManager getTransactionManager() 216 throws EJBException 217 { 218 return _transactionManager; 219 } 220 221 public Transaction getTransaction() 222 throws EJBException 223 { 224 try { 225 return _transactionManager.getTransaction(); 226 } catch (Exception e) { 227 throw EJBExceptionWrapper.create(e); 228 } 229 } 230 231 public TransactionContext getTransactionContext() 232 { 233 return _threadTransaction.get(); 234 } 235 236 243 public TransactionContext beginRequired() 244 throws EJBException 245 { 246 try { 247 Transaction oldTrans = _transactionManager.getTransaction(); 248 TransactionContext oldCxt = _threadTransaction.get(); 249 250 if (oldCxt != null && oldTrans != null && 253 oldCxt.getTransaction() == oldTrans) { 254 oldCxt.pushDepth(); 255 return oldCxt; 256 } 257 258 261 if (oldTrans != null) { 262 TransactionContext cxt = _transactionMap.get(oldTrans); 263 264 if (cxt != null) { 265 _transactionMap.remove(oldTrans); 266 267 _threadTransaction.set(cxt); 268 cxt.pushDepth(); 269 270 return cxt; 271 } 272 } 273 274 TransactionContext cxt = createTransaction(); 276 cxt.setOld(oldCxt); 277 278 _threadTransaction.set(cxt); 279 if (oldTrans != null) { 281 setTransaction(cxt, oldTrans); 282 cxt.setUserTransaction(true); 284 cxt.pushDepth(); 285 } 286 else { 287 _userTransaction.setTransactionTimeout((int) (_transactionTimeout / 1000L)); 288 _userTransaction.begin(); 289 Transaction trans = _transactionManager.getTransaction(); 290 291 setTransaction(cxt, trans); 292 } 293 294 if (_resinIsolation == RESIN_ROW_LOCKING) 295 cxt.setRowLocking(true); 296 297 return cxt; 298 } catch (Exception e) { 299 log.log(Level.WARNING, e.toString(), e); 300 301 throw EJBExceptionWrapper.create(e); 302 } 303 } 304 305 312 public TransactionContext beginSingleRead() 313 throws EJBException 314 { 315 try { 316 TransactionContext cxt = _threadTransaction.get(); 317 Transaction trans = _transactionManager.getTransaction(); 318 319 if (trans == null) 320 return null; 321 322 if (cxt != null && cxt.getTransaction() == trans) { 324 cxt.pushDepth(); 325 return cxt; 326 } 327 328 TransactionContext newCxt = _transactionMap.get(trans); 330 331 if (newCxt != null) { 332 newCxt.pushDepth(); 333 return newCxt; 334 } 335 336 newCxt = createTransaction(); 338 newCxt.pushDepth(); 339 340 _threadTransaction.set(newCxt); 341 setTransaction(newCxt, trans); 342 newCxt.setUserTransaction(true); 344 345 return newCxt; 346 } catch (Exception e) { 347 log.log(Level.WARNING, e.toString(), e); 348 349 throw EJBExceptionWrapper.create(e); 350 } 351 } 352 353 358 public TransactionContext beginRequiresNew() 359 throws EJBException 360 { 361 try { 362 TransactionContext oldCxt = _threadTransaction.get(); 363 Transaction oldTrans = _transactionManager.suspend(); 364 365 TransactionContext newCxt = createTransaction(); 366 newCxt.setOld(oldCxt); 367 newCxt.setOldTrans(oldTrans); 368 369 _threadTransaction.set(newCxt); 370 371 if (_resinIsolation == RESIN_ROW_LOCKING) 372 newCxt.setRowLocking(true); 373 374 _userTransaction.setTransactionTimeout((int) (_transactionTimeout / 1000L)); 375 _userTransaction.begin(); 376 Transaction trans = _transactionManager.getTransaction(); 377 378 setTransaction(newCxt, trans); 379 380 return newCxt; 381 } catch (Exception e) { 382 log.log(Level.WARNING, e.toString(), e); 383 384 throw EJBExceptionWrapper.create(e); 385 } 386 } 387 388 393 public TransactionContext beginSupports() 394 throws EJBException 395 { 396 try { 397 Transaction trans = _transactionManager.getTransaction(); 398 TransactionContext cxt = _threadTransaction.get(); 399 400 if (cxt == null || cxt.getTransaction() != trans) { 402 if (trans != null) 404 cxt = _transactionMap.get(trans); 405 else 406 cxt = null; 407 408 if (cxt == null) { 409 cxt = createTransactionNoDepth(); 410 setTransaction(cxt, trans); 411 } 412 413 _threadTransaction.set(cxt); 414 415 if (trans != null) { 416 cxt.setUserTransaction(true); 417 cxt.pushDepth(); 418 } 419 } 420 421 cxt.pushDepth(); 422 423 if (_resinIsolation == RESIN_ROW_LOCKING) 424 cxt.setRowLocking(true); 425 426 return cxt; 427 } catch (Exception e) { 428 log.log(Level.WARNING, e.toString(), e); 429 430 throw EJBExceptionWrapper.create(e); 431 } 432 } 433 434 439 public TransactionContext suspend() 440 throws EJBException 441 { 442 try { 443 TransactionContext oldCxt = _threadTransaction.get(); 444 Transaction oldTrans = _transactionManager.suspend(); 445 446 if (oldTrans == null && oldCxt != null) { 447 oldCxt.pushDepth(); 448 return oldCxt; 449 } 450 451 TransactionContext cxt = createTransaction(); 452 _threadTransaction.set(cxt); 453 454 cxt.setOld(oldCxt); 455 cxt.setOldTrans(oldTrans); 456 457 return cxt; 458 } catch (Exception e) { 459 log.log(Level.WARNING, e.toString(), e); 460 461 throw EJBExceptionWrapper.create(e); 462 } 463 } 464 465 470 public TransactionContext beginNever() 471 throws EJBException 472 { 473 try { 474 Transaction oldTrans = _transactionManager.getTransaction(); 475 476 if (oldTrans != null) 477 throw new EJBException ("Transaction forbidden in 'Never' method"); 478 479 TransactionContext cxt = _threadTransaction.get(); 480 481 if (cxt == null) { 482 cxt = createTransaction(); 483 _threadTransaction.set(cxt); 484 } 485 else 486 cxt.pushDepth(); 487 488 return cxt; 489 } catch (Exception e) { 490 log.log(Level.WARNING, e.toString(), e); 491 492 throw EJBExceptionWrapper.create(e); 493 } 494 } 495 496 501 public TransactionContext beginMandatory() 502 throws EJBException 503 { 504 try { 505 Transaction trans = _transactionManager.getTransaction(); 506 507 if (trans == null) 508 throw new EJBException ("Transaction required in 'Mandatory' method"); 509 510 return beginRequired(); 511 } catch (Exception e) { 512 log.log(Level.WARNING, e.toString(), e); 513 514 throw EJBExceptionWrapper.create(e); 515 } 516 } 517 518 523 public void resume(TransactionContext oldCxt, 524 Transaction oldTrans, 525 Transaction completedTransaction) 526 throws EJBException 527 { 528 try { 529 if (completedTransaction != null) 530 _transactionMap.remove(completedTransaction); 531 _threadTransaction.set(oldCxt); 532 533 if (oldTrans != null) 534 _transactionManager.resume(oldTrans); 535 } catch (Exception e) { 536 log.log(Level.WARNING, e.toString(), e); 537 538 throw EJBExceptionWrapper.create(e); 539 } 540 } 541 542 545 private void setTransaction(TransactionContext cxt, Transaction trans) 546 { 547 if (cxt != null) { 548 Transaction old = cxt.getTransaction(); 549 550 if (old != null) 551 _transactionMap.remove(old); 552 } 553 else if (trans != null) 554 _transactionMap.remove(trans); 555 556 cxt.setTransaction(trans); 557 558 if (trans != null) 559 _transactionMap.put(trans, cxt); 560 } 561 562 565 TransactionContext createTransaction() 566 { 567 TransactionContext trans = _freeTransactions.allocate(); 568 569 if (trans == null) 570 trans = new TransactionContext(this); 571 trans.init(true); 572 573 return trans; 574 } 575 576 579 TransactionContext createTransactionNoDepth() 580 { 581 TransactionContext trans = _freeTransactions.allocate(); 582 583 if (trans == null) 584 trans = new TransactionContext(this); 585 trans.init(false); 586 587 return trans; 588 } 589 590 593 public TransactionContext startTransaction(String xid) 594 { 595 try { 596 TransactionContext xa = _foreignTransactionMap.get(xid); 597 598 if (xa != null) { 599 resume(xa, xa.getTransaction(), null); 600 return xa; 601 } 602 603 xa = beginRequiresNew(); 604 605 _foreignTransactionMap.put(xid, xa); 606 607 return xa; 608 } catch (Throwable e) { 609 log.log(Level.FINE, e.toString(), e); 610 611 _foreignTransactionMap.remove(xid); 612 613 return null; 614 } 615 } 616 617 620 public void finishTransaction(String xid) 621 { 622 try { 623 TransactionContext xa = _foreignTransactionMap.get(xid); 624 625 if (xa == null) { 626 } 627 else if (xa.isEmpty()) { 628 _foreignTransactionMap.remove(xid); 629 xa.commit(); 630 } 631 else { 632 suspend(); 633 } 635 } catch (Exception e) { 636 log.log(Level.FINE, e.toString(), e); 637 } 638 } 639 640 643 public void commitTransaction(String xid) 644 { 645 try { 646 TransactionContext xa = _foreignTransactionMap.remove(xid); 647 648 if (xa != null) { 649 resume(xa, xa.getTransaction(), null); 650 xa.commit(); 651 } 652 } catch (Throwable e) { 653 log.log(Level.FINE, e.toString(), e); 654 } 655 } 656 657 660 public void rollbackTransaction(String xid) 661 { 662 try { 663 TransactionContext xa = _foreignTransactionMap.remove(xid); 664 665 if (xa != null) { 666 resume(xa, xa.getTransaction(), null); 667 xa.rollback(); 668 } 669 } catch (Throwable e) { 670 log.log(Level.FINE, e.toString(), e); 671 } 672 } 673 674 677 void freeTransaction(TransactionContext trans) 678 { 679 _freeTransactions.free(trans); 680 } 681 682 685 public void destroy() 686 { 687 synchronized (this) { 688 if (_isClosed) 689 return; 690 691 _isClosed = true; 692 } 693 694 _transactionMap = null; 695 } 696 } 697 698 | Popular Tags |