1 23 24 package org.objectweb.speedo.jca; 25 26 import org.objectweb.speedo.api.Debug; 27 import org.objectweb.speedo.api.ExceptionHelper; 28 import org.objectweb.speedo.pm.api.ProxyManager; 29 import org.objectweb.util.monolog.api.BasicLevel; 30 import org.objectweb.util.monolog.api.Logger; 31 32 import javax.jdo.JDOException; 33 import javax.jdo.JDOFatalException; 34 import javax.jdo.Transaction; 35 import javax.resource.ResourceException ; 36 import javax.resource.cci.Connection ; 37 import javax.resource.spi.*; 38 import javax.security.auth.Subject ; 39 import javax.transaction.RollbackException ; 40 import javax.transaction.TransactionManager ; 41 import javax.transaction.xa.XAException ; 42 import javax.transaction.xa.XAResource ; 43 import javax.transaction.xa.Xid ; 44 import java.io.PrintWriter ; 45 import java.util.ArrayList ; 46 import java.util.Iterator ; 47 48 51 public class JdoManagedConnection 52 implements ManagedConnection, 53 javax.resource.spi.LocalTransaction , 54 javax.resource.cci.LocalTransaction , 55 XAResource , 56 ManagedConnectionMetaData { 57 58 public final static String EIS_PRODUCT_NAME = "Speedo Resource Adapter"; 59 public final static String EIS_PRODUCT_VERSION = "1.0"; 60 public final static String USER_NAME = "No user name needed to use a JDO driver"; 61 62 65 private Logger logger; 66 67 71 private JdoManagedConnectionFactory mcf; 72 73 77 private ArrayList logicalConnections = new ArrayList (1); 78 79 82 private ArrayList listeners = null; 83 84 87 private ProxyManager localTransactionPM = null; 88 89 93 public XAContext xac; 94 95 99 private ProxyManager defaultPM = null; 100 101 protected JDOConnectionSpec cri = null; 102 103 110 JdoManagedConnection(Logger el, JdoManagedConnectionFactory fmcf) { 111 logger = el; 112 if (Debug.ON) 113 logger.log(BasicLevel.DEBUG, 114 "Constructs a new JdoManagedConnection"); 115 mcf = fmcf; 116 listeners = null; 117 } 118 119 125 protected ProxyManager getProxyManager() { 126 if (localTransactionPM != null) { 127 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 128 logger.log(BasicLevel.DEBUG, "return localTransactionPM: " 129 + localTransactionPM); 130 } 131 return localTransactionPM; 132 } 133 if (xac != null) { 134 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 135 logger.log(BasicLevel.DEBUG, 136 "xac.status= " + xac.status 137 + "xac.xid= " + xac.xid); 138 } 139 if (xac.status != XAContext.STARTED) { 140 throw new JDOFatalException( 141 "XA context should have been started here: xac.status= " 142 + xac.status + "xac.xid= " + xac.xid); 143 } 144 if (xac.pm == null) { 145 synchronized(xac) { 146 if (xac.pm == null) { 147 xac.pm = (ProxyManager) mcf.pmf.getPersistenceManager(); 148 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 149 logger.log(BasicLevel.DEBUG, 150 "Creates a PersistenceManager (" + xac.pm 151 + ") associated to the XID: " + xac.xid); 152 } 153 } 154 } 155 } 156 if (!xac.synchroRegistred) { 157 try { 159 registerSynchronization(); 160 } catch (XAException ex) { 161 JDOFatalException e = new JDOFatalException( 162 "Problem while registering a synchronization.", ex); 163 logger.log(BasicLevel.ERROR, e.getMessage(), ex); 164 throw e; 165 } 166 } 167 return xac.pm; 168 } 169 if (defaultPM == null) { 170 defaultPM = (ProxyManager) mcf.pmf.getPersistenceManager(); 171 } 172 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 173 logger.log(BasicLevel.DEBUG, 174 "return the default persistence manager: " + defaultPM); 175 } 176 return defaultPM; 177 } 178 179 180 188 private XAContext getXAContext(Xid xid, int flag) 189 throws XAException { 190 XAContext _xac = mcf.getXAContext(xid); 191 if (_xac == null) { 192 if (flag == 0) { try { 194 _xac = mcf.createXAContext(xid); 195 } catch (JDOException fe) { 196 Exception ie = ExceptionHelper.getNested(fe); 197 XAException e = new XAException ( 198 "Error during the creation of the XA context with the xid: " 199 + xid + ", error message:" + ie.getMessage()); 200 logger.log(BasicLevel.ERROR, ie.getMessage(), ie); 201 throw e; 202 } 203 } else if (flag == 1) { XAException e = new XAException ("No XA context found for the xid=" + xid); 205 logger.log(BasicLevel.ERROR, e.getMessage(), e); 206 throw e; 207 } } 209 return _xac; 210 } 211 212 220 private synchronized void registerSynchronization() throws XAException { 221 if (xac.synchroRegistred) { 222 return; 223 } 224 Transaction tx = xac.pm.currentTransaction(); 225 if (tx.isActive()) { 226 logger.log(BasicLevel.WARN, "JDO Transaction started and the " + 227 "PersistenceManager is not marked as registered to " + 228 "the XA transaction"); 229 } 230 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 231 logger.log(BasicLevel.DEBUG, "registerSynchronization"); 232 } 233 TransactionManager tm = mcf.tm; 234 if (tm == null) { 235 String msg = "Impossible to register the JDO " + 236 "container as synchronization on the current transaction: " + 237 (tm == null 238 ? "The transaction manager has not found with the JNDI name: " 239 + mcf.getTransactionManagerJNDIName() 240 : "The Transaction object of the JDO implementation does not implement javax.transaction.Synchronization"); 241 logger.log(BasicLevel.ERROR, msg); 242 throw new XAException (msg); 243 } 244 try { 245 tm.getTransaction().registerSynchronization(xac.pm); 246 if (!tx.isActive()) { 247 tx.begin(); 248 } 249 xac.synchroRegistred = true; 250 } catch (RollbackException e) { 251 if (tx.isActive()) { 254 tx.rollback(); 255 } 256 } catch (Exception e) { 257 String msg = "Impossible to register the JDO " + 258 "container as synchronization on the current" + 259 " transaction: " + e.getMessage(); 260 logger.log(BasicLevel.ERROR, msg, e); 261 throw new XAException (msg); 262 } 263 } 264 265 269 protected boolean localTransactionTerminated() { 270 return localTransactionPM == null; 271 } 272 273 278 protected synchronized void dissociateConnection(Object conn) throws ResourceException { 279 int ind = logicalConnections.indexOf(conn); 280 if (ind == -1) { 281 throw new ResourceException ("JDO Connector: cannot dissociate an unknown Connection:" 282 + conn + "\n among " + logicalConnections); 283 } 284 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 285 logger.log(BasicLevel.DEBUG, "Dissociates Connection (" + ind + "): " + conn); 286 } 287 logicalConnections.remove(ind); 288 ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED); 289 ce.setConnectionHandle(conn); 290 if (listeners != null) { 291 synchronized(this) { 292 for (int i=0; i<listeners.size();) { 293 ConnectionEventListener cel = (ConnectionEventListener) listeners.get(i); 294 cel.connectionClosed(ce); 295 if (i<listeners.size() && cel == listeners.get(i)) { 296 i++; 297 } } 299 } 300 } 301 } 302 303 304 306 public String getEISProductName() throws ResourceException { 307 return EIS_PRODUCT_NAME; 308 } 309 310 public String getEISProductVersion() throws ResourceException { 311 return EIS_PRODUCT_VERSION; 312 } 313 314 public int getMaxConnections() throws ResourceException { 315 return 10; 317 } 318 319 public String getUserName() throws ResourceException { 320 return USER_NAME; 321 } 322 323 324 327 331 public Object getConnection(Subject subject, ConnectionRequestInfo info) 332 throws ResourceException { 333 JdoConnection rac = mcf.connectionFactory.createConnection(); 334 rac.initialize(this); 335 associateConnection(rac); 336 return rac; 337 } 338 339 342 public void cleanup() throws ResourceException { 343 if (Debug.ON) 344 logger.log(BasicLevel.DEBUG, "Cleans up ManagedConnection"); 345 int s = (logicalConnections == null ? 0 : logicalConnections.size()); 346 if (s > 0) { 347 s -=1; 348 for(int i=s; i>=0; i--) { 349 ((Connection ) logicalConnections.get(i)).close(); 350 } 351 } 352 if (localTransactionPM != null) { 353 localTransactionPM.close(); 354 localTransactionPM = null; 355 } 356 if (defaultPM != null) { 357 defaultPM.close(); 358 defaultPM = null; 359 } 360 } 362 363 366 public void destroy() throws ResourceException { 367 cleanup(); 368 logger = null; 369 mcf = null; 370 logicalConnections = null; 371 listeners = null; 372 localTransactionPM = null; 373 } 374 375 379 public synchronized void associateConnection(Object o) throws ResourceException { 380 if (Debug.ON) 381 logger.log(BasicLevel.DEBUG, "Associates Connection: " + o + " to the MC " + this); 382 if (!logicalConnections.contains(o)) 383 logicalConnections.add(o); 384 else 385 logger.log(BasicLevel.WARN, "Connection: " + o 386 + "has already been associated: ignored!"); 387 } 388 389 394 public synchronized void addConnectionEventListener( 395 ConnectionEventListener listener) { 396 if (listeners == null) 397 listeners = new ArrayList (); 398 if (Debug.ON) 399 logger.log(BasicLevel.DEBUG, "Associates ConnectionEventListener: " 400 + listener); 401 if (!listeners.contains(listener)) 402 listeners.add(listener); 403 else 404 logger.log(BasicLevel.WARN, "ConnectionEventListener: " + listener 405 + "has already been associated: ignored!"); 406 } 407 408 413 public synchronized void removeConnectionEventListener( 414 ConnectionEventListener listener) { 415 if (listeners == null) { 416 logger.log(BasicLevel.WARN, 417 "No associated ConnectionEventListener: ignored!"); 418 return; 419 } 420 int ind = listeners.indexOf(listener); 421 if (Debug.ON) 422 logger.log(BasicLevel.DEBUG, 423 "Index within the listeners: " + ind); 424 if (ind == -1) 425 logger.log(BasicLevel.WARN, "ConnectionEventListener" + listener 426 + "not associated here: ignored!"); 427 else 428 listeners.remove(ind); 429 } 430 431 434 public synchronized XAResource getXAResource() throws ResourceException { 435 logger.log(BasicLevel.DEBUG, "getXAResource()"); 436 if (localTransactionPM != null) { 437 throw new ResourceException ( 438 "Try switching to XA mode while running a LocalTransaction."); 439 } 440 if (defaultPM != null) { 441 defaultPM.close(); 442 defaultPM = null; 443 } 444 return this; 445 } 446 447 public LocalTransaction getLocalTransaction() throws ResourceException { 448 return this; 449 } 450 451 public ManagedConnectionMetaData getMetaData() throws ResourceException { 452 return this; 453 } 454 455 458 public void setLogWriter(PrintWriter writer) throws ResourceException { 459 throw new ResourceException ("JDO Connector: logging to PrintWriter not supported yet."); 460 } 461 462 465 public PrintWriter getLogWriter() throws ResourceException { 466 throw new ResourceException ("JDO Connector: logging to PrintWriter not supported yet."); 467 } 468 469 470 473 476 public synchronized void begin() throws ResourceException { 477 if (localTransactionPM != null) { 478 throw new ResourceException ("JDO Connector: a LocalTransaction has already begun."); 479 } 480 try { 481 if (defaultPM != null) { 482 defaultPM.close(); 483 defaultPM = null; 484 } 485 localTransactionPM = (ProxyManager) 486 mcf.pmf.getPersistenceManager(); 487 localTransactionPM.currentTransaction().begin(); 488 if (Debug.ON) 489 logger.log(BasicLevel.DEBUG, "LocalTransaction begin - txContext: " 490 + localTransactionPM); 491 if (xac != null) 492 logger.log(BasicLevel.WARN, 493 "Begins a LocalTransaction on a ManagedConnection that runs in XA mode!"); 494 ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_STARTED); 495 if (listeners != null) { 496 synchronized(this) { 497 for (Iterator it = listeners.iterator(); it.hasNext();) { 498 ((ConnectionEventListener) it.next()).localTransactionStarted(ce); 499 } 500 } 501 } 502 } catch (JDOException fe) { 503 ResourceException re = new ResourceException ( 504 "JDO Connector: cannot begin LocalTransaction [nested exception]."); 505 re.setLinkedException(fe); 506 throw re; 507 } 508 } 509 510 513 public synchronized void commit() throws ResourceException { 514 if (localTransactionPM == null) 515 throw new ResourceException ("JDO Connector: no LocalTransaction has been begun."); 516 if (Debug.ON) 517 logger.log(BasicLevel.DEBUG, "LocalTransaction commit - txContext: " 518 + localTransactionPM); 519 try { 520 localTransactionPM.currentTransaction().commit(); 521 ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_COMMITTED); 522 if (listeners != null) { 523 synchronized(this) { 524 for (Iterator it = listeners.iterator(); it.hasNext();) { 525 ((ConnectionEventListener) it.next()).localTransactionCommitted(ce); 526 } 527 } 528 } 529 } catch (JDOException fe) { 530 ResourceException re = new ResourceException ( 531 "JDO Connector: cannot commit LocalTransaction [nested exception]."); 532 re.setLinkedException(fe); 533 throw re; 534 } finally { 535 localTransactionPM.close(); 536 localTransactionPM = null; 537 } 538 } 539 540 543 public synchronized void rollback() throws ResourceException { 544 if (localTransactionPM == null) 545 throw new ResourceException ("JDO Connector: no LocalTransaction has been begun."); 546 if (Debug.ON) 547 logger.log(BasicLevel.DEBUG, "LocalTransaction rollback - txContext: " 548 + localTransactionPM); 549 try { 550 localTransactionPM.currentTransaction().rollback(); 551 ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK); 552 if (listeners != null) { 553 synchronized(this) { 554 for (Iterator it = listeners.iterator(); it.hasNext();) { 555 ((ConnectionEventListener) it.next()).localTransactionRolledback(ce); 556 } 557 } 558 } 559 } catch (JDOException fe) { 560 ResourceException re = new ResourceException ( 561 "JDO Connector: cannot rollback LocalTransaction [nested exception]."); 562 re.setLinkedException(fe); 563 throw re; 564 } finally { 565 localTransactionPM.close(); 566 localTransactionPM = null; 567 } 568 } 569 570 571 574 578 public void start(Xid xid, int i) throws XAException { 579 try { 580 switch(i) { 581 case XAResource.TMRESUME: 582 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 583 logger.log(BasicLevel.DEBUG, "start(" + xid + ", TMRESUME)"); 584 } 585 xac = getXAContext(xid, 1); 586 if (xac.pm != null) { 587 mcf.pmf.bindPM2Thread(xac.pm); 588 } 589 break; 590 case XAResource.TMJOIN: 591 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 592 logger.log(BasicLevel.DEBUG, "start(" + xid + ", TMJOIN)"); 593 } 594 xac = getXAContext(xid, 1); 595 break; 596 case XAResource.TMNOFLAGS: 597 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 598 logger.log(BasicLevel.DEBUG, "start(" + xid + ", TMNOFLAGS)"); 599 } 600 xac = getXAContext(xid, 0); 601 break; 602 default: 603 String msg = "Unexpected flag: " + i; 604 logger.log(BasicLevel.ERROR, msg); 605 throw new XAException (msg); 606 } 607 xac.status = XAContext.STARTED; 608 } catch (XAException e) { 609 logger.log(BasicLevel.ERROR, 610 "Error in the Jdo XAResource starting (" + i + ")", e); 611 throw e; 612 } catch (RuntimeException e) { 613 logger.log(BasicLevel.ERROR, 614 "Error in the Jdo XAResource starting (" + i + ")", e); 615 throw e; 616 } 617 } 618 619 622 public void end(Xid xid, int i) throws XAException { 623 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 624 logger.log(BasicLevel.DEBUG, "xid=" + xid); 625 } 626 XAContext _xac = getXAContext(xid, 2); 627 if (_xac != null) { 628 _xac.status = XAContext.ENDED; 629 if (xac == _xac) { 630 xac = null; 631 } 632 } } 634 635 642 public boolean isSameRM(XAResource resource) throws XAException { 643 boolean res = (resource instanceof JdoManagedConnection) 644 && ((JdoManagedConnection) resource).mcf == mcf; 645 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 646 logger.log(BasicLevel.DEBUG, "isSameRM(" + resource + "): " + res); 647 } 648 return res; 649 } 650 651 653 656 public int prepare(Xid xid) throws XAException { 657 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 658 logger.log(BasicLevel.DEBUG, "prepare(" + xid + ")"); 659 } 660 XAContext _xac = getXAContext(xid, 1); 661 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 662 if (_xac.pm == null) { 663 logger.log(BasicLevel.DEBUG, "prepare(" + xid 664 + "): no PersistenceManager"); 665 } else { 666 logger.log(BasicLevel.DEBUG, "prepare(" + xid 667 + "): speedo Tx status=" 668 + ((org.objectweb.speedo.workingset.api.Transaction) 669 _xac.pm.currentTransaction()).getStatus()); 670 } 671 } 672 return XAResource.XA_OK; 673 } 674 675 679 public void commit(Xid xid, boolean b) throws XAException { 680 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 681 logger.log(BasicLevel.DEBUG, "commit(" + xid + ", 1PC: " + b + ")"); 682 } 683 XAContext _xac = mcf.releaseXAContext(xid, true); 684 if (xac == _xac) { 685 this.xac = null; 686 } 687 } 688 689 693 public void rollback(Xid xid) throws XAException { 694 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 695 logger.log(BasicLevel.DEBUG, "rollback(" + xid + ")"); 696 } 697 XAContext _xac = mcf.releaseXAContext(xid, true); 698 if (xac == _xac) { 699 this.xac = null; 700 } 701 } 702 703 public void forget(Xid xid) throws XAException { 704 XAContext _xac = mcf.releaseXAContext(xid, false); 705 if (xac == _xac) { 706 this.xac = null; 707 } 708 } 709 710 714 public Xid [] recover(int i) throws XAException { 715 return new Xid [0]; 716 } 717 718 public int getTransactionTimeout() throws XAException { 719 return 0; 720 } 721 722 public boolean setTransactionTimeout(int i) throws XAException { 723 return false; 724 } 725 726 } | Popular Tags |