00001
00027 package org.objectweb.jonas.dbm;
00028
00029 import java.io.FileNotFoundException;
00030 import java.util.Enumeration;
00031 import java.util.Hashtable;
00032 import java.util.Iterator;
00033 import java.util.List;
00034 import java.util.Properties;
00035 import java.util.Set;
00036 import java.util.StringTokenizer;
00037 import java.util.Vector;
00038
00039 import javax.management.InstanceNotFoundException;
00040 import javax.management.MBeanRegistrationException;
00041 import javax.management.MBeanServer;
00042 import javax.management.MalformedObjectNameException;
00043 import javax.management.ObjectName;
00044 import javax.management.modelmbean.ModelMBean;
00045 import javax.naming.Context;
00046 import javax.naming.InitialContext;
00047 import javax.naming.NamingException;
00048
00049 import org.apache.commons.modeler.ManagedBean;
00050 import org.apache.commons.modeler.Registry;
00051 import org.objectweb.jonas.common.JModule;
00052 import org.objectweb.jonas.common.JProp;
00053 import org.objectweb.jonas.common.Log;
00054 import org.objectweb.jonas.jmx.J2eeObjectName;
00055 import org.objectweb.jonas.jmx.JmxService;
00056 import org.objectweb.jonas.jmx.JonasObjectName;
00057 import org.objectweb.jonas.jtm.TransactionService;
00058 import org.objectweb.jonas.management.JonasMBeanTools;
00059 import org.objectweb.jonas.service.AbsServiceImpl;
00060 import org.objectweb.jonas.service.ServiceException;
00061 import org.objectweb.jonas.service.ServiceManager;
00062 import org.objectweb.util.monolog.api.BasicLevel;
00063 import org.objectweb.util.monolog.api.Logger;
00064
00085 public class DataBaseServiceImpl extends AbsServiceImpl implements DataBaseService, DataBaseServiceImplMBean {
00086
00087 static private Logger logger = null;
00088
00089
00090 private Vector cmList = new Vector();
00091
00092
00093 private Hashtable bindedDatasources = new Hashtable();
00094
00095
00096 private Vector dataSourceNames = new Vector();
00097
00098
00099 private TransactionService transactionService = null;
00100
00101
00102 private Context ictx = null;
00103
00104
00105 static final String DATASOURCES = "jonas.service.dbm.datasources";
00106 static final String CLASS = "jonas.service.dbm.class";
00107
00108
00109 static final String NAME = "datasource.name";
00110 static final String CLASSNAME = "datasource.classname";
00111 static final String DEF_CLASSNAME = "no class name";
00112 static final String URL = "datasource.url";
00113 static final String DEF_URL = "no url";
00114 static final String DESCRIPTION = "datasource.description";
00115 static final String DEF_DESCRIPTION = "no desc";
00116 static final String USERNAME = "datasource.username";
00117 static final String DEF_USERNAME = "";
00118 static final String PASSWORD = "datasource.password";
00119 static final String DEF_PASSWORD = "";
00120 static final String ISOLATIONLEVEL = "datasource.isolationlevel";
00121 static final String DEF_ISOLATIONLEVEL = "";
00122 static final String MAPPERNAME = "datasource.mapper";
00123 static final String DEF_MAPPERNAME = "rdb";
00124
00125
00126 public static final String CONNCHECKLEVEL = "jdbc.connchecklevel";
00127 static final String DEF_CONNCHECKLEVEL = "1";
00128 public static final String CONNMAXAGE = "jdbc.connmaxage";
00129 static final String DEF_CONNMAXAGE = "1440";
00130 public static final String MAXOPENTIME = "jdbc.maxopentime";
00131 static final String DEF_MAXOPENTIME = "1440";
00132 public static final String CONNTESTSTMT = "jdbc.connteststmt";
00133 static final String DEF_CONNTESTSTMT = "SELECT 1";
00134 static final String MINCONPOOL = "jdbc.minconpool";
00135 static final String DEF_MINCONPOOL = "0";
00136 static final String MAXCONPOOL = "jdbc.maxconpool";
00137 static final String DEF_MAXCONPOOL = "-1";
00138 static final String MAXWAITTIME = "jdbc.maxwaittime";
00139 static final String DEF_MAXWAITTIME = "10";
00140 static final String MAXWAITERS = "jdbc.maxwaiters";
00141 static final String DEF_MAXWAITERS = "1000";
00142 static final String SAMPLINGPERIOD = "jdbc.samplingperiod";
00143 static final String DEF_SAMPLINGPERIOD = "60";
00144
00145
00146
00150 public static final String JDBCResourceName = "JDBCResource";
00154 private JDBCResource jdbcResourceMBean = null;
00155 private Registry oRegistry = null;
00156 private ManagedBean oManaged = null;
00157 private ModelMBean oMBean = null;
00158 private MBeanServer mbeanServer = null;
00159 private String domainName = null;
00160 private String serverName = null;
00161
00162
00163
00164
00165
00166
00171 public void doInit(Context ctx) throws ServiceException {
00172 logger = Log.getLogger(Log.JONAS_DBM_PREFIX);
00173
00174 try {
00175 ictx = new InitialContext();
00176 } catch (NamingException e) {
00177 logger.log(BasicLevel.ERROR, "Cannot create initial context when DataBase service initializing");
00178 throw new ServiceException("Cannot create initial context when DataBase service initializing", e);
00179 }
00180
00181
00182 String ds = null;
00183 try {
00184 ds = (String) ctx.lookup(DATASOURCES);
00185 } catch (NamingException e) {
00186
00187 }
00188 if (ds != null) {
00189 StringTokenizer st = new StringTokenizer(ds, ",");
00190 while (st.hasMoreTokens()) {
00191 dataSourceNames.add(st.nextToken().trim());
00192 }
00193 }
00194
00195
00196 try {
00197 transactionService =
00198 (TransactionService) ServiceManager.getInstance().getTransactionService();
00199 } catch (ServiceException se) {
00200 logger.log(BasicLevel.ERROR, "Cannot get the Transaction service: " + se);
00201 throw se;
00202 } catch (Exception e) {
00203 logger.log(BasicLevel.ERROR, "Cannot get the Transaction service: " + e);
00204 throw new ServiceException("Cannot get the Transaction service: ", e);
00205 }
00206
00207
00208 try {
00209 mbeanServer =
00210 ((JmxService) ServiceManager.getInstance().getJmxService()).getJmxServer();
00211 } catch (Exception e) {
00212
00213 mbeanServer = null;
00214 }
00215
00216 oRegistry = JonasMBeanTools.getRegistry();
00217
00218 logger.log(BasicLevel.DEBUG, "DataBaseService initialized");
00219 }
00220
00225 public void doStart() throws ServiceException {
00226
00227
00228
00229
00230
00231
00232 domainName = getDomainName();
00233 serverName = getJonasServerName();
00234 if (mbeanServer != null) {
00235 try {
00236 ObjectName onJDBCResource = J2eeObjectName.JDBCResource(domainName, serverName, JDBCResourceName);
00237 jdbcResourceMBean = new JDBCResource(onJDBCResource.toString());
00238 oManaged = oRegistry.findManagedBean("JDBCResource");
00239 oMBean = oManaged.createMBean(jdbcResourceMBean);
00240 if (logger.isLoggable(BasicLevel.DEBUG)) {
00241 logger.log(BasicLevel.DEBUG, "JDBResource J2EEResource created");
00242 }
00243 mbeanServer.registerMBean(oMBean, onJDBCResource);
00244 } catch (Exception e) {
00245 e.printStackTrace();
00246 logger.log(BasicLevel.ERROR, "JOnAS: Cannot register JDBCResource mBean" + e);
00247 }
00248 }
00249
00250
00251 String dsName = null;
00252 for (int i = 0; i < dataSourceNames.size(); i++) {
00253 dsName = (String) dataSourceNames.elementAt(i);
00254 try {
00255 JProp prop = JProp.getInstance(dsName);
00256 logger.log(BasicLevel.DEBUG, "Creating Datasource " + dsName);
00257 createDataSource(dsName, prop.getConfigFileEnv());
00258 } catch (Exception e) {
00259 logger.log(BasicLevel.ERROR, "JOnAS: Cannot create datasource: " + dsName + " " + e);
00260 logger.log(BasicLevel.ERROR, "Please check if " + dsName + ".properties is available");
00261 }
00262 }
00263
00264
00265 try {
00266 mbeanServer.registerMBean(this, JonasObjectName.databaseService());
00267 } catch (ServiceException se) {
00268
00269 } catch (Exception e) {
00270 logger.log(BasicLevel.ERROR, "DataBaseService: Cannot start the DataBase service:\n" + e);
00271 throw new ServiceException("DataBaseService: Cannot start the DataBase service", e);
00272 }
00273
00274 logger.log(BasicLevel.DEBUG, "DataBaseService started");
00275 }
00276
00281 public void doStop() throws ServiceException {
00282 try {
00283 unbindDataSources();
00284 } catch (NamingException e) {
00285 logger.log(BasicLevel.ERROR, "Cannot unbind datasources " + e);
00286 throw new ServiceException("Cannot unbind datasources ", e);
00287 }
00288
00289 try {
00290 if (mbeanServer != null) {
00291
00292 mbeanServer.unregisterMBean(JonasObjectName.databaseService());
00293
00294 ObjectName onJDBCResource = J2eeObjectName.JDBCResource(domainName, serverName, JDBCResourceName);
00295 mbeanServer.unregisterMBean(onJDBCResource);
00296 }
00297 } catch (ServiceException se) {
00298
00299 } catch (Exception e) {
00300 logger.log(BasicLevel.ERROR, "EJBService: Cannot stop the DataBase service:\n"+e);
00301 throw new ServiceException("DataBaseService: Cannot stop the DataBase service",e);
00302 }
00303
00304 logger.log(BasicLevel.DEBUG, "DataBaseService stopped");
00305 }
00306
00307
00308
00309
00310
00316 public void createDataSource(String datasourceName, Properties dsd) throws Exception {
00317
00318 String dsName = dsd.getProperty(NAME);
00319 if (dsName != null) {
00320 dsName = dsName.trim();
00321 } else {
00322 logger.log(BasicLevel.ERROR, "");
00323 throw new ServiceException("Cannot create datasource as JNDI name not provided");
00324 }
00325 String className = dsd.getProperty(CLASSNAME, DEF_CLASSNAME).trim();
00326 String url = dsd.getProperty(URL, DEF_URL).trim();
00327 String description = dsd.getProperty(DESCRIPTION, DEF_DESCRIPTION).trim();
00328 String user = dsd.getProperty(USERNAME, DEF_USERNAME).trim();
00329 String password = dsd.getProperty(PASSWORD, DEF_PASSWORD).trim();
00330 String connCheckLevel = dsd.getProperty(CONNCHECKLEVEL, DEF_CONNCHECKLEVEL).trim();
00331 String connMaxAge = dsd.getProperty(CONNMAXAGE, DEF_CONNMAXAGE).trim();
00332 String maxOpenTime = dsd.getProperty(MAXOPENTIME, DEF_MAXOPENTIME).trim();
00333 String minconpool = dsd.getProperty(MINCONPOOL, DEF_MINCONPOOL).trim();
00334 String maxconpool = dsd.getProperty(MAXCONPOOL, DEF_MAXCONPOOL).trim();
00335 String maxwaittime = dsd.getProperty(MAXWAITTIME, DEF_MAXWAITTIME).trim();
00336 String maxwaiters = dsd.getProperty(MAXWAITERS, DEF_MAXWAITERS).trim();
00337 String samplingperiod = dsd.getProperty(SAMPLINGPERIOD, DEF_SAMPLINGPERIOD).trim();
00338 String defaultStatement = dsd.getProperty(CONNTESTSTMT, DEF_CONNTESTSTMT).trim();
00339
00340
00341 logger.log(BasicLevel.DEBUG, "create JOnAS ConnectionManager corresponding to data source " + datasourceName + " with JNDI name " + dsName);
00342 ConnectionManager ds = new ConnectionManager();
00343
00344
00345 ds.setDatasourceName(datasourceName);
00346 ds.setDSName(dsName);
00347 ds.setUrl(url);
00348 ds.setClassName(className);
00349 ds.setUserName(user);
00350 ds.setPassword(password);
00351 ds.setTransactionIsolation(dsd.getProperty(ISOLATIONLEVEL, DEF_ISOLATIONLEVEL).trim());
00352 ds.setMapperName(dsd.getProperty(MAPPERNAME, DEF_MAPPERNAME).trim());
00353 ds.setDataSourceDescription(description);
00354 ds.poolConfigure(connCheckLevel, connMaxAge, maxOpenTime, defaultStatement,
00355 minconpool, maxconpool, maxwaittime, maxwaiters, samplingperiod);
00356
00357
00358 cmList.addElement(ds);
00359 ictx.rebind(dsName, ds);
00360
00361 bindedDatasources.put(dsName, datasourceName);
00362 logger.log(BasicLevel.INFO, "Mapping ConnectionManager " + url + " on " + dsName);
00363
00364 try {
00365
00366
00367
00368 if (mbeanServer != null) {
00369
00370
00371
00372
00373 String jdbcDataSourceName = datasourceName;
00374 ObjectName onJDBCDataSource =
00375 J2eeObjectName.getJDBCDataSource(domainName,
00376 serverName,
00377 jdbcDataSourceName);
00378 JDBCDataSource jdbcDataSourceMBean = new JDBCDataSource(onJDBCDataSource.toString(), ds);
00379 oManaged = oRegistry.findManagedBean("JDBCDataSource");
00380 oMBean = oManaged.createMBean(jdbcDataSourceMBean);
00381 if (logger.isLoggable(BasicLevel.DEBUG)) {
00382 logger.log(BasicLevel.DEBUG, "JDBCDataSource created");
00383 }
00384 mbeanServer.registerMBean(oMBean, onJDBCDataSource);
00385
00386
00387
00388 jdbcResourceMBean.addJdbcDataSource(onJDBCDataSource.toString());
00389
00390
00391
00392 String jdbcDriverName = "aJDBCDriver-" + jdbcDataSourceName;
00393 ObjectName onJDBCDriver =
00394 J2eeObjectName.getJDBCDriver(domainName,
00395 serverName,
00396 jdbcDriverName);
00397 JDBCDriver jdbcDriverMBean =
00398 new JDBCDriver(onJDBCDriver.toString());
00399 jdbcDriverMBean.setClassName(className);
00400 oManaged = oRegistry.findManagedBean("JDBCDriver");
00401 oMBean = oManaged.createMBean(jdbcDriverMBean);
00402 if (logger.isLoggable(BasicLevel.DEBUG)) {
00403 logger.log(BasicLevel.DEBUG, "JDBCDriver created");
00404 }
00405 mbeanServer.registerMBean(oMBean, onJDBCDriver);
00406
00407
00408 jdbcDataSourceMBean.setJdbcDriver(onJDBCDriver.toString());
00409 if (logger.isLoggable(BasicLevel.DEBUG)) {
00410 logger.log(BasicLevel.DEBUG, "JDBCDataSource updated");
00411 }
00412
00413 }
00414 } catch (ServiceException se) {
00415
00416 }
00417
00418 }
00419
00423 public void unbindDataSources() throws NamingException {
00424
00425 logger.log(BasicLevel.DEBUG, "");
00426
00427 try {
00428 if (cmList.size() > 0) {
00429 String dsn = null;
00430 for (Enumeration lk = cmList.elements(); lk.hasMoreElements();) {
00431 ConnectionManager cm = (ConnectionManager) lk.nextElement();
00432 cm.closeAllConnection();
00433 dsn = cm.getDSName();
00434 ictx.unbind(dsn);
00435 bindedDatasources.remove(dsn);
00436 }
00437 }
00438 } catch (NamingException e) {
00439 logger.log(BasicLevel.ERROR, "cannot unbind DataSources : " + e);
00440 throw e;
00441 }
00442
00443
00444
00445
00446 if (mbeanServer != null) {
00447 try {
00448
00449 String[] ons = jdbcResourceMBean.getJdbcDataSources();
00450 ObjectName onJDBCDataSource = null;
00451 ObjectName onJDBCDriver = null;
00452 for (int i = 0; i < ons.length; i++) {
00453 onJDBCDataSource = ObjectName.getInstance(ons[i]);
00454 String jdbcDriverName = (String) mbeanServer.getAttribute(onJDBCDataSource, "jdbcDriver");
00455 onJDBCDriver = new ObjectName(jdbcDriverName);
00456
00457 mbeanServer.unregisterMBean(onJDBCDataSource);
00458
00459 mbeanServer.unregisterMBean(onJDBCDriver);
00460
00461 jdbcResourceMBean.removeJdbcDataSource(onJDBCDataSource.toString());
00462 }
00463 } catch (MalformedObjectNameException ma) {
00464 logger.log(BasicLevel.ERROR, "Cannot cleanly unregister DataSource: "
00465 + ma.getMessage());
00466 } catch (MBeanRegistrationException mr) {
00467 logger.log(BasicLevel.ERROR, "Cannot cleanly unregister DataSource: "
00468 + mr.getMessage());
00469 } catch (InstanceNotFoundException infe) {
00470 logger.log(BasicLevel.ERROR, "Cannot cleanly unregister DataSource: "
00471 + infe.getMessage());
00472 } catch (Exception e) {
00473 logger.log(BasicLevel.ERROR, "Cannot cleanly unregister DataSource: "
00474 + e.getMessage());
00475 }
00476 }
00477 }
00478
00482 public ConnectionManager getConnectionManager(String dsname) {
00483 ConnectionManager cm = null;
00484 if (cmList.size() > 0) {
00485 for (Enumeration lk = cmList.elements(); lk.hasMoreElements(); ) {
00486 cm = (ConnectionManager)lk.nextElement();
00487 if (cm.getDSName().equals(dsname)) {
00488 return cm;
00489 }
00490 }
00491 }
00492 return null;
00493 }
00494
00495
00496
00501 public List getDataSourcePropertiesFiles() throws Exception {
00502 return JModule.getDatasourcePropsInDir();
00503 }
00504
00509 public Integer getCurrentNumberOfDataSource() {
00510 return new Integer(cmList.size());
00511 }
00512
00517 public Integer getTotalCurrentNumberOfJDBCConnectionOpen(){
00518 int result = 0;
00519 if (cmList.size() > 0) {
00520 for (Enumeration lk = cmList.elements(); lk.hasMoreElements(); ) {
00521 ConnectionManager cm = (ConnectionManager)lk.nextElement();
00522 result += cm.getCurrentOpened().intValue();
00523 }
00524 }
00525 return new Integer(result);
00526 }
00527
00532 public boolean isLoadedDataSource(String dsName) {
00533 boolean result = false;
00534 if (cmList.size() > 0) {
00535 for (Enumeration lk = cmList.elements(); lk.hasMoreElements(); ) {
00536 ConnectionManager cm = (ConnectionManager)lk.nextElement();
00537 if (cm.getDatasourceName().equals(dsName))
00538 return true;
00539 }
00540 }
00541 return result;
00542 }
00543
00548 public void unloadDataSource(String name) {
00549 logger.log(BasicLevel.DEBUG, "");
00550 try {
00551 if (cmList.size() > 0) {
00552 for (Enumeration lk = cmList.elements(); lk.hasMoreElements();) {
00553 ConnectionManager cm = (ConnectionManager) lk.nextElement();
00554 String dsName = cm.getDatasourceName();
00555 String jndiName = cm.getDSName();
00556 if (dsName.equals(name)) {
00557
00558 cm.closeAllConnection();
00559 ictx.unbind(jndiName);
00560
00561 cmList.remove(cm);
00562 if (mbeanServer != null) {
00563 ObjectName onJDBCDataSource = J2eeObjectName.getJDBCDataSource(domainName, serverName, dsName);
00564 String jdbcDriverName = (String) mbeanServer.getAttribute(onJDBCDataSource, "jdbcDriver");
00565 ObjectName onJDBCDriver = new ObjectName(jdbcDriverName);
00566
00567 mbeanServer.unregisterMBean(onJDBCDataSource);
00568
00569 mbeanServer.unregisterMBean(onJDBCDriver);
00570
00571 jdbcResourceMBean.removeJdbcDataSource(onJDBCDataSource.toString());
00572 }
00573 return;
00574 }
00575 }
00576 }
00577 } catch (Exception e) {
00578 logger.log(BasicLevel.ERROR, "cannot unload DataSources : " + e);
00579 }
00580 }
00581
00586 public Properties getDataSourcePropertiesFile(String dsFile) throws Exception {
00587 try {
00588 return JProp.getInstance(dsFile).getConfigFileEnv();
00589
00590 } catch (Exception e) {
00591 if (e instanceof FileNotFoundException) {
00592 logger.log(BasicLevel.ERROR, "Please check if "+dsFile+".properties is available in JONAS_BASE/conf/ directory");
00593 } else {
00594 logger.log(BasicLevel.ERROR, "Error occured when reading file " + dsFile);
00595 }
00596 throw e;
00597 }
00598 }
00599
00606 public void loadDataSource(String name, Properties prop, Boolean loadFromFile) throws ServiceException {
00607 boolean fromFile = loadFromFile.booleanValue();
00608
00609 if (fromFile) {
00610 logger.log(BasicLevel.DEBUG, "Load data source named " + name + " from file");
00611 } else {
00612 logger.log(BasicLevel.DEBUG, "Load data source named " + name + " from form");
00613 if (isLoadedDataSource(name)) {
00614 logger.log(BasicLevel.DEBUG, "This data source, " + name + " is already loaded ; Unload it !");
00615 unloadDataSource(name);
00616 }
00617 try {
00618 logger.log(BasicLevel.DEBUG, "Call getInstance on JProp in order to create the properties file");
00619 JProp.getInstance(name, prop);
00620 } catch (Exception e) {
00621 logger.log(BasicLevel.ERROR, "Cannot create datasource " + name + " as cannot create properties file : " + e.toString());
00622 throw new ServiceException("DatabaseService: Cannot create datasource " + name + ",\n" + e.toString());
00623 }
00624 }
00625
00626 try {
00627 logger.log(BasicLevel.DEBUG, "Call method to create a data source");
00628 createDataSource(name, prop);
00629 logger.log(BasicLevel.DEBUG, "New data source created");
00630 } catch (Exception e) {
00631 logger.log(BasicLevel.ERROR, "Cannot create datasource: "+name);
00632 throw new ServiceException("DatabaseService: Cannot create datasource: " + name + ",\n" + e.toString());
00633 }
00634 }
00635
00641 public String getDatasourceName(String jndiName) {
00642 return (String)bindedDatasources.get(jndiName);
00643 }
00644
00645 }
00646