/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.ode.il.dbutil;
import java.io.File;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.dao.bpel.BpelDAOConnectionFactory;
import org.apache.ode.dao.scheduler.SchedulerDAOConnectionFactory;
import org.apache.ode.dao.store.ConfStoreDAOConnectionFactory;
import org.apache.ode.il.config.OdeConfigProperties;
import org.apache.ode.utils.LoggingInterceptor;
/**
* Does the dirty work of setting up / obtaining a DataSource based on the configuration in the {@link OdeConfigProperties} object.
*
*/
public class Database {
private static final Log __log = LogFactory.getLog(Database.class);
private static final Log __logSql = LogFactory.getLog("org.apache.ode.sql");
private static final Messages __msgs = Messages.getMessages(Messages.class);
private OdeConfigProperties _odeConfig;
private boolean _started;
private DatabaseConnectionManager _connectionManager;
private TransactionManager _txm;
private DataSource _datasource;
private File _workRoot;
private boolean _needShutdown;
private EmbeddedDatabase _embeddedDB;
public Database(OdeConfigProperties props) {
if (props == null)
throw new NullPointerException("Must provide a configuration.");
_odeConfig = props;
}
public void setWorkRoot(File workRoot) {
_workRoot = workRoot;
}
public void setTransactionManager(TransactionManager txm) {
_txm = txm;
}
public synchronized void start() throws DatabaseConfigException {
if (_started)
return;
_needShutdown = false;
_datasource = null;
_connectionManager = null;
initDataSource();
_started = true;
}
public synchronized void shutdown() {
if (!_started) {
return;
}
if (_connectionManager != null) {
try {
__log.debug("Stopping connection manager");
_connectionManager.shutdown();
} catch (Throwable t) {
__log.warn("Exception while stopping connection manager: " + t.getMessage());
} finally {
_connectionManager = null;
}
}
if (_needShutdown) {
__log.debug("shutting down database.");
_embeddedDB.shutdown();
}
_needShutdown = false;
_datasource = null;
_started = false;
}
public DataSource getDataSource() {
DataSource ds = __logSql.isDebugEnabled() ? LoggingInterceptor.createLoggingDS(_datasource, __logSql) : _datasource;
return ds;
}
private void initDataSource() throws DatabaseConfigException {
switch (_odeConfig.getDbMode()) {
case EXTERNAL:
initExternalDb();
break;
case EMBEDDED:
initEmbeddedDb();
break;
case INTERNAL:
initInternalDb();
break;
default:
break;
}
}
private void initExternalDb() throws DatabaseConfigException {
try {
_datasource = (DataSource) lookupInJndi(_odeConfig.getDbDataSource());
__log.debug(__msgs.msgOdeUsingExternalDb(_odeConfig.getDbDataSource()));
} catch (Exception ex) {
String msg = __msgs.msgOdeInitExternalDbFailed(_odeConfig.getDbDataSource());
__log.error(msg, ex);
throw new DatabaseConfigException(msg, ex);
}
}
private void initInternalDb() throws DatabaseConfigException {
__log.debug(__msgs.msgOdeUsingInternalDb(_odeConfig.getDbIntenralJdbcUrl(), _odeConfig.getDbInternalJdbcDriverClass()));
initInternalDb(_odeConfig.getDbIntenralJdbcUrl(), _odeConfig.getDbInternalJdbcDriverClass(),
_odeConfig.getDbInternalUserName(), _odeConfig.getDbInternalPassword());
}
private void initInternalDb(String url, String driverClass, String username,String password) throws DatabaseConfigException {
_connectionManager = new DatabaseConnectionManager(_txm,_odeConfig);
_connectionManager.init(url, driverClass, username, password);
_datasource = _connectionManager.getDataSource();
}
/**
* Initialize embedded (DERBY) database.
*/
private void initEmbeddedDb() throws DatabaseConfigException {
switch (_odeConfig.getDbEmbeddedType()) {
case H2:
_embeddedDB = new H2Database();
break;
default:
_embeddedDB = new H2Database();
}
_embeddedDB.init(_workRoot,_odeConfig,_txm);
_datasource = _embeddedDB.getDataSource();
_needShutdown = true;
}
@SuppressWarnings("unchecked")
private <T> T lookupInJndi(String objName) throws Exception {
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
try {
InitialContext ctx = null;
try {
ctx = new InitialContext();
return (T) ctx.lookup(objName);
} finally {
if (ctx != null)
try {
ctx.close();
} catch (Exception ex1) {
__log.error("Error closing JNDI connection.", ex1);
}
}
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
public BpelDAOConnectionFactory createDaoCF() throws DatabaseConfigException {
String pClassName = _odeConfig.getDAOConnectionFactory();
__log.debug(__msgs.msgOdeUsingDAOImpl(pClassName));
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
BpelDAOConnectionFactory cf;
try {
try {
cf = (BpelDAOConnectionFactory) Class.forName(pClassName).newInstance();
} catch (Exception ex) {
String errmsg = __msgs.msgDAOInstantiationFailed(pClassName);
__log.error(errmsg, ex);
throw new DatabaseConfigException(errmsg, ex);
}
cf.init(_odeConfig.getProperties(),_txm,getDataSource());
return cf;
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
public ConfStoreDAOConnectionFactory createDaoStoreCF() throws DatabaseConfigException {
String pClassName = _odeConfig.getDAOConfStoreConnectionFactory();
__log.debug(__msgs.msgOdeUsingDAOImpl(pClassName));
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
ConfStoreDAOConnectionFactory cf;
try {
try {
cf = (ConfStoreDAOConnectionFactory) Class.forName(pClassName).newInstance();
} catch (Exception ex) {
String errmsg = __msgs.msgDAOInstantiationFailed(pClassName);
__log.error(errmsg, ex);
throw new DatabaseConfigException(errmsg, ex);
}
cf.init(_odeConfig.getProperties(),_txm,getDataSource());
return cf;
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
public SchedulerDAOConnectionFactory createDaoSchedulerCF() throws DatabaseConfigException {
String pClassName = _odeConfig.getDAOConfScheduleConnectionFactory();
__log.debug(__msgs.msgOdeUsingDAOImpl(pClassName));
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
SchedulerDAOConnectionFactory sdcf;
try {
try {
sdcf = (SchedulerDAOConnectionFactory) Class.forName(pClassName).newInstance();
} catch (Exception ex) {
String errmsg = __msgs.msgDAOInstantiationFailed(pClassName);
__log.error(errmsg, ex);
throw new DatabaseConfigException(errmsg, ex);
}
sdcf.init(_odeConfig.getProperties(), _txm, getDataSource());
return sdcf;
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
}