| 1 25 26 27 package org.objectweb.jonas.resource; 28 29 import java.io.PrintWriter ; 30 import java.sql.Connection ; 31 import java.sql.PreparedStatement ; 32 import java.sql.ResultSet ; 33 import java.sql.SQLException ; 34 import java.util.Enumeration ; 35 import java.util.HashSet ; 36 import java.util.Hashtable ; 37 import java.util.Iterator ; 38 import java.util.Properties ; 39 import java.util.Set ; 40 import java.util.Vector ; 41 42 import javax.naming.Context ; 43 import javax.naming.NamingException ; 44 import javax.resource.ResourceException ; 45 import javax.resource.spi.ConnectionEvent ; 46 import javax.resource.spi.ConnectionEventListener ; 47 import javax.resource.spi.ConnectionManager ; 48 import javax.resource.spi.ConnectionRequestInfo ; 49 import javax.resource.spi.ManagedConnection ; 50 import javax.resource.spi.ManagedConnectionFactory ; 51 import javax.resource.spi.ResourceAllocationException ; 52 import javax.resource.spi.ValidatingManagedConnectionFactory ; 53 import javax.security.auth.Subject ; 54 import javax.transaction.RollbackException ; 55 import javax.transaction.Transaction ; 56 import javax.transaction.xa.XAResource ; 57 58 import org.objectweb.jonas.resource.pool.api.Pool; 59 import org.objectweb.jonas.resource.pool.api.PoolMatchFactory; 60 import org.objectweb.jonas.resource.pool.lib.HArrayPool; 61 import org.objectweb.jotm.Current; 62 import org.objectweb.jotm.TransactionResourceManager; 63 import org.objectweb.transaction.jta.ResourceManagerEventListener; 64 import org.objectweb.transaction.jta.TransactionManager; 65 import org.objectweb.util.monolog.api.BasicLevel; 66 import org.objectweb.util.monolog.api.Logger; 67 import org.objectweb.util.monolog.api.LoggerFactory; 68 import org.objectweb.util.monolog.wrapper.printwriter.LoggerImpl; 69 70 76 public class ConnectionManagerImpl implements ConnectionEventListener , ConnectionManager , 77 PoolMatchFactory, SQLManager, 78 TransactionResourceManager { 79 80 83 protected static Logger trace = null; 84 87 protected static Logger poolTrace = null; 88 89 93 protected ResourceManagerEventListener rmel = null; 94 95 98 private String resourceBundleName = null; 99 100 103 protected TransactionManager tm; 104 105 109 protected Hashtable mc2mci = null; 110 111 114 private int mcMaxPoolSize = -1; 115 116 119 private int mcMinPoolSize = 0; 120 121 125 private ManagedConnectionFactory mcf; 126 130 private ValidatingManagedConnectionFactory vmcf = null; 131 132 135 protected Pool poolMCs = null; 136 137 141 protected Hashtable usedMCs = null; 142 143 146 static final int MAX_PSTMT_SIZE = 10; 147 148 151 private int maxPstmtPoolSize = MAX_PSTMT_SIZE; 152 153 156 private int jdbcConnLevel = 0; 157 160 private String jdbcConnTestStmt = ""; 161 162 165 protected Vector mcs = new Vector (); 166 167 170 protected Vector synchros = new Vector (); 171 172 176 private ResourceSpec rs = null; 177 178 181 private String transSupport = null; 182 183 186 public final static String RESOURCE_BUNDLE_NAME = "resourceBundleName"; 187 190 public final static String LOGGER = "org.objectweb.util.monolog.logger"; 191 194 public final static String POOL_LOGGER = "org.objectweb.util.monolog.logger_pool"; 195 198 public final static String LOGGER_FACTORY = "org.objectweb.util.monolog.loggerFactory"; 199 202 public final static String TRANSACTION_MANAGER = "transactionManager"; 203 206 public final static String RESOURCE_MANAGER_EVENT_LISTENER = "resourceManagerEventListener"; 207 210 public final static String RESOURCE_ADAPTER = "resourceAdapter"; 211 214 public final static String PRINT_WRITER = "printWriter"; 215 216 219 222 public final static String NO_TRANS_SUPPORT = "NoTransaction"; 223 226 public final static String LOCAL_TRANS_SUPPORT = "LocalTransaction"; 227 230 public final static String XA_TRANS_SUPPORT = "XATransaction"; 231 232 236 public final static int PSWRAP_1 = 1; 237 public final static int PSWRAP_2 = 2; 238 public final static int PSWRAP_3 = 3; 239 public final static int PSWRAP_4 = 4; 240 public final static int PSWRAP_5 = 5; 241 242 246 private ManagedConnection jotmMc = null; 247 250 private XAResource jotmXar = null; 251 254 private String xaName = null; 255 256 259 private boolean isEnabledDebug = false; 260 261 262 266 public ConnectionManagerImpl(String transSupport) { 267 if (transSupport.length() == 0) { 268 transSupport = NO_TRANS_SUPPORT; 269 } else { 270 this.transSupport = transSupport; 271 } 272 } 273 274 280 public void setLogger(Logger l) { 281 trace = l; 282 isEnabledDebug = trace.isLoggable(BasicLevel.DEBUG); 283 } 284 285 286 292 public void setLoggerFactory(LoggerFactory lf) { 293 trace = lf.getLogger("org.objectweb.resource.server"); 294 isEnabledDebug = trace.isLoggable(BasicLevel.DEBUG); 295 } 296 297 298 304 public void setPrintWriter(PrintWriter pw) { 305 trace = new LoggerImpl(pw); 306 } 307 308 309 315 public void setResourceManagerEventListener( 316 ResourceManagerEventListener rmel) { 317 this.rmel = rmel; 318 } 319 320 321 327 public void setTransactionManager(TransactionManager tm) { 328 this.tm = tm; 329 } 330 331 332 340 public void setResourceAdapter(ManagedConnectionFactory tmcf) 341 throws Exception { 342 setResourceAdapter(tmcf, new ConnectionManagerPoolParams()); 343 } 344 345 354 public void setResourceAdapter(ManagedConnectionFactory tmcf, 355 ConnectionManagerPoolParams cmpp) 356 throws Exception { 357 358 if (cmpp.getPoolMax() != 0) { 360 mcMaxPoolSize = cmpp.getPoolMax(); 361 } 362 if (cmpp.getPoolMin() > 0) { 363 mcMinPoolSize = cmpp.getPoolMin(); 364 } 365 366 jdbcConnLevel = cmpp.getJdbcConnLevel(); 368 jdbcConnTestStmt = cmpp.getJdbcConnTestStmt(); 369 370 mcf = tmcf; 371 if (mcf instanceof ValidatingManagedConnectionFactory ) { 372 vmcf = (ValidatingManagedConnectionFactory ) mcf; 373 } 374 375 poolMCs = new HArrayPool(poolTrace); 376 poolMCs.setMatchFactory(this); 377 poolMCs.setMaxSize(mcMaxPoolSize); 378 poolMCs.setMinSize(mcMinPoolSize); 379 poolMCs.setInitSize(cmpp.getPoolInit()); 380 381 if (cmpp.getPoolMaxAge() > 0) { 382 int min = (int) (cmpp.getPoolMaxAge() / 60); 383 poolMCs.setMaxAge(min); 384 } else { 385 poolMCs.setMaxAge(cmpp.getPoolMaxAgeMinutes()); 386 } 387 388 if (cmpp.getPoolMaxOpentime() > 0) { 389 poolMCs.setMaxOpentime(cmpp.getPoolMaxOpentime()); 390 } 391 poolMCs.setMaxWaiters(cmpp.getPoolMaxWaiters()); 392 if (cmpp.getPoolMaxWaittime() > 0) { 393 poolMCs.setMaxWaitTime(cmpp.getPoolMaxWaittime()); 394 } 395 396 poolMCs.startMonitor(); 397 poolMCs.setSamplingPeriod(cmpp.getPoolSamplingPeriod()); 398 maxPstmtPoolSize = cmpp.getPstmtMax(); 399 400 usedMCs = new Hashtable (); 401 rs = new ResourceSpec(null, null); 402 403 if (isEnabledDebug) { 404 trace.log(BasicLevel.DEBUG, ""); 405 } 406 } 407 408 409 424 public void init(Context ctx) throws Exception { 425 mc2mci = new Hashtable (); 426 427 String resourceBundleName = null; 430 try { 431 resourceBundleName = (String ) ctx.lookup(RESOURCE_BUNDLE_NAME); 432 } catch (NamingException e) { 433 } 434 435 try { 437 trace = (Logger) ctx.lookup(LOGGER); 438 poolTrace = (Logger) ctx.lookup(POOL_LOGGER); 439 } catch (NamingException e) { 440 } 441 442 if (trace == null) { 443 try { 444 setLoggerFactory((LoggerFactory) ctx.lookup(LOGGER_FACTORY)); 445 } catch (NamingException e2) { 446 } 447 } 448 if (trace == null) { 449 PrintWriter pw = null; 450 try { 451 pw = (PrintWriter ) ctx.lookup(PRINT_WRITER); 452 } catch (NamingException e3) { 453 } 454 setPrintWriter(pw); 455 } 456 457 if (!transSupport.equalsIgnoreCase(NO_TRANS_SUPPORT)) { 458 tm = (TransactionManager) ctx.lookup(TRANSACTION_MANAGER); 460 } 461 462 try { 464 rmel = (ResourceManagerEventListener) 465 ctx.lookup(RESOURCE_MANAGER_EVENT_LISTENER); 466 } catch (NamingException ne) { 467 } 468 469 try { 472 setResourceAdapter( 473 (ManagedConnectionFactory ) ctx.lookup(RESOURCE_ADAPTER)); 474 } catch (NamingException ne) { 475 } 476 } 477 478 479 484 public void cleanResourceAdapter() throws ResourceException { 485 PreparedStatementWrapper pw = null; 487 while (mcs != null && mcs.size() > 0) { 488 MCInfo mci = (MCInfo) mcs.remove(0); 489 mci.usedCs.clear(); 490 synchronized (mci.pStmts) { 491 while (mci.pStmts != null && mci.pStmts.size() > 0) { 493 pw = (PreparedStatementWrapper) mci.pStmts.remove(0); 494 try { 495 pw.destroy(); 496 } catch (Exception ex) { 497 } 498 } 499 } 500 try { 501 mc2mci.remove(mci.mc); 502 mci.mc.destroy(); 503 } catch (Exception ex) { 504 } 505 } 506 if (usedMCs != null) { 507 for (Enumeration en = usedMCs.keys(); en.hasMoreElements();) { 508 Transaction tx = (Transaction ) en.nextElement(); 509 MCInfo mci = (MCInfo) usedMCs.get(tx); 510 if (mci == null) { 511 continue; 512 } 513 if (mci.rmeCalled) { 514 mci.rme.isValid = false; 515 rmel.connectionClosed(mci.rme); 516 mci.rmeCalled = false; 517 } 518 mci.usedCs.clear(); 519 synchronized (mci.pStmts) { 521 while (mci.pStmts != null && mci.pStmts.size() > 0) { 522 pw = (PreparedStatementWrapper) mci.pStmts.remove(0); 523 try { 524 pw.destroy(); 525 } catch (Exception ex) { 526 } 527 } 528 } 529 try { 530 mc2mci.remove(mci.mc); 531 mci.mc.destroy(); 532 } catch (Exception ex) { 533 } 534 } 535 } 536 while (synchros != null && synchros.size() > 0) { 537 MCInfo mci = (MCInfo) synchros.remove(0); 538 mci.usedCs.clear(); 539 synchronized (mci.pStmts) { 541 while (mci.pStmts != null && mci.pStmts.size() > 0) { 542 pw = (PreparedStatementWrapper) mci.pStmts.remove(0); 543 try { 544 pw.destroy(); 545 } catch (Exception ex) { 546 } 547 } 548 } 549 try { 550 mc2mci.remove(mci.mc); 551 mci.mc.destroy(); 552 } catch (Exception ex) { 553 } 554 } 555 } 556 557 558 565 public Object allocateConnection(ManagedConnectionFactory pMcf, ConnectionRequestInfo cxRequestInfo) 566 throws ResourceException { 567 568 MCInfo mci = null; 569 Transaction currentTx = null; 570 Object connection = null; 571 int retries = 0; 572 Subject subject = null; 573 574 while (connection == null && retries < 20) { 575 if (mcf != pMcf) { 576 throw new ResourceException ( 577 "This ConnectionManager doesn't manage this RA:" + mcf); 578 } 579 580 currentTx = null; 581 try { 582 if (tm != null) { 583 currentTx = tm.getTransaction(); 584 } 585 } catch (Exception e) { 586 trace.log(BasicLevel.ERROR, 587 "Impossible to get the current transaction", e, 588 "ConnectionManagerImpl", "allocateConnection"); 589 } 590 591 mci = (currentTx == null ? null : (MCInfo) usedMCs.get(currentTx)); 593 if (mci != null) { 594 if (mci.mc != null) { 595 if (isEnabledDebug) { 598 trace.log(BasicLevel.DEBUG, "MC (" + mci.mc + ") associated to the current Tx (" + currentTx + ") found"); 599 } 600 Set s = new HashSet (); 601 s.add(mci.mc); 602 if (mci.mc != mcf.matchManagedConnections(s, null, cxRequestInfo)) { 603 throw new ResourceException ( 604 "ConnectionManagerImpl.allocateConnection: illegal state : no mc is matched by mcf"); 605 } 606 if (isEnabledDebug) { 607 trace.log(BasicLevel.DEBUG, "XA Resource " + mci.getXAResource() 608 + " is already enlisted in Tx:" + mci.ctx); 609 } 610 } else { 611 trace.log(BasicLevel.INFO, "remnant of an old failed connection"); 613 mci.ctx = null; 614 mci = null; 615 usedMCs.remove(currentTx); 616 } 617 } 618 619 if (mci == null) { 620 623 rs.cxRequestInfo = cxRequestInfo; 625 if (subject == null && cxRequestInfo != null) { 626 } 628 try { 629 ManagedConnection mc = (ManagedConnection ) poolMCs.getResource(rs); 630 if (mc == null) { 631 throw new ResourceException ("ConnectionManagerImpl.allocateConnection: cannot allocate a ManagedConnection"); 632 } 633 mci = (MCInfo) mc2mci.get(mc); 634 if (mci == null) { 635 mci = new MCInfo(mc); 636 mc2mci.put(mc, mci); 637 } 638 if (isEnabledDebug) { 639 trace.log(BasicLevel.DEBUG, "get a MC from the ra pool, mc=" + mci.mc); 640 } 641 if (transSupport.equalsIgnoreCase(LOCAL_TRANS_SUPPORT)) { 642 if (mci.lw == null) { 643 mci.lw = new LocalXAWrapper(mci.mc.getLocalTransaction(), trace); 644 } 645 } else if (mci.lw != null) { 646 mci.lw = null; 647 } 648 if (!mci.connectionEventListener) { 649 mci.mc.addConnectionEventListener(this); 650 mci.connectionEventListener = true; 651 } 652 mci.synchro = null; 653 if (currentTx != null) { 656 if (isEnabledDebug) { 657 trace.log(BasicLevel.DEBUG, "Enlist the XA Resource " 658 + mci.getXAResource() + " in Tx:" 659 + currentTx); 660 } 661 currentTx.enlistResource(mci.getXAResource()); 662 usedMCs.put(currentTx, mci); 663 mci.ctx = currentTx; 664 } else { 665 mci.ctx = null; 668 mcs.add(mci); 670 if (!transSupport.equalsIgnoreCase(NO_TRANS_SUPPORT)) { 672 mci.rme = new RMEImpl(mci, trace); 673 if (isEnabledDebug) { 674 trace.log(BasicLevel.DEBUG, "Register the managed connection (no tx)"); 675 } 676 if (!mci.rmeCalled) { 678 mci.rme.isValid = true; 679 rmel.connectionOpened(mci.rme); 680 mci.rmeCalled = true; 681 } 682 } 683 } 684 } catch (ResourceException re) { 685 trace.log(BasicLevel.ERROR, re.getMessage(), re); 686 throw re; 687 } catch (Exception e) { 688 String err = "Error related allocation of ManagedConnection"; 689 trace.log(BasicLevel.ERROR, err, e); 690 throw new ResourceException (err, e); 691 } 692 693 } 694 695 connection = mci.mc.getConnection(null, cxRequestInfo); 697 mci.usedCs.add(connection); 699 if (connection instanceof java.sql.Connection ) { 700 try { 701 if (connection instanceof org.objectweb.jonas.jdbc.ConnectionImpl) { 703 ((org.objectweb.jonas.jdbc.ConnectionImpl) connection).setJonasInfo(mci, this); 704 } else { 705 connection = JonasSQLWrapper.createSQLWrapper(connection, mci, this, trace); 706 } 707 if (jdbcConnLevel > 0) { 709 try { 710 if (isEnabledDebug) { 711 trace.log(BasicLevel.DEBUG, "Check the JDBC connection"); 712 } 713 boolean isClosed = true; 714 if (connection instanceof org.objectweb.jonas.jdbc.ConnectionImpl) { 716 isClosed = ((org.objectweb.jonas.jdbc.ConnectionImpl) connection).isPhysicallyClosed(); 717 } else { 718 isClosed = ((Connection ) connection).isClosed(); 719 } 720 if (isClosed) { 721 connectionErrorOccurred(new ConnectionEvent (mci.mc, 722 ConnectionEvent.CONNECTION_ERROR_OCCURRED)); 723 connection = null; 724 retries++; 725 continue; 726 } 727 if (jdbcConnLevel > 1 && jdbcConnTestStmt != null 728 && jdbcConnTestStmt.length() > 0) { 729 if (isEnabledDebug) { 730 trace.log(BasicLevel.DEBUG, "retrying connection: " + jdbcConnTestStmt); 731 }
|