1 21 22 package org.apache.derby.jdbc; 23 24 import java.sql.SQLException ; 25 import javax.transaction.xa.XAResource ; 26 import javax.transaction.xa.Xid ; 27 import javax.transaction.xa.XAException ; 28 29 import org.apache.derby.iapi.error.StandardException; 30 import org.apache.derby.iapi.jdbc.BrokeredConnection; 31 import org.apache.derby.iapi.jdbc.ResourceAdapter; 32 import org.apache.derby.iapi.reference.SQLState; 33 import org.apache.derby.iapi.reference.JDBC30Translation; 34 import org.apache.derby.iapi.services.context.ContextManager; 35 import org.apache.derby.iapi.services.context.ContextService; 36 import org.apache.derby.iapi.services.info.JVMInfo; 37 import org.apache.derby.iapi.store.access.XATransactionController; 38 import org.apache.derby.iapi.store.access.xa.XAResourceManager; 39 import org.apache.derby.iapi.store.access.xa.XAXactId; 40 import org.apache.derby.impl.jdbc.EmbedConnection; 41 import org.apache.derby.impl.jdbc.TransactionResourceImpl; 42 43 46 class EmbedXAResource implements XAResource { 47 48 private EmbedPooledConnection con; 49 private ResourceAdapter ra; 50 private XAXactId currentXid; 51 52 EmbedXAResource (EmbedPooledConnection con, ResourceAdapter ra) { 53 this.con = con; 54 this.ra = ra; 55 } 56 57 72 public final synchronized void commit(Xid xid, boolean onePhase) 73 throws XAException { 74 checkXAActive(); 75 XAXactId xid_im = new XAXactId(xid); 77 XATransactionState tranState = getTransactionState(xid_im); 78 79 if (tranState == null) { 80 XAResourceManager rm = ra.getXAResourceManager(); 81 ContextManager inDoubtCM = rm.find(xid); 82 if (inDoubtCM == null) 84 throw new XAException (XAException.XAER_NOTA); 85 ContextService csf = ContextService.getFactory(); 86 csf.setCurrentContextManager(inDoubtCM); 87 try { 88 rm.commit(inDoubtCM, xid_im, onePhase); 89 90 inDoubtCM.cleanupOnError(StandardException.closeException()); 93 return; 94 } catch (StandardException se) { 95 inDoubtCM.cleanupOnError(se); 99 throw wrapInXAException(se); 100 } finally { 101 csf.resetCurrentContextManager(inDoubtCM); 102 } 103 104 } 105 106 synchronized (tranState) { 107 checkUserCredentials(tranState.creatingResource); 108 109 switch (tranState.associationState) { 112 case XATransactionState.T0_NOT_ASSOCIATED: 113 break; 114 115 case XATransactionState.TRO_FAIL: 116 throw new XAException (tranState.rollbackOnlyCode); 117 118 default: 119 throw new XAException (XAException.XAER_PROTO); 120 } 121 122 if (tranState.suspendedList != null && tranState.suspendedList.size() != 0) 123 throw new XAException (XAException.XAER_PROTO); 124 125 if (tranState.isPrepared == onePhase) 126 throw new XAException (XAException.XAER_PROTO); 127 128 EmbedConnection conn = tranState.conn; 129 130 try { 131 conn.xa_commit(onePhase); 132 } catch (SQLException sqle) { 133 throw wrapInXAException(sqle); 134 } finally { 135 returnConnectionToResource(tranState, xid_im); 136 } 137 } 138 } 139 140 164 public final synchronized void end(Xid xid, int flags) throws XAException { 165 checkXAActive(); 166 167 try { 168 if (con.currentConnectionHandle != null) 176 con.currentConnectionHandle.getIsolationUptoDate(); 177 } catch (SQLException sqle) { 178 throw wrapInXAException(sqle); 179 } 180 181 XAXactId xid_im = new XAXactId(xid); 183 184 boolean endingCurrentXid = false; 185 186 if (currentXid != null) { 188 if (!currentXid.equals(xid_im)) 189 throw new XAException (XAException.XAER_PROTO); 190 endingCurrentXid = true; 191 } 192 193 XATransactionState tranState = getTransactionState(xid_im); 194 if (tranState == null) 195 throw new XAException (XAException.XAER_NOTA); 196 197 boolean rollbackOnly = tranState.end(this, flags, endingCurrentXid); 198 199 if (endingCurrentXid) { 202 currentXid = null; 203 con.realConnection = null; 204 } 205 206 if (rollbackOnly) 207 throw new XAException (tranState.rollbackOnlyCode); 208 } 209 210 226 public final synchronized int prepare(Xid xid) throws XAException { 227 checkXAActive(); 228 229 XAXactId xid_im = new XAXactId(xid); 231 232 XATransactionState tranState = getTransactionState(xid_im); 233 234 if (tranState == null) { 235 XAResourceManager rm = ra.getXAResourceManager(); 236 237 ContextManager inDoubtCM = rm.find(xid); 238 239 if (inDoubtCM == null) 241 throw new XAException (XAException.XAER_NOTA); 242 243 throw new XAException (XAException.XAER_PROTO); 245 246 } 247 248 synchronized (tranState) { 249 250 checkUserCredentials(tranState.creatingResource); 251 252 switch (tranState.associationState) { 255 case XATransactionState.T0_NOT_ASSOCIATED: 256 break; 257 258 case XATransactionState.TRO_FAIL: 259 throw new XAException (tranState.rollbackOnlyCode); 260 261 default: 262 throw new XAException (XAException.XAER_PROTO); 263 } 264 265 if (tranState.suspendedList != null 266 && tranState.suspendedList.size() != 0) 267 throw new XAException (XAException.XAER_PROTO); 268 269 if (tranState.isPrepared) 270 throw new XAException (XAException.XAER_PROTO); 271 272 EmbedConnection conn = tranState.conn; 273 274 try { 275 276 int ret = conn.xa_prepare(); 277 278 if (ret == XATransactionController.XA_OK) { 279 tranState.isPrepared = true; 280 281 return XAResource.XA_OK; 282 } else { 283 284 returnConnectionToResource(tranState, xid_im); 285 return XAResource.XA_RDONLY; 286 } 287 } catch (SQLException sqle) { 288 throw wrapInXAException(sqle); 289 } 290 } 291 292 } 293 294 303 public int getTransactionTimeout() { 304 return 0; 305 } 306 307 319 public final synchronized boolean isSameRM(XAResource xares) 320 throws XAException { 321 checkXAActive(); 322 if (xares instanceof EmbedXAResource) { 323 return ra == ((EmbedXAResource) xares).ra; 324 } 325 return false; 326 } 327 328 346 public final synchronized Xid [] recover(int flag) throws XAException { 347 checkXAActive(); 348 349 try { 350 return ra.getXAResourceManager().recover(flag); 351 } catch (StandardException se) { 352 throw wrapInXAException(se); 353 } 354 } 355 356 364 public final synchronized void forget(Xid xid) throws XAException { 365 366 checkXAActive(); 367 368 XAXactId xid_im = new XAXactId(xid); 370 371 XATransactionState tranState = getTransactionState(xid_im); 372 if (tranState == null) { 373 XAResourceManager rm = ra.getXAResourceManager(); 374 375 ContextManager inDoubtCM = rm.find(xid); 376 377 if (inDoubtCM == null) 379 throw new XAException (XAException.XAER_NOTA); 380 381 ContextService csf = ContextService.getFactory(); 382 383 csf.setCurrentContextManager(inDoubtCM); 384 try { 385 rm.forget(inDoubtCM, xid_im); 386 387 inDoubtCM.cleanupOnError(StandardException.closeException()); 389 return; 390 } catch (StandardException se) { 391 inDoubtCM.cleanupOnError(se); 395 throw wrapInXAException(se); 396 } finally { 397 csf.resetCurrentContextManager(inDoubtCM); 398 } 399 400 } 401 402 throw new XAException (tranState.isPrepared 403 ? XAException.XAER_NOTA 404 : XAException.XAER_PROTO); 405 } 406 407 414 public final synchronized void rollback(Xid xid) throws XAException { 415 checkXAActive(); 416 417 XAXactId xid_im = new XAXactId(xid); 419 420 XATransactionState tranState = getTransactionState(xid_im); 421 422 if (tranState == null) { 423 XAResourceManager rm = ra.getXAResourceManager(); 424 425 ContextManager inDoubtCM = rm.find(xid); 426 427 if (inDoubtCM == null) 429 throw new XAException (XAException.XAER_NOTA); 430 431 ContextService csf = ContextService.getFactory(); 432 433 csf.setCurrentContextManager(inDoubtCM); 434 try { 435 rm.rollback(inDoubtCM, xid_im); 436 437 inDoubtCM.cleanupOnError(StandardException.closeException()); 439 return; 440 } catch (StandardException se) { 441 inDoubtCM.cleanupOnError(se); 445 throw wrapInXAException(se); 446 } finally { 447 csf.resetCurrentContextManager(inDoubtCM); 448 } 449 450 } 451 452 synchronized (tranState) { 453 454 switch (tranState.associationState) { 457 case XATransactionState.T0_NOT_ASSOCIATED: 458 case XATransactionState.TRO_FAIL: 459 break; 460 461 default: 462 throw new XAException (XAException.XAER_PROTO); 463 } 464 465 if (tranState.suspendedList != null 466 && tranState.suspendedList.size() != 0) 467 throw new XAException (XAException.XAER_PROTO); 468 469 checkUserCredentials(tranState.creatingResource); 470 471 try { 472 473 tranState.conn.xa_rollback(); 474 } catch (SQLException sqle) { 475 throw wrapInXAException(sqle); 476 } finally { 477 returnConnectionToResource(tranState, xid_im); 478 } 479 } 480 } 481 482 483 500 public boolean setTransactionTimeout(int seconds) { 501 return false; 502 } 503 504 521 public final synchronized void start(Xid xid, 522 int flags) throws XAException { 523 checkXAActive(); 524 525 if (currentXid != null) 527 throw new XAException (XAException.XAER_PROTO); 528 529 XAXactId xid_im = new XAXactId(xid); 531 532 XATransactionState tranState = getTransactionState(xid_im); 533 534 switch (flags) { 535 case XAResource.TMNOFLAGS: 536 if (tranState != null) 537 throw new XAException (XAException.XAER_DUPID); 538 539 try { 540 541 if (con.realConnection == null) { 542 con.openRealConnection(); 543 544 if (con.currentConnectionHandle != null) { 545 546 con.currentConnectionHandle.setState(true); 550 con.realConnection.setApplicationConnection 551 (con.currentConnectionHandle); 552 } 553 554 } else { 555 556 if (con.currentConnectionHandle != null) { 559 if (con.currentConnectionHandle.getAutoCommit()) 560 con.currentConnectionHandle.rollback(); 561 } 562 if (!con.realConnection.transactionIsIdle()) 563 throw new XAException (XAException.XAER_OUTSIDE); 564 565 if (con.currentConnectionHandle != null) { 566 con.currentConnectionHandle.getIsolationUptoDate(); 576 con.currentConnectionHandle.setState(true); 579 580 con.realConnection.rollback(); 584 } else { 585 con.resetRealConnection(); 586 } 587 588 } 589 590 con.realConnection.setAutoCommit(false); 592 593 con.realConnection.setHoldability( 596 JDBC30Translation.CLOSE_CURSORS_AT_COMMIT); 597 598 con.realConnection.getLanguageConnection(). 599 getTransactionExecute(). 600 createXATransactionFromLocalTransaction( 601 xid_im.getFormatId(), 602 xid_im.getGlobalTransactionId(), 603 xid_im.getBranchQualifier()); 604 605 606 } catch (StandardException se) { 607 throw wrapInXAException(se); 608 } catch (SQLException sqle) { 609 throw wrapInXAException(sqle); 610 } 611 612 613 if (!ra.addConnection(xid_im, 614 new XATransactionState( 615 con.realConnection.getContextManager(), 616 con.realConnection, this, xid_im))) 617 throw new XAException (XAException.XAER_DUPID); 618 619 break; 620 621 case XAResource.TMRESUME: 622 case XAResource.TMJOIN: 623 if (tranState == null) 624 throw new XAException (XAException.XAER_NOTA); 625 626 tranState.start(this, flags); 627 628 if (tranState.conn != con.realConnection) { 629 630 if (con.realConnection != null) { 631 632 if (!con.realConnection.transactionIsIdle()) 633 throw new XAException (XAException.XAER_OUTSIDE); 634 635 try { 643 if (con.currentConnectionHandle != null) { 644 con.currentConnectionHandle.getIsolationUptoDate(); 645 } 646 } catch (SQLException sqle) { 647 throw wrapInXAException(sqle); 648 } 649 650 closeUnusedConnection(con.realConnection); 651 } 652 con.realConnection = tranState.conn; 653 654 if (con.currentConnectionHandle != null) { 655 656 try { 657 con.currentConnectionHandle.setState(false); 660 con.realConnection.setApplicationConnection( 661 con.currentConnectionHandle); 662 } catch (SQLException sqle) { 663 throw wrapInXAException(sqle); 664 } 665 } 666 667 } 668 669 670 break; 671 672 default: 673 throw new XAException (XAException.XAER_INVAL); 674 } 675 676 currentXid = xid_im; 677 } 678 679 683 Xid getCurrentXid () { 684 return currentXid; 685 } 686 687 692 private XATransactionState getTransactionState(XAXactId xid_im) { 693 return (XATransactionState) ra.findConnection(xid_im); 694 } 695 696 702 private void checkUserCredentials(EmbedXAResource original) 703 throws XAException { 704 if (original == this) 705 return; 706 if (original.con.getPassword().equals(con.getPassword()) && 707 (original.con.getUsername().equals(con.getUsername()))) 708 return; 709 throw new XAException (XAException.XA_RBINTEGRITY); 710 } 711 712 716 private void checkXAActive() throws XAException { 717 try { 718 con.checkActive(); 719 } catch (SQLException sqle) { 720 throw wrapInXAException(sqle); 721 } 722 } 723 724 728 private static XAException wrapInXAException(SQLException se) { 729 String sqlstate = se.getSQLState(); 731 String message = se.getMessage(); 732 733 XAException xae; 734 735 if (sqlstate == null) { 736 if (message != null) 738 xae = new XAException (message); 739 else 740 xae = new XAException (XAException.XAER_RMERR); 741 } else if (sqlstate.equals(StandardException.getSQLStateFromIdentifier( 742 SQLState.STORE_XA_XAER_DUPID))) 743 xae = new XAException (XAException.XAER_DUPID); 744 else if (sqlstate.equals(StandardException.getSQLStateFromIdentifier( 745 SQLState.STORE_XA_PROTOCOL_VIOLATION))) 746 xae = new XAException (XAException.XA_RBPROTO); 747 else if (sqlstate.equals(SQLState.DEADLOCK)) 748 xae = new XAException (XAException.XA_RBDEADLOCK); 749 else if (sqlstate.equals(SQLState.LOCK_TIMEOUT)) 750 xae = new XAException (XAException.XA_RBTIMEOUT); 751 else if (message != null) 752 xae = new XAException (message); 753 else 754 xae = new XAException (XAException.XAER_RMERR); 755 756 if (JVMInfo.JDK_ID >= JVMInfo.J2SE_14) 757 xae.initCause(se); 758 return xae; 759 } 760 761 765 private static XAException wrapInXAException(StandardException se) { 766 return wrapInXAException( 767 TransactionResourceImpl.wrapInSQLException( 768 (SQLException ) null, se)); 769 } 770 771 777 private void returnConnectionToResource(XATransactionState tranState, 778 XAXactId xid_im) { 779 780 removeXATransaction(xid_im); 781 synchronized (tranState) { 782 tranState.associationState = XATransactionState.TC_COMPLETED; 784 tranState.notifyAll(); 785 786 EmbedConnection conn = tranState.conn; 787 788 if ((tranState.creatingResource.con.realConnection == conn) || 791 (tranState.creatingResource.con.realConnection == null)) { 792 793 tranState.creatingResource.con.realConnection = conn; 794 795 BrokeredConnection handle = 796 tranState.creatingResource.con.currentConnectionHandle; 797 798 conn.setApplicationConnection(handle); 799 800 if (handle != null) { 801 try { 802 handle.setState(true); 803 } catch (SQLException sqle) { 804 805 closeUnusedConnection(tranState.conn); 807 tranState.creatingResource.con.realConnection = null; 808 } 809 } 810 return; 811 } 812 } 813 814 closeUnusedConnection(tranState.conn); 816 } 817 818 819 824 private static void closeUnusedConnection(EmbedConnection conn) { 825 if (conn != null) { 826 try { 827 conn.close(); 828 } catch (SQLException sqle) { 829 830 } 831 } 832 } 833 834 838 private void removeXATransaction(XAXactId xid_im) { 839 XATransactionState tranState = 840 (XATransactionState) ra.removeConnection(xid_im); 841 if (tranState != null) 842 tranState.popMe(); 843 } 844 845 } 846 | Popular Tags |