/*
* 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.ngrinder.infra.config;
import cubrid.jdbc.driver.CUBRIDDriver;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang.StringUtils;
import org.hibernate.dialect.CUBRIDExDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2ExDialect;
import org.ngrinder.common.util.PropertiesWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Driver;
/**
* Database handler for supported databases.
* <p/>
* You can easily add the more database type into {@link Database} enum.
*
* @author JunHo Yoon
* @since 3.0
*/
public enum Database {
/**
* CUBRID.
*/
cubrid(CUBRIDDriver.class, CUBRIDExDialect.class, "jdbc:CUBRID:%s:::?charset=utf-8%s") {
@Override
protected void setupVariants(BasicDataSource dataSource, PropertiesWrapper databaseProperties) {
dataSource.setUrl(String.format(getUrlTemplate(),
databaseProperties.getProperty(DatabaseConfig.PROP_DATABASE_URL),
StringUtils.trimToEmpty(databaseProperties.getProperty(DatabaseConfig.PROP_DATABASE_URL_OPTION))));
dataSource.setUsername(databaseProperties.getProperty(DatabaseConfig.PROP_DATABASE_USERNAME));
dataSource.setPassword(databaseProperties.getProperty(DatabaseConfig.PROP_DATABASE_PASSWORD));
}
},
/**
* H2.
*/
H2(org.h2.Driver.class, H2ExDialect.class, "jdbc:h2:%s/db/h2", false) {
@Override
protected void setupVariants(BasicDataSource dataSource, PropertiesWrapper databaseProperties) {
String format = String.format(getUrlTemplate(), databaseProperties.getProperty("NGRINDER_HOME", "."));
final String databaseURL = databaseProperties.getProperty(DatabaseConfig.PROP_DATABASE_URL);
if (databaseURL.startsWith("tcp://")) {
format = "jdbc:h2:" + databaseURL;
}
if (databaseProperties.exist("unit-test")) {
format = format + ";DB_CLOSE_ON_EXIT=FALSE";
}
dataSource.setUrl(format);
dataSource.setUsername(databaseProperties.getProperty(DatabaseConfig.PROP_DATABASE_USERNAME));
dataSource.setPassword(databaseProperties.getProperty(DatabaseConfig.PROP_DATABASE_PASSWORD));
}
};
/*
* Default db constants
*/
private static final int DB_MAX_OPEN_PREPARED_STATEMENTS = 50;
private static final int DB_MAX_WAIT = 3000;
private static final int DB_MIN_IDLE = 5;
private static final int DB_MAX_ACTIVE = 20;
private static final int DB_INITIAL_SIZE = 5;
private static final Logger LOG = LoggerFactory.getLogger(Database.class);
private final String urlTemplate;
private final String jdbcDriverName;
private final String dialect;
private final boolean clusterSupport;
/**
* Constructor with cluster mode true.
*
* @param jdbcDriver JDBC Driver class
* @param dialect the dialect to be used
* @param urlTemplate database url template. This will be used to be combined with database_url property in
* database.conf
*/
Database(Class<? extends Driver> jdbcDriver, Class<? extends Dialect> dialect, String urlTemplate) {
this(jdbcDriver, dialect, urlTemplate, true);
}
/**
* Constructor.
*
* @param jdbcDriver JDBC Driver class
* @param dialect the dialect to be used
* @param urlTemplate database url template. This will be used to be combined with database_url property in
* database.conf
* @param clusterSupport true if cluster mode is supported.
* @since 3.1
*/
Database(Class<? extends Driver> jdbcDriver, Class<? extends Dialect> dialect, String urlTemplate,
boolean clusterSupport) {
this.clusterSupport = clusterSupport;
this.dialect = dialect.getCanonicalName();
this.jdbcDriverName = jdbcDriver.getCanonicalName();
this.urlTemplate = urlTemplate;
}
/**
* Get the Jdbc driver name.
*
* @return driver name
*/
public String getJdbcDriverName() {
return jdbcDriverName;
}
/**
* Get the database URL template.
*
* @return database URL template
*/
public String getUrlTemplate() {
return urlTemplate;
}
/**
* Get the {@link Database} enum value for the given type.
*
* @param type db type name. For example... H2, Cubrid..
* @return found {@link Database}. {@link Database#H2} if not found.
*/
public static Database getDatabase(String type) {
for (Database database : values()) {
if (database.name().equalsIgnoreCase(type)) {
return database;
}
}
LOG.error("[FATAL] Database type {} is not supported.\n" +
"Please check the ${NGRINDER_HOME}/database.conf.\n "
+ "Use H2 instead.", type);
return H2;
}
/**
* Set up database. this method consists of two parts.<br/>
* The first part is variant setup b/w databases. The second is common setup among databases.
*
* @param dataSource dataSource
* @param propertiesWrapper {@link PropertiesWrapper} which contains db access info
*/
public void setup(BasicDataSource dataSource, PropertiesWrapper propertiesWrapper) {
setupVariants(dataSource, propertiesWrapper);
setupCommon(dataSource);
}
/**
* Setup the database specific features. Each {@link Database} enums should inherits this method.
*
* @param dataSource dataSource
* @param databaseConf "database.conf" properties.
*/
protected abstract void setupVariants(BasicDataSource dataSource, PropertiesWrapper databaseConf);
/**
* Setup the database common features.
*
* @param dataSource datasource
*/
protected void setupCommon(BasicDataSource dataSource) {
dataSource.setDriverClassName(getJdbcDriverName());
dataSource.setInitialSize(DB_INITIAL_SIZE);
dataSource.setMaxActive(DB_MAX_ACTIVE);
dataSource.setMinIdle(DB_MIN_IDLE);
dataSource.setMaxWait(DB_MAX_WAIT);
dataSource.setPoolPreparedStatements(true);
dataSource.setMaxOpenPreparedStatements(DB_MAX_OPEN_PREPARED_STATEMENTS);
dataSource.setTestWhileIdle(true);
dataSource.setTestOnBorrow(true);
dataSource.setTestOnReturn(true);
dataSource.setValidationQuery("SELECT 1");
}
/**
* Get the current used dialect.
*
* @return dialect name
*/
public String getDialect() {
return dialect;
}
/**
* Check if it's cluster mode.
*
* @return true if support
*/
public boolean isClusterSupport() {
return clusterSupport;
}
}