io.logspace.agent.shaded.mchange.v2.c3p0.DataSources Maven / Gradle / Ivy
/*
* Distributed as part of c3p0 v.0.9.1.1
*
* Copyright (C) 2005 Machinery For Change, Inc.
*
* Author: Steve Waldman
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1, as
* published by the Free Software Foundation.
*
* This software 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; see the file LICENSE. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
package io.logspace.agent.shaded.mchange.v2.c3p0;
import io.logspace.agent.shaded.mchange.v2.log.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.sql.SQLException;
import javax.sql.DataSource;
import javax.sql.ConnectionPoolDataSource;
import io.logspace.agent.shaded.mchange.v2.sql.SqlUtils;
import io.logspace.agent.shaded.mchange.v2.beans.BeansUtils;
/**
* A simple factory class for creating DataSources. Generally, users will call DataSources.unpooledDataSource() to get
* a basic DataSource, and then get a pooled version by calling DataSources.pooledDataSource().
*
* Most users will not need to worry about configuration details. If you want to use a PreparedStatement cache, be sure to call
* the version of DataSources.pooledDataSource() that accepts a statement_cache_size parameter, and set that to
* be a number (much) greater than zero. (For maximum performance, you would set this to be several times the number kinds of
* PreparedStatements you expect your application to use.)
*
* For those interested in detailed configuration, note that c3p0 pools can be configured by explicit method calls on PoolConfig objects,
* by defining System properties, or by defining a c3p0.properties file in your resource path. See {@link io.logspace.agent.shaded.mchange.v2.c3p0.PoolConfig}
* for details.
*
*/
public final class DataSources
{
final static MLogger logger = MLog.getLogger( DataSources.class );
final static Set WRAPPER_CXN_POOL_DATA_SOURCE_OVERWRITE_PROPS; //22 -- includes factory class location
final static Set POOL_BACKED_DATA_SOURCE_OVERWRITE_PROPS; //2 -- includes factory class location, excludes pool-owner id token
static
{
// As of c3p0-0.9.1
//
// This list is no longer updated, as the PoolConfig approach to setting up DataSources
// is now deprecated. (This was getting to be hard to maintain as new config properties
// were added.)
String[] props = new String[]
{
"checkoutTimeout", //1
"acquireIncrement", //2
"acquireRetryAttempts", //3
"acquireRetryDelay", //4
"autoCommitOnClose", //5
"connectionTesterClassName", //6
"forceIgnoreUnresolvedTransactions", //7
"idleConnectionTestPeriod", //8
"initialPoolSize", //9
"maxIdleTime", //10
"maxPoolSize", //11
"maxStatements", //12
"maxStatementsPerConnection", //13
"minPoolSize", //14
"propertyCycle", //15
"breakAfterAcquireFailure", //16
"testConnectionOnCheckout", //17
"testConnectionOnCheckin", //18
"usesTraditionalReflectiveProxies", //19
"preferredTestQuery", //20
"automaticTestTable", //21
"factoryClassLocation" //22
};
WRAPPER_CXN_POOL_DATA_SOURCE_OVERWRITE_PROPS = Collections.unmodifiableSet( new HashSet( Arrays.asList( props ) ) );
// As of c3p0-0.9.1
//
// This list is no longer updated, as the PoolConfig approach to setting up DataSources
// is now deprecated. (This was getting to be hard to maintain as new config properties
// were added.)
props = new String[]
{
"numHelperThreads",
"factoryClassLocation"
};
POOL_BACKED_DATA_SOURCE_OVERWRITE_PROPS = Collections.unmodifiableSet( new HashSet( Arrays.asList( props ) ) );
}
/**
* Defines an unpooled DataSource all of whose paramateres (especially jdbcUrl)
* should be set in config files.
*/
public static DataSource unpooledDataSource() throws SQLException
{
DriverManagerDataSource out = new DriverManagerDataSource();
return out;
}
public static DataSource unpooledDataSource(String jdbcUrl) throws SQLException
{
DriverManagerDataSource out = new DriverManagerDataSource();
out.setJdbcUrl( jdbcUrl );
return out;
}
/**
* Defines an unpooled DataSource on the specified JDBC URL, authenticating with a username and password.
*/
public static DataSource unpooledDataSource(String jdbcUrl, String user, String password) throws SQLException
{
Properties props = new Properties();
props.put(SqlUtils.DRIVER_MANAGER_USER_PROPERTY, user);
props.put(SqlUtils.DRIVER_MANAGER_PASSWORD_PROPERTY, password);
return unpooledDataSource( jdbcUrl, props );
}
/**
* Defines an unpooled DataSource on the specified JDBC URL.
*
* @param driverProps the usual DriverManager properties for your JDBC driver
* (e.g. "user" and "password" for all drivers that support
* authentication)
*
* @see java.sql.DriverManager
*/
public static DataSource unpooledDataSource(String jdbcUrl, Properties driverProps) throws SQLException
{
DriverManagerDataSource out = new DriverManagerDataSource();
out.setJdbcUrl( jdbcUrl );
out.setProperties( driverProps );
return out;
}
/**
* Creates a pooled version of an unpooled DataSource using default configuration information.
* NOTE: By default, statement pooling is turned off, because for simple databases that do
* not pre-parse and optimize PreparedStatements, statement caching is a net
* performance loss. But if your database does optimize PreparedStatements
* you'll want to turn StatementCaching on via {@link #pooledDataSource(javax.sql.DataSource, int)}.
* @return a DataSource that can be cast to a {@link PooledDataSource} if you are interested in pool statistics
*/
public static DataSource pooledDataSource( DataSource unpooledDataSource ) throws SQLException
{ return pooledDataSource( unpooledDataSource, null, (Map) null ); }
/**
* Creates a pooled version of an unpooled DataSource using default configuration information
* and the specified startement cache size.
* Use a value greater than zero to turn statement caching on.
*
* @return a DataSource that can be cast to a {@link PooledDataSource} if you are interested in pool statistics
*/
public static DataSource pooledDataSource( DataSource unpooledDataSource, int statement_cache_size ) throws SQLException
{
// PoolConfig pcfg = new PoolConfig();
// pcfg.setMaxStatements( statement_cache_size );
Map overrideProps = new HashMap();
overrideProps.put( "maxStatements", new Integer( statement_cache_size ) );
return pooledDataSource( unpooledDataSource, null, overrideProps );
}
/**
* Creates a pooled version of an unpooled DataSource using configuration
* information supplied explicitly by a {@link io.logspace.agent.shaded.mchange.v2.c3p0.PoolConfig}.
*
* @return a DataSource that can be cast to a {@link PooledDataSource} if you are interested in pool statistics
*
* @deprecated if you want to set properties programmatically, please construct a ComboPooledDataSource and
* set its properties rather than using PoolConfig
*/
public static DataSource pooledDataSource( DataSource unpooledDataSource, PoolConfig pcfg ) throws SQLException
{
try
{
WrapperConnectionPoolDataSource wcpds = new WrapperConnectionPoolDataSource();
wcpds.setNestedDataSource( unpooledDataSource );
// set PoolConfig info -- WrapperConnectionPoolDataSource properties
BeansUtils.overwriteSpecificAccessibleProperties( pcfg, wcpds, WRAPPER_CXN_POOL_DATA_SOURCE_OVERWRITE_PROPS );
PoolBackedDataSource nascent_pbds = new PoolBackedDataSource();
nascent_pbds.setConnectionPoolDataSource( wcpds );
BeansUtils.overwriteSpecificAccessibleProperties( pcfg, nascent_pbds, POOL_BACKED_DATA_SOURCE_OVERWRITE_PROPS );
return nascent_pbds;
}
// catch ( PropertyVetoException e )
// {
// e.printStackTrace();
// PropertyChangeEvent evt = e.getPropertyChangeEvent();
// throw new SQLException("Illegal value attempted for property " + evt.getPropertyName() + ": " + evt.getNewValue());
// }
catch ( Exception e )
{
//e.printStackTrace();
SQLException sqle = SqlUtils.toSQLException("Exception configuring pool-backed DataSource: " + e, e);
if (Debug.DEBUG && Debug.TRACE >= Debug.TRACE_MED && logger.isLoggable( MLevel.FINE ) && e != sqle)
logger.log( MLevel.FINE, "Converted exception to throwable SQLException", e );
throw sqle;
}
}
/*
public static DataSource pooledDataSource( DataSource unpooledDataSource, String overrideDefaultUser, String overrideDefaultPassword ) throws SQLException
{
Map overrideProps;
if (overrideDefaultUser != null)
{
overrideProps = new HashMap();
overrideProps.put( "overrideDefaultUser", overrideDefaultUser );
overrideProps.put( "overrideDefaultPassword", overrideDefaultPassword );
}
else
overrideProps = null;
return pooledDataSource( unpooledDataSource, null, overrideProps );
}
*/
public static DataSource pooledDataSource( DataSource unpooledDataSource, String configName ) throws SQLException
{ return pooledDataSource( unpooledDataSource, configName, null ); }
public static DataSource pooledDataSource( DataSource unpooledDataSource, Map overrideProps ) throws SQLException
{ return pooledDataSource( unpooledDataSource, null, overrideProps ); }
public static DataSource pooledDataSource( DataSource unpooledDataSource, String configName, Map overrideProps ) throws SQLException
{
try
{
WrapperConnectionPoolDataSource wcpds = new WrapperConnectionPoolDataSource(configName);
wcpds.setNestedDataSource( unpooledDataSource );
if (overrideProps != null)
BeansUtils.overwriteAccessiblePropertiesFromMap( overrideProps,
wcpds,
false,
null,
true,
MLevel.WARNING,
MLevel.WARNING,
false);
PoolBackedDataSource nascent_pbds = new PoolBackedDataSource(configName);
nascent_pbds.setConnectionPoolDataSource( wcpds );
if (overrideProps != null)
BeansUtils.overwriteAccessiblePropertiesFromMap( overrideProps,
nascent_pbds,
false,
null,
true,
MLevel.WARNING,
MLevel.WARNING,
false);
return nascent_pbds;
}
// catch ( PropertyVetoException e )
// {
// e.printStackTrace();
// PropertyChangeEvent evt = e.getPropertyChangeEvent();
// throw new SQLException("Illegal value attempted for property " + evt.getPropertyName() + ": " + evt.getNewValue());
// }
catch ( Exception e )
{
//e.printStackTrace();
SQLException sqle = SqlUtils.toSQLException("Exception configuring pool-backed DataSource: " + e, e);
if (Debug.DEBUG && Debug.TRACE >= Debug.TRACE_MED && logger.isLoggable( MLevel.FINE ) && e != sqle)
logger.log( MLevel.FINE, "Converted exception to throwable SQLException", e );
throw sqle;
}
}
/**
*
Creates a pooled version of an unpooled DataSource using configuration
* information supplied explicitly by a Java Properties object.
*
* @return a DataSource that can be cast to a {@link PooledDataSource} if you are interested in pool statistics
* @see io.logspace.agent.shaded.mchange.v2.c3p0.PoolConfig
*/
public static DataSource pooledDataSource( DataSource unpooledDataSource, Properties props ) throws SQLException
{
//return pooledDataSource( unpooledDataSource, new PoolConfig( props ) );
Properties peeledProps = new Properties();
for (Iterator ii = props.keySet().iterator(); ii.hasNext(); )
{
String propKey = (String) ii.next();
String propVal = props.getProperty( propKey );
String peeledKey = (propKey.startsWith("c3p0.") ? propKey.substring(5) : propKey );
peeledProps.put( peeledKey, propVal );
}
return pooledDataSource( unpooledDataSource, null, peeledProps );
}
/**
* Immediately releases resources (Threads and database Connections) that are
* held by a C3P0 DataSource.
*
*
Only DataSources created by the poolingDataSource() method hold any
* non-memory resources. Calling this method on unpooled DataSources is
* effectively a no-op.
*
* You can safely presume that destroying a pooled DataSource that is wrapped around
* another DataSource created by this library destroys both the outer and the wrapped
* DataSource. There is no reason to hold a reference to a nested DataSource in order
* to explicitly destroy it.
*
* @see io.logspace.agent.shaded.mchange.v2.c3p0.PoolConfig
*/
public static void destroy( DataSource pooledDataSource ) throws SQLException
{ destroy( pooledDataSource, false ); }
/**
* @deprecated forceDestroy() is no longer meaningful, as a set of pools is now
* directly associated with a DataSource, and not potentially shared.
* (This simplification was made possible by canonicalization of
* JNDI-looked-up DataSources within a virtual machine.) Just use
* DataSources.destroy().
*
* @see #destroy
*/
public static void forceDestroy( DataSource pooledDataSource ) throws SQLException
{ destroy( pooledDataSource, true ); }
private static void destroy( DataSource pooledDataSource, boolean force ) throws SQLException
{
if ( pooledDataSource instanceof PoolBackedDataSource)
{
ConnectionPoolDataSource cpds = ((PoolBackedDataSource) pooledDataSource).getConnectionPoolDataSource();
if (cpds instanceof WrapperConnectionPoolDataSource)
destroy( ((WrapperConnectionPoolDataSource) cpds).getNestedDataSource(), force );
}
if ( pooledDataSource instanceof PooledDataSource )
((PooledDataSource) pooledDataSource).close( force );
}
private DataSources()
{}
}