/*******************************************************************************
* Copyright (c) 2013 hangum.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* hangum - initial API and implementation
******************************************************************************/
package com.hangum.tadpole.engine.manager.transaction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.AbandonedConfig;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.log4j.Logger;
import com.hangum.tadpole.cipher.core.manager.CipherManager;
import com.hangum.tadpole.commons.libs.core.define.PublicTadpoleDefine;
import com.hangum.tadpole.engine.define.DBDefine;
import com.hangum.tadpole.engine.query.dao.system.UserDBDAO;
/**
* DBCP connection manager
*
* @author hangum
*
*/
public class DBCPConnectionManager {
private static final Logger logger = Logger.getLogger(DBCPConnectionManager.class);
private static Properties propertiesObjectPool = new Properties();
public static DBCPConnectionManager instance = null;
private Map<String, DataSource> mapDataSource = new HashMap<String, DataSource>();
private Map<String, GenericObjectPool<Object> > mapGenericObject = new HashMap<String, GenericObjectPool<Object> >();
private DBCPConnectionManager() {
}
public static DBCPConnectionManager getInstance() {
if(instance == null) {
instance = new DBCPConnectionManager();
try {
propertiesObjectPool.load(DBCPConnectionManager.class.getResourceAsStream("ObjectPool.properties"));
} catch (Exception e) {
logger.error("Not found Transaction poolinfo config files. File name is ObjectPool.properties.");
}
}
return instance;
}
private DataSource makePool(final String searchKey, UserDBDAO userDB) {
GenericObjectPool<Object> connectionPool = _makeGenericObjectPool();
String passwdDecrypt = "";
try {
passwdDecrypt = CipherManager.getInstance().decryption(userDB.getPasswd());
} catch(Exception e) {
passwdDecrypt = userDB.getPasswd();
}
final String strValidateQuery = userDB.getDBDefine().getValidateQuery(true);
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(userDB.getUrl(), userDB.getUsers(), passwdDecrypt);
PoolableConnectionFactory pcf = new PoolableConnectionFactory(
connectionFactory,
connectionPool,
null,
strValidateQuery,
false,
false,
-1, // defaultTransactionIsolation
_makeAbandonedConfig()
);
connectionPool.setFactory(pcf);
pcf.setValidationQuery(strValidateQuery);
pcf.setValidationQueryTimeout(10000);
if(!"".equals(PublicTadpoleDefine.CERT_USER_INFO)) {
// initialize connection string
List<String> listInitializeSql = new ArrayList<String>();
listInitializeSql.add(
String.format(PublicTadpoleDefine.CERT_USER_INFO, userDB.getTdbLogingIP(), userDB.getTdbUserID()) + " " + strValidateQuery
);
if(userDB.getDBDefine() == DBDefine.ORACLE_DEFAULT) {
listInitializeSql.add(String.format("CALL DBMS_APPLICATION_INFO.SET_MODULE('TadpoleHub-Tran(%s)', '')", userDB.getTdbUserID()));
} else if(userDB.getDBDefine() == DBDefine.POSTGRE_DEFAULT) {
listInitializeSql.add(String.format("SET application_name = 'TadpoleHub-Tran(%s)'", userDB.getTdbUserID()));
}
pcf.setConnectionInitSql(listInitializeSql);
}
// setting poolable connection factory
DataSource ds = new PoolingDataSource(connectionPool);
mapDataSource.put(searchKey, ds);
mapGenericObject.put(searchKey, connectionPool);
return ds;
}
/**
* make abandoned config
*
* @return
*/
private static AbandonedConfig _makeAbandonedConfig() {
AbandonedConfig abandonedConfig = new AbandonedConfig();
abandonedConfig.setLogAbandoned(false);
abandonedConfig.setRemoveAbandoned(true);
abandonedConfig.setRemoveAbandonedTimeout(300);
return abandonedConfig;
}
/**
* make GenericObjectPool
*
* @return
*/
private static GenericObjectPool<Object> _makeGenericObjectPool() {
GenericObjectPool<Object> connectionPool = new GenericObjectPool<Object>();
connectionPool.setMaxActive(Integer.parseInt(propertiesObjectPool.getProperty("connectionPool.setMaxActive")));
connectionPool.setMaxIdle(Integer.parseInt(propertiesObjectPool.getProperty("connectionPool.setMaxIdle")));
connectionPool.setMaxWait(Integer.parseInt(propertiesObjectPool.getProperty("connectionPool.setMaxWait"))); // 1분대기.
// connectionPool.setWhenExhaustedAction(Integer.parseInt(propertiesObjectPool.getProperty("connectionPool.setWhenExhaustedAction")));
connectionPool.setTestOnBorrow(Boolean.parseBoolean(propertiesObjectPool.getProperty("connectionPool.setTestOnBorrow")));
connectionPool.setTestOnReturn(Boolean.parseBoolean(propertiesObjectPool.getProperty("connectionPool.setTestOnReturn")));
connectionPool.setTestWhileIdle(Boolean.parseBoolean(propertiesObjectPool.getProperty("connectionPool.setTestWhileIdle")));
connectionPool.setTimeBetweenEvictionRunsMillis(Long.parseLong(propertiesObjectPool.getProperty("connectionPool.setTimeBetweenEvictionRunsMillis"))); // 60초에 한번씩 테스트
connectionPool.setMinEvictableIdleTimeMillis(Long.parseLong(propertiesObjectPool.getProperty("connectionPool.setMinEvictableIdleTimeMillis")));
connectionPool.setNumTestsPerEvictionRun(Integer.parseInt(propertiesObjectPool.getProperty("connectionPool.setNumTestsPerEvictionRun")));
connectionPool.setMinIdle(Integer.parseInt(propertiesObjectPool.getProperty("connectionPool.setMinIdle")));
// connectionPool.setSoftMinEvictableIdleTimeMillis(Integer.parseInt(propertiesObjectPool.getProperty("connectionPool.setSoftMinEvictableIdleTimeMillis")));
return connectionPool;
}
public DataSource makeDataSource(final String searchKey, final UserDBDAO userDB) {
DataSource retDataSource = mapDataSource.get(searchKey);
if(retDataSource == null) {
return makePool(searchKey, userDB);
}
return retDataSource;
}
private DataSource getDataSource(final String searchKey) {
return mapDataSource.get(searchKey);
}
public void releaseConnectionPool(final String searchKey) {
GenericObjectPool connectionPool = mapGenericObject.remove(searchKey);
try {
if(connectionPool != null) {
connectionPool.clear();
connectionPool.close();
}
} catch(Exception e) {
logger.error(String.format("**** release connection key is %s", searchKey), e);
} finally {
connectionPool = null;
DataSource ds = mapDataSource.remove(searchKey);
ds = null;
}
}
}