package org.test4j.module.database.environment; import static org.test4j.module.core.utility.IPropItem.PROPKEY_DATABASE_TYPE; import static org.test4j.module.core.utility.IPropItem.PROPKEY_DATASOURCE_DRIVERCLASSNAME; import static org.test4j.module.core.utility.IPropItem.PROPKEY_DATASOURCE_PASSWORD; import static org.test4j.module.core.utility.IPropItem.PROPKEY_DATASOURCE_SCHEMAS; import static org.test4j.module.core.utility.IPropItem.PROPKEY_DATASOURCE_URL; import static org.test4j.module.core.utility.IPropItem.PROPKEY_DATASOURCE_USERNAME; import static org.test4j.module.database.annotations.Transactional.TransactionMode.DEFAULT; import static org.test4j.module.database.environment.DBEnvironment.CUSTOMIZED_DATASOURCE_NAME; import static org.test4j.module.database.environment.DBEnvironment.DEFAULT_DATASOURCE_FROM; import static org.test4j.module.database.environment.DBEnvironment.DEFAULT_DATASOURCE_NAME; import static org.test4j.tools.commons.AnnotationHelper.getMethodOrClassLevelAnnotationProperty; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.UUID; import org.test4j.module.core.TestContext; import org.test4j.module.core.utility.IPropItem; import org.test4j.module.database.annotations.Transactional; import org.test4j.module.database.annotations.Transactional.TransactionMode; import org.test4j.module.database.environment.types.DerbyEnvironment; import org.test4j.module.database.environment.types.MySqlEnvironment; import org.test4j.module.database.environment.types.OracleEnvironment; import org.test4j.module.database.environment.types.SqlServerEnvironment; import org.test4j.module.database.utility.DataSourceType; import org.test4j.tools.commons.ConfigHelper; import org.test4j.tools.commons.ResourceHelper; import org.test4j.tools.commons.StringHelper; public final class DBEnvironmentFactory { private static Map<String, DBEnvironment> environments = new HashMap<String, DBEnvironment>(); private static DBEnvironment newInstance(DataSourceType dataSourceType, String dataSourceName, String dataSourceFrom) { if (dataSourceType == null) { throw new RuntimeException("DatabaseType can't be null."); } switch (dataSourceType) { case MYSQL: return new MySqlEnvironment(dataSourceName, dataSourceFrom); case ORACLE: return new OracleEnvironment(dataSourceName, dataSourceFrom); case SQLSERVER: return new SqlServerEnvironment(dataSourceName, dataSourceFrom); case DERBYDB: return new DerbyEnvironment(dataSourceName, dataSourceFrom); default: throw new RuntimeException("unsupport database type:" + dataSourceType.name()); } } /** * 构造自定义的数据库连接识别码 * * @param type * @param driver * @param url * @param username * @param password * @return */ public static DBEnvironment getDBEnvironment(String type, String driver, String url, String username, String password) { DataSourceType dataSourceType = DataSourceType.databaseType(type); String dataSourceFrom = "customized-" + UUID.randomUUID().toString(); DBEnvironment enviroment = newInstance(dataSourceType, CUSTOMIZED_DATASOURCE_NAME, dataSourceFrom); environments.put(DEFAULT_DATASOURCE_NAME + "=" + dataSourceFrom, enviroment); if (StringHelper.isBlankOrNull(driver)) { driver = ConfigHelper.databaseDriver(); } if (StringHelper.isBlankOrNull(url)) { url = ConfigHelper.databaseUrl(); } if (StringHelper.isBlankOrNull(username)) { username = ConfigHelper.databaseUserName(); } if (StringHelper.isBlankOrNull(password)) { password = ConfigHelper.databasePassword(); } enviroment.setDataSource(driver, url, "", username, password); return enviroment; } final static String NO_VALID_VALUE_MESSAGE = "can't find valid value of key[%s] in file[%s]!"; /** * 获取默认的数据库连接识别码 * * @return */ public static DBEnvironment getDefaultDBEnvironment() { DBEnvironment enviroment = getDBEnvironment(DEFAULT_DATASOURCE_NAME, DEFAULT_DATASOURCE_FROM); return enviroment; } /** * 从test4j配置中取指定的数据源 * * @param dataSourceName * @return */ public static DBEnvironment getDBEnvironment(String dataSourceName) { if (StringHelper.isBlankOrNull(dataSourceName)) { dataSourceName = DEFAULT_DATASOURCE_NAME; } DBEnvironment enviroment = getDBEnvironment(dataSourceName, DEFAULT_DATASOURCE_FROM); return enviroment; } /** * 从文件中获取指定的数据库连接识别码 * * @param dataSourceName * @param dataSourceFrom * @return */ public static DBEnvironment getDBEnvironment(String dataSourceName, String dataSourceFrom) { dataSourceName = StringHelper.isBlankOrNull(dataSourceName) ? DEFAULT_DATASOURCE_NAME : dataSourceName; dataSourceFrom = StringHelper.isBlankOrNull(dataSourceFrom) ? DEFAULT_DATASOURCE_FROM : dataSourceFrom; DBEnvironment enviroment = environments.get(dataSourceName + "=" + dataSourceFrom); if (enviroment == null) { Properties props = null; if (StringHelper.isBlankOrNull(dataSourceFrom) == false && DEFAULT_DATASOURCE_FROM.equalsIgnoreCase(dataSourceFrom) == false) { props = ResourceHelper.loadPropertiesFrom(dataSourceFrom); } String typeProperty = ConfigHelper.getString(props, getMergeKey(dataSourceName, PROPKEY_DATABASE_TYPE)); DataSourceType dataSourceType = DataSourceType.databaseType(typeProperty); enviroment = newInstance(dataSourceType, dataSourceName, dataSourceFrom); environments.put(dataSourceName + "=" + dataSourceFrom, enviroment); String driver = ConfigHelper.getString(props, getMergeKey(dataSourceName, PROPKEY_DATASOURCE_DRIVERCLASSNAME)); String url = ConfigHelper.getString(props, getMergeKey(dataSourceName, PROPKEY_DATASOURCE_URL)); String user = ConfigHelper.getString(props, getMergeKey(dataSourceName, PROPKEY_DATASOURCE_USERNAME)); if (StringHelper.isBlankOrNull(driver) || StringHelper.isBlankOrNull(url) || StringHelper.isBlankOrNull(user)) { throw new RuntimeException(String.format(NO_VALID_VALUE_MESSAGE, dataSourceName + "." + PROPKEY_DATASOURCE_USERNAME, dataSourceFrom)); } String pass = ConfigHelper.getString(props, getMergeKey(dataSourceName, PROPKEY_DATASOURCE_PASSWORD)); if (pass == null) { pass = ""; } String schemas = ConfigHelper.getString(props, getMergeKey(dataSourceName, PROPKEY_DATASOURCE_SCHEMAS), ""); schemas = schemas == null ? "" : schemas; enviroment.setDataSource(driver, url, schemas, user, pass); } return enviroment; } private static String getMergeKey(String dataSourceName, String key) { if (StringHelper.isBlankOrNull(dataSourceName) || DEFAULT_DATASOURCE_NAME.equalsIgnoreCase(dataSourceName)) { return key; } else { return dataSourceName + "." + key; } } /** * 当前正在使用的数据库类型 */ private static DBEnvironment currDBEnvironment = null; /** * 获取当前的数据库处理环境 * * @return */ public static DBEnvironment getCurrentDBEnvironment() { if (currDBEnvironment == null) { currDBEnvironment = getDefaultDBEnvironment(); } return currDBEnvironment; } /** * 切换数据库环境<br> * 先关闭上一个数据库连接,再设置当前数据库连接 * * @param DataSourceIdentify * @throws SQLException */ public static void changeDBEnvironment(DBEnvironment environment) { // if (currDBEnvironment != null && // currDBEnvironment.equals(environment) == false) { // currDBEnvironment.close(); // } currDBEnvironment = environment; } /** * 切换数据源<br> * 先关闭上一个数据库连接,再设置当前数据库连接 * * @param dataSourceName test4j中配置的数据源名称 */ public static void changeDBEnvironment(String dataSourceName) { if (StringHelper.isBlankOrNull(dataSourceName)) { dataSourceName = DEFAULT_DATASOURCE_NAME; } DBEnvironment specEnvironment = DBEnvironmentFactory.getDBEnvironment(dataSourceName); DBEnvironmentFactory.changeDBEnvironment(specEnvironment); } /** * 当前测试方法的事务模式 * * @param testedObject * @param testedMethod * @return */ public static TransactionMode getTransactionMode() { if (TestContext.currTestedObject() == null || TestContext.currTestedMethod() == null) { return TransactionMode.DISABLED; } TransactionMode transactionMode = getMethodOrClassLevelAnnotationProperty(Transactional.class, "value", DEFAULT, TestContext.currTestedMethod(), TestContext.currTestedClazz()); if (transactionMode == TransactionMode.DEFAULT) { String mode = ConfigHelper.getString(IPropItem.TRANSACTIONAL_MODE_DEFAULT, "DISABLED"); transactionMode = TransactionMode.valueOf(mode.toUpperCase()); } if (transactionMode == null || transactionMode == TransactionMode.DEFAULT) { return TransactionMode.DISABLED; } else { return transactionMode; } } private final static String DEFAULT_ENVIRONMENT_KEY = DEFAULT_DATASOURCE_NAME + "=" + DEFAULT_DATASOURCE_FROM; /** * 结束所有可能的事务 * * @throws SQLException */ public static void closeDBEnvironment() { StringBuilder err = new StringBuilder(); for (Map.Entry<String, DBEnvironment> environment : environments.entrySet()) { try { if (environment.getKey().equals(DEFAULT_ENVIRONMENT_KEY)) { environment.getValue().endTransaction(); } } catch (Throwable e) { err.append(StringHelper.exceptionTrace(e)); } } String msg = err.toString(); if ("".equalsIgnoreCase(msg.trim()) == false) { throw new RuntimeException(msg); } } /** * 启动默认的事务管理 */ public static void startDBEnvironment() { TransactionMode mode = DBEnvironmentFactory.getTransactionMode(); if (mode == TransactionMode.COMMIT || mode == TransactionMode.ROLLBACK) { DBEnvironmentFactory.getDefaultDBEnvironment().startTransaction(); } } }