package org.ovirt.engine.core.dal.dbbroker;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.ovirt.engine.core.common.utils.ResourceUtils;
import org.ovirt.engine.core.compat.LogCompat;
import org.ovirt.engine.core.compat.LogFactoryCompat;
import org.ovirt.engine.core.utils.FileUtil;
import org.ovirt.engine.core.utils.ejb.ContainerManagedResourceType;
import org.ovirt.engine.core.utils.ejb.EjbUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
/**
* A locator singleton for looking up (and initializing) DbFacade instance
*/
public class DbFacadeLocator {
private static DbFacade dbFacade;
private static final LogCompat log = LogFactoryCompat.getLog(DbFacadeLocator.class);
static {
try {
// ok we need to locate the datasource
DataSource datasource = EjbUtils
.findResource(ContainerManagedResourceType.DATA_SOURCE);
if (datasource == null)
throw new RuntimeException("Datasource is not defined ");
// create the facade and return it
dbFacade = new DbFacade();
dbFacade.setDbEngineDialect(loadDbEngineDialect());
loadDbFacadeConfig();
JdbcTemplate jdbcTemplate = dbFacade.getDbEngineDialect().createJdbcTemplate(datasource);
SQLErrorCodeSQLExceptionTranslator tr = new CustomSQLErrorCodeSQLExceptionTranslator(datasource);
jdbcTemplate.setExceptionTranslator(tr);
dbFacade.setTemplate(jdbcTemplate);
} catch (Exception e) {
log.fatal("Unable to locate DbFacade instance", e);
}
}
public static DbFacade getDbFacade() {
return dbFacade;
}
/**
* Generate and sets the database engine dialect object according to configuration.
*
* @throws Exception
*/
public static DbEngineDialect loadDbEngineDialect() throws Exception {
final String ENGINE_DB_ENGINE_PROPERTIES = "engine-db-engine.properties";
final String DIALECT = "DbEngineDialect";
Properties props = ResourceUtils.loadProperties(DbFacadeLocator.class, ENGINE_DB_ENGINE_PROPERTIES);
if (props.getProperty(DIALECT) == null) {
throw new IllegalStateException("Failed to get property key value");
}
return (DbEngineDialect) Class.forName(props.getProperty(DIALECT)).newInstance();
}
public static void loadDbFacadeConfig() throws Exception {
boolean configSucceeded = false;
final String ENGINE_CONF_FILE = "/etc/engine/engine.conf";
final String ON_START_CONNECTION_TIMEOUT = "OnStartConnectionTimeout";
final String CONNECTION_CHECK_INTERVAL = "ConnectionCheckInterval";
final String DEFAULT_TIMEOUT_VALUE = "300000";
final String DEFAULT_INTERVAL_VALUE = "1000";
InputStream inputStream = null;
try {
String onStartConnectionTimeout = null;
String connectionCheckInterval = null;
Properties props = new Properties();
if (FileUtil.fileExists(ENGINE_CONF_FILE)) {
// File exists, load /etc/engine.conf and set values in DbFacade
inputStream = new FileInputStream(ENGINE_CONF_FILE);
props.load(inputStream);
onStartConnectionTimeout = props.getProperty(ON_START_CONNECTION_TIMEOUT);
connectionCheckInterval = props.getProperty(CONNECTION_CHECK_INTERVAL);
if (!validNumber(onStartConnectionTimeout)) {
onStartConnectionTimeout = DEFAULT_TIMEOUT_VALUE;
}
if (!validNumber(connectionCheckInterval)) {
connectionCheckInterval = DEFAULT_INTERVAL_VALUE;
}
} else {
// File does not exist - use defaults
log.warn(String.format("%1$s file is not found. Please check your engine installation. " +
"Default values will be used"
, ENGINE_CONF_FILE));
onStartConnectionTimeout = DEFAULT_TIMEOUT_VALUE;
connectionCheckInterval = DEFAULT_INTERVAL_VALUE;
}
dbFacade.setOnStartConnectionTimeout(Integer.parseInt(onStartConnectionTimeout));
dbFacade.setConnectionCheckInterval(Integer.parseInt(connectionCheckInterval));
configSucceeded = true;
} catch (Exception ex) {
log.error("Error in configuration of db facade " + ExceptionUtils.getMessage(ex));
} finally {
if (!configSucceeded) {
dbFacade.setOnStartConnectionTimeout(300000);
dbFacade.setConnectionCheckInterval(1000);
}
if (inputStream != null) {
inputStream.close();
}
}
}
private static boolean validNumber(String numberStr) {
return numberStr != null && NumberUtils.isNumber(numberStr);
}
}