1 9 package org.jboss.portal.common.transaction; 10 11 import javax.transaction.Status ; 12 import javax.transaction.SystemException ; 13 import javax.transaction.Transaction ; 14 import javax.transaction.TransactionManager ; 15 import javax.transaction.NotSupportedException ; 16 import javax.transaction.HeuristicMixedException ; 17 import javax.transaction.HeuristicRollbackException ; 18 import javax.transaction.RollbackException ; 19 20 import org.apache.log4j.Logger; 21 22 28 public class Transactions 29 { 30 31 private static Logger log = Logger.getLogger(Transactions.class); 32 33 private static final String [] STATUS_NAMES = { 34 "CANNOT_GET_STATUS", 35 "STATUS_ACTIVE", 36 "STATUS_MARKED_ROLLBACK", 37 "STATUS_PREPARED", 38 "STATUS_COMMITTED", 39 "STATUS_ROLLEDBACK", 40 "STATUS_UNKNOWN", 41 "STATUS_NO_TRANSACTION", 42 "STATUS_PREPARING", 43 "STATUS_COMMITTING", 44 "STATUS_ROLLING_BACK"}; 45 46 55 public static Transaction applyBefore(Type type, TransactionManager tm) throws TransactionException, IllegalArgumentException 56 { 57 if (tm == null) 58 { 59 throw new IllegalArgumentException ("No transaction manager provided"); 60 } 61 if (type == null) 62 { 63 throw new IllegalArgumentException ("No type"); 64 } 65 66 Transaction oldTx = suspend(tm); 68 69 if (oldTx != null) 70 { 71 type.txBefore(tm, oldTx); 72 } 73 else 74 { 75 type.noTxBefore(tm); 76 } 77 78 return oldTx; 79 } 80 81 90 public static void applyAfter(Type type, TransactionManager tm, Transaction oldTx) throws TransactionException, IllegalArgumentException 91 { 92 if (tm == null) 93 { 94 throw new IllegalArgumentException ("No transaction manager provided"); 95 } 96 if (type == null) 97 { 98 throw new IllegalArgumentException ("No type"); 99 } 100 101 try 102 { 103 if (oldTx != null) 104 { 105 type.txAfter(tm, oldTx); 106 } 107 else 108 { 109 type.noTxAfter(tm); 110 } 111 } 112 finally 113 { 114 if (oldTx != null) 115 { 116 try 117 { 118 resume(tm, oldTx); 119 } 120 catch (TransactionException ignore) 121 { 122 log.error("Was not capable to resume the incoming transaction", ignore); 123 } 124 } 125 } 126 } 127 128 139 public static Object apply(Type type, TransactionManager tm, final Runnable runnable) throws NestedException, TransactionException, IllegalArgumentException 140 { 141 if (tm == null) 142 { 143 throw new IllegalArgumentException ("No transaction manager provided"); 144 } 145 if (runnable == null) 146 { 147 throw new IllegalArgumentException ("No code to execute"); 148 } 149 if (type == null) 150 { 151 throw new IllegalArgumentException ("No type"); 152 } 153 154 Throwable throwable = null; 156 157 Object ret = null; 159 160 Transaction oldTx = suspend(tm); 162 163 try 164 { 165 if (oldTx != null) 166 { 167 type.txBefore(tm, oldTx); 168 try 169 { 170 ret = runnable.run(); 171 } 172 catch (Throwable t) 173 { 174 throwable = t; 175 } 176 finally 177 { 178 type.txAfter(tm, oldTx); 179 } 180 } 181 else 182 { 183 type.noTxBefore(tm); 184 try 185 { 186 ret = runnable.run(); 187 } 188 catch (Throwable t) 189 { 190 throwable = t; 191 } 192 finally 193 { 194 type.noTxAfter(tm); 195 } 196 } 197 } 198 finally 199 { 200 if (oldTx != null) 201 { 202 try 203 { 204 resume(tm, oldTx); 205 } 206 catch (TransactionException ignore) 207 { 208 log.error("Was not capable to resume the incoming transaction", ignore); 209 } 210 } 211 } 212 if (throwable != null) 213 { 214 if (throwable instanceof Error ) 215 { 216 throw (Error )throwable; 217 } 218 else 219 { 220 throw new NestedException(throwable); 221 } 222 } 223 else 224 { 225 return ret; 226 } 227 } 228 229 public static Object notSupported(TransactionManager tm, Runnable runnable) 230 throws NestedException, TransactionException 231 { 232 return apply(TYPE_NOT_SUPPORTED, tm, runnable); 233 } 234 235 public static Object never(TransactionManager tm, Runnable runnable) 236 throws NestedException, TransactionException 237 { 238 return apply(TYPE_NEVER, tm, runnable); 239 } 240 241 public static Object mandatory(TransactionManager tm, Runnable runnable) 242 throws NestedException, TransactionException 243 { 244 return apply(TYPE_MANDATORY, tm, runnable); 245 } 246 247 public static Object supports(TransactionManager tm, Runnable runnable) 248 throws NestedException, TransactionException 249 { 250 return apply(TYPE_SUPPORTS, tm, runnable); 251 } 252 253 public static Object required(TransactionManager tm, Runnable runnable) 254 throws NestedException, TransactionException 255 { 256 return apply(TYPE_REQUIRED, tm, runnable); 257 } 258 259 public static Object requiresNew(TransactionManager tm, Runnable runnable) 260 throws NestedException, TransactionException 261 { 262 return apply(TYPE_REQUIRES_NEW, tm, runnable); 263 } 264 265 271 public static void begin(TransactionManager tm) throws IllegalArgumentException , TransactionException 272 { 273 try 274 { 275 if (tm == null) 276 { 277 throw new IllegalArgumentException ("No transaction manager"); 278 } 279 tm.begin(); 280 } 281 catch (SystemException e) 282 { 283 log.error("Problem when beginning transaction", e); 284 throw new TransactionException(e); 285 } 286 catch (NotSupportedException e) 287 { 288 log.error("Problem when beginning transaction", e); 289 throw new TransactionException(e); 290 } 291 } 292 293 300 private static void setRollbackOnly(Transaction tx) throws IllegalArgumentException , TransactionException 301 { 302 try 303 { 304 if (tx == null) 305 { 306 throw new IllegalArgumentException ("No transaction to set rollback only"); 307 } 308 tx.setRollbackOnly(); 309 } 310 catch (SystemException e) 311 { 312 log.error("Problem when setting transaction as rollback only", e); 313 throw new TransactionException(e); 314 } 315 } 316 317 324 public static void setRollbackOnly(TransactionManager tm) throws IllegalArgumentException , TransactionException 325 { 326 try 327 { 328 if (tm == null) 329 { 330 throw new IllegalArgumentException ("No transaction manager"); 331 } 332 Transaction tx = tm.getTransaction(); 333 if (tx == null) 334 { 335 throw new TransactionException("No active transaction to set rollback only"); 336 } 337 setRollbackOnly(tx); 338 } 339 catch (SystemException e) 340 { 341 log.error("Problem when setting transaction as rollback only", e); 342 throw new TransactionException(e); 343 } 344 } 345 346 public void safeSetRollbackOnly(TransactionManager tm) 347 { 348 try 349 { 350 setRollbackOnly(tm); 351 } 352 catch (IllegalArgumentException e) 353 { 354 log.error("", e); 355 } 356 catch (TransactionException e) 357 { 358 log.error("", e); 359 } 360 } 361 362 public static void safeEnd(TransactionManager tm) 363 { 364 try 365 { 366 end(tm); 367 } 368 catch (IllegalArgumentException e) 369 { 370 log.error("", e); 371 } 372 catch (TransactionException e) 373 { 374 log.error("", e); 375 } 376 } 377 378 386 public static boolean end(TransactionManager tm) throws IllegalArgumentException , TransactionException 387 { 388 try 389 { 390 if (tm == null) 391 { 392 throw new IllegalArgumentException ("No transaction manager"); 393 } 394 int status = tm.getStatus(); 395 switch (status) 396 { 397 case Status.STATUS_MARKED_ROLLBACK: 398 tm.rollback(); 399 return false; 400 case Status.STATUS_ACTIVE: 401 tm.commit(); 402 return true; 403 default: 404 throw new TransactionException("Abnormal status for ending a tx " + STATUS_NAMES[status]); 405 } 406 } 407 catch (SystemException e) 408 { 409 log.error("Problem when ending transaction", e); 410 throw new TransactionException(e); 411 } 412 catch (HeuristicMixedException e) 413 { 414 log.error("Problem when ending transaction", e); 415 throw new TransactionException(e); 416 } 417 catch (HeuristicRollbackException e) 418 { 419 log.error("Problem when ending transaction", e); 420 throw new TransactionException(e); 421 } 422 catch (RollbackException e) 423 { 424 log.error("Problem when ending transaction", e); 425 throw new TransactionException(e); 426 } 427 } 428 429 437 public static void resume(TransactionManager tm, Transaction tx) throws IllegalArgumentException , TransactionException 438 { 439 try 440 { 441 if (tm == null) 442 { 443 throw new IllegalArgumentException ("No transaction manager"); 444 } 445 if (tx == null) 446 { 447 throw new IllegalArgumentException ("No transaction to resume"); 448 } 449 tm.resume(tx); 450 } 451 catch (Exception e) 452 { 453 log.error("Problem when resuming transaction", e); 454 throw new TransactionException(e); 455 } 456 } 457 458 466 public static Transaction suspend(TransactionManager tm) throws IllegalArgumentException , TransactionException 467 { 468 try 469 { 470 if (tm == null) 471 { 472 throw new IllegalArgumentException ("No transaction manager"); 473 } 474 return tm.suspend(); 475 } 476 catch (SystemException e) 477 { 478 log.error("Problem when suspending transaction", e); 479 throw new TransactionException(e); 480 } 481 } 482 483 public interface Runnable 484 { 485 Object run() throws Exception ; 486 } 487 488 public abstract static class Type 489 { 490 private final String name; 491 492 private Type(String name) 493 { 494 this.name = name; 495 } 496 497 abstract void txBefore(TransactionManager tm, Transaction oldTx) throws TransactionException; 498 499 abstract void txAfter(TransactionManager tm, Transaction oldTx); 500 501 abstract void noTxBefore(TransactionManager tm) throws TransactionException; 502 503 abstract void noTxAfter(TransactionManager tm); 504 505 public String getName() 506 { 507 return name; 508 } 509 510 public String toString() 511 { 512 return name; 513 } 514 } 515 516 public static final Type TYPE_NOT_SUPPORTED = new Type("NOT_SUPPORTED") 517 { 518 void txBefore(TransactionManager tm, Transaction oldTx) 519 { 520 } 521 void txAfter(TransactionManager tm, Transaction oldTx) 522 { 523 } 524 void noTxBefore(TransactionManager tm) 525 { 526 } 527 void noTxAfter(TransactionManager tm) 528 { 529 } 530 }; 531 532 public static final Type TYPE_SUPPORTS = new Type("SUPPORTS") 533 { 534 void txBefore(TransactionManager tm, Transaction oldTx) throws TransactionException 535 { 536 resume(tm, oldTx); 537 } 538 void txAfter(TransactionManager tm, Transaction oldTx) 539 { 540 try 541 { 542 suspend(tm); 543 } 544 catch (IllegalStateException ignore) 545 { 546 log.error("Problem when suspending transaction", ignore); 547 } 548 } 549 void noTxBefore(TransactionManager tm) 550 { 551 } 552 void noTxAfter(TransactionManager tm) 553 { 554 } 555 }; 556 557 public static final Type TYPE_REQUIRED = new Type("REQUIRED") 558 { 559 void txBefore(TransactionManager tm, Transaction oldTx) 560 { 561 resume(tm, oldTx); 562 } 563 void txAfter(TransactionManager tm, Transaction oldTx) 564 { 565 try 566 { 567 suspend(tm); 568 } 569 catch (TransactionException ignore) 570 { 571 log.error("Problem when suspending transaction", ignore); 572 } 573 } 574 void noTxBefore(TransactionManager tm) throws TransactionException 575 { 576 begin(tm); 577 } 578 void noTxAfter(TransactionManager tm) 579 { 580 try 581 { 582 end(tm); 583 } 584 catch (IllegalStateException ignore) 585 { 586 log.error("Problem when ending transaction", ignore); 587 } 588 } 589 }; 590 591 public static final Type TYPE_REQUIRES_NEW = new Type("REQUIRES_NEW") 592 { 593 void txBefore(TransactionManager tm, Transaction oldTx) throws TransactionException 594 { 595 begin(tm); 596 } 597 void txAfter(TransactionManager tm, Transaction oldTx) 598 { 599 try 600 { 601 end(tm); 602 } 603 catch (IllegalStateException ignore) 604 { 605 log.error("Problem when ending transaction", ignore); 606 } 607 } 608 void noTxBefore(TransactionManager tm) throws TransactionException 609 { 610 begin(tm); 611 } 612 void noTxAfter(TransactionManager tm) 613 { 614 try 615 { 616 end(tm); 617 } 618 catch (IllegalStateException ignore) 619 { 620 log.error("Problem when ending transaction", ignore); 621 } 622 } 623 }; 624 625 public static final Type TYPE_MANDATORY = new Type("MANDATORY") 626 { 627 void txBefore(TransactionManager tm, Transaction oldTx) throws TransactionException 628 { 629 resume(tm, oldTx); 630 } 631 void txAfter(TransactionManager tm, Transaction oldTx) 632 { 633 } 634 void noTxBefore(TransactionManager tm) throws TransactionException 635 { 636 throw new TransactionException("No incoming transaction"); 637 } 638 void noTxAfter(TransactionManager tm) 639 { 640 throw new UnsupportedOperationException ("Should never ne called"); 641 } 642 }; 643 644 public static final Type TYPE_NEVER = new Type("NEVER") 645 { 646 void txBefore(TransactionManager tm, Transaction oldTx) throws TransactionException 647 { 648 throw new TransactionException("Need no incoming transaction"); 649 } 650 void txAfter(TransactionManager tm, Transaction oldTx) 651 { 652 throw new UnsupportedOperationException ("Should never ne called"); 653 } 654 void noTxBefore(TransactionManager tm) 655 { 656 } 657 void noTxAfter(TransactionManager tm) 658 { 659 } 660 }; 661 } 662 | Popular Tags |