00001
00027 package org.objectweb.jonas.dbm;
00028
00029 import java.io.Serializable;
00030 import java.sql.Connection;
00031 import java.sql.SQLException;
00032 import java.util.HashMap;
00033 import java.util.Map;
00034
00035 import javax.naming.NamingException;
00036 import javax.naming.Reference;
00037 import javax.naming.Referenceable;
00038 import javax.naming.StringRefAddr;
00039 import javax.sql.ConnectionEvent;
00040 import javax.sql.ConnectionEventListener;
00041 import javax.sql.DataSource;
00042 import javax.sql.XAConnection;
00043 import javax.transaction.RollbackException;
00044 import javax.transaction.SystemException;
00045 import javax.transaction.Transaction;
00046 import javax.transaction.xa.XAResource;
00047
00048 import org.objectweb.jonas.common.Log;
00049 import org.objectweb.jonas.jdbc_xa.XADataSourceImpl;
00050 import org.objectweb.jonas.jtm.TransactionService;
00051 import org.objectweb.jonas.service.ServiceManager;
00052 import org.objectweb.transaction.jta.ResourceManagerEventListener;
00053 import org.objectweb.transaction.jta.TransactionManager;
00054 import org.objectweb.util.monolog.api.BasicLevel;
00055 import org.objectweb.util.monolog.api.Logger;
00056
00086 public class ConnectionManager
00087 implements DataSource,
00088 Referenceable,
00089 Serializable,
00090 ConnectionEventListener {
00091
00092 private static Logger logger = null;
00093
00094
00095
00096 private static Map cmList = new HashMap();
00097
00102 private TransactionManager tm = null;
00103
00108 private XADataSourceImpl xads = null;
00109
00114 private Pool pool = null;
00115
00119 public Pool getPool() {
00120 return pool;
00121 }
00122
00123
00124
00125
00126
00130 private String dSName = null;
00131
00135 private String datasourceName;
00136
00140 private String url = null;
00144 private String className = null;
00148 private String userName = null;
00152 private String password = null;
00153
00157 private int isolationLevel = -1;
00158 private String isolationStr = null;
00159
00163 private String currentMapperName = null;
00164
00169 private boolean isClient = false;
00170
00174 private String xaName = null;
00175 private String dsDescription = null;
00176
00177 private static ResourceManagerEventListener rmListener = null;
00178
00179
00180
00181
00182
00186 public ConnectionManager() throws Exception {
00187 logger = Log.getLogger(Log.JONAS_DBM_PREFIX);
00188
00189
00190 try {
00191
00192 ServiceManager sm = ServiceManager.getInstance();
00193 TransactionService ts = (TransactionService) sm.getTransactionService();
00194 tm = ts.getTransactionManager();
00195 } catch (Exception e) {
00196 throw e;
00197 }
00198
00199
00200 setRMEListener(tm);
00201
00202
00203
00204
00205 xads = new XADataSourceImpl();
00206 pool = new Pool(this, xads);
00207 }
00208
00214 public ConnectionManager(boolean isClient) throws Exception {
00215 logger = Log.getLogger(Log.JONAS_DBM_PREFIX);
00216 this.isClient = isClient;
00217 xads = new XADataSourceImpl();
00218 }
00219
00225 public boolean isClientCase() {
00226 return isClient;
00227 }
00228
00229
00230
00231
00232
00233 public void setRMEListener(ResourceManagerEventListener rmel) {
00234 rmListener = rmel;
00235 }
00236
00240 public String getDSName() {
00241 return dSName;
00242 }
00243
00247 public void setDSName(String s) {
00248 dSName = s;
00249 xads.setDataSourceName(s);
00250
00251 cmList.put(s, this);
00252 }
00253
00254 public String getUrl() {
00255 return url;
00256 }
00257 public void setUrl(String s) {
00258 url = s;
00259
00260 xads.setUrl(s);
00261 }
00262
00263 public String getClassName() {
00264 return className;
00265 }
00266 public void setClassName(String s) throws ClassNotFoundException {
00267 className = s;
00268
00269 xads.setClassName(s);
00270 }
00271
00272 public String getUserName() {
00273 return userName;
00274 }
00275 public void setUserName(String s) {
00276 userName = s;
00277
00278 xads.setUserName(s);
00279 }
00280
00281 public String getPassword() {
00282 return password;
00283 }
00284 public void setPassword(String s) {
00285 password = s;
00286
00287 xads.setPassword(s);
00288 }
00289
00290 public void setTransactionIsolation(String level) {
00291 logger.log(BasicLevel.DEBUG, level);
00292 if (level.equals("serializable")) {
00293 isolationLevel = Connection.TRANSACTION_SERIALIZABLE;
00294 } else if (level.equals("none")) {
00295 isolationLevel = Connection.TRANSACTION_NONE;
00296 } else if (level.equals("read_committed")) {
00297 isolationLevel = Connection.TRANSACTION_READ_COMMITTED;
00298 } else if (level.equals("read_uncommitted")) {
00299 isolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
00300 } else if (level.equals("repeatable_read")) {
00301 isolationLevel = Connection.TRANSACTION_REPEATABLE_READ;
00302 } else {
00303 isolationStr = "default";
00304 return;
00305 }
00306
00307 isolationStr = level;
00308 xads.setTransactionIsolation(isolationLevel);
00309 }
00310
00311 public String getTransactionIsolation() {
00312 logger.log(BasicLevel.DEBUG, isolationStr);
00313 return isolationStr;
00314 }
00315
00316 public void setMapperName(String mappername) {
00317 currentMapperName = mappername;
00318 }
00319
00320 public String getMapperName() {
00321 return currentMapperName;
00322 }
00323
00338 public void poolConfigure(String connchecklevel,
00339 String connmaxage,
00340 String maxopentime,
00341 String connteststmt,
00342 String minconpool,
00343 String maxconpool,
00344 String maxwaittime,
00345 String maxwaiters,
00346 String samplingperiod) {
00347
00348
00349 pool.setCheckLevel((new Integer(connchecklevel)).intValue());
00350
00351 pool.setMaxAge((new Integer(connmaxage)).intValue());
00352 pool.setMaxOpenTime((new Integer(maxopentime)).intValue());
00353 pool.setTestStatement(connteststmt);
00354 pool.setPoolMin((new Integer(minconpool)).intValue());
00355 pool.setPoolMax((new Integer(maxconpool)).intValue());
00356 pool.setMaxWaitTime((new Integer(maxwaittime)).intValue());
00357 pool.setMaxWaiters((new Integer(maxwaiters)).intValue());
00358 pool.setSamplingPeriod((new Integer(samplingperiod)).intValue());
00359 if (logger.isLoggable(BasicLevel.DEBUG)) {
00360 logger.log(BasicLevel.DEBUG, "ConnectionManager configured with:");
00361 logger.log(BasicLevel.DEBUG, " jdbcConnCheckLevel = " + connchecklevel);
00362 logger.log(BasicLevel.DEBUG, " jdbcConnMaxAge = " + connmaxage);
00363 logger.log(BasicLevel.DEBUG, " jdbcMaxOpenTime = " + maxopentime);
00364 logger.log(BasicLevel.DEBUG, " jdbcTestStmt = " + connteststmt);
00365 logger.log(BasicLevel.DEBUG, " minConPool = " + pool.getPoolMin());
00366 logger.log(BasicLevel.DEBUG, " maxConPool = " + pool.getPoolMax());
00367 logger.log(BasicLevel.DEBUG, " maxWaitTime = " + pool.getMaxWaitTime());
00368 logger.log(BasicLevel.DEBUG, " maxWaiters = " + pool.getMaxWaiters());
00369 logger.log(BasicLevel.DEBUG, " samplingPeriod = " + pool.getSamplingPeriod());
00370 }
00371 }
00372
00373
00374
00375
00376
00384 public Connection getConnection() throws SQLException {
00385 return getConnection(userName, password);
00386 }
00387
00398 public Connection getConnection(String username, String password) throws SQLException {
00399 XAConnection xac = null;
00400 Transaction tx = null;
00401 try {
00402 tx = tm.getTransaction();
00403 } catch (NullPointerException n) {
00404
00405 logger.log(BasicLevel.ERROR, "ConnectionManager: should not be used outside a JOnAS Server");
00406 } catch (SystemException e) {
00407 logger.log(BasicLevel.ERROR, "ConnectionManager: getTransaction failed:" + e);
00408 }
00409 if (logger.isLoggable(BasicLevel.DEBUG)) {
00410 logger.log(BasicLevel.DEBUG, "Tx = " + tx);
00411 }
00412
00413
00414 PoolItem pi = pool.openConnection(username, (Transaction) tx);
00415
00416 xac = pi.getXACon();
00417
00418 Connection ret = xac.getConnection();
00419
00420 if (tx != null) {
00421 if (pi.getOpenCount() == 1) {
00422 try {
00423 if (logger.isLoggable(BasicLevel.DEBUG)) {
00424 logger.log(BasicLevel.DEBUG, "enlist XAResource on " + tx);
00425 }
00426 tx.enlistResource(xac.getXAResource());
00427
00428 ret.setAutoCommit(false);
00429 } catch (RollbackException e) {
00430
00431
00432 logger.log(BasicLevel.WARN, "XAResource enlisted, but tx is marked rollback");
00433 } catch (IllegalStateException e) {
00434
00435 ret.setAutoCommit(true);
00436 } catch (Exception e) {
00437 logger.log(BasicLevel.ERROR, "Cannot enlist XAResource:" + e);
00438 logger.log(BasicLevel.ERROR, "Connection will not be enlisted in a transaction");
00439
00440 throw new SQLException("Cannot enlist XAResource");
00441 }
00442 }
00443 } else {
00444 ret.setAutoCommit(true);
00445 }
00446
00447
00448 if (!pi.isRME()) {
00449 logger.log(BasicLevel.DEBUG, "register this connection to the TM.");
00450 pi.setRME(true);
00451 rmListener.connectionOpened(pi);
00452 }
00453
00454 return ret;
00455 }
00456
00473 public java.io.PrintWriter getLogWriter() throws SQLException {
00474 return xads.getLogWriter();
00475 }
00476
00477
00494 public void setLogWriter(java.io.PrintWriter out) throws SQLException {
00495 xads.setLogWriter(out);
00496 }
00497
00498
00511 public void setLoginTimeout(int seconds) throws SQLException {
00512 xads.setLoginTimeout(seconds);
00513 }
00514
00526 public int getLoginTimeout() throws SQLException {
00527 return xads.getLoginTimeout();
00528 }
00529
00530
00531
00532
00533
00539 public void connectionClosed(ConnectionEvent event) {
00540 logger.log(BasicLevel.DEBUG, " ");
00541
00542 XAConnection xac = (XAConnection) event.getSource();
00543 PoolItem pi = pool.closeConnection(xac, XAResource.TMSUCCESS);
00544
00545
00546
00547 if (pi != null && pi.isRME()) {
00548 logger.log(BasicLevel.DEBUG, "unregister this connection to the TM.");
00549 pi.setRME(false);
00550 rmListener.connectionClosed(pi);
00551 }
00552 }
00553
00559 public void connectionErrorOccurred(ConnectionEvent event) {
00560 logger.log(BasicLevel.DEBUG, "");
00561
00562 XAConnection xac = (XAConnection) event.getSource();
00563 PoolItem pi = pool.closeConnection(xac, XAResource.TMFAIL);
00564
00565
00566
00567 if (pi != null && pi.isRME()) {
00568 logger.log(BasicLevel.DEBUG, "unregister this connection to the TM.");
00569 pi.setRME(false);
00570 rmListener.connectionErrorOccured(pi);
00571 }
00572 }
00573
00574
00575
00576
00577
00586 public Reference getReference() throws NamingException {
00587
00588 Reference ref = new Reference (this.getClass().getName(),
00589 "org.objectweb.jonas.dbm.DataSourceFactory",
00590 null);
00591
00592 ref.add(new StringRefAddr("datasource.name", getDSName()));
00593 ref.add(new StringRefAddr("datasource.url", getUrl()));
00594 ref.add(new StringRefAddr("datasource.classname", getClassName()));
00595 ref.add(new StringRefAddr("datasource.username", getUserName()));
00596 ref.add(new StringRefAddr("datasource.password", getPassword()));
00597 ref.add(new StringRefAddr("datasource.isolationlevel", getTransactionIsolation()));
00598 ref.add(new StringRefAddr("datasource.mapper", getMapperName()));
00599 Integer checklevel = new Integer(pool.getCheckLevel());
00600 ref.add(new StringRefAddr("connchecklevel", checklevel.toString()));
00601 Integer maxage = new Integer(pool.getMaxAge());
00602 ref.add(new StringRefAddr("connmaxage", maxage.toString()));
00603 Integer maxopentime = new Integer(pool.getMaxOpenTime());
00604 ref.add(new StringRefAddr("maxopentime", maxopentime.toString()));
00605 ref.add(new StringRefAddr("connteststmt", pool.getTestStatement()));
00606 Integer minpool = new Integer(pool.getPoolMin());
00607 ref.add(new StringRefAddr("minconpool", minpool.toString()));
00608 Integer maxpool = new Integer(pool.getPoolMax());
00609 ref.add(new StringRefAddr("maxconpool", maxpool.toString()));
00610 Integer maxwaittime = new Integer(pool.getMaxWaitTime());
00611 ref.add(new StringRefAddr("maxwaittime", maxwaittime.toString()));
00612 Integer maxwaiters = new Integer(pool.getMaxWaiters());
00613 ref.add(new StringRefAddr("maxwaiters", maxwaiters.toString()));
00614 Integer samplingperiod = new Integer(pool.getSamplingPeriod());
00615 ref.add(new StringRefAddr("samplingperiod", samplingperiod.toString()));
00616 return ref;
00617 }
00618
00622 public static ConnectionManager getConnectionManager(String dsname) {
00623
00624 ConnectionManager cm = (ConnectionManager) cmList.get(dsname);
00625 return cm;
00626 }
00627
00628 public void closeAllConnection() {
00629 logger.log(BasicLevel.DEBUG, "");
00630 pool.closeAllConnections();
00631 }
00632
00633 public static ResourceManagerEventListener getResourceManagerEventListener() {
00634 return rmListener;
00635 }
00636
00640 public String getDatasourceName() {
00641 return datasourceName;
00642 }
00643
00647 public void setDatasourceName(String s) {
00648 datasourceName = s;
00649 }
00650
00654 public String getDataSourceDescription() {
00655 return dsDescription;
00656 }
00657
00661 public void setDataSourceDescription(String dsDesc) {
00662 dsDescription = dsDesc;
00663 }
00668 public Integer getCurrentOpened() {
00669 return new Integer(pool.getCurrentOpened());
00670 }
00671 }