/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* Copyright 2005 - 2008 Pentaho Corporation. All rights reserved.
*
* @created Jul 07, 2008
* @author rmansoor
*/
package org.pentaho.platform.engine.services.connection.datasource.dbcp;
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.pentaho.platform.api.data.DatasourceServiceException;
import org.pentaho.platform.api.data.IDatasourceService;
import org.pentaho.platform.api.engine.ICacheManager;
import org.pentaho.platform.api.repository.datasource.IDatasource;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.util.StringUtil;
import org.pentaho.platform.util.logging.Logger;
public class PooledDatasourceHelper {
public static PoolingDataSource setupPooledDataSource(IDatasource datasource) throws DatasourceServiceException{
try {
PoolingDataSource poolingDataSource = null;
ICacheManager cacheManager = PentahoSystem.getCacheManager(null);
// Read default connecion pooling parameter
String maxdleConn = PentahoSystem.getSystemSetting("dbcp-defaults/max-idle-conn", null); //$NON-NLS-1$
String minIdleConn = PentahoSystem.getSystemSetting("dbcp-defaults/min-idle-conn", null); //$NON-NLS-1$
String maxActConn = PentahoSystem.getSystemSetting("dbcp-defaults/max-act-conn", null); //$NON-NLS-1$
String numIdleConn = PentahoSystem.getSystemSetting("dbcp-defaults/num-idle-conn", null); //$NON-NLS-1$
String validQuery = null;
String whenExhaustedAction = PentahoSystem.getSystemSetting("dbcp-defaults/when-exhausted-action", null); //$NON-NLS-1$
String wait = PentahoSystem.getSystemSetting("dbcp-defaults/wait", null); //$NON-NLS-1$
String testWhileIdleValue = PentahoSystem.getSystemSetting("dbcp-defaults/test-while-idle", null); //$NON-NLS-1$
String testOnBorrowValue = PentahoSystem.getSystemSetting("dbcp-defaults/test-on-borrow", null); //$NON-NLS-1$
String testOnReturnValue = PentahoSystem.getSystemSetting("dbcp-defaults/test-on-return", null); //$NON-NLS-1$
boolean testWhileIdle = !StringUtil.isEmpty(testWhileIdleValue) ? Boolean.parseBoolean(testWhileIdleValue) : false;
boolean testOnBorrow = !StringUtil.isEmpty(testOnBorrowValue) ? Boolean.parseBoolean(testOnBorrowValue) : false;
boolean testOnReturn = !StringUtil.isEmpty(testOnReturnValue) ? Boolean.parseBoolean(testOnReturnValue) : false;
int maxActiveConnection = -1;
int numIdleConnection = -1;
long waitTime = -1;
byte whenExhaustedActionType = -1;
int minIdleConnection = !StringUtil.isEmpty(minIdleConn) ? Integer.parseInt(minIdleConn) : -1;
int maxIdleConnection = !StringUtil.isEmpty(maxdleConn) ? Integer.parseInt(maxdleConn) : -1;
if(datasource.getMaxActConn() >0) {
maxActiveConnection = datasource.getMaxActConn();
} else {
if(!StringUtil.isEmpty(maxActConn)) {
maxActiveConnection = Integer.parseInt(maxActConn);
}
}
if(datasource.getIdleConn() >0) {
numIdleConnection = datasource.getIdleConn();
} else {
if(!StringUtil.isEmpty(numIdleConn)) {
numIdleConnection = Integer.parseInt(numIdleConn);
}
}
if(datasource.getWait() >0) {
waitTime = datasource.getWait();
} else {
if(!StringUtil.isEmpty(wait)) {
waitTime = Long.parseLong(wait);
}
}
if(!StringUtil.isEmpty(datasource.getQuery())) {
validQuery = datasource.getQuery();
}
if(!StringUtil.isEmpty(whenExhaustedAction)) {
whenExhaustedActionType = Byte.parseByte(whenExhaustedAction);
} else {
whenExhaustedActionType = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
}
poolingDataSource = new PoolingDataSource();
Class.forName(datasource.getDriverClass());
// As the name says, this is a generic pool; it returns basic Object-class objects.
final GenericObjectPool pool = new GenericObjectPool(null);
pool.setWhenExhaustedAction(whenExhaustedActionType);
// Tuning the connection pool
pool.setMaxActive(maxActiveConnection);
pool.setMaxIdle(maxIdleConnection);
pool.setMaxWait(waitTime);
pool.setMinIdle(minIdleConnection);
pool.setTestWhileIdle(testWhileIdle);
pool.setTestOnReturn(testOnReturn);
pool.setTestOnBorrow(testOnBorrow);
pool.setTestWhileIdle(testWhileIdle);
/*
ConnectionFactory creates connections on behalf of the pool.
Here, we use the DriverManagerConnectionFactory because that essentially
uses DriverManager as the source of connections.
*/
ConnectionFactory factory = new DriverManagerConnectionFactory(datasource.getUrl(), datasource.getUserName(),
datasource.getPassword());
/*
Puts pool-specific wrappers on factory connections. For clarification:
"[PoolableConnection]Factory," not "Poolable[ConnectionFactory]."
*/
PoolableConnectionFactory pcf = new PoolableConnectionFactory(factory, // ConnectionFactory
pool, // ObjectPool
null, // KeyedObjectPoolFactory
validQuery, // String (validation query)
false, // boolean (default to read-only?)
true // boolean (default to auto-commit statements?)
);
/*
initialize the pool to X connections
*/
Logger.debug(PooledDatasourceHelper.class, "Pool defaults to " + maxActiveConnection + " max active/" + maxIdleConnection + "max idle" + "with " + waitTime + "wait time"//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ " idle connections."); //$NON-NLS-1$
for (int i = 0; i < maxIdleConnection; ++i) {
pool.addObject();
}
Logger.debug(PooledDatasourceHelper.class, "Pool now has " + pool.getNumActive() + " active/" + pool.getNumIdle() + " idle connections."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
/*
All of this is wrapped in a DataSource, which client code should
already know how to handle (since it's the same class of object
they'd fetch via the container's JNDI tree
*/
poolingDataSource.setPool(pool);
// store the pool, so we can get to it later
cacheManager.putInRegionCache(IDatasourceService.JDBC_POOL, datasource.getName(), pool);
return (poolingDataSource);
} catch(Exception e) {
throw new DatasourceServiceException(e);
}
}
}