Recombine into a single Java 7 compatible build.

pull/295/head
Brett Wooldridge 10 years ago
parent 32d6668a6a
commit ded61125fe

@ -1,18 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>HikariCP-common</artifactId>
<packaging>jar</packaging>
<name>hikaricp-common</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-parent</artifactId>
<version>2.3.4-SNAPSHOT</version>
</parent>
</project>

@ -1,41 +0,0 @@
/*
* Copyright (C) 2013 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Interface whose implementers can perform one-time customization of a
* Connection before it is added to the pool. Note the implemention
* of the <code>customize()</code> method must be multithread-safe as
* it may be called by multiple threads at one time.
*
* @author Brett Wooldridge
*/
public interface IConnectionCustomizer
{
/**
* The Connection object that is passed into this method is the "raw"
* Connection instance provided by the JDBC driver, not a wrapped
* HikariCP connection.
*
* @param connection a native JDBC driver Connection instance to customize
* @throws SQLException should be thrown if an error condition is encountered during customization
*/
void customize(Connection connection) throws SQLException;
}

@ -1,261 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- For release: mvn release:perform -Darguments=-Dgpg.passphrase=PASSPHRASE -->
<artifactId>HikariCP-java6</artifactId>
<packaging>bundle</packaging>
<name>HikariCP-java6</name>
<description>Ultimate JDBC Connection Pool</description>
<url>https://github.com/brettwooldridge/HikariCP</url>
<organization>
<name>Zaxxer.com</name>
<url>https://github.com/brettwooldridge</url>
</organization>
<scm>
<connection>scm:git:git@github.com:brettwooldridge/HikariCP.git</connection>
<developerConnection>scm:git:git@github.com:brettwooldridge/HikariCP.git</developerConnection>
<url>git@github.com:brettwooldridge/HikariCP.git</url>
<tag>HikariCP-2.3.2</tag>
</scm>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<name>Brett Wooldridge</name>
<email>brett.wooldridge@gmail.com</email>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<felix.bundle.plugin.version>2.5.3</felix.bundle.plugin.version>
<felix.version>4.6.0</felix.version>
</properties>
<parent>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-parent</artifactId>
<version>2.3.6-SNAPSHOT</version>
</parent>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>src</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../hikaricp-common/src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>test</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>../hikaricp-common/src/test/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>test-resources</id>
<phase>generate-test-resources</phase>
<goals>
<goal>add-test-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>../hikaricp-common/src/test/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<extensions>true</extensions>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${felix.bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Name>HikariCP-java6</Bundle-Name>
<Export-Package>
com.zaxxer.hikari,
com.zaxxer.hikari.hibernate
</Export-Package>
<Private-Package>com.zaxxer.hikari.*</Private-Package>
<_exportcontents>
com.zaxxer.hikari.pool,
com.zaxxer.hikari.util,
com.zaxxer.hikari.proxy
</_exportcontents>
<Import-Package>
javassist.*,
javax.management,
javax.naming,
javax.naming.spi,
javax.sql,
javax.sql.rowset,
javax.sql.rowset.serial,
javax.sql.rowset.spi,
com.codahale.metrics;resolution:=optional,
com.codahale.metrics.health;resolution:=optional,
org.slf4j;version="[1.6,2)",
org.hibernate;resolution:=optional,
org.hibernate.cfg;resolution:=optional,
org.hibernate.engine.jdbc.connections.spi;resolution:=optional,
org.hibernate.service;resolution:=optional,
org.hibernate.service.spi;resolution:=optional
</Import-Package>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
<executions>
<!-- This execution makes sure that the manifest is available when the tests are executed -->
<execution>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5</version>
<configuration>
<tagNameFormat>HikariCP-@{project.version}</tagNameFormat>
</configuration>
</plugin>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.felix</groupId>
<artifactId>
maven-bundle-plugin
</artifactId>
<versionRange>[2.4.0,)</versionRange>
<goals>
<goal>manifest</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<profiles>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>felix</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>pax.exam.framework</name>
<value>felix</value>
</property>
</activation>
<properties>
<pax.exam.framework>felix</pax.exam.framework>
<pax.exam.logging>none</pax.exam.logging>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>${felix.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

@ -1,87 +0,0 @@
/*
* Copyright (C) 2013, 2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import com.zaxxer.hikari.proxy.JavassistProxyFactory;
import com.zaxxer.hikari.util.PropertyBeanSetter;
public class HikariConfig extends AbstractHikariConfig
{
static {
JavassistProxyFactory.initialize();
}
/**
* Default constructor
*/
public HikariConfig()
{
super();
}
/**
* Construct a HikariConfig from the specified properties object.
*
* @param properties the name of the property file
*/
public HikariConfig(Properties properties)
{
super(properties);
}
/**
* Construct a HikariConfig from the specified property file name. <code>propertyFileName</code>
* will first be treated as a path in the file-system, and if that fails the
* ClassLoader.getResourceAsStream(propertyFileName) will be tried.
*
* @param propertyFileName the name of the property file
*/
public HikariConfig(String propertyFileName)
{
super(propertyFileName);
}
protected void loadProperties(String propertyFileName)
{
final File propFile = new File(propertyFileName);
try {
final InputStream is = propFile.isFile() ? new FileInputStream(propFile) : this.getClass().getResourceAsStream(propertyFileName);
if (is != null) {
try {
Properties props = new Properties();
props.load(is);
PropertyBeanSetter.setTargetFromProperties(this, props);
}
finally {
is.close();
}
}
else {
throw new IllegalArgumentException("Property file " + propertyFileName + " was not found.");
}
}
catch (IOException io) {
throw new RuntimeException("Error loading properties file", io);
}
}
}

@ -1,252 +0,0 @@
/*
* Copyright (C) 2013,2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.pool;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
import static com.zaxxer.hikari.util.UtilityElf.quietlySleep;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.util.ConcurrentBag;
import com.zaxxer.hikari.util.IBagStateListener;
import com.zaxxer.hikari.util.Java6ConcurrentBag;
/**
* This is the primary connection pool class that provides the basic
* pooling behavior for HikariCP.
*
* @author Brett Wooldridge
*/
public final class HikariPool extends BaseHikariPool
{
/**
* Construct a HikariPool with the specified configuration.
*
* @param configuration a HikariConfig instance
*/
public HikariPool(HikariConfig configuration)
{
this(configuration, configuration.getUsername(), configuration.getPassword());
}
/**
* Construct a HikariPool with the specified configuration.
*
* @param configuration a HikariConfig instance
* @param username authentication username
* @param password authentication password
*/
public HikariPool(HikariConfig configuration, String username, String password)
{
super(configuration, username, password);
}
// ***********************************************************************
// IBagStateListener callback
// ***********************************************************************
/** {@inheritDoc} */
@Override
public void addBagItem()
{
class AddConnection implements Runnable
{
public void run()
{
long sleepBackoff = 200L;
final int maxPoolSize = configuration.getMaximumPoolSize();
while (poolState == POOL_RUNNING && totalConnections.get() < maxPoolSize && !addConnection()) {
// If we got into the loop, addConnection() failed, so we sleep and retry
quietlySleep(sleepBackoff);
sleepBackoff = Math.min(connectionTimeout / 2, (long) ((double) sleepBackoff * 1.5));
}
}
}
addConnectionExecutor.execute(new AddConnection());
}
// ***********************************************************************
// HikariPoolMBean methods
// ***********************************************************************
/** {@inheritDoc} */
@Override
public void softEvictConnections()
{
for (PoolBagEntry bagEntry : connectionBag.values(STATE_IN_USE)) {
bagEntry.evicted = true;
}
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(bagEntry)) {
closeConnection(bagEntry);
}
}
}
// ***********************************************************************
// Protected methods
// ***********************************************************************
/**
* Permanently close the real (underlying) connection (eat any exception).
*
* @param connectionProxy the connection to actually close
*/
@Override
protected void closeConnection(final PoolBagEntry bagEntry)
{
bagEntry.cancelMaxLifeTermination();
if (connectionBag.remove(bagEntry)) {
final int tc = totalConnections.decrementAndGet();
if (tc < 0) {
LOGGER.warn("Internal accounting inconsistency, totalConnections={}", tc, new Exception());
}
closeConnectionExecutor.execute(new Runnable() {
public void run() {
poolUtils.quietlyCloseConnection(bagEntry.connection);
}
});
}
}
/**
* Check whether the connection is alive or not.
*
* @param connection the connection to test
* @param timeoutMs the timeout before we consider the test a failure
* @return true if the connection is alive, false if it is not alive or we timed out
*/
@Override
protected boolean isConnectionAlive(final Connection connection)
{
try {
final int timeoutSec = (int) TimeUnit.MILLISECONDS.toSeconds(validationTimeout);
if (isUseJdbc4Validation) {
return connection.isValid(timeoutSec);
}
final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, validationTimeout);
Statement statement = connection.createStatement();
try {
poolUtils.setQueryTimeout(statement, timeoutSec);
statement.executeQuery(configuration.getConnectionTestQuery());
}
finally {
statement.close();
}
if (isIsolateInternalQueries && !isAutoCommit) {
connection.rollback();
}
poolUtils.setNetworkTimeout(connection, originalTimeout);
return true;
}
catch (SQLException e) {
LOGGER.warn("Exception during keep alive check, that means the connection ({}) must be dead.", connection, e);
return false;
}
}
/**
* Attempt to abort() active connections on Java7+, or close() them on Java6.
*
* @throws InterruptedException
*/
@Override
protected void abortActiveConnections(final ExecutorService assassinExecutor) throws InterruptedException
{
for (PoolBagEntry bagEntry : connectionBag.values(STATE_IN_USE)) {
try {
bagEntry.aborted = bagEntry.evicted = true;
bagEntry.connection.abort(assassinExecutor);
}
catch (Throwable e) {
if (e instanceof InterruptedException) {
throw (InterruptedException) e;
}
poolUtils.quietlyCloseConnection(bagEntry.connection);
}
finally {
if (connectionBag.remove(bagEntry)) {
totalConnections.decrementAndGet();
}
}
}
}
/** {@inheritDoc} */
@Override
protected Runnable getHouseKeeper()
{
return new HouseKeeper();
}
/** {@inheritDoc} */
@Override
protected ConcurrentBag<PoolBagEntry> createConcurrentBag(IBagStateListener listener)
{
return new Java6ConcurrentBag(listener);
}
// ***********************************************************************
// Non-anonymous Inner-classes
// ***********************************************************************
/**
* The house keeping task to retire idle connections.
*/
private class HouseKeeper implements Runnable
{
@Override
public void run()
{
logPoolState("Before cleanup ");
connectionTimeout = configuration.getConnectionTimeout(); // refresh member in case it changed
final long now = System.currentTimeMillis();
final long idleTimeout = configuration.getIdleTimeout();
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(bagEntry)) {
if (bagEntry.evicted || (idleTimeout > 0L && now > bagEntry.lastAccess + idleTimeout)) {
closeConnection(bagEntry);
}
else {
connectionBag.unreserve(bagEntry);
}
}
}
logPoolState("After cleanup ");
fillPool(); // Try to maintain minimum connections
}
}
}

@ -1,270 +0,0 @@
/*
* Copyright (C) 2013, 2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.proxy;
import java.lang.reflect.Array;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.Modifier;
import javassist.NotFoundException;
import com.zaxxer.hikari.util.ClassLoaderUtils;
/**
* This class generates the proxy objects for {@link Connection}, {@link Statement},
* {@link PreparedStatement}, and {@link CallableStatement}. Additionally it injects
* method bodies into the {@link ProxyFactory} class methods that can instantiate
* instances of the generated proxies.
*
* @author Brett Wooldridge
*/
public final class JavassistProxyFactory
{
private ClassPool classPool;
static {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(JavassistProxyFactory.class.getClassLoader());
JavassistProxyFactory proxyFactoryFactory = new JavassistProxyFactory();
proxyFactoryFactory.modifyProxyFactory();
}
catch (Exception e) {
throw new RuntimeException("Fatal exception during proxy generation", e);
}
finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
/**
* Simply invoking this method causes the initialization of this class. All work
* by this class is performed in static initialization.
*/
public static void initialize()
{
// no-op
}
private JavassistProxyFactory() throws Exception {
classPool = new ClassPool();
classPool.importPackage("java.sql");
classPool.appendClassPath(new LoaderClassPath(this.getClass().getClassLoader()));
// Cast is not needed for these
String methodBody = "{ try { return delegate.method($$); } catch (SQLException e) { throw checkException(e); } }";
generateProxyClass(Connection.class, ConnectionProxy.class, methodBody);
generateProxyClass(Statement.class, StatementProxy.class, methodBody);
generateProxyClass(ResultSet.class, ResultSetProxy.class, methodBody);
// For these we have to cast the delegate
methodBody = "{ try { return ((cast) delegate).method($$); } catch (SQLException e) { throw checkException(e); } }";
generateProxyClass(PreparedStatement.class, PreparedStatementProxy.class, methodBody);
generateProxyClass(CallableStatement.class, CallableStatementProxy.class, methodBody);
}
private void modifyProxyFactory() throws Exception
{
String packageName = JavassistProxyFactory.class.getPackage().getName();
CtClass proxyCt = classPool.getCtClass("com.zaxxer.hikari.proxy.ProxyFactory");
for (CtMethod method : proxyCt.getMethods()) {
String methodName = method.getName();
if ("getProxyConnection".equals(methodName)) {
method.setBody("{return new " + packageName + ".ConnectionJavassistProxy($$);}");
}
else if ("getProxyStatement".equals(methodName)) {
method.setBody("{return new " + packageName + ".StatementJavassistProxy($$);}");
}
else if ("getProxyPreparedStatement".equals(methodName)) {
method.setBody("{return new " + packageName + ".PreparedStatementJavassistProxy($$);}");
}
else if ("getProxyCallableStatement".equals(methodName)) {
method.setBody("{return new " + packageName + ".CallableStatementJavassistProxy($$);}");
}
else if ("getProxyResultSet".equals(methodName)) {
method.setBody("{return new " + packageName + ".ResultSetJavassistProxy($$);}");
}
}
proxyCt.toClass(classPool.getClassLoader(), getClass().getProtectionDomain());
}
/**
* Generate Javassist Proxy Classes
*/
@SuppressWarnings("unchecked")
private <T> Class<T> generateProxyClass(Class<T> primaryInterface, Class<?> superClass, String methodBody) throws Exception
{
// Make a new class that extends one of the JavaProxy classes (ie. superClass); use the name to XxxJavassistProxy instead of XxxProxy
String superClassName = superClass.getName();
CtClass superClassCt = classPool.getCtClass(superClassName);
CtClass targetCt = classPool.makeClass(superClassName.replace("Proxy", "JavassistProxy"), superClassCt);
targetCt.setModifiers(Modifier.FINAL);
// Make a set of method signatures we inherit implementation for, so we don't generate delegates for these
Set<String> superSigs = new HashSet<String>();
for (CtMethod method : superClassCt.getMethods()) {
if ((method.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
superSigs.add(method.getName() + method.getSignature());
}
}
Set<String> methods = new HashSet<String>();
Set<Class<?>> interfaces = ClassLoaderUtils.getAllInterfaces(primaryInterface);
for (Class<?> intf : interfaces) {
CtClass intfCt = classPool.getCtClass(intf.getName());
targetCt.addInterface(intfCt);
for (CtMethod intfMethod : intfCt.getDeclaredMethods()) {
final String signature = intfMethod.getName() + intfMethod.getSignature();
// don't generate delegates for methods we override
if (superSigs.contains(signature)) {
continue;
}
// Ignore already added methods that come from other interfaces
if (methods.contains(signature)) {
continue;
}
// Ignore default methods (only for Jre8 or later)
if (isDefaultMethod(intf, intfCt, intfMethod)) {
continue;
}
// Track what methods we've added
methods.add(signature);
// Clone the method we want to inject into
CtMethod method = CtNewMethod.copy(intfMethod, targetCt, null);
String modifiedBody = methodBody;
// If the super-Proxy has concrete methods (non-abstract), transform the call into a simple super.method() call
CtMethod superMethod = superClassCt.getMethod(intfMethod.getName(), intfMethod.getSignature());
if ((superMethod.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT) {
modifiedBody = modifiedBody.replace("((cast) ", "");
modifiedBody = modifiedBody.replace("delegate", "super");
modifiedBody = modifiedBody.replace("super)", "super");
}
modifiedBody = modifiedBody.replace("cast", primaryInterface.getName());
// Generate a method that simply invokes the same method on the delegate
if (isThrowsSqlException(intfMethod)) {
modifiedBody = modifiedBody.replace("method", method.getName());
}
else {
modifiedBody = "{ return ((cast) delegate).method($$); }".replace("method", method.getName()).replace("cast", primaryInterface.getName());
}
if (method.getReturnType() == CtClass.voidType) {
modifiedBody = modifiedBody.replace("return", "");
}
method.setBody(modifiedBody);
targetCt.addMethod(method);
}
}
return targetCt.toClass(classPool.getClassLoader(), getClass().getProtectionDomain());
}
private boolean isThrowsSqlException(CtMethod method)
{
try {
for (CtClass clazz : method.getExceptionTypes()) {
if (clazz.getSimpleName().equals("SQLException")) {
return true;
}
}
}
catch (NotFoundException e) {
// fall thru
}
return false;
}
private boolean isDefaultMethod(Class<?> intf, CtClass intfCt, CtMethod intfMethod) throws Exception
{
List<Class<?>> paramTypes = new ArrayList<Class<?>>();
for (CtClass pt : intfMethod.getParameterTypes()) {
paramTypes.add(toJavaClass(pt));
}
return intf.getDeclaredMethod(intfMethod.getName(), paramTypes.toArray(new Class[0])).toString().contains("default ");
}
private Class<?> toJavaClass(CtClass cls) throws Exception
{
if (cls.getName().endsWith("[]")) {
return Array.newInstance(toJavaClass(cls.getName().replace("[]", "")), 0).getClass();
}
else {
return toJavaClass(cls.getName());
}
}
private Class<?> toJavaClass(String cn) throws Exception
{
if ("int".equals(cn)) {
return int.class;
}
if ("long".equals(cn)) {
return long.class;
}
if ("short".equals(cn)) {
return short.class;
}
if ("byte".equals(cn)) {
return byte.class;
}
if ("float".equals(cn)) {
return float.class;
}
if ("double".equals(cn)) {
return double.class;
}
if ("boolean".equals(cn)) {
return boolean.class;
}
if ("char".equals(cn)) {
return char.class;
}
if ("void".equals(cn)) {
return void.class;
}
return Class.forName(cn);
}
}

@ -1,132 +0,0 @@
/*
* Copyright (C) 2013, 2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.util;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
import static com.zaxxer.hikari.util.UtilityElf.IS_JAVA7;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
import com.zaxxer.hikari.pool.PoolBagEntry;
/**
* This is a specialized concurrent bag that achieves superior performance
* to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a
* connection pool. It uses ThreadLocal storage when possible to avoid
* locks, but resorts to scanning a common collection if there are no
* available items in the ThreadLocal list. Not-in-use items in the
* ThreadLocal lists can be "stolen" when the borrowing thread has none
* of its own. It is a "lock-less" implementation using a specialized
* AbstractQueuedLongSynchronizer to manage cross-thread signaling.
*
* Note that items that are "borrowed" from the bag are not actually
* removed from any collection, so garbage collection will not occur
* even if the reference is abandoned. Thus care must be taken to
* "requite" borrowed objects otherwise a memory leak will result. Only
* the "remove" method can completely remove an object from the bag.
*
* @author Brett Wooldridge
*
* @param <T> the templated type to store in the bag
*/
public final class Java6ConcurrentBag extends ConcurrentBag<PoolBagEntry>
{
public Java6ConcurrentBag(IBagStateListener listener)
{
super(listener);
}
@Override
protected AbstractQueuedLongSynchronizer createQueuedSynchronizer()
{
return new Synchronizer();
}
/**
* This method provides a "snaphot" in time of the BagEntry
* items in the bag in the specified state. It does not "lock"
* or reserve items in any way. Call <code>reserve(BagEntry)</code>
* on items in list before performing any action on them.
*
* @param state one of STATE_NOT_IN_USE or STATE_IN_USE
* @return a possibly empty list of objects having the state specified
*/
public List<PoolBagEntry> values(final int state)
{
final ArrayList<PoolBagEntry> list = new ArrayList<PoolBagEntry>(sharedList.size());
if (state == STATE_IN_USE || state == STATE_NOT_IN_USE) {
for (final PoolBagEntry reference : sharedList) {
if (reference.state.get() == state) {
list.add(reference);
}
}
}
return list;
}
/**
* Get a count of the number of items in the specified state at the time of this call.
*
* @param state the state of the items to count
* @return a count of how many items in the bag are in the specified state
*/
public int getCount(final int state)
{
int count = 0;
for (final PoolBagEntry reference : sharedList) {
if (reference.state.get() == state) {
count++;
}
}
return count;
}
/**
* Our private synchronizer that handles notify/wait type semantics.
*/
private static final class Synchronizer extends AbstractQueuedLongSynchronizer
{
private static final long serialVersionUID = 104753538004341218L;
@Override
protected long tryAcquireShared(long seq)
{
return getState() > seq && !java67hasQueuedPredecessors() ? 1L : -1L;
}
/** {@inheritDoc} */
@Override
protected boolean tryReleaseShared(long updateSeq)
{
setState(updateSeq);
return true;
}
private boolean java67hasQueuedPredecessors()
{
if (IS_JAVA7) {
return hasQueuedPredecessors();
}
return false;
}
}
}

@ -1,210 +0,0 @@
# This is a manually maintained codex of JDBC drivers and the
# classes within that need to be instrumented.
#
# ------ HSQLDB v2.3.1 ----------------------------------------------------------
#
org.hsqldb.jdbc.JDBCDataSource=hsqldb
hsqldb.baseConnection=org.hsqldb.jdbc.JDBCConnection
hsqldb.baseStatement=org.hsqldb.jdbc.JDBCStatement
hsqldb.basePreparedStatement=org.hsqldb.jdbc.JDBCPreparedStatement
hsqldb.subCallableStatement=org.hsqldb.jdbc.JDBCCallableStatement
hsqldb.baseResultSet=org.hsqldb.jdbc.JDBCResultSet
hsqldb.subResultSet=org.hsqldb.jdbc.JDBCResultSet$JDBCResultSetBasic
# ------ Derby v10.10.1.1 -------------------------------------------------------
#
org.apache.derby.jdbc.ClientDataSource40=derby
derby.baseConnection=org.apache.derby.client.am.Connection
derby.subConnection=org.apache.derby.client.net.NetConnection40
derby.baseStatement=org.apache.derby.client.am.Statement
derby.subPreparedStatement=org.apache.derby.client.am.PreparedStatement
derby.subPreparedStatement=org.apache.derby.client.am.PreparedStatement40
#derby.subPreparedStatement=org.apache.derby.client.am.PreparedStatement42
derby.subCallableStatement=org.apache.derby.client.am.CallableStatement
derby.subCallableStatement=org.apache.derby.client.am.CallableStatement40
#derby.subCallableStatement=org.apache.derby.client.am.CallableStatement42
derby.baseResultSet=org.apache.derby.client.am.ResultSet
derby.subResultSet=org.apache.derby.client.net.NetResultSet40
#derby.subResultSet=org.apache.derby.client.net.NetResultSet42
# ------ Derby Embedded v10.10.1.1 ----------------------------------------------
#
derby-em.baseConnection=org.apache.derby.impl.jdbc.EmbedConnection
derby-em.baseConnection=org.apache.derby.iapi.jdbc.BrokeredConnection
derby-em.subConnection=org.apache.derby.impl.jdbc.EmbedConnection40
derby-em.subConnection=org.apache.derby.iapi.jdbc.BrokeredConnection40
#derby-em.subConnection=org.apache.derby.iapi.jdbc.BrokeredConnection42
derby-em.baseStatement=org.apache.derby.impl.jdbc.EmbedStatement
derby-em.baseStatement=org.apache.derby.iapi.jdbc.BrokeredStatement
derby-em.baseStatement=org.apache.derby.client.am.Statement
derby-em.subStatement=org.apache.derby.impl.jdbc.EmbedStatement40
derby-em.subStatement=org.apache.derby.iapi.jdbc.BrokeredStatement40
derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement
derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement20
derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement30
derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement40
#derby-em.subPreparedStatement=org.apache.derby.impl.jdbc.EmbedPreparedStatement42
derby-em.subPreparedStatement=org.apache.derby.iapi.jdbc.BrokeredPreparedStatement
derby-em.subPreparedStatement=org.apache.derby.iapi.jdbc.BrokeredPreparedStatement40
#derby-em.subPreparedStatement=org.apache.derby.iapi.jdbc.BrokeredPreparedStatement42
derby-em.subPreparedStatement=org.apache.derby.client.am.PreparedStatement
derby-em.subPreparedStatement=org.apache.derby.client.am.PreparedStatement40
#derby-em.subPreparedStatement=org.apache.derby.client.am.PreparedStatement42
derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement
derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement20
derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement30
derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement40
#derby-em.subCallableStatement=org.apache.derby.impl.jdbc.EmbedCallableStatement42
derby-em.subCallableStatement=org.apache.derby.iapi.jdbc.BrokeredCallableStatement
derby-em.subCallableStatement=org.apache.derby.iapi.jdbc.BrokeredCallableStatement40
#derby-em.subCallableStatement=org.apache.derby.iapi.jdbc.BrokeredCallableStatement42
derby-em.subCallableStatement=org.apache.derby.client.am.CallableStatement
derby-em.subCallableStatement=org.apache.derby.client.am.CallableStatement40
#derby-em.subCallableStatement=org.apache.derby.client.am.CallableStatement42
# ------ PostgreSQL v9.2-1003.jdbc4 ----------------------------------------------
#
org.postgresql.ds.PGSimpleDataSource=pgsql
pgsql.baseConnection=org.postgresql.jdbc2.AbstractJdbc2Connection
pgsql.subConnection=org.postgresql.jdbc3.AbstractJdbc3Connection
pgsql.subConnection=org.postgresql.jdbc3g.AbstractJdbc3gConnection
pgsql.subConnection=org.postgresql.jdbc4.AbstractJdbc4Connection
pgsql.subConnection=org.postgresql.jdbc4.Jdbc4Connection
pgsql.basePreparedStatement=org.postgresql.jdbc2.AbstractJdbc2Statement
pgsql.subPreparedStatement=org.postgresql.jdbc3.AbstractJdbc3Statement
pgsql.subPreparedStatement=org.postgresql.jdbc3g.AbstractJdbc3gStatement
pgsql.subPreparedStatement=org.postgresql.jdbc4.AbstractJdbc4Statement
pgsql.subPreparedStatement=org.postgresql.jdbc4.Jdbc4Statement
pgsql.subPreparedStatement=org.postgresql.jdbc4.Jdbc4PreparedStatement
pgsql.subCallableStatement=org.postgresql.jdbc4.Jdbc4CallableStatement
pgsql.baseResultSet=org.postgresql.jdbc2.AbstractJdbc2ResultSet
pgsql.subResultSet=org.postgresql.jdbc3.AbstractJdbc3ResultSet
pgsql.subResultSet=org.postgresql.jdbc3g.AbstractJdbc3gResultSet
pgsql.subResultSet=org.postgresql.jdbc4.AbstractJdbc4ResultSet
pgsql.subResultSet=org.postgresql.jdbc4.Jdbc4ResultSet
# ------ MySQL Connector/J v5.1.26 ----------------------------------------------
#
com.mysql.jdbc.jdbc2.optional.MysqlDataSource=mysql
mysql.baseConnection=com.mysql.jdbc.ConnectionImpl
mysql.baseConnection=com.mysql.jdbc.ReplicationConnection
mysql.baseConnection=com.mysql.jdbc.LoadBalancedMySQLConnection
mysql.subConnection=com.mysql.jdbc.JDBC4Connection
mysql.subConnection=com.mysql.jdbc.JDBC4LoadBalancedMySQLConnection
mysql.baseStatement=com.mysql.jdbc.StatementImpl
mysql.subPreparedStatement=com.mysql.jdbc.PreparedStatement
mysql.subPreparedStatement=com.mysql.jdbc.ServerPreparedStatement
mysql.subPreparedStatement=com.mysql.jdbc.JDBC4ServerPreparedStatement
mysql.subCallableStatement=com.mysql.jdbc.CallableStatement
mysql.subCallableStatement=com.mysql.jdbc.JDBC4CallableStatement
mysql.baseResultSet=com.mysql.jdbc.ResultSetImpl
mysql.subResultSet=com.mysql.jdbc.JDBC4ResultSet
mysql.subResultSet=com.mysql.jdbc.UpdatableResultSet
mysql.subResultSet=com.mysql.jdbc.JDBC4UpdatableResultSet
# ------ MariaDB JDBC v1.1.5 --------------------------------------------------
#
org.mariadb.jdbc.MySQLDataSource=maria
maria.baseConnection=org.mariadb.jdbc.MySQLConnection
maria.baseStatement=org.mariadb.jdbc.MySQLStatement
maria.subPreparedStatement=org.mariadb.jdbc.MySQLPreparedStatement
maria.baseCallableStatement=org.mariadb.jdbc.MySQLCallableStatement
maria.baseResultSet=org.mariadb.jdbc.MySQLResultSet
# ------ JTDS v1.3.1 ----------------------------------------------------------
#
net.sourceforge.jtds.jdbcx.JtdsDataSource=jtds
jtds.baseConnection=net.sourceforge.jtds.jdbc.JtdsConnection
jtds.baseConnection=net.sourceforge.jtds.jdbcx.proxy.ConnectionProxy
jtds.baseStatement=net.sourceforge.jtds.jdbc.JtdsStatement
jtds.baseStatement=net.sourceforge.jtds.jdbcx.proxy.StatementProxy
jtds.subPreparedStatement=net.sourceforge.jtds.jdbc.JtdsPreparedStatement
jtds.subPreparedStatement=net.sourceforge.jtds.jdbcx.proxy.PreparedStatementProxy
jtds.subCallableStatement=net.sourceforge.jtds.jdbc.JtdsCallableStatement
jtds.subCallableStatement=net.sourceforge.jtds.jdbcx.proxy.CallableStatementProxy
jtds.baseResultSet=net.sourceforge.jtds.jdbc.JtdsResultSet
jtds.subResultSet=net.sourceforge.jtds.jdbc.CachedResultSet
jtds.subResultSet=net.sourceforge.jtds.jdbc.MSCursorResultSet
# ------ Oracle v12.1.0.1 -----------------------------------------------------
#
oracle.jdbc.pool.OracleDataSource=oracle
oracle.baseConnection=oracle.jdbc.driver.OracleConnection
oracle.subConnection=oracle.jdbc.driver.PhysicalConnection
oracle.subConnection=oracle.jdbc.driver.T4CConnection
oracle.baseStatement=oracle.jdbc.driver.OracleStatement
oracle.subPreparedStatement=oracle.jdbc.driver.OraclePreparedStatement
oracle.subCallableStatement=oracle.jdbc.driver.OracleCallableStatement
oracle.baseResultSet=oracle.jdbc.driver.OracleResultSet
oracle.subResultSet=oracle.jdbc.driver.ArrayDataResultSet
oracle.subResultSet=oracle.jdbc.driver.GeneratedScrollableResultSet
oracle.subResultSet=oracle.jdbc.driver.InsensitiveScrollableResultSet
oracle.subResultSet=oracle.jdbc.driver.ForwardOnlyResultSet
oracle.subResultSet=oracle.jdbc.driver.ArrayLocatorResultSet
oracle.subResultSet=oracle.jdbc.driver.SensitiveScrollableResultSet
oracle.subResultSet=oracle.jdbc.driver.OracleReturnResultSet
oracle.subResultSet=oracle.jdbc.driver.GeneratedUpdatableResultSet
oracle.subResultSet=oracle.jdbc.driver.UpdatableResultSet
# ------ HikariCP Testing v0.0.0 ----------------------------------------------
#
com.zaxxer.hikari.mocks.StubDataSource=hikari
hikari.baseConnection=com.zaxxer.hikari.mocks.StubBaseConnection
hikari.subConnection=com.zaxxer.hikari.mocks.StubConnection
hikari.baseStatement=com.zaxxer.hikari.mocks.StubStatement
hikari.subPreparedStatement=com.zaxxer.hikari.mocks.StubPreparedStatement
hikari.baseResultSet=com.zaxxer.hikari.mocks.StubResultSet
com.zaxxer.hikari.performance.StubDataSource=hikari-perf
hikari-perf.baseConnection=com.zaxxer.hikari.performance.StubConnection
hikari-perf.baseStatement=com.zaxxer.hikari.performance.StubStatement
hikari-perf.subPreparedStatement=com.zaxxer.hikari.performance.StubPreparedStatement
hikari-perf.baseResultSet=com.zaxxer.hikari.performance.StubResultSet

@ -1,91 +0,0 @@
/*
* Copyright (C) 2013 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.osgi;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import javax.inject.Inject;
import java.io.File;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.ops4j.pax.exam.CoreOptions.*;
/**
* @author lburgazzoli
*/
@RunWith(PaxExam.class)
public class OSGiBundleTest
{
@Inject
BundleContext context;
@Configuration
public Option[] config()
{
return options(
systemProperty("org.osgi.framework.storage.clean").value("true"),
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("WARN"),
mavenBundle("org.slf4j","slf4j-api","1.7.5"),
mavenBundle("org.slf4j","slf4j-simple","1.7.5").noStart(),
mavenBundle("org.javassist", "javassist", "3.19.0-GA"),
new File("target/classes").exists()
? bundle("reference:file:target/classes")
: bundle("reference:file:../target/classes"),
junitBundles(),
cleanCaches()
);
}
@Test
public void checkInject()
{
assertNotNull(context);
}
@Test
public void checkBundle()
{
Boolean bundleFound = false;
Boolean bundleActive = false;
Bundle[] bundles = context.getBundles();
for(Bundle bundle : bundles)
{
if(bundle != null)
{
if(bundle.getSymbolicName().equals("com.zaxxer.HikariCP-java6"))
{
bundleFound = true;
if(bundle.getState() == Bundle.ACTIVE)
{
bundleActive = true;
}
}
}
}
assertTrue(bundleFound);
assertTrue(bundleActive);
}
}

@ -1,4 +0,0 @@
hibernate.hikari.minimumIdle=5
hibernate.hikari.connectionTestQuery=SELECT 1
hibernate.hikari.dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource
hibernate.connection.autocommit=false

@ -1,4 +0,0 @@
minimumIdle=5
connectionTestQuery=SELECT 1
autoCommit=false
dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource

@ -1,5 +0,0 @@
connectionTestQuery=SELECT 1
autoCommit=false
dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource
dataSource.user=test
dataSource.password=test

@ -1,6 +0,0 @@
connectionTestQuery=SELECT 1
autoCommit=false
dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource
dataSource.user=test
dataSource.password=test
dataSource.url=jdbc:stub:foo

@ -1,353 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- For release: mvn release:perform -Darguments=-Dgpg.passphrase=PASSPHRASE -->
<artifactId>HikariCP</artifactId>
<packaging>bundle</packaging>
<name>HikariCP</name>
<description>Ultimate JDBC Connection Pool</description>
<url>https://github.com/brettwooldridge/HikariCP</url>
<organization>
<name>Zaxxer.com</name>
<url>https://github.com/brettwooldridge</url>
</organization>
<scm>
<connection>scm:git:git@github.com:brettwooldridge/HikariCP.git</connection>
<developerConnection>scm:git:git@github.com:brettwooldridge/HikariCP.git</developerConnection>
<url>git@github.com:brettwooldridge/HikariCP.git</url>
<tag>HikariCP-2.3.2</tag>
</scm>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<name>Brett Wooldridge</name>
<email>brett.wooldridge@gmail.com</email>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<felix.version>4.6.0</felix.version>
<felix.bundle.plugin.version>2.5.3</felix.bundle.plugin.version>
</properties>
<parent>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-parent</artifactId>
<version>2.3.6-SNAPSHOT</version>
</parent>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Sets the VM argument line used when unit tests are run. -->
<argLine>${surefireArgLine}</argLine>
<!-- Skips unit tests if the value of skip.unit.tests property is true -->
<skipTests>${skip.unit.tests}</skipTests>
<classpathDependencyExcludes>
<classpathDependencyExclude>io.dropwizard.metrics:metrics-core</classpathDependencyExclude>
<classpathDependencyExclude>io.dropwizard.metrics:metrics-healthchecks</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.2.201409121644</version>
<executions>
<!-- Prepares the property pointing to the JaCoCo runtime agent which is passed as VM argument when Maven the Surefire plugin is executed. -->
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile>
<!-- Sets the name of the property containing the settings for JaCoCo runtime agent. -->
<propertyName>surefireArgLine</propertyName>
<excludes>
<exclude>**/com/zaxxer/hikari/proxy/ProxyFactory</exclude>
<exclude>**/com/zaxxer/hikari/proxy/ResultSetProxy</exclude>
<exclude>**/com/zaxxer/hikari/proxy/StatementProxy</exclude>
<exclude>**/com/zaxxer/hikari/proxy/CallableStatementProxy</exclude>
<exclude>**/com/zaxxer/hikari/proxy/PreparedStatementProxy</exclude>
<exclude>**/com/zaxxer/hikari/metrics/**</exclude>
</excludes>
</configuration>
</execution>
<!-- Ensures that the code coverage report for unit tests is created after unit tests have been run. -->
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<dataFile>${project.build.directory}/coverage-reports/jacoco.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
<excludes>
<exclude>**/com/zaxxer/hikari/proxy/ProxyFactory.class</exclude>
<exclude>**/com/zaxxer/hikari/proxy/ResultSetProxy.class</exclude>
<exclude>**/com/zaxxer/hikari/proxy/StatementProxy.class</exclude>
<exclude>**/com/zaxxer/hikari/proxy/CallableStatementProxy.class</exclude>
<exclude>**/com/zaxxer/hikari/proxy/PreparedStatementProxy.class</exclude>
<exclude>**/com/zaxxer/hikari/metrics/**</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>src</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../hikaricp-common/src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>test</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>../hikaricp-common/src/test/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>test-resources</id>
<phase>generate-test-resources</phase>
<goals>
<goal>add-test-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>../hikaricp-common/src/test/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<extensions>true</extensions>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${felix.bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Name>HikariCP</Bundle-Name>
<Export-Package>
com.zaxxer.hikari,
com.zaxxer.hikari.hibernate
</Export-Package>
<Private-Package>com.zaxxer.hikari.*</Private-Package>
<_exportcontents>
com.zaxxer.hikari.pool,
com.zaxxer.hikari.util,
com.zaxxer.hikari.proxy
</_exportcontents>
<Import-Package>
javassist.*,
javax.management,
javax.naming,
javax.naming.spi,
javax.sql,
javax.sql.rowset,
javax.sql.rowset.serial,
javax.sql.rowset.spi,
com.codahale.metrics;resolution:=optional,
com.codahale.metrics.health;resolution:=optional,
org.slf4j;version="[1.6,2)",
org.hibernate;resolution:=optional,
org.hibernate.cfg;resolution:=optional,
org.hibernate.engine.jdbc.connections.spi;resolution:=optional,
org.hibernate.service;resolution:=optional,
org.hibernate.service.spi;resolution:=optional
</Import-Package>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
<executions>
<!-- This execution makes sure that the manifest is available when the tests are executed -->
<execution>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5</version>
<configuration>
<tagNameFormat>HikariCP-@{project.version}</tagNameFormat>
</configuration>
</plugin>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.felix</groupId>
<artifactId>
maven-bundle-plugin
</artifactId>
<versionRange>[2.4.0,)</versionRange>
<goals>
<goal>manifest</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<profiles>
<profile>
<id>coverage</id>
<build>
<plugins>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>coveralls</id>
<phase>verify</phase>
<goals>
<goal>jacoco</goal>
</goals>
<inherited>false</inherited>
<configuration>
<sourceDirectories>../hikaricp-common/src/main/java</sourceDirectories>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>felix</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>pax.exam.framework</name>
<value>felix</value>
</property>
</activation>
<properties>
<pax.exam.framework>felix</pax.exam.framework>
<pax.exam.logging>none</pax.exam.logging>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>${felix.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

@ -1,81 +0,0 @@
/*
* Copyright (C) 2013, 2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import com.zaxxer.hikari.proxy.JavassistProxyFactory;
import com.zaxxer.hikari.util.PropertyBeanSetter;
public class HikariConfig extends AbstractHikariConfig
{
static {
JavassistProxyFactory.initialize();
}
/**
* Default constructor
*/
public HikariConfig()
{
super();
}
/**
* Construct a HikariConfig from the specified properties object.
*
* @param properties the name of the property file
*/
public HikariConfig(Properties properties)
{
super(properties);
}
/**
* Construct a HikariConfig from the specified property file name. <code>propertyFileName</code>
* will first be treated as a path in the file-system, and if that fails the
* ClassLoader.getResourceAsStream(propertyFileName) will be tried.
*
* @param propertyFileName the name of the property file
*/
public HikariConfig(String propertyFileName)
{
super(propertyFileName);
}
protected void loadProperties(String propertyFileName)
{
final File propFile = new File(propertyFileName);
try (final InputStream is = propFile.isFile() ? new FileInputStream(propFile) : this.getClass().getResourceAsStream(propertyFileName)) {
if (is != null) {
Properties props = new Properties();
props.load(is);
PropertyBeanSetter.setTargetFromProperties(this, props);
}
else {
throw new IllegalArgumentException("Property file " + propertyFileName + " was not found.");
}
}
catch (IOException io) {
throw new RuntimeException("Error loading properties file", io);
}
}
}

@ -1,227 +0,0 @@
/*
* Copyright (C) 2013,2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.pool;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
import static com.zaxxer.hikari.util.UtilityElf.quietlySleep;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.util.ConcurrentBag;
import com.zaxxer.hikari.util.IBagStateListener;
import com.zaxxer.hikari.util.Java8ConcurrentBag;
/**
* This is the primary connection pool class that provides the basic
* pooling behavior for HikariCP.
*
* @author Brett Wooldridge
*/
public final class HikariPool extends BaseHikariPool
{
/**
* Construct a HikariPool with the specified configuration.
*
* @param configuration a HikariConfig instance
*/
public HikariPool(HikariConfig configuration)
{
this(configuration, configuration.getUsername(), configuration.getPassword());
}
/**
* Construct a HikariPool with the specified configuration.
*
* @param configuration a HikariConfig instance
* @param username authentication username
* @param password authentication password
*/
public HikariPool(HikariConfig configuration, String username, String password)
{
super(configuration, username, password);
}
// ***********************************************************************
// IBagStateListener callback
// ***********************************************************************
/** {@inheritDoc} */
@Override
public void addBagItem()
{
addConnectionExecutor.execute( () -> {
long sleepBackoff = 200L;
final int maxPoolSize = configuration.getMaximumPoolSize();
while (poolState == POOL_RUNNING && totalConnections.get() < maxPoolSize && !addConnection()) {
// If we got into the loop, addConnection() failed, so we sleep and retry
quietlySleep(sleepBackoff);
sleepBackoff = Math.min(connectionTimeout / 2, (long) ((double) sleepBackoff * 1.5));
}
});
}
// ***********************************************************************
// HikariPoolMBean methods
// ***********************************************************************
/** {@inheritDoc} */
@Override
public void softEvictConnections()
{
connectionBag.values(STATE_IN_USE).forEach(bagEntry -> bagEntry.evicted = true);
connectionBag.values(STATE_NOT_IN_USE).stream().filter(p -> connectionBag.reserve(p)).forEach(bagEntry -> closeConnection(bagEntry));
}
// ***********************************************************************
// Protected methods
// ***********************************************************************
/**
* Permanently close the real (underlying) connection (eat any exception).
*
* @param connectionProxy the connection to actually close
*/
@Override
protected void closeConnection(final PoolBagEntry bagEntry)
{
bagEntry.cancelMaxLifeTermination();
if (connectionBag.remove(bagEntry)) {
final int tc = totalConnections.decrementAndGet();
if (tc < 0) {
LOGGER.warn("Internal accounting inconsistency, totalConnections={}", tc, new Exception());
}
closeConnectionExecutor.execute(() -> { poolUtils.quietlyCloseConnection(bagEntry.connection); });
}
}
/**
* Check whether the connection is alive or not.
*
* @param connection the connection to test
* @param timeoutMs the timeout before we consider the test a failure
* @return true if the connection is alive, false if it is not alive or we timed out
*/
@Override
protected boolean isConnectionAlive(final Connection connection)
{
try {
int timeoutSec = (int) TimeUnit.MILLISECONDS.toSeconds(validationTimeout);
if (isUseJdbc4Validation) {
return connection.isValid(timeoutSec);
}
final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, validationTimeout);
try (Statement statement = connection.createStatement()) {
poolUtils.setQueryTimeout(statement, timeoutSec);
statement.executeQuery(configuration.getConnectionTestQuery());
}
if (isIsolateInternalQueries && !isAutoCommit) {
connection.rollback();
}
poolUtils.setNetworkTimeout(connection, originalTimeout);
return true;
}
catch (SQLException e) {
LOGGER.warn("Exception during keep alive check, that means the connection ({}) must be dead.", connection, e);
return false;
}
}
/**
* Attempt to abort() active connections on Java7+, or close() them on Java6.
*
* @throws InterruptedException
*/
@Override
protected void abortActiveConnections(final ExecutorService assassinExecutor) throws InterruptedException
{
connectionBag.values(STATE_IN_USE).stream().forEach(bagEntry -> {
try {
bagEntry.aborted = bagEntry.evicted = true;
bagEntry.connection.abort(assassinExecutor);
}
catch (SQLException | NoSuchMethodError | AbstractMethodError e) {
poolUtils.quietlyCloseConnection(bagEntry.connection);
}
finally {
if (connectionBag.remove(bagEntry)) {
totalConnections.decrementAndGet();
}
}
});
}
/** {@inheritDoc} */
@Override
protected Runnable getHouseKeeper()
{
return new HouseKeeper();
}
/** {@inheritDoc} */
@Override
protected ConcurrentBag<PoolBagEntry> createConcurrentBag(IBagStateListener listener)
{
return new Java8ConcurrentBag(listener);
}
// ***********************************************************************
// Non-anonymous Inner-classes
// ***********************************************************************
/**
* The house keeping task to retire idle connections.
*/
private class HouseKeeper implements Runnable
{
@Override
public void run()
{
logPoolState("Before cleanup ");
connectionTimeout = configuration.getConnectionTimeout(); // refresh member in case it changed
validationTimeout = configuration.getValidationTimeout(); // refresh member in case it changed
final long now = System.currentTimeMillis();
final long idleTimeout = configuration.getIdleTimeout();
connectionBag.values(STATE_NOT_IN_USE).stream().filter(p -> connectionBag.reserve(p)).forEach(bagEntry -> {
if (bagEntry.evicted || (idleTimeout > 0L && now > bagEntry.lastAccess + idleTimeout)) {
closeConnection(bagEntry);
}
else {
connectionBag.unreserve(bagEntry);
}
});
logPoolState("After cleanup ");
fillPool(); // Try to maintain minimum connections
}
}
}

@ -1,119 +0,0 @@
/*
* Copyright (C) 2013, 2014 Brett Wooldridge
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zaxxer.hikari.util;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
import java.util.stream.Collectors;
import com.zaxxer.hikari.pool.PoolBagEntry;
/**
* This is a specialized concurrent bag that achieves superior performance
* to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a
* connection pool. It uses ThreadLocal storage when possible to avoid
* locks, but resorts to scanning a common collection if there are no
* available items in the ThreadLocal list. Not-in-use items in the
* ThreadLocal lists can be "stolen" when the borrowing thread has none
* of its own. It is a "lock-less" implementation using a specialized
* AbstractQueuedLongSynchronizer to manage cross-thread signaling.
*
* Note that items that are "borrowed" from the bag are not actually
* removed from any collection, so garbage collection will not occur
* even if the reference is abandoned. Thus care must be taken to
* "requite" borrowed objects otherwise a memory leak will result. Only
* the "remove" method can completely remove an object from the bag.
*
* @author Brett Wooldridge
*
* @param <T> the templated type to store in the bag
*/
public final class Java8ConcurrentBag extends ConcurrentBag<PoolBagEntry>
{
/**
* Construct a ConcurrentBag with the specified listener.
*
* @param listener the IBagStateListener to attach to this bag
*/
public Java8ConcurrentBag(IBagStateListener listener)
{
super(listener);
}
@Override
protected AbstractQueuedLongSynchronizer createQueuedSynchronizer()
{
return new Synchronizer();
}
/**
* This method provides a "snaphot" in time of the BagEntry
* items in the bag in the specified state. It does not "lock"
* or reserve items in any way. Call <code>reserve(BagEntry)</code>
* on items in list before performing any action on them.
*
* @param state one of STATE_NOT_IN_USE or STATE_IN_USE
* @return a possibly empty list of objects having the state specified
*/
public List<PoolBagEntry> values(final int state)
{
if (state == STATE_IN_USE || state == STATE_NOT_IN_USE) {
return sharedList.stream()
.filter(reference -> reference.state.get() == state)
.collect(Collectors.toList());
}
return new ArrayList<PoolBagEntry>(0);
}
/**
* Get a count of the number of items in the specified state at the time of this call.
*
* @param state the state of the items to count
* @return a count of how many items in the bag are in the specified state
*/
public int getCount(final int state)
{
return (int) sharedList.stream().filter(reference -> reference.state.get() == state).count();
}
/**
* Our private synchronizer that handles notify/wait type semantics.
*/
private static final class Synchronizer extends AbstractQueuedLongSynchronizer
{
private static final long serialVersionUID = 104753538004341218L;
@Override
protected long tryAcquireShared(long seq)
{
return getState() > seq && !hasQueuedPredecessors() ? 1L : -1L;
}
/** {@inheritDoc} */
@Override
protected boolean tryReleaseShared(long updateSeq)
{
setState(updateSeq);
return true;
}
}
}

@ -1,13 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-parent</artifactId>
<version>2.3.6-SNAPSHOT</version>
<packaging>pom</packaging>
<artifactId>HikariCP</artifactId>
<version>2.4.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>HikariCP-parent</name>
<name>HikariCP</name>
<description>Ultimate JDBC Connection Pool</description>
<url>https://github.com/brettwooldridge/HikariCP</url>
@ -20,7 +19,7 @@
<connection>scm:git:git@github.com:brettwooldridge/HikariCP.git</connection>
<developerConnection>scm:git:git@github.com:brettwooldridge/HikariCP.git</developerConnection>
<url>git@github.com:brettwooldridge/HikariCP.git</url>
<tag>HikariCP-2.3.2</tag>
<tag>HEAD</tag>
</scm>
<licenses>
@ -49,6 +48,8 @@
<pax.exam.version>3.4.0</pax.exam.version>
<pax.url.version>2.3.0</pax.url.version>
<slf4j.version>1.7.10</slf4j.version>
<felix.bundle.plugin.version>2.4.0</felix.bundle.plugin.version>
<felix.version>4.2.1</felix.version>
</properties>
<parent>
@ -57,11 +58,6 @@
<version>7</version>
</parent>
<modules>
<module>hikaricp</module>
<module>hikaricp-java6</module>
</modules>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
@ -114,7 +110,7 @@
<scope>test</scope>
</dependency>
<!-- OSGi test -->
<!-- OSGi test -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
@ -160,8 +156,71 @@
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${felix.bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Name>HikariCP</Bundle-Name>
<Export-Package>
com.zaxxer.hikari,
com.zaxxer.hikari.hibernate
</Export-Package>
<Private-Package>com.zaxxer.hikari.*</Private-Package>
<_exportcontents>
com.zaxxer.hikari.pool,
com.zaxxer.hikari.util,
com.zaxxer.hikari.proxy
</_exportcontents>
<Import-Package>
javassist.*,
javax.management,
javax.naming,
javax.naming.spi,
javax.sql,
javax.sql.rowset,
javax.sql.rowset.serial,
javax.sql.rowset.spi,
com.codahale.metrics;resolution:=optional,
com.codahale.metrics.health;resolution:=optional,
org.slf4j;version="[1.6,2)",
org.hibernate;resolution:=optional,
org.hibernate.cfg;resolution:=optional,
org.hibernate.engine.jdbc.connections.spi;resolution:=optional,
org.hibernate.service;resolution:=optional,
org.hibernate.service.spi;resolution:=optional
</Import-Package>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
<executions>
<!-- This execution makes sure that the manifest is available when the tests are executed -->
<execution>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<extensions>true</extensions>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
@ -177,9 +236,9 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<!-- Sets the VM argument line used when unit tests are run. -->
<!-- Sets the VM argument line used when unit tests are run. -->
<argLine>${surefireArgLine}</argLine>
<!-- Skips unit tests if the value of skip.unit.tests property is true -->
<!-- Skips unit tests if the value of skip.unit.tests property is true -->
<skipTests>${skip.unit.tests}</skipTests>
</configuration>
</plugin>
@ -189,7 +248,8 @@
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<!-- outputDirectory>/absolute/path/to/the/output/directory</outputDirectory> <finalName>filename-of-generated-jar-file</finalName -->
<!-- outputDirectory>/absolute/path/to/the/output/directory</outputDirectory>
<finalName>filename-of-generated-jar-file</finalName -->
<attach>true</attach>
</configuration>
<executions>
@ -208,10 +268,9 @@
<version>2.9.1</version>
<configuration>
<show>public</show>
<!-- excludePackageNames>com.zaxxer.hikari.*</excludePackageNames -->
<!-- excludePackageNames>com.zaxxer.hikari.*</excludePackageNames -->
<attach>true</attach>
<maxmemory>1024m</maxmemory>
<sourcepath>../hikaricp-common/src/main/java</sourcepath>
</configuration>
<executions>
<execution>
@ -256,5 +315,28 @@
</plugins>
</build>
</profile>
<profile>
<id>felix</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>pax.exam.framework</name>
<value>felix</value>
</property>
</activation>
<properties>
<pax.exam.framework>felix</pax.exam.framework>
<pax.exam.logging>none</pax.exam.logging>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>${felix.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

@ -16,10 +16,12 @@
package com.zaxxer.hikari;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
@ -35,10 +37,11 @@ import org.slf4j.LoggerFactory;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.health.HealthCheckRegistry;
import com.zaxxer.hikari.proxy.JavassistProxyFactory;
import com.zaxxer.hikari.util.PropertyBeanSetter;
import com.zaxxer.hikari.util.UtilityElf;
public abstract class AbstractHikariConfig implements HikariConfigMBean
public class HikariConfig implements HikariConfigMBean
{
private static final Logger LOGGER = LoggerFactory.getLogger(HikariConfig.class);
@ -82,16 +85,20 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
private boolean isAllowPoolSuspension;
private DataSource dataSource;
private Properties dataSourceProperties;
private IConnectionCustomizer customizer;
private ThreadFactory threadFactory;
private Object metricRegistry;
private Object healthCheckRegistry;
private Properties healthCheckProperties;
static
{
JavassistProxyFactory.initialize();
}
/**
* Default constructor
*/
public AbstractHikariConfig()
public HikariConfig()
{
dataSourceProperties = new Properties();
healthCheckProperties = new Properties();
@ -104,12 +111,6 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
minIdle = -1;
maxPoolSize = 10;
maxLifetime = MAX_LIFETIME;
customizer = new IConnectionCustomizer() {
@Override
public void customize(Connection connection) throws SQLException
{
}
};
String systemProp = System.getProperty("hikaricp.configurationFile");
if ( systemProp != null) {
@ -122,7 +123,7 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
*
* @param properties the name of the property file
*/
public AbstractHikariConfig(Properties properties)
public HikariConfig(Properties properties)
{
this();
PropertyBeanSetter.setTargetFromProperties(this, properties);
@ -135,7 +136,7 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
*
* @param propertyFileName the name of the property file
*/
public AbstractHikariConfig(String propertyFileName)
public HikariConfig(String propertyFileName)
{
this();
@ -162,54 +163,6 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
this.catalog = catalog;
}
/**
* Get the name of the connection customizer class to instantiate and execute
* on all new connections.
*
* @return the name of the customizer class, or null
*/
@Deprecated
public String getConnectionCustomizerClassName()
{
return connectionCustomizerClassName;
}
/**
* Set the name of the connection customizer class to instantiate and execute
* on all new connections.
*
* @param connectionCustomizerClassName the name of the customizer class
*/
@Deprecated
public void setConnectionCustomizerClassName(String connectionCustomizerClassName)
{
this.connectionCustomizerClassName = connectionCustomizerClassName;
LOGGER.warn("The connectionCustomizerClassName property has been deprecated and may be removed in a future release");
}
/**
* Get the customizer instance specified by the user.
*
* @return an instance of IConnectionCustomizer
*/
@Deprecated
public IConnectionCustomizer getConnectionCustomizer()
{
return customizer;
}
/**
* Set the connection customizer to be used by the pool.
*
* @param customizer an instance of IConnectionCustomizer
*/
@Deprecated
public void setConnectionCustomizer(IConnectionCustomizer customizer)
{
this.customizer = customizer;
LOGGER.warn("The connectionCustomizer property has been deprecated and may be removed in a future release");
}
/**
* Get the SQL query to be executed to test the validity of connections.
*
@ -853,11 +806,27 @@ public abstract class AbstractHikariConfig implements HikariConfigMBean
}
}
abstract protected void loadProperties(String propertyFileName);
protected void loadProperties(String propertyFileName)
{
final File propFile = new File(propertyFileName);
try (final InputStream is = propFile.isFile() ? new FileInputStream(propFile) : this.getClass().getResourceAsStream(propertyFileName)) {
if (is != null) {
Properties props = new Properties();
props.load(is);
PropertyBeanSetter.setTargetFromProperties(this, props);
}
else {
throw new IllegalArgumentException("Property file " + propertyFileName + " was not found.");
}
}
catch (IOException io) {
throw new RuntimeException("Error loading properties file", io);
}
}
public void copyState(AbstractHikariConfig other)
public void copyState(HikariConfig other)
{
for (Field field : AbstractHikariConfig.class.getDeclaredFields()) {
for (Field field : HikariConfig.class.getDeclaredFields()) {
if (!Modifier.isFinal(field.getModifiers())) {
field.setAccessible(true);
try {

@ -24,7 +24,7 @@ import com.codahale.metrics.CachedGauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.zaxxer.hikari.pool.BaseHikariPool;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.pool.PoolBagEntry;
public final class CodaHaleMetricsTracker extends MetricsTracker
@ -33,7 +33,7 @@ public final class CodaHaleMetricsTracker extends MetricsTracker
private final Histogram connectionUsage;
private final MetricRegistry registry;
public CodaHaleMetricsTracker(final BaseHikariPool pool, final MetricRegistry registry) {
public CodaHaleMetricsTracker(final HikariPool pool, final MetricRegistry registry) {
super(pool);
this.registry = registry;

@ -29,7 +29,7 @@ import com.codahale.metrics.Timer;
import com.codahale.metrics.health.HealthCheck;
import com.codahale.metrics.health.HealthCheckRegistry;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.pool.BaseHikariPool;
import com.zaxxer.hikari.pool.HikariPool;
/**
* Provides Dropwizard HealthChecks. Two health checks are provided:
@ -54,7 +54,7 @@ public final class CodahaleHealthChecker
* @param pool the pool to register health checks for
* @param registry the HealthCheckRegistry into which checks will be registered
*/
public static void registerHealthChecks(final BaseHikariPool pool, final HealthCheckRegistry registry)
public static void registerHealthChecks(final HikariPool pool, final HealthCheckRegistry registry)
{
final HikariConfig hikariConfig = pool.getConfiguration();
final Properties healthCheckProperties = hikariConfig.getHealthCheckProperties();
@ -87,10 +87,10 @@ public final class CodahaleHealthChecker
private static class ConnectivityHealthCheck extends HealthCheck
{
private final BaseHikariPool pool;
private final HikariPool pool;
private final long checkTimeoutMs;
ConnectivityHealthCheck(final BaseHikariPool pool, final long checkTimeoutMs)
ConnectivityHealthCheck(final HikariPool pool, final long checkTimeoutMs)
{
this.pool = pool;
this.checkTimeoutMs = (checkTimeoutMs > 0 && checkTimeoutMs != Integer.MAX_VALUE ? checkTimeoutMs : TimeUnit.SECONDS.toMillis(10));

@ -16,7 +16,7 @@
package com.zaxxer.hikari.metrics;
import com.zaxxer.hikari.pool.BaseHikariPool;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.pool.PoolBagEntry;
/**
@ -28,9 +28,9 @@ public class MetricsTracker
{
public static final MetricsContext NO_CONTEXT = new MetricsContext();
protected final BaseHikariPool pool;
protected final HikariPool pool;
public MetricsTracker(final BaseHikariPool pool)
public MetricsTracker(final HikariPool pool)
{
this.pool = pool;
}

@ -52,7 +52,7 @@ public final class HikariMBeanElf
* @param configuration a HikariConfig instance
* @param pool a HikariPool instance
*/
public static void registerMBeans(final HikariConfig configuration, final BaseHikariPool pool)
public static void registerMBeans(final HikariConfig configuration, final HikariPool pool)
{
if (!configuration.isRegisterMbeans()) {
return;
@ -82,7 +82,7 @@ public final class HikariMBeanElf
* @param configuration a HikariConfig instance
* @param pool a HikariPool instance
*/
public static void unregisterMBeans(final HikariConfig configuration, final BaseHikariPool pool)
public static void unregisterMBeans(final HikariConfig configuration, final HikariPool pool)
{
try {
final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();

@ -21,15 +21,15 @@ import static com.zaxxer.hikari.pool.HikariMBeanElf.unregisterMBeans;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_IN_USE;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_NOT_IN_USE;
import static com.zaxxer.hikari.util.IConcurrentBagEntry.STATE_REMOVED;
import static com.zaxxer.hikari.util.UtilityElf.createInstance;
import static com.zaxxer.hikari.util.UtilityElf.createThreadPoolExecutor;
import static com.zaxxer.hikari.util.UtilityElf.elapsedTimeMs;
import static com.zaxxer.hikari.util.UtilityElf.getTransactionIsolation;
import static com.zaxxer.hikari.util.UtilityElf.setRemoveOnCancelPolicy;
import static com.zaxxer.hikari.util.UtilityElf.quietlySleep;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLTimeoutException;
import java.sql.Statement;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
@ -46,7 +46,6 @@ import org.slf4j.LoggerFactory;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.health.HealthCheckRegistry;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.IConnectionCustomizer;
import com.zaxxer.hikari.metrics.CodaHaleMetricsTracker;
import com.zaxxer.hikari.metrics.CodahaleHealthChecker;
import com.zaxxer.hikari.metrics.MetricsTracker;
@ -64,7 +63,7 @@ import com.zaxxer.hikari.util.IBagStateListener;
*
* @author Brett Wooldridge
*/
public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListener
public class HikariPool implements HikariPoolMBean, IBagStateListener
{
protected final Logger LOGGER = LoggerFactory.getLogger(getClass());
private static final long ALIVE_BYPASS_WINDOW = Long.getLong("com.zaxxer.hikari.aliveBypassWindow", 1000L);
@ -96,7 +95,6 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
private final LeakTask leakTask;
private final DataSource dataSource;
private final GlobalPoolLock suspendResumeLock;
private final IConnectionCustomizer connectionCustomizer;
private final AtomicReference<Throwable> lastConnectionFailure;
private final String username;
@ -110,7 +108,7 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
*
* @param configuration a HikariConfig instance
*/
public BaseHikariPool(HikariConfig configuration)
public HikariPool(HikariConfig configuration)
{
this(configuration, configuration.getUsername(), configuration.getPassword());
}
@ -123,14 +121,14 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
* @param username authentication username
* @param password authentication password
*/
public BaseHikariPool(HikariConfig configuration, String username, String password)
public HikariPool(HikariConfig configuration, String username, String password)
{
this.username = username;
this.password = password;
this.configuration = configuration;
this.poolUtils = new PoolUtilities(configuration);
this.connectionBag = createConcurrentBag(this);
this.connectionBag = new ConcurrentBag<PoolBagEntry>(this);
this.totalConnections = new AtomicInteger();
this.connectionTimeout = configuration.getConnectionTimeout();
this.validationTimeout = configuration.getValidationTimeout();
@ -142,7 +140,6 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
this.suspendResumeLock = configuration.isAllowPoolSuspension() ? new GlobalPoolLock(true) : GlobalPoolLock.FAUX_LOCK;
this.catalog = configuration.getCatalog();
this.connectionCustomizer = initializeCustomizer();
this.transactionIsolation = getTransactionIsolation(configuration.getTransactionIsolation());
this.isIsolateInternalQueries = configuration.isIsolateInternalQueries();
this.isUseJdbc4Validation = configuration.getConnectionTestQuery() == null;
@ -158,11 +155,11 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
long delayPeriod = Long.getLong("com.zaxxer.hikari.housekeeping.periodMs", TimeUnit.SECONDS.toMillis(30L));
ThreadFactory threadFactory = configuration.getThreadFactory() != null ? configuration.getThreadFactory() : new DefaultThreadFactory("Hikari Housekeeping Timer (pool " + configuration.getPoolName() + ")", true);
this.houseKeepingExecutorService = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy());
this.houseKeepingExecutorService.scheduleAtFixedRate(getHouseKeeper(), delayPeriod, delayPeriod, TimeUnit.MILLISECONDS);
this.houseKeepingExecutorService.scheduleAtFixedRate(new HouseKeeper(), delayPeriod, delayPeriod, TimeUnit.MILLISECONDS);
this.houseKeepingExecutorService.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
this.houseKeepingExecutorService.setRemoveOnCancelPolicy(true);
this.leakTask = (configuration.getLeakDetectionThreshold() == 0) ? LeakTask.NO_LEAK : new LeakTask(configuration.getLeakDetectionThreshold(), houseKeepingExecutorService);
setRemoveOnCancelPolicy(houseKeepingExecutorService);
poolUtils.setLoginTimeout(dataSource, connectionTimeout);
registerMBeans(configuration, this);
initializeConnections();
@ -208,7 +205,7 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
else {
metricsContext.setConnectionLastOpen(bagEntry, now);
metricsContext.stop();
return ProxyFactory.getProxyConnection((HikariPool) this, bagEntry, leakTask.start(bagEntry));
return ProxyFactory.getProxyConnection(this, bagEntry, leakTask.start(bagEntry));
}
}
while (timeout > 0L);
@ -320,6 +317,31 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
return configuration.getPoolName();
}
// ***********************************************************************
// IBagStateListener callback
// ***********************************************************************
/** {@inheritDoc} */
@Override
public void addBagItem()
{
class AddConnection implements Runnable
{
public void run()
{
long sleepBackoff = 200L;
final int maxPoolSize = configuration.getMaximumPoolSize();
while (poolState == POOL_RUNNING && totalConnections.get() < maxPoolSize && !addConnection()) {
// If we got into the loop, addConnection() failed, so we sleep and retry
quietlySleep(sleepBackoff);
sleepBackoff = Math.min(connectionTimeout / 2, (long) ((double) sleepBackoff * 1.5));
}
}
}
addConnectionExecutor.execute(new AddConnection());
}
// ***********************************************************************
// HikariPoolMBean methods
// ***********************************************************************
@ -352,6 +374,21 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
return connectionBag.getPendingQueue();
}
/** {@inheritDoc} */
@Override
public void softEvictConnections()
{
for (PoolBagEntry bagEntry : connectionBag.values(STATE_IN_USE)) {
bagEntry.evicted = true;
}
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(bagEntry)) {
closeConnection(bagEntry);
}
}
}
/** {@inheritDoc} */
@Override
public final void suspendPool()
@ -418,7 +455,6 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
transactionIsolation = (transactionIsolation < 0 ? connection.getTransactionIsolation() : transactionIsolation);
poolUtils.setupConnection(connection, isAutoCommit, isReadOnly, transactionIsolation, catalog);
connectionCustomizer.customize(connection);
poolUtils.executeSql(connection, configuration.getConnectionInitSql(), isAutoCommit);
poolUtils.setNetworkTimeout(connection, originalTimeout);
@ -456,46 +492,89 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
}
}
// ***********************************************************************
// Abstract methods
// ***********************************************************************
/**
* Permanently close the real (underlying) connection (eat any exception).
*
* @param connectionProxy the connection to actually close
*/
protected abstract void closeConnection(final PoolBagEntry bagEntry);
protected void closeConnection(final PoolBagEntry bagEntry)
{
bagEntry.cancelMaxLifeTermination();
if (connectionBag.remove(bagEntry)) {
final int tc = totalConnections.decrementAndGet();
if (tc < 0) {
LOGGER.warn("Internal accounting inconsistency, totalConnections={}", tc, new Exception());
}
closeConnectionExecutor.execute(new Runnable() {
public void run() {
poolUtils.quietlyCloseConnection(bagEntry.connection);
}
});
}
}
/**
* Check whether the connection is alive or not.
*
* @param connection the connection to test
* @param timeoutMs the timeout before we consider the test a failure
* @return true if the connection is alive, false if it is not alive or we timed out
*/
protected abstract boolean isConnectionAlive(final Connection connection);
protected boolean isConnectionAlive(final Connection connection)
{
try {
int timeoutSec = (int) TimeUnit.MILLISECONDS.toSeconds(validationTimeout);
/**
* Attempt to abort() active connections on Java7+, or close() them on Java6.
* @param assassinExecutor
*
* @throws InterruptedException
*/
protected abstract void abortActiveConnections(final ExecutorService assassinExecutor) throws InterruptedException;
if (isUseJdbc4Validation) {
return connection.isValid(timeoutSec);
}
/**
* Create the JVM version-specific ConcurrentBag instance used by the pool.
*
* @param listener the IBagStateListener instance
* @return a ConcurrentBag instance
*/
protected abstract ConcurrentBag<PoolBagEntry> createConcurrentBag(IBagStateListener listener);
final int originalTimeout = poolUtils.getAndSetNetworkTimeout(connection, validationTimeout);
try (Statement statement = connection.createStatement()) {
poolUtils.setQueryTimeout(statement, timeoutSec);
statement.executeQuery(configuration.getConnectionTestQuery());
}
if (isIsolateInternalQueries && !isAutoCommit) {
connection.rollback();
}
poolUtils.setNetworkTimeout(connection, originalTimeout);
return true;
}
catch (SQLException e) {
LOGGER.warn("Exception during keep alive check, that means the connection ({}) must be dead.", connection, e);
return false;
}
}
/**
* Create the JVM version-specific Housekeeping runnable instance used by the pool.
* @return the HouseKeeper instance
* Attempt to abort() active connections, or close() them.
*
* @throws InterruptedException
*/
protected abstract Runnable getHouseKeeper();
protected void abortActiveConnections(final ExecutorService assassinExecutor) throws InterruptedException
{
for (PoolBagEntry bagEntry : connectionBag.values(STATE_IN_USE)) {
try {
bagEntry.aborted = bagEntry.evicted = true;
bagEntry.connection.abort(assassinExecutor);
}
catch (Throwable e) {
if (e instanceof InterruptedException) {
throw (InterruptedException) e;
}
poolUtils.quietlyCloseConnection(bagEntry.connection);
}
finally {
if (connectionBag.remove(bagEntry)) {
totalConnections.decrementAndGet();
}
}
}
}
// ***********************************************************************
// Private methods
@ -531,20 +610,6 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
fillPool();
}
/**
* Construct the user's connection customizer, if specified.
*
* @return an IConnectionCustomizer instance
*/
private IConnectionCustomizer initializeCustomizer()
{
if (configuration.getConnectionCustomizerClassName() != null) {
return createInstance(configuration.getConnectionCustomizerClassName(), IConnectionCustomizer.class);
}
return configuration.getConnectionCustomizer();
}
public final void logPoolState(String... prefix)
{
if (LOGGER.isDebugEnabled()) {
@ -553,4 +618,40 @@ public abstract class BaseHikariPool implements HikariPoolMBean, IBagStateListen
getTotalConnections(), getActiveConnections(), getIdleConnections(), getThreadsAwaitingConnection());
}
}
// ***********************************************************************
// Non-anonymous Inner-classes
// ***********************************************************************
/**
* The house keeping task to retire idle connections.
*/
private class HouseKeeper implements Runnable
{
@Override
public void run()
{
logPoolState("Before cleanup ");
connectionTimeout = configuration.getConnectionTimeout(); // refresh member in case it changed
final long now = System.currentTimeMillis();
final long idleTimeout = configuration.getIdleTimeout();
for (PoolBagEntry bagEntry : connectionBag.values(STATE_NOT_IN_USE)) {
if (connectionBag.reserve(bagEntry)) {
if (bagEntry.evicted || (idleTimeout > 0L && now > bagEntry.lastAccess + idleTimeout)) {
closeConnection(bagEntry);
}
else {
connectionBag.unreserve(bagEntry);
}
}
}
logPoolState("After cleanup ");
fillPool(); // Try to maintain minimum connections
}
}
}

@ -40,7 +40,7 @@ public final class PoolBagEntry implements IConcurrentBagEntry
private volatile ScheduledFuture<?> endOfLife;
public PoolBagEntry(final Connection connection, final BaseHikariPool pool) {
public PoolBagEntry(final Connection connection, final HikariPool pool) {
this.connection = connection;
this.lastAccess = System.currentTimeMillis();

@ -71,17 +71,12 @@ public class ConcurrentBag<T extends IConcurrentBagEntry>
public ConcurrentBag(IBagStateListener listener)
{
this.sharedList = new CopyOnWriteArrayList<T>();
this.synchronizer = createQueuedSynchronizer();
this.synchronizer = new Synchronizer();
this.sequence = new AtomicLong(1);
this.listener = listener;
this.threadList = new ThreadLocal<ArrayList<WeakReference<IConcurrentBagEntry>>>();
}
protected AbstractQueuedLongSynchronizer createQueuedSynchronizer()
{
throw new RuntimeException("createQueuedSynchronizer() method must be overridden");
}
/**
* The method will borrow a BagEntry from the bag, blocking for the
* specified timeout if none are available.
@ -307,4 +302,27 @@ public class ConcurrentBag<T extends IConcurrentBagEntry>
LOGGER.info(bagEntry.toString());
}
}
/**
* Our private synchronizer that handles notify/wait type semantics.
*/
private static final class Synchronizer extends AbstractQueuedLongSynchronizer
{
private static final long serialVersionUID = 104753538004341218L;
@Override
protected long tryAcquireShared(long seq)
{
return getState() > seq && !hasQueuedPredecessors() ? 1L : -1L;
}
/** {@inheritDoc} */
@Override
protected boolean tryReleaseShared(long updateSeq)
{
setState(updateSeq);
return true;
}
}
}

@ -21,11 +21,9 @@ import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
/**
*
@ -33,19 +31,6 @@ import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
*/
public final class UtilityElf
{
public static final boolean IS_JAVA7;
static {
boolean b = false;
try {
b = AbstractQueuedLongSynchronizer.class.getMethod("hasQueuedPredecessors", new Class<?>[0]) != null;
}
catch (Exception e) {
}
IS_JAVA7 = b;
}
/**
* Get the elapsed time in millisecond between the specified start time and now.
*
@ -72,18 +57,6 @@ public final class UtilityElf
}
}
/**
* If the scheduled executor supports it, set the removeonCancelPolicy.
*
* @param executor the executor to set
*/
public static void setRemoveOnCancelPolicy(ScheduledThreadPoolExecutor executor)
{
if (IS_JAVA7) {
executor.setRemoveOnCancelPolicy(true);
}
}
/**
* Create and instance of the specified class using the constructor matching the specified
* arguments.

@ -12,7 +12,6 @@ import com.zaxxer.hikari.util.UtilityElf;
public class ConnectionStateTest
{
@SuppressWarnings("deprecation")
@Test
public void testAutoCommit() throws SQLException
{
@ -20,7 +19,6 @@ public class ConnectionStateTest
ds.setAutoCommit(true);
ds.setMinimumIdle(1);
ds.setMaximumPoolSize(1);
ds.setJdbc4ConnectionTest(false);
ds.setConnectionTestQuery("VALUES 1");
ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
ds.addDataSourceProperty("user", "bar");

@ -16,12 +16,9 @@
package com.zaxxer.hikari;
import static com.zaxxer.hikari.util.UtilityElf.IS_JAVA7;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
import org.junit.AfterClass;
import org.junit.Assert;
@ -31,8 +28,6 @@ import org.junit.Test;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.pool.PoolBagEntry;
import com.zaxxer.hikari.util.ConcurrentBag;
import com.zaxxer.hikari.util.IConcurrentBagEntry;
import com.zaxxer.hikari.util.Java8ConcurrentBag;
/**
*
@ -64,7 +59,7 @@ public class TestConcurrentBag
@Test
public void testConcurrentBag() throws InterruptedException
{
ConcurrentBag<PoolBagEntry> bag = new Java8ConcurrentBag(null);
ConcurrentBag<PoolBagEntry> bag = new ConcurrentBag<PoolBagEntry>(null);
Assert.assertEquals(0, bag.values(8).size());
HikariPool pool = TestElf.getPool(ds);
@ -83,7 +78,7 @@ public class TestConcurrentBag
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos, true);
TestElf.setSlf4jTargetStream(Java8ConcurrentBag.class, ps);
TestElf.setSlf4jTargetStream(ConcurrentBag.class, ps);
bag.requite(reserved);
Assert.assertTrue(new String(baos.toByteArray()).contains("does not exist"));
@ -110,60 +105,4 @@ public class TestConcurrentBag
Assert.assertNotNull(notinuse.toString());
}
@Test
public void testConcurrentBag2() throws InterruptedException
{
ConcurrentBag<PoolBagEntry> bag = new FauxJava6ConcurrentBag();
Assert.assertEquals(0, bag.values(IConcurrentBagEntry.STATE_IN_USE).size());
Assert.assertEquals(0, bag.getCount(IConcurrentBagEntry.STATE_IN_USE));
}
private static class FauxJava6ConcurrentBag extends ConcurrentBag<PoolBagEntry>
{
/**
* @param listener
*/
public FauxJava6ConcurrentBag() {
super(null);
}
@Override
protected AbstractQueuedLongSynchronizer createQueuedSynchronizer()
{
return new Synchronizer();
}
}
/**
* Our private synchronizer that handles notify/wait type semantics.
*/
private static final class Synchronizer extends AbstractQueuedLongSynchronizer
{
private static final long serialVersionUID = 104753538004341218L;
@Override
protected long tryAcquireShared(long seq)
{
return getState() > seq && !java67hasQueuedPredecessors() ? 1L : -1L;
}
/** {@inheritDoc} */
@Override
protected boolean tryReleaseShared(long updateSeq)
{
setState(updateSeq);
return true;
}
private boolean java67hasQueuedPredecessors()
{
if (IS_JAVA7) {
return hasQueuedPredecessors();
}
return false;
}
}
}

@ -41,7 +41,6 @@ import com.zaxxer.hikari.util.UtilityElf;
*/
public class TestConnections
{
@SuppressWarnings("deprecation")
@Test
public void testCreate() throws SQLException
{

@ -78,7 +78,7 @@ public final class TestElf
public static void setConfigUnitTest(boolean unitTest)
{
try {
Field field = AbstractHikariConfig.class.getDeclaredField("unitTest");
Field field = HikariConfig.class.getDeclaredField("unitTest");
field.setAccessible(true);
field.setBoolean(null, unitTest);
}

@ -17,8 +17,6 @@ package com.zaxxer.hikari;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;
import org.junit.Assert;
@ -29,7 +27,6 @@ import com.zaxxer.hikari.mocks.StubDataSource;
/**
* @author Brett Wooldridge
*/
@SuppressWarnings("deprecation")
public class TestValidation
{
@Test
@ -41,47 +38,6 @@ public class TestValidation
Assert.assertEquals(5, config.getMinimumIdle());
}
@Test
public void validateInvalidCustomizer()
{
HikariConfig config = new HikariConfig();
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
config.setConnectionCustomizerClassName("invalid");
config.validate();
Assert.assertNull(config.getConnectionCustomizerClassName());
}
@Test
public void validateValidCustomizer()
{
try {
HikariConfig config = new HikariConfig();
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
config.setConnectionCustomizerClassName("com.zaxxer.hikari.TestValidation$TestCustomizer");
config.validate();
Assert.assertNotNull(config.getConnectionCustomizer());
}
catch (Exception e) {
Assert.fail();
}
}
@Test
public void validateValidCustomizer2()
{
try {
HikariConfig config = new HikariConfig();
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
config.setConnectionCustomizer(new TestCustomizer());
config.validate();
Assert.assertNotNull(config.getConnectionCustomizer());
}
catch (Exception e) {
Assert.fail();
}
}
@Test
public void validateMissingProperties()
{
@ -297,12 +253,4 @@ public class TestValidation
// pass
}
}
public static class TestCustomizer implements IConnectionCustomizer
{
@Override
public void customize(Connection connection) throws SQLException
{
}
}
}
Loading…
Cancel
Save