/*
* Copyright (c) 2011, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.wso2.carbon.humantask.core.db;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.humantask.core.configuration.HumanTaskServerConfiguration;
import org.wso2.carbon.humantask.core.dao.Constants;
import org.wso2.carbon.humantask.core.dao.HumanTaskDAOConnectionFactoryJDBC;
import org.wso2.carbon.humantask.core.engine.HumanTaskServerException;
import org.wso2.carbon.humantask.core.utils.HumanTaskDatabaseCreator;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Internal representation of the human task database.
*/
public class Database {
private static final Log log = LogFactory.getLog(Database.class);
private HumanTaskServerConfiguration serverConfiguration;
/* A flag indicating whether the database is already initiated */
private boolean started;
private TransactionManager tnxManager;
private DataSource dataSource;
/**
* @return The Human Task DataSource..
*/
public synchronized DataSource getDataSource() {
if (this.dataSource == null) {
throw new RuntimeException("Human Task Database is not properly initialised!");
}
return this.dataSource;
}
public Database(HumanTaskServerConfiguration htConfig) {
if (htConfig == null) {
throw new IllegalArgumentException("Must provide the human task server configuration!");
}
this.serverConfiguration = htConfig;
}
/**
* Database initialization logic.
*/
public synchronized void start() throws DatabaseConfigurationException, HumanTaskServerException {
if (started) {
return;
}
this.dataSource = null;
initDataSource();
setupHumanTaskDatabase();
}
private void setupHumanTaskDatabase() throws HumanTaskServerException {
if (System.getProperty("setup") != null) {
HumanTaskDatabaseCreator humantaskDBCreator;
try {
humantaskDBCreator = new HumanTaskDatabaseCreator(getDataSource());
} catch (Exception e) {
String errMsg = "Error creating HumanTaskDatabaseCreator";
log.error(errMsg, e);
throw new HumanTaskServerException(errMsg, e);
}
if (!humantaskDBCreator.isDatabaseStructureCreated("SELECT * FROM HT_JOB")) {
try {
//TODO rename following method
humantaskDBCreator.createRegistryDatabase();
} catch (Exception e) {
String errMsg = "Error creating HumanTask database";
log.error(errMsg, e);
throw new HumanTaskServerException(errMsg, e);
}
} else {
if (log.isDebugEnabled()) {
log.debug("HumanTask database already exists. Using the old database.");
}
}
}
}
/**
* Shut down logic for the Database related resources.
*/
public synchronized void shutdown() {
if (!started) {
return;
}
this.dataSource = null;
this.started = false;
}
private void initDataSource() throws DatabaseConfigurationException {
//Note : We can improve this to consider internal/external databases.
initExternalDb();
}
private void initExternalDb() throws DatabaseConfigurationException {
try {
this.dataSource = (DataSource) lookupInJndi(serverConfiguration.getDataSourceName());
if(log.isDebugEnabled()) {
log.debug("HumanTask Server using external DataSource " +
serverConfiguration.getDataSourceName());
}
} catch (Exception e) {
String errorMsg = "Failed to resolved external DataSource at " +
serverConfiguration.getDataSourceName();
log.error(errorMsg, e);
throw new DatabaseConfigurationException(errorMsg, e);
}
}
@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 {
if (serverConfiguration.getDataSourceJNDIRepoInitialContextFactory() != null &&
serverConfiguration.getDataSourceJNDIRepoProviderURL() != null) {
Properties jndiProps = new Properties();
jndiProps.setProperty(Context.INITIAL_CONTEXT_FACTORY,
serverConfiguration.getDataSourceJNDIRepoInitialContextFactory());
jndiProps.setProperty(Context.PROVIDER_URL,
serverConfiguration.getDataSourceJNDIRepoProviderURL());
ctx = new InitialContext(jndiProps);
} else {
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);
}
}
/**
*
* @param tnxManager : The transaction manager to set.
*/
public void setTransactionManager(TransactionManager tnxManager) {
this.tnxManager = tnxManager;
}
/**
* Creates the DAO connection factory.
* @return : the connection factory.
* @throws DatabaseConfigurationException : If the provided config factory cannot be instantiated.
*/
public HumanTaskDAOConnectionFactoryJDBC createDAOConnectionFactory()
throws DatabaseConfigurationException {
String connectionFactoryClassName = serverConfiguration.getDaoConnectionFactoryClass();
if(log.isDebugEnabled()) {
log.debug("Using DAO connection factory class: " + connectionFactoryClassName);
}
HumanTaskDAOConnectionFactoryJDBC humanTaskDAOConnectionFactoryJDBC;
try{
humanTaskDAOConnectionFactoryJDBC = (HumanTaskDAOConnectionFactoryJDBC)
Class.forName(connectionFactoryClassName).newInstance();
} catch (Exception ex) {
String errMsg = "Human Task DAO Connection Factory instantiation failed!";
log.error(errMsg);
throw new DatabaseConfigurationException(errMsg, ex);
}
humanTaskDAOConnectionFactoryJDBC.setDataSource(getDataSource());
humanTaskDAOConnectionFactoryJDBC.setTransactionManager(getTnxManager());
humanTaskDAOConnectionFactoryJDBC.setDAOConnectionFactoryProperties(
getGenericDAOFactoryProperties());
humanTaskDAOConnectionFactoryJDBC.init();
return humanTaskDAOConnectionFactoryJDBC;
}
/**
* Gets the generic properties for DAO Connection Factory.
* @return
*/
private Map<String, Object> getGenericDAOFactoryProperties(){
Map<String, Object> daoFactoryProperties = new HashMap<String, Object>();
daoFactoryProperties.put(Constants.DATA_SOURCE_PROP, getDataSource());
daoFactoryProperties.put(Constants.PROP_ENABLE_DDL_GENERATION,
serverConfiguration.isGenerateDdl());
daoFactoryProperties.put(Constants.PROP_ENABLE_SQL_TRACING, serverConfiguration.isShowSql());
daoFactoryProperties.put(Constants.DAO_FACTORY_CLASS_PROP,
serverConfiguration.getDaoConnectionFactoryClass());
return daoFactoryProperties;
}
public TransactionManager getTnxManager() {
return tnxManager;
}
}