package org.opensource.clearpool.core; import java.io.Closeable; import java.sql.Connection; import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.sql.CommonDataSource; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import org.opensource.clearpool.configuration.ConfigurationVO; import org.opensource.clearpool.configuration.JDBCConfiguration; import org.opensource.clearpool.configuration.XMLConfiguration; import org.opensource.clearpool.configuration.console.Console; import org.opensource.clearpool.datasource.AbstractDataSource; import org.opensource.clearpool.exception.ConnectionPoolXMLParseException; /** * This class is used by IOC container.Or you can use it by programming. * * @author xionghui * @date 26.07.2014 * @version 1.0 */ public class ClearPoolDataSource extends AbstractDataSource implements IConnectionPool, Closeable, ConnectionPoolDataSource { private static volatile boolean isInited = false; private Lock lock = new ReentrantLock(); private String poolPath; private boolean isUsePath; private ConfigurationVO vo = new ConfigurationVO(); private boolean isUseVO; private Console console; private CommonDataSource dataSource; private String driverClassName; private String jdbcUrl; private String jdbcUser; private String jdbcPassword; public static String getEncoding() { return XMLConfiguration.getEncoding(); } public static void setEncoding(String encoding) { XMLConfiguration.setEncoding(encoding); } public void setPoolPath(String poolPath) { if (this.isUseVO) { throw new ConnectionPoolXMLParseException( "we shouldn't use ConfigurationVO and poolPath at the same time"); } this.isUsePath = true; this.poolPath = poolPath; } public void setPort(int port) { this.checkCfgLegal(); if (this.console == null) { this.console = new Console(); } this.console.setPort(port); } public void setSecurityMap(Map<String, String> securityMap) { this.checkCfgLegal(); if (this.console == null) { this.console = new Console(); } this.console.setSecurityMap(securityMap); } public void setAlias(String poolName) { this.checkCfgLegal(); this.vo.setAlias(poolName); } public void setDataSource(CommonDataSource dataSource) { this.checkCfgLegal(); if (this.driverClassName != null || this.jdbcUrl != null || this.jdbcUser != null || this.jdbcPassword != null) { throw new ConnectionPoolXMLParseException( "we shouldn't use JDBC and dataSource at the same time"); } this.dataSource = dataSource; } public void setDriverClassName(String driverClassName) { this.checkCfgLegal(); boolean noneChange = (this.driverClassName == null ? driverClassName == null : this.driverClassName.equals(driverClassName)); if (noneChange) { return; } this.checkAndInitJDBC(); this.driverClassName = driverClassName; } public void setJdbcUrl(String jdbcUrl) { this.checkCfgLegal(); boolean noneChange = (this.jdbcUrl == null ? jdbcUrl == null : this.jdbcUrl.equals(jdbcUrl)); if (noneChange) { return; } this.checkAndInitJDBC(); this.jdbcUrl = jdbcUrl; } public void setJdbcUser(String jdbcUser) { this.checkCfgLegal(); boolean noneChange = (this.jdbcUser == null ? jdbcUser == null : this.jdbcUser.equals(jdbcUser)); if (noneChange) { return; } this.checkAndInitJDBC(); this.jdbcUser = jdbcUser; } public void setJdbcPassword(String jdbcPassword) { this.checkCfgLegal(); boolean noneChange = (this.jdbcPassword == null ? jdbcPassword == null : this.jdbcPassword.equals(jdbcPassword)); if (noneChange) { return; } this.checkAndInitJDBC(); this.jdbcPassword = jdbcPassword; } public void setJtaSupport(boolean jtaSupport) { this.checkCfgLegal(); this.vo.setJtaSupport(jtaSupport); } public void setCorePoolSize(int corePoolSize) { this.checkCfgLegal(); this.vo.setCorePoolSize(corePoolSize); } public void setMaxPoolSize(int maxPoolSize) { this.checkCfgLegal(); this.vo.setMaxPoolSize(maxPoolSize); } public void setAcquireIncrement(int acquireIncrement) { this.checkCfgLegal(); this.vo.setAcquireIncrement(acquireIncrement); } public void setAcquireRetryTimes(int acquireRetryTimes) { this.checkCfgLegal(); this.vo.setAcquireRetryTimes(acquireRetryTimes); } public void setUselessConnectionException(boolean uselessConnectionException) { this.checkCfgLegal(); this.vo.setUselessConnectionException(uselessConnectionException); } public void setLimitIdleTime(long limitIdleTime) { this.checkCfgLegal(); this.vo.setLimitIdleTime(limitIdleTime); } public void setKeepTestPeriod(long keepTestPeriod) { this.checkCfgLegal(); this.vo.setKeepTestPeriod(keepTestPeriod); } public void setTestTableName(String testTableName) { this.checkCfgLegal(); this.vo.setTestTableName(testTableName); } public void setTestBeforeUse(boolean testBeforeUse) { this.checkCfgLegal(); this.vo.setTestBeforeUse(testBeforeUse); } public void setTestQuerySql(String testQuerySql) { this.checkCfgLegal(); this.vo.setTestQuerySql(testQuerySql); } public void setShowSql(boolean showSql) { this.checkCfgLegal(); this.vo.setShowSql(showSql); } public void setSqlTimeFilter(long sqlTimeFilter) { this.checkCfgLegal(); this.vo.setSqlTimeFilter(sqlTimeFilter); } /** * Check if cfg is legal. */ private void checkCfgLegal() { if (this.isUsePath) { throw new ConnectionPoolXMLParseException( "we shouldn't use poolPath and ConfigurationVO at the same time"); } this.isUseVO = true; } /** * Check if JDBC is legal,and we will init it if necessary. */ private void checkAndInitJDBC() { if (this.dataSource != null) { throw new ConnectionPoolXMLParseException( "we shouldn't use dataSource and JDBC at the same time"); } } /** * Init the pool */ @Override public void init() { if (isInited) { return; } this.lock.lock(); try { if (isInited) { return; } if (!this.isUseVO) { // Note:if we haven't set poolPath and ConfigurationVO,we will // use // the default path to init pool this.initPath(this.poolPath); } else { if (this.dataSource == null && (this.driverClassName != null || this.jdbcUrl != null || this.jdbcUser != null || this.jdbcPassword != null)) { // we are trying to use jdbc driver if dataSource is null. this.dataSource = JDBCConfiguration.getDataSource(this.driverClassName, this.jdbcUrl, this.jdbcUser, this.jdbcPassword); } this.vo.setCommonDataSource(this.dataSource); ConfigurationVO.setConsole(this.console); this.initVO(this.vo); } isInited = true; } finally { this.lock.unlock(); } } /** * Init pool by the given path */ @Override public void initPath(String path) { if (isInited) { return; } this.lock.lock(); try { if (isInited) { return; } ConnectionPoolImpl.getInstance().initPath(path); isInited = true; } finally { this.lock.unlock(); } } @Override public void initVO(ConfigurationVO vo) { if (isInited) { return; } this.lock.lock(); try { if (isInited) { return; } ConnectionPoolImpl.getInstance().initVO(vo); isInited = true; } finally { this.lock.unlock(); } } @Override public void initVOList(List<ConfigurationVO> voList) { if (isInited) { return; } this.lock.lock(); try { if (isInited) { return; } ConnectionPoolImpl.getInstance().initVOList(voList); isInited = true; } finally { this.lock.unlock(); } } @Override public Connection getConnection() throws SQLException { this.init(); return ConnectionPoolImpl.getInstance().getConnection(); } @Override public Connection getConnection(String name) throws SQLException { this.init(); return ConnectionPoolImpl.getInstance().getConnection(name); } @Override public PooledConnection getPooledConnection() throws SQLException { this.init(); return ConnectionPoolImpl.getInstance().getPooledConnection(); } @Override public PooledConnection getPooledConnection(String name) throws SQLException { this.init(); return ConnectionPoolImpl.getInstance().getPooledConnection(name); } @Override public PooledConnection getPooledConnection(String user, String password) throws SQLException { throw new UnsupportedOperationException("not supported yet"); } @Override public void close(String name) { ConnectionPoolImpl.getInstance().close(name); } @Override public void close() { ConnectionPoolImpl.getInstance().close(); } @Override public void destory() { ConnectionPoolImpl.getInstance().destory(); } }