[
  {
    "path": ".circleci/config.yml",
    "content": "jobs:\n  build: # name of your job\n    machine: true # executor type\n    resource_class: brettwooldridge/ubuntu\n\n    steps:\n      # Commands run in a Linux virtual machine environment\n      - checkout\n      - run: mvn clean package\n\n"
  },
  {
    "path": ".editorconfig",
    "content": "# EditorConfig is awesome: http://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n[**]\nend_of_line = lf\ninsert_final_newline = true\ncharset = utf-8\nindent_style = space\ntrim_trailing_whitespace = true\n\n[**.{java,xml}]\nindent_size = 3\n\n[**.{yaml,yml}]\nindent_size = 2\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  pull_request:\n    branches:\n      - master\n  push:\n    branches:\n      - master\n  # Allows you to run this workflow manually from the Actions tab\n  workflow_dispatch:\njobs:\n  build:\n    runs-on: ubuntu-20.04\n    strategy:\n      matrix:\n        java: ['11']\n    steps:\n    - uses: actions/checkout@v2\n    - name: Set up JDK\n      uses: actions/setup-java@v1\n      with:\n        java-version: ${{ matrix.java }}\n    - name: print Java version\n      run: java -version\n    - uses: actions/cache@v2\n      with:\n        path: ~/.m2/repository\n        key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}\n        restore-keys: |\n          ${{ runner.os }}-maven-\n    - name: Build\n      run: mvn --no-transfer-progress -B clean package --file pom.xml\n"
  },
  {
    "path": ".gitignore",
    "content": ".classpath\n.project\n.metadata\n\ntarget/\ndependency-reduced-pom.xml\n\n.DS_Store\n\n**/*.iml\n\n*.class\n*.jar\n*.war\n*.ear\n*.iml\n*.iws\n*.ipr\n\n.tm_*\n.idea/\n.gradle/\nout/\n"
  },
  {
    "path": ".settings/org.eclipse.core.resources.prefs",
    "content": "eclipse.preferences.version=1\nencoding//src/main/java=UTF-8\nencoding//src/main/resources=UTF-8\nencoding//src/test/java=UTF-8\nencoding//src/test/resources=UTF-8\nencoding//target/classes=UTF-8\nencoding/<project>=UTF-8\n"
  },
  {
    "path": ".settings/org.eclipse.jdt.apt.core.prefs",
    "content": "eclipse.preferences.version=1\norg.eclipse.jdt.apt.aptEnabled=false\n"
  },
  {
    "path": ".settings/org.eclipse.jdt.core.prefs",
    "content": "eclipse.preferences.version=1\norg.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=ignore\norg.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\norg.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate\norg.eclipse.jdt.core.compiler.codegen.targetPlatform=11\norg.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve\norg.eclipse.jdt.core.compiler.compliance=11\norg.eclipse.jdt.core.compiler.debug.lineNumber=generate\norg.eclipse.jdt.core.compiler.debug.localVariable=generate\norg.eclipse.jdt.core.compiler.debug.sourceFile=generate\norg.eclipse.jdt.core.compiler.problem.assertIdentifier=error\norg.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled\norg.eclipse.jdt.core.compiler.problem.enumIdentifier=error\norg.eclipse.jdt.core.compiler.problem.forbiddenReference=warning\norg.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore\norg.eclipse.jdt.core.compiler.processAnnotations=disabled\norg.eclipse.jdt.core.compiler.release=enabled\norg.eclipse.jdt.core.compiler.source=11\n"
  },
  {
    "path": ".settings/org.eclipse.m2e.core.prefs",
    "content": "activeProfiles=\neclipse.preferences.version=1\nresolveWorkspaceProjects=true\nversion=1\n"
  },
  {
    "path": ".settings/org.eclipse.pde.core.prefs",
    "content": "BUNDLE_ROOT_PATH=target/classes\neclipse.preferences.version=1\n"
  },
  {
    "path": "CHANGES",
    "content": "HikariCP Changes\n\nChanges in 7.0.2\n\n * decrease thread yield frequency in ConcurrentBag.unreserve()\n\nChanges in 7.0.1\n\n * merged #2346 fix regression with setSchema behavior\n\n * decrease thread yield frequency in ConcurrentBag.requite()\n\nChanges in 7.0.0\n\n * merged #2340 NoSuchMethodException error that is thrown when setting a metric registry, fixes to UtilityElf\n   reflection code to use the correct method signature.\n\n * fixed #1294 add support for HikariCredentialsProvider class\n\n * fixed #2265 bail out of the pool filling loop if the thread is interrupted\n\nChanges in 6.3.3\n\n * backport #2340 NoSuchMethodException error that is thrown when setting a metric registry, fixes to UtilityElf\n   reflection code to use the correct method signature.\n\nChanges in 6.3.2\n\n * fixed #2342 restore module-info.class to jar file, which was lost in 6.3.1\n\n * fixed #2256 add support for legacy override of getUsername()/getPassword() of HikariDataSource. See project page\n   for documentation of system property com.zaxxer.hikari.legacy.supportUserPassDataSourceOverride.\n\n * fixed #2323 right or wrong (wrt driver behavior) return to previous Connection.get/setSchema behavior\n\n * fixed #2288 upgrade dependencies and fix build warnings\n\nChanges in 6.3.1\n\n * fixed #2315 source jar contains also binary .class files and missing some .java files\n\n * fixed #2307 remove improper hardcoded timout, use validationTimeout\n\n * fixed #2305 keep properties key and values as is rather than forcing stringification. Also fixes #2286 and #2304\n\n * upgraded various maven plugin dependencies to latest versions\n\nChanges in 6.3.0\n\n * increase keepaliveTime variance from 10% to 20%\n\n * merged #2266 support duration values for configuration from properties, such as 10ms, 20s, 30m, 40h or 50d\n\n * merged #2284 align logs from HikariPool.logPoolState()\n\n * merged #2285 set default value for maxIdle in HikariConfig constructor (no functional change)\n\n * merged #2294 Allow setting String[] and int[] properties (useful for pgjdbc HA configuration)\n\n * merged #2300 catch java.lang.Error instead of java.lang.Exception under certain conditions\n\nChanges in 6.2.1\n\n * change default keepaliveTime to 2 minutes\n\n * fix commons-compress dependency, make test scope\n\nChanges in 6.2.0\n\n * merged #2238 handle SQLTimeoutException without eviction. Users looking to preserve previous behavior\n   should provide an implementation of com.zaxxer.hikari.SQLExceptionOverride to the pool configuration.\n\n * added new enum value, Override.MUST_EVICT, available to implementations of com.zaxxer.hikari.SQLExceptionOverride\n\n * enhanced debug logging in circumstances where the pool falls to zero size and new connections to the database\n   continue to fail.\n\n * update test dependencies that were flagged as having vulnerabilities\n\nChanges in 6.1.0\n\n * fixed #1960 allow SQLExceptionOverride to adjudicate all exceptions for eviction\n\n * merged #1962 dropwizard 5 metrics are now supported via the setMetricRegistry() method in HikariConfig and in HikariDataSource\n\n * merged #2244 improve JavassistProxyFactory\n\n * merged #2243 fix inconsistency between isWrapperFor and unwrap\n\n * merged #1827 support loading properties file in unnamed resources module\n\n * merged #1842 don't clear isCommitStateDirty flag in setReadOnly\n\n * change default maxLifetime variance from 2.5% to 25% to further avoid mass connection die-off dips\n\nChanges in 6.0.0\n\n * fixed #2152 duplicate connection in try with resources clause caused close() being called twice on each connection\n\n * merged #2226 consistent handling of errorCode and sqlState in timeout exception\n\n * merged #2199 eliminate network call if state get is called after set\n\n * merged #2189 add support to get and set db credentials in an atomic operation\n\n * merged #2149 make Savepoint rollbacks mark the connection dirty\n\n * merged #2157 close connections marked as evicted instead of returning them to the pool\n\n * merged #2147 skip Connection::setNetworkTimeout if PoolBase::shutdownNetworkTimeoutExecutor is called\n\n * merged #2126 added Support For beginRequest and endRequest\n\n * small improvements and cleanup from pull request #2166\n\n * minor debug logging enhancements\n\nChanges in 5.1.0\n\n * fixed #1907 re-added automatic.module.name that was lost along the way\n\n * fixed #1986 evict connection exceptions with (SQLState HY000) error code 1105.\n\n * merged #2059 add support for char[] in DataSource properties\n\n * merged #1979 and #1993 mask any property that looks like a password in URLs\n\n * add pool stats to connection acquisition timeout exception\n\n * merged #2076 don't case metric registry before it is checked for null\n\n * merged #1820 allow minimum login timeout to be set as system property\n\n * merged #1952 add more isolation levels\n\n * merged #1660 remove redundant error log for poll initialization exception\n\nChanges in 5.0.1\n\n * Update log4j version to 2.17.1 to address Log4Shell vulnerability (although this is only used in tests, so it doesn't really impact users)\n\nChanges in 5.0.0\n\n * rewrote connection elide/add code to fix an unconfirmed but occasionally reported\n   race condition that results in the pool draining to 0 and not refilling.\n\nChanges in 4.0.3\n\n * fixed #1735 added system property to permit override of lower limit of connectionTimeout\n   and validation timeout\n\nChanges in 4.0.2\n\n * fixed regression caused by #1605 affecting block-until-filled semantic\n\nChanges in 4.0.1\n\n * fixed #1725 pom file change to be more gradle-friendly\n\n * fixed #1726 regression in micrometrics caused by lack of a strong reference to an\n   object\n\nChanges in 4.0.0\n\n * merged #1669 #1582 mark optional dependencies as 'require static' in module-info\n\n * merged #1700 remove micrometer metrics upon close\n\n * merged #1661 mark generated proxy classes final\n\n * merged #1681 allow alternate, more standard, JMX ObjectName, enabled by setting system\n   property 'hikaricp.jmx.register2.0=true'\n\n * merged #1605 fixes Java 11 issue where setMaximumPoolSize needs to be called before\n   setCorePoolSize in ThreadPoolExecutor\n\n * merged #1581 handle setting java 'short' property values from property files\n\n * merged #1699 add new configuration property 'keepaliveTime'\n\n * merged #1692 fix prometheus histogram metric tracker for multiple pools\n\nChanges in 3.4.5\n\n * fixed 1578 build change to ensure that proxies are generated using Java 8, otherwise we end\n   up with class references to Java 11 classes, which fail to load on Java 8.\n\nChanges in 3.4.4\n\n * Build HikariCP as a JEP 238 Multi-Release jar for increased compatability with Java 11 and\n   future modularized Java versions.\n\nChanges in 3.4.3\n\n * fixed 1534 check resultSet.getStatement() for null in ProxyDatabaseMetaData.\n\n * add additional debug logging around connection add.\n\n * add ThreadLocal removal attempt when bag item is removed.\n\nChanges in 3.4.2\n\n * fixed 1528 regression caused by pull request 1159 whereby fail-fast logic would exit upon all\n   errors even if it was configured to continue trying.\n\nChanges in 3.4.1\n\n * fix regression caused by 1337, which broke the ability to pass the isolation level by integer\n   value (string) instead of isolation level name.\n\nChanges in 3.4.0\n\n * merged 1265 alternative Prometheus metrics Histogram instead of locking Summary (which is\n   purportedly quite lock-heavy.\n\n * merged 1337 support accepting TRANSACTION_SQL_SERVER_SNAPSHOT_ISOLATION_LEVEL string for\n   isolation level.\n\n * merged 1331 user contribution: major refactor of metrics handling, hopefully without any\n   breakage.\n\n * add proxy class for DatabaseMetaData to intercept DatabaseMetaData.getConnection() call which was\n   leaking the raw database Connection object.\n\nChanges in 3.3.1\n\n * fixed 1287 set core pool size before max pool size\n\n * fixed 1308 treat a SQLTimeoutException as an evictable offense\n\n * do not default maxPoolSize to minIdle when only minIdle is specified\n\n * do not log warning about idleTimeout unless minimumIdle is less than maxPoolSize (because otherwise\n   it does not apply)\n\nChanges in 3.3.0\n\n * Revert change where Connection.isClosed() was called outside of setNetworkTimeout() block, opening\n   vulnerability to unacknowledged TCP traffic.\n\n * fixed 1186 limit number of items in the ConcurrentBag's ThreadLocal list to avoid OOM errors in some\n   borrow/requite patterns.\n\n * Merged changed to log uncaught (Throwable) exceptions during connection acquisition.\n\n * fixed 1161 fix logging formatting anchor.\n\n * fixed 1181, 1182 allow passing a Prometheus CollectorRegistry rather than always using the default\n   registry.\n\n * merged 1210 use orElseGet() to delay call until necessary with respect to the housekeeper thread\n   factory.\n\n * fixed 1074 capability to instantiate an object based on the String class name, usefull when you want\n   to set the MetricsTackerFactory from a property.\n\n * merged 1250 fix proxy classes generation reproducibility using a sorted LinkedHashSet\n\n * various clean-ups pointed out by sonarcloud.io\n\n * merged 1290 Class.newInstance() is deprecated as of Java 9. Usage should be replaced by calling\n   Class.getDeclaredConstructor().newInstance().\n\n * fixed #1305 ensure that ConcurrentBag.add() does not spin under high load, when waiting threads may never\n   reach 0.\n\n * fixes #1287 when system property blockUntilFilled is set, use multiple threads to fill the pool.\n\nChanges in 3.2.0\n\n * check connection closed condition before attempting to set network timeout to avoid spurios exceptions\n   in the log.\n\n * updated validation failure message to include recommendation to check maxLifetime value.\n\n * fixed 1141 do not throw SQLException when calling isClosed() or close() on a already closed unwrapped\n   Connection, as per JDBC specification.\n\n * fixed 1137 support changing user/password at runtime for DriverDataSource-wrapped driver connections.\n\n * fixed 1136 log loaded driver when using jdbcUrl.\n\n * pull 1135 extract sealed pool check into independent method.\n\n * fixed 1126 correct error in JavaDoc for HikariConfig.setInitializationFailTimeout().\n\n * fixed 1114 removed unreachable code.\n\nChanges in 3.1.0\n\n * Add get/setCatalog() to HikariConfigMXBean, allowing the catalog to be changed at runtime.\n   The catalog should only be changed while the pool is suspended, and after evicting existing\n   connections via HikariPoolMXBean.softEvictConnections().\n\nChanges in 3.0.0\n\n * Removed previously deprecated methods;\n     HikariConfig.copyState()\n     HikariConfig.getScheduledExecutorService()\n     HikariConfig.setScheduledExecutorService()\n     HikariConfig.isInitializationFailFast()\n     HikariConfig.setInitializationFailFast()\n     HikariConfig.isJdbc4ConnectionTest()\n     HikariConfig.setJdbc4ConnectionTest()\n\n     HikariDataSource.copyState()\n     HikariDataSource.getScheduledExecutorService()\n     HikariDataSource.setScheduledExecutorService()\n     HikariDataSource.suspendPool()\n     HikariDataSource.resumePool()\n     HikariDataSource.shutdown()\n     HikariDataSource.isInitializationFailFast()\n     HikariDataSource.setInitializationFailFast()\n     HikariDataSource.isJdbc4ConnectionTest()\n     HikariDataSource.setJdbc4ConnectionTest()\n\n * pull 1110 add currently configured maxConnections and minConnections to pool metrics.\n\n * pull 1100 remove hard-coded percentiles for Micrometer metrics.\n\n * pull 1108 maintain a strong reference to PoolStats for Micrometer gauges to prevent premature\n   garbage collection.\n\n * pull 1098 update to Micrometer 1.0.0.\n\nChanges in 2.7.8\n\n * fixed 1095 fix breakage caused by sealed configuration with respect to special handling for the\n   metricsRegistry and metricsTrackerFactory properties, which are allowed to be altered *once*\n   after the pool has started (even after the configuration is sealed).\n\n * pull 1089 allowing anonymous subclasses of MetricRegistry. Changed checks for metrics libraries\n   from a class name check to the assignableFrom() API.\n\nChanges in 2.7.7\n\n * fixed issue whereby configuration through the HikariConfigMXBean could not be altered due\n   to the sealed configuration change introduced in 2.7.5.\n\nChanges in 2.7.6\n\n * issue 1064 fixed regression where HikariConfig.copyStateTo() propagated the \"sealed\" status\n   of the source configuration to the target configuration -- preventing further changes.\n\nChanges in 2.7.5\n\n * issue 1061/pull 1062 fixed compatibility issue with requery.io caused by HikariCP's\n   proxied Statement class returning a driver-native ResultSet instance from getGeneratedKeys()\n   instead of returning a HikariCP proxied ResultSet.\n\n * pull 1058 enable quantiles on Prometheus metrics.\n\n * pull 1055 fixed incorrect JavaDoc for HikariConfigMXBean.getMinimumIdle() method.\n\n * issue 1045/pull 1047 added Automatic-Module-Name to jar manifest to ensure that the Java 8\n   library plays well with the Java 9 module system.\n\n * introduced the concept of a \"sealed\" configuration.  Once a pool is started, attempts to\n   alter its configuration outside of the HikariConfigMXBean will result in an IllegalStateException.\n\nChanges in 2.7.4\n\n * pull 1026 added support for SQL Server's specific isolation level (SNAPSHOT).\n\n * issue 926/pull 1022 HikariJNDIFactory should not throw a NamingException or else\n   cascading to other object factories cannot occur.\n\nChanges in 2.7.3\n\n * issue 1003 added PostgreSQL SQL State 0A000 to list of unrecoverable states calling\n   for eviction.\n\n * pull 1002 updated micrometer support due to API changes in their release candidate.\n\nChanges in 2.7.2\n\n * issue 983 fix logic that determines how many idle connections can be removed, without\n   violating the minimumIdle contract.\n\n * pull 987 add thread name to leak detection messages.\n\n * issue 982 fix classloader order, try the ThreadContext classloader before other\n   classloaders.\n\n * pull 977 log better messages when connection is evicted.\n\n * fallback to four digit random pool suffix when SecurityManager prevents writing\n   to system properties for the purpose of JVM-wide unique pool identifiers.\n\nChanges in 2.7.1\n\n * issue 968 Wrong label order in MicrometerMetricsTracker for the connection usage\n   metric.\n\n * issue 967 incorrect bitwise operator value in ConcurrentBag.requite method\n   intended to cause parkNanos() to be called every 256 iterations. Thanks to @ztkmkoo\n   for finding this.\n\nChanges in 2.4.13\n\n * backport more efficient contention handling in ConcurrentBag.requite from 2.6.x\n   branch.\n\n * issue 955 fix possible race condition when Statements are closed on different\n   threads from which they were created.\n\nChanges in 2.7.0\n\n * added support for micrometer metrics (currently Alpha-level support).\n\n * issue 905 mask JDBC password in URLs\n\n * issue 940 fix Prometheus metric collector for multiple data config\n\n * issue 941 add support for setting a default schema\n\n * issue 955 fix possible race condition when Statements are closed on different\n   threads from which they were created.\n\nChanges in 2.6.3\n\n * issue 878 load driver class from ThreadContext classloader if it is not found\n   via the regular classloader.\n\nChanges in 2.6.2\n\n * issue 890 add support for Prometheus metrics and multiple HikariCP pools.\n\n * issue 880 fix race condition caused by sorting collection while the condition of\n   sort can change.\n\n * issue 876 add support for using a Prometheus CollectorRegistry other than the\n   default one.\n\n * issue 867 support network timeout even for Connection.isValid().\n\n * issue 866 mark commit state dirty when Connection.getMetaData() is called.\n\nChanges in 2.6.1\n\n * issue 821 if a disconnection class exception is thrown during initial connection\n   setup, do not set the flag that indicates that checkDriverSupport() is complete.\n\n * issue 835 fix increased CPU consumption under heavy load caused by excessive\n   spinning in the ConcurrentBag.requite() method.\n\n * issue 817 updated behavior of new initializationFailTimeout, please see the\n   official documentation for details.\n\n * issue 742 add direct MXBean accessor methods to HikariDataSource for users who do\n   not want run run JMX.\n\nChanges in 2.6.0\n\n * Redesign of the contention code path resulting in doubling contended throughput; now\n   contended pool access retains 98% of the uncontended throughput.\n\n * issue 793 add new HikariConfig method, setScheduledExecutor(ScheduledExecutorService),\n   and deprecate method setScheduledExecutorService(ScheduledThreadPoolExecutor). It is\n   unfortunate that the deprecated method has the more accurate name, but its signature\n   cannot be changed without breaking binary compatibility.\n\n * issue 770 add a new property initializationFailTimeout, and deprecate configuration\n   property initializationFailFast.\n\n * issue 774 significantly improve spike load handling.\n\n * issues 518/769 add new metric for tracking how long physical connection acquisition is\n   taking.  DropWizard histogram name \"ConnectionCreation\", and Prometheus summary name\n   \"hikaricp_connection_creation_millis\".\n\n * issue 741 cancel HouseKeeper task on pool shutdown. If the ScheduledExecutor being used\n   did not belong to HikariCP, this task would remain scheduled after shutdown, causing a\n   memory leak.\n\n * issue 781 more technically accurate wording of pool startup and shutdown log messages.\n\nChanges in 2.5.1\n\n * issue 719 only reset lastConnectionFailure after a successful dataSource.getConnection()\n   call.\n\n * issue 716 do not scan deeper than 10 nested SQLExceptions, it's typically a trap ...\n   a chain that never terminates.\n\n * issue 714 fix possible issue with cross-thread visibility.  Change pool entry state from\n   AtomicInteger w/lazySet() to a volatile int with use of AtomicIntegerFieldUpdater.\n\nChanges in 2.5.0\n\n * Release 2.5.0 marks the start of a Java 8 HikariCP artifact.  The Java 7 artifact is\n   now called \"HikariCP-java7\".\n\n * HikariCP 2.5.0 and HikariCP-java7 2.4.8 have identical functionality.\n\nChanges in 2.4.12\n\n * issue 878 search for driverClass in both HikariCP class classloader and Thread Context\n   ClassLoader\n\nChanges in 2.4.11\n\n * issue 793 add new HikariConfig method, setScheduledExecutor(ScheduledExecutorService),\n   and deprecate method setScheduledExecutorService(ScheduledThreadPoolExecutor). It is\n   unfortunate that the deprecated method has the more accurate name, but its signature\n   cannot be changed without breaking binary compatibility.\n\n * issue 600 ignore Java 8 default methods when generating proxy classes for Java 7.\n\nChanges in 2.4.10\n\n * Redesign of the contention code path resulting in doubling contended throughput; now\n   contended pool access retains 98% of the uncontended throughput.\n\n * issue 770 add a new property initializationFailTimeout, and deprecate configuration\n   property initializationFailFast.\n\n * issue 774 significantly improve spike load handling.\n\n * issue 741 cancel HouseKeeper task on pool shutdown. If the ScheduledExecutor being used\n   did not belong to HikariCP, this task would remain scheduled after shutdown, causing a\n   memory leak.\n\nChanges in 2.4.9\n\n * issue 719 only reset lastConnectionFailure after a successful dataSource.getConnection()\n   call.\n\n * issue 716 do not scan deeper than 10 nested SQLExceptions, it's typically a trap ...\n   a chain that never terminates.\n\n * issue 714 fix possible issue with cross-thread visibility.  Change pool entry state from\n   AtomicInteger w/lazySet() to a volatile int with use of AtomicIntegerFieldUpdater.\n\nChanges in 2.4.8\n\n * Release 2.4.8 marks the start of a Java 7 HikariCP artifact, HikariCP-java7, representing\n   support for Java 7 entering maintenance mode.\n\n * Added Connection.commit() call to the fail-fast initialization for databases that\n   automatically start a new Connection in a transaction and throw an exception on close\n   if it is not committed.\n\n * feature 694: report if a previously reported leaked connection is returned to the pool\n\n * issue 689: log a warning if default transaction isolation level cannot be detected.\n   This can occur with pseudo-database drivers such as the one for JSonar\n\n * issue 674: fix regression caused by pull request #450 (overzealous optimisation)\n\nChanges in 2.4.7\n\n * Miscellaneous stability improvements.\n\n * Removed Oracle SQL state 61000, added specific error code (2399) to evict connections\n   when it is encountered.\n\n * issue 664: do not recycle PoolEntry objects that have closed their held connection.\n\n * issue 641, 643: reflection used method String.toUpperCase() without a Locale, which causes\n   problems in some locales such as Turkish.\n\n * pull 632: added support for Prometheus metrics tracker.\n\n * issue 650: detect Amazon Redshift connection refused error codes.\n\nChanges in 2.4.6\n\n * Added Oracle SQL error code 61000 (exceeded maximum connect time) to evict connections\n   when it is encountered.\n\n * issue 621: fix NPE in shutdown if invoked during initialization.\n\n * issue 606, 610: housekeeper thread was running before all class members were\n   initialized, causing an unrecoverable exception and disabling idle connection\n   retirement (maximumLifetime still applied).\n\nChanges in 2.4.5\n\n * issue 596: fix bug that occurs when minimumIdle is set to 0, but maximumPoolSize is\n   not explicitly set.\n\n * issue 594: fix incompatibility with various libraries caused by storing a non-String\n   object in System properties.\n\n * issue 593: improve logging when network timeout is not supported by the driver\n\n * issue 591: improve thread-safety of Statement proxies\n\nChanges in 2.4.4\n\n * Generate unique sequential pool names, even across container classloaders to avoid\n   JMX name collisions when registering pools.\n\n * Improve pool stability when running on computers using power-saving or sleep modes\n   where wake-up previously caused pool to grow to maximum size.\n\n * Improve pool stability under severe thread-starvation conditions.  Previous code\n   could interpret prolonged starvation (exceeding one minute) as non-contiguous clock\n   advancement, and reacted by soft-evicting connections (unnecessarily).\n\n * Added connection timeout rate to Dropwizard metrics (ConnectionTimeoutRate).\n\n * issue 563: Do not start the house-keeping thread until after pool initialisation\n   has succeeded.\n\n * issue 559: Ensure the pool refill after house-keeping does not enqueue more add\n   connection requests if there are already minimumIdle requests pending.\n\n * issue 555: include support for Java 8 interface 'default' methods during proxy\n   generation.\n\n * issue 547: decreased allowable minimum connectionTimeout and validationTimeout to\n   250ms.\n\n * issue 495: implemented iterator() method on custom FastList to support Tomcat\n   memory leak detection.\n\nChanges in 2.3.13\n\n * issue 512: reduce the number of calls made to Connection.getAutoCommit().\n\nChanges in 2.4.3\n\n * Improve pool shutdown behavior.  Stop active connection acquisition once the\n   shutdown sequence has initiated.\n\n * Improved detection and reporting of ambiguous pool configuration, when both the\n   connection URL and DataSource class names are specified.\n\nChanges in 2.4.2\n\n * Improve accuracy of timeouts for getConnection() calls by accounting for possibly\n   long delay aliveness tests.\n\n * Improve adherence to minimumIdle goal by closing idle connections starting from\n   longest idle time to shortest.  Additionally, stop when minimumIdle is reached even\n   if connections exceeding idleTimeout remain (but are still within maxLifetime).\n\n * Introduce larger variance into maxLifetime to avoid mass connection closing and\n   subsequent new connection creation load on the database.  Connections now have a\n   maximum lifetime between 97.5-100% of configured maxLifetime.  In the case of the\n   default 30 minute lifetime, this generates actual lifetimes with a maximum deviation\n   of 45 seconds.  Currently, no attempt is made to further avoid clustering that may\n   occur due to randomness.\n\n * Ongoing com.zaxxer.hikari.metrics refactors. This is not considered public API until\n   such time as we announce it. Caveat lector.\n\n * Performance improvements in the getConnection()/close() hot path.\n\n * issue 452: fixed race condition when creating an rapidly ramping connections in the\n   pool.\n\n * issue 415: removed use of java.beans classes to allow use of HikariCP with the\n   Zulu JRE compact3 profile.\n\n * issue 406: execute validation query during connection setup to make sure it is\n   valid SQL.\n\nChanges in 2.3.12\n\n * Fixed issue with proxy generation whereby the generated classes contain the\n   major version number for Java 8, which makes them incompatible with the Java 7\n   runtime.\n\nChanges in 2.4.1\n\n * issue 380: housekeeper was not being scheduled in the case of a user specified\n   ScheduledExecutorService instance.\n\n * issue 340: rollback change that elides setting the readonly property if the user\n   never explicitly configured it.  See discussion in the Github issue tracker.  Also\n   fixes binary ABI breakage between 2.3.9 and 2.4.0.\n\n * issue 379: stop closing idle connections, to keep minimumIdle connections in pool\n\n * issue 375: fixed InvalidPathException in HikariConfig\n\n * issue 362: fixed NullPointerException in closing connection (closing statements)\n\n * issue 357: allow altering the username & password through JMX at runtime\n\n * issue 349: handle integer Transaction isolation level\n\n * Throw SQLTransientConnectionException instead of SQLTimeoutException\n\n * for validating connection, if network time out is set, do not set query timeout too\n\n * ResultSet.getStatement() should return StatementProxy\n\nChanges in 2.4.0\n\n * Consolidated distribution into single JVM target (Java 7/8).  Java 6 support has\n   entered maintenance mode, bug fixes will continue on the 2.3.x branch.\n\n * Removed runtime dependency on Javassist by pre-generating proxy classes at build-time.\n\n * Significantly reduced overhead, and increased reliability, of ConcurrentBag.\n\n * Reduced garbage generation by 2-3x.\n\n * Add connection soft-eviction and replacement if backward system clock motion or\n   significant forward jumps (greater than 1 minute) are detected.\n\n * Pool configuration properties and DataSource methods previously marked as\n   @Deprecated have been removed.\n\n * Deprecated HikariDataSource.shutdown() in favor of close().\n\n * Improve shutdown performance.\n\n * Allow user specified ScheduledThreadPoolExecutor for housekeeping timer.  Useful\n   in applications with dozens or hundreds of pools in the same JVM.\n\n * Reduce overhead and accuracy of Dropwizard gauges.\n\nChanges in 2.3.7\n\n * Try harder at resolving the driver by various means when both driverClassName and jdbcUrl\n   have been specified.\n\n * Allow a specifically set DataSource instance to override other settings such as jdbcUrl,\n   dataSourceClassName, or driverClassName.\n\n * Fixed issue where, in the case of a driver-based configuration (jdbcUrl), we were not\n   initialising the network timeout Executor.\n\n * Fixed race condition uncovered during load-testing in which the connections in the pool\n   can spike to the maximum pool size when many connections reach their maxLifetime at the\n   same time.\n\nChanges in 2.3.6\n\n * Allow explicit definition of driverClassName to override DriverManager.getDriver(url)\n   located driver.\n\n * Fixed a rare issue where a Connection that is held out of the pool, and never used by\n   the holding thread, upon returning to the pool might be given to another thread without\n   an aliveness test.\n\nChanges in 2.3.5\n\n * Fixed regression caused by enhancement #279 that imposed a runtime dependency on\n   Dropwizard metrics.\n\nChanges in 2.3.4\n\n * Fixed class cast exception when setting the HealthCheckRegistry via JNDI lookup.\n\n * Allow Dropwizard MetricRegistry/HealthCheckRegistry to be set after pool startup --\n   one time only.\n\n * Make logger in BaseHikariPool non-static and use getClass() to log messages as the\n   implementation class rather than as BaseHikariPool.\n\n * Removed deprecation from connectionInitSql, it will be allowed.\n\n * Made suspect/resume lock non-static (should be be shared across pools).\n\n * Improved unwrap() behavior in the Hibernate HikariConnectionProvider.\n\n * Improved leak detection log\n\nChanges in 2.3.3\n\n * Fixed bad interaction with PostgeSQL JDBC driver whereby a SQLException thrown by\n   PostgreSQL where the getNextException() call returns the original exception and causes\n   an infinite loop in HikariCP (and eventual stack overflow).\n\n * Throw a typed Exception rather than a simple RuntimeException when pool initialization\n   fails.\n\n * Allow Dropwizard Metrics and HealthChecks to be configured by a JNDI lookup.\n\nChanges in 2.3.2\n\n * Add support for Dropwizard HealthChecks through the introduction of two initial health\n   checks: ConnectivityCheck and Connection99Percent.  See the Github project wiki for\n   documentation.\n\n * Allow a lower maxLifetime setting of 30 seconds (compared to previous 120 second limit)\n\n * Improve the message displayed when a connection leak is detected.\n\n * Fixed a bug where Connection.setNetworkTimeout() was called on an already closed connection\n   resulting in a warning log from the AS400 JDBC driver.\n\nChanges in 2.3.1\n\n * Work around a bug in the MySQL Connector/J implementation of Connection.setNetworkTimeout()\n   that results in non-deterministic asynchronous application of the timeout, resulting in an\n   NPE from the MySQL driver when setNetworkTimeout() is followed immediately by close().\n\n * Introduced a separate validationTimeout property, distict from connectionTimeout, to allow\n   greater control for some deployments that desire a long (or infinite) connectionTimeout\n   but expect the aliveness check to succeed for fail within a different (shorter) amount of\n   time.\n\nChanges in 2.3.0\n\n * Support pool suspend/resume to support certain failover scenarios.\n\n * Fix theoretical race in JDBC 4.0 detection support.\n\n * Improve shutdown() semantics to avoid exceptions as connections are forcefully\n   aborted.\n\n * Unregister Codahale metrics at shutdown, if metrics are enabled.\n\n * Major internal project layout restructuring to allow shared use of common code\n   between the Java 6/7 and Java 8 versions.\n\n * Fixed bug where two pools in the same VM (and ClassLoading domain), using drivers\n   with differing JDBC support levels, would fail unless both pools were using\n   connectionTestQuery.\n\n * Improved timeliness of maxLifetime evictions, while increasing performance of\n   getConnection() slightly as a side-effect.\n\n * Fixed bug in HikariDataSource unwrap() semantics.\n\n * Allow a lower leakDetectionThreshold of 2 seconds.\n\n * Fixed bug when using the HikariJNDIFactory that required the presence of\n   Codahale metrics.\n\n * Support initializationFailFast even when minimumIdle = 0\n\n * Log internal pool inconsistencies rather than throwing exceptions that might\n   disrupt internal executors.\n\n * Guard against poor or unreliable System.nanoTime() implementations.\n\nChanges in 2.2.5\n\n * Fixes for Java 6 compatibility.\n\n * Implement full transaction state tracking.  This allows HikariCP to bypass\n   the automatic rollback when connections are returned to the pool if the\n   transaction state is \"clean\".\n\n * Rename MBean closeIdleConnections() to softEvictConnections() and implement\n   \"evict on return\" semantics.\n\n * Fixed bug in code that sets HikariConfig values from a Properties instance\n   that prevented defaults from being read properly.\n\n * Fixed an obscure bug in connection creation with a driver that throws an\n   exception when setTransactionIsolation() is called with the value returned\n   by getTransactionIsolation().  We now bypass setTransactionIsolation() if\n   the user has not configured an isolation level (using the default).\n\n * Fix a bug where DataSource.loginTimeout() was always being set to 1 second.\n\n * Fix bug where some drivers return 0 from Connection.getNetworkTimeout(),\n   and yet throw SQLFeatureNotSupportedException when setNetworkTimeout() is\n   called. This broke they way that HikariCP had implemented JDBC 4.1 support\n   detection.\n\nChanges in 2.2.4\n\n * Generate proxy classes into the same protection domain as the HikariCP\n   loaded classes.  This solves issues with signed jars.\n\n * Improve accuracy of pool statistics available to JMX and logged at debug\n   level (at a slight performance cost).\n\n * Fixed issue where after a database down condition, and when minimumIdle is\n   set to 0, when the database connectivity is restored the connections could\n   ramp up to the maximum pool size.  Eventually, idleTimeout and maxLifetime\n   would restore normal pool conditions, but it was still undesirable behavior.\n\n * Improved connection timeout handling by using Connection.setNetworkTimeout()\n   if available (JDBC 4.1).\n\n * driverClassName is no longer a required property when jdbcUrl is specified.\n   Omitting this property only works for compliant drivers.\n\n * Add auto-detection of support for Statement.setQueryTimeout() used in the\n   alive check.  Fixes failures with test queries on the PostgreSQL driver\n   when not using JDBC4 isValid() alive checks.\n\n * The pool now defaults to fail-fast initialization.  If you need to start\n   your application without/before the database, you will need to explicitly\n   set initializationFailFast to false.\n\n * Dropwizard/Codahale metrics are now supported via the setMetricRegistry()\n   method in HikariConfig and in HikariDataSource.\n\n * Fixed issue with pool initialization of MySQL after default value of\n   initializationFailFast property was changed to false.\n\n * Further shadow runtime dependency on Codahale metrics from reflection\n   performed by Spring and other IoC containers.\n\n * Fix issue where network timeout was not properly restored to its default\n   value after modifying it for the duration of the addConnection() method.\n\nChanges in 2.1.0\n\n * Significant internal refactor supporting creation of new proxy instances\n   (throwaway) around Connections for each call to getConnection().  This\n   can avoid issues where a thread continues to try to use a connection\n   after it is closed [returned to the pool].\n\n * Allow HikariConfig(String propertyFileName) to load properties file from\n   classloader as a stream, with fall-back to the file-system.\n\n * Allow loading of properties file specified by -Dhikaricp.configurationFile\n   system property when using the default HikariConfig() or HikariDataSource()\n   constructors.\n\n * Fixed accounting issue with totalConnections when aborting connections\n   during shutdown, causing a warning message to be logged.\n\n * Fixed regression in Java 8 codeline that would prevent minimumIdle from\n   being set before maxPoolSize.\n\n * Fixed regression with Tomcat carping about ThreadLocal variables held after\n   web application restart\n\n * Change to make HikariConfig.getTransactionIsolation()/setTransactionIsolation()\n   follow proper bean semantics.\n\n * Fixed issue where connections created in the pool would skip the alive check\n   the first time they were used.\n\nChanges in 2.0.1\n\n * Split project into Java 6/7 and Java 8 components.\n\n * Fixed issue in JNDI object factory which would not allow JNDI-defined\n   DataSource properties to pass-thru to the pool.\n\n * Fixed issue where under certain conditions getConnection() could\n   timeout prematurely.\n\n * Fixed issue where user-defined pool name would be overridden by the\n   automatically generated name.\n\n * Fixed NPE when one of either username and password is defined, and the\n   other is null.\n\n * Fixed issue tracking the statements when there are mixed statement\n   types (Statement, PreparedStatement, etc.) open on the connection and\n   the number of unclosed statements exceeds 32.\n\n * Fixed issue where housekeeping threads would add idle connections\n   even when minimumIdle was 0.\n\n * Fixed issue where Wrapper.isWrapperFor() and Wrapper.unwrap() calls\n   did not recurse as per specification.\n\n * HikariDataSource now implements the Closable interface.\n\n * Integrated change to allow specifying a ThreadGroup for thread\n   creation is certain restricted environments.\n\nChanges in 1.4.0\n\n *) Fix bug that did not allow minIdle property to be set.\n\nChanges in 1.3.9\n\n *) Added pool name to housekeeping thread name to make thread dumps\n    more meaningful in containers with multiple pools.\n\n *) Improved shutdown semantics; make a concerted effort to close\n    idle connections and abort or close active connections.\n\n *) Performance enhancements.\n\nChanges in 1.3.8\n\n *) Fixed incorrect logic when using JDBC4 isValid() test for alive\n    status of connection.\n\nChanges in 1.3.7\n\n *) Added JNDI object factory (com.zaxxer.hikari.HikariJNDIFactory)\n    for Tomcat and other containers that prefer JNDI-registered DataSource\n    factories.\n\n *) Fix NPE that can occur when connections cannot be created and\n    callers to getConnection() timeout.\n\n *) Various bug fixes and minor enhancements.\n\nChanges in 1.3.6\n\n *) Include connection failure cause in calls to getConnection() that\n    timeout (due to connection failure).  Removed chatty logging.\n\n *) Java8 Compatibility fixes.\n\n *) Include pool name in logging messages.  Thanks for the contribution\n    @jaredstehler.\n\nChanges in 1.3.5\n\n *) Fixed a regression in the Javassist code generation.\n\n *) Various bug fixes and minor enhancements.\n\nChanges in 1.3.4\n\n *) Added new property isolateInternalQueries used to control whether\n    internal pool queries such as connection alive tests are isolated\n    in their own transaction.\n\n *) Added properties for DriverManager (driverClassName) and JDBC URL-based\n    (jdbcUrl) configuration.  1999 called and wants its JDBC driver back.\n\n *) Added new username and password properties to allow default authentication\n    for connections.\n\n *) Added support for the getConnection(username, password) method signature\n    to HikariDataSource.\n\n *) Added new property readOnly to control the default read-only status\n    of connections in the pool.\n\n *) Deprecated acquireIncrement property.\n\n *) Deprecated acquireRetries property.\n\n *) Deprecated acquireRetryDelay property.\n\n *) Deprecated minimumPoolSize property.\n\n *) Added new property minimumIdle used to control the minimum number of\n    idle connections the pool should try to maintain on a running basis.\n\n *) Added evictConnection(Connection) method to HikariDataSource to allow\n    special cases where users wish to forcibly eject a connection from\n    the pool.  To use used cautiously, read the JavaDoc before using.\n\n *) Various bug fixes and minor enhancements.\n\nChanges in 1.3.3\n\n *) Removed shared state contention that was causing excessive CPU cache-line\n    flushing.  Nearly 4x improvement in Connection acquisition/release\n    performance.\n\n *) Fixed issue with Tomcat carping about ThreadLocal variables held after\n    web application restart.\n\n *) Fixed issue where the maximum configured connections could be overrun\n    during large burst requests for connections.\n\nChanges in 1.3.2\n\n *) Java 6 compatibility.\n\n *) HikariDataSource now extends HikariConfig, so pool properties can be\n    set directly on a HikariDataSource without need to create a  HikariConfig.\n    The cost of doing so is a small runtime cost due to the fact that an\n    \"is initialized\" check must be performed on every invocation of\n    getConnection() due to lazy initialization of the pool.\n\n *) Added Sybase-specific disconnect error codes to SQLException snooping.\n\n *) Added HikariConfig.setCatalog() method to set DataSource catalog.\n\n *) Add DataSource.close() method that is synonymous  with shutdown().\n\n *) More performance improvements (never ending).\n\n *) Moved benchmarks to https://github.com/brettwooldridge/HikariCP-benchmark\n\nChanges in 1.3.0\n\n *) Pool is now backed by a custom lock-less ConcurrentBag that\n    provides superior performance to LinkedBlockingQueue and\n    LinkedTransferQueue for usage patterns of connection pools.\n\n *) Fixed bugs reported against the 1.2.9 release.\n\n *) Added more detailed logging for broken connections and failures\n    during new connection creation.\n\nChanges in 1.2.9\n\n *) Added a fail-fast option for pool initialization.  If enabled, a\n    RuntimeException will be thrown if there are errors during pool\n    initialization.\n\n *) Made the registration of the HikariCP MBeans optional.  They now\n    default to not being registered.  Registering them causes a minor\n    performance hit due to additional pool data collection in\n    HikariDataSource.getConnection().\n\n *) Added the SQLException message to the log entry when an exception\n    occurs during physical connection acquisition.\n\n *) Implemented an orderly shutdown of the pool via the shutdown() method\n    on HikariDataSource.\n\n *) Listened to \"Adele - Live At The Royal Albert Hall\" on endless loop.\n\nChanges in 1.2.8\n\n *) Fixed a critical bug introduced in 1.2.7 occurring when the number of\n    concurrently open statements exceeds sixteen.\n\nChanges in 1.2.7\n\n *) Finally achieved performance parity between the generated delegates\n    and the former method of instrumenting driver classes directly.\n\n *) Improved generated delegate code. Removed unnecessary casts, moved\n    to a static proxy factory rather than a singleton (performance win).\n\n *) Improved performance of FastStatementList (primary source of speed-up\n    to reach parity with former instrumentation code).\n\n *) Removed aliveness check on connection creation.\n\n *) Track connection isolation level and only reset if the state has\n    become \"dirty\".  Avoids unnecessary round trip to the DB during the\n    aliveness check.\n\n *) Added interface IConnectionCustomizer and related HikariConfig\n    property 'connectionCustomizerClassName' to allow users to specify\n    a connection customization implementation.\n\nChanges in 1.2.6\n\n *) Fixed regression that caused IndexOutOfBounds when multiple unclosed\n    Statements existed at the time of Connection.close().\n\n *) Fixed incorrect pom.xml dependency on Hibernate.\n\nChanges in 1.2.5\n\n *) Instrumentation mode (agent) removed due to narrowing gap between\n    delegation mode and instrumentation (and to simplify the code base).\n\n *) Added setDataSource() to HikariConfig to allow a DataSource instance\n    to be explicitly wrapped by the pool.  Only available when creating\n    HikariConfig programmatically or constructing HikariConfig from a\n    java.util.Properties instance.\n\n *) Fixed Hibernate threading issue (certain usage patterns) introduced\n    in 1.2.2.\n\n *) Fixed issue observed with PostgreSQL whereby the query that tests the\n    connection for \"aliveness\" also starts a transaction (when auto-commit\n    is false), thereby causing a later failure when we tried to set the\n    transaction isolation level.\n\n *) Fixed issue where idleTimeout could not be set to 0, thereby disabling\n    it. Incorrect value validation caused 0 to be rejected as a valid value.\n\nChanges in 1.2.4\n\n *) Fix another Hibernate-related issue whereby an NPE is encountered when\n    a thread that was not the thread that obtained a Connection tries to\n    interact with that Connection.\n\nChanges in 1.2.3\n\n *) Fix internal (but suppressed) exception during rollback of connections\n    returned to the pool with auto-commit turned off.\n\n *) Fix a reflection issue that causes Hibernate failures due to the\n    CallableStatement interface being incorrectly injected into statement\n    proxies that are PreparedStatement or Statement instances.\n\nChanges in 1.2.2\n\n *) Perform a rollback() on connections returned to the pool with\n    auto commit disabled.\n\n *) Add a constructor for HikariConfig that accepts a Properties\n    object.\n\n *) Speed improvements for delegate mode.\n\n *) Fix a bug where connection timeouts could not be disabled.\n\n *) Permit setting the DataSource logWriter either on the HikariDataSource\n    or via addDataSourceProperty() on the HikariConfig.\n\n *) Add transactionIsolation property to allow setting the default\n    transaction isolation level for connections.\n\nChanges in 1.2.1\n\n *) Clear SQL warnings before returning a connection to the user.\n\n *) Added asynchronous connection backfill strategy that triggers\n    when the pool becomes empty as a result of dispatching a\n    connection.\n\n *) Changed default acquireIncrement to 1, set minimum timeout of\n    100ms for acquiring a connection.\n\nChanges in 1.1.9\n\n *) Added connectionInitSql property to allow setting connection\n    properties when a new connection is created.\n\n *) Added setDataSourceProperties() setter to HikariConfig to\n    allow easier configuration though Spring.\n"
  },
  {
    "path": "KEYS.txt",
    "content": "# GPG Release Key Fingerprints\nBrett Wooldridge <brett.wooldridge@gmail.com> F3A9 0E6B 10E8 09F8 51AB  4FC5 4CC0 8E7F 47C3 EC76\nLeo Bayer        <lfbayer@gmail.com>          9579 802D C3E1 5DE9 C389  239F C0D4 8A11 9CE7 EE7B\n"
  },
  {
    "path": "LICENSE",
    "content": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\" shall mean the terms and conditions for use, reproduction, and\ndistribution as defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright\nowner that is granting the License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all other entities\nthat control, are controlled by, or are under common control with that entity.\nFor the purposes of this definition, \"control\" means (i) the power, direct or\nindirect, to cause the direction or management of such entity, whether by\ncontract or otherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising\npermissions granted by this License.\n\n\"Source\" form shall mean the preferred form for making modifications, including\nbut not limited to software source code, documentation source, and configuration\nfiles.\n\n\"Object\" form shall mean any form resulting from mechanical transformation or\ntranslation of a Source form, including but not limited to compiled object code,\ngenerated documentation, and conversions to other media types.\n\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made\navailable under the License, as indicated by a copyright notice that is included\nin or attached to the work (an example is provided in the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that\nis based on (or derived from) the Work and for which the editorial revisions,\nannotations, elaborations, or other modifications represent, as a whole, an\noriginal work of authorship. For the purposes of this License, Derivative Works\nshall not include works that remain separable from, or merely link (or bind by\nname) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\" shall mean any work of authorship, including the original version\nof the Work and any modifications or additions to that Work or Derivative Works\nthereof, that is intentionally submitted to Licensor for inclusion in the Work\nby the copyright owner or by an individual or Legal Entity authorized to submit\non behalf of the copyright owner. For the purposes of this definition,\n\"submitted\" means any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems, and\nissue tracking systems that are managed by, or on behalf of, the Licensor for\nthe purpose of discussing and improving the Work, but excluding communication\nthat is conspicuously marked or otherwise designated in writing by the copyright\nowner as \"Not a Contribution.\"\n\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf\nof whom a Contribution has been received by Licensor and subsequently\nincorporated within the Work.\n\n2. Grant of Copyright License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable copyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the Work and such\nDerivative Works in Source or Object form.\n\n3. Grant of Patent License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable (except as stated in this section) patent license to make, have\nmade, use, offer to sell, sell, import, and otherwise transfer the Work, where\nsuch license applies only to those patent claims licensable by such Contributor\nthat are necessarily infringed by their Contribution(s) alone or by combination\nof their Contribution(s) with the Work to which such Contribution(s) was\nsubmitted. If You institute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work or a\nContribution incorporated within the Work constitutes direct or contributory\npatent infringement, then any patent licenses granted to You under this License\nfor that Work shall terminate as of the date such litigation is filed.\n\n4. Redistribution.\n\nYou may reproduce and distribute copies of the Work or Derivative Works thereof\nin any medium, with or without modifications, and in Source or Object form,\nprovided that You meet the following conditions:\n\nYou must give any other recipients of the Work or Derivative Works a copy of\nthis License; and\nYou must cause any modified files to carry prominent notices stating that You\nchanged the files; and\nYou must retain, in the Source form of any Derivative Works that You distribute,\nall copyright, patent, trademark, and attribution notices from the Source form\nof the Work, excluding those notices that do not pertain to any part of the\nDerivative Works; and\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any\nDerivative Works that You distribute must include a readable copy of the\nattribution notices contained within such NOTICE file, excluding those notices\nthat do not pertain to any part of the Derivative Works, in at least one of the\nfollowing places: within a NOTICE text file distributed as part of the\nDerivative Works; within the Source form or documentation, if provided along\nwith the Derivative Works; or, within a display generated by the Derivative\nWorks, if and wherever such third-party notices normally appear. The contents of\nthe NOTICE file are for informational purposes only and do not modify the\nLicense. You may add Your own attribution notices within Derivative Works that\nYou distribute, alongside or as an addendum to the NOTICE text from the Work,\nprovided that such additional attribution notices cannot be construed as\nmodifying the License.\nYou may add Your own copyright statement to Your modifications and may provide\nadditional or different license terms and conditions for use, reproduction, or\ndistribution of Your modifications, or for any such Derivative Works as a whole,\nprovided Your use, reproduction, and distribution of the Work otherwise complies\nwith the conditions stated in this License.\n\n5. Submission of Contributions.\n\nUnless You explicitly state otherwise, any Contribution intentionally submitted\nfor inclusion in the Work by You to the Licensor shall be under the terms and\nconditions of this License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify the terms of\nany separate license agreement you may have executed with Licensor regarding\nsuch Contributions.\n\n6. Trademarks.\n\nThis License does not grant permission to use the trade names, trademarks,\nservice marks, or product names of the Licensor, except as required for\nreasonable and customary use in describing the origin of the Work and\nreproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty.\n\nUnless required by applicable law or agreed to in writing, Licensor provides the\nWork (and each Contributor provides its Contributions) on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,\nincluding, without limitation, any warranties or conditions of TITLE,\nNON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are\nsolely responsible for determining the appropriateness of using or\nredistributing the Work and assume any risks associated with Your exercise of\npermissions under this License.\n\n8. Limitation of Liability.\n\nIn no event and under no legal theory, whether in tort (including negligence),\ncontract, or otherwise, unless required by applicable law (such as deliberate\nand grossly negligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special, incidental,\nor consequential damages of any character arising as a result of this License or\nout of the use or inability to use the Work (including but not limited to\ndamages for loss of goodwill, work stoppage, computer failure or malfunction, or\nany and all other commercial damages or losses), even if such Contributor has\nbeen advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability.\n\nWhile redistributing the Work or Derivative Works thereof, You may choose to\noffer, and charge a fee for, acceptance of support, warranty, indemnity, or\nother liability obligations and/or rights consistent with this License. However,\nin accepting such obligations, You may act only on Your own behalf and on Your\nsole responsibility, not on behalf of any other Contributor, and only if You\nagree to indemnify, defend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason of your\naccepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work\n\nTo apply the Apache License to your work, attach the following boilerplate\nnotice, with the fields enclosed by brackets \"[]\" replaced with your own\nidentifying information. (Don't include the brackets!) The text should be\nenclosed in the appropriate comment syntax for the file format. We also\nrecommend that a file or class name and description of purpose be included on\nthe same \"printed page\" as the copyright notice for easier identification within\nthird-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "<h1><img src=\"https://github.com/brettwooldridge/HikariCP/wiki/Hikari.png\"> HikariCP<sup><sup>&nbsp;It's Faster.</sup></sup><sub><sub><sup>Hi·ka·ri [hi·ka·'lē] &#40;<i>Origin: Japanese</i>): light; ray.</sup></sub></sub></h1><br>\n\n[![][Build Status img]][Build Status]\n[![][Coverage Status img]][Coverage Status]\n[![][license img]][license]\n![Maven Central Version](https://img.shields.io/maven-central/v/com.zaxxer/HikariCP?label=maven%20central&link=https%3A%2F%2Fcentral.sonatype.com%2Fartifact%2Fcom.zaxxer%2FHikariCP)\n[![][Javadocs img]][Javadocs]\n[![][Librapay img]][Librapay]\n\nFast, simple, reliable.  HikariCP is a \"zero-overhead\" production ready JDBC connection pool.  At roughly 165Kb, the library is very light.  Read about [how we do it here](https://github.com/brettwooldridge/HikariCP/wiki/Down-the-Rabbit-Hole).\n\n&nbsp;&nbsp;&nbsp;<sup>**\"Simplicity is prerequisite for reliability.\"**<br>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- *Dr. Edsger Dijkstra*</sup>\n\n----------------------------------------------------\n\n> [!IMPORTANT]\n> In order to avoid a rare condition where the pool goes to zero and does not recover it is necessary to configure *TCP keepalive*. Some JDBC drivers support this via properties, for example ``tcpKeepAlive=true`` on PostgreSQL, but in any case it can also be configured at the OS-level. See [Setting OS TCP Keepalive](https://github.com/brettwooldridge/HikariCP/wiki/Setting-Driver-or-OS-TCP-Keepalive) and/or [TCP keepalive for a better PostgreSQL experience](https://www.cybertec-postgresql.com/en/tcp-keepalive-for-a-better-postgresql-experience/#setting-tcp-keepalive-parameters-on-the-operating-system).\n\n----------------------------------------------------\n\n### Index\n* [Artifacts](#artifacts)\n* [JMH Benchmarks](#checkered_flag-jmh-benchmarks)\n* [Analyses](#microscope-analyses)\n  * [Spike Demand Pool Comparison](#spike-demand-pool-comparison)\n  * [You're probably doing it wrong](#youre-probably-doing-it-wrong)\n  * [WIX Engineering Analysis](#wix-engineering-analysis)\n  * [Failure: Pools behaving badly](#failure-pools-behaving-badly)\n* [User Testimonials](#family-user-testimonials) <br>\n* [Configuration](#gear-configuration-knobs-baby) <br>\n  * [Essentials](#essentials)\n  * [Frequently used](#frequently-used)\n  * [Infrequently used](#infrequently-used)\n* [Initialization](#rocket-initialization)\n\n----------------------------------------------------\n\n### Artifacts\n\n_**Java 11+** maven artifact:_\n```xml\n<dependency>\n   <groupId>com.zaxxer</groupId>\n   <artifactId>HikariCP</artifactId>\n   <version>7.0.2</version>\n</dependency>\n```\n_Java 8 maven artifact (*deprecated*):_\n```xml\n<dependency>\n   <groupId>com.zaxxer</groupId>\n   <artifactId>HikariCP</artifactId>\n   <version>4.0.3</version>\n</dependency>\n```\n_Java 7 maven artifact (*deprecated*):_\n```xml\n<dependency>\n   <groupId>com.zaxxer</groupId>\n   <artifactId>HikariCP-java7</artifactId>\n   <version>2.4.13</version>\n</dependency>\n```\n_Java 6 maven artifact (*deprecated*):_\n```xml\n<dependency>\n   <groupId>com.zaxxer</groupId>\n   <artifactId>HikariCP-java6</artifactId>\n   <version>2.3.13</version>\n</dependency>\n```\nOr [download from here](http://search.maven.org/#search%7Cga%7C1%7Ccom.zaxxer.hikaricp).\n\n----------------------------------------------------\n\n### :checkered_flag: JMH Benchmarks\n\nMicrobenchmarks were created to isolate and measure the overhead of pools using the [JMH microbenchmark framework](http://openjdk.java.net/projects/code-tools/jmh/). You can checkout the [HikariCP benchmark project for details](https://github.com/brettwooldridge/HikariCP-benchmark) and review/run the benchmarks yourself.\n\n![](https://github.com/brettwooldridge/HikariCP/wiki/HikariCP-bench-2.6.0.png)\n\n * One *Connection Cycle* is defined as single ``DataSource.getConnection()``/``Connection.close()``.\n * One *Statement Cycle* is defined as single ``Connection.prepareStatement()``, ``Statement.execute()``, ``Statement.close()``.\n\n<sup>\n<sup>1</sup> Versions: HikariCP 2.6.0, commons-dbcp2 2.1.1, Tomcat 8.0.24, Vibur 16.1, c3p0 0.9.5.2, Java 8u111 <br/>\n<sup>2</sup> Intel Core i7-3770 CPU @ 3.40GHz <br/>\n<sup>3</sup> Uncontended benchmark: 32 threads/32 connections, Contended benchmark: 32 threads, 16 connections <br/>\n<sup>4</sup> Apache Tomcat fails to complete the Statement benchmark when the Tomcat <i>StatementFinalizer</i> is used <a href=\"https://raw.githubusercontent.com/wiki/brettwooldridge/HikariCP/markdown/Tomcat-Statement-Failure.md\">due to excessive garbage collection times</a><br/>\n<sup>5</sup> Apache DBCP fails to complete the Statement benchmark <a href=\"https://raw.githubusercontent.com/wiki/brettwooldridge/HikariCP/markdown/Dbcp2-Statement-Failure.md\">due to excessive garbage collection times</a>\n</sup>\n\n----------------------------------------------------\n### :microscope: Analyses\n\n#### Spike Demand Pool Comparison\n<a href=\"https://github.com/brettwooldridge/HikariCP/blob/dev/documents/Welcome-To-The-Jungle.md\"><img width=\"400\" align=\"right\" src=\"https://github.com/brettwooldridge/HikariCP/wiki/Spike-Hikari.png\"></a>\nAnalysis of HikariCP v2.6, in comparison to other pools, in relation to a unique \"spike demand\" load.\n\nThe customer's environment imposed a high cost of new connection acquisition, and a requirement for a dynamically-sized pool, but yet a need for responsiveness to request spikes.  Read about the spike demand handling [here](https://github.com/brettwooldridge/HikariCP/blob/dev/documents/Welcome-To-The-Jungle.md).\n<br/>\n<br/>\n#### You're [probably] doing it wrong\n<a href=\"https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing\"><img width=\"200\" align=\"right\" src=\"https://github.com/brettwooldridge/HikariCP/wiki/Postgres_Chart.png\"></a>\nAKA *\"What you probably didn't know about connection pool sizing\"*.  Watch a video from the Oracle Real-world Performance group, and learn about why database connections do not need to be so numerous as they often are. In fact, too many connections have a clear and demonstrable *negative* impact on performance; a 50x difference in the case of the Oracle demonstration.  [Read on to find out](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing).\n<br/>\n#### WIX Engineering Analysis\n<a href=\"https://www.wix.engineering/blog/how-does-hikaricp-compare-to-other-connection-pools\"><img width=\"180\" align=\"left\" src=\"https://github.com/brettwooldridge/HikariCP/wiki/Wix-Engineering.png\"></a>\nWe'd like to thank the guys over at WIX for the unsolicited and deep write-up about HikariCP on their [engineering blog](https://www.wix.engineering/post/how-does-hikaricp-compare-to-other-connection-pools).  Take a look if you have time.\n<br/>\n<br/>\n<br/>\n#### Failure: Pools behaving badly\nRead our interesting [\"Database down\" pool challenge](https://github.com/brettwooldridge/HikariCP/wiki/Bad-Behavior:-Handling-Database-Down).\n\n----------------------------------------------------\n#### \"Imitation Is The Sincerest Form Of Plagiarism\" - <sub><sup>anonymous</sup></sub>\nOpen source software like HikariCP, like any product, competes in the free market.  We get it.  We understand that product advancements, once public, are often co-opted.  And we understand that ideas can arise from the zeitgeist; simultaneously and independently.  But the timeline of innovation, particularly in open source projects, is also clear and we want our users to understand the direction of flow of innovation in our space.  It could be demoralizing to see the result of hundreds of hours of thought and research co-opted so easily, and perhaps that is inherent in a free marketplace, but we are not demoralized.  *We are motivated; to widen the gap.*\n\n----------------------------------------------------\n### :family: User Testimonials\n\n[![](https://github.com/brettwooldridge/HikariCP/wiki/tweet3.png)](https://twitter.com/jkuipers)<br/>\n[![](https://github.com/brettwooldridge/HikariCP/wiki/tweet1.png)](https://twitter.com/steve_objectify)<br/>\n[![](https://github.com/brettwooldridge/HikariCP/wiki/tweet2.png)](https://twitter.com/brettemeyer)<br/>\n[![](https://github.com/brettwooldridge/HikariCP/wiki/tweet4.png)](https://twitter.com/dgomesbr/status/527521925401419776)\n\nIf you like this project, consider leaving a word for us on social media:\n\n[![](https://raw.github.com/wiki/brettwooldridge/HikariCP/twitter.png)](https://twitter.com/share?text=Interesting%20JDBC%20Connection%20Pool&hashtags=HikariCP&url=https%3A%2F%2Fgithub.com%2Fbrettwooldridge%2FHikariCP)&nbsp;[![](https://raw.github.com/wiki/brettwooldridge/HikariCP/facebook.png)](http://www.facebook.com/plugins/like.php?href=https%3A%2F%2Fgithub.com%2Fbrettwooldridge%2FHikariCP&width&layout=standard&action=recommend&show_faces=true&share=false&height=80)\n------------------------------\n### :gear: Configuration (knobs, baby!)\nHikariCP comes with *sane* defaults that perform well in most deployments without additional tweaking. **Every property is optional, except for the \"essentials\" marked below.**\n\n<sup>&#128206;</sup>&nbsp;*HikariCP uses milliseconds for all time values.*\n\n&#128680;&nbsp;HikariCP relies on accurate timers for both performance and reliability. It is *imperative* that your server is synchronized with a time-source such as an NTP server. *Especially* if your server is running within a virtual machine.  Why? [Read more here](https://dba.stackexchange.com/a/171020). **Do not rely on hypervisor settings to \"synchronize\" the clock of the virtual machine. Configure time-source synchronization inside the virtual machine.**   If you come asking for support on an issue that turns out to be caused by lack time synchronization, you will be taunted publicly on Twitter.\n\n#### Essentials\n\n&#128292;``dataSourceClassName``<br/>\nThis is the name of the ``DataSource`` class provided by the JDBC driver.  Consult the\ndocumentation for your specific JDBC driver to get this class name, or see the [table](https://github.com/brettwooldridge/HikariCP#popular-datasource-class-names) below.\nNote XA data sources are not supported.  XA requires a real transaction manager like\n[bitronix](https://github.com/bitronix/btm). Note that you do not need this property if you are using\n``jdbcUrl`` for \"old-school\" DriverManager-based JDBC driver configuration.\n*Default: none*\n\n*- or -*\n\n&#128292;``jdbcUrl``<br/>\nThis property directs HikariCP to use \"DriverManager-based\" configuration.  We feel that DataSource-based\nconfiguration (above) is superior for a variety of reasons (see below), but for many deployments there is\nlittle significant difference.  **When using this property with \"old\" drivers, you may also need to set\nthe  ``driverClassName`` property, but try it first without.**  Note that if this property is used, you may\nstill use *DataSource* properties to configure your driver and is in fact recommended over driver parameters\nspecified in the URL itself.\n*Default: none*\n\n***\n\n&#128292;``username``<br/>\nThis property sets the default authentication username used when obtaining *Connections* from\nthe underlying driver.  Note that for DataSources this works in a very deterministic fashion by\ncalling ``DataSource.getConnection(*username*, password)`` on the underlying DataSource.  However,\nfor Driver-based configurations, every driver is different.  In the case of Driver-based, HikariCP\nwill use this ``username`` property to set a ``user`` property in the ``Properties`` passed to the\ndriver's ``DriverManager.getConnection(jdbcUrl, props)`` call.  If this is not what you need,\nskip this method entirely and call ``addDataSourceProperty(\"username\", ...)``, for example.\n*Default: none*\n\n&#128292;``password``<br/>\nThis property sets the default authentication password used when obtaining *Connections* from\nthe underlying driver. Note that for DataSources this works in a very deterministic fashion by\ncalling ``DataSource.getConnection(username, *password*)`` on the underlying DataSource.  However,\nfor Driver-based configurations, every driver is different.  In the case of Driver-based, HikariCP\nwill use this ``password`` property to set a ``password`` property in the ``Properties`` passed to the\ndriver's ``DriverManager.getConnection(jdbcUrl, props)`` call.  If this is not what you need,\nskip this method entirely and call ``addDataSourceProperty(\"pass\", ...)``, for example.\n*Default: none*\n\n#### Frequently used\n\n&#9989;``autoCommit``<br/>\nThis property controls the default auto-commit behavior of connections returned from the pool.\nIt is a boolean value.\n*Default: true*\n\n&#9203;``connectionTimeout``<br/>\nThis property controls the maximum number of milliseconds that a client (that's you) will wait\nfor a connection from the pool.  If this time is exceeded without a connection becoming\navailable, a SQLException will be thrown.  Lowest acceptable connection timeout is 250 ms.\n*Default: 30000 (30 seconds)*\n\n&#9203;``idleTimeout``<br/>\nThis property controls the maximum amount of time that a connection is allowed to sit idle in the\npool.  **This setting only applies when ``minimumIdle`` is defined to be less than ``maximumPoolSize``.**\nIdle connections will *not* be retired once the pool reaches ``minimumIdle`` connections.  Whether a\nconnection is retired as idle or not is subject to a maximum variation of +30 seconds, and average\nvariation of +15 seconds.  A connection will never be retired as idle *before* this timeout.  A value\nof 0 means that idle connections are never removed from the pool.  The minimum allowed value is 10000ms\n(10 seconds).\n*Default: 600000 (10 minutes)*\n\n&#9203;``keepaliveTime``<br/>\nThis property controls how frequently HikariCP will attempt to keep a connection alive, in order to prevent\nit from being timed out by the database or network infrastructure. This value must be less than the\n`maxLifetime` value. A \"keepalive\" will only occur on an idle connection. When the time arrives for a \"keepalive\"\nagainst a given connection, that connection will be removed from the pool, \"pinged\", and then returned to the\npool. The 'ping' is one of either: invocation of the JDBC4 `isValid()` method, or execution of the\n`connectionTestQuery`. Typically, the duration out-of-the-pool should be measured in single digit milliseconds\nor even sub-millisecond, and therefore should have little or no noticeable performance impact. The minimum\nallowed value is 30000ms (30 seconds), but a value in the range of minutes is most desirable.\n*Default: 120000 (2 minutes)*\n\n&#9203;``maxLifetime``<br/>\nThis property controls the maximum lifetime of a connection in the pool.  An in-use connection will\nnever be retired, only when it is closed will it then be removed.  On a connection-by-connection\nbasis, minor negative attenuation is applied to avoid mass-extinction in the pool.  **We strongly recommend\nsetting this value, and it should be several seconds shorter than any database or infrastructure imposed\nconnection time limit.**  A value of 0 indicates no maximum lifetime (infinite lifetime), subject of\ncourse to the ``idleTimeout`` setting.  The minimum allowed value is 30000ms (30 seconds).\n*Default: 1800000 (30 minutes)*\n\n&#128292;``connectionTestQuery``<br/>\n**If your driver supports JDBC4 we strongly recommend not setting this property.** This is for\n\"legacy\" drivers that do not support the JDBC4 ``Connection.isValid() API``.  This is the query that\nwill be executed just before a connection is given to you from the pool to validate that the\nconnection to the database is still alive. *Again, try running the pool without this property,\nHikariCP will log an error if your driver is not JDBC4 compliant to let you know.*\n*Default: none*\n\n&#128290;``minimumIdle``<br/>\nThis property controls the minimum number of *idle connections* that HikariCP tries to maintain\nin the pool.  If the idle connections dip below this value and total connections in the pool are less than ``maximumPoolSize``,\nHikariCP will make a best effort to add additional connections quickly and efficiently.\nHowever, for maximum performance and responsiveness to spike demands,\nwe recommend *not* setting this value and instead allowing HikariCP to act as a *fixed size* connection pool.\n*Default: same as maximumPoolSize*\n\n&#128290;``maximumPoolSize``<br/>\nThis property controls the maximum size that the pool is allowed to reach, including both\nidle and in-use connections.  Basically this value will determine the maximum number of\nactual connections to the database backend.  A reasonable value for this is best determined\nby your execution environment.  When the pool reaches this size, and no idle connections are\navailable, calls to getConnection() will block for up to ``connectionTimeout`` milliseconds\nbefore timing out.  Please read [about pool sizing](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing).\n*Default: 10*\n\n&#128200;``metricRegistry``<br/>\nThis property is only available via programmatic configuration or IoC container.  This property\nallows you to specify an instance of a *Codahale/Dropwizard* ``MetricRegistry`` to be used by the\npool to record various metrics.  See the [Metrics](https://github.com/brettwooldridge/HikariCP/wiki/Dropwizard-Metrics)\nwiki page for details.\n*Default: none*\n\n&#128200;``healthCheckRegistry``<br/>\nThis property is only available via programmatic configuration or IoC container.  This property\nallows you to specify an instance of a *Codahale/Dropwizard* ``HealthCheckRegistry`` to be used by the\npool to report current health information.  See the [Health Checks](https://github.com/brettwooldridge/HikariCP/wiki/Dropwizard-HealthChecks)\nwiki page for details.\n*Default: none*\n\n&#128292;``poolName``<br/>\nThis property represents a user-defined name for the connection pool and appears mainly\nin logging and JMX management consoles to identify pools and pool configurations.\n*Default: auto-generated*\n\n#### Infrequently used\n\n&#9203;``initializationFailTimeout``<br/>\nThis property controls whether the pool will \"fail fast\" if the pool cannot be seeded with\nan initial connection successfully.  Any positive number is taken to be the number of\nmilliseconds to attempt to acquire an initial connection; the application thread will be\nblocked during this period.  If a connection cannot be acquired before this timeout occurs,\nan exception will be thrown.  This timeout is applied *after* the ``connectionTimeout``\nperiod.  If the value is zero (0), HikariCP will attempt to obtain and validate a connection.\nIf a connection is obtained, but fails validation, an exception will be thrown and the pool\nnot started.  However, if a connection cannot be obtained, the pool will start, but later\nefforts to obtain a connection may fail.  A value less than zero will bypass any initial\nconnection attempt, and the pool will start immediately while trying to obtain connections\nin the background.  Consequently, later efforts to obtain a connection may fail.\n*Default: 1*\n\n&#10062;``isolateInternalQueries``<br/>\nThis property determines whether HikariCP isolates internal pool queries, such as the\nconnection alive test, in their own transaction.  Since these are typically read-only\nqueries, it is rarely necessary to encapsulate them in their own transaction.  This\nproperty only applies if ``autoCommit`` is disabled.\n*Default: false*\n\n&#10062;``allowPoolSuspension``<br/>\nThis property controls whether the pool can be suspended and resumed through JMX.  This is\nuseful for certain failover automation scenarios.  When the pool is suspended, calls to\n``getConnection()`` will *not* timeout and will be held until the pool is resumed.\n*Default: false*\n\n&#10062;``readOnly``<br/>\nThis property controls whether *Connections* obtained from the pool are in read-only mode by\ndefault.  Note some databases do not support the concept of read-only mode, while others provide\nquery optimizations when the *Connection* is set to read-only.  Whether you need this property\nor not will depend largely on your application and database.\n*Default: false*\n\n&#10062;``registerMbeans``<br/>\nThis property controls whether or not JMX Management Beans (\"MBeans\") are registered or not.\n*Default: false*\n\n&#128292;``catalog``<br/>\nThis property sets the default *catalog* for databases that support the concept of catalogs.\nIf this property is not specified, the default catalog defined by the JDBC driver is used.\n*Default: driver default*\n\n&#128292;``connectionInitSql``<br/>\nThis property sets a SQL statement that will be executed after every new connection creation\nbefore adding it to the pool. If this SQL is not valid or throws an exception, it will be\ntreated as a connection failure and the standard retry logic will be followed.\n*Default: none*\n\n&#128292;``driverClassName``<br/>\nHikariCP will attempt to resolve a driver through the DriverManager based solely on the ``jdbcUrl``,\nbut for some older drivers the ``driverClassName`` must also be specified.  Omit this property unless\nyou get an obvious error message indicating that the driver was not found.\n*Default: none*\n\n&#128292;``transactionIsolation``<br/>\nThis property controls the default transaction isolation level of connections returned from\nthe pool.  If this property is not specified, the default transaction isolation level defined\nby the JDBC driver is used.  Only use this property if you have specific isolation requirements that are\ncommon for all queries.  The value of this property is the constant name from the ``Connection``\nclass such as ``TRANSACTION_READ_COMMITTED``, ``TRANSACTION_REPEATABLE_READ``, etc.\n*Default: driver default*\n\n&#9203;``validationTimeout``<br/>\nThis property controls the maximum amount of time that a connection will be tested for aliveness.\nThis value must be less than the ``connectionTimeout``.  Lowest acceptable validation timeout is 250 ms.\n*Default: 5000*\n\n&#9203;``leakDetectionThreshold``<br/>\nThis property controls the amount of time that a connection can be out of the pool before a\nmessage is logged indicating a possible connection leak.  A value of 0 means leak detection\nis disabled.  Lowest acceptable value for enabling leak detection is 2000 (2 seconds).\n*Default: 0*\n\n&#10145;``dataSource``<br/>\nThis property is only available via programmatic configuration or IoC container. This property\nallows you to directly set the instance of the ``DataSource`` to be wrapped by the pool, rather than\nhaving HikariCP construct it via reflection.  This can be useful in some dependency injection\nframeworks. When this property is specified, the ``dataSourceClassName`` property and all\nDataSource-specific properties will be ignored.\n*Default: none*\n\n&#128292;``schema``<br/>\nThis property sets the default *schema* for databases that support the concept of schemas.\nIf this property is not specified, the default schema defined by the JDBC driver is used.\n*Default: driver default*\n\n&#10145;``threadFactory``<br/>\nThis property is only available via programmatic configuration or IoC container. This property\nallows you to set the instance of the ``java.util.concurrent.ThreadFactory`` that will be used\nfor creating all threads used by the pool. It is needed in some restricted execution environments\nwhere threads can only be created through a ``ThreadFactory`` provided by the application container.\n*Default: none*\n\n&#10145;``scheduledExecutor``<br/>\nThis property is only available via programmatic configuration or IoC container. This property\nallows you to set the instance of the ``java.util.concurrent.ScheduledExecutorService`` that will\nbe used for various internally scheduled tasks.  If supplying HikariCP with a ``ScheduledThreadPoolExecutor``\ninstance, it is recommended that ``setRemoveOnCancelPolicy(true)`` is used.\n*Default: none*\n\n&#10145;``exceptionOverride``<br/>\nThis property is only available via programmatic configuration or IoC container. This property\nallows you to set an instance of a class, implementing the ``com.zaxxer.hikari.SQLExceptionOverride``\ninterface, that will be called before a connection is evicted from the pool due to specific exception\nconditions. Typically, when a ``SQLException`` is thrown, connections are evicted from the pool when\nspecific *SQLStates* or *ErrorCodes* are present. The ``adjudicate()`` method will be called on the\n``SQLExceptionOverride`` instance, which may return one of: ``Override.CONTINUE_EVICT``.\n``Override.DO_NOT_EVICT`` or ``Override.MUST_EVICT``. Except in very specific cases\n``Override.CONTINUE_EVICT`` should be returned, allowing the default evict/no-evict logic to execute.\n*Default: none*\n\n&#128292;``exceptionOverrideClassName``<br/>\nThis property allows you to specify the name of a user-supplied class implementing the\n``com.zaxxer.hikari.SQLExceptionOverride`` interface. An instance of the class will be instantiated\nby the pool to adjudicate connection evictions. See the above property ``exceptionOverride`` for a\nfull description.\n*Default: none*\n\n----------------------------------------------------\n\n#### Missing Knobs\n\nHikariCP has plenty of \"knobs\" to turn as you can see above, but comparatively less than some other pools.\nThis is a design philosophy.  The HikariCP design aesthetic is Minimalism.  In keeping with the\n*simple is better* or *less is more* design philosophy, some configuration axis are intentionally left out.\n\n#### Statement Cache\n\nMany connection pools, including Apache DBCP, Vibur, c3p0 and others offer ``PreparedStatement`` caching.\nHikariCP does not.  Why?\n\nAt the connection pool layer ``PreparedStatements`` can only be cached *per connection*.  If your application\nhas 250 commonly executed queries and a pool of 20 connections you are asking your database to hold on to\n5000 query execution plans -- and similarly the pool must cache this many ``PreparedStatements`` and their\nrelated graph of objects.\n\nMost major database JDBC drivers already have a Statement cache that can be configured, including PostgreSQL,\nOracle, Derby, MySQL, DB2, and many others.  JDBC drivers are in a unique position to exploit database specific\nfeatures, and nearly all of the caching implementations are capable of sharing execution plans *across connections*.\nThis means that instead of 5000 statements in memory and associated execution plans, your 250 commonly executed\nqueries result in exactly 250 execution plans in the database.  Clever implementations do not even retain\n``PreparedStatement`` objects in memory at the driver-level but instead merely attach new instances to existing plan IDs.\n\nUsing a statement cache at the pooling layer is an [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern),\nand will negatively impact your application performance compared to driver-provided caches.\n\n#### Log Statement Text / Slow Query Logging\n\nLike Statement caching, most major database vendors support statement logging through\nproperties of their own driver.  This includes Oracle, MySQL, Derby, MSSQL, and others.  Some\neven support slow query logging.  For those few databases that do not support it, several options are available.\nWe have received [a report that p6spy works well](https://github.com/brettwooldridge/HikariCP/issues/57#issuecomment-354647631),\nand also note the availability of [log4jdbc](https://github.com/arthurblake/log4jdbc) and [jdbcdslog-exp](https://code.google.com/p/jdbcdslog-exp/).\n\n#### Rapid Recovery\nPlease read the [Rapid Recovery Guide](https://github.com/brettwooldridge/HikariCP/wiki/Rapid-Recovery) for details on how to configure your driver and system for proper recovery from database restart and network partition events.\n\n----------------------------------------------------\n\n### :see_no_evil: Secret Properties\n\nHikariCP has several Java system properties that control various aspects of the pool. These properties are *unsupported*\nfor user manipulation. It is possible though unlikely that they may not exist in the future. This means: do not open an issue of any kind if you have modified these properties. *Pretend you never heard anything about \"secret properties\".*\n\n| Property                                      | Description                                                                                                                                                                                                                                       |\n|:----------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| ``com.zaxxer.hikari.blockUntilFilled``        | When this property is set ``true`` *and* ``initializationFailTimeout`` is greater than 1, the pool will block during start until completely filled.                                                                                               |\n| ``com.zaxxer.hikari.enableRequestBoundaries`` | When this property is set ``true``, HikariCP will bracket connection acquisition and return with calls to ``Connection.beginRequest()`` and ``Connection.endRequest()``.                                                                          |\n| ``com.zaxxer.hikari.housekeeping.period``     | This property controls the frequency of the housekeeping thread, represented in milliseconds. Really, don't mess with this.                                                                                                                       |\n| ``com.zaxxer.hikari.legacy.supportUserPassDataSourceOverride`` | When this property is set ``true``, HikariCP will support the legacy behavior of overriding the ``getUsername()/getPassword()`` methods on *HikariDataSource*. Preferred method is overriding ``getCredentials()``.             |\n| ``com.zaxxer.hikari.useWeakReferences``       | When this property is set ``true`` it will force HikariCP to use ``WeakReference`` objects in the ``ConcurrentBag`` internal collection ThreadLocals and prevent the use of our ``FastList`` class, all to avoid TomCat warnings during redeploy. |\n\nEither don't use these properties or take on full responsibility for the consequences.\n\n### :rocket: Initialization\n\nYou can use the ``HikariConfig`` class like so<sup>1</sup>:\n```java\nHikariConfig config = new HikariConfig();\nconfig.setJdbcUrl(\"jdbc:mysql://localhost:3306/simpsons\");\nconfig.setUsername(\"bart\");\nconfig.setPassword(\"51mp50n\");\nconfig.addDataSourceProperty(\"cachePrepStmts\", \"true\");\nconfig.addDataSourceProperty(\"prepStmtCacheSize\", \"250\");\nconfig.addDataSourceProperty(\"prepStmtCacheSqlLimit\", \"2048\");\n\nHikariDataSource ds = new HikariDataSource(config);\n```\n&nbsp;<sup><sup>1</sup> MySQL-specific example, DO NOT COPY VERBATIM.</sup>\n\nor directly instantiate a ``HikariDataSource`` like so:\n```java\nHikariDataSource ds = new HikariDataSource();\nds.setJdbcUrl(\"jdbc:mysql://localhost:3306/simpsons\");\nds.setUsername(\"bart\");\nds.setPassword(\"51mp50n\");\n...\n```\nor property file based:\n```java\n// Examines both filesystem and classpath for .properties file\nHikariConfig config = new HikariConfig(\"/some/path/hikari.properties\");\nHikariDataSource ds = new HikariDataSource(config);\n```\nExample property file:\n```ini\ndataSourceClassName=org.postgresql.ds.PGSimpleDataSource\ndataSource.user=test\ndataSource.password=test\ndataSource.databaseName=mydb\ndataSource.portNumber=5432\ndataSource.serverName=localhost\n```\nor ``java.util.Properties`` based:\n```java\nProperties props = new Properties();\nprops.setProperty(\"dataSourceClassName\", \"org.postgresql.ds.PGSimpleDataSource\");\nprops.setProperty(\"dataSource.user\", \"test\");\nprops.setProperty(\"dataSource.password\", \"test\");\nprops.setProperty(\"dataSource.databaseName\", \"mydb\");\nprops.put(\"dataSource.logWriter\", new PrintWriter(System.out));\n\nHikariConfig config = new HikariConfig(props);\nHikariDataSource ds = new HikariDataSource(config);\n```\n\nThere is also a System property available, ``hikaricp.configurationFile``, that can be used to specify the\nlocation of a properties file.  If you intend to use this option, construct a ``HikariConfig`` or ``HikariDataSource``\ninstance using the default constructor and the properties file will be loaded.\n\n### Performance Tips\n[MySQL Performance Tips](https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration)\n\n### Popular DataSource Class Names\n\nWe recommended using ``dataSourceClassName`` instead of ``jdbcUrl``, but either is acceptable.  We'll say that again, *either is acceptable*.\n\n&#9888;&nbsp;*Note: Spring Boot auto-configuration users, you need to use ``jdbcUrl``-based configuration.*\n\n&#9888;&nbsp;The MySQL DataSource is known to be broken with respect to network timeout support. Use ``jdbcUrl`` configuration instead.\n\nHere is a list of JDBC *DataSource* classes for popular databases:\n\n| Database         | Driver       | *DataSource* class |\n|:---------------- |:------------ |:-------------------|\n| Apache Derby     | Derby        | org.apache.derby.jdbc.ClientDataSource |\n| Firebird         | Jaybird      | org.firebirdsql.ds.FBSimpleDataSource |\n| Google Spanner   | Spanner      | com.google.cloud.spanner.jdbc.JdbcDriver |\n| H2               | H2           | org.h2.jdbcx.JdbcDataSource |\n| HSQLDB           | HSQLDB       | org.hsqldb.jdbc.JDBCDataSource |\n| IBM DB2          | IBM JCC      | com.ibm.db2.jcc.DB2SimpleDataSource |\n| IBM Informix     | IBM Informix | com.informix.jdbcx.IfxDataSource |\n| MS SQL Server    | Microsoft    | com.microsoft.sqlserver.jdbc.SQLServerDataSource |\n| ~~MySQL~~        | Connector/J  | ~~com.mysql.jdbc.jdbc2.optional.MysqlDataSource~~ |\n| MariaDB          | MariaDB      | org.mariadb.jdbc.MariaDbDataSource |\n| Oracle           | Oracle       | oracle.jdbc.pool.OracleDataSource |\n| OrientDB         | OrientDB     | com.orientechnologies.orient.jdbc.OrientDataSource |\n| PostgreSQL       | pgjdbc-ng    | com.impossibl.postgres.jdbc.PGDataSource |\n| PostgreSQL       | PostgreSQL   | org.postgresql.ds.PGSimpleDataSource |\n| SAP MaxDB        | SAP          | com.sap.dbtech.jdbc.DriverSapDB |\n| SQLite           | xerial       | org.sqlite.SQLiteDataSource |\n| SyBase           | jConnect     | com.sybase.jdbc4.jdbc.SybDataSource |\n\n### Play Framework Plugin\n\nNote Play 2.4 now uses HikariCP by default.  A new plugin has come up for the the Play framework; [play-hikaricp](http://edulify.github.io/play-hikaricp.edulify.com/).  If you're using the excellent Play framework,  your application deserves HikariCP.  Thanks Edulify Team!\n\n### Clojure Wrapper\n\nA new Clojure wrapper has been created by [tomekw](https://github.com/tomekw) and can be [found here](https://github.com/tomekw/hikari-cp).\n\n### JRuby Wrapper\n\nA new JRuby wrapper has been created by [tomekw](https://github.com/tomekw) and can be [found here](https://github.com/tomekw/hucpa).\n\n----------------------------------------------------\n\n### Wiki\n\nDon't forget the [Wiki](https://github.com/brettwooldridge/HikariCP/wiki) for additional information such as:\n * [FAQ](https://github.com/brettwooldridge/HikariCP/wiki/FAQ)\n * [Hibernate 4.x Configuration](https://github.com/brettwooldridge/HikariCP/wiki/Hibernate4)\n * [MySQL Configuration Tips](https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration)\n * etc.\n\n----------------------------------------------------\n\n### Requirements\n\n &#8658; Java 11+ (Java 6/7/8 artifacts are in maintenance mode)<br/>\n &#8658; slf4j library<br/>\n\n### Sponsors\nHigh-performance projects can never have too many tools!  We would like to thank the following companies:\n\nThanks to [ej-technologies](https://www.ej-technologies.com) for their excellent all-in-one profiler, [JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html).\n\nYourKit supports open source projects with its full-featured Java Profiler.  Click the YourKit logo below to learn more.<br/>\n[![](https://github.com/brettwooldridge/HikariCP/wiki/yklogo.png)](http://www.yourkit.com/java/profiler/index.jsp)<br/>\n\n\n### Contributions\n\nPlease perform changes and submit pull requests from the ``dev`` branch instead of ``master``.  Please set your editor to use spaces instead of tabs, and adhere to the apparent style of the code you are editing.  The ``dev`` branch is always more \"current\" than the ``master`` if you are looking to live life on the edge.\n\n[Build Status]:https://circleci.com/gh/brettwooldridge/HikariCP\n[Build Status img]:https://circleci.com/gh/brettwooldridge/HikariCP/tree/dev.svg?style=shield\n\n[Coverage Status]:https://codecov.io/gh/brettwooldridge/HikariCP\n[Coverage Status img]:https://codecov.io/gh/brettwooldridge/HikariCP/branch/dev/graph/badge.svg\n\n[license]:LICENSE\n[license img]:https://img.shields.io/badge/license-Apache%202-blue.svg\n\n[Javadocs]:http://javadoc.io/doc/com.zaxxer/HikariCP\n[Javadocs img]:http://javadoc.io/badge/com.zaxxer/HikariCP.svg\n\n[Librapay]:https://liberapay.com/brettwooldridge\n[Librapay img]:https://img.shields.io/liberapay/patrons/brettwooldridge.svg?logo=liberapay\n"
  },
  {
    "path": "codecov.yml",
    "content": "codecov:\n  notify:\n    require_ci_to_pass: yes\n\ncoverage:\n  precision: 2\n  round: down\n  range: \"50..80\"\n\n  status:\n    project: yes\n    patch: yes\n    changes: no\n\nparsers:\n  gcov:\n    branch_detection:\n      conditional: yes\n      loop: yes\n      method: no\n      macro: no\n\ncomment:\n  layout: \"reach, diff, flags, files, footer\"\n  behavior: default\n  require_changes: no\n\n"
  },
  {
    "path": "documents/Wall-of-Fame.md",
    "content": "<img width=\"260\" valign=\"middle\" src=\"http://d26gg7w375vuv5.cloudfront.net/Design+Assets/black+Wix+Logo+Assets/Black+Wix+logo+Assets.png\">![][spacer]<img width=\"250\" height=\"88\" valign=\"middle\" src=\"https://www.skytap.com/wp-content/uploads/2016/05/Puppets_company_logo.png\">![][spacer]<img width=\"250\" height=\"88\" valign=\"middle\" src=\"https://web.liferay.com/osb-community-theme/images/custom/heading.png\">\n\n<img width=\"240\" valign=\"middle\" src=\"https://www.playframework.com/assets/images/logos/play_full_color.png\">![][spacer]<img width=\"240\" valign=\"middle\" src=\"https://www.atlassian.com/dam/jcr:416a5a7b-55dc-435d-a3e3-22aa2650ba5d/AtlassianLogo.svg\">![][spacer]<img width=\"240\" valign=\"middle\" src=\"https://www.saydaily.com/.image/c_limit%2Ccs_srgb%2Cq_auto:good%2Cw_410/MTM0ODg3OTkwOTMyNTc1NTA2/screen-shot-2015-12-03-at-22820-pmpng.png\">\n\n<img width=\"240\" valign=\"middle\" src=\"https://upload.wikimedia.org/wikipedia/commons/e/e8/Splunk-Logo.jpg\">![][spacer]<img width=\"240\" valign=\"middle\" src=\"https://www.surpasshosting.com/images/comodo_logo.png\">![][spacer]<img width=\"240\" valign=\"middle\" src=\"https://www.ca.com/content/dam/ca/us/images/company/ca-logo-b-w.jpg\">\n\n<img width=\"260\" valign=\"middle\" src=\"http://fiware-cosmos.readthedocs.io/en/r4_fiware/user_and_programmer_manual/streaming/images/storm_logo.png\">![][spacer]<img width=\"240\" valign=\"middle\" src=\"https://image.slidesharecdn.com/apachehive-151229131013/95/apache-hive-1-638.jpg?cb=1451394627\">![][spacer]<img width=\"240\" valign=\"middle\" src=\"http://design.jboss.org/hibernate/logo/final/hibernate_logo_whitebkg.svg\">\n\n<img width=\"240\" valign=\"middle\" src=\"https://spring.io/img/spring-by-pivotal.png\">![][spacer]<img width=\"240\" valign=\"middle\" src=\"https://jaxenter.com/wp-content/uploads/2013/02/slick.jpg\">![][spacer]<img width=\"240\" valign=\"middle\" src=\"https://www.opennms.com/wp-content/uploads/2015/02/openNMSlogo-transparent-noninterlaced-150ppi.png\">\n\n<img width=\"240\" valign=\"middle\" src=\"https://aries.apache.org/images/Arieslogo_Horizontal.gif\">\n\n\n<img height=\"60\" src=\"https://github.com/brettwooldridge/HikariCP/wiki/space60x1.gif\"/>\n\n-------------------------------------------------------------------------------------\n * Images on this page are Trademarked and Copyrighted by their respective rights holders.\n * Images on this page are used without express permission, and do not constitute an endorsement of HikariCP. If you are a trademark or copyright holder and wish an image to be removed from this page, please open a request in the issue tracker.\n\n[spacer]: https://github.com/brettwooldridge/HikariCP/wiki/space60x1.gif\n"
  },
  {
    "path": "documents/Welcome-To-The-Jungle.md",
    "content": "<img width=\"340\" height=\"240\" align=\"left\" src=\"https://github.com/brettwooldridge/HikariCP/wiki/welcome-to-the-jungle.jpg\">\r\nMicrobenchmarks are great at measuring performance \"in the small\"; for example, measuring the performance of individual methods. But good results do not necessarily translate into macro-scale performance.  Real world access patterns and demand loads often run into deeper, systemic, architectural design issues that cannot be discerned at the micro level.<br><br>\r\n\r\nHikariCP has over 1 million users, so from time to time we are approached with challenges encountered \"in the wild\".  Recently, one such challenge led to a deeper investigation: ***Spike Demand***.\r\n\r\n### The Challenge\r\nThe user has an environment where connection creation is expensive, on the order of 150ms; and yet queries typically execute in ~2ms.  Long connection setup times can be the result of various factors, alone or in combination: DNS resolution times, encrypted connections with strong encryption (2048/4096 bit), external authentication, database server load, etc.\r\n\r\n*Generally speaking, for the best performance in response to spike demands, HikariCP recommends a fixed-size pool.*\r\n\r\nUnfortunately, the user's application is also in an environment where many other applications are connected to the same database, and therefore dynamically-sized pools are desirable -- where idle applications are allowed to give up some of their connections.  The user is running the application with HikariCP configured as ``minimumIdle=5``.\r\n\r\nIn this environment, the application has periods of quiet, as well as sudden spikes of requests, and periods of sustained activity.  The combination of high connection setup times, a dynamically-sized pool requirement, and spike demands is just about the worst case scenario for a connection pool.\r\n\r\nThe questions ultimately were these:\r\n\r\n> * If the pool is sitting idle with 5 connections, and is suddenly hit with 50 requests, what should happen?\r\n> * Given that a each new connection is going to take 150ms to establish, and given that each request can ultimately be satisfied in ~2ms, shouldn't even a single one of the idle connections be able to handle all the of the requests in ~100ms anyway?\r\n> * So, why is the pool size growing [so much]?\r\n\r\nWe thought these were interesting questions, and HikariCP was indeed creating more connections than we expected...\r\n\r\n### 3, 2, 1 ... Go!\r\nIn order to explore these questions, we built a simulation and started measuring.  The simulation harness [code is here](https://github.com/brettwooldridge/HikariCP-benchmark/blob/master/src/test/java/com/zaxxer/hikari/benchmark/SpikeLoadTest.java).\r\n\r\nThe constraints are simple:\r\n * Connection establishment takes 150ms.\r\n * Query execution takes 2ms.\r\n * The maximum pool size is 50.\r\n * The minimum idle connections is 5.\r\n\r\nAnd the simulation is fairly simple:\r\n * Everything is quiet, and then ... Boom! ... 50 threads, at once, wanting a connection and to execute a query.\r\n * Take measurements every 250μs (microseconds).\r\n\r\n### Results\r\nAfter running HikariCP through the simulation, tweaking the code (ultimately a one-line change), and satisfying ourselves that the behavior is as we would wish, we ran a few other pools through the simulation.\r\n\r\nThe code was run as follows:\r\n```\r\nbash$ ./spiketest.sh 150 <pool> 50\r\n```\r\nWhere ``150`` is the connection establishment time, ``<pool>`` is one of [*hikari*, *dbcp2*, *vibur*, *tomcat*, *c3p0*], and ``50`` is the number of threads/requests.  Note that *c3p0* was dropped from the analysis here, as its run time was ~120x that of HikariCP.\r\n\r\n#### HikariCP (v2.6.0) <sub><sup><a href=\"https://github.com/brettwooldridge/HikariCP/wiki/Spike-Hikari-data.txt\">raw data</a></sup></sub>\r\n\r\n--------------------\r\n[![](https://github.com/brettwooldridge/HikariCP/wiki/Spike-Hikari.png)](https://github.com/brettwooldridge/HikariCP/wiki/Spike-Hikari.png)\r\n\r\n#### Apache DBCP (v2.1.1) <sub><sup><a href=\"https://github.com/brettwooldridge/HikariCP/wiki/Spike-DBCP2-data.txt\">raw data</a></sup></sub>\r\n\r\n--------------------\r\n[![](https://github.com/brettwooldridge/HikariCP/wiki/Spike-DBCP2.png)](https://github.com/brettwooldridge/HikariCP/wiki/Spike-DBCP2.png)\r\n\r\n#### Apache Tomcat (v8.0.24) <sub><sup><a href=\"https://github.com/brettwooldridge/HikariCP/wiki/Spike-Tomcat-data.txt\">raw data</a></sup></sub>\r\n\r\n--------------------\r\n[![](https://github.com/brettwooldridge/HikariCP/wiki/Spike-Tomcat.png)](https://github.com/brettwooldridge/HikariCP/wiki/Spike-Tomcat.png)\r\n\r\n#### Vibur DBCP (v16.1) <sub><sup><a href=\"https://github.com/brettwooldridge/HikariCP/wiki/Spike-Vibur-data.txt\">raw data</a></sup></sub>\r\n\r\n--------------------\r\n[![](https://github.com/brettwooldridge/HikariCP/wiki/Spike-Vibur.png)](https://github.com/brettwooldridge/HikariCP/wiki/Spike-Vibur.png)\r\n\r\n<sup>* Note that the times provided in the raw data is the number of microseconds (μs) since the start of the test. For graphing purposes, raw data for each pool was trimmed such that the first entry has 0 requests enqueued, and the last entry has all connections completed. </sup>\r\n\r\n--------------------\r\n### Apache DBCP vs HikariCP\r\n:point_right: In case you missed the *time-scale* in the graphs above, here is a properly scaled comparable.\r\n\r\nApache DBCP on *top*, HikariCP on the *bottom*.\r\n\r\n[![](https://github.com/brettwooldridge/HikariCP/wiki/Spike-Compare.png)](https://github.com/brettwooldridge/HikariCP/wiki/Spike-Compare.png)\r\n\r\n### Commentary\r\nWe'll start by saying that we are not going to comment on the implementation specifics of the other pools, but you may be able to draw inferences by our comments regarding HikariCP.\r\n\r\nLooking at the HikariCP graph, we couldn't have wished for a better profile; it's about as close to perfect efficiency as we could expect.  It is interesting, though not surprising, that the other pool profiles are so similar to each other. Even though arrived at via different implementations, they are the result of a *conventional* or *obvious* approach to pool design.\r\n\r\nHikariCP's profile in this case, and the reason for the difference observed between other pools, is the result of our Prime Directive:\r\n\r\n💡 **User threads should only ever block on the** ***pool itself***.<sup>1</sup><br>\r\n<img width=\"32px\" src=\"https://github.com/brettwooldridge/HikariCP/wiki/space60x1.gif\"><sub><sup>1</sup>&nbsp;to the greatest extent possible.</sub>\r\n\r\nConsider this hypothetical scenario:\r\n```\r\nThere is a pool with five connections in-use, and zero idle (available) connections. Then, a new thread\r\ncomes in requesting a connection.\r\n```\r\n\"How does the prime directive apply in this case?\"  We'll answer with a question of our own:\r\n\r\n> If the thread is directed to create a new connection, and that connection takes 150ms to establish, what happens if one of the five in-use connections is returned to the pool?\r\n\r\n---------------------\r\nBoth Apache DBCP2 and Vibur ended the run with 45 connections, Apache Tomcat (inexplicably) with 40 connections, while HikariCP ended the run with 5 (technically six, see below).  This has major and measurable effects for real world deployments.  That is 35-40 additional connections that are not available to other applications, and 35-40 additional threads and associated memory structures in the database.\r\n\r\nWe know what you are thinking, *\"What if the load had been sustained?\"*&nbsp;&nbsp;The answer is: HikariCP also would have ramped up.\r\n\r\nIn point of fact, as soon as the pool hit zero available connections, right around 800μs into the run, HikariCP began requesting connections to be added to the pool asynchronously.  If the metrics had continued to be collected past the end of the spike -- out beyond 150ms -- you would observe that an additional connection is indeed added to the pool.  But *only one*, because HikariCP employs *elision logic*; at that point HikariCP would also realize that there is actually no more pending demand, and the remaining connection acquisitions would be elided.\r\n\r\n### Epilog\r\nThis scenario represents only *one* of many access patterns. HikariCP will continue to research *and innovate* when presented with challenging problems encountered in real world deployments.  As always, thank you for your patronage.\r\n"
  },
  {
    "path": "install-jdk.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Install JDK for Linux and Mac OS\n#\n# This script determines the most recent early-access build number,\n# downloads the JDK archive to the user home directory and extracts\n# it there.\n#\n# Exported environment variables (when sourcing this script)\n#\n#   JAVA_HOME is set to the extracted JDK directory\n#   PATH is prepended with ${JAVA_HOME}/bin\n#\n# (C) 2020 Christian Stein\n#\n# https://github.com/sormuras/bach/blob/master/install-jdk.sh\n#\n\nset -o errexit\n#set -o nounset # https://github.com/travis-ci/travis-ci/issues/5434\n#set -o xtrace\n\nfunction initialize() {\n    readonly script_name=\"$(basename \"${BASH_SOURCE[0]}\")\"\n    readonly script_version='2020-03-17'\n\n    dry=false\n    silent=false\n    verbose=false\n    emit_java_home=false\n\n    feature='ea'\n    license='GPL' # Force GPLv2+CE\n    os='?'\n    url='?'\n    workspace=\"${HOME}\"\n    target='?'\n    cacerts=false\n}\n\nfunction usage() {\ncat << EOF\nUsage: ${script_name} [OPTION]...\nDownload and extract latest-and-greatest JDK from https://jdk.java.net\n\nVersion: ${script_version}\nOptions:\n  -h|--help                 Displays this help\n  -d|--dry-run              Activates dry-run mode\n  -s|--silent               Displays no output\n  -e|--emit-java-home       Print value of \"JAVA_HOME\" to stdout (ignores silent mode)\n  -v|--verbose              Displays verbose output\n\n  -f|--feature 11|12|...|ea JDK feature release number, defaults to \"ea\"\n  -o|--os linux-x64|osx-x64 Operating system identifier\n  -u|--url \"https://...\"    Use custom JDK archive (provided as .tar.gz file)\n  -w|--workspace PATH       Working directory defaults to \\${HOME} [${HOME}]\n  -t|--target PATH          Target directory, defaults to first component of the tarball\n  -c|--cacerts              Link system CA certificates (currently only Debian/Ubuntu is supported)\nEOF\n}\n\nfunction script_exit() {\n    if [[ $# -eq 1 ]]; then\n        printf '%s\\n' \"$1\"\n        exit 0\n    fi\n\n    if [[ $# -eq 2 && $2 =~ ^[0-9]+$ ]]; then\n        printf '%b\\n' \"$1\"\n        exit \"$2\"\n    fi\n\n    script_exit 'Invalid arguments passed to script_exit()!' 2\n}\n\nfunction say() {\n    if [[ ${silent} != true ]]; then\n        echo \"$@\"\n    fi\n}\n\nfunction verbose() {\n    if [[ ${verbose} == true ]]; then\n        echo \"$@\"\n    fi\n}\n\nfunction parse_options() {\n    local option\n    while [[ $# -gt 0 ]]; do\n        option=\"$1\"\n        shift\n        case ${option} in\n            -h|-H|--help)\n                usage\n                exit 0\n                ;;\n            -v|-V|--verbose)\n                verbose=true\n                ;;\n            -s|-S|--silent)\n                silent=true\n                verbose \"Silent mode activated\"\n                ;;\n            -d|-D|--dry-run)\n                dry=true\n                verbose \"Dry-run mode activated\"\n                ;;\n            -e|-E|--emit-java-home)\n                emit_java_home=true\n                verbose \"Emitting JAVA_HOME\"\n                ;;\n            -f|-F|--feature)\n                feature=\"$1\"\n                verbose \"feature=${feature}\"\n                shift\n                ;;\n            -l|-L|--license)\n                # license=\"$1\"\n                say \"Ignoring license option: $1 -- using GPLv2+CE by default\"\n                verbose \"license=${license}\"\n                shift\n                ;;\n            -o|-O|--os)\n                os=\"$1\"\n                verbose \"os=${os}\"\n                shift\n                ;;\n            -u|-U|--url)\n                url=\"$1\"\n                verbose \"url=${url}\"\n                shift\n                ;;\n            -w|-W|--workspace)\n                workspace=\"$1\"\n                verbose \"workspace=${workspace}\"\n                shift\n                ;;\n            -t|-T|--target)\n                target=\"$1\"\n                verbose \"target=${target}\"\n                shift\n                ;;\n            -c|-C|--cacerts)\n                cacerts=true\n                verbose \"Linking system CA certificates\"\n                ;;\n            *)\n                script_exit \"Invalid argument was provided: ${option}\" 2\n                ;;\n        esac\n    done\n}\n\nfunction determine_latest_jdk() {\n    local number\n    local curl_result\n    local url\n\n    number=15\n    verbose \"Determine latest JDK feature release number, starting with ${number}\"\n    while [[ ${number} != 99 ]]\n    do\n      url=\"https://jdk.java.net/${number}\"\n      curl_result=$(curl -o /dev/null --silent --head --write-out %{http_code} ${url})\n      if [[ ${curl_result} -ge 400 ]]; then\n        break\n      fi\n      verbose \"  Found ${url} [${curl_result}]\"\n      latest_jdk=${number}\n      number=$[$number +1]\n    done\n\n    verbose \"Latest JDK feature release number is: ${latest_jdk}\"\n}\n\nfunction perform_sanity_checks() {\n    if [[ ${feature} == '?' ]] || [[ ${feature} == 'ea' ]]; then\n        feature=${latest_jdk}\n    fi\n    if [[ ${feature} -lt 9 ]] || [[ ${feature} -gt ${latest_jdk} ]]; then\n        script_exit \"Expected feature release number in range of 9 to ${latest_jdk}, but got: ${feature}\" 3\n    fi\n    if [[ -d \"$target\" ]]; then\n        script_exit \"Target directory must not exist, but it does: $(du -hs '${target}')\" 3\n    fi\n}\n\nfunction determine_url() {\n    local JAVA_NET=\"https://jdk.java.net/${feature}\"\n    local DOWNLOAD='https://download.java.net/java'\n\n    # An official GA build or an archived feature? Use predefined URL\n    case \"${feature}\" in\n        9) url=\"${DOWNLOAD}/GA/jdk9/9.0.4/binaries/openjdk-9.0.4_${os}_bin.tar.gz\"; return;;\n       10) url=\"${DOWNLOAD}/GA/jdk10/10.0.2/19aef61b38124481863b1413dce1855f/13/openjdk-10.0.2_${os}_bin.tar.gz\"; return;;\n       11) url=\"${DOWNLOAD}/GA/jdk11/9/GPL/openjdk-11.0.2_${os}_bin.tar.gz\"; return;;\n       12) url=\"${DOWNLOAD}/GA/jdk12.0.2/e482c34c86bd4bf8b56c0b35558996b9/10/GPL/openjdk-12.0.2_${os}_bin.tar.gz\"; return;;\n       13) url=\"${DOWNLOAD}/GA/jdk13.0.2/d4173c853231432d94f001e99d882ca7/8/GPL/openjdk-13.0.2_${os}_bin.tar.gz\"; return;;\n       14) url=\"${DOWNLOAD}/GA/jdk14/076bab302c7b4508975440c56f6cc26a/36/GPL/openjdk-14_${os}_bin.tar.gz\"; return;;\n    #  15) is still available from its EA/RC location determined below\n    esac\n\n    # EA or RC build? Grab URL from HTML source of jdk.java.net/${feature}\n    local candidates=$(wget --quiet --output-document - ${JAVA_NET} | grep -Eo 'href[[:space:]]*=[[:space:]]*\"[^\\\"]+\"' | grep -Eo '(http|https)://[^\"]+')\n    url=$(echo \"${candidates}\" | grep -Eo \"${DOWNLOAD}/.+/jdk${feature}/.*${license}/.*jdk-${feature}.+${os}_bin(.tar.gz|.zip)$\" || true)\n\n    if [[ -z ${url} ]]; then\n        script_exit \"Couldn't determine a download url for ${feature}-${license} on ${os}\" 1\n    fi\n}\n\nfunction prepare_variables() {\n    if [[ ${os} == '?' ]]; then\n        if [[ \"$OSTYPE\" == \"darwin\"* ]]; then\n          os='osx-x64'\n        else\n          os='linux-x64'\n        fi\n    fi\n    if [[ ${url} == '?' ]]; then\n        determine_latest_jdk\n        perform_sanity_checks\n        determine_url\n    else\n        feature='<overridden by custom url>'\n        license='<overridden by custom url>'\n        os='<overridden by custom url>'\n    fi\n    status=$(curl -o /dev/null --silent --head --write-out %{http_code} ${url})\n}\n\nfunction print_variables() {\ncat << EOF\nVariables:\n  feature = ${feature}\n       os = ${os}\n      url = ${url}\n   status = ${status}\nEOF\n}\n\nfunction download_and_extract_and_set_target() {\n    local quiet='--quiet'; if [[ ${verbose} == true ]]; then quiet=''; fi\n    local local=\"--directory-prefix ${workspace} --output-document=jdk.tar.gz\"\n    local remote='--timestamping --continue'\n    local wget_options=\"${quiet} ${local} ${remote}\"\n    local tar_options=\"--file jdk.tar.gz\"\n\n    say \"Downloading JDK from ${url}...\"\n    verbose \"Using wget options: ${wget_options}\"\n    wget ${wget_options} ${url}\n\n    if [[ ${os} == 'windows-x64' ]]; then\n        script_exit \"Extracting archives on Windows isn't supported, yet\" 4\n    fi\n\n    verbose \"Using tar options: ${tar_options}\"\n    if [[ ${target} == '?' ]]; then\n        tar --extract ${tar_options} -C \"${workspace}\"\n        if [[ \"$OSTYPE\" != \"darwin\"* ]]; then\n            target=\"${workspace}\"/$(tar --list ${tar_options} | grep 'bin/javac' | tr '/' '\\n' | tail -3 | head -1)\n        else\n            target=\"${workspace}\"/$(tar --list ${tar_options} | head -2 | tail -1 | cut -f 2 -d '/' -)/Contents/Home\n        fi\n        verbose \"Set target to: ${target}\"\n    else\n        echo \"Using custom target: ${target}\"\n        if [[ \"$OSTYPE\" != \"darwin\"* ]]; then\n            mkdir --parents \"${target}\"\n            tar --extract ${tar_options} -C \"${target}\" --strip-components=1\n        else\n            mkdir -p \"${target}\"\n            tar --extract ${tar_options} -C \"${target}\" --strip-components=4\n        fi\n    fi\n\n    if [[ ${verbose} == true ]]; then\n        echo \"Content of target directory:\"\n        ls \"${target}\"\n        echo \"Content of release file:\"\n        [[ ! -f \"${target}/release\" ]] || cat \"${target}/release\"\n    fi\n\n    # Link to system certificates\n    # https://openjdk.java.net/jeps/319\n    # https://bugs.openjdk.java.net/browse/JDK-8196141\n    if [[ ${cacerts} == true ]]; then\n        local directory=\"${target}/lib/security/cacerts\"\n        if [[ -f \"${directory}\" ]]; then\n            mv \"${directory}\" \"${directory}.jdk\"\n            ln -s /etc/ssl/certs/java/cacerts \"${directory}\"\n        else\n            verbose \"Directory ${directory} doesn't exist, didn't link system CA certificates.\"\n        fi\n    fi\n}\n\nfunction main() {\n    initialize\n    parse_options \"$@\"\n\n    say \"$script_name $script_version\"\n    prepare_variables\n\n    if [[ ${silent} == false ]]; then print_variables; fi\n    if [[ ${dry} == true ]]; then exit 0; fi\n\n    download_and_extract_and_set_target\n\n    export JAVA_HOME=$(cd \"${target}\"; pwd)\n    export PATH=${JAVA_HOME}/bin:$PATH\n\n    if [[ ${silent} == false ]]; then java -Xmx100m -version; fi\n    if [[ ${emit_java_home} == true ]]; then echo \"${JAVA_HOME}\"; fi\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "osx-toolchains.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF8\"?>\n<toolchains>\n   <toolchain>\n      <type>paths</type>\n      <provides>\n         <id>java</id>\n      </provides>\n      <configuration>\n         <paths>\n            <path>/Library/Java/JavaVirtualMachines/jdk-11.0.11.jdk/Contents/Home/bin</path>\n         </paths>\n      </configuration>\n   </toolchain>\n</toolchains>\n"
  },
  {
    "path": "pom.xml",
    "content": "<!--\n   Copyright (C) 2013, 2014 Brett Wooldridge\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n-->\n<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\">\n   <modelVersion>4.0.0</modelVersion>\n\n   <properties>\n      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n      <sureFireOptions11>--add-modules=ALL-MODULE-PATH</sureFireOptions11>\n      <sureFireForks11>false</sureFireForks11>\n      <!--java11.sourceDirectory>${project.basedir}/src/main/java11</java11.sourceDirectory -->\n      <!--java11.build.outputDirectory>${project.build.directory}/classes-java11</java11.build.outputDirectory -->\n      <artifact.classifier />\n\n      <!-- When releasing a new version, this property controls whether the staged artifacts will be automatically\n           released in Nexus. If this is set to false (-DautoReleaseStagedArtifacts=false), artifacts will need to\n           be manually released via the Nexus UI at https://oss.sonatype.org -->\n      <autoReleaseStagedArtifacts>true</autoReleaseStagedArtifacts>\n\n      <commons.csv.version>1.12.0</commons.csv.version>\n      <docker.maven.plugin.fabric8.version>0.45.0</docker.maven.plugin.fabric8.version>\n      <felix.bundle.plugin.version>5.1.9</felix.bundle.plugin.version>\n      <felix.version>7.0.5</felix.version>\n      <h2.version>2.3.232</h2.version>\n      <hibernate.version>5.4.24.Final</hibernate.version>\n      <javassist.version>3.29.2-GA</javassist.version>\n      <jndi.version>0.11.4.1</jndi.version>\n      <junit.version>4.13.2</junit.version>\n      <log4j.version>2.25.1</log4j.version>\n      <maven.release.version>3.0.1</maven.release.version>\n      <metrics.version>3.2.5</metrics.version>\n      <metrics5.version>5.0.0-rc17</metrics5.version>\n      <micrometer.version>1.5.4</micrometer.version>\n      <mockito.version>3.7.7</mockito.version>\n      <pax.exam.version>4.14.0</pax.exam.version>\n      <pax.url.version>2.5.4</pax.url.version>\n      <postgresql.version>42.7.7</postgresql.version>\n      <simpleclient.version>0.16.0</simpleclient.version>\n      <slf4j.version>2.0.17</slf4j.version>\n      <testcontainers.version>1.20.3</testcontainers.version>\n   </properties>\n\n   <groupId>com.zaxxer</groupId>\n   <artifactId>HikariCP</artifactId>\n   <version>7.0.3-SNAPSHOT</version>\n   <packaging>bundle</packaging>\n\n   <name>HikariCP</name>\n   <description>Ultimate JDBC Connection Pool</description>\n   <url>https://github.com/brettwooldridge/HikariCP</url>\n   <inceptionYear>2013</inceptionYear>\n\n   <organization>\n      <name>Zaxxer.com</name>\n      <url>https://github.com/brettwooldridge</url>\n   </organization>\n\n   <scm>\n      <connection>scm:git:https://github.com/brettwooldridge/HikariCP.git</connection>\n      <developerConnection>scm:git:https://github.com/brettwooldridge/HikariCP.git</developerConnection>\n      <url>https://github.com/brettwooldridge/HikariCP</url>\n      <tag>HEAD</tag>\n   </scm>\n\n   <distributionManagement>\n      <snapshotRepository>\n         <id>ossrh</id>\n         <url>https://oss.sonatype.org/content/repositories/snapshots</url>\n      </snapshotRepository>\n   </distributionManagement>\n\n   <issueManagement>\n      <url>https://github.com/brettwooldridge/HikariCP/issues</url>\n   </issueManagement>\n\n   <licenses>\n      <license>\n         <name>The Apache Software License, Version 2.0</name>\n         <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>\n         <distribution>repo</distribution>\n      </license>\n   </licenses>\n\n   <developers>\n      <developer>\n         <name>Brett Wooldridge</name>\n         <email>brett.wooldridge@gmail.com</email>\n      </developer>\n   </developers>\n\n   <dependencies>\n      <dependency>\n         <groupId>org.slf4j</groupId>\n         <artifactId>slf4j-api</artifactId>\n         <version>${slf4j.version}</version>\n      </dependency>\n      <dependency>\n         <groupId>org.apache.logging.log4j</groupId>\n         <artifactId>log4j-api</artifactId>\n         <version>${log4j.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.apache.logging.log4j</groupId>\n         <artifactId>log4j-core</artifactId>\n         <version>${log4j.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.testcontainers</groupId>\n         <artifactId>postgresql</artifactId>\n         <version>${testcontainers.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.apache.commons</groupId>\n         <artifactId>commons-compress</artifactId>\n         <version>1.27.1</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.apache.commons</groupId>\n         <artifactId>commons-lang3</artifactId>\n         <version>3.18.0</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.apache.commons</groupId>\n         <artifactId>commons-csv</artifactId>\n         <version>${commons.csv.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.mockito</groupId>\n         <artifactId>mockito-core</artifactId>\n         <version>${mockito.version}</version>\n         <scope>test</scope>\n         <exclusions>\n            <exclusion>\n               <groupId>org.hamcrest</groupId>\n               <artifactId>hamcrest-core</artifactId>\n            </exclusion>\n         </exclusions>\n      </dependency>\n      <dependency>\n         <groupId>junit</groupId>\n         <artifactId>junit</artifactId>\n         <version>${junit.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.javassist</groupId>\n         <artifactId>javassist</artifactId>\n         <version>${javassist.version}</version>\n         <optional>true</optional>\n      </dependency>\n      <dependency>\n         <groupId>io.micrometer</groupId>\n         <artifactId>micrometer-core</artifactId>\n         <version>${micrometer.version}</version>\n         <optional>true</optional>\n      </dependency>\n      <dependency>\n         <groupId>org.postgresql</groupId>\n         <artifactId>postgresql</artifactId>\n         <version>${postgresql.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.hibernate</groupId>\n         <artifactId>hibernate-core</artifactId>\n         <version>${hibernate.version}</version>\n         <scope>provided</scope>\n         <optional>true</optional>\n         <exclusions>\n            <exclusion>\n               <artifactId>jboss-logging</artifactId>\n               <groupId>org.jboss.logging</groupId>\n            </exclusion>\n            <exclusion>\n               <artifactId>jboss-logging-annotations</artifactId>\n               <groupId>org.jboss.logging</groupId>\n            </exclusion>\n         </exclusions>\n      </dependency>\n      <dependency>\n         <groupId>io.dropwizard.metrics</groupId>\n         <artifactId>metrics-core</artifactId>\n         <version>${metrics.version}</version>\n         <scope>provided</scope>\n         <optional>true</optional>\n      </dependency>\n      <dependency>\n         <groupId>io.dropwizard.metrics</groupId>\n         <artifactId>metrics-healthchecks</artifactId>\n         <version>${metrics.version}</version>\n         <scope>provided</scope>\n         <optional>true</optional>\n      </dependency>\n      <dependency>\n         <groupId>io.dropwizard.metrics5</groupId>\n         <artifactId>metrics-core</artifactId>\n         <version>${metrics5.version}</version>\n         <scope>provided</scope>\n         <optional>true</optional>\n      </dependency>\n      <dependency>\n         <groupId>io.prometheus</groupId>\n         <artifactId>simpleclient</artifactId>\n         <version>${simpleclient.version}</version>\n         <scope>provided</scope>\n         <optional>true</optional>\n      </dependency>\n      <dependency>\n         <groupId>simple-jndi</groupId>\n         <artifactId>simple-jndi</artifactId>\n         <version>${jndi.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.apache.logging.log4j</groupId>\n         <artifactId>log4j-slf4j2-impl</artifactId>\n         <version>${log4j.version}</version>\n         <scope>test</scope>\n      </dependency>\n\n      <!-- OSGi test -->\n      <dependency>\n         <groupId>javax.inject</groupId>\n         <artifactId>javax.inject</artifactId>\n         <version>1</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.apache.felix</groupId>\n         <artifactId>org.apache.felix.framework</artifactId>\n         <version>${felix.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.ops4j.pax.exam</groupId>\n         <artifactId>pax-exam-container-native</artifactId>\n         <version>${pax.exam.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.ops4j.pax.exam</groupId>\n         <artifactId>pax-exam-junit4</artifactId>\n         <version>${pax.exam.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.ops4j.pax.exam</groupId>\n         <artifactId>pax-exam-link-assembly</artifactId>\n         <version>${pax.exam.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.ops4j.pax.exam</groupId>\n         <artifactId>pax-exam-link-mvn</artifactId>\n         <version>${pax.exam.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.ops4j.pax.url</groupId>\n         <artifactId>pax-url-aether</artifactId>\n         <version>${pax.url.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>org.ops4j.pax.url</groupId>\n         <artifactId>pax-url-reference</artifactId>\n         <version>${pax.url.version}</version>\n         <scope>test</scope>\n      </dependency>\n      <dependency>\n         <groupId>com.h2database</groupId>\n         <artifactId>h2</artifactId>\n         <version>${h2.version}</version>\n         <scope>test</scope>\n      </dependency>\n   </dependencies>\n\n   <build>\n      <pluginManagement>\n         <plugins>\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-resources-plugin</artifactId>\n               <version>3.3.1</version>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-install-plugin</artifactId>\n               <version>3.1.4</version>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-clean-plugin</artifactId>\n               <version>3.2.0</version>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-compiler-plugin</artifactId>\n               <version>3.10.1</version>\n               <configuration>\n                  <source>11</source>\n                  <target>11</target>\n                  <compilerArgs>-Xlint</compilerArgs>\n               </configuration>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-deploy-plugin</artifactId>\n               <version>2.8.2</version>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-gpg-plugin</artifactId>\n               <version>3.0.1</version>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-release-plugin</artifactId>\n               <version>2.5.3</version>\n            </plugin>\n\n            <plugin>\n               <groupId>org.sonatype.plugins</groupId>\n               <artifactId>nexus-staging-maven-plugin</artifactId>\n               <version>1.6.12</version>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-surefire-plugin</artifactId>\n               <version>3.0.0-M8</version>\n               <configuration>\n                  <!-- Sets the VM argument line used when unit tests are run. -->\n                  <argLine>${surefireArgLine} ${sureFireOptions11}</argLine>\n                  <reuseForks>${sureFireForks11}</reuseForks>\n                  <useModulePath>false</useModulePath>\n               </configuration>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-source-plugin</artifactId>\n               <version>3.0.1</version>\n               <configuration>\n                  <!-- outputDirectory>/absolute/path/to/the/output/directory</outputDirectory>\n                     <finalName>filename-of-generated-jar-file</finalName -->\n                  <attach>true</attach>\n               </configuration>\n               <executions>\n                  <execution>\n                     <id>attach-sources</id>\n                     <goals>\n                        <goal>jar-no-fork</goal>\n                     </goals>\n                  </execution>\n               </executions>\n            </plugin>\n\n            <plugin>\n               <groupId>org.apache.maven.plugins</groupId>\n               <artifactId>maven-javadoc-plugin</artifactId>\n               <version>3.11.2</version>\n               <configuration>\n                  <show>public</show>\n                  <attach>true</attach>\n                  <maxmemory>1024m</maxmemory>\n                  <legacyMode>true</legacyMode>\n                  <sourceFileExcludes>\n                     <sourceFileExclude>**\\/module-info.java</sourceFileExclude>\n                     <sourceFileExclude>**\\/HikariConfigurationUtil.java</sourceFileExclude>\n                     <sourceFileExclude>**\\/HikariConnectionProvider.java</sourceFileExclude>\n                     <sourceFileExclude>**\\/Prometheus*Tracker.java</sourceFileExclude>\n                     <sourceFileExclude>**\\/Micrometer*Tracker.java</sourceFileExclude>\n                     <sourceFileExclude>**\\/Dropwizard*Tracker.java</sourceFileExclude>\n                     <sourceFileExclude>**\\/Coda*Tracker.java</sourceFileExclude>\n                  </sourceFileExcludes>\n                  <disableSourcepathUsage>true</disableSourcepathUsage>\n                  <bottom><![CDATA[Copyright © {inceptionYear}–{currentYear} Brett Wooldridge. All rights reserved.]]></bottom>\n               </configuration>\n               <executions>\n                  <execution>\n                     <id>attach-javadoc</id>\n                     <phase>package</phase>\n                     <goals>\n                        <goal>jar</goal>\n                     </goals>\n                  </execution>\n               </executions>\n            </plugin>\n         </plugins>\n      </pluginManagement>\n\n      <plugins>\n         <plugin>\n            <groupId>org.apache.maven.plugins</groupId>\n            <artifactId>maven-enforcer-plugin</artifactId>\n            <version>3.4.1</version>\n            <executions>\n               <execution>\n                  <id>enforce-maven</id>\n                  <goals>\n                     <goal>enforce</goal>\n                  </goals>\n                  <configuration>\n                     <rules>\n                        <requireMavenVersion>\n                           <version>(3.0.0,)</version>\n                        </requireMavenVersion>\n                     </rules>\n                  </configuration>\n               </execution>\n            </executions>\n         </plugin>\n\n         <plugin>\n            <artifactId>maven-dependency-plugin</artifactId>\n            <version>2.8</version>\n            <executions>\n               <execution>\n                  <phase>generate-sources</phase>\n                  <goals>\n                     <goal>build-classpath</goal>\n                  </goals>\n                  <configuration>\n                     <outputProperty>maven.compile.classpath</outputProperty>\n                  </configuration>\n               </execution>\n            </executions>\n         </plugin>\n\n         <plugin>\n            <groupId>org.apache.maven.plugins</groupId>\n            <artifactId>maven-javadoc-plugin</artifactId>\n         </plugin>\n\n         <plugin>\n            <!-- Generate proxies -->\n            <groupId>org.codehaus.mojo</groupId>\n            <artifactId>exec-maven-plugin</artifactId>\n            <version>1.6.0</version>\n            <extensions>true</extensions>\n            <executions>\n               <execution>\n                  <phase>compile</phase>\n                  <!-- phase>generate-test-sources</phase -->\n                  <goals>\n                     <goal>exec</goal>\n                  </goals>\n               </execution>\n            </executions>\n            <configuration>\n               <executable>java</executable>\n               <arguments>\n                  <argument>-cp</argument>\n                  <argument>${project.build.outputDirectory}${path.separator}${maven.compile.classpath}</argument>\n                  <argument>com.zaxxer.hikari.util.JavassistProxyFactory</argument>\n                  <argument>${project.basedir}</argument>\n               </arguments>\n            </configuration>\n         </plugin>\n\n         <plugin>\n            <!-- The Docker Maven plugin is used to create docker image with the fat jar -->\n            <groupId>io.fabric8</groupId>\n            <artifactId>docker-maven-plugin</artifactId>\n            <version>${docker.maven.plugin.fabric8.version}</version>\n            <configuration>\n               <logDate>default</logDate>\n               <autoPull>true</autoPull>\n               <images>\n                  <!-- Postgres Image is used 'as-is' and iked into the service s linimage -->\n                  <image>\n                     <alias>db</alias>\n                     <name>postgres:16</name>\n                     <run>\n                        <env>\n                           <POSTGRES_PASSWORD>password</POSTGRES_PASSWORD>\n                        </env>\n                        <wait>\n                           <log>database system is ready to accept connections</log>\n                           <time>20000</time>\n                        </wait>\n                        <log>\n                           <prefix>DB</prefix>\n                           <color>yellow</color>\n                        </log>\n                     </run>\n                  </image>\n               </images>\n            </configuration>\n\n            <!-- Hooking into the lifecycle -->\n            <executions>\n               <execution>\n                  <id>start</id>\n                  <phase>pre-integration-test</phase>\n                  <goals>\n                     <goal>build</goal>\n                     <goal>start</goal>\n                  </goals>\n               </execution>\n               <execution>\n                  <id>stop</id>\n                  <phase>post-integration-test</phase>\n                  <goals>\n                     <goal>stop</goal>\n                  </goals>\n               </execution>\n            </executions>\n         </plugin>\n\n         <plugin>\n            <groupId>org.jacoco</groupId>\n            <artifactId>jacoco-maven-plugin</artifactId>\n            <version>0.8.8</version>\n            <executions>\n               <!-- Prepares the property pointing to the JaCoCo runtime agent which is passed as VM argument when Maven the Surefire plugin is executed. -->\n               <execution>\n                  <goals>\n                     <goal>prepare-agent</goal>\n                  </goals>\n                  <configuration>\n                     <!-- Sets the path to the file which contains the execution data. -->\n                     <destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile>\n                     <!-- Sets the name of the property containing the settings for JaCoCo runtime agent. -->\n                     <propertyName>surefireArgLine</propertyName>\n                     <excludes>\n                        <exclude>**/com/zaxxer/hikari/util/JavassistProxyFactory*</exclude>\n                        <exclude>**/com/zaxxer/hikari/pool/HikariProxy*</exclude>\n                        <exclude>**/com/zaxxer/hikari/metrics/**</exclude>\n                     </excludes>\n                  </configuration>\n               </execution>\n               <!-- Ensures that the code coverage report for unit tests is created after unit tests have been run. -->\n               <execution>\n                  <id>report</id>\n                  <phase>test</phase>\n                  <goals>\n                     <goal>report</goal>\n                  </goals>\n                  <configuration>\n                     <!-- Sets the path to the file which contains the execution data. -->\n                     <dataFile>${project.build.directory}/coverage-reports/jacoco.exec</dataFile>\n                     <excludes>\n                        <exclude>**/com/zaxxer/hikari/pool/HikariProxy*</exclude>\n                        <exclude>**/com/zaxxer/hikari/metrics/**</exclude>\n                     </excludes>\n                  </configuration>\n               </execution>\n            </executions>\n         </plugin>\n\n         <plugin>\n            <groupId>org.apache.maven.plugins</groupId>\n            <artifactId>maven-failsafe-plugin</artifactId>\n            <version>3.0.0-M3</version>\n            <executions>\n               <execution>\n                  <goals>\n                     <goal>integration-test</goal>\n                     <goal>verify</goal>\n                  </goals>\n               </execution>\n            </executions>\n         </plugin>\n\n         <plugin>\n            <groupId>org.apache.felix</groupId>\n            <artifactId>maven-bundle-plugin</artifactId>\n            <version>${felix.bundle.plugin.version}</version>\n            <extensions>true</extensions>\n            <configuration>\n               <classifier>${artifact.classifier}</classifier>\n               <instructions>\n                  <Automatic-Module-Name>com.zaxxer.hikari</Automatic-Module-Name>\n                  <!-- Multi-Release>true</Multi-Release-->\n                  <Bundle-Name>HikariCP</Bundle-Name>\n                  <Export-Package>\n                     com.zaxxer.hikari,\n                     com.zaxxer.hikari.hibernate,\n                     com.zaxxer.hikari.metrics,\n                     com.zaxxer.hikari.metrics.dropwizard,\n                     com.zaxxer.hikari.metrics.micrometer,\n                     com.zaxxer.hikari.metrics.prometheus\n                  </Export-Package>\n                  <Private-Package>com.zaxxer.hikari.*</Private-Package>\n                  <Include-Resource>target/classes/module-info.class</Include-Resource>\n                  <_exportcontents>\n                     com.zaxxer.hikari.pool,\n                     com.zaxxer.hikari.util\n                  </_exportcontents>\n                  <Import-Package>\n                     javax.management,\n                     javax.naming,\n                     javax.naming.spi,\n                     javax.sql,\n                     javax.sql.rowset,\n                     javax.sql.rowset.serial,\n                     javax.sql.rowset.spi,\n                     com.codahale.metrics;resolution:=optional,\n                     com.codahale.metrics.health;resolution:=optional,\n                     io.dropwizard.metrics5;resolution:=optional,\n                     io.micrometer.core.instrument;resolution:=optional,\n                     org.slf4j;version=\"[1.6,2)\",\n                     org.hibernate;resolution:=optional,\n                     org.hibernate.cfg;resolution:=optional,\n                     org.hibernate.engine.jdbc.connections.spi;resolution:=optional,\n                     org.hibernate.service;resolution:=optional,\n                     org.hibernate.service.spi;resolution:=optional\n                  </Import-Package>\n                  <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>\n                  <DynamicImport-Package>*</DynamicImport-Package>\n               </instructions>\n            </configuration>\n            <executions>\n               <!-- This execution makes sure that the manifest is available when the tests are executed -->\n               <execution>\n                  <goals>\n                     <goal>manifest</goal>\n                  </goals>\n               </execution>\n            </executions>\n         </plugin>\n      </plugins>\n   </build>\n\n   <profiles>\n      <profile>\n         <id>felix</id>\n         <activation>\n            <activeByDefault>true</activeByDefault>\n            <property>\n               <name>pax.exam.framework</name>\n               <value>felix</value>\n            </property>\n         </activation>\n         <properties>\n            <pax.exam.framework>felix</pax.exam.framework>\n            <pax.exam.logging>none</pax.exam.logging>\n         </properties>\n         <dependencies>\n            <dependency>\n               <groupId>org.apache.felix</groupId>\n               <artifactId>org.apache.felix.framework</artifactId>\n               <version>${felix.version}</version>\n               <scope>test</scope>\n            </dependency>\n         </dependencies>\n      </profile>\n\n      <profile>\n         <id>release</id>\n         <activation>\n            <property>\n               <name>performRelease</name>\n               <value>true</value>\n            </property>\n         </activation>\n         <build>\n            <plugins>\n               <plugin>\n                  <groupId>org.apache.maven.plugins</groupId>\n                  <artifactId>maven-source-plugin</artifactId>\n                  <version>3.3.0</version>\n                  <executions>\n                     <execution>\n                        <id>attach-sources</id>\n                        <goals>\n                           <goal>jar-no-fork</goal>\n                        </goals>\n                     </execution>\n                  </executions>\n               </plugin>\n\n               <!-- For release: mvn release:perform -Darguments=-Dgpg.passphrase=PASSPHRASE\n                      With gpg2 you don't need to pass the passphrase; the GPG agent will prompt for it. -->\n               <plugin>\n                  <groupId>org.apache.maven.plugins</groupId>\n                  <artifactId>maven-gpg-plugin</artifactId>\n                  <executions>\n                     <execution>\n                        <id>sign-artifacts</id>\n                        <phase>verify</phase>\n                        <goals>\n                           <goal>sign</goal>\n                        </goals>\n                     </execution>\n                  </executions>\n               </plugin>\n\n               <!-- nexus-staging-maven-plugin replaces the standard maven-deploy-plugin for releases and\n                    is useful for ensuring artifacts are all-or-nothing, as well as allowing artifacts to\n                    be reviewed before they're made public -->\n               <plugin>\n                  <groupId>org.sonatype.plugins</groupId>\n                  <artifactId>nexus-staging-maven-plugin</artifactId>\n                  <extensions>true</extensions>\n                  <configuration>\n                     <autoReleaseAfterClose>${autoReleaseStagedArtifacts}</autoReleaseAfterClose>\n                     <nexusUrl>https://ossrh-staging-api.central.sonatype.com</nexusUrl>\n                     <serverId>ossrh</serverId>\n                  </configuration>\n               </plugin>\n            </plugins>\n         </build>\n      </profile>\n   </profiles>\n</project>\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/HikariConfig.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari;\n\nimport com.codahale.metrics.health.HealthCheckRegistry;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.util.Credentials;\nimport com.zaxxer.hikari.util.PropertyElf;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.naming.InitialContext;\nimport javax.naming.NamingException;\nimport javax.sql.DataSource;\nimport java.io.*;\nimport java.lang.reflect.Modifier;\nimport java.security.AccessControlException;\nimport java.sql.Connection;\nimport java.util.Properties;\nimport java.util.TreeSet;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.ThreadLocalRandom;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static com.zaxxer.hikari.util.UtilityElf.*;\nimport static java.util.concurrent.TimeUnit.MINUTES;\nimport static java.util.concurrent.TimeUnit.SECONDS;\n\n@SuppressWarnings({\"SameParameterValue\", \"unused\"})\npublic class HikariConfig implements HikariConfigMXBean\n{\n   private static final Logger LOGGER = LoggerFactory.getLogger(HikariConfig.class);\n\n   private static final char[] ID_CHARACTERS = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\".toCharArray();\n   private static final long CONNECTION_TIMEOUT = SECONDS.toMillis(30);\n   private static final long VALIDATION_TIMEOUT = SECONDS.toMillis(5);\n   private static final long SOFT_TIMEOUT_FLOOR = Long.getLong(\"com.zaxxer.hikari.timeoutMs.floor\", 250L);\n   private static final long IDLE_TIMEOUT = MINUTES.toMillis(10);\n   private static final long MAX_LIFETIME = MINUTES.toMillis(30);\n   private static final long DEFAULT_KEEPALIVE_TIME = MINUTES.toMillis(2);\n   private static final int DEFAULT_POOL_SIZE = 10;\n\n   private static boolean unitTest = false;\n\n   // Properties changeable at runtime through the HikariConfigMXBean\n   //\n   private volatile String catalog;\n   private volatile long connectionTimeout;\n   private volatile long validationTimeout;\n   private volatile long idleTimeout;\n   private volatile long leakDetectionThreshold;\n   private volatile long maxLifetime;\n   private volatile int maxPoolSize;\n   private volatile int minIdle;\n   private final AtomicReference<Credentials> credentials = new AtomicReference<>(Credentials.of(null, null));\n\n   // Properties NOT changeable at runtime\n   //\n   private long initializationFailTimeout;\n   private String connectionInitSql;\n   private String connectionTestQuery;\n   private String credentialsProviderClassName;\n   private String dataSourceClassName;\n   private String dataSourceJndiName;\n   private String driverClassName;\n   private String exceptionOverrideClassName;\n   private SQLExceptionOverride exceptionOverride;\n   private String jdbcUrl;\n   private String poolName;\n   private String schema;\n   private String transactionIsolationName;\n   private boolean isAutoCommit;\n   private boolean isReadOnly;\n   private boolean isIsolateInternalQueries;\n   private boolean isRegisterMbeans;\n   private boolean isAllowPoolSuspension;\n   private HikariCredentialsProvider credentialsProvider;\n   private DataSource dataSource;\n   private Properties dataSourceProperties;\n   private ThreadFactory threadFactory;\n   private ScheduledExecutorService scheduledExecutor;\n   private MetricsTrackerFactory metricsTrackerFactory;\n   private Object metricRegistry;\n   private Object healthCheckRegistry;\n   private Properties healthCheckProperties;\n\n   private long keepaliveTime;\n\n   private volatile boolean sealed;\n\n   /**\n    * Default constructor\n    * <p>\n    * If the System property {@code hikari.configurationFile} is set,\n    * then the default constructor will attempt to load the specified configuration file\n    * <p>\n    * {@link #HikariConfig(String propertyFileName)} can be similarly used\n    * instead of using the system property\n    */\n   public HikariConfig()\n   {\n      dataSourceProperties = new Properties();\n      healthCheckProperties = new Properties();\n\n      minIdle = -1;\n      maxPoolSize = DEFAULT_POOL_SIZE;\n      maxLifetime = MAX_LIFETIME;\n      connectionTimeout = CONNECTION_TIMEOUT;\n      validationTimeout = VALIDATION_TIMEOUT;\n      idleTimeout = IDLE_TIMEOUT;\n      initializationFailTimeout = 1;\n      isAutoCommit = true;\n      keepaliveTime = DEFAULT_KEEPALIVE_TIME;\n\n      var systemProp = System.getProperty(\"hikaricp.configurationFile\");\n      if (systemProp != null) {\n         loadProperties(systemProp);\n      }\n   }\n\n   /**\n    * Construct a HikariConfig from the specified properties object.\n    *\n    * @param properties the name of the property file\n    */\n   public HikariConfig(Properties properties)\n   {\n      this();\n      PropertyElf.setTargetFromProperties(this, properties);\n   }\n\n   /**\n    * Construct a HikariConfig from the specified property file name.  <code>propertyFileName</code>\n    * will first be treated as a path in the file-system, and if that fails the\n    * Class.getResourceAsStream(propertyFileName) will be tried.\n    *\n    * @param propertyFileName the name of the property file\n    */\n   public HikariConfig(String propertyFileName)\n   {\n      this();\n\n      loadProperties(propertyFileName);\n   }\n\n   // ***********************************************************************\n   //                       HikariConfigMXBean methods\n   // ***********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public String getCatalog()\n   {\n      return catalog;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setCatalog(String catalog)\n   {\n      this.catalog = catalog;\n   }\n\n\n   /** {@inheritDoc} */\n   @Override\n   public long getConnectionTimeout()\n   {\n      return connectionTimeout;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setConnectionTimeout(long connectionTimeoutMs)\n   {\n      if (connectionTimeoutMs == 0) {\n         this.connectionTimeout = Integer.MAX_VALUE;\n      }\n      else if (connectionTimeoutMs < SOFT_TIMEOUT_FLOOR) {\n         throw new IllegalArgumentException(\"connectionTimeout cannot be less than \" + SOFT_TIMEOUT_FLOOR + \"ms\");\n      }\n      else {\n         this.connectionTimeout = connectionTimeoutMs;\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long getIdleTimeout()\n   {\n      return idleTimeout;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setIdleTimeout(long idleTimeoutMs)\n   {\n      if (idleTimeoutMs < 0) {\n         throw new IllegalArgumentException(\"idleTimeout cannot be negative\");\n      }\n      this.idleTimeout = idleTimeoutMs;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long getLeakDetectionThreshold()\n   {\n      return leakDetectionThreshold;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setLeakDetectionThreshold(long leakDetectionThresholdMs)\n   {\n      this.leakDetectionThreshold = leakDetectionThresholdMs;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long getMaxLifetime()\n   {\n      return maxLifetime;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setMaxLifetime(long maxLifetimeMs)\n   {\n      this.maxLifetime = maxLifetimeMs;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getMaximumPoolSize()\n   {\n      return maxPoolSize;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setMaximumPoolSize(int maxPoolSize)\n   {\n      if (maxPoolSize < 1) {\n         throw new IllegalArgumentException(\"maxPoolSize cannot be less than 1\");\n      }\n      this.maxPoolSize = maxPoolSize;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getMinimumIdle()\n   {\n      return minIdle;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setMinimumIdle(int minIdle)\n   {\n      if (minIdle < 0) {\n         throw new IllegalArgumentException(\"minimumIdle cannot be negative\");\n      }\n      this.minIdle = minIdle;\n   }\n\n   /**\n    * Get the default password to use for DataSource.getConnection(username, password) calls.\n    * @return the password\n    */\n   public String getPassword()\n   {\n      return credentials.get().getPassword();\n   }\n\n   /**\n    * Set the default password to use for DataSource.getConnection(username, password) calls.\n    * @param password the password\n    */\n   @Override\n   public void setPassword(String password)\n   {\n      credentials.updateAndGet(current -> Credentials.of(current.getUsername(), password));\n   }\n\n   /**\n    * Get the default username used for DataSource.getConnection(username, password) calls.\n    *\n    * @return the username\n    */\n   public String getUsername()\n   {\n      return credentials.get().getUsername();\n   }\n\n   /**\n    * Set the default username used for DataSource.getConnection(username, password) calls.\n    *\n    * @param username the username\n    */\n   @Override\n   public void setUsername(String username)\n   {\n      credentials.updateAndGet(current -> Credentials.of(username, current.getPassword()));\n   }\n\n   /**\n    * Atomically set the default username and password to use for DataSource.getConnection(username, password) calls.\n    *\n    * @param credentials the username and password pair\n    */\n   @Override\n   public void setCredentials(final Credentials credentials)\n   {\n      this.credentials.set(credentials);\n   }\n\n   /**\n    * Atomically get the default username and password to use for DataSource.getConnection(username, password) calls.\n    *\n    * @return the username and password pair\n    */\n   public Credentials getCredentials()\n   {\n      return credentials.get();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long getValidationTimeout()\n   {\n      return validationTimeout;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setValidationTimeout(long validationTimeoutMs)\n   {\n      if (validationTimeoutMs < SOFT_TIMEOUT_FLOOR) {\n         throw new IllegalArgumentException(\"validationTimeout cannot be less than \" + SOFT_TIMEOUT_FLOOR + \"ms\");\n      }\n\n      this.validationTimeout = validationTimeoutMs;\n   }\n\n   // ***********************************************************************\n   //                     All other configuration methods\n   // ***********************************************************************\n\n   /**\n    * Get the SQL query to be executed to test the validity of connections.\n    *\n    * @return the SQL query string, or null\n    */\n   public String getConnectionTestQuery()\n   {\n      return connectionTestQuery;\n   }\n\n   /**\n    * Set the SQL query to be executed to test the validity of connections. Using\n    * the JDBC4 <code>Connection.isValid()</code> method to test connection validity can\n    * be more efficient on some databases and is recommended.\n    *\n    * @param connectionTestQuery a SQL query string\n    */\n   public void setConnectionTestQuery(String connectionTestQuery)\n   {\n      checkIfSealed();\n      this.connectionTestQuery = connectionTestQuery;\n   }\n\n   /**\n    * Get the SQL string that will be executed on all new connections when they are\n    * created, before they are added to the pool.\n    *\n    * @return the SQL to execute on new connections, or null\n    */\n   public String getConnectionInitSql()\n   {\n      return connectionInitSql;\n   }\n\n   /**\n    * Set the SQL string that will be executed on all new connections when they are\n    * created, before they are added to the pool.  If this query fails, it will be\n    * treated as a failed connection attempt.\n    *\n    * @param connectionInitSql the SQL to execute on new connections\n    */\n   public void setConnectionInitSql(String connectionInitSql)\n   {\n      checkIfSealed();\n      this.connectionInitSql = connectionInitSql;\n   }\n\n   /**\n    * Get the {@link DataSource} that has been explicitly specified to be wrapped by the\n    * pool.\n    *\n    * @return the {@link DataSource} instance, or null\n    */\n   public DataSource getDataSource()\n   {\n      return dataSource;\n   }\n\n   /**\n    * Set a {@link DataSource} for the pool to explicitly wrap.  This setter is not\n    * available through property file based initialization.\n    *\n    * @param dataSource a specific {@link DataSource} to be wrapped by the pool\n    */\n   public void setDataSource(DataSource dataSource)\n   {\n      checkIfSealed();\n      this.dataSource = dataSource;\n   }\n\n   /**\n    * Get the name of the JDBC {@link DataSource} class used to create Connections.\n    *\n    * @return the fully qualified name of the JDBC {@link DataSource} class\n    */\n   public String getDataSourceClassName()\n   {\n      return dataSourceClassName;\n   }\n\n   /**\n    * Set the fully qualified class name of the JDBC {@link DataSource} that will be used create Connections.\n    *\n    * @param className the fully qualified name of the JDBC {@link DataSource} class\n    */\n   public void setDataSourceClassName(String className)\n   {\n      checkIfSealed();\n      this.dataSourceClassName = className;\n   }\n\n   /**\n    * Add a property (name/value pair) that will be used to configure the {@link DataSource}/{@link java.sql.Driver}.\n    * <p>\n    * In the case of a {@link DataSource}, the property names will be translated to Java setters following the Java Bean\n    * naming convention.  For example, the property {@code cachePrepStmts} will translate into {@code setCachePrepStmts()}\n    * with the {@code value} passed as a parameter.\n    * <p>\n    * In the case of a {@link java.sql.Driver}, the property will be added to a {@link Properties} instance that will\n    * be passed to the driver during {@link java.sql.Driver#connect(String, Properties)} calls.\n    *\n    * @param propertyName the name of the property\n    * @param value the value to be used by the DataSource/Driver\n    */\n   public void addDataSourceProperty(String propertyName, Object value)\n   {\n      checkIfSealed();\n      dataSourceProperties.put(propertyName, value);\n   }\n\n   public String getDataSourceJNDI()\n   {\n      return this.dataSourceJndiName;\n   }\n\n   public void setDataSourceJNDI(String jndiDataSource)\n   {\n      checkIfSealed();\n      this.dataSourceJndiName = jndiDataSource;\n   }\n\n   public Properties getDataSourceProperties()\n   {\n      return dataSourceProperties;\n   }\n\n   public void setDataSourceProperties(Properties dsProperties)\n   {\n      checkIfSealed();\n      dataSourceProperties.putAll(dsProperties);\n   }\n\n   public String getDriverClassName()\n   {\n      return driverClassName;\n   }\n\n   public void setDriverClassName(String driverClassName)\n   {\n      checkIfSealed();\n\n      try {\n         createInstance(driverClassName, java.sql.Driver.class);\n         this.driverClassName = driverClassName;\n      }\n      catch (Exception e) {\n         throw new RuntimeException(\"Failed to load driver class \" + driverClassName, e);\n      }\n   }\n\n   public String getJdbcUrl()\n   {\n      return jdbcUrl;\n   }\n\n   public void setJdbcUrl(String jdbcUrl)\n   {\n      checkIfSealed();\n      this.jdbcUrl = jdbcUrl;\n   }\n\n   /**\n    * Get the default auto-commit behavior of connections in the pool.\n    *\n    * @return the default auto-commit behavior of connections\n    */\n   public boolean isAutoCommit()\n   {\n      return isAutoCommit;\n   }\n\n   /**\n    * Set the default auto-commit behavior of connections in the pool.\n    *\n    * @param isAutoCommit the desired auto-commit default for connections\n    */\n   public void setAutoCommit(boolean isAutoCommit)\n   {\n      checkIfSealed();\n      this.isAutoCommit = isAutoCommit;\n   }\n\n   /**\n    * Get the pool suspension behavior (allowed or disallowed).\n    *\n    * @return the pool suspension behavior\n    */\n   public boolean isAllowPoolSuspension()\n   {\n      return isAllowPoolSuspension;\n   }\n\n   /**\n    * Set whether or not pool suspension is allowed.  There is a performance\n    * impact when pool suspension is enabled.  Unless you need it (for a\n    * redundancy system for example) do not enable it.\n    *\n    * @param isAllowPoolSuspension the desired pool suspension allowance\n    */\n   public void setAllowPoolSuspension(boolean isAllowPoolSuspension)\n   {\n      checkIfSealed();\n      this.isAllowPoolSuspension = isAllowPoolSuspension;\n   }\n\n   /**\n    * Get the pool initialization failure timeout.  See {@code #setInitializationFailTimeout(long)}\n    * for details.\n    *\n    * @return the number of milliseconds before the pool initialization fails\n    * @see HikariConfig#setInitializationFailTimeout(long)\n    */\n   public long getInitializationFailTimeout()\n   {\n      return initializationFailTimeout;\n   }\n\n   /**\n    * Set the pool initialization failure timeout.  This setting applies to pool\n    * initialization when {@link HikariDataSource} is constructed with a {@link HikariConfig},\n    * or when {@link HikariDataSource} is constructed using the no-arg constructor\n    * and {@link HikariDataSource#getConnection()} is called.\n    * <ul>\n    *   <li>Any value greater than zero will be treated as a timeout for pool initialization.\n    *       The calling thread will be blocked from continuing until a successful connection\n    *       to the database, or until the timeout is reached.  If the timeout is reached, then\n    *       a {@code PoolInitializationException} will be thrown. </li>\n    *   <li>A value of zero will <i>not</i>  prevent the pool from starting in the\n    *       case that a connection cannot be obtained. However, upon start the pool will\n    *       attempt to obtain a connection and validate that the {@code connectionTestQuery}\n    *       and {@code connectionInitSql} are valid.  If those validations fail, an exception\n    *       will be thrown.  If a connection cannot be obtained, the validation is skipped\n    *       and the the pool will start and continue to try to obtain connections in the\n    *       background.  This can mean that callers to {@code DataSource#getConnection()} may\n    *       encounter exceptions. </li>\n    *   <li>A value less than zero will bypass any connection attempt and validation during\n    *       startup, and therefore the pool will start immediately.  The pool will continue to\n    *       try to obtain connections in the background. This can mean that callers to\n    *       {@code DataSource#getConnection()} may encounter exceptions. </li>\n    * </ul>\n    * Note that if this timeout value is greater than or equal to zero (0), and therefore an\n    * initial connection validation is performed, this timeout does not override the\n    * {@code connectionTimeout} or {@code validationTimeout}; they will be honored before this\n    * timeout is applied.  The default value is one millisecond.\n    *\n    * @param initializationFailTimeout the number of milliseconds before the\n    *        pool initialization fails, or 0 to validate connection setup but continue with\n    *        pool start, or less than zero to skip all initialization checks and start the\n    *        pool without delay.\n    */\n   public void setInitializationFailTimeout(long initializationFailTimeout)\n   {\n      checkIfSealed();\n      this.initializationFailTimeout = initializationFailTimeout;\n   }\n\n   /**\n    * Determine whether internal pool queries, principally aliveness checks, will be isolated in their own transaction\n    * via {@link Connection#rollback()}.  Defaults to {@code false}.\n    *\n    * @return {@code true} if internal pool queries are isolated, {@code false} if not\n    */\n   public boolean isIsolateInternalQueries()\n   {\n      return isIsolateInternalQueries;\n   }\n\n   /**\n    * Configure whether internal pool queries, principally aliveness checks, will be isolated in their own transaction\n    * via {@link Connection#rollback()}.  Defaults to {@code false}.\n    *\n    * @param isolate {@code true} if internal pool queries should be isolated, {@code false} if not\n    */\n   public void setIsolateInternalQueries(boolean isolate)\n   {\n      checkIfSealed();\n      this.isIsolateInternalQueries = isolate;\n   }\n\n   public MetricsTrackerFactory getMetricsTrackerFactory()\n   {\n      return metricsTrackerFactory;\n   }\n\n   public void setMetricsTrackerFactory(MetricsTrackerFactory metricsTrackerFactory)\n   {\n      if (metricRegistry != null) {\n         throw new IllegalStateException(\"cannot use setMetricsTrackerFactory() and setMetricRegistry() together\");\n      }\n\n      this.metricsTrackerFactory = metricsTrackerFactory;\n   }\n\n   /**\n    * Get the MetricRegistry instance to use for registration of metrics used by HikariCP.  Default is {@code null}.\n    *\n    * @return the MetricRegistry instance that will be used\n    */\n   public Object getMetricRegistry()\n   {\n      return metricRegistry;\n   }\n\n   /**\n    * Set a MetricRegistry instance to use for registration of metrics used by HikariCP.\n    *\n    * @param metricRegistry the MetricRegistry instance to use\n    */\n   public void setMetricRegistry(Object metricRegistry)\n   {\n      if (metricsTrackerFactory != null) {\n         throw new IllegalStateException(\"cannot use setMetricRegistry() and setMetricsTrackerFactory() together\");\n      }\n\n      if (metricRegistry != null) {\n         metricRegistry = getObjectOrPerformJndiLookup(metricRegistry);\n\n         if (!safeIsAssignableFrom(metricRegistry, \"com.codahale.metrics.MetricRegistry\")\n             && !(safeIsAssignableFrom(metricRegistry, \"io.dropwizard.metrics5.MetricRegistry\"))\n             && !(safeIsAssignableFrom(metricRegistry, \"io.micrometer.core.instrument.MeterRegistry\"))) {\n            throw new IllegalArgumentException(\"Class must be instance of com.codahale.metrics.MetricRegistry, \" +\n               \"io.dropwizard.metrics5.MetricRegistry, or io.micrometer.core.instrument.MeterRegistry\");\n         }\n      }\n\n      this.metricRegistry = metricRegistry;\n   }\n\n   /**\n    * Get the HealthCheckRegistry that will be used for registration of health checks by HikariCP.  Currently only\n    * Codahale/DropWizard is supported for health checks.\n    *\n    * @return the HealthCheckRegistry instance that will be used\n    */\n   public Object getHealthCheckRegistry()\n   {\n      return healthCheckRegistry;\n   }\n\n   /**\n    * Set the HealthCheckRegistry that will be used for registration of health checks by HikariCP.  Currently only\n    * Codahale/DropWizard is supported for health checks.  Default is {@code null}.\n    *\n    * @param healthCheckRegistry the HealthCheckRegistry to be used\n    */\n   public void setHealthCheckRegistry(Object healthCheckRegistry)\n   {\n      checkIfSealed();\n\n      if (healthCheckRegistry != null) {\n         healthCheckRegistry = getObjectOrPerformJndiLookup(healthCheckRegistry);\n\n         if (!(healthCheckRegistry instanceof HealthCheckRegistry)) {\n            throw new IllegalArgumentException(\"Class must be an instance of com.codahale.metrics.health.HealthCheckRegistry\");\n         }\n      }\n\n      this.healthCheckRegistry = healthCheckRegistry;\n   }\n\n   public Properties getHealthCheckProperties()\n   {\n      return healthCheckProperties;\n   }\n\n   public void setHealthCheckProperties(Properties healthCheckProperties)\n   {\n      checkIfSealed();\n      this.healthCheckProperties.putAll(healthCheckProperties);\n   }\n\n   public void addHealthCheckProperty(String key, String value)\n   {\n      checkIfSealed();\n      healthCheckProperties.setProperty(key, value);\n   }\n\n   /**\n    * This property controls the keepalive interval for a connection in the pool. An in-use connection will never be\n    * tested by the keepalive thread, only when it is idle will it be tested.\n    *\n    * @return the interval in which connections will be tested for aliveness, thus keeping them alive by the act of checking. Value is in milliseconds, default is 0 (disabled).\n    */\n   public long getKeepaliveTime() {\n      return keepaliveTime;\n   }\n\n   /**\n    * This property controls the keepalive interval for a connection in the pool. An in-use connection will never be\n    * tested by the keepalive thread, only when it is idle will it be tested.\n    *\n    * @param keepaliveTimeMs the interval in which connections will be tested for aliveness, thus keeping them alive by the act of checking. Value is in milliseconds, default is 0 (disabled).\n    */\n   public void setKeepaliveTime(long keepaliveTimeMs) {\n      this.keepaliveTime = keepaliveTimeMs;\n   }\n\n   /**\n    * Determine whether the Connections in the pool are in read-only mode.\n    *\n    * @return {@code true} if the Connections in the pool are read-only, {@code false} if not\n    */\n   public boolean isReadOnly()\n   {\n      return isReadOnly;\n   }\n\n   /**\n    * Configures the Connections to be added to the pool as read-only Connections.\n    *\n    * @param readOnly {@code true} if the Connections in the pool are read-only, {@code false} if not\n    */\n   public void setReadOnly(boolean readOnly)\n   {\n      checkIfSealed();\n      this.isReadOnly = readOnly;\n   }\n\n   /**\n    * Determine whether HikariCP will self-register {@link HikariConfigMXBean} and {@link HikariPoolMXBean} instances\n    * in JMX.\n    *\n    * @return {@code true} if HikariCP will register MXBeans, {@code false} if it will not\n    */\n   public boolean isRegisterMbeans()\n   {\n      return isRegisterMbeans;\n   }\n\n   /**\n    * Configures whether HikariCP self-registers the {@link HikariConfigMXBean} and {@link HikariPoolMXBean} in JMX.\n    *\n    * @param register {@code true} if HikariCP should register MXBeans, {@code false} if it should not\n    */\n   public void setRegisterMbeans(boolean register)\n   {\n      checkIfSealed();\n      this.isRegisterMbeans = register;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String getPoolName()\n   {\n      return poolName;\n   }\n\n   /**\n    * Set the name of the connection pool.  This is primarily used in logging and JMX management consoles\n    * to identify pools and pool configurations\n    *\n    * @param poolName the name of the connection pool to use\n    */\n   public void setPoolName(String poolName)\n   {\n      checkIfSealed();\n      this.poolName = poolName;\n   }\n\n   /**\n    * Get the ScheduledExecutorService used for housekeeping.\n    *\n    * @return the executor\n    */\n   public ScheduledExecutorService getScheduledExecutor()\n   {\n      return scheduledExecutor;\n   }\n\n   /**\n    * Set the ScheduledExecutorService used for housekeeping.\n    *\n    * @param executor the ScheduledExecutorService\n    */\n   public void setScheduledExecutor(ScheduledExecutorService executor)\n   {\n      checkIfSealed();\n      this.scheduledExecutor = executor;\n   }\n\n   public String getTransactionIsolation()\n   {\n      return transactionIsolationName;\n   }\n\n   /**\n    * Get the default schema name to be set on connections.\n    *\n    * @return the default schema name\n    */\n   public String getSchema()\n   {\n      return schema;\n   }\n\n   /**\n    * Set the default schema name to be set on connections.\n    *\n    * @param schema the name of the default schema\n    */\n   public void setSchema(String schema)\n   {\n      checkIfSealed();\n      this.schema = schema;\n   }\n\n   /**\n    * Get the class name of the {@link HikariCredentialsProvider} that will be used to get credentials at runtime.\n    *\n    * @return the class name of the credentials provider\n    * @see HikariCredentialsProvider\n    */\n   public String getCredentialsProviderClassName()\n   {\n      return credentialsProviderClassName;\n   }\n\n   /**\n    * Set the class name of the {@link HikariCredentialsProvider} that will be used to get credentials at runtime. Use this method\n    * or provide a {@link HikariCredentialsProvider} instance via the {@link #setCredentialsProvider(HikariCredentialsProvider)} method.\n    *\n    * @param credentialsProviderClassName the class name of the credentials provider\n    * @see HikariCredentialsProvider\n    */\n   public void setCredentialsProviderClassName(String credentialsProviderClassName) {\n      checkIfSealed();\n\n      try {\n         this.credentialsProvider = createInstance(credentialsProviderClassName, HikariCredentialsProvider.class);\n         this.exceptionOverrideClassName = credentialsProviderClassName;\n      }\n      catch (Exception e) {\n         throw new RuntimeException(\"Failed to instantiate class \" + credentialsProviderClassName, e);\n      }\n   }\n\n   /**\n    * Get the {@link HikariCredentialsProvider} instance created by {@link #setCredentialsProviderClassName(String)} or specified by\n    * {@link #setCredentialsProvider(HikariCredentialsProvider)}.\n    *\n    * @return the HikariCredentialsProvider instance, or null\n    * @see HikariCredentialsProvider\n    */\n   public HikariCredentialsProvider getCredentialsProvider() {\n      return credentialsProvider;\n   }\n\n   /**\n    * Set a user supplied {@link HikariCredentialsProvider} instance. If this method is used, then the {@link #setCredentialsProviderClassName(String)}\n    * method should not be used. The {@link HikariCredentialsProvider} instance will be used to get credentials at runtime.\n    *\n    * @param credentialsProvider a user supplied HikariCredentialsProvider instance\n    * @see HikariCredentialsProvider\n    */\n   public void setCredentialsProvider(HikariCredentialsProvider credentialsProvider) {\n      checkIfSealed();\n      this.credentialsProvider = credentialsProvider;\n   }\n\n   /**\n    * Get the user supplied SQLExceptionOverride class name.\n    *\n    * @return the user supplied SQLExceptionOverride class name\n    * @see SQLExceptionOverride\n    */\n   public String getExceptionOverrideClassName()\n   {\n      return this.exceptionOverrideClassName;\n   }\n\n   /**\n    * Set the user supplied SQLExceptionOverride class name.\n    *\n    * @param exceptionOverrideClassName the user supplied SQLExceptionOverride class name\n    * @see SQLExceptionOverride\n    */\n   public void setExceptionOverrideClassName(String exceptionOverrideClassName)\n   {\n      checkIfSealed();\n\n      try {\n         this.exceptionOverride = createInstance(exceptionOverrideClassName, SQLExceptionOverride.class);\n         this.exceptionOverrideClassName = exceptionOverrideClassName;\n      }\n      catch (Exception e) {\n         throw new RuntimeException(\"Failed to instantiate class \" + exceptionOverrideClassName, e);\n      }\n   }\n\n   /**\n    * Get the SQLExceptionOverride instance created by {@link #setExceptionOverrideClassName(String)} or specified by\n    * {@link #setExceptionOverride(SQLExceptionOverride)}.\n    *\n    * @return the SQLExceptionOverride instance, or null\n    * @see SQLExceptionOverride\n    */\n   public SQLExceptionOverride getExceptionOverride()\n   {\n      return this.exceptionOverride;\n   }\n\n   /**\n    * Set the user supplied SQLExceptionOverride instance.\n    *\n    * @param exceptionOverride the user supplied SQLExceptionOverride instance\n    * @see SQLExceptionOverride\n    */\n   public void setExceptionOverride(SQLExceptionOverride exceptionOverride) {\n      checkIfSealed();\n      this.exceptionOverride = exceptionOverride;\n   }\n\n   /**\n    * Set the default transaction isolation level.  The specified value is the\n    * constant name from the <code>Connection</code> class, eg.\n    * <code>TRANSACTION_REPEATABLE_READ</code>.\n    *\n    * @param isolationLevel the name of the isolation level\n    */\n   public void setTransactionIsolation(String isolationLevel)\n   {\n      checkIfSealed();\n      this.transactionIsolationName = isolationLevel;\n   }\n\n   /**\n    * Get the thread factory used to create threads.\n    *\n    * @return the thread factory (may be null, in which case the default thread factory is used)\n    */\n   public ThreadFactory getThreadFactory()\n   {\n      return threadFactory;\n   }\n\n   /**\n    * Set the thread factory to be used to create threads.\n    *\n    * @param threadFactory the thread factory (setting to null causes the default thread factory to be used)\n    */\n   public void setThreadFactory(ThreadFactory threadFactory)\n   {\n      checkIfSealed();\n      this.threadFactory = threadFactory;\n   }\n\n   void seal()\n   {\n      this.sealed = true;\n   }\n\n   /**\n    * Copies the state of {@code this} into {@code other}.\n    *\n    * @param other Other {@link HikariConfig} to copy the state to.\n    */\n   @SuppressWarnings({\"rawtypes\", \"unchecked\"})\n   public void copyStateTo(HikariConfig other)\n   {\n      for (var field : HikariConfig.class.getDeclaredFields()) {\n         try {\n            if (!Modifier.isFinal(field.getModifiers())) {\n               field.setAccessible(true);\n               field.set(other, field.get(this));\n            } else if (field.getType().isAssignableFrom(AtomicReference.class)) {\n               ((AtomicReference) field.get(other)).set(((AtomicReference) field.get(this)).get());\n            }\n         }\n         catch (Exception e) {\n            throw new RuntimeException(\"Failed to copy HikariConfig state: \" + e.getMessage(), e);\n         }\n      }\n\n      other.sealed = false;\n   }\n\n   // ***********************************************************************\n   //                          Private methods\n   // ***********************************************************************\n\n   @SuppressWarnings(\"StatementWithEmptyBody\")\n   public void validate()\n   {\n      if (poolName == null) {\n         poolName = generatePoolName();\n      }\n      else if (isRegisterMbeans && poolName.contains(\":\")) {\n         throw new IllegalArgumentException(\"poolName cannot contain ':' when used with JMX\");\n      }\n\n      // treat empty property as null\n      //noinspection NonAtomicOperationOnVolatileField\n      catalog = getNullIfEmpty(catalog);\n      connectionInitSql = getNullIfEmpty(connectionInitSql);\n      connectionTestQuery = getNullIfEmpty(connectionTestQuery);\n      transactionIsolationName = getNullIfEmpty(transactionIsolationName);\n      dataSourceClassName = getNullIfEmpty(dataSourceClassName);\n      dataSourceJndiName = getNullIfEmpty(dataSourceJndiName);\n      driverClassName = getNullIfEmpty(driverClassName);\n      jdbcUrl = getNullIfEmpty(jdbcUrl);\n\n      // Check Data Source Options\n      if (dataSource != null) {\n         if (dataSourceClassName != null) {\n            LOGGER.warn(\"{} - using dataSource and ignoring dataSourceClassName.\", poolName);\n         }\n      }\n      else if (dataSourceClassName != null) {\n         if (driverClassName != null) {\n            LOGGER.error(\"{} - cannot use driverClassName and dataSourceClassName together.\", poolName);\n            // NOTE: This exception text is referenced by a Spring Boot FailureAnalyzer, it should not be\n            // changed without first notifying the Spring Boot developers.\n            throw new IllegalStateException(\"cannot use driverClassName and dataSourceClassName together.\");\n         }\n         else if (jdbcUrl != null) {\n            LOGGER.warn(\"{} - using dataSourceClassName and ignoring jdbcUrl.\", poolName);\n         }\n      }\n      else if (jdbcUrl != null || dataSourceJndiName != null) {\n         // ok\n      }\n      else if (driverClassName != null) {\n         LOGGER.error(\"{} - jdbcUrl is required with driverClassName.\", poolName);\n         throw new IllegalArgumentException(\"jdbcUrl is required with driverClassName.\");\n      }\n      else {\n         LOGGER.error(\"{} - dataSource or dataSourceClassName or jdbcUrl is required.\", poolName);\n         throw new IllegalArgumentException(\"dataSource or dataSourceClassName or jdbcUrl is required.\");\n      }\n\n      validateNumerics();\n\n      if (LOGGER.isDebugEnabled() || unitTest) {\n         logConfiguration();\n      }\n   }\n\n   private void validateNumerics()\n   {\n      if (maxLifetime != 0 && maxLifetime < SECONDS.toMillis(30)) {\n         LOGGER.warn(\"{} - maxLifetime is less than 30000ms, setting to default {}ms.\", poolName, MAX_LIFETIME);\n         maxLifetime = MAX_LIFETIME;\n      }\n\n      // keepalive time must larger than 30 seconds\n      if (keepaliveTime != 0 && keepaliveTime < SECONDS.toMillis(30)) {\n         LOGGER.warn(\"{} - keepaliveTime is less than 30000ms, disabling it.\", poolName);\n         keepaliveTime = 0L;\n      }\n\n      // keepalive time must be less than maxLifetime (if maxLifetime is enabled)\n      if (keepaliveTime != 0 && maxLifetime != 0 && keepaliveTime >= maxLifetime) {\n         LOGGER.warn(\"{} - keepaliveTime is greater than or equal to maxLifetime, disabling it.\", poolName);\n         keepaliveTime = 0L;\n      }\n\n      if (leakDetectionThreshold > 0 && !unitTest) {\n         if (leakDetectionThreshold < SECONDS.toMillis(2) || (leakDetectionThreshold > maxLifetime && maxLifetime > 0)) {\n            LOGGER.warn(\"{} - leakDetectionThreshold is less than 2000ms or more than maxLifetime, disabling it.\", poolName);\n            leakDetectionThreshold = 0;\n         }\n      }\n\n      if (connectionTimeout < SOFT_TIMEOUT_FLOOR) {\n         LOGGER.warn(\"{} - connectionTimeout is less than {}ms, setting to {}ms.\", poolName, SOFT_TIMEOUT_FLOOR, CONNECTION_TIMEOUT);\n         connectionTimeout = CONNECTION_TIMEOUT;\n      }\n\n      if (validationTimeout < SOFT_TIMEOUT_FLOOR) {\n         LOGGER.warn(\"{} - validationTimeout is less than {}ms, setting to {}ms.\", poolName, SOFT_TIMEOUT_FLOOR, VALIDATION_TIMEOUT);\n         validationTimeout = VALIDATION_TIMEOUT;\n      }\n\n      if (minIdle < 0 || minIdle > maxPoolSize) {\n         minIdle = maxPoolSize;\n      }\n\n      if (idleTimeout + SECONDS.toMillis(1) > maxLifetime && maxLifetime > 0 && minIdle < maxPoolSize) {\n         LOGGER.warn(\"{} - idleTimeout is close to or more than maxLifetime, disabling it.\", poolName);\n         idleTimeout = 0;\n      }\n      else if (idleTimeout != 0 && idleTimeout < SECONDS.toMillis(10) && minIdle < maxPoolSize) {\n         LOGGER.warn(\"{} - idleTimeout is less than 10000ms, setting to default {}ms.\", poolName, IDLE_TIMEOUT);\n         idleTimeout = IDLE_TIMEOUT;\n      }\n      else  if (idleTimeout != IDLE_TIMEOUT && idleTimeout != 0 && minIdle == maxPoolSize) {\n         LOGGER.warn(\"{} - idleTimeout has been set but has no effect because the pool is operating as a fixed size pool.\", poolName);\n      }\n   }\n\n   private void checkIfSealed()\n   {\n      if (sealed) throw new IllegalStateException(\"The configuration of the pool is sealed once started. Use HikariConfigMXBean for runtime changes.\");\n   }\n\n   private void logConfiguration()\n   {\n      LOGGER.debug(\"{} - configuration:\", poolName);\n      final var propertyNames = new TreeSet<>(PropertyElf.getPropertyNames(HikariConfig.class));\n      for (var prop : propertyNames) {\n         try {\n            var value = PropertyElf.getProperty(prop, this);\n            if (\"dataSourceProperties\".equals(prop)) {\n               var dsProps = PropertyElf.copyProperties(dataSourceProperties);\n               dsProps.setProperty(\"password\", \"<masked>\");\n               value = dsProps;\n            }\n\n            if (\"initializationFailTimeout\".equals(prop) && initializationFailTimeout == Long.MAX_VALUE) {\n               value = \"infinite\";\n            }\n            else if (\"transactionIsolation\".equals(prop) && transactionIsolationName == null) {\n               value = \"default\";\n            }\n            else if (prop.matches(\"scheduledExecutorService|threadFactory\") && value == null) {\n               value = \"internal\";\n            }\n            else if (prop.contains(\"jdbcUrl\") && value instanceof String) {\n               value = maskPasswordInJdbcUrl((String) value);\n            }\n            else if (prop.contains(\"password\")) {\n               value = \"<masked>\";\n            }\n            else if (value instanceof String) {\n               value = \"\\\"\" + value + \"\\\"\"; // quote to see lead/trailing spaces is any\n            }\n            else if (value == null) {\n               value = \"none\";\n            }\n            LOGGER.debug(\"{}{}\", (prop + \"................................................\").substring(0, 32), value);\n         }\n         catch (Exception e) {\n            // continue\n         }\n      }\n   }\n\n   private void loadProperties(String propertyFileName)\n   {\n      try (final var is = openPropertiesInputStream(propertyFileName)) {\n         if (is != null) {\n            var props = new Properties();\n            props.load(is);\n            PropertyElf.setTargetFromProperties(this, props);\n         }\n         else {\n            throw new IllegalArgumentException(\"Cannot find property file: \" + propertyFileName);\n         }\n      }\n      catch (IOException io) {\n         throw new RuntimeException(\"Failed to read property file\", io);\n      }\n   }\n\n   private InputStream openPropertiesInputStream(String propertyFileName) throws FileNotFoundException {\n      final var propFile = new File(propertyFileName);\n      if (propFile.isFile()) {\n         return new FileInputStream(propFile);\n      }\n      var propertiesInputStream = this.getClass().getResourceAsStream(propertyFileName);\n      if (propertiesInputStream == null) {\n        propertiesInputStream = this.getClass().getClassLoader().getResourceAsStream(propertyFileName);\n      }\n      return propertiesInputStream;\n   }\n\n   private String generatePoolName()\n   {\n      final var prefix = \"HikariPool-\";\n      try {\n         // Pool number is global to the VM to avoid overlapping pool numbers in classloader scoped environments\n         synchronized (System.getProperties()) {\n            final var next = String.valueOf(Integer.getInteger(\"com.zaxxer.hikari.pool_number\", 0) + 1);\n            System.setProperty(\"com.zaxxer.hikari.pool_number\", next);\n            return prefix + next;\n         }\n      } catch (AccessControlException e) {\n         // The SecurityManager didn't allow us to read/write system properties\n         // so just generate a random pool number instead\n         final var random = ThreadLocalRandom.current();\n         final var buf = new StringBuilder(prefix);\n\n         for (var i = 0; i < 4; i++) {\n            buf.append(ID_CHARACTERS[random.nextInt(62)]);\n         }\n\n         LOGGER.info(\"assigned random pool name '{}' (security manager prevented access to system properties)\", buf);\n\n         return buf.toString();\n      }\n   }\n\n   private Object getObjectOrPerformJndiLookup(Object object)\n   {\n      if (object instanceof String) {\n         try {\n            var initCtx = new InitialContext();\n            return initCtx.lookup((String) object);\n         }\n         catch (NamingException e) {\n            throw new IllegalArgumentException(e);\n         }\n      }\n      return object;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/HikariConfigMXBean.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari;\n\nimport com.zaxxer.hikari.util.Credentials;\n\n/**\n * The javax.management MBean for a Hikari pool configuration.\n *\n * @author Brett Wooldridge\n */\npublic interface HikariConfigMXBean\n{\n   /**\n    * Get the maximum number of milliseconds that a client will wait for a connection from the pool. If this\n    * time is exceeded without a connection becoming available, a SQLException will be thrown from\n    * {@link javax.sql.DataSource#getConnection()}.\n    *\n    * @return the connection timeout in milliseconds\n    */\n   long getConnectionTimeout();\n\n   /**\n    * Set the maximum number of milliseconds that a client will wait for a connection from the pool. If this\n    * time is exceeded without a connection becoming available, a SQLException will be thrown from\n    * {@link javax.sql.DataSource#getConnection()}.\n    *\n    * @param connectionTimeoutMs the connection timeout in milliseconds\n    */\n   void setConnectionTimeout(long connectionTimeoutMs);\n\n   /**\n    * Get the maximum number of milliseconds that the pool will wait for a connection to be validated as\n    * alive.\n    *\n    * @return the validation timeout in milliseconds\n    */\n   long getValidationTimeout();\n\n   /**\n    * Sets the maximum number of milliseconds that the pool will wait for a connection to be validated as\n    * alive.\n    *\n    * @param validationTimeoutMs the validation timeout in milliseconds\n    */\n   void setValidationTimeout(long validationTimeoutMs);\n\n   /**\n    * This property controls the maximum amount of time (in milliseconds) that a connection is allowed to sit\n    * idle in the pool. Whether a connection is retired as idle or not is subject to a maximum variation of +30\n    * seconds, and average variation of +15 seconds. A connection will never be retired as idle before this timeout.\n    * A value of 0 means that idle connections are never removed from the pool.\n    *\n    * @return the idle timeout in milliseconds\n    */\n   long getIdleTimeout();\n\n   /**\n    * This property controls the maximum amount of time (in milliseconds) that a connection is allowed to sit\n    * idle in the pool. Whether a connection is retired as idle or not is subject to a maximum variation of +30\n    * seconds, and average variation of +15 seconds. A connection will never be retired as idle before this timeout.\n    * A value of 0 means that idle connections are never removed from the pool.\n    *\n    * @param idleTimeoutMs the idle timeout in milliseconds\n    */\n   void setIdleTimeout(long idleTimeoutMs);\n\n   /**\n    * This property controls the amount of time that a connection can be out of the pool before a message is\n    * logged indicating a possible connection leak. A value of 0 means leak detection is disabled.\n    *\n    * @return the connection leak detection threshold in milliseconds\n    */\n   long getLeakDetectionThreshold();\n\n   /**\n    * This property controls the amount of time that a connection can be out of the pool before a message is\n    * logged indicating a possible connection leak. A value of 0 means leak detection is disabled.\n    *\n    * @param leakDetectionThresholdMs the connection leak detection threshold in milliseconds\n    */\n   void setLeakDetectionThreshold(long leakDetectionThresholdMs);\n\n   /**\n    * This property controls the maximum lifetime of a connection in the pool. When a connection reaches this\n    * timeout, even if recently used, it will be retired from the pool. An in-use connection will never be\n    * retired, only when it is idle will it be removed.\n    *\n    * @return the maximum connection lifetime in milliseconds\n    */\n   long getMaxLifetime();\n\n   /**\n    * This property controls the maximum lifetime of a connection in the pool. When a connection reaches this\n    * timeout, even if recently used, it will be retired from the pool. An in-use connection will never be\n    * retired, only when it is idle will it be removed.\n    *\n    * @param maxLifetimeMs the maximum connection lifetime in milliseconds\n    */\n   void setMaxLifetime(long maxLifetimeMs);\n\n   /**\n    * The property controls the minimum number of idle connections that HikariCP tries to maintain in the pool,\n    * including both idle and in-use connections. If the idle connections dip below this value, HikariCP will\n    * make a best effort to restore them quickly and efficiently.\n    *\n    * @return the minimum number of connections in the pool\n    */\n   int getMinimumIdle();\n\n   /**\n    * The property controls the minimum number of idle connections that HikariCP tries to maintain in the pool,\n    * including both idle and in-use connections. If the idle connections dip below this value, HikariCP will\n    * make a best effort to restore them quickly and efficiently.\n    *\n    * @param minIdle the minimum number of idle connections in the pool to maintain\n    */\n   void setMinimumIdle(int minIdle);\n\n   /**\n    * The property controls the maximum number of connections that HikariCP will keep in the pool,\n    * including both idle and in-use connections.\n    *\n    * @return the maximum number of connections in the pool\n    */\n   int getMaximumPoolSize();\n\n   /**\n    * The property controls the maximum size that the pool is allowed to reach, including both idle and in-use\n    * connections. Basically this value will determine the maximum number of actual connections to the database\n    * backend.\n    * <p>\n    * When the pool reaches this size, and no idle connections are available, calls to getConnection() will\n    * block for up to connectionTimeout milliseconds before timing out.\n    *\n    * @param maxPoolSize the maximum number of connections in the pool\n    */\n   void setMaximumPoolSize(int maxPoolSize);\n\n   /**\n    * Set the password used for authentication. Changing this at runtime will apply to new connections only.\n    * Altering this at runtime only works for DataSource-based connections, not Driver-class or JDBC URL-based\n    * connections.\n    *\n    * @param password the database password\n    */\n   void setPassword(String password);\n\n   /**\n    * Set the username used for authentication. Changing this at runtime will apply to new connections only.\n    * Altering this at runtime only works for DataSource-based connections, not Driver-class or JDBC URL-based\n    * connections.\n    *\n    * @param username the database username\n    */\n   void setUsername(String username);\n\n   /**\n    * Set the username and password used for authentication. Changing this at runtime will apply to new\n    * connections only. Altering this at runtime only works for DataSource-based connections, not Driver-class\n    * or JDBC URL-based connections.\n    *\n    * @param credentials the database username and password pair\n    */\n   void setCredentials(Credentials credentials);\n\n   /**\n    * The name of the connection pool.\n    *\n    * @return the name of the connection pool\n    */\n   String getPoolName();\n\n   /**\n    * Get the default catalog name to be set on connections.\n    *\n    * @return the default catalog name\n    */\n   String getCatalog();\n\n   /**\n    * Set the default catalog name to be set on connections.\n    * <p>\n    * WARNING: THIS VALUE SHOULD ONLY BE CHANGED WHILE THE POOL IS SUSPENDED, AFTER CONNECTIONS HAVE BEEN EVICTED.\n    *\n    * @param catalog the catalog name, or null\n    */\n   void setCatalog(String catalog);\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/HikariCredentialsProvider.java",
    "content": "/*\n * Copyright (C) 2025 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari;\n\nimport com.zaxxer.hikari.util.Credentials;\n\n/**\n * Users can implement this interface to provide credentials for HikariCP.\n * This is useful when credentials need to be dynamically generated or retrieved\n * at runtime, rather than being hardcoded in the configuration.\n */\npublic interface HikariCredentialsProvider {\n      /**\n      * This method is called to retrieve the credentials for HikariCP.\n      *\n      * @return a {@link Credentials} object containing the username and password\n      */\n   Credentials getCredentials();\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/HikariDataSource.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari;\n\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.pool.HikariPool;\nimport com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.sql.DataSource;\nimport java.io.Closeable;\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static com.zaxxer.hikari.pool.HikariPool.POOL_NORMAL;\n\n/**\n * The HikariCP pooled DataSource.\n *\n * @author Brett Wooldridge\n */\npublic class HikariDataSource extends HikariConfig implements DataSource, Closeable\n{\n   private static final Logger LOGGER = LoggerFactory.getLogger(HikariDataSource.class);\n\n   private final AtomicBoolean isShutdown = new AtomicBoolean();\n\n   private final HikariPool fastPathPool;\n   private volatile HikariPool pool;\n\n   /**\n    * Default constructor.  Setters are used to configure the pool.  Using\n    * this constructor vs. {@link #HikariDataSource(HikariConfig)} will\n    * result in {@link #getConnection()} performance that is slightly lower\n    * due to lazy initialization checks.\n    *\n    * The first call to {@link #getConnection()} starts the pool.  Once the pool\n    * is started, the configuration is \"sealed\" and no further configuration\n    * changes are possible -- except via {@link HikariConfigMXBean} methods.\n    */\n   public HikariDataSource()\n   {\n      fastPathPool = null;\n   }\n\n   /**\n    * Construct a HikariDataSource with the specified configuration.  The\n    * {@link HikariConfig} is copied and the pool is started by invoking this\n    * constructor.\n    *\n    * The {@link HikariConfig} can be modified without affecting the HikariDataSource\n    * and used to initialize another HikariDataSource instance.\n    *\n    * @param configuration a HikariConfig instance\n    */\n   public HikariDataSource(HikariConfig configuration)\n   {\n      configuration.validate();\n      configuration.copyStateTo(this);\n\n      LOGGER.info(\"{} - Starting...\", configuration.getPoolName());\n      pool = fastPathPool = new HikariPool(this);\n      LOGGER.info(\"{} - Start completed.\", configuration.getPoolName());\n\n      this.seal();\n   }\n\n   // ***********************************************************************\n   //                          DataSource methods\n   // ***********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public Connection getConnection() throws SQLException\n   {\n      if (isClosed()) {\n         throw new SQLException(\"HikariDataSource \" + this + \" has been closed.\");\n      }\n\n      if (fastPathPool != null) {\n         return fastPathPool.getConnection();\n      }\n\n      // See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java\n      HikariPool result = pool;\n      if (result == null) {\n         synchronized (this) {\n            result = pool;\n            if (result == null) {\n               validate();\n               LOGGER.info(\"{} - Starting...\", getPoolName());\n               try {\n                  pool = result = new HikariPool(this);\n                  this.seal();\n               }\n               catch (PoolInitializationException pie) {\n                  if (pie.getCause() instanceof SQLException) {\n                     throw (SQLException) pie.getCause();\n                  }\n                  else {\n                     throw pie;\n                  }\n               }\n               LOGGER.info(\"{} - Start completed.\", getPoolName());\n            }\n         }\n      }\n\n      return result.getConnection();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Connection getConnection(String username, String password) throws SQLException\n   {\n      throw new SQLFeatureNotSupportedException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PrintWriter getLogWriter() throws SQLException\n   {\n      HikariPool p = pool;\n      return (p != null ? p.getUnwrappedDataSource().getLogWriter() : null);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setLogWriter(PrintWriter out) throws SQLException\n   {\n      var p = pool;\n      if (p != null) {\n         p.getUnwrappedDataSource().setLogWriter(out);\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setLoginTimeout(int seconds) throws SQLException\n   {\n      var p = pool;\n      if (p != null) {\n         p.getUnwrappedDataSource().setLoginTimeout(seconds);\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getLoginTimeout() throws SQLException\n   {\n      var p = pool;\n      return (p != null ? p.getUnwrappedDataSource().getLoginTimeout() : 0);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException\n   {\n      throw new SQLFeatureNotSupportedException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   @SuppressWarnings(\"unchecked\")\n   public <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      if (iface.isInstance(this)) {\n         return (T) this;\n      }\n\n      var p = pool;\n      if (p != null) {\n         final var unwrappedDataSource = p.getUnwrappedDataSource();\n         if (iface.isInstance(unwrappedDataSource)) {\n            return (T) unwrappedDataSource;\n         }\n\n         if (unwrappedDataSource != null) {\n            return unwrappedDataSource.unwrap(iface);\n         }\n      }\n\n      throw new SQLException(\"Wrapped DataSource is not an instance of \" + iface);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      if (iface.isInstance(this)) {\n         return true;\n      }\n\n      var p = pool;\n      if (p != null) {\n         final var unwrappedDataSource = p.getUnwrappedDataSource();\n         if (iface.isInstance(unwrappedDataSource)) {\n            return true;\n         }\n\n         if (unwrappedDataSource != null) {\n            return unwrappedDataSource.isWrapperFor(iface);\n         }\n      }\n\n      return false;\n   }\n\n   // ***********************************************************************\n   //                        HikariConfigMXBean methods\n   // ***********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public void setMetricRegistry(Object metricRegistry)\n   {\n      var isAlreadySet = getMetricRegistry() != null;\n      super.setMetricRegistry(metricRegistry);\n\n      var p = pool;\n      if (p != null) {\n         if (isAlreadySet) {\n            throw new IllegalStateException(\"MetricRegistry can only be set one time\");\n         }\n         else {\n            p.setMetricRegistry(super.getMetricRegistry());\n         }\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setMetricsTrackerFactory(MetricsTrackerFactory metricsTrackerFactory)\n   {\n      var isAlreadySet = getMetricsTrackerFactory() != null;\n      super.setMetricsTrackerFactory(metricsTrackerFactory);\n\n      var p = pool;\n      if (p != null) {\n         if (isAlreadySet) {\n            throw new IllegalStateException(\"MetricsTrackerFactory can only be set one time\");\n         }\n         else {\n            p.setMetricsTrackerFactory(super.getMetricsTrackerFactory());\n         }\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setHealthCheckRegistry(Object healthCheckRegistry)\n   {\n      var isAlreadySet = getHealthCheckRegistry() != null;\n      super.setHealthCheckRegistry(healthCheckRegistry);\n\n      var p = pool;\n      if (p != null) {\n         if (isAlreadySet) {\n            throw new IllegalStateException(\"HealthCheckRegistry can only be set one time\");\n         }\n         else {\n            p.setHealthCheckRegistry(super.getHealthCheckRegistry());\n         }\n      }\n   }\n\n   // ***********************************************************************\n   //                        HikariCP-specific methods\n   // ***********************************************************************\n\n   /**\n    * Returns {@code true} if the pool as been started and is not suspended or shutdown.\n    *\n    * @return {@code true} if the pool as been started and is not suspended or shutdown.\n    */\n   public boolean isRunning()\n   {\n      return pool != null && pool.poolState == POOL_NORMAL;\n   }\n\n   /**\n    * Get the {@code HikariPoolMXBean} for this HikariDataSource instance.  If this method is called on\n    * a {@code HikariDataSource} that has been constructed without a {@code HikariConfig} instance,\n    * and before an initial call to {@code #getConnection()}, the return value will be {@code null}.\n    *\n    * @return the {@code HikariPoolMXBean} instance, or {@code null}.\n    */\n   public HikariPoolMXBean getHikariPoolMXBean()\n   {\n      return pool;\n   }\n\n   /**\n    * Get the {@code HikariConfigMXBean} for this HikariDataSource instance.\n    *\n    * @return the {@code HikariConfigMXBean} instance.\n    */\n   public HikariConfigMXBean getHikariConfigMXBean()\n   {\n      return this;\n   }\n\n   /**\n    * Evict a connection from the pool.  If the connection has already been closed (returned to the pool)\n    * this may result in a \"soft\" eviction; the connection will be evicted sometime in the future if it is\n    * currently in use.  If the connection has not been closed, the eviction is immediate.\n    *\n    * @param connection the connection to evict from the pool\n    */\n   public void evictConnection(Connection connection)\n   {\n      HikariPool p;\n      if (!isClosed() && (p = pool) != null && connection.getClass().getName().startsWith(\"com.zaxxer.hikari\")) {\n         p.evictConnection(connection);\n      }\n   }\n\n   /**\n    * Shutdown the DataSource and its associated pool.\n    */\n   @Override\n   public void close()\n   {\n      if (isShutdown.getAndSet(true)) {\n         return;\n      }\n\n      var p = pool;\n      if (p != null) {\n         try {\n            LOGGER.info(\"{} - Shutdown initiated...\", getPoolName());\n            p.shutdown();\n            LOGGER.info(\"{} - Shutdown completed.\", getPoolName());\n         }\n         catch (InterruptedException e) {\n            LOGGER.warn(\"{} - Interrupted during closing\", getPoolName(), e);\n            Thread.currentThread().interrupt();\n         }\n      }\n   }\n\n   /**\n    * Determine whether the HikariDataSource has been closed.\n    *\n    * @return true if the HikariDataSource has been closed, false otherwise\n    */\n   public boolean isClosed()\n   {\n      return isShutdown.get();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String toString()\n   {\n      return \"HikariDataSource (\" + pool + \")\";\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/HikariJNDIFactory.java",
    "content": "/*\n * Copyright (C) 2013,2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari;\n\nimport com.zaxxer.hikari.util.PropertyElf;\n\nimport javax.naming.*;\nimport javax.naming.spi.ObjectFactory;\nimport javax.sql.DataSource;\nimport java.util.Hashtable;\nimport java.util.Properties;\n\n/**\n * A JNDI factory that produces HikariDataSource instances.\n *\n * @author Brett Wooldridge\n */\npublic class HikariJNDIFactory implements ObjectFactory\n{\n   @Override\n   synchronized public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception\n   {\n      // We only know how to deal with <code>javax.naming.Reference</code> that specify a class name of \"javax.sql.DataSource\"\n      if (obj instanceof Reference && \"javax.sql.DataSource\".equals(((Reference) obj).getClassName())) {\n         var ref = (Reference) obj;\n         var hikariPropSet = PropertyElf.getPropertyNames(HikariConfig.class);\n\n         var properties = new Properties();\n         var enumeration = ref.getAll();\n         while (enumeration.hasMoreElements()) {\n            var element = enumeration.nextElement();\n            var type = element.getType();\n            if (type.startsWith(\"dataSource.\") || hikariPropSet.contains(type)) {\n               properties.setProperty(type, element.getContent().toString());\n            }\n         }\n         return createDataSource(properties, nameCtx);\n      }\n      return null;\n   }\n\n   private DataSource createDataSource(final Properties properties, final Context context) throws NamingException\n   {\n      var jndiName = properties.getProperty(\"dataSourceJNDI\");\n      if (jndiName != null) {\n         return lookupJndiDataSource(properties, context, jndiName);\n      }\n\n      return new HikariDataSource(new HikariConfig(properties));\n   }\n\n   private DataSource lookupJndiDataSource(final Properties properties, final Context context, final String jndiName) throws NamingException\n   {\n      if (context == null) {\n         throw new RuntimeException(\"JNDI context does not found for dataSourceJNDI : \" + jndiName);\n      }\n\n      var jndiDS = (DataSource) context.lookup(jndiName);\n      if (jndiDS == null) {\n         final var ic = new InitialContext();\n         jndiDS = (DataSource) ic.lookup(jndiName);\n         ic.close();\n      }\n\n      if (jndiDS != null) {\n         var config = new HikariConfig(properties);\n         config.setDataSource(jndiDS);\n         return new HikariDataSource(config);\n      }\n\n      return null;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/HikariPoolMXBean.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari;\n\nimport javax.sql.DataSource;\n\n/**\n * The javax.management MBean for a Hikari pool instance.\n *\n * @author Brett Wooldridge\n */\npublic interface HikariPoolMXBean\n{\n   /**\n    * Get the number of currently idle connections in the pool.\n    * <p>\n    * The return value is extremely transient and is a point-in-time measurement.  Therefore, due to a time\n    * difference between invoking this method and {@link #getActiveConnections()}, it is possible for the sum\n    * of idle plus active connections to be either less than or greater than the value returned by\n    * {@link #getTotalConnections()}.\n    *\n    * @return the current number of idle connections in the pool\n    */\n   int getIdleConnections();\n\n   /**\n    * Get the number of currently active connections in the pool.\n    * <p>\n    * The return value is extremely transient and is a point-in-time measurement.  Therefore, due to a time\n    * difference between invoking this method and {@link #getIdleConnections()}, it is possible for the sum\n    * of idle plus active connections to be either less than or greater than the value returned by\n    * {@link #getTotalConnections()}.\n    *\n    * @return the current number of active (in-use) connections in the pool\n    */\n   int getActiveConnections();\n\n   /**\n    * Get the total number of connections currently in the pool.  The return value is transient and is a\n    * point-in-time measurement.\n    *\n    * @return the total number of connections in the pool\n    */\n   int getTotalConnections();\n\n   /**\n    * Get the number of threads awaiting connections from the pool.  The return value is extremely transient and is\n    * a point-in-time measurement.\n    *\n    * @return the number of threads awaiting a connection from the pool\n    */\n   int getThreadsAwaitingConnection();\n\n   /**\n    * Evict currently idle connections from the pool, and mark active (in-use) connections for eviction when they are\n    * returned to the pool.\n    */\n   void softEvictConnections();\n\n   /**\n    * Suspend the pool.  When the pool is suspended, threads calling {@link DataSource#getConnection()} will be\n    * blocked <i>with no timeout</i> until the pool is resumed via the {@link #resumePool()} method.\n    * <br>\n    * This method has no effect unless the {@link HikariConfig#setAllowPoolSuspension(boolean)} method or equivalent\n    * property has been set to {@code true}.\n    */\n   void suspendPool();\n\n   /**\n    * Resume the pool.  Enables connection borrowing to resume on a pool that has been suspended via the\n    * {@link #suspendPool()} method.\n    * <br>\n    * This method has no effect unless the {@link HikariConfig#setAllowPoolSuspension(boolean)} method or equivalent\n    * property has been set to {@code true}.\n    */\n   void resumePool();\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/SQLExceptionOverride.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari;\n\nimport java.sql.SQLException;\n\n/**\n * Users can implement this interface to override the default SQLException handling\n * of HikariCP. When a SQLException is thrown from JDBC execution methods, the\n * SQLState and error code will be checked to determine if the connection should\n * be evicted from the pool.\n * <p>\n * By supplying an implementation of this interface, users can override the default\n * handling of SQLExceptions. The {@link #adjudicate(SQLException)} method will be called\n * with the SQLException that was thrown. If the method returns {@link Override#CONTINUE_EVICT}\n * the customary built-in handling will occur. If the method returns {@link Override#DO_NOT_EVICT}\n * the eviction will be elided. If the method returns {@link Override#MUST_EVICT} the eviction will\n * be evicted regardless of the SQLState or error code.\n */\npublic interface SQLExceptionOverride {\n   enum Override {\n      CONTINUE_EVICT,\n      DO_NOT_EVICT,\n      MUST_EVICT\n   }\n\n   /**\n    * This method is called when a SQLException is thrown from a JDBC method.\n    *\n    * @param sqlException the SQLException that was thrown\n    * @return an {@link Override} value indicating how eviction should proceed\n    */\n   default Override adjudicate(final SQLException sqlException)\n   {\n      return Override.CONTINUE_EVICT;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/hibernate/HikariConfigurationUtil.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.hibernate;\n\nimport java.util.Map;\nimport java.util.Properties;\n\nimport org.hibernate.cfg.AvailableSettings;\n\nimport com.zaxxer.hikari.HikariConfig;\n\n/**\n * Utility class to map Hibernate properties to HikariCP configuration properties.\n *\n * @author Brett Wooldridge, Luca Burgazzoli\n */\npublic class HikariConfigurationUtil\n{\n   public static final String CONFIG_PREFIX = \"hibernate.hikari.\";\n   public static final String CONFIG_PREFIX_DATASOURCE = \"hibernate.hikari.dataSource.\";\n\n   /**\n    * Create/load a HikariConfig from Hibernate properties.\n    *\n    * @param props a map of Hibernate properties\n    * @return a HikariConfig\n    */\n   @SuppressWarnings(\"rawtypes\")\n   public static HikariConfig loadConfiguration(Map props)\n   {\n      Properties hikariProps = new Properties();\n      copyProperty(AvailableSettings.ISOLATION, props, \"transactionIsolation\", hikariProps);\n      copyProperty(AvailableSettings.AUTOCOMMIT, props, \"autoCommit\", hikariProps);\n      copyProperty(AvailableSettings.DRIVER, props, \"driverClassName\", hikariProps);\n      copyProperty(AvailableSettings.URL, props, \"jdbcUrl\", hikariProps);\n      copyProperty(AvailableSettings.USER, props, \"username\", hikariProps);\n      copyProperty(AvailableSettings.PASS, props, \"password\", hikariProps);\n\n      for (Object keyo : props.keySet()) {\n         String key = (String) keyo;\n         if (key.startsWith(CONFIG_PREFIX)) {\n            hikariProps.setProperty(key.substring(CONFIG_PREFIX.length()), (String) props.get(key));\n         }\n      }\n\n      return new HikariConfig(hikariProps);\n   }\n\n   @SuppressWarnings(\"rawtypes\")\n   private static void copyProperty(String srcKey, Map src, String dstKey, Properties dst)\n   {\n      if (src.containsKey(srcKey)) {\n         dst.setProperty(dstKey, (String) src.get(srcKey));\n      }\n   }\n}"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/hibernate/HikariConnectionProvider.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.hibernate;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Map;\n\nimport org.hibernate.HibernateException;\nimport org.hibernate.Version;\nimport org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;\nimport org.hibernate.service.UnknownUnwrapTypeException;\nimport org.hibernate.service.spi.Configurable;\nimport org.hibernate.service.spi.Stoppable;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\n\nimport javax.sql.DataSource;\n\n/**\n * Connection provider for Hibernate 4.3.\n *\n * @author Brett Wooldridge, Luca Burgazzoli\n */\npublic class HikariConnectionProvider implements ConnectionProvider, Configurable, Stoppable\n{\n   private static final long serialVersionUID = -9131625057941275711L;\n\n   private static final Logger LOGGER = LoggerFactory.getLogger(HikariConnectionProvider.class);\n\n   /**\n    * HikariCP configuration.\n    */\n   private HikariConfig hcfg;\n\n   /**\n    * HikariCP data source.\n    */\n   private HikariDataSource hds;\n\n   // *************************************************************************\n   //\n   // *************************************************************************\n\n   /**\n    * c-tor\n    */\n   public HikariConnectionProvider()\n   {\n      this.hcfg = null;\n      this.hds = null;\n      if (Version.getVersionString().substring(0, 5).compareTo(\"4.3.6\") >= 1) {\n         LOGGER.warn(\"com.zaxxer.hikari.hibernate.HikariConnectionProvider has been deprecated for versions of \"\n                     + \"Hibernate 4.3.6 and newer.  Please switch to org.hibernate.hikaricp.internal.HikariCPConnectionProvider.\");\n      }\n   }\n\n   // *************************************************************************\n   // Configurable\n   // *************************************************************************\n\n   @SuppressWarnings(\"rawtypes\")\n   @Override\n   public void configure(Map props) throws HibernateException\n   {\n      try {\n         LOGGER.debug(\"Configuring HikariCP\");\n\n         this.hcfg = HikariConfigurationUtil.loadConfiguration(props);\n         this.hds = new HikariDataSource(this.hcfg);\n\n      }\n      catch (Exception e) {\n         throw new HibernateException(e);\n      }\n\n      LOGGER.debug(\"HikariCP Configured\");\n   }\n\n   // *************************************************************************\n   // ConnectionProvider\n   // *************************************************************************\n\n   @Override\n   public Connection getConnection() throws SQLException\n   {\n      Connection conn = null;\n      if (this.hds != null) {\n         conn = this.hds.getConnection();\n      }\n\n      return conn;\n   }\n\n   @Override\n   public void closeConnection(Connection conn) throws SQLException\n   {\n      conn.close();\n   }\n\n   @Override\n   public boolean supportsAggressiveRelease()\n   {\n      return false;\n   }\n\n   @Override\n   @SuppressWarnings(\"rawtypes\")\n   public boolean isUnwrappableAs(Class unwrapType)\n   {\n      return ConnectionProvider.class.equals(unwrapType) || HikariConnectionProvider.class.isAssignableFrom(unwrapType);\n   }\n\n   @Override\n   @SuppressWarnings(\"unchecked\")\n   public <T> T unwrap(Class<T> unwrapType)\n   {\n       if ( ConnectionProvider.class.equals( unwrapType ) ||\n               HikariConnectionProvider.class.isAssignableFrom( unwrapType ) ) {\n           return (T) this;\n       }\n       else if ( DataSource.class.isAssignableFrom( unwrapType ) ) {\n           return (T) this.hds;\n       }\n       else {\n           throw new UnknownUnwrapTypeException( unwrapType );\n       }\n   }\n\n   // *************************************************************************\n   // Stoppable\n   // *************************************************************************\n\n   @Override\n   public void stop()\n   {\n      this.hds.close();\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java",
    "content": "/*\n * Copyright (C) 2017 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics;\n\n/**\n * @author Brett Wooldridge\n */\npublic interface IMetricsTracker extends AutoCloseable\n{\n   default void recordConnectionCreatedMillis(long connectionCreatedMillis) {}\n\n   default void recordConnectionAcquiredNanos(final long elapsedAcquiredNanos) {}\n\n   default void recordConnectionUsageMillis(final long elapsedBorrowedMillis) {}\n\n   default void recordConnectionTimeout() {}\n\n   @Override\n   default void close() {}\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java",
    "content": "/*\n * Copyright (C) 2013,2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics;\n\n/**\n * This class only supports realtime, not historical metrics.\n *\n * @author Brett Wooldridge\n */\n@Deprecated\npublic class MetricsTracker implements IMetricsTracker\n{\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/MetricsTrackerFactory.java",
    "content": "/*\n * Copyright (C) 2013,2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics;\n\npublic interface MetricsTrackerFactory\n{\n   /**\n    * Create an instance of an IMetricsTracker.\n    *\n    * @param poolName the name of the pool\n    * @param poolStats a PoolStats instance to use\n    * @return a IMetricsTracker implementation instance\n    */\n   IMetricsTracker create(String poolName, PoolStats poolStats);\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/PoolStats.java",
    "content": "/*\n * Copyright (C) 2015 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics;\n\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\nimport static com.zaxxer.hikari.util.ClockSource.plusMillis;\n\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n *\n * @author Brett Wooldridge\n */\npublic abstract class PoolStats\n{\n   private final AtomicLong reloadAt;\n   private final long timeoutMs;\n\n   protected volatile int totalConnections;\n   protected volatile int idleConnections;\n   protected volatile int activeConnections;\n   protected volatile int pendingThreads;\n   protected volatile int maxConnections;\n   protected volatile int minConnections;\n\n   public PoolStats(final long timeoutMs)\n   {\n      this.timeoutMs = timeoutMs;\n      this.reloadAt = new AtomicLong();\n   }\n\n   public int getTotalConnections()\n   {\n      if (shouldLoad()) {\n         update();\n      }\n\n      return totalConnections;\n   }\n\n   public int getIdleConnections()\n   {\n      if (shouldLoad()) {\n         update();\n      }\n\n      return idleConnections;\n   }\n\n   public int getActiveConnections()\n   {\n      if (shouldLoad()) {\n         update();\n      }\n\n      return activeConnections;\n   }\n\n   public int getPendingThreads()\n   {\n      if (shouldLoad()) {\n         update();\n      }\n\n      return pendingThreads;\n   }\n\n   public int getMaxConnections() {\n      if (shouldLoad()) {\n         update();\n      }\n\n      return maxConnections;\n   }\n\n   public int getMinConnections() {\n      if (shouldLoad()) {\n         update();\n      }\n\n      return minConnections;\n   }\n\n   protected abstract void update();\n\n   private boolean shouldLoad()\n   {\n      for (; ; ) {\n          final var now = currentTime();\n          final var reloadTime = reloadAt.get();\n          if (reloadTime > now) {\n              return false;\n          }\n          else if (reloadAt.compareAndSet(reloadTime, plusMillis(now, timeoutMs))) {\n              return true;\n          }\n      }\n  }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/dropwizard/CodaHaleMetricsTracker.java",
    "content": "/*\n * Copyright (C) 2013,2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.dropwizard;\n\nimport java.util.concurrent.TimeUnit;\n\nimport com.codahale.metrics.Gauge;\nimport com.codahale.metrics.Histogram;\nimport com.codahale.metrics.Meter;\nimport com.codahale.metrics.MetricRegistry;\nimport com.codahale.metrics.Timer;\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.PoolStats;\n\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_CATEGORY;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_ACTIVE_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_CONNECT;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_IDLE_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_MAX_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_MIN_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_PENDING_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_TIMEOUT_RATE;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_TOTAL_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_USAGE;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_WAIT;\n\npublic final class CodaHaleMetricsTracker implements IMetricsTracker\n{\n   private final String poolName;\n   private final Timer connectionObtainTimer;\n   private final Histogram connectionUsage;\n   private final Histogram connectionCreation;\n   private final Meter connectionTimeoutMeter;\n   private final MetricRegistry registry;\n\n   CodaHaleMetricsTracker(final String poolName, final PoolStats poolStats, final MetricRegistry registry)\n   {\n      this.poolName = poolName;\n      this.registry = registry;\n      this.connectionObtainTimer = registry.timer(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_WAIT));\n      this.connectionUsage = registry.histogram(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_USAGE));\n      this.connectionCreation = registry.histogram(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_CONNECT));\n      this.connectionTimeoutMeter = registry.meter(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TIMEOUT_RATE));\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TOTAL_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getTotalConnections);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_IDLE_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getIdleConnections);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_ACTIVE_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getActiveConnections);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_PENDING_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getPendingThreads);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MAX_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getMaxConnections);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MIN_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getMinConnections);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void close()\n   {\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_WAIT));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_USAGE));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_CONNECT));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TIMEOUT_RATE));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TOTAL_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_IDLE_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_ACTIVE_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_PENDING_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MAX_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MIN_CONNECTIONS));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void recordConnectionAcquiredNanos(final long elapsedAcquiredNanos)\n   {\n      connectionObtainTimer.update(elapsedAcquiredNanos, TimeUnit.NANOSECONDS);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void recordConnectionUsageMillis(final long elapsedBorrowedMillis)\n   {\n      connectionUsage.update(elapsedBorrowedMillis);\n   }\n\n   @Override\n   public void recordConnectionTimeout()\n   {\n      connectionTimeoutMeter.mark();\n   }\n\n   @Override\n   public void recordConnectionCreatedMillis(long connectionCreatedMillis)\n   {\n      connectionCreation.update(connectionCreatedMillis);\n   }\n\n   public Timer getConnectionAcquisitionTimer()\n   {\n      return connectionObtainTimer;\n   }\n\n   public Histogram getConnectionDurationHistogram()\n   {\n      return connectionUsage;\n   }\n\n   public Histogram getConnectionCreationHistogram()\n   {\n      return connectionCreation;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/dropwizard/CodahaleHealthChecker.java",
    "content": "/*\n * Copyright (C) 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.dropwizard;\n\nimport com.codahale.metrics.MetricRegistry;\nimport com.codahale.metrics.Timer;\nimport com.codahale.metrics.health.HealthCheck;\nimport com.codahale.metrics.health.HealthCheckRegistry;\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.pool.HikariPool;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Provides Dropwizard HealthChecks.  Two health checks are provided:\n * <ul>\n *   <li>ConnectivityCheck</li>\n *   <li>Connection99Percent</li>\n * </ul>\n * The ConnectivityCheck will use the <code>connectionTimeout</code>, unless the health check property\n * <code>connectivityCheckTimeoutMs</code> is defined.  However, if either the <code>connectionTimeout</code>\n * or the <code>connectivityCheckTimeoutMs</code> is 0 (infinite), a timeout of 10 seconds will be used.\n * <p>\n * The Connection99Percent health check will only be registered if the health check property\n * <code>expected99thPercentileMs</code> is defined and greater than 0.\n *\n * @author Brett Wooldridge\n */\npublic final class CodahaleHealthChecker\n{\n   /**\n    * Register Dropwizard health checks.\n    *\n    * @param pool the pool to register health checks for\n    * @param hikariConfig the pool configuration\n    * @param registry the HealthCheckRegistry into which checks will be registered\n    */\n   public static void registerHealthChecks(final HikariPool pool, final HikariConfig hikariConfig, final HealthCheckRegistry registry)\n   {\n      final var healthCheckProperties = hikariConfig.getHealthCheckProperties();\n\n      final var checkTimeoutMs = Long.parseLong(healthCheckProperties.getProperty(\"connectivityCheckTimeoutMs\", String.valueOf(hikariConfig.getConnectionTimeout())));\n      registry.register(MetricRegistry.name(hikariConfig.getPoolName(), \"pool\", \"ConnectivityCheck\"), new ConnectivityHealthCheck(pool, checkTimeoutMs));\n\n      final var expected99thPercentile = Long.parseLong(healthCheckProperties.getProperty(\"expected99thPercentileMs\", \"0\"));\n\n      final Object metricRegistryObj = hikariConfig.getMetricRegistry();\n\n      if (expected99thPercentile > 0 && metricRegistryObj instanceof MetricRegistry) {\n         final var metricRegistry = (MetricRegistry) metricRegistryObj;\n         var timers = metricRegistry.getTimers((name, metric) -> name.equals(MetricRegistry.name(hikariConfig.getPoolName(), \"pool\", \"Wait\")));\n\n         if (!timers.isEmpty()) {\n            final var timer = timers.entrySet().iterator().next().getValue();\n            registry.register(MetricRegistry.name(hikariConfig.getPoolName(), \"pool\", \"Connection99Percent\"), new Connection99Percent(timer, expected99thPercentile));\n         }\n      }\n   }\n\n   private CodahaleHealthChecker()\n   {\n      // private constructor\n   }\n\n   private static class ConnectivityHealthCheck extends HealthCheck\n   {\n      private final HikariPool pool;\n      private final long checkTimeoutMs;\n\n      ConnectivityHealthCheck(final HikariPool pool, final long checkTimeoutMs)\n      {\n         this.pool = pool;\n         this.checkTimeoutMs = (checkTimeoutMs > 0 && checkTimeoutMs != Integer.MAX_VALUE ? checkTimeoutMs : TimeUnit.SECONDS.toMillis(10));\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      protected Result check() throws Exception\n      {\n         try (Connection connection = pool.getConnection(checkTimeoutMs)) {\n            return Result.healthy();\n         }\n         catch (SQLException e) {\n            return Result.unhealthy(e);\n         }\n      }\n   }\n\n   private static class Connection99Percent extends HealthCheck\n   {\n      private final Timer waitTimer;\n      private final long expected99thPercentile;\n\n      Connection99Percent(final Timer waitTimer, final long expected99thPercentile)\n      {\n         this.waitTimer = waitTimer;\n         this.expected99thPercentile = expected99thPercentile;\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      protected Result check() throws Exception\n      {\n         final long the99thPercentile = TimeUnit.NANOSECONDS.toMillis(Math.round(waitTimer.getSnapshot().get99thPercentile()));\n         return the99thPercentile <= expected99thPercentile ? Result.healthy() : Result.unhealthy(\"99th percentile connection wait time of %dms exceeds the threshold %dms\", the99thPercentile, expected99thPercentile);\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/dropwizard/CodahaleMetricsTrackerFactory.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.dropwizard;\n\nimport com.codahale.metrics.MetricRegistry;\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.PoolStats;\n\npublic final class CodahaleMetricsTrackerFactory implements MetricsTrackerFactory\n{\n   private final MetricRegistry registry;\n\n   public CodahaleMetricsTrackerFactory(MetricRegistry registry)\n   {\n      this.registry = registry;\n   }\n\n   public MetricRegistry getRegistry()\n   {\n      return registry;\n   }\n\n   @Override\n   public IMetricsTracker create(String poolName, PoolStats poolStats)\n   {\n      return new CodaHaleMetricsTracker(poolName, poolStats, registry);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTracker.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.dropwizard;\n\nimport java.util.concurrent.TimeUnit;\n\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport io.dropwizard.metrics5.Gauge;\nimport io.dropwizard.metrics5.Histogram;\nimport io.dropwizard.metrics5.Meter;\nimport io.dropwizard.metrics5.MetricRegistry;\nimport io.dropwizard.metrics5.Timer;\n\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_CATEGORY;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_ACTIVE_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_CONNECT;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_IDLE_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_MAX_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_MIN_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_PENDING_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_TIMEOUT_RATE;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_TOTAL_CONNECTIONS;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_USAGE;\nimport static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_WAIT;\n\npublic class Dropwizard5MetricsTracker implements IMetricsTracker\n{\n   private final String poolName;\n   private final Timer connectionObtainTimer;\n   private final Histogram connectionUsage;\n   private final Histogram connectionCreation;\n   private final Meter connectionTimeoutMeter;\n   private final MetricRegistry registry;\n\n   Dropwizard5MetricsTracker(final String poolName, final PoolStats poolStats, final MetricRegistry registry)\n   {\n      this.poolName = poolName;\n      this.registry = registry;\n      this.connectionObtainTimer = registry.timer(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_WAIT));\n      this.connectionUsage = registry.histogram(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_USAGE));\n      this.connectionCreation = registry.histogram(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_CONNECT));\n      this.connectionTimeoutMeter = registry.meter(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TIMEOUT_RATE));\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TOTAL_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getTotalConnections);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_IDLE_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getIdleConnections);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_ACTIVE_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getActiveConnections);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_PENDING_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getPendingThreads);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MAX_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getMaxConnections);\n\n      registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MIN_CONNECTIONS),\n         (Gauge<Integer>) poolStats::getMinConnections);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void close()\n   {\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_WAIT));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_USAGE));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_CONNECT));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TIMEOUT_RATE));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TOTAL_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_IDLE_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_ACTIVE_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_PENDING_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MAX_CONNECTIONS));\n      registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MIN_CONNECTIONS));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void recordConnectionAcquiredNanos(final long elapsedAcquiredNanos)\n   {\n      connectionObtainTimer.update(elapsedAcquiredNanos, TimeUnit.NANOSECONDS);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void recordConnectionUsageMillis(final long elapsedBorrowedMillis)\n   {\n      connectionUsage.update(elapsedBorrowedMillis);\n   }\n\n   @Override\n   public void recordConnectionTimeout()\n   {\n      connectionTimeoutMeter.mark();\n   }\n\n   @Override\n   public void recordConnectionCreatedMillis(final long connectionCreatedMillis)\n   {\n      connectionCreation.update(connectionCreatedMillis);\n   }\n\n   public Timer getConnectionAcquisitionTimer()\n   {\n      return connectionObtainTimer;\n   }\n\n   public Histogram getConnectionDurationHistogram()\n   {\n      return connectionUsage;\n   }\n\n   public Histogram getConnectionCreationHistogram()\n   {\n      return connectionCreation;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerFactory.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.dropwizard;\n\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport io.dropwizard.metrics5.MetricRegistry;\n\npublic class Dropwizard5MetricsTrackerFactory implements MetricsTrackerFactory\n{\n   private final MetricRegistry registry;\n\n   public Dropwizard5MetricsTrackerFactory(final MetricRegistry registry)\n   {\n      this.registry = registry;\n   }\n\n   public MetricRegistry getRegistry()\n   {\n      return registry;\n   }\n\n   @Override\n   public IMetricsTracker create(final String poolName, final PoolStats poolStats)\n   {\n      return new Dropwizard5MetricsTracker(poolName, poolStats, registry);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/dropwizard/DropwizardCommon.java",
    "content": "/*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.dropwizard;\n\nfinal class DropwizardCommon {\n   private DropwizardCommon()\n   {\n   }\n\n   static final String METRIC_CATEGORY = \"pool\";\n   static final String METRIC_NAME_WAIT = \"Wait\";\n   static final String METRIC_NAME_USAGE = \"Usage\";\n   static final String METRIC_NAME_CONNECT = \"ConnectionCreation\";\n   static final String METRIC_NAME_TIMEOUT_RATE = \"ConnectionTimeoutRate\";\n   static final String METRIC_NAME_TOTAL_CONNECTIONS = \"TotalConnections\";\n   static final String METRIC_NAME_IDLE_CONNECTIONS = \"IdleConnections\";\n   static final String METRIC_NAME_ACTIVE_CONNECTIONS = \"ActiveConnections\";\n   static final String METRIC_NAME_PENDING_CONNECTIONS = \"PendingConnections\";\n   static final String METRIC_NAME_MAX_CONNECTIONS = \"MaxConnections\";\n   static final String METRIC_NAME_MIN_CONNECTIONS = \"MinConnections\";\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/micrometer/MicrometerMetricsTracker.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.micrometer;\n\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport io.micrometer.core.instrument.Counter;\nimport io.micrometer.core.instrument.Gauge;\nimport io.micrometer.core.instrument.MeterRegistry;\nimport io.micrometer.core.instrument.Timer;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * {@link IMetricsTracker Metrics tracker} for Micrometer.\n * HikariCP metrics can be configured in your application by applying a\n * {@link io.micrometer.core.instrument.config.MeterFilter MeterFilter} to metrics starting with\n * {@link #HIKARI_METRIC_NAME_PREFIX}. For example, to configure client-side calculated percentiles:\n *\n * <blockquote><pre>\n *     new MeterFilter() {\n *       &#064;Override\n *       public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {\n *         if (id.getName().startsWith(MicrometerMetricsTracker.HIKARI_METRIC_NAME_PREFIX)) {\n *           return DistributionStatisticConfig.builder()\n *               .percentiles(0.5, 0.95)\n *               .build()\n *               .merge(config);\n *            }\n *         return config;\n *         }\n *      };\n * </pre></blockquote>\n */\n@SuppressWarnings(\"ALL\")\npublic class MicrometerMetricsTracker implements IMetricsTracker\n{\n   /** Prefix used for all HikariCP metric names. */\n   public static final String HIKARI_METRIC_NAME_PREFIX = \"hikaricp\";\n\n   private static final String METRIC_CATEGORY = \"pool\";\n   private static final String METRIC_NAME_WAIT = HIKARI_METRIC_NAME_PREFIX + \".connections.acquire\";\n   private static final String METRIC_NAME_USAGE = HIKARI_METRIC_NAME_PREFIX + \".connections.usage\";\n   private static final String METRIC_NAME_CONNECT = HIKARI_METRIC_NAME_PREFIX + \".connections.creation\";\n\n   private static final String METRIC_NAME_TIMEOUT_RATE = HIKARI_METRIC_NAME_PREFIX + \".connections.timeout\";\n   private static final String METRIC_NAME_TOTAL_CONNECTIONS = HIKARI_METRIC_NAME_PREFIX + \".connections\";\n   private static final String METRIC_NAME_IDLE_CONNECTIONS = HIKARI_METRIC_NAME_PREFIX + \".connections.idle\";\n   private static final String METRIC_NAME_ACTIVE_CONNECTIONS = HIKARI_METRIC_NAME_PREFIX + \".connections.active\";\n   private static final String METRIC_NAME_PENDING_CONNECTIONS = HIKARI_METRIC_NAME_PREFIX + \".connections.pending\";\n   private static final String METRIC_NAME_MAX_CONNECTIONS = HIKARI_METRIC_NAME_PREFIX + \".connections.max\";\n   private static final String METRIC_NAME_MIN_CONNECTIONS = HIKARI_METRIC_NAME_PREFIX + \".connections.min\";\n\n   private final Timer connectionObtainTimer;\n   private final Counter connectionTimeoutCounter;\n   private final Timer connectionUsage;\n   private final Timer connectionCreation;\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private final Gauge totalConnectionGauge;\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private final Gauge idleConnectionGauge;\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private final Gauge activeConnectionGauge;\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private final Gauge pendingConnectionGauge;\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private final Gauge maxConnectionGauge;\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private final Gauge minConnectionGauge;\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private final MeterRegistry meterRegistry;\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private final PoolStats poolStats;\n\n\n   MicrometerMetricsTracker(final String poolName, final PoolStats poolStats, final MeterRegistry meterRegistry)\n   {\n      // poolStats must be held with a 'strong reference' even though it is never referenced within this class\n      this.poolStats = poolStats;  // DO NOT REMOVE\n\n      this.meterRegistry = meterRegistry;\n\n      this.connectionObtainTimer = Timer.builder(METRIC_NAME_WAIT)\n         .description(\"Connection acquire time\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.connectionCreation = Timer.builder(METRIC_NAME_CONNECT)\n         .description(\"Connection creation time\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.connectionUsage = Timer.builder(METRIC_NAME_USAGE)\n         .description(\"Connection usage time\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.connectionTimeoutCounter = Counter.builder(METRIC_NAME_TIMEOUT_RATE)\n         .description(\"Connection timeout total count\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.totalConnectionGauge = Gauge.builder(METRIC_NAME_TOTAL_CONNECTIONS, poolStats, PoolStats::getTotalConnections)\n         .description(\"Total connections\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.idleConnectionGauge = Gauge.builder(METRIC_NAME_IDLE_CONNECTIONS, poolStats, PoolStats::getIdleConnections)\n         .description(\"Idle connections\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.activeConnectionGauge = Gauge.builder(METRIC_NAME_ACTIVE_CONNECTIONS, poolStats, PoolStats::getActiveConnections)\n         .description(\"Active connections\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.pendingConnectionGauge = Gauge.builder(METRIC_NAME_PENDING_CONNECTIONS, poolStats, PoolStats::getPendingThreads)\n         .description(\"Pending threads\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.maxConnectionGauge = Gauge.builder(METRIC_NAME_MAX_CONNECTIONS, poolStats, PoolStats::getMaxConnections)\n         .description(\"Max connections\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n      this.minConnectionGauge = Gauge.builder(METRIC_NAME_MIN_CONNECTIONS, poolStats, PoolStats::getMinConnections)\n         .description(\"Min connections\")\n         .tags(METRIC_CATEGORY, poolName)\n         .register(meterRegistry);\n\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void recordConnectionAcquiredNanos(final long elapsedAcquiredNanos)\n   {\n      connectionObtainTimer.record(elapsedAcquiredNanos, TimeUnit.NANOSECONDS);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void recordConnectionUsageMillis(final long elapsedBorrowedMillis)\n   {\n      connectionUsage.record(elapsedBorrowedMillis, TimeUnit.MILLISECONDS);\n   }\n\n   @Override\n   public void recordConnectionTimeout()\n   {\n      connectionTimeoutCounter.increment();\n   }\n\n   @Override\n   public void recordConnectionCreatedMillis(long connectionCreatedMillis)\n   {\n      connectionCreation.record(connectionCreatedMillis, TimeUnit.MILLISECONDS);\n   }\n\n   @Override\n   public void close() {\n      meterRegistry.remove(connectionObtainTimer);\n      meterRegistry.remove(connectionTimeoutCounter);\n      meterRegistry.remove(connectionUsage);\n      meterRegistry.remove(connectionCreation);\n      meterRegistry.remove(totalConnectionGauge);\n      meterRegistry.remove(idleConnectionGauge);\n      meterRegistry.remove(activeConnectionGauge);\n      meterRegistry.remove(pendingConnectionGauge);\n      meterRegistry.remove(maxConnectionGauge);\n      meterRegistry.remove(minConnectionGauge);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/micrometer/MicrometerMetricsTrackerFactory.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.micrometer;\n\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport io.micrometer.core.instrument.MeterRegistry;\n\npublic class MicrometerMetricsTrackerFactory implements MetricsTrackerFactory\n{\n\n   private final MeterRegistry registry;\n\n   public MicrometerMetricsTrackerFactory(MeterRegistry registry)\n   {\n      this.registry = registry;\n   }\n\n   @Override\n   public IMetricsTracker create(String poolName, PoolStats poolStats)\n   {\n      return new MicrometerMetricsTracker(poolName, poolStats, registry);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/prometheus/HikariCPCollector.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport io.prometheus.client.Collector;\nimport io.prometheus.client.GaugeMetricFamily;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.function.Function;\n\n/**\n * <pre>{@code\n * HikariConfig config = new HikariConfig();\n * config.setMetricsTrackerFactory(new HikariCPCollector());\n * }</pre>\n * or\n * <pre>{@code\n * config.setMetricsTrackerFactory(new HikariCPCollector(new CollectorRegistry()));\n * }</pre>\n */\nclass HikariCPCollector extends Collector\n{\n\n   private static final List<String> LABEL_NAMES = Collections.singletonList(\"pool\");\n\n   private final Map<String, PoolStats> poolStatsMap = new ConcurrentHashMap<>();\n\n   @Override\n   public List<MetricFamilySamples> collect()\n   {\n      return Arrays.asList(\n         createGauge(\"hikaricp_active_connections\", \"Active connections\",\n            PoolStats::getActiveConnections),\n         createGauge(\"hikaricp_idle_connections\", \"Idle connections\",\n            PoolStats::getIdleConnections),\n         createGauge(\"hikaricp_pending_threads\", \"Pending threads\",\n            PoolStats::getPendingThreads),\n         createGauge(\"hikaricp_connections\", \"The number of current connections\",\n            PoolStats::getTotalConnections),\n         createGauge(\"hikaricp_max_connections\", \"Max connections\",\n            PoolStats::getMaxConnections),\n         createGauge(\"hikaricp_min_connections\", \"Min connections\",\n            PoolStats::getMinConnections)\n      );\n   }\n\n   void add(String name, PoolStats poolStats)\n   {\n      poolStatsMap.put(name, poolStats);\n   }\n\n   void remove(String name)\n   {\n      poolStatsMap.remove(name);\n   }\n\n   private GaugeMetricFamily createGauge(String metric, String help,\n                                         Function<PoolStats, Integer> metricValueFunction)\n   {\n      var metricFamily = new GaugeMetricFamily(metric, help, LABEL_NAMES);\n      poolStatsMap.forEach((k, v) -> metricFamily.addMetric(\n         Collections.singletonList(k),\n         metricValueFunction.apply(v)\n      ));\n      return metricFamily;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTracker.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport io.prometheus.client.CollectorRegistry;\nimport io.prometheus.client.Counter;\nimport io.prometheus.client.Histogram;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.*;\nimport static com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus.REGISTERED;\n\n/**\n * Alternative Prometheus metrics tracker using a Histogram instead of Summary\n * <p>\n * This is an alternative metrics tracker that doesn't use a {@link io.prometheus.client.Summary}. Summaries require\n * heavy locks that might cause performance issues. Source: https://github.com/prometheus/client_java/issues/328\n *\n * @see PrometheusMetricsTracker\n */\nclass PrometheusHistogramMetricsTracker implements IMetricsTracker\n{\n   private static final Counter CONNECTION_TIMEOUT_COUNTER = Counter.build()\n      .name(\"hikaricp_connection_timeout_total\")\n      .labelNames(\"pool\")\n      .help(\"Connection timeout total count\")\n      .create();\n\n   private static final Histogram ELAPSED_ACQUIRED_HISTOGRAM =\n      registerHistogram(\"hikaricp_connection_acquired_nanos\", \"Connection acquired time (ns)\", 1_000);\n\n   private static final Histogram ELAPSED_BORROWED_HISTOGRAM =\n      registerHistogram(\"hikaricp_connection_usage_millis\", \"Connection usage (ms)\", 1);\n\n   private static final Histogram ELAPSED_CREATION_HISTOGRAM =\n      registerHistogram(\"hikaricp_connection_creation_millis\", \"Connection creation (ms)\", 1);\n\n   private final Counter.Child connectionTimeoutCounterChild;\n\n   private static Histogram registerHistogram(String name, String help, double bucketStart) {\n      return Histogram.build()\n         .name(name)\n         .labelNames(\"pool\")\n         .help(help)\n         .exponentialBuckets(bucketStart, 2.0, 11)\n         .create();\n   }\n\n   private final static Map<CollectorRegistry, RegistrationStatus> registrationStatuses = new ConcurrentHashMap<>();\n\n   private final String poolName;\n   private final HikariCPCollector hikariCPCollector;\n\n   private final Histogram.Child elapsedAcquiredHistogramChild;\n   private final Histogram.Child elapsedBorrowedHistogramChild;\n   private final Histogram.Child elapsedCreationHistogramChild;\n\n   PrometheusHistogramMetricsTracker(String poolName, CollectorRegistry collectorRegistry, HikariCPCollector hikariCPCollector) {\n      registerMetrics(collectorRegistry);\n      this.poolName = poolName;\n      this.hikariCPCollector = hikariCPCollector;\n      this.connectionTimeoutCounterChild = CONNECTION_TIMEOUT_COUNTER.labels(poolName);\n      this.elapsedAcquiredHistogramChild = ELAPSED_ACQUIRED_HISTOGRAM.labels(poolName);\n      this.elapsedBorrowedHistogramChild = ELAPSED_BORROWED_HISTOGRAM.labels(poolName);\n      this.elapsedCreationHistogramChild = ELAPSED_CREATION_HISTOGRAM.labels(poolName);\n   }\n\n   private void registerMetrics(CollectorRegistry collectorRegistry) {\n      if (registrationStatuses.putIfAbsent(collectorRegistry, REGISTERED) == null) {\n         CONNECTION_TIMEOUT_COUNTER.register(collectorRegistry);\n         ELAPSED_ACQUIRED_HISTOGRAM.register(collectorRegistry);\n         ELAPSED_BORROWED_HISTOGRAM.register(collectorRegistry);\n         ELAPSED_CREATION_HISTOGRAM.register(collectorRegistry);\n      }\n   }\n\n   @Override\n   public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos) {\n      elapsedAcquiredHistogramChild.observe(elapsedAcquiredNanos);\n   }\n\n   @Override\n   public void recordConnectionUsageMillis(long elapsedBorrowedMillis) {\n      elapsedBorrowedHistogramChild.observe(elapsedBorrowedMillis);\n   }\n\n   @Override\n   public void recordConnectionCreatedMillis(long connectionCreatedMillis) {\n      elapsedCreationHistogramChild.observe(connectionCreatedMillis);\n   }\n\n   @Override\n   public void recordConnectionTimeout() {\n      connectionTimeoutCounterChild.inc();\n   }\n\n   @Override\n   public void close() {\n      hikariCPCollector.remove(poolName);\n      CONNECTION_TIMEOUT_COUNTER.remove(poolName);\n      ELAPSED_ACQUIRED_HISTOGRAM.remove(poolName);\n      ELAPSED_BORROWED_HISTOGRAM.remove(poolName);\n      ELAPSED_CREATION_HISTOGRAM.remove(poolName);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerFactory.java",
    "content": "/*\n * Copyright (C) 2016 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus;\nimport io.prometheus.client.Collector;\nimport io.prometheus.client.CollectorRegistry;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus.*;\n\n/**\n * <pre>{@code\n * HikariConfig config = new HikariConfig();\n * config.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory());\n * }</pre>\n */\npublic class PrometheusHistogramMetricsTrackerFactory implements MetricsTrackerFactory {\n\n   private final static Map<CollectorRegistry, RegistrationStatus> registrationStatuses = new ConcurrentHashMap<>();\n\n   private final HikariCPCollector collector = new HikariCPCollector();\n\n   private final CollectorRegistry collectorRegistry;\n\n   /**\n    * Default Constructor. The Hikari metrics are registered to the default\n    * collector registry ({@code CollectorRegistry.defaultRegistry}).\n    */\n   public PrometheusHistogramMetricsTrackerFactory() {\n      this(CollectorRegistry.defaultRegistry);\n   }\n\n   /**\n    * Constructor that allows to pass in a {@link CollectorRegistry} to which the\n    * Hikari metrics are registered.\n    *\n    * @param collectorRegistry the collector registry to register the metrics to\n    */\n   public PrometheusHistogramMetricsTrackerFactory(CollectorRegistry collectorRegistry) {\n      this.collectorRegistry = collectorRegistry;\n   }\n\n   @Override\n   public IMetricsTracker create(String poolName, PoolStats poolStats) {\n      registerCollector(this.collector, this.collectorRegistry);\n      this.collector.add(poolName, poolStats);\n      return new PrometheusHistogramMetricsTracker(poolName, this.collectorRegistry, this.collector);\n   }\n\n   private void registerCollector(Collector collector, CollectorRegistry collectorRegistry) {\n      if (registrationStatuses.putIfAbsent(collectorRegistry, REGISTERED) == null) {\n         collector.register(collectorRegistry);\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusMetricsTracker.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus;\nimport io.prometheus.client.CollectorRegistry;\nimport io.prometheus.client.Counter;\nimport io.prometheus.client.Summary;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus.REGISTERED;\n\n/**\n * <pre>{@code\n * HikariConfig config = new HikariConfig();\n * config.setMetricsTrackerFactory(new PrometheusMetricsTracker());\n * }</pre>\n * or\n * <pre>{@code\n * config.setMetricsTrackerFactory(new PrometheusMetricsTracker(new CollectorRegistry()));\n * }</pre>\n */\nclass PrometheusMetricsTracker implements IMetricsTracker\n{\n   private final static Counter CONNECTION_TIMEOUT_COUNTER = Counter.build()\n      .name(\"hikaricp_connection_timeout_total\")\n      .labelNames(\"pool\")\n      .help(\"Connection timeout total count\")\n      .create();\n\n   private final static Summary ELAPSED_ACQUIRED_SUMMARY =\n      createSummary(\"hikaricp_connection_acquired_nanos\", \"Connection acquired time (ns)\");\n\n   private final static Summary ELAPSED_USAGE_SUMMARY =\n      createSummary(\"hikaricp_connection_usage_millis\", \"Connection usage (ms)\");\n\n   private final static Summary ELAPSED_CREATION_SUMMARY =\n      createSummary(\"hikaricp_connection_creation_millis\", \"Connection creation (ms)\");\n\n   private final static Map<CollectorRegistry, RegistrationStatus> registrationStatuses = new ConcurrentHashMap<>();\n\n   private final String poolName;\n   private final HikariCPCollector hikariCPCollector;\n\n   private final Counter.Child connectionTimeoutCounterChild;\n\n   private final Summary.Child elapsedAcquiredSummaryChild;\n   private final Summary.Child elapsedUsageSummaryChild;\n   private final Summary.Child elapsedCreationSummaryChild;\n\n   PrometheusMetricsTracker(String poolName, CollectorRegistry collectorRegistry, HikariCPCollector hikariCPCollector)\n   {\n      registerMetrics(collectorRegistry);\n      this.poolName = poolName;\n      this.hikariCPCollector = hikariCPCollector;\n      this.connectionTimeoutCounterChild = CONNECTION_TIMEOUT_COUNTER.labels(poolName);\n      this.elapsedAcquiredSummaryChild = ELAPSED_ACQUIRED_SUMMARY.labels(poolName);\n      this.elapsedUsageSummaryChild = ELAPSED_USAGE_SUMMARY.labels(poolName);\n      this.elapsedCreationSummaryChild = ELAPSED_CREATION_SUMMARY.labels(poolName);\n   }\n\n   private void registerMetrics(CollectorRegistry collectorRegistry)\n   {\n      if (registrationStatuses.putIfAbsent(collectorRegistry, REGISTERED) == null) {\n         CONNECTION_TIMEOUT_COUNTER.register(collectorRegistry);\n         ELAPSED_ACQUIRED_SUMMARY.register(collectorRegistry);\n         ELAPSED_USAGE_SUMMARY.register(collectorRegistry);\n         ELAPSED_CREATION_SUMMARY.register(collectorRegistry);\n      }\n   }\n\n   @Override\n   public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos)\n   {\n      elapsedAcquiredSummaryChild.observe(elapsedAcquiredNanos);\n   }\n\n   @Override\n   public void recordConnectionUsageMillis(long elapsedBorrowedMillis)\n   {\n      elapsedUsageSummaryChild.observe(elapsedBorrowedMillis);\n   }\n\n   @Override\n   public void recordConnectionCreatedMillis(long connectionCreatedMillis)\n   {\n      elapsedCreationSummaryChild.observe(connectionCreatedMillis);\n   }\n\n   @Override\n   public void recordConnectionTimeout()\n   {\n      connectionTimeoutCounterChild.inc();\n   }\n\n   private static Summary createSummary(String name, String help)\n   {\n      return Summary.build()\n         .name(name)\n         .labelNames(\"pool\")\n         .help(help)\n         .quantile(0.5, 0.05)\n         .quantile(0.95, 0.01)\n         .quantile(0.99, 0.001)\n         .maxAgeSeconds(TimeUnit.MINUTES.toSeconds(5))\n         .ageBuckets(5)\n         .create();\n   }\n\n   @Override\n   public void close()\n   {\n      hikariCPCollector.remove(poolName);\n      CONNECTION_TIMEOUT_COUNTER.remove(poolName);\n      ELAPSED_ACQUIRED_SUMMARY.remove(poolName);\n      ELAPSED_USAGE_SUMMARY.remove(poolName);\n      ELAPSED_CREATION_SUMMARY.remove(poolName);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/metrics/prometheus/PrometheusMetricsTrackerFactory.java",
    "content": "/*\n * Copyright (C) 2016 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport io.prometheus.client.Collector;\nimport io.prometheus.client.CollectorRegistry;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory.RegistrationStatus.REGISTERED;\n\n/**\n * <pre>{@code\n * HikariConfig config = new HikariConfig();\n * config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());\n * }</pre>\n * or\n * <pre>{@code\n * config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(new CollectorRegistry()));\n * }</pre>\n *\n * Note: the internal {@link io.prometheus.client.Summary} requires heavy locks. Consider using\n * {@link PrometheusHistogramMetricsTrackerFactory} if performance plays a role and you don't need the summary per se.\n */\npublic class PrometheusMetricsTrackerFactory implements MetricsTrackerFactory\n{\n\n   private final static Map<CollectorRegistry, RegistrationStatus> registrationStatuses = new ConcurrentHashMap<>();\n\n   private final HikariCPCollector collector = new HikariCPCollector();\n\n   private final CollectorRegistry collectorRegistry;\n\n   enum RegistrationStatus\n   {\n      REGISTERED\n   }\n\n   /**\n    * Default Constructor. The Hikari metrics are registered to the default\n    * collector registry ({@code CollectorRegistry.defaultRegistry}).\n    */\n   public PrometheusMetricsTrackerFactory()\n   {\n      this(CollectorRegistry.defaultRegistry);\n   }\n\n   /**\n    * Constructor that allows to pass in a {@link CollectorRegistry} to which the\n    * Hikari metrics are registered.\n    *\n    * @param collectorRegistry the collector registry to register the metrics to\n    */\n   public PrometheusMetricsTrackerFactory(CollectorRegistry collectorRegistry)\n   {\n      this.collectorRegistry = collectorRegistry;\n   }\n\n   @Override\n   public IMetricsTracker create(String poolName, PoolStats poolStats)\n   {\n      registerCollector(this.collector, this.collectorRegistry);\n      this.collector.add(poolName, poolStats);\n      return new PrometheusMetricsTracker(poolName, this.collectorRegistry, this.collector);\n   }\n\n   private void registerCollector(Collector collector, CollectorRegistry collectorRegistry)\n   {\n      if (registrationStatuses.putIfAbsent(collectorRegistry, REGISTERED) == null) {\n         collector.register(collectorRegistry);\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/HikariPool.java",
    "content": "/*\n * Copyright (C) 2013,2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.HikariPoolMXBean;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport com.zaxxer.hikari.util.ConcurrentBag;\nimport com.zaxxer.hikari.util.ConcurrentBag.IBagStateListener;\nimport com.zaxxer.hikari.util.SuspendResumeLock;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLTransientConnectionException;\nimport java.util.Optional;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicReferenceFieldUpdater;\n\nimport static com.zaxxer.hikari.util.ClockSource.*;\nimport static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_IN_USE;\nimport static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_NOT_IN_USE;\nimport static com.zaxxer.hikari.util.UtilityElf.*;\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\nimport static java.util.concurrent.TimeUnit.SECONDS;\n\n/**\n * This is the primary connection pool class that provides the basic\n * pooling behavior for HikariCP.\n *\n * @author Brett Wooldridge\n * @hidden\n */\npublic final class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateListener\n{\n   private final Logger logger = LoggerFactory.getLogger(HikariPool.class);\n\n   public static final int POOL_NORMAL = 0;\n   public static final int POOL_SUSPENDED = 1;\n   public static final int POOL_SHUTDOWN = 2;\n\n   public volatile int poolState;\n\n   private final long aliveBypassWindowMs = Long.getLong(\"com.zaxxer.hikari.aliveBypassWindowMs\", MILLISECONDS.toMillis(500));\n   private final long housekeepingPeriodMs = Long.getLong(\"com.zaxxer.hikari.housekeeping.periodMs\", SECONDS.toMillis(30));\n   private final long lifeTimeVarianceFactor = Math.min(40, Math.max(2, Long.getLong(\"com.zaxxer.hikari.lifeTimeVarianceFactor\", 4))); // variance% = 100 / factor\n   private final boolean isRequestBoundariesEnabled = Boolean.getBoolean(\"com.zaxxer.hikari.enableRequestBoundaries\");\n\n   private static final String EVICTED_CONNECTION_MESSAGE = \"(connection was evicted)\";\n   private static final String DEAD_CONNECTION_MESSAGE = \"(connection is dead)\";\n\n   private final PoolEntryCreator poolEntryCreator = new PoolEntryCreator();\n   private final PoolEntryCreator postFillPoolEntryCreator = new PoolEntryCreator(\"After adding \");\n   private final ThreadPoolExecutor addConnectionExecutor;\n   private final ThreadPoolExecutor closeConnectionExecutor;\n\n   private final ConcurrentBag<PoolEntry> connectionBag;\n\n   private final ProxyLeakTaskFactory leakTaskFactory;\n   private final SuspendResumeLock suspendResumeLock;\n\n   private final ScheduledExecutorService houseKeepingExecutorService;\n   private ScheduledFuture<?> houseKeeperTask;\n\n   /**\n    * Construct a HikariPool with the specified configuration.\n    *\n    * @param config a HikariConfig instance\n    */\n   public HikariPool(final HikariConfig config)\n   {\n      super(config);\n\n      this.connectionBag = new ConcurrentBag<>(this);\n      this.suspendResumeLock = config.isAllowPoolSuspension() ? new SuspendResumeLock() : SuspendResumeLock.FAUX_LOCK;\n\n      this.houseKeepingExecutorService = initializeHouseKeepingExecutorService();\n\n      checkFailFast();\n\n      if (config.getMetricsTrackerFactory() != null) {\n         setMetricsTrackerFactory(config.getMetricsTrackerFactory());\n      }\n      else {\n         setMetricRegistry(config.getMetricRegistry());\n      }\n\n      setHealthCheckRegistry(config.getHealthCheckRegistry());\n\n      handleMBeans(this, true);\n\n      ThreadFactory threadFactory = config.getThreadFactory();\n\n      final int maxPoolSize = config.getMaximumPoolSize();\n      this.addConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + \":connection-adder\", threadFactory, new CustomDiscardPolicy());\n      this.closeConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + \":connection-closer\", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());\n\n      this.leakTaskFactory = new ProxyLeakTaskFactory(config.getLeakDetectionThreshold(), houseKeepingExecutorService);\n\n      this.houseKeeperTask = houseKeepingExecutorService.scheduleWithFixedDelay(new HouseKeeper(), 100L, housekeepingPeriodMs, MILLISECONDS);\n\n      if (Boolean.getBoolean(\"com.zaxxer.hikari.blockUntilFilled\") && config.getInitializationFailTimeout() > 1) {\n         addConnectionExecutor.setMaximumPoolSize(Math.min(16, Runtime.getRuntime().availableProcessors()));\n         addConnectionExecutor.setCorePoolSize(Math.min(16, Runtime.getRuntime().availableProcessors()));\n\n         final long startTime = currentTime();\n         while (elapsedMillis(startTime) < config.getInitializationFailTimeout() && getTotalConnections() < config.getMinimumIdle()) {\n            quietlySleep(MILLISECONDS.toMillis(100));\n         }\n\n         addConnectionExecutor.setCorePoolSize(1);\n         addConnectionExecutor.setMaximumPoolSize(1);\n      }\n   }\n\n   /**\n    * Get a connection from the pool, or timeout after connectionTimeout milliseconds.\n    *\n    * @return a java.sql.Connection instance\n    * @throws SQLException thrown if a timeout occurs trying to obtain a connection\n    */\n   public Connection getConnection() throws SQLException\n   {\n      return getConnection(connectionTimeout);\n   }\n\n   /**\n    * Get a connection from the pool, or timeout after the specified number of milliseconds.\n    *\n    * @param hardTimeout the maximum time to wait for a connection from the pool\n    * @return a java.sql.Connection instance\n    * @throws SQLException thrown if a timeout occurs trying to obtain a connection\n    */\n   public Connection getConnection(final long hardTimeout) throws SQLException\n   {\n      suspendResumeLock.acquire();\n      final var startTime = currentTime();\n\n      try {\n         var timeout = hardTimeout;\n         do {\n            var poolEntry = connectionBag.borrow(timeout, MILLISECONDS);\n            if (poolEntry == null) {\n               break; // We timed out... break and throw exception\n            }\n\n            final var now = currentTime();\n            if (poolEntry.isMarkedEvicted() || (elapsedMillis(poolEntry.lastAccessed, now) > aliveBypassWindowMs && isConnectionDead(poolEntry.connection))) {\n               closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);\n               timeout = hardTimeout - elapsedMillis(startTime);\n            }\n            else {\n               metricsTracker.recordBorrowStats(poolEntry, startTime);\n               if (isRequestBoundariesEnabled) {\n                  try {\n                     poolEntry.connection.beginRequest();\n                  } catch (SQLException e) {\n                     logger.warn(\"beginRequest Failed for: {}, ({})\", poolEntry.connection, e.getMessage());\n                  }\n               }\n               return poolEntry.createProxyConnection(leakTaskFactory.schedule(poolEntry));\n            }\n         } while (timeout > 0L);\n\n         metricsTracker.recordBorrowTimeoutStats(startTime);\n         throw createTimeoutException(startTime);\n      }\n      catch (InterruptedException e) {\n         Thread.currentThread().interrupt();\n         throw new SQLException(poolName + \" - Interrupted during connection acquisition\", e);\n      }\n      finally {\n         suspendResumeLock.release();\n      }\n   }\n\n   /**\n    * Shutdown the pool, closing all idle connections and aborting or closing\n    * active connections.\n    *\n    * @throws InterruptedException thrown if the thread is interrupted during shutdown\n    */\n   public synchronized void shutdown() throws InterruptedException\n   {\n      try {\n         poolState = POOL_SHUTDOWN;\n\n         if (addConnectionExecutor == null) { // pool never started\n            return;\n         }\n\n         logPoolState(\"Before shutdown \");\n\n         if (houseKeeperTask != null) {\n            houseKeeperTask.cancel(false);\n            houseKeeperTask = null;\n         }\n\n         softEvictConnections();\n\n         addConnectionExecutor.shutdown();\n         if (!addConnectionExecutor.awaitTermination(getLoginTimeout(), SECONDS)) {\n            logger.warn(\"Timed-out waiting for add connection executor to shutdown\");\n         }\n\n         destroyHouseKeepingExecutorService();\n\n         connectionBag.close();\n\n         final var assassinExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), poolName + \":connection-assassinator\",\n                                                                           config.getThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());\n         try {\n            final var start = currentTime();\n            do {\n               abortActiveConnections(assassinExecutor);\n               softEvictConnections();\n            } while (getTotalConnections() > 0 && elapsedMillis(start) < SECONDS.toMillis(10));\n         }\n         finally {\n            assassinExecutor.shutdown();\n            if (!assassinExecutor.awaitTermination(10L, SECONDS)) {\n               logger.warn(\"Timed-out waiting for connection assassin to shutdown\");\n            }\n         }\n\n         shutdownNetworkTimeoutExecutor();\n         closeConnectionExecutor.shutdown();\n         if (!closeConnectionExecutor.awaitTermination(10L, SECONDS)) {\n            logger.warn(\"Timed-out waiting for close connection executor to shutdown\");\n         }\n      }\n      finally {\n         logPoolState(\"After  shutdown \");\n         handleMBeans(this, false);\n         metricsTracker.close();\n      }\n   }\n\n   /**\n    * Evict a Connection from the pool.\n    *\n    * @param connection the Connection to evict (actually a {@link ProxyConnection})\n    */\n   public void evictConnection(Connection connection)\n   {\n      var proxyConnection = (ProxyConnection) connection;\n      proxyConnection.cancelLeakTask();\n\n      try {\n         softEvictConnection(proxyConnection.getPoolEntry(), \"(connection evicted by user)\", !connection.isClosed() /* owner */);\n      }\n      catch (SQLException e) {\n         // unreachable in HikariCP, but we're still forced to catch it\n      }\n   }\n\n   /**\n    * Set a metrics registry to be used when registering metrics collectors.  The HikariDataSource prevents this\n    * method from being called more than once.\n    *\n    * @param metricRegistry the metrics registry instance to use\n    */\n   public void setMetricRegistry(Object metricRegistry)\n   {\n      if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, \"com.codahale.metrics.MetricRegistry\")) {\n         setMetricsTrackerFactory(createInstance(\"com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory\",\n                                                  MetricsTrackerFactory.class, metricRegistry));\n      }\n      else if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, \"io.dropwizard.metrics5.MetricRegistry\")) {\n         setMetricsTrackerFactory(createInstance(\"com.zaxxer.hikari.metrics.dropwizard.Dropwizard5MetricsTrackerFactory\",\n                                                  MetricsTrackerFactory.class, metricRegistry));\n      }\n      else if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, \"io.micrometer.core.instrument.MeterRegistry\")) {\n         setMetricsTrackerFactory(createInstance(\"com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory\",\n                                                  MetricsTrackerFactory.class, metricRegistry));\n      }\n      else {\n         setMetricsTrackerFactory(null);\n      }\n   }\n\n   /**\n    * Set the MetricsTrackerFactory to be used to create the IMetricsTracker instance used by the pool.\n    *\n    * @param metricsTrackerFactory an instance of a class that subclasses MetricsTrackerFactory\n    */\n   public void setMetricsTrackerFactory(MetricsTrackerFactory metricsTrackerFactory)\n   {\n      if (metricsTrackerFactory != null) {\n         this.metricsTracker = new MetricsTrackerDelegate(metricsTrackerFactory.create(config.getPoolName(), getPoolStats()));\n      }\n      else {\n         this.metricsTracker = new NopMetricsTrackerDelegate();\n      }\n   }\n\n   /**\n    * Set the health check registry to be used when registering health checks.  Currently only Codahale health\n    * checks are supported.\n    *\n    * @param healthCheckRegistry the health check registry instance to use\n    */\n   public void setHealthCheckRegistry(Object healthCheckRegistry)\n   {\n      if (healthCheckRegistry != null) {\n         try {\n            Class<?> checkerClazz = HikariPool.class.getClassLoader().loadClass(\"com.zaxxer.hikari.metrics.dropwizard.CodahaleHealthChecker\");\n            Class<?> healthCheckRegistryClazz = HikariPool.class.getClassLoader().loadClass(\"com.codahale.metrics.health.HealthCheckRegistry\");\n            checkerClazz.getMethod(\"registerHealthChecks\", HikariPool.class, HikariConfig.class, healthCheckRegistryClazz)\n                 .invoke(null, this, config, healthCheckRegistry);\n         } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {\n            throw new RuntimeException(e);\n         }\n      }\n   }\n\n   // ***********************************************************************\n   //                        IBagStateListener callback\n   // ***********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public void addBagItem(final int waiting)\n   {\n      if (waiting > addConnectionExecutor.getQueue().size())\n         addConnectionExecutor.submit(poolEntryCreator);\n   }\n\n   // ***********************************************************************\n   //                        HikariPoolMBean methods\n   // ***********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public int getActiveConnections()\n   {\n      return connectionBag.getCount(STATE_IN_USE);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getIdleConnections()\n   {\n      return connectionBag.getCount(STATE_NOT_IN_USE);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getTotalConnections()\n   {\n      return connectionBag.size();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getThreadsAwaitingConnection()\n   {\n      return connectionBag.getWaitingThreadCount();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void softEvictConnections()\n   {\n      connectionBag.values().forEach(poolEntry -> softEvictConnection(poolEntry, \"(connection evicted)\", false /* not owner */));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public synchronized void suspendPool()\n   {\n      if (suspendResumeLock == SuspendResumeLock.FAUX_LOCK) {\n         throw new IllegalStateException(poolName + \" - is not suspendable\");\n      }\n      else if (poolState != POOL_SUSPENDED) {\n         suspendResumeLock.suspend();\n         poolState = POOL_SUSPENDED;\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public synchronized void resumePool()\n   {\n      if (poolState == POOL_SUSPENDED) {\n         poolState = POOL_NORMAL;\n         fillPool(false);\n         suspendResumeLock.resume();\n      }\n   }\n\n   // ***********************************************************************\n   //                           Package methods\n   // ***********************************************************************\n\n   /**\n    * Log the current pool state at debug level.\n    *\n    * @param prefix an optional prefix to prepend the log message\n    */\n   void logPoolState(String... prefix)\n   {\n      if (logger.isDebugEnabled()) {\n         logger.debug(\"{} - {}stats (total={}/{}, idle={}/{}, active={}, waiting={})\",\n                      poolName, (prefix.length > 0 ? prefix[0] : \"\"),\n                      getTotalConnections(), config.getMaximumPoolSize(), getIdleConnections(), config.getMinimumIdle(), getActiveConnections(), getThreadsAwaitingConnection());\n      }\n   }\n\n   /**\n    * Recycle PoolEntry (add back to the pool)\n    *\n    * @param poolEntry the PoolEntry to recycle\n    */\n   @Override\n   void recycle(final PoolEntry poolEntry)\n   {\n      metricsTracker.recordConnectionUsage(poolEntry);\n      if (poolEntry.isMarkedEvicted()) {\n         closeConnection(poolEntry, EVICTED_CONNECTION_MESSAGE);\n      } else {\n         if (isRequestBoundariesEnabled) {\n            try {\n               poolEntry.connection.endRequest();\n            } catch (SQLException e) {\n               logger.warn(\"endRequest Failed for: {},({})\", poolEntry.connection, e.getMessage());\n            }\n         }\n         connectionBag.requite(poolEntry);\n      }\n   }\n\n   /**\n    * Permanently close the real (underlying) connection (eat any exception).\n    *\n    * @param poolEntry poolEntry having the connection to close\n    * @param closureReason reason to close\n    */\n   void closeConnection(final PoolEntry poolEntry, final String closureReason)\n   {\n      if (connectionBag.remove(poolEntry)) {\n         final var connection = poolEntry.close();\n         closeConnectionExecutor.execute(() -> {\n            quietlyCloseConnection(connection, closureReason);\n            if (poolState == POOL_NORMAL) {\n               fillPool(false);\n            }\n         });\n      }\n   }\n\n   @SuppressWarnings(\"unused\")\n   int[] getPoolStateCounts()\n   {\n      return connectionBag.getStateCounts();\n   }\n\n\n   // ***********************************************************************\n   //                           Private methods\n   // ***********************************************************************\n\n   /**\n    * Creating new poolEntry. If maxLifetime is configured, create a future End-of-life task with variance from\n    * the maxLifetime time to ensure there is no massive die-off of Connections in the pool.\n    */\n   private PoolEntry createPoolEntry()\n   {\n      try {\n         final var poolEntry = newPoolEntry(getTotalConnections() == 0);\n\n         final var maxLifetime = config.getMaxLifetime();\n         if (maxLifetime > 0) {\n            // default variance upto 25% of the maxLifetime (random)\n            final var variance = maxLifetime > 10_000L ? ThreadLocalRandom.current().nextLong( maxLifetime / lifeTimeVarianceFactor ) : 0L;\n            final var lifetime = maxLifetime - variance;\n            poolEntry.setFutureEol(houseKeepingExecutorService.schedule(new MaxLifetimeTask(poolEntry), lifetime, MILLISECONDS));\n         }\n\n         final long keepaliveTime = config.getKeepaliveTime();\n         if (keepaliveTime > 0) {\n            // variance up to 20% of the heartbeat time\n            final var variance = ThreadLocalRandom.current().nextLong(keepaliveTime / 5);\n            final var heartbeatTime = keepaliveTime - variance;\n            poolEntry.setKeepalive(houseKeepingExecutorService.scheduleWithFixedDelay(new KeepaliveTask(poolEntry), heartbeatTime, heartbeatTime, MILLISECONDS));\n         }\n\n         return poolEntry;\n      }\n      catch (ConnectionSetupException e) {\n         if (poolState == POOL_NORMAL) { // we check POOL_NORMAL to avoid a flood of messages if shutdown() is running concurrently\n            logger.debug(\"{} - Error thrown while acquiring connection from data source\", poolName, e.getCause());\n         }\n      }\n      catch (Throwable e) {\n         if (poolState == POOL_NORMAL) { // we check POOL_NORMAL to avoid a flood of messages if shutdown() is running concurrently\n            logger.debug(\"{} - Cannot acquire connection from data source\", poolName, e);\n         }\n      }\n\n      return null;\n   }\n\n   /**\n    * Fill pool up from current idle connections (as they are perceived at the point of execution) to minimumIdle connections.\n    */\n   private synchronized void fillPool(final boolean isAfterAdd)\n   {\n      final var idle = getIdleConnections();\n      final var shouldAdd = getTotalConnections() < config.getMaximumPoolSize() && idle < config.getMinimumIdle();\n\n      if (shouldAdd) {\n         final var countToAdd = config.getMinimumIdle() - idle;\n         for (int i = 0; i < countToAdd; i++)\n            addConnectionExecutor.submit(isAfterAdd ? postFillPoolEntryCreator : poolEntryCreator);\n      }\n      else if (isAfterAdd) {\n         logger.debug(\"{} - Fill pool skipped, pool has sufficient level or currently being filled.\", poolName);\n      }\n   }\n\n   /**\n    * Attempt to abort or close active connections.\n    *\n    * @param assassinExecutor the ExecutorService to pass to Connection.abort()\n    */\n   private void abortActiveConnections(final ExecutorService assassinExecutor)\n   {\n      for (var poolEntry : connectionBag.values(STATE_IN_USE)) {\n         Connection connection = poolEntry.close();\n         try {\n            connection.abort(assassinExecutor);\n         }\n         catch (Throwable e) {\n            quietlyCloseConnection(connection, \"(connection aborted during shutdown)\");\n         }\n         finally {\n            connectionBag.remove(poolEntry);\n         }\n      }\n   }\n\n   /**\n    * If {@code initializationFailTimeout} is configured, check that we have DB connectivity.\n    *\n    * @throws PoolInitializationException if fails to create or validate connection\n    * @see HikariConfig#setInitializationFailTimeout(long)\n    */\n   private void checkFailFast()\n   {\n      final var initializationFailTimeout = config.getInitializationFailTimeout();\n      if (initializationFailTimeout < 0) {\n         return;\n      }\n\n      final var startTime = currentTime();\n      do {\n         final var poolEntry = createPoolEntry();\n         if (poolEntry != null) {\n            if (config.getMinimumIdle() > 0) {\n               connectionBag.add(poolEntry);\n               logger.info(\"{} - Added connection {}\", poolName, poolEntry.connection);\n            }\n            else {\n               quietlyCloseConnection(poolEntry.close(), \"(initialization check complete and minimumIdle is zero)\");\n            }\n\n            return;\n         }\n\n         if (getLastConnectionFailure() instanceof ConnectionSetupException) {\n            throwPoolInitializationException(getLastConnectionFailure().getCause());\n         }\n\n         quietlySleep(SECONDS.toMillis(1));\n      } while (elapsedMillis(startTime) < initializationFailTimeout);\n\n      if (initializationFailTimeout > 0) {\n         throwPoolInitializationException(getLastConnectionFailure());\n      }\n   }\n\n   /**\n    * Log the Throwable that caused pool initialization to fail, and then throw a PoolInitializationException with\n    * that cause attached.\n    *\n    * @param t the Throwable that caused the pool to fail to initialize (possibly null)\n    */\n   private void throwPoolInitializationException(Throwable t)\n   {\n      destroyHouseKeepingExecutorService();\n      throw new PoolInitializationException(t);\n   }\n\n   /**\n    * \"Soft\" evict a Connection (/PoolEntry) from the pool.  If this method is being called by the user directly\n    * through {@link HikariDataSource#evictConnection(Connection)} then {@code owner} is {@code true}.\n    * <p>\n    * If the caller is the owner, or if the Connection is idle (i.e. can be \"reserved\" in the {@link ConcurrentBag}),\n    * then we can close the connection immediately.  Otherwise, we leave it \"marked\" for eviction so that it is evicted\n    * the next time someone tries to acquire it from the pool.\n    * <p>\n    * @param poolEntry the PoolEntry (/Connection) to \"soft\" evict from the pool\n    * @param reason the reason that the connection is being evicted\n    * @param owner true if the caller is the owner of the connection, false otherwise\n    * @return true if the connection was evicted (closed), false if it was merely marked for eviction\n    */\n   private boolean softEvictConnection(final PoolEntry poolEntry, final String reason, final boolean owner)\n   {\n      poolEntry.markEvicted();\n      if (owner || connectionBag.reserve(poolEntry)) {\n         closeConnection(poolEntry, reason);\n         return true;\n      }\n\n      return false;\n   }\n\n   /**\n    * Create/initialize the Housekeeping service {@link ScheduledExecutorService}.  If the user specified an Executor\n    * to be used in the {@link HikariConfig}, then we use that.  If no Executor was specified (typical), then create\n    * an Executor and configure it.\n    *\n    * @return either the user specified {@link ScheduledExecutorService}, or the one we created\n    */\n   private ScheduledExecutorService initializeHouseKeepingExecutorService()\n   {\n      if (config.getScheduledExecutor() == null) {\n         final var threadFactory = Optional.ofNullable(config.getThreadFactory()).orElseGet(() -> new DefaultThreadFactory(poolName + \":housekeeper\"));\n         final var executor = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy());\n         executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);\n         executor.setRemoveOnCancelPolicy(true);\n         return executor;\n      }\n      else {\n         return config.getScheduledExecutor();\n      }\n   }\n\n   /**\n    * Destroy (/shutdown) the Housekeeping service Executor, if it was the one that we created.\n    */\n   private void destroyHouseKeepingExecutorService()\n   {\n      if (config.getScheduledExecutor() == null) {\n         houseKeepingExecutorService.shutdownNow();\n      }\n   }\n\n   /**\n    * Create a PoolStats instance that will be used by metrics tracking, with a pollable resolution of 1 second.\n    *\n    * @return a PoolStats instance\n    */\n   private PoolStats getPoolStats()\n   {\n      return new PoolStats(SECONDS.toMillis(1)) {\n         @Override\n         protected void update() {\n            this.pendingThreads = HikariPool.this.getThreadsAwaitingConnection();\n            this.idleConnections = HikariPool.this.getIdleConnections();\n            this.totalConnections = HikariPool.this.getTotalConnections();\n            this.activeConnections = HikariPool.this.getActiveConnections();\n            this.maxConnections = config.getMaximumPoolSize();\n            this.minConnections = config.getMinimumIdle();\n         }\n      };\n   }\n\n   /**\n    * Create a timeout exception (specifically, {@link SQLTransientConnectionException}) to be thrown, because a\n    * timeout occurred when trying to acquire a Connection from the pool.  If there was an underlying cause for the\n    * timeout, e.g. a SQLException thrown by the driver while trying to create a new Connection, then use the\n    * SQL State from that exception as our own and additionally set that exception as the \"next\" SQLException inside\n    * our exception.\n    * <p>\n    * As a side effect, log the timeout failure at DEBUG, and record the timeout failure in the metrics tracker.\n    *\n    * @param startTime the start time (timestamp) of the acquisition attempt\n    * @return a SQLException to be thrown from {@link #getConnection()}\n    */\n   private SQLException createTimeoutException(long startTime)\n   {\n      logPoolState(\"Timeout failure \");\n      metricsTracker.recordConnectionTimeout();\n\n      String sqlState = null;\n      int errorCode = 0;\n      final var originalException = getLastConnectionFailure();\n      if (originalException instanceof SQLException) {\n         sqlState = ((SQLException) originalException).getSQLState();\n         errorCode = ((SQLException) originalException).getErrorCode();\n      }\n      final var connectionException = new SQLTransientConnectionException(\n         poolName + \" - Connection is not available, request timed out after \" + elapsedMillis(startTime) + \"ms \" +\n            \"(total=\" + getTotalConnections() + \", active=\" + getActiveConnections() + \", idle=\" + getIdleConnections() + \", waiting=\" + getThreadsAwaitingConnection() + \")\",\n         sqlState, errorCode, originalException);\n      if (originalException instanceof SQLException) {\n         connectionException.setNextException((SQLException) originalException);\n      }\n\n      return connectionException;\n   }\n\n\n   // ***********************************************************************\n   //                      Non-anonymous Inner-classes\n   // ***********************************************************************\n\n   /**\n    * Creating and adding poolEntries (connections) to the pool.\n    */\n   private final class PoolEntryCreator implements Callable<Boolean>\n   {\n      private final String loggingPrefix;\n\n      PoolEntryCreator()\n      {\n         this(null);\n      }\n\n      PoolEntryCreator(String loggingPrefix)\n      {\n         this.loggingPrefix = loggingPrefix;\n      }\n\n      @Override\n      public Boolean call()\n      {\n         var backoffMs = 10L;\n         var added = false;\n         try {\n            while (shouldContinueCreating()) {\n               final var poolEntry = createPoolEntry();\n               if (poolEntry != null) {\n                  added = true;\n                  connectionBag.add(poolEntry);\n                  logger.debug(\"{} - Added connection {}\", poolName, poolEntry.connection);\n                  quietlySleep(30L);\n                  break;\n               } else {  // failed to get connection from db, sleep and retry\n                  if (loggingPrefix != null && backoffMs % 50 == 0)\n                     logger.debug(\"{} - Connection add failed, sleeping with backoff: {}ms\", poolName, backoffMs);\n                  quietlySleep(backoffMs);\n                  backoffMs = Math.min(SECONDS.toMillis(5), backoffMs * 2);\n               }\n            }\n         }\n         finally {\n            if (added && loggingPrefix != null)\n               logPoolState(loggingPrefix);\n            else if (!added)\n               logPoolState(\"Connection not added, \");\n         }\n\n         // Pool is suspended, shutdown, or at max size\n         return Boolean.FALSE;\n      }\n\n      /**\n       * We only create connections if we need another idle connection or have threads still waiting\n       * for a new connection. Otherwise, we bail out of the request to create.\n       *\n       * @return true if we should create a connection, false if the need has disappeared\n       */\n      private synchronized boolean shouldContinueCreating() {\n         return poolState == POOL_NORMAL && !Thread.interrupted() && getTotalConnections() < config.getMaximumPoolSize() &&\n            (getIdleConnections() < config.getMinimumIdle() || connectionBag.getWaitingThreadCount() > getIdleConnections());\n      }\n   }\n\n   /**\n    * The housekeeping task to retire and maintain minimum idle connections.\n    */\n   private final class HouseKeeper implements Runnable\n   {\n      private volatile long previous = plusMillis(currentTime(), -housekeepingPeriodMs);\n      @SuppressWarnings(\"AtomicFieldUpdaterNotStaticFinal\")\n      private final AtomicReferenceFieldUpdater<PoolBase, String> catalogUpdater = AtomicReferenceFieldUpdater.newUpdater(PoolBase.class, String.class, \"catalog\");\n\n      @Override\n      public void run()\n      {\n         try {\n            // refresh values in case they changed via MBean\n            connectionTimeout = config.getConnectionTimeout();\n            validationTimeout = config.getValidationTimeout();\n            leakTaskFactory.updateLeakDetectionThreshold(config.getLeakDetectionThreshold());\n\n            if (config.getCatalog() != null && !config.getCatalog().equals(catalog)) {\n               catalogUpdater.set(HikariPool.this, config.getCatalog());\n            }\n\n            final var idleTimeout = config.getIdleTimeout();\n            final var now = currentTime();\n\n            // Detect retrograde time, allowing +128ms as per NTP spec.\n            if (plusMillis(now, 128) < plusMillis(previous, housekeepingPeriodMs)) {\n               logger.warn(\"{} - Retrograde clock change detected (housekeeper delta={}), soft-evicting connections from pool.\",\n                           poolName, elapsedDisplayString(previous, now));\n               previous = now;\n               softEvictConnections();\n               return;\n            }\n            else if (now > plusMillis(previous, (3 * housekeepingPeriodMs) / 2)) {\n               // No point evicting for forward clock motion, this merely accelerates connection retirement anyway\n               logger.warn(\"{} - Thread starvation or clock leap detected (housekeeper delta={}).\", poolName, elapsedDisplayString(previous, now));\n            }\n\n            previous = now;\n\n            if (idleTimeout > 0L && config.getMinimumIdle() < config.getMaximumPoolSize()) {\n               logPoolState(\"Before cleanup \");\n               final var notInUse = connectionBag.values(STATE_NOT_IN_USE);\n               var maxToRemove = notInUse.size() - config.getMinimumIdle();\n               for (PoolEntry entry : notInUse) {\n                  if (maxToRemove > 0 && elapsedMillis(entry.lastAccessed, now) > idleTimeout && connectionBag.reserve(entry)) {\n                     closeConnection(entry, \"(connection has passed idleTimeout)\");\n                     maxToRemove--;\n                  }\n               }\n               logPoolState(\"After  cleanup \");\n            }\n            else\n               logPoolState(\"Pool \");\n\n            fillPool(true); // Try to maintain minimum connections\n         }\n         catch (Exception e) {\n            logger.error(\"Unexpected exception in housekeeping task\", e);\n         }\n      }\n   }\n\n   private final class MaxLifetimeTask implements Runnable\n   {\n      private final PoolEntry poolEntry;\n\n      MaxLifetimeTask(final PoolEntry poolEntry)\n      {\n         this.poolEntry = poolEntry;\n      }\n\n      public void run()\n      {\n         if (softEvictConnection(poolEntry, \"(connection has passed maxLifetime)\", false /* not owner */)) {\n            addBagItem(connectionBag.getWaitingThreadCount());\n         }\n      }\n   }\n\n   private final class KeepaliveTask implements Runnable\n   {\n      private final PoolEntry poolEntry;\n\n      KeepaliveTask(final PoolEntry poolEntry)\n      {\n         this.poolEntry = poolEntry;\n      }\n\n      public void run()\n      {\n         if (connectionBag.reserve(poolEntry)) {\n            if (isConnectionDead(poolEntry.connection)) {\n               softEvictConnection(poolEntry, DEAD_CONNECTION_MESSAGE, true);\n               addBagItem(connectionBag.getWaitingThreadCount());\n            }\n            else {\n               connectionBag.unreserve(poolEntry);\n               logger.debug(\"{} - keepalive: connection {} is alive\", poolName, poolEntry.connection);\n            }\n         }\n      }\n   }\n\n   /**\n    * Exception thrown when the pool fails to initialize, typically due to a failure to create or validate a connection.\n    * @hidden\n    */\n   public static class PoolInitializationException extends RuntimeException\n   {\n      private static final long serialVersionUID = 929872118275916520L;\n\n      /**\n       * Construct an exception, possibly wrapping the provided Throwable as the cause.\n       * @param t the Throwable to wrap\n       */\n      public PoolInitializationException(Throwable t)\n      {\n         super(\"Failed to initialize pool: \" + t.getMessage(), t);\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/PoolBase.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariCredentialsProvider;\nimport com.zaxxer.hikari.SQLExceptionOverride;\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;\nimport com.zaxxer.hikari.util.Credentials;\nimport com.zaxxer.hikari.util.DriverDataSource;\nimport com.zaxxer.hikari.util.PropertyElf;\nimport com.zaxxer.hikari.util.UtilityElf;\nimport com.zaxxer.hikari.util.UtilityElf.DefaultThreadFactory;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.management.ObjectName;\nimport javax.naming.InitialContext;\nimport javax.naming.NamingException;\nimport javax.sql.DataSource;\nimport java.lang.management.ManagementFactory;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLTransientConnectionException;\nimport java.sql.Statement;\nimport java.util.StringJoiner;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static com.zaxxer.hikari.pool.ProxyConnection.*;\nimport static com.zaxxer.hikari.util.ClockSource.*;\nimport static com.zaxxer.hikari.util.UtilityElf.createInstance;\nimport static java.util.concurrent.TimeUnit.*;\n\nabstract class PoolBase\n{\n   private final Logger logger = LoggerFactory.getLogger(PoolBase.class);\n\n   public final HikariConfig config;\n   IMetricsTrackerDelegate metricsTracker;\n\n   protected final String poolName;\n\n   volatile String catalog;\n   final AtomicReference<Throwable> lastConnectionFailure;\n   final AtomicLong connectionFailureTimestamp;\n\n   long connectionTimeout;\n   long validationTimeout;\n\n   SQLExceptionOverride exceptionOverride;\n   HikariCredentialsProvider credentialsProvider;\n\n   private static final String[] RESET_STATES = {\"readOnly\", \"autoCommit\", \"isolation\", \"catalog\", \"netTimeout\", \"schema\"};\n   private static final int UNINITIALIZED = -1;\n   private static final int TRUE = 1;\n   private static final int FALSE = 0;\n   private static final int MINIMUM_LOGIN_TIMEOUT = Integer.getInteger(\"com.zaxxer.hikari.minimumLoginTimeoutSecs\", 1);\n   private static final boolean LEGACY_USERPASS_DS_OVERRIDE = Boolean.getBoolean(\"com.zaxxer.hikari.legacy.supportUserPassDataSourceOverride\");\n\n   private int networkTimeout;\n   private volatile int isNetworkTimeoutSupported;\n   private int isQueryTimeoutSupported;\n   private int defaultTransactionIsolation;\n   private int transactionIsolation;\n   private Executor netTimeoutExecutor;\n   private DataSource dataSource;\n\n   private final String schema;\n   private final boolean isReadOnly;\n   private final boolean isAutoCommit;\n\n   private final boolean isUseJdbc4Validation;\n   private final boolean isIsolateInternalQueries;\n\n   private volatile boolean isValidChecked;\n\n   PoolBase(final HikariConfig config)\n   {\n      this.config = config;\n\n      this.networkTimeout = UNINITIALIZED;\n      this.catalog = config.getCatalog();\n      this.schema = config.getSchema();\n      this.isReadOnly = config.isReadOnly();\n      this.isAutoCommit = config.isAutoCommit();\n      this.exceptionOverride = config.getExceptionOverride();\n      this.credentialsProvider = config.getCredentialsProvider();\n      this.transactionIsolation = UtilityElf.getTransactionIsolation(config.getTransactionIsolation());\n\n      this.isQueryTimeoutSupported = UNINITIALIZED;\n      this.isNetworkTimeoutSupported = UNINITIALIZED;\n      this.isUseJdbc4Validation = config.getConnectionTestQuery() == null;\n      this.isIsolateInternalQueries = config.isIsolateInternalQueries();\n\n      this.poolName = config.getPoolName();\n      this.connectionTimeout = config.getConnectionTimeout();\n      this.validationTimeout = config.getValidationTimeout();\n      this.lastConnectionFailure = new AtomicReference<>();\n      this.connectionFailureTimestamp = new AtomicLong();\n\n      initializeDataSource();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String toString()\n   {\n      return poolName;\n   }\n\n   abstract void recycle(final PoolEntry poolEntry);\n\n   // ***********************************************************************\n   //                           JDBC methods\n   // ***********************************************************************\n\n   void quietlyCloseConnection(final Connection connection, final String closureReason)\n   {\n      if (connection != null) {\n         try {\n            logger.debug(\"{} - Closing connection {}: {}\", poolName, connection, closureReason);\n\n            // continue with the close even if setNetworkTimeout() throws\n            try (connection) {\n               if (!connection.isClosed())\n                  setNetworkTimeout(connection, SECONDS.toMillis(15));\n               } catch (SQLException e) {\n                  // ignore\n            }\n         }\n         catch (Exception e) {\n            logger.debug(\"{} - Closing connection {} failed\", poolName, connection, e);\n         }\n      }\n   }\n\n   boolean isConnectionDead(final Connection connection)\n   {\n      try {\n         setNetworkTimeout(connection, validationTimeout);\n         try {\n            final var validationSeconds = (int) Math.max(1000L, validationTimeout) / 1000;\n\n            if (isUseJdbc4Validation) {\n               return !connection.isValid(validationSeconds);\n            }\n\n            try (var statement = connection.createStatement()) {\n               if (isNetworkTimeoutSupported != TRUE) {\n                  setQueryTimeout(statement, validationSeconds);\n               }\n\n               statement.execute(config.getConnectionTestQuery());\n            }\n         }\n         finally {\n            setNetworkTimeout(connection, networkTimeout);\n\n            if (isIsolateInternalQueries && !isAutoCommit) {\n               connection.rollback();\n            }\n         }\n\n         return false;\n      }\n      catch (Exception e) {\n         lastConnectionFailure.set(e);\n         logger.warn(\"{} - Failed to validate connection {} ({}). Possibly consider using a shorter maxLifetime value.\",\n                     poolName, connection, e.getMessage());\n         return true;\n      }\n   }\n\n   Throwable getLastConnectionFailure()\n   {\n      return lastConnectionFailure.get();\n   }\n\n   public DataSource getUnwrappedDataSource()\n   {\n      return dataSource;\n   }\n\n   // ***********************************************************************\n   //                         PoolEntry methods\n   // ***********************************************************************\n\n   PoolEntry newPoolEntry(final boolean isEmptyPool) throws Exception\n   {\n      return new PoolEntry(newConnection(isEmptyPool), this, isReadOnly, isAutoCommit);\n   }\n\n   void resetConnectionState(final Connection connection, final ProxyConnection proxyConnection, final int dirtyBits) throws SQLException\n   {\n      int resetBits = 0;\n\n      if ((dirtyBits & DIRTY_BIT_READONLY) != 0 && proxyConnection.getReadOnlyState() != isReadOnly) {\n         connection.setReadOnly(isReadOnly);\n         resetBits |= DIRTY_BIT_READONLY;\n      }\n\n      if ((dirtyBits & DIRTY_BIT_AUTOCOMMIT) != 0 && proxyConnection.getAutoCommitState() != isAutoCommit) {\n         connection.setAutoCommit(isAutoCommit);\n         resetBits |= DIRTY_BIT_AUTOCOMMIT;\n      }\n\n      if ((dirtyBits & DIRTY_BIT_ISOLATION) != 0 && proxyConnection.getTransactionIsolationState() != transactionIsolation) {\n         //noinspection MagicConstant\n         connection.setTransactionIsolation(transactionIsolation);\n         resetBits |= DIRTY_BIT_ISOLATION;\n      }\n\n      if ((dirtyBits & DIRTY_BIT_CATALOG) != 0 && catalog != null && !catalog.equals(proxyConnection.getCatalogState())) {\n         connection.setCatalog(catalog);\n         resetBits |= DIRTY_BIT_CATALOG;\n      }\n\n      if ((dirtyBits & DIRTY_BIT_NETTIMEOUT) != 0 && proxyConnection.getNetworkTimeoutState() != networkTimeout) {\n         setNetworkTimeout(connection, networkTimeout);\n         resetBits |= DIRTY_BIT_NETTIMEOUT;\n      }\n\n      if ((dirtyBits & DIRTY_BIT_SCHEMA) != 0 && schema != null && !schema.equals(proxyConnection.getSchemaState())) {\n         connection.setSchema(schema);\n         resetBits |= DIRTY_BIT_SCHEMA;\n      }\n\n      if (resetBits != 0 && logger.isDebugEnabled()) {\n         logger.debug(\"{} - Reset ({}) on connection {}\", poolName, stringFromResetBits(resetBits), connection);\n      }\n   }\n\n   void shutdownNetworkTimeoutExecutor()\n   {\n      isNetworkTimeoutSupported = UNINITIALIZED;\n      if (netTimeoutExecutor instanceof ThreadPoolExecutor) {\n         ((ThreadPoolExecutor) netTimeoutExecutor).shutdownNow();\n      }\n   }\n\n   long getLoginTimeout()\n   {\n      try {\n         return (dataSource != null) ? dataSource.getLoginTimeout() : SECONDS.toSeconds(5);\n      } catch (SQLException e) {\n         return SECONDS.toSeconds(5);\n      }\n   }\n\n   // ***********************************************************************\n   //                       JMX methods\n   // ***********************************************************************\n\n   /**\n    * Register MBeans for HikariConfig and HikariPool.\n    *\n    * @param hikariPool a HikariPool instance\n    */\n   void handleMBeans(final HikariPool hikariPool, final boolean register)\n   {\n      if (!config.isRegisterMbeans()) {\n         return;\n      }\n\n      try {\n         final var mBeanServer = ManagementFactory.getPlatformMBeanServer();\n\n         ObjectName beanConfigName, beanPoolName;\n         if (\"true\".equals(System.getProperty(\"hikaricp.jmx.register2.0\"))) {\n             beanConfigName = new ObjectName(\"com.zaxxer.hikari:type=PoolConfig,name=\" + poolName);\n             beanPoolName = new ObjectName(\"com.zaxxer.hikari:type=Pool,name=\" + poolName);\n         } else {\n            beanConfigName = new ObjectName(\"com.zaxxer.hikari:type=PoolConfig (\" + poolName + \")\");\n            beanPoolName = new ObjectName(\"com.zaxxer.hikari:type=Pool (\" + poolName + \")\");\n         }\n         if (register) {\n            if (!mBeanServer.isRegistered(beanConfigName)) {\n               mBeanServer.registerMBean(config, beanConfigName);\n               mBeanServer.registerMBean(hikariPool, beanPoolName);\n            } else {\n               logger.error(\"{} - JMX name ({}) is already registered.\", poolName, poolName);\n            }\n         }\n         else if (mBeanServer.isRegistered(beanConfigName)) {\n            mBeanServer.unregisterMBean(beanConfigName);\n            mBeanServer.unregisterMBean(beanPoolName);\n         }\n      }\n      catch (Exception e) {\n         logger.warn(\"{} - Failed to {} management beans.\", poolName, (register ? \"register\" : \"unregister\"), e);\n      }\n   }\n\n   // ***********************************************************************\n   //                          Private methods\n   // ***********************************************************************\n\n   /**\n    * Create/initialize the underlying DataSource.\n    */\n   private void initializeDataSource()\n   {\n      final var jdbcUrl = config.getJdbcUrl();\n      final var dsClassName = config.getDataSourceClassName();\n      final var driverClassName = config.getDriverClassName();\n      final var dataSourceJNDI = config.getDataSourceJNDI();\n      final var dataSourceProperties = config.getDataSourceProperties();\n      final var credentials = getCredentials();\n\n      var ds = config.getDataSource();\n      if (dsClassName != null && ds == null) {\n         ds = createInstance(dsClassName, DataSource.class);\n         PropertyElf.setTargetFromProperties(ds, dataSourceProperties);\n      }\n      else if (jdbcUrl != null && ds == null) {\n         ds = new DriverDataSource(jdbcUrl, driverClassName, dataSourceProperties, credentials.getUsername(), credentials.getPassword());\n      }\n      else if (dataSourceJNDI != null && ds == null) {\n         try {\n            var ic = new InitialContext();\n            ds = (DataSource) ic.lookup(dataSourceJNDI);\n         } catch (NamingException e) {\n            throw new PoolInitializationException(e);\n         }\n      }\n\n      if (ds != null) {\n         setLoginTimeout(ds);\n         createNetworkTimeoutExecutor(ds, dsClassName, jdbcUrl);\n      }\n\n      this.dataSource = ds;\n   }\n\n   /**\n    * Obtain connection from data source.\n    *\n    * @return a Connection\n    */\n   private Connection newConnection(final boolean isEmptyPool) throws Exception\n   {\n      final var start = currentTime();\n      final var id = java.util.UUID.randomUUID();\n\n      Connection connection = null;\n      try {\n         final var credentials = getCredentials();\n         final var username = credentials.getUsername();\n         final var password = credentials.getPassword();\n\n         logger.debug(\"{} - Attempting to create/setup new connection ({})\", poolName, id);\n\n         connection = (username == null) ? dataSource.getConnection() : dataSource.getConnection(username, password);\n         if (connection == null) {\n            throw new SQLTransientConnectionException(\"DataSource returned null unexpectedly\");\n         }\n\n         setupConnection(connection);\n\n         lastConnectionFailure.set(null);\n         connectionFailureTimestamp.set(0);\n\n         logger.debug(\"{} - Established new connection ({})\", poolName, id);\n         return connection;\n      }\n      catch (Throwable t) {\n         logger.debug(\"{} - Failed to create/setup connection ({}): {}\", poolName, id, t.getMessage());\n\n         connectionFailureTimestamp.compareAndSet(0, start);\n         if (isEmptyPool && elapsedMillis(connectionFailureTimestamp.get()) > MINUTES.toMillis(1)) {\n            logger.warn(\"{} - Pool is empty, failed to create/setup connection ({})\", poolName, id, t);\n            connectionFailureTimestamp.set(0);\n         }\n\n         if (connection != null) {\n            quietlyCloseConnection(connection, \"(Failed to create/setup connection (\".concat(id.toString()).concat(\")\"));\n         }\n\n         lastConnectionFailure.set(t);\n         throw t;\n      }\n      finally {\n         // tracker will be null during failFast check\n         if (metricsTracker != null) {\n            metricsTracker.recordConnectionCreated(elapsedMillis(start));\n         }\n      }\n   }\n\n   /**\n    * Set up a connection initial state.\n    *\n    * @param connection a Connection\n    * @throws ConnectionSetupException thrown if any exception is encountered\n    */\n   private void setupConnection(final Connection connection) throws ConnectionSetupException\n   {\n      try {\n         if (networkTimeout == UNINITIALIZED) {\n            networkTimeout = getAndSetNetworkTimeout(connection, validationTimeout);\n         }\n         else {\n            setNetworkTimeout(connection, validationTimeout);\n         }\n\n         if (connection.isReadOnly() != isReadOnly) {\n            connection.setReadOnly(isReadOnly);\n         }\n\n         if (connection.getAutoCommit() != isAutoCommit) {\n            connection.setAutoCommit(isAutoCommit);\n         }\n\n         checkDriverSupport(connection);\n\n         if (transactionIsolation != defaultTransactionIsolation) {\n            //noinspection MagicConstant\n            connection.setTransactionIsolation(transactionIsolation);\n         }\n\n         if (catalog != null) {\n            connection.setCatalog(catalog);\n         }\n\n         if (schema != null) {\n            connection.setSchema(schema);\n         }\n\n         executeSql(connection, config.getConnectionInitSql(), true);\n\n         setNetworkTimeout(connection, networkTimeout);\n      }\n      catch (SQLException e) {\n         throw new ConnectionSetupException(e);\n      }\n   }\n\n   /**\n    * Execute isValid() or connection test query.\n    *\n    * @param connection a Connection to check\n    */\n   private void checkDriverSupport(final Connection connection) throws SQLException\n   {\n      if (!isValidChecked) {\n         checkValidationSupport(connection);\n         checkDefaultIsolation(connection);\n\n         isValidChecked = true;\n      }\n   }\n\n   /**\n    * Check whether Connection.isValid() is supported, or that the user has test query configured.\n    *\n    * @param connection a Connection to check\n    * @throws SQLException rethrown from the driver\n    */\n   private void checkValidationSupport(final Connection connection) throws SQLException\n   {\n      try {\n         if (isUseJdbc4Validation) {\n            connection.isValid(Math.max(1, (int) MILLISECONDS.toSeconds(validationTimeout)));\n         }\n         else {\n            executeSql(connection, config.getConnectionTestQuery(), false);\n         }\n      }\n      catch (Exception | AbstractMethodError e) {\n         logger.error(\"{} - Failed to execute{} connection test query ({}).\", poolName, (isUseJdbc4Validation ? \" isValid() for connection, configure\" : \"\"), e.getMessage());\n         throw e;\n      }\n   }\n\n   /**\n    * Check the default transaction isolation of the Connection.\n    *\n    * @param connection a Connection to check\n    * @throws SQLException rethrown from the driver\n    */\n   private void checkDefaultIsolation(final Connection connection) throws SQLException\n   {\n      try {\n         defaultTransactionIsolation = connection.getTransactionIsolation();\n         if (transactionIsolation == -1) {\n            transactionIsolation = defaultTransactionIsolation;\n         }\n      }\n      catch (SQLException e) {\n         logger.warn(\"{} - Default transaction isolation level detection failed ({}).\", poolName, e.getMessage());\n         if (e.getSQLState() != null && !e.getSQLState().startsWith(\"08\")) {\n            throw e;\n         }\n      }\n   }\n\n   /**\n    * Set the query timeout, if it is supported by the driver.\n    *\n    * @param statement a statement to set the query timeout on\n    * @param timeoutSec the number of seconds before timeout\n    */\n   private void setQueryTimeout(final Statement statement, final int timeoutSec)\n   {\n      if (isQueryTimeoutSupported != FALSE) {\n         try {\n            statement.setQueryTimeout(timeoutSec);\n            isQueryTimeoutSupported = TRUE;\n         }\n         catch (Exception e) {\n            if (isQueryTimeoutSupported == UNINITIALIZED) {\n               isQueryTimeoutSupported = FALSE;\n               logger.info(\"{} - Failed to set query timeout for statement. ({})\", poolName, e.getMessage());\n            }\n         }\n      }\n   }\n\n   /**\n    * Set the network timeout, if <code>isUseNetworkTimeout</code> is <code>true</code> and the\n    * driver supports it.  Return the pre-existing value of the network timeout.\n    *\n    * @param connection the connection to set the network timeout on\n    * @param timeoutMs the number of milliseconds before timeout\n    * @return the pre-existing network timeout value\n    */\n   private int getAndSetNetworkTimeout(final Connection connection, final long timeoutMs)\n   {\n      if (isNetworkTimeoutSupported != FALSE) {\n         try {\n            final var originalTimeout = connection.getNetworkTimeout();\n            connection.setNetworkTimeout(netTimeoutExecutor, (int) timeoutMs);\n            isNetworkTimeoutSupported = TRUE;\n            return originalTimeout;\n         }\n         catch (Exception | AbstractMethodError e) {\n            if (isNetworkTimeoutSupported == UNINITIALIZED) {\n               isNetworkTimeoutSupported = FALSE;\n\n               logger.info(\"{} - Driver does not support get/set network timeout for connections. ({})\", poolName, e.getMessage());\n               if (validationTimeout < SECONDS.toMillis(1)) {\n                  logger.warn(\"{} - A validationTimeout of less than 1 second cannot be honored on drivers without setNetworkTimeout() support.\", poolName);\n               }\n               else if (validationTimeout % SECONDS.toMillis(1) != 0) {\n                  logger.warn(\"{} - A validationTimeout with fractional second granularity cannot be honored on drivers without setNetworkTimeout() support.\", poolName);\n               }\n            }\n         }\n      }\n\n      return 0;\n   }\n\n   /**\n    * Set the network timeout, if <code>isUseNetworkTimeout</code> is <code>true</code> and the\n    * driver supports it.\n    *\n    * @param connection the connection to set the network timeout on\n    * @param timeoutMs the number of milliseconds before timeout\n    * @throws SQLException throw if the connection.setNetworkTimeout() call throws\n    */\n   private void setNetworkTimeout(final Connection connection, final long timeoutMs) throws SQLException\n   {\n      if (isNetworkTimeoutSupported == TRUE) {\n         connection.setNetworkTimeout(netTimeoutExecutor, (int) timeoutMs);\n      }\n   }\n\n   /**\n    * Execute the user-specified init SQL.\n    *\n    * @param connection the connection to initialize\n    * @param sql the SQL to execute\n    * @param isCommit whether to commit the SQL after execution or not\n    * @throws SQLException throws if the init SQL execution fails\n    */\n   private void executeSql(final Connection connection, final String sql, final boolean isCommit) throws SQLException\n   {\n      if (sql != null) {\n         try (var statement = connection.createStatement()) {\n            // connection was created a few milliseconds before, so set query timeout is omitted (we assume it will succeed)\n            statement.execute(sql);\n         }\n\n         if (isIsolateInternalQueries && !isAutoCommit) {\n            if (isCommit) {\n               connection.commit();\n            }\n            else {\n               connection.rollback();\n            }\n         }\n      }\n   }\n\n   private void createNetworkTimeoutExecutor(final DataSource dataSource, final String dsClassName, final String jdbcUrl)\n   {\n      // Temporary hack for MySQL issue: http://bugs.mysql.com/bug.php?id=75615\n      if ((dsClassName != null && dsClassName.contains(\"Mysql\")) ||\n          (jdbcUrl != null && jdbcUrl.contains(\"mysql\")) ||\n          (dataSource != null && dataSource.getClass().getName().contains(\"Mysql\"))) {\n         netTimeoutExecutor = new SynchronousExecutor();\n      }\n      else {\n         ThreadFactory threadFactory = config.getThreadFactory();\n         threadFactory = threadFactory != null ? threadFactory : new DefaultThreadFactory(poolName + \":network-timeout-executor\");\n         ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(threadFactory);\n         executor.setKeepAliveTime(15, SECONDS);\n         executor.allowCoreThreadTimeOut(true);\n         netTimeoutExecutor = executor;\n      }\n   }\n\n   /**\n    * Set the loginTimeout on the specified DataSource.\n    *\n    * @param dataSource the DataSource\n    */\n   private void setLoginTimeout(final DataSource dataSource)\n   {\n      if (connectionTimeout != Integer.MAX_VALUE) {\n         try {\n            dataSource.setLoginTimeout(Math.max(MINIMUM_LOGIN_TIMEOUT, (int) MILLISECONDS.toSeconds(500L + connectionTimeout)));\n         }\n         catch (Exception e) {\n            logger.info(\"{} - Failed to set login timeout for data source. ({})\", poolName, e.getMessage());\n         }\n      }\n   }\n\n   /**\n    * This will create a string for debug logging. Given a set of \"reset bits\", this\n    * method will return a concatenated string, for example:\n    * <p\n    * Input : 0b00110\n    * Output: \"autoCommit, isolation\"\n    *\n    * @param bits a set of \"reset bits\"\n    * @return a string of which states were reset\n    */\n   private String stringFromResetBits(final int bits)\n   {\n      final var sb = new StringJoiner(\", \");\n      for (int ndx = 0; ndx < RESET_STATES.length; ndx++) {\n         if ( (bits & (0b1 << ndx)) != 0) {\n            sb.add(RESET_STATES[ndx]);\n         }\n      }\n\n      return sb.toString();\n   }\n\n   private Credentials getCredentials()\n   {\n      if (credentialsProvider != null) {\n         return credentialsProvider.getCredentials();\n      }\n\n      var credentials = config.getCredentials();\n      if (LEGACY_USERPASS_DS_OVERRIDE) {\n         credentials = Credentials.of(config.getUsername(), config.getPassword());\n      }\n      return credentials;\n   }\n\n   // ***********************************************************************\n   //                      Private Classes\n   // ***********************************************************************\n\n   static class ConnectionSetupException extends Exception\n   {\n      private static final long serialVersionUID = 929872118275916521L;\n\n      ConnectionSetupException(Throwable t)\n      {\n         super(t);\n      }\n   }\n\n   /**\n    * Special executor used only to work around a MySQL issue that has not been addressed.\n    * MySQL issue: <a href=\"http://bugs.mysql.com/bug.php?id=75615\">...</a>\n    */\n   private static class SynchronousExecutor implements Executor\n   {\n      /** {@inheritDoc} */\n      @Override\n      @SuppressWarnings(\"NullableProblems\")\n      public void execute(Runnable command)\n      {\n         try {\n            command.run();\n         }\n         catch (Exception t) {\n            LoggerFactory.getLogger(PoolBase.class).debug(\"Failed to execute: {}\", command, t);\n         }\n      }\n   }\n\n   interface IMetricsTrackerDelegate extends AutoCloseable\n   {\n      default void recordConnectionUsage(PoolEntry poolEntry) {}\n\n      default void recordConnectionCreated(long connectionCreatedMillis) {}\n\n      default void recordBorrowTimeoutStats(long startTime) {}\n\n      default void recordBorrowStats(final PoolEntry poolEntry, final long startTime) {}\n\n      default void recordConnectionTimeout() {}\n\n      @Override\n      default void close() {}\n   }\n\n   /**\n    * A class that delegates to a MetricsTracker implementation.  The use of a delegate\n    * allows us to use the NopMetricsTrackerDelegate when metrics are disabled, which in\n    * turn allows the JIT to completely optimize away to callsites to record metrics.\n    */\n   static class MetricsTrackerDelegate implements IMetricsTrackerDelegate\n   {\n      final IMetricsTracker tracker;\n\n      MetricsTrackerDelegate(IMetricsTracker tracker)\n      {\n         this.tracker = tracker;\n      }\n\n      @Override\n      public void recordConnectionUsage(final PoolEntry poolEntry)\n      {\n         tracker.recordConnectionUsageMillis(poolEntry.getMillisSinceBorrowed());\n      }\n\n      @Override\n      public void recordConnectionCreated(long connectionCreatedMillis)\n      {\n         tracker.recordConnectionCreatedMillis(connectionCreatedMillis);\n      }\n\n      @Override\n      public void recordBorrowTimeoutStats(long startTime)\n      {\n         tracker.recordConnectionAcquiredNanos(elapsedNanos(startTime));\n      }\n\n      @Override\n      public void recordBorrowStats(final PoolEntry poolEntry, final long startTime)\n      {\n         final var now = currentTime();\n         poolEntry.lastBorrowed = now;\n         tracker.recordConnectionAcquiredNanos(elapsedNanos(startTime, now));\n      }\n\n      @Override\n      public void recordConnectionTimeout() {\n         tracker.recordConnectionTimeout();\n      }\n\n      @Override\n      public void close()\n      {\n         tracker.close();\n      }\n   }\n\n   /**\n    * A no-op implementation of the IMetricsTrackerDelegate that is used when metrics capture is\n    * disabled.\n    */\n   static final class NopMetricsTrackerDelegate implements IMetricsTrackerDelegate {}\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/PoolEntry.java",
    "content": "/*\n * Copyright (C) 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry;\nimport com.zaxxer.hikari.util.FastList;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\n\nimport static com.zaxxer.hikari.util.ClockSource.*;\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\n\n/**\n * Entry used in the ConcurrentBag to track Connection instances.\n *\n * @author Brett Wooldridge\n */\nfinal class PoolEntry implements IConcurrentBagEntry\n{\n   private static final Logger LOGGER = LoggerFactory.getLogger(PoolEntry.class);\n   private static final AtomicIntegerFieldUpdater<PoolEntry> stateUpdater;\n\n   Connection connection;\n   long lastAccessed;\n   long lastBorrowed;\n\n   @SuppressWarnings(\"FieldCanBeLocal\")\n   private volatile int state = 0;\n   private volatile boolean evict;\n\n   private volatile ScheduledFuture<?> endOfLife;\n   private volatile ScheduledFuture<?> keepalive;\n\n   private final FastList<Statement> openStatements;\n   private final HikariPool hikariPool;\n\n   private final boolean isReadOnly;\n   private final boolean isAutoCommit;\n\n   static\n   {\n      stateUpdater = AtomicIntegerFieldUpdater.newUpdater(PoolEntry.class, \"state\");\n   }\n\n   PoolEntry(final Connection connection, final PoolBase pool, final boolean isReadOnly, final boolean isAutoCommit)\n   {\n      this.connection = connection;\n      this.hikariPool = (HikariPool) pool;\n      this.isReadOnly = isReadOnly;\n      this.isAutoCommit = isAutoCommit;\n      this.lastAccessed = currentTime();\n      this.openStatements = new FastList<>(Statement.class, 16);\n   }\n\n   /**\n    * Release this entry back to the pool.\n    */\n   void recycle()\n   {\n      if (connection != null) {\n         this.lastAccessed = currentTime();\n         hikariPool.recycle(this);\n      }\n   }\n\n   /**\n    * Set the end of life {@link ScheduledFuture}.\n    *\n    * @param endOfLife this PoolEntry/Connection's end of life {@link ScheduledFuture}\n    */\n   void setFutureEol(final ScheduledFuture<?> endOfLife)\n   {\n      this.endOfLife = endOfLife;\n   }\n\n   public void setKeepalive(ScheduledFuture<?> keepalive) {\n      this.keepalive = keepalive;\n   }\n\n   Connection createProxyConnection(final ProxyLeakTask leakTask)\n   {\n      return ProxyFactory.getProxyConnection(this, connection, openStatements, leakTask, isReadOnly, isAutoCommit);\n   }\n\n   void resetConnectionState(final ProxyConnection proxyConnection, final int dirtyBits) throws SQLException\n   {\n      hikariPool.resetConnectionState(connection, proxyConnection, dirtyBits);\n   }\n\n   String getPoolName()\n   {\n      return hikariPool.toString();\n   }\n\n   boolean isMarkedEvicted()\n   {\n      return evict;\n   }\n\n   void markEvicted()\n   {\n      this.evict = true;\n   }\n\n   void evict(final String closureReason)\n   {\n      hikariPool.closeConnection(this, closureReason);\n   }\n\n   /** Returns millis since lastBorrowed */\n   long getMillisSinceBorrowed()\n   {\n      return elapsedMillis(lastBorrowed);\n   }\n\n   PoolBase getPoolBase()\n   {\n      return hikariPool;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String toString()\n   {\n      final var now = currentTime();\n      return connection\n         + \", accessed \" + elapsedDisplayString(lastAccessed, now) + \" ago, \"\n         + stateToString();\n   }\n\n   // ***********************************************************************\n   //                      IConcurrentBagEntry methods\n   // ***********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public int getState()\n   {\n      return stateUpdater.get(this);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean compareAndSet(int expect, int update)\n   {\n      return stateUpdater.compareAndSet(this, expect, update);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setState(int update)\n   {\n      stateUpdater.set(this, update);\n   }\n\n   Connection close()\n   {\n      var eol = endOfLife;\n      if (eol != null && !eol.isDone() && !eol.cancel(false)) {\n         LOGGER.warn(\"{} - maxLifeTime expiration task cancellation unexpectedly returned false for connection {}\", getPoolName(), connection);\n      }\n\n      var ka = keepalive;\n      if (ka != null && !ka.isDone() && !ka.cancel(false)) {\n         LOGGER.warn(\"{} - keepalive task cancellation unexpectedly returned false for connection {}\", getPoolName(), connection);\n      }\n\n      var con = connection;\n      connection = null;\n      endOfLife = null;\n      keepalive = null;\n      return con;\n   }\n\n   private String stateToString()\n   {\n      switch (state) {\n      case STATE_IN_USE:\n         return \"IN_USE\";\n      case STATE_NOT_IN_USE:\n         return \"NOT_IN_USE\";\n      case STATE_REMOVED:\n         return \"REMOVED\";\n      case STATE_RESERVED:\n         return \"RESERVED\";\n      default:\n         return \"Invalid\";\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyCallableStatement.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.sql.CallableStatement;\n\n/**\n * This is the proxy class for {@link CallableStatement}.\n *\n * @author Brett Wooldridge\n */\npublic abstract class ProxyCallableStatement extends ProxyPreparedStatement implements CallableStatement\n{\n   protected ProxyCallableStatement(ProxyConnection connection, CallableStatement statement)\n   {\n      super(connection, statement);\n   }\n\n   // **********************************************************************\n   //               Overridden java.sql.CallableStatement Methods\n   // **********************************************************************\n\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyConnection.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.util.FastList;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Proxy;\nimport java.sql.*;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.concurrent.Executor;\n\nimport static com.zaxxer.hikari.SQLExceptionOverride.Override.*;\n\n/**\n * This is the proxy class for {@link Connection}.\n *\n * @author Brett Wooldridge\n */\npublic abstract class ProxyConnection implements Connection\n{\n   static final int DIRTY_BIT_READONLY   = 0b000001;\n   static final int DIRTY_BIT_AUTOCOMMIT = 0b000010;\n   static final int DIRTY_BIT_ISOLATION  = 0b000100;\n   static final int DIRTY_BIT_CATALOG    = 0b001000;\n   static final int DIRTY_BIT_NETTIMEOUT = 0b010000;\n   static final int DIRTY_BIT_SCHEMA     = 0b100000;\n\n   private static final Logger LOGGER;\n   private static final Set<String> ERROR_STATES;\n   private static final Set<Integer> ERROR_CODES;\n\n   @SuppressWarnings(\"WeakerAccess\")\n   protected Connection delegate;\n\n   private final PoolEntry poolEntry;\n   private final ProxyLeakTask leakTask;\n   private final FastList<Statement> openStatements;\n\n   private int dirtyBits;\n   private boolean isCommitStateDirty;\n\n   private boolean isReadOnly;\n   private boolean isAutoCommit;\n   private int networkTimeout;\n   private int transactionIsolation;\n   private String dbcatalog;\n   private String dbschema;\n\n   // static initializer\n   static {\n      LOGGER = LoggerFactory.getLogger(ProxyConnection.class);\n\n      ERROR_STATES = new HashSet<>();\n      ERROR_STATES.add(\"0A000\"); // FEATURE UNSUPPORTED\n      ERROR_STATES.add(\"57P01\"); // ADMIN SHUTDOWN\n      ERROR_STATES.add(\"57P02\"); // CRASH SHUTDOWN\n      ERROR_STATES.add(\"57P03\"); // CANNOT CONNECT NOW\n      ERROR_STATES.add(\"01002\"); // SQL92 disconnect error\n      ERROR_STATES.add(\"JZ0C0\"); // Sybase disconnect error\n      ERROR_STATES.add(\"JZ0C1\"); // Sybase disconnect error\n\n      ERROR_CODES = new HashSet<>();\n      ERROR_CODES.add(500150);\n      ERROR_CODES.add(2399);\n      ERROR_CODES.add(1105);\n   }\n\n   protected ProxyConnection(final PoolEntry poolEntry,\n                             final Connection connection,\n                             final FastList<Statement> openStatements,\n                             final ProxyLeakTask leakTask,\n                             final boolean isReadOnly,\n                             final boolean isAutoCommit) {\n      this.poolEntry = poolEntry;\n      this.delegate = connection;\n      this.openStatements = openStatements;\n      this.leakTask = leakTask;\n      this.isReadOnly = isReadOnly;\n      this.isAutoCommit = isAutoCommit;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public final String toString()\n   {\n      return this.getClass().getSimpleName() + '@' + System.identityHashCode(this) + \" wrapping \" + delegate;\n   }\n\n   // ***********************************************************************\n   //                     Connection State Accessors\n   // ***********************************************************************\n\n   final boolean getAutoCommitState()\n   {\n      return isAutoCommit;\n   }\n\n   final String getCatalogState()\n   {\n      return dbcatalog;\n   }\n\n   final String getSchemaState()\n   {\n      return dbschema;\n   }\n\n   final int getTransactionIsolationState()\n   {\n      return transactionIsolation;\n   }\n\n   final boolean getReadOnlyState()\n   {\n      return isReadOnly;\n   }\n\n   final int getNetworkTimeoutState()\n   {\n      return networkTimeout;\n   }\n\n   // ***********************************************************************\n   //                          Internal methods\n   // ***********************************************************************\n\n   final PoolEntry getPoolEntry()\n   {\n      return poolEntry;\n   }\n\n   @SuppressWarnings(\"ConstantConditions\")\n   final SQLException checkException(SQLException sqle)\n   {\n      var evict = false;\n      SQLException nse = sqle;\n      final var exceptionOverride = poolEntry.getPoolBase().exceptionOverride;\n      for (int depth = 0; delegate != ClosedConnection.CLOSED_CONNECTION && nse != null && depth < 10; depth++) {\n         final var sqlState = nse.getSQLState();\n         final var shouldEvict = exceptionOverride != null ? exceptionOverride.adjudicate(nse) : CONTINUE_EVICT;\n         if (shouldEvict == DO_NOT_EVICT) {\n            break;\n         }\n         else if (sqlState != null && sqlState.startsWith(\"08\")\n             || ERROR_STATES.contains(sqlState)\n             || ERROR_CODES.contains(nse.getErrorCode())\n             || shouldEvict == MUST_EVICT) {\n\n            // broken connection\n            evict = true;\n            break;\n         }\n         else {\n            nse = nse.getNextException();\n         }\n      }\n\n      if (evict) {\n         var exception = (nse != null) ? nse : sqle;\n         LOGGER.warn(\"{} - Connection {} marked as broken because of SQLSTATE({}), ErrorCode({})\",\n            poolEntry.getPoolName(), delegate, exception.getSQLState(), exception.getErrorCode(), exception);\n         leakTask.cancel();\n         poolEntry.evict(\"(connection is broken)\");\n         delegate = ClosedConnection.CLOSED_CONNECTION;\n      }\n\n      return sqle;\n   }\n\n   final synchronized void untrackStatement(final Statement statement)\n   {\n      openStatements.remove(statement);\n   }\n\n   final void markCommitStateDirty()\n   {\n      if (!isAutoCommit) {\n         isCommitStateDirty = true;\n      }\n   }\n\n   void cancelLeakTask()\n   {\n      leakTask.cancel();\n   }\n\n   private synchronized <T extends Statement> T trackStatement(final T statement)\n   {\n      openStatements.add(statement);\n\n      return statement;\n   }\n\n   @SuppressWarnings(\"EmptyTryBlock\")\n   private synchronized void closeStatements()\n   {\n      final var size = openStatements.size();\n      if (size > 0) {\n         for (int i = 0; i < size && delegate != ClosedConnection.CLOSED_CONNECTION; i++) {\n            try (Statement ignored = openStatements.get(i)) {\n               // automatic resource cleanup\n            }\n            catch (SQLException e) {\n               LOGGER.warn(\"{} - Connection {} marked as broken because of an exception closing open statements during Connection.close()\",\n                           poolEntry.getPoolName(), delegate);\n               leakTask.cancel();\n               poolEntry.evict(\"(exception closing Statements during Connection.close())\");\n               delegate = ClosedConnection.CLOSED_CONNECTION;\n            }\n         }\n\n         openStatements.clear();\n      }\n   }\n\n   // **********************************************************************\n   //              \"Overridden\" java.sql.Connection Methods\n   // **********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public final void close() throws SQLException\n   {\n      // Closing statements can cause connection eviction, so this must run before the conditional below\n      closeStatements();\n\n      if (delegate != ClosedConnection.CLOSED_CONNECTION) {\n         leakTask.cancel();\n\n         try {\n            if (isCommitStateDirty && !isAutoCommit) {\n               delegate.rollback();\n               LOGGER.debug(\"{} - Executed rollback on connection {} due to dirty commit state on close().\", poolEntry.getPoolName(), delegate);\n            }\n\n            if (dirtyBits != 0) {\n               poolEntry.resetConnectionState(this, dirtyBits);\n            }\n\n            delegate.clearWarnings();\n         }\n         catch (SQLException e) {\n            // when connections are aborted, exceptions are often thrown that should not reach the application\n            if (!poolEntry.isMarkedEvicted()) {\n               throw checkException(e);\n            }\n         }\n         finally {\n            delegate = ClosedConnection.CLOSED_CONNECTION;\n            poolEntry.recycle();\n         }\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   @SuppressWarnings(\"RedundantThrows\")\n   public boolean isClosed() throws SQLException\n   {\n      return (delegate == ClosedConnection.CLOSED_CONNECTION);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Statement createStatement() throws SQLException\n   {\n      return ProxyFactory.getProxyStatement(this, trackStatement(delegate.createStatement()));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Statement createStatement(int resultSetType, int concurrency) throws SQLException\n   {\n      return ProxyFactory.getProxyStatement(this, trackStatement(delegate.createStatement(resultSetType, concurrency)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Statement createStatement(int resultSetType, int concurrency, int holdability) throws SQLException\n   {\n      return ProxyFactory.getProxyStatement(this, trackStatement(delegate.createStatement(resultSetType, concurrency, holdability)));\n   }\n\n\n   /** {@inheritDoc} */\n   @Override\n   public CallableStatement prepareCall(String sql) throws SQLException\n   {\n      return ProxyFactory.getProxyCallableStatement(this, trackStatement(delegate.prepareCall(sql)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public CallableStatement prepareCall(String sql, int resultSetType, int concurrency) throws SQLException\n   {\n      return ProxyFactory.getProxyCallableStatement(this, trackStatement(delegate.prepareCall(sql, resultSetType, concurrency)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public CallableStatement prepareCall(String sql, int resultSetType, int concurrency, int holdability) throws SQLException\n   {\n      return ProxyFactory.getProxyCallableStatement(this, trackStatement(delegate.prepareCall(sql, resultSetType, concurrency, holdability)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql) throws SQLException\n   {\n      return ProxyFactory.getProxyPreparedStatement(this, trackStatement(delegate.prepareStatement(sql)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException\n   {\n      return ProxyFactory.getProxyPreparedStatement(this, trackStatement(delegate.prepareStatement(sql, autoGeneratedKeys)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, int resultSetType, int concurrency) throws SQLException\n   {\n      return ProxyFactory.getProxyPreparedStatement(this, trackStatement(delegate.prepareStatement(sql, resultSetType, concurrency)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, int resultSetType, int concurrency, int holdability) throws SQLException\n   {\n      return ProxyFactory.getProxyPreparedStatement(this, trackStatement(delegate.prepareStatement(sql, resultSetType, concurrency, holdability)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException\n   {\n      return ProxyFactory.getProxyPreparedStatement(this, trackStatement(delegate.prepareStatement(sql, columnIndexes)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException\n   {\n      return ProxyFactory.getProxyPreparedStatement(this, trackStatement(delegate.prepareStatement(sql, columnNames)));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public DatabaseMetaData getMetaData() throws SQLException\n   {\n      markCommitStateDirty();\n      return ProxyFactory.getProxyDatabaseMetaData(this, delegate.getMetaData());\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void commit() throws SQLException\n   {\n      delegate.commit();\n      isCommitStateDirty = false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void rollback() throws SQLException\n   {\n      delegate.rollback();\n      isCommitStateDirty = false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void rollback(Savepoint savepoint) throws SQLException\n   {\n      delegate.rollback(savepoint);\n      isCommitStateDirty = true;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean getAutoCommit() throws SQLException\n   {\n      if ((dirtyBits & DIRTY_BIT_AUTOCOMMIT) != 0) {\n         return isAutoCommit;\n      }\n      return delegate.getAutoCommit();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setAutoCommit(boolean autoCommit) throws SQLException\n   {\n      delegate.setAutoCommit(autoCommit);\n      isAutoCommit = autoCommit;\n      dirtyBits |= DIRTY_BIT_AUTOCOMMIT;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isReadOnly() throws SQLException\n   {\n      if ((dirtyBits & DIRTY_BIT_READONLY) != 0) {\n         return isReadOnly;\n      }\n      return delegate.isReadOnly();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setReadOnly(boolean readOnly) throws SQLException\n   {\n      delegate.setReadOnly(readOnly);\n      isReadOnly = readOnly;\n      dirtyBits |= DIRTY_BIT_READONLY;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getTransactionIsolation() throws SQLException\n   {\n      if ((dirtyBits & DIRTY_BIT_ISOLATION) != 0) {\n         return transactionIsolation;\n      }\n      return delegate.getTransactionIsolation();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setTransactionIsolation(int level) throws SQLException\n   {\n      delegate.setTransactionIsolation(level);\n      transactionIsolation = level;\n      dirtyBits |= DIRTY_BIT_ISOLATION;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String getCatalog() throws SQLException\n   {\n      if ((dirtyBits & DIRTY_BIT_CATALOG) != 0) {\n         return dbcatalog;\n      }\n      return delegate.getCatalog();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setCatalog(String catalog) throws SQLException\n   {\n      delegate.setCatalog(catalog);\n      dbcatalog = catalog;\n      dirtyBits |= DIRTY_BIT_CATALOG;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getNetworkTimeout() throws SQLException\n   {\n      if ((dirtyBits & DIRTY_BIT_NETTIMEOUT) != 0) {\n         return networkTimeout;\n      }\n      return delegate.getNetworkTimeout();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException\n   {\n      delegate.setNetworkTimeout(executor, milliseconds);\n      networkTimeout = milliseconds;\n      dirtyBits |= DIRTY_BIT_NETTIMEOUT;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String getSchema() throws SQLException\n   {\n      if ((dirtyBits & DIRTY_BIT_SCHEMA) != 0) {\n         return dbschema;\n      }\n      return delegate.getSchema();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setSchema(String schema) throws SQLException\n   {\n      delegate.setSchema(schema);\n      dbschema = delegate.getSchema();\n      dirtyBits |= DIRTY_BIT_SCHEMA;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public final boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      return iface.isInstance(delegate) || (delegate != null && delegate.isWrapperFor(iface));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   @SuppressWarnings(\"unchecked\")\n   public final <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      if (iface.isInstance(delegate)) {\n         return (T) delegate;\n      }\n      else if (delegate != null) {\n          return delegate.unwrap(iface);\n      }\n\n      throw new SQLException(\"Wrapped connection is not an instance of \" + iface);\n   }\n\n   // **********************************************************************\n   //                         Private classes\n   // **********************************************************************\n\n   private static final class ClosedConnection\n   {\n      static final Connection CLOSED_CONNECTION = getClosedConnection();\n\n      private static Connection getClosedConnection()\n      {\n         InvocationHandler handler = (proxy, method, args) -> {\n            final String methodName = method.getName();\n            switch (methodName) {\n               case \"isClosed\":\n                  return Boolean.TRUE;\n               case \"isValid\":\n                  return Boolean.FALSE;\n               case \"abort\":\n                  return Void.TYPE;\n               case \"close\":\n                  return Void.TYPE;\n               case \"toString\":\n                  return ClosedConnection.class.getCanonicalName();\n            }\n\n            throw new SQLException(\"Connection is closed\");\n         };\n\n         return (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), new Class[] { Connection.class }, handler);\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyDatabaseMetaData.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.sql.Connection;\nimport java.sql.DatabaseMetaData;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\n/**\n * This is the proxy class for {@link DatabaseMetaData}.\n *\n * @author Brett Wooldridge\n * @author Yanming Zhou\n */\npublic abstract class ProxyDatabaseMetaData implements DatabaseMetaData\n{\n   protected final ProxyConnection connection;\n\n   @SuppressWarnings(\"WeakerAccess\")\n   protected final DatabaseMetaData delegate;\n\n   ProxyDatabaseMetaData(ProxyConnection connection, DatabaseMetaData metaData)\n   {\n      this.connection = connection;\n      this.delegate = metaData;\n   }\n\n   final SQLException checkException(SQLException e)\n   {\n      return connection.checkException(e);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public final String toString()\n   {\n      final var delegateToString = delegate.toString();\n      return this.getClass().getSimpleName() + '@' + System.identityHashCode(this) + \" wrapping \" + delegateToString;\n   }\n\n   // **********************************************************************\n   //                 Overridden java.sql.DatabaseMetaData Methods\n   // **********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public final Connection getConnection()\n   {\n      return connection;\n   }\n\n   @Override\n   public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {\n      var resultSet = delegate.getProcedures(catalog, schemaPattern, procedureNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException {\n      var resultSet = delegate.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException {\n      var resultSet = delegate.getTables(catalog, schemaPattern, tableNamePattern, types);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getSchemas() throws SQLException {\n      var resultSet = delegate.getSchemas();\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getCatalogs() throws SQLException {\n      var resultSet = delegate.getCatalogs();\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getTableTypes() throws SQLException {\n      var resultSet = delegate.getTableTypes();\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {\n      var resultSet = delegate.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException {\n      var resultSet = delegate.getColumnPrivileges(catalog, schema, table, columnNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {\n      var resultSet = delegate.getTablePrivileges(catalog, schemaPattern, tableNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException {\n      var resultSet = delegate.getBestRowIdentifier(catalog, schema, table, scope, nullable);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {\n      var resultSet = delegate.getVersionColumns(catalog, schema, table);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {\n      var resultSet = delegate.getPrimaryKeys(catalog, schema, table);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {\n      var resultSet = delegate.getImportedKeys(catalog, schema, table);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {\n      var resultSet = delegate.getExportedKeys(catalog, schema, table);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException {\n      var resultSet = delegate.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getTypeInfo() throws SQLException {\n      var resultSet = delegate.getTypeInfo();\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException {\n      var resultSet = delegate.getIndexInfo(catalog, schema, table, unique, approximate);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException {\n      var resultSet = delegate.getUDTs(catalog, schemaPattern, typeNamePattern, types);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {\n      var resultSet = delegate.getSuperTypes(catalog, schemaPattern, typeNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {\n      var resultSet = delegate.getSuperTables(catalog, schemaPattern, tableNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException {\n      var resultSet = delegate.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {\n      var resultSet = delegate.getSchemas(catalog, schemaPattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getClientInfoProperties() throws SQLException {\n      var resultSet = delegate.getClientInfoProperties();\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {\n      var resultSet = delegate.getFunctions(catalog, schemaPattern, functionNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException {\n      var resultSet = delegate.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   @Override\n   public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {\n      var resultSet = delegate.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);\n      var statement = resultSet.getStatement();\n      if (statement != null) {\n         statement = ProxyFactory.getProxyStatement(connection, statement);\n      }\n      return ProxyFactory.getProxyResultSet(connection, (ProxyStatement) statement, resultSet);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public final boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      return iface.isInstance(delegate) || (delegate != null && delegate.isWrapperFor(iface));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   @SuppressWarnings(\"unchecked\")\n   public final <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      if (iface.isInstance(delegate)) {\n         return (T) delegate;\n      }\n      else if (delegate != null) {\n         return delegate.unwrap(iface);\n      }\n\n      throw new SQLException(\"Wrapped DatabaseMetaData is not an instance of \" + iface);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyFactory.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.sql.*;\n\nimport com.zaxxer.hikari.util.FastList;\n\n/**\n * A factory class that produces proxies around instances of the standard\n * JDBC interfaces.\n *\n * @author Brett Wooldridge\n */\npublic final class ProxyFactory\n{\n   private ProxyFactory()\n   {\n      // unconstructable\n   }\n\n   /**\n    * Create a proxy for the specified {@link Connection} instance.\n    * @param poolEntry the PoolEntry holding pool state\n    * @param connection the raw database Connection\n    * @param openStatements a reusable list to track open Statement instances\n    * @param leakTask the ProxyLeakTask for this connection\n    * @param isReadOnly the default readOnly state of the connection\n    * @param isAutoCommit the default autoCommit state of the connection\n    * @return a proxy that wraps the specified {@link Connection}\n    */\n   static ProxyConnection getProxyConnection(final PoolEntry poolEntry, final Connection connection, final FastList<Statement> openStatements, final ProxyLeakTask leakTask, final boolean isReadOnly, final boolean isAutoCommit)\n   {\n      // Body is replaced (injected) by JavassistProxyFactory\n      throw new IllegalStateException(\"You need to run the CLI build and you need target/classes in your classpath to run.\");\n   }\n\n   static Statement getProxyStatement(final ProxyConnection connection, final Statement statement)\n   {\n      // Body is replaced (injected) by JavassistProxyFactory\n      throw new IllegalStateException(\"You need to run the CLI build and you need target/classes in your classpath to run.\");\n   }\n\n   static CallableStatement getProxyCallableStatement(final ProxyConnection connection, final CallableStatement statement)\n   {\n      // Body is replaced (injected) by JavassistProxyFactory\n      throw new IllegalStateException(\"You need to run the CLI build and you need target/classes in your classpath to run.\");\n   }\n\n   static PreparedStatement getProxyPreparedStatement(final ProxyConnection connection, final PreparedStatement statement)\n   {\n      // Body is replaced (injected) by JavassistProxyFactory\n      throw new IllegalStateException(\"You need to run the CLI build and you need target/classes in your classpath to run.\");\n   }\n\n   static ResultSet getProxyResultSet(final ProxyConnection connection, final ProxyStatement statement, final ResultSet resultSet)\n   {\n      // Body is replaced (injected) by JavassistProxyFactory\n      throw new IllegalStateException(\"You need to run the CLI build and you need target/classes in your classpath to run.\");\n   }\n\n   static DatabaseMetaData getProxyDatabaseMetaData(final ProxyConnection connection, final DatabaseMetaData metaData)\n   {\n      // Body is replaced (injected) by JavassistProxyFactory\n      throw new IllegalStateException(\"You need to run the CLI build and you need target/classes in your classpath to run.\");\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyLeakTask.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.TimeUnit;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * A Runnable that is scheduled in the future to report leaks.  The ScheduledFuture is\n * cancelled if the connection is closed before the leak time expires.\n *\n * @author Brett Wooldridge\n */\nclass ProxyLeakTask implements Runnable\n{\n   private static final Logger LOGGER = LoggerFactory.getLogger(ProxyLeakTask.class);\n   static final ProxyLeakTask NO_LEAK;\n\n   private ScheduledFuture<?> scheduledFuture;\n   private String connectionName;\n   private Exception exception;\n   private String threadName;\n   private boolean isLeaked;\n\n   static\n   {\n      NO_LEAK = new ProxyLeakTask() {\n         @Override\n         void schedule(ScheduledExecutorService executorService, long leakDetectionThreshold) {}\n\n         @Override\n         public void run() {}\n\n         @Override\n         public void cancel() {}\n      };\n   }\n\n   ProxyLeakTask(final PoolEntry poolEntry)\n   {\n      this.exception = new Exception(\"Apparent connection leak detected\");\n      this.threadName = Thread.currentThread().getName();\n      this.connectionName = poolEntry.connection.toString();\n   }\n\n   private ProxyLeakTask()\n   {\n   }\n\n   void schedule(ScheduledExecutorService executorService, long leakDetectionThreshold)\n   {\n      scheduledFuture = executorService.schedule(this, leakDetectionThreshold, TimeUnit.MILLISECONDS);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void run()\n   {\n      isLeaked = true;\n\n      final var stackTrace = exception.getStackTrace();\n      final var trace = new StackTraceElement[stackTrace.length - 5];\n\n      System.arraycopy(stackTrace, 5, trace, 0, trace.length);\n\n      exception.setStackTrace(trace);\n      LOGGER.warn(\"Connection leak detection triggered for {} on thread {}, stack trace follows\", connectionName, threadName, exception);\n   }\n\n   void cancel()\n   {\n      scheduledFuture.cancel(false);\n      if (isLeaked) {\n         LOGGER.info(\"Previously reported leaked connection {} on thread {} was returned to the pool (unleaked)\", connectionName, threadName);\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyLeakTaskFactory.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.util.concurrent.ScheduledExecutorService;\n\n/**\n * A factory for {@link ProxyLeakTask} Runnables that are scheduled in the future to report leaks.\n *\n * @author Brett Wooldridge\n * @author Andreas Brenk\n */\nclass ProxyLeakTaskFactory\n{\n   private ScheduledExecutorService executorService;\n   private long leakDetectionThreshold;\n\n   ProxyLeakTaskFactory(final long leakDetectionThreshold, final ScheduledExecutorService executorService)\n   {\n      this.executorService = executorService;\n      this.leakDetectionThreshold = leakDetectionThreshold;\n   }\n\n   ProxyLeakTask schedule(final PoolEntry poolEntry)\n   {\n      return (leakDetectionThreshold == 0) ? ProxyLeakTask.NO_LEAK : scheduleNewTask(poolEntry);\n   }\n\n   void updateLeakDetectionThreshold(final long leakDetectionThreshold)\n   {\n      this.leakDetectionThreshold = leakDetectionThreshold;\n   }\n\n   private ProxyLeakTask scheduleNewTask(PoolEntry poolEntry) {\n      var task = new ProxyLeakTask(poolEntry);\n      task.schedule(executorService, leakDetectionThreshold);\n\n      return task;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyPreparedStatement.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\n/**\n * This is the proxy class for {@link PreparedStatement}.\n *\n * @author Brett Wooldridge\n */\npublic abstract class ProxyPreparedStatement extends ProxyStatement implements PreparedStatement\n{\n   ProxyPreparedStatement(ProxyConnection connection, PreparedStatement statement)\n   {\n      super(connection, statement);\n   }\n\n   // **********************************************************************\n   //              Overridden java.sql.PreparedStatement Methods\n   // **********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return ((PreparedStatement) delegate).execute();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ResultSet executeQuery() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      var resultSet = ((PreparedStatement) delegate).executeQuery();\n      return ProxyFactory.getProxyResultSet(connection, this, resultSet);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return ((PreparedStatement) delegate).executeUpdate();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long executeLargeUpdate() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return ((PreparedStatement) delegate).executeLargeUpdate();\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyResultSet.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\n/**\n * This is the proxy class for {@link ResultSet}.\n *\n * @author Brett Wooldridge\n * @author Yanming Zhou\n */\npublic abstract class ProxyResultSet implements ResultSet\n{\n   protected final ProxyConnection connection;\n   protected final ProxyStatement statement;\n   final ResultSet delegate;\n\n   protected ProxyResultSet(ProxyConnection connection, ProxyStatement statement, ResultSet resultSet)\n   {\n      this.connection = connection;\n      this.statement = statement;\n      this.delegate = resultSet;\n   }\n\n   final SQLException checkException(SQLException e)\n   {\n      return connection.checkException(e);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String toString()\n   {\n      return this.getClass().getSimpleName() + '@' + System.identityHashCode(this) + \" wrapping \" + delegate;\n   }\n\n   // **********************************************************************\n   //                 Overridden java.sql.ResultSet Methods\n   // **********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public final Statement getStatement() throws SQLException\n   {\n      return statement;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void updateRow() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      delegate.updateRow();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void insertRow() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      delegate.insertRow();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void deleteRow() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      delegate.deleteRow();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public final boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      return iface.isInstance(delegate) || (delegate != null && delegate.isWrapperFor(iface));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   @SuppressWarnings(\"unchecked\")\n   public final <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      if (iface.isInstance(delegate)) {\n         return (T) delegate;\n      }\n      else if (delegate != null) {\n          return delegate.unwrap(iface);\n      }\n\n      throw new SQLException(\"Wrapped ResultSet is not an instance of \" + iface);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/pool/ProxyStatement.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\n/**\n * This is the proxy class for {@link Statement}.\n *\n * @author Brett Wooldridge\n * @author Yanming Zhou\n */\npublic abstract class ProxyStatement implements Statement\n{\n   protected final ProxyConnection connection;\n   final Statement delegate;\n\n   private boolean isClosed;\n   private ResultSet proxyResultSet;\n\n   ProxyStatement(ProxyConnection connection, Statement statement)\n   {\n      this.connection = connection;\n      this.delegate = statement;\n   }\n\n   final SQLException checkException(SQLException e)\n   {\n      return connection.checkException(e);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public final String toString()\n   {\n      final var delegateToString = delegate.toString();\n      return this.getClass().getSimpleName() + '@' + System.identityHashCode(this) + \" wrapping \" + delegateToString;\n   }\n\n   // **********************************************************************\n   //                 Overridden java.sql.Statement Methods\n   // **********************************************************************\n\n   /** {@inheritDoc} */\n   @Override\n   public final void close() throws SQLException\n   {\n      synchronized (this) {\n         if (isClosed) {\n            return;\n         }\n\n         isClosed = true;\n      }\n\n      connection.untrackStatement(delegate);\n\n      try {\n         delegate.close();\n      }\n      catch (SQLException e) {\n         throw connection.checkException(e);\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Connection getConnection() throws SQLException\n   {\n      return connection;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute(String sql) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.execute(sql);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute(String sql, int autoGeneratedKeys) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.execute(sql, autoGeneratedKeys);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ResultSet executeQuery(String sql) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      ResultSet resultSet = delegate.executeQuery(sql);\n      return ProxyFactory.getProxyResultSet(connection, this, resultSet);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate(String sql) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeUpdate(sql);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int[] executeBatch() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeBatch();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeUpdate(sql, autoGeneratedKeys);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate(String sql, int[] columnIndexes) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeUpdate(sql, columnIndexes);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate(String sql, String[] columnNames) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeUpdate(sql, columnNames);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute(String sql, int[] columnIndexes) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.execute(sql, columnIndexes);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute(String sql, String[] columnNames) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.execute(sql, columnNames);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long[] executeLargeBatch() throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeLargeBatch();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long executeLargeUpdate(String sql) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeLargeUpdate(sql);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeLargeUpdate(sql, autoGeneratedKeys);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeLargeUpdate(sql, columnIndexes);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException\n   {\n      connection.markCommitStateDirty();\n      return delegate.executeLargeUpdate(sql, columnNames);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ResultSet getResultSet() throws SQLException {\n      final var resultSet = delegate.getResultSet();\n      if (resultSet != null) {\n         if (proxyResultSet == null || ((ProxyResultSet) proxyResultSet).delegate != resultSet) {\n            proxyResultSet = ProxyFactory.getProxyResultSet(connection, this, resultSet);\n         }\n      }\n      else {\n         proxyResultSet = null;\n      }\n      return proxyResultSet;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ResultSet getGeneratedKeys() throws SQLException\n   {\n      var resultSet = delegate.getGeneratedKeys();\n      if (proxyResultSet == null || ((ProxyResultSet) proxyResultSet).delegate != resultSet) {\n         proxyResultSet = ProxyFactory.getProxyResultSet(connection, this, resultSet);\n      }\n      return proxyResultSet;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public final boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      return iface.isInstance(delegate) || (delegate != null && delegate.isWrapperFor(iface));\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   @SuppressWarnings(\"unchecked\")\n   public final <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      if (iface.isInstance(delegate)) {\n         return (T) delegate;\n      }\n      else if (delegate != null) {\n          return delegate.unwrap(iface);\n      }\n\n      throw new SQLException(\"Wrapped statement is not an instance of \" + iface);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/ClockSource.java",
    "content": "/*\n * Copyright (C) 2015 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport static java.util.concurrent.TimeUnit.DAYS;\nimport static java.util.concurrent.TimeUnit.HOURS;\nimport static java.util.concurrent.TimeUnit.MICROSECONDS;\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\nimport static java.util.concurrent.TimeUnit.MINUTES;\nimport static java.util.concurrent.TimeUnit.NANOSECONDS;\nimport static java.util.concurrent.TimeUnit.SECONDS;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * A resolution-independent provider of current time-stamps and elapsed time\n * calculations.\n *\n * @author Brett Wooldridge\n * @hidden\n */\npublic interface ClockSource\n{\n   static ClockSource CLOCK = Factory.create();\n\n   /**\n    * Get the current time-stamp (resolution is opaque).\n    *\n    * @return the current time-stamp\n    */\n   static long currentTime() {\n      return CLOCK.currentTime0();\n   }\n\n   long currentTime0();\n\n   /**\n    * Convert an opaque time-stamp returned by currentTime() into\n    * milliseconds.\n    *\n    * @param time an opaque time-stamp returned by an instance of this class\n    * @return the time-stamp in milliseconds\n    */\n   static long toMillis(long time) {\n      return CLOCK.toMillis0(time);\n   }\n\n   long toMillis0(long time);\n\n   /**\n    * Convert an opaque time-stamp returned by currentTime() into\n    * nanoseconds.\n    *\n    * @param time an opaque time-stamp returned by an instance of this class\n    * @return the time-stamp in nanoseconds\n    */\n   static long toNanos(long time) {\n      return CLOCK.toNanos0(time);\n   }\n\n   long toNanos0(long time);\n\n   /**\n    * Convert an opaque time-stamp returned by currentTime() into an\n    * elapsed time in milliseconds, based on the current instant in time.\n    *\n    * @param startTime an opaque time-stamp returned by an instance of this class\n    * @return the elapsed time between startTime and now in milliseconds\n    */\n   static long elapsedMillis(long startTime) {\n      return CLOCK.elapsedMillis0(startTime);\n   }\n\n   long elapsedMillis0(long startTime);\n\n   /**\n    * Get the difference in milliseconds between two opaque time-stamps returned\n    * by currentTime().\n    *\n    * @param startTime an opaque time-stamp returned by an instance of this class\n    * @param endTime an opaque time-stamp returned by an instance of this class\n    * @return the elapsed time between startTime and endTime in milliseconds\n    */\n   static long elapsedMillis(long startTime, long endTime) {\n      return CLOCK.elapsedMillis0(startTime, endTime);\n   }\n\n   long elapsedMillis0(long startTime, long endTime);\n\n   /**\n    * Convert an opaque time-stamp returned by currentTime() into an\n    * elapsed time in milliseconds, based on the current instant in time.\n    *\n    * @param startTime an opaque time-stamp returned by an instance of this class\n    * @return the elapsed time between startTime and now in milliseconds\n    */\n   static long elapsedNanos(long startTime) {\n      return CLOCK.elapsedNanos0(startTime);\n   }\n\n   long elapsedNanos0(long startTime);\n\n   /**\n    * Get the difference in nanoseconds between two opaque time-stamps returned\n    * by currentTime().\n    *\n    * @param startTime an opaque time-stamp returned by an instance of this class\n    * @param endTime an opaque time-stamp returned by an instance of this class\n    * @return the elapsed time between startTime and endTime in nanoseconds\n    */\n   static long elapsedNanos(long startTime, long endTime) {\n      return CLOCK.elapsedNanos0(startTime, endTime);\n   }\n\n   long elapsedNanos0(long startTime, long endTime);\n\n   /**\n    * Return the specified opaque time-stamp plus the specified number of milliseconds.\n    *\n    * @param time an opaque time-stamp\n    * @param millis milliseconds to add\n    * @return a new opaque time-stamp\n    */\n   static long plusMillis(long time, long millis) {\n      return CLOCK.plusMillis0(time, millis);\n   }\n\n   long plusMillis0(long time, long millis);\n\n   /**\n    * Get the TimeUnit the ClockSource is denominated in.\n    * @return the TimeUnit used by the ClockSource\n    */\n   static TimeUnit getSourceTimeUnit() {\n      return CLOCK.getSourceTimeUnit0();\n   }\n\n   TimeUnit getSourceTimeUnit0();\n\n   /**\n    * Get a String representation of the elapsed time in appropriate magnitude terminology.\n    *\n    * @param startTime an opaque time-stamp\n    * @param endTime an opaque time-stamp\n    * @return a string representation of the elapsed time interval\n    */\n   static String elapsedDisplayString(long startTime, long endTime) {\n      return CLOCK.elapsedDisplayString0(startTime, endTime);\n   }\n\n   default String elapsedDisplayString0(long startTime, long endTime) {\n      long elapsedNanos = elapsedNanos0(startTime, endTime);\n\n      StringBuilder sb = new StringBuilder(elapsedNanos < 0 ? \"-\" : \"\");\n      elapsedNanos = Math.abs(elapsedNanos);\n\n      for (TimeUnit unit : TIMEUNITS_DESCENDING) {\n         long converted = unit.convert(elapsedNanos, NANOSECONDS);\n         if (converted > 0) {\n            sb.append(converted).append(TIMEUNIT_DISPLAY_VALUES[unit.ordinal()]);\n            elapsedNanos -= NANOSECONDS.convert(converted, unit);\n         }\n      }\n\n      return sb.toString();\n   }\n\n   TimeUnit[] TIMEUNITS_DESCENDING = {DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS};\n\n   String[] TIMEUNIT_DISPLAY_VALUES = {\"ns\", \"µs\", \"ms\", \"s\", \"m\", \"h\", \"d\"};\n\n   /**\n    * Factory class used to create a platform-specific ClockSource.\n    * @hidden\n    */\n   class Factory\n   {\n      private static ClockSource create() {\n         String os = System.getProperty(\"os.name\");\n         if (\"Mac OS X\".equals(os)) {\n            return new MillisecondClockSource();\n         }\n\n         return new NanosecondClockSource();\n      }\n   }\n\n   /**\n    * A ClockSource that uses System.currentTimeMillis() for time-stamps.\n    * This is the default implementation on Mac OS X, and is used when\n    * System.nanoTime() is not available.\n    * @hidden\n    */\n   final class MillisecondClockSource implements ClockSource\n   {\n      /** {@inheritDoc} */\n      @Override\n      public long currentTime0() {\n         return System.currentTimeMillis();\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long elapsedMillis0(final long startTime) {\n         return System.currentTimeMillis() - startTime;\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long elapsedMillis0(final long startTime, final long endTime) {\n         return endTime - startTime;\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long elapsedNanos0(final long startTime) {\n         return MILLISECONDS.toNanos(System.currentTimeMillis() - startTime);\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long elapsedNanos0(final long startTime, final long endTime) {\n         return MILLISECONDS.toNanos(endTime - startTime);\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long toMillis0(final long time) {\n         return time;\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long toNanos0(final long time) {\n         return MILLISECONDS.toNanos(time);\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long plusMillis0(final long time, final long millis) {\n         return time + millis;\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public TimeUnit getSourceTimeUnit0() {\n         return MILLISECONDS;\n      }\n   }\n\n   /**\n    * A ClockSource that uses System.nanoTime() for time-stamps.\n    * This is the default implementation on all platforms except Mac OS X.\n    * @hidden\n    */\n   class NanosecondClockSource implements ClockSource\n   {\n      /** {@inheritDoc} */\n      @Override\n      public long currentTime0() {\n         return System.nanoTime();\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long toMillis0(final long time) {\n         return NANOSECONDS.toMillis(time);\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long toNanos0(final long time) {\n         return time;\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long elapsedMillis0(final long startTime) {\n         return NANOSECONDS.toMillis(System.nanoTime() - startTime);\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long elapsedMillis0(final long startTime, final long endTime) {\n         return NANOSECONDS.toMillis(endTime - startTime);\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long elapsedNanos0(final long startTime) {\n         return System.nanoTime() - startTime;\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long elapsedNanos0(final long startTime, final long endTime) {\n         return endTime - startTime;\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public long plusMillis0(final long time, final long millis) {\n         return time + MILLISECONDS.toNanos(millis);\n      }\n\n      /** {@inheritDoc} */\n      @Override\n      public TimeUnit getSourceTimeUnit0() {\n         return NANOSECONDS;\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/ConcurrentBag.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.util;\n\nimport com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.SynchronousQueue;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.stream.Collectors;\n\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\nimport static com.zaxxer.hikari.util.ClockSource.elapsedNanos;\nimport static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.*;\nimport static java.util.concurrent.TimeUnit.MICROSECONDS;\nimport static java.util.concurrent.TimeUnit.NANOSECONDS;\nimport static java.util.concurrent.locks.LockSupport.parkNanos;\n\n/**\n * This is a specialized concurrent bag that achieves superior performance\n * to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a\n * connection pool.  It uses ThreadLocal storage when possible to avoid\n * locks, but resorts to scanning a common collection if there are no\n * available items in the ThreadLocal list.  Not-in-use items in the\n * ThreadLocal lists can be \"stolen\" when the borrowing thread has none\n * of its own.  It is a \"lock-less\" implementation using a specialized\n * AbstractQueuedLongSynchronizer to manage cross-thread signaling.\n * <p>\n * Note that items that are \"borrowed\" from the bag are not actually\n * removed from any collection, so garbage collection will not occur\n * even if the reference is abandoned.  Thus care must be taken to\n * \"requite\" borrowed objects otherwise a memory leak will result.  Only\n * the \"remove\" method can completely remove an object from the bag.\n *\n * @author Brett Wooldridge\n *\n * @param <T> the templated type to store in the bag\n * @hidden\n */\n@SuppressWarnings(\"DuplicatedCode\")\npublic class ConcurrentBag<T extends IConcurrentBagEntry> implements AutoCloseable\n{\n   private static final Logger LOGGER = LoggerFactory.getLogger(ConcurrentBag.class);\n\n   private final CopyOnWriteArrayList<T> sharedList;\n   private final boolean useWeakThreadLocals;\n\n   private final ThreadLocal<List<Object>> threadLocalList;\n   private final IBagStateListener listener;\n   private final AtomicInteger waiters;\n   private volatile boolean closed;\n\n   private final SynchronousQueue<T> handoffQueue;\n\n   /**\n    * This interface defines the contract for an entry in the ConcurrentBag.\n    * It provides methods to manage the state of the entry, which can be\n    * \"not in use\", \"in use\", \"removed\", or \"reserved\".\n    * @hidden\n    */\n   public interface IConcurrentBagEntry\n   {\n      int STATE_NOT_IN_USE = 0;\n      int STATE_IN_USE = 1;\n      int STATE_REMOVED = -1;\n      int STATE_RESERVED = -2;\n\n      boolean compareAndSet(int expectState, int newState);\n      void setState(int newState);\n      int getState();\n   }\n\n   /**\n    * This interface defines a listener that will be notified when items\n    * are added to the bag, allowing for external management of bag state.\n    * The listener is typically used to inform the pool manager about the\n    * number of items waiting for a bag item to become available.\n    * @hidden\n    */\n   public interface IBagStateListener\n   {\n      void addBagItem(int waiting);\n   }\n\n   /**\n    * Construct a ConcurrentBag with the specified listener.\n    *\n    * @param listener the IBagStateListener to attach to this bag\n    */\n   public ConcurrentBag(final IBagStateListener listener)\n   {\n      this.listener = listener;\n      this.useWeakThreadLocals = useWeakThreadLocals();\n\n      this.handoffQueue = new SynchronousQueue<>(true);\n      this.waiters = new AtomicInteger();\n      this.sharedList = new CopyOnWriteArrayList<>();\n      this.threadLocalList = ThreadLocal.withInitial(() ->\n         useWeakThreadLocals ? new ArrayList<>(16) : new FastList<>(IConcurrentBagEntry.class, 16)\n      );\n   }\n\n   /**\n    * The method will borrow a BagEntry from the bag, blocking for the\n    * specified timeout if none are available.\n    *\n    * @param timeout how long to wait before giving up, in units of unit\n    * @param timeUnit a <code>TimeUnit</code> determining how to interpret the timeout parameter\n    * @return a borrowed instance from the bag or null if a timeout occurs\n    * @throws InterruptedException if interrupted while waiting\n    */\n   public T borrow(long timeout, final TimeUnit timeUnit) throws InterruptedException\n   {\n      // Try the thread-local list first\n      final var list = threadLocalList.get();\n      for (var i = list.size() - 1; i >= 0; i--) {\n         final var entry = list.remove(i);\n         @SuppressWarnings(\"unchecked\")\n         final T bagEntry = useWeakThreadLocals ? ((WeakReference<T>) entry).get() : (T) entry;\n         if (bagEntry != null && bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {\n            return bagEntry;\n         }\n      }\n\n      // Otherwise, scan the shared list ... then poll the handoff queue\n      final var waiting = waiters.incrementAndGet();\n      try {\n         for (T bagEntry : sharedList) {\n            if (bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {\n               // If we may have stolen another waiter's connection, request another bag add.\n               if (waiting > 1) {\n                  listener.addBagItem(waiting - 1);\n               }\n               return bagEntry;\n            }\n         }\n\n         listener.addBagItem(waiting);\n\n         timeout = timeUnit.toNanos(timeout);\n         do {\n            final var start = currentTime();\n            final T bagEntry = handoffQueue.poll(timeout, NANOSECONDS);\n            if (bagEntry == null || bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_IN_USE)) {\n               return bagEntry;\n            }\n\n            timeout -= elapsedNanos(start);\n         } while (timeout > 10_000);\n\n         return null;\n      }\n      finally {\n         waiters.decrementAndGet();\n      }\n   }\n\n   /**\n    * This method will return a borrowed object to the bag.  Objects\n    * that are borrowed from the bag but never \"requited\" will result\n    * in a memory leak.\n    *\n    * @param bagEntry the value to return to the bag\n    * @throws NullPointerException if value is null\n    * @throws IllegalStateException if the bagEntry was not borrowed from the bag\n    */\n   public void requite(final T bagEntry)\n   {\n      bagEntry.setState(STATE_NOT_IN_USE);\n\n      for (int i = 1, waiting = waiters.get(); waiting > 0; i++, waiting = waiters.get()) {\n         if (bagEntry.getState() != STATE_NOT_IN_USE || handoffQueue.offer(bagEntry)) {\n            return;\n         }\n         else if ((i & 0xff) == 0xff || (waiting > 1 && i % waiting == 0)) {\n            parkNanos(MICROSECONDS.toNanos(10));\n         }\n         else {\n            Thread.yield();\n         }\n      }\n\n      final var threadLocalEntries = this.threadLocalList.get();\n      if (threadLocalEntries.size() < 16) {\n         threadLocalEntries.add(useWeakThreadLocals ? new WeakReference<>(bagEntry) : bagEntry);\n      }\n   }\n\n   /**\n    * Add a new object to the bag for others to borrow.\n    *\n    * @param bagEntry an object to add to the bag\n    */\n   public void add(final T bagEntry)\n   {\n      if (closed) {\n         LOGGER.info(\"ConcurrentBag has been closed, ignoring add()\");\n         throw new IllegalStateException(\"ConcurrentBag has been closed, ignoring add()\");\n      }\n\n      sharedList.add(bagEntry);\n\n      // spin until a thread takes it or none are waiting\n      while (waiters.get() > 0 && bagEntry.getState() == STATE_NOT_IN_USE && !handoffQueue.offer(bagEntry)) {\n         Thread.yield();\n      }\n   }\n\n   /**\n    * Remove a value from the bag.  This method should only be called\n    * with objects obtained by <code>borrow(long, TimeUnit)</code> or <code>reserve(T)</code>\n    *\n    * @param bagEntry the value to remove\n    * @return true if the entry was removed, false otherwise\n    * @throws IllegalStateException if an attempt is made to remove an object\n    *         from the bag that was not borrowed or reserved first\n    */\n   public boolean remove(final T bagEntry)\n   {\n      if (!bagEntry.compareAndSet(STATE_IN_USE, STATE_REMOVED) && !bagEntry.compareAndSet(STATE_RESERVED, STATE_REMOVED) && !closed) {\n         LOGGER.warn(\"Attempt to remove an object from the bag that was not borrowed or reserved: {}\", bagEntry);\n         return false;\n      }\n\n      final var removed = sharedList.remove(bagEntry);\n      if (!removed && !closed) {\n         LOGGER.warn(\"Attempt to remove an object from the bag that does not exist: {}\", bagEntry);\n      }\n\n      threadLocalList.get().remove(bagEntry);\n\n      return removed;\n   }\n\n   /**\n    * Close the bag to further adds.\n    */\n   @Override\n   public void close()\n   {\n      closed = true;\n   }\n\n   /**\n    * This method provides a \"snapshot\" in time of the BagEntry\n    * items in the bag in the specified state.  It does not \"lock\"\n    * or reserve items in any way.  Call <code>reserve(T)</code>\n    * on items in list before performing any action on them.\n    *\n    * @param state one of the {@link IConcurrentBagEntry} states\n    * @return a possibly empty list of objects having the state specified\n    */\n   public List<T> values(final int state)\n   {\n      final var list = sharedList.stream().filter(e -> e.getState() == state).collect(Collectors.toList());\n      Collections.reverse(list);\n      return list;\n   }\n\n   /**\n    * This method provides a \"snapshot\" in time of the bag items.  It\n    * does not \"lock\" or reserve items in any way.  Call <code>reserve(T)</code>\n    * on items in the list, or understand the concurrency implications of\n    * modifying items, before performing any action on them.\n    *\n    * @return a possibly empty list of (all) bag items\n    */\n   @SuppressWarnings(\"unchecked\")\n   public List<T> values()\n   {\n      return (List<T>) sharedList.clone();\n   }\n\n   /**\n    * The method is used to make an item in the bag \"unavailable\" for\n    * borrowing.  It is primarily used when wanting to operate on items\n    * returned by the <code>values(int)</code> method.  Items that are\n    * reserved can be removed from the bag via <code>remove(T)</code>\n    * without the need to unreserve them.  Items that are not removed\n    * from the bag can be make available for borrowing again by calling\n    * the <code>unreserve(T)</code> method.\n    *\n    * @param bagEntry the item to reserve\n    * @return true if the item was able to be reserved, false otherwise\n    */\n   public boolean reserve(final T bagEntry)\n   {\n      return bagEntry.compareAndSet(STATE_NOT_IN_USE, STATE_RESERVED);\n   }\n\n   /**\n    * This method is used to make an item reserved via <code>reserve(T)</code>\n    * available again for borrowing.\n    *\n    * @param bagEntry the item to unreserve\n    */\n   @SuppressWarnings(\"SpellCheckingInspection\")\n   public void unreserve(final T bagEntry)\n   {\n      if (bagEntry.compareAndSet(STATE_RESERVED, STATE_NOT_IN_USE)) {\n         // spin until a thread takes it or none are waiting\n         for (int i = 1, waiting = waiters.get(); waiting > 0; i++, waiting = waiters.get()) {\n            if (bagEntry.getState() != STATE_NOT_IN_USE || handoffQueue.offer(bagEntry)) {\n               return;\n            }\n            else if ((i & 0xff) == 0xff || (waiting > 1 && i % waiting == 0)) {\n               parkNanos(MICROSECONDS.toNanos(10));\n            }\n            else {\n               Thread.yield();\n            }\n         }\n      }\n      else {\n         LOGGER.warn(\"Attempt to relinquish an object to the bag that was not reserved: {}\", bagEntry);\n      }\n   }\n\n   /**\n    * Get the number of threads pending (waiting) for an item from the\n    * bag to become available.\n    *\n    * @return the number of threads waiting for items from the bag\n    */\n   public int getWaitingThreadCount()\n   {\n      return waiters.get();\n   }\n\n   /**\n    * Get a count of the number of items in the specified state at the time of this call.\n    *\n    * @param state the state of the items to count\n    * @return a count of how many items in the bag are in the specified state\n    */\n   public int getCount(final int state)\n   {\n      var count = 0;\n      for (var e : sharedList) {\n         if (e.getState() == state) {\n            count++;\n         }\n      }\n      return count;\n   }\n\n   public int[] getStateCounts()\n   {\n      final var states = new int[6];\n      for (var e : sharedList) {\n         ++states[e.getState()];\n      }\n      states[4] = sharedList.size();\n      states[5] = waiters.get();\n\n      return states;\n   }\n\n   /**\n    * Get the total number of items in the bag.\n    *\n    * @return the number of items in the bag\n    */\n   public int size()\n   {\n      return sharedList.size();\n   }\n\n   public void dumpState()\n   {\n      sharedList.forEach(entry -> LOGGER.info(entry.toString()));\n   }\n\n   /**\n    * Determine whether to use WeakReferences based on whether there is a\n    * custom ClassLoader implementation sitting between this class and the\n    * System ClassLoader.\n    *\n    * @return true if we should use WeakReferences in our ThreadLocals, false otherwise\n    */\n   private boolean useWeakThreadLocals()\n   {\n      try {\n         if (System.getProperty(\"com.zaxxer.hikari.useWeakReferences\") != null) {   // undocumented manual override of WeakReference behavior\n            return Boolean.getBoolean(\"com.zaxxer.hikari.useWeakReferences\");\n         }\n\n         return getClass().getClassLoader() != ClassLoader.getSystemClassLoader();\n      }\n      catch (SecurityException se) {\n         return true;\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/Credentials.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport javax.management.ConstructorParameters;\n\n/**\n * A simple class to hold connection credentials and is designed to be immutable.\n */\npublic final class Credentials\n{\n\n   private final String username;\n   private final String password;\n\n   /**\n    * Construct an immutable Credentials object with the supplied username and password.\n    *\n    * @param username the username\n    * @param password the password\n    * @return a new Credentials object\n    */\n   public static Credentials of(final String username, final String password) {\n      return new Credentials(username, password);\n   }\n\n   /**\n    * Construct an immutable Credentials object with the supplied username and password.\n    *\n    * @param username the username\n    * @param password the password\n    */\n   @ConstructorParameters({ \"username\", \"password\" })\n   public Credentials(final String username, final String password)\n   {\n      this.username = username;\n      this.password = password;\n   }\n\n   /**\n    * Get the username.\n    *\n    * @return the username\n    */\n   public String getUsername()\n   {\n      return username;\n   }\n\n   /**\n    * Get the password.\n    *\n    * @return the password\n    */\n   public String getPassword()\n   {\n      return password;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/DriverDataSource.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.util;\n\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.Driver;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.Properties;\n\nimport javax.sql.DataSource;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport static com.zaxxer.hikari.util.UtilityElf.maskPasswordInJdbcUrl;\n\n/**\n * A DataSource implementation that uses a JDBC Driver to create connections.\n * This class is used to provide a DataSource that can be configured with a\n * specific JDBC driver and connection properties.\n * @author Brett Wooldridge\n * @hidden\n */\npublic final class DriverDataSource implements DataSource\n{\n   private static final Logger LOGGER = LoggerFactory.getLogger(DriverDataSource.class);\n   private static final String PASSWORD = \"password\";\n   private static final String USER = \"user\";\n\n   private final String jdbcUrl;\n   private final Properties driverProperties;\n   private Driver driver;\n\n   public DriverDataSource(String jdbcUrl, String driverClassName, Properties properties, String username, String password)\n   {\n      this.jdbcUrl = jdbcUrl;\n      this.driverProperties = new Properties();\n\n      driverProperties.putAll(properties);\n\n      if (username != null) {\n         driverProperties.put(USER, driverProperties.getProperty(USER, username));\n      }\n      if (password != null) {\n         driverProperties.put(PASSWORD, driverProperties.getProperty(PASSWORD, password));\n      }\n\n      if (driverClassName != null) {\n         var drivers = DriverManager.getDrivers();\n         while (drivers.hasMoreElements()) {\n            var d = drivers.nextElement();\n            if (d.getClass().getName().equals(driverClassName)) {\n               driver = d;\n               break;\n            }\n         }\n\n         if (driver == null) {\n            LOGGER.warn(\"Registered driver with driverClassName={} was not found, trying direct instantiation.\", driverClassName);\n            Class<?> driverClass = null;\n            var threadContextClassLoader = Thread.currentThread().getContextClassLoader();\n            try {\n               if (threadContextClassLoader != null) {\n                  try {\n                     driverClass = threadContextClassLoader.loadClass(driverClassName);\n                     LOGGER.debug(\"Driver class {} found in Thread context class loader {}\", driverClassName, threadContextClassLoader);\n                  }\n                  catch (ClassNotFoundException e) {\n                     LOGGER.debug(\"Driver class {} not found in Thread context class loader {}, trying classloader {}\",\n                                  driverClassName, threadContextClassLoader, this.getClass().getClassLoader());\n                  }\n               }\n\n               if (driverClass == null) {\n                  driverClass = this.getClass().getClassLoader().loadClass(driverClassName);\n                  LOGGER.debug(\"Driver class {} found in the HikariConfig class classloader {}\", driverClassName, this.getClass().getClassLoader());\n               }\n            } catch (ClassNotFoundException e) {\n               LOGGER.debug(\"Failed to load driver class {} from HikariConfig class classloader {}\", driverClassName, this.getClass().getClassLoader());\n            }\n\n            if (driverClass != null) {\n               try {\n                  driver = (Driver) driverClass.getDeclaredConstructor().newInstance();\n               } catch (Exception e) {\n                  LOGGER.warn(\"Failed to create instance of driver class {}, trying jdbcUrl resolution\", driverClassName, e);\n               }\n            }\n         }\n      }\n\n      final var sanitizedUrl = maskPasswordInJdbcUrl(jdbcUrl);\n\n      try {\n         if (driver == null) {\n            driver = DriverManager.getDriver(jdbcUrl);\n            LOGGER.debug(\"Loaded driver with class name {} for jdbcUrl={}\", driver.getClass().getName(), sanitizedUrl);\n         }\n         else if (!driver.acceptsURL(jdbcUrl)) {\n            throw new RuntimeException(\"Driver \" + driverClassName + \" claims to not accept jdbcUrl, \" + sanitizedUrl);\n         }\n      }\n      catch (SQLException e) {\n         throw new RuntimeException(\"Failed to get driver instance for jdbcUrl=\" + sanitizedUrl, e);\n      }\n   }\n\n   @Override\n   public Connection getConnection() throws SQLException\n   {\n      return driver.connect(jdbcUrl, driverProperties);\n   }\n\n   @Override\n   public Connection getConnection(final String username, final String password) throws SQLException\n   {\n      final var cloned = (Properties) driverProperties.clone();\n      if (username != null) {\n         cloned.put(USER, username);\n         if (cloned.containsKey(\"username\")) {\n            cloned.put(\"username\", username);\n         }\n      }\n      if (password != null) {\n         cloned.put(PASSWORD, password);\n      }\n\n      return driver.connect(jdbcUrl, cloned);\n   }\n\n   @Override\n   public PrintWriter getLogWriter() throws SQLException\n   {\n      throw new SQLFeatureNotSupportedException();\n   }\n\n   @Override\n   public void setLogWriter(PrintWriter logWriter) throws SQLException\n   {\n      throw new SQLFeatureNotSupportedException();\n   }\n\n   @Override\n   public void setLoginTimeout(int seconds) throws SQLException\n   {\n      DriverManager.setLoginTimeout(seconds);\n   }\n\n   @Override\n   public int getLoginTimeout() throws SQLException\n   {\n      return DriverManager.getLoginTimeout();\n   }\n\n   @Override\n   public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException\n   {\n      return driver.getParentLogger();\n   }\n\n   @Override\n   public <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      throw new SQLFeatureNotSupportedException();\n   }\n\n   @Override\n   public boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      return false;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/FastList.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport java.io.Serializable;\nimport java.lang.reflect.Array;\nimport java.util.Collection;\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.ListIterator;\nimport java.util.NoSuchElementException;\nimport java.util.RandomAccess;\nimport java.util.Spliterator;\nimport java.util.function.Consumer;\nimport java.util.function.Predicate;\nimport java.util.function.UnaryOperator;\n\n/**\n * Fast list without range checking.\n *\n * @author Brett Wooldridge\n * @hidden\n */\n@SuppressWarnings(\"NullableProblems\")\npublic final class FastList<T> implements List<T>, RandomAccess, Serializable\n{\n   private static final long serialVersionUID = -4598088075242913858L;\n\n   private final Class<?> clazz;\n   private T[] elementData;\n   private int size;\n\n   /**\n    * Construct a FastList with a default size of 32.\n    * @param clazz the Class stored in the collection\n    */\n   @SuppressWarnings(\"unchecked\")\n   public FastList(Class<?> clazz)\n   {\n      this.elementData = (T[]) Array.newInstance(clazz, 32);\n      this.clazz = clazz;\n   }\n\n   /**\n    * Construct a FastList with a specified size.\n    * @param clazz the Class stored in the collection\n    * @param capacity the initial size of the FastList\n    */\n   @SuppressWarnings(\"unchecked\")\n   public FastList(Class<?> clazz, int capacity)\n   {\n      this.elementData = (T[]) Array.newInstance(clazz, capacity);\n      this.clazz = clazz;\n   }\n\n   /**\n    * Add an element to the tail of the FastList.\n    *\n    * @param element the element to add\n    */\n   @Override\n   public boolean add(T element)\n   {\n      if (size < elementData.length) {\n         elementData[size++] = element;\n      }\n      else {\n         // overflow-conscious code\n         final var oldCapacity = elementData.length;\n         final var newCapacity = oldCapacity << 1;\n         @SuppressWarnings(\"unchecked\")\n         final var newElementData = (T[]) Array.newInstance(clazz, newCapacity);\n         System.arraycopy(elementData, 0, newElementData, 0, oldCapacity);\n         newElementData[size++] = element;\n         elementData = newElementData;\n      }\n\n      return true;\n   }\n\n   /**\n    * Get the element at the specified index.\n    *\n    * @param index the index of the element to get\n    * @return the element, or ArrayIndexOutOfBounds is thrown if the index is invalid\n    */\n   @Override\n   public T get(int index)\n   {\n      return elementData[index];\n   }\n\n   /**\n    * Remove the last element from the list.  No bound check is performed, so if this\n    * method is called on an empty list and ArrayIndexOutOfBounds exception will be\n    * thrown.\n    *\n    * @return the last element of the list\n    */\n   public T removeLast()\n   {\n      T element = elementData[--size];\n      elementData[size] = null;\n      return element;\n   }\n\n   /**\n    * This remove method is most efficient when the element being removed\n    * is the last element.  Equality is identity based, not equals() based.\n    * Only the first matching element is removed.\n    *\n    * @param element the element to remove\n    */\n   @Override\n   public boolean remove(Object element)\n   {\n      for (var index = size - 1; index >= 0; index--) {\n         if (element == elementData[index]) {\n            final var numMoved = size - index - 1;\n            if (numMoved > 0) {\n               System.arraycopy(elementData, index + 1, elementData, index, numMoved);\n            }\n            elementData[--size] = null;\n            return true;\n         }\n      }\n\n      return false;\n   }\n\n   /**\n    * Clear the FastList.\n    */\n   @Override\n   public void clear()\n   {\n      for (var i = 0; i < size; i++) {\n         elementData[i] = null;\n      }\n\n      size = 0;\n   }\n\n   /**\n    * Get the current number of elements in the FastList.\n    *\n    * @return the number of current elements\n    */\n   @Override\n   public int size()\n   {\n      return size;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isEmpty()\n   {\n      return size == 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public T set(int index, T element)\n   {\n      T old = elementData[index];\n      elementData[index] = element;\n      return old;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public T remove(int index)\n   {\n      if (size == 0) {\n         return null;\n      }\n\n      final T old = elementData[index];\n\n      final var numMoved = size - index - 1;\n      if (numMoved > 0) {\n         System.arraycopy(elementData, index + 1, elementData, index, numMoved);\n      }\n\n      elementData[--size] = null;\n\n      return old;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean contains(Object o)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Iterator<T> iterator()\n   {\n      return new Iterator<>() {\n         private int index;\n\n         @Override\n         public boolean hasNext()\n         {\n            return index < size;\n         }\n\n         @Override\n         public T next()\n         {\n            if (index < size) {\n               return elementData[index++];\n            }\n\n            throw new NoSuchElementException(\"No more elements in FastList\");\n         }\n      };\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Object[] toArray()\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public <E> E[] toArray(E[] a)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean containsAll(Collection<?> c)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean addAll(Collection<? extends T> c)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean addAll(int index, Collection<? extends T> c)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean removeAll(Collection<?> c)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean retainAll(Collection<?> c)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void add(int index, T element)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int indexOf(Object o)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int lastIndexOf(Object o)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ListIterator<T> listIterator()\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ListIterator<T> listIterator(int index)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public List<T> subList(int fromIndex, int toIndex)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Object clone()\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void forEach(Consumer<? super T> action)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Spliterator<T> spliterator()\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean removeIf(Predicate<? super T> filter)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void replaceAll(UnaryOperator<T> operator)\n   {\n      throw new UnsupportedOperationException();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void sort(Comparator<? super T> c)\n   {\n      throw new UnsupportedOperationException();\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/IsolationLevel.java",
    "content": "/*\n * Copyright (C) 2019 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\n/**\n * An enumeration representing the various isolation levels for database transactions.\n * Each isolation level corresponds to a specific behavior regarding visibility of changes made by other transactions.\n * The levels are defined according to the SQL standard and may vary in implementation across different databases.\n *\n * @author Brett Wooldridge\n * @hidden\n */\npublic enum IsolationLevel\n{\n   TRANSACTION_NONE(0),\n   TRANSACTION_READ_UNCOMMITTED(1),\n   TRANSACTION_READ_COMMITTED(2),\n   TRANSACTION_CURSOR_STABILITY(3),\n   TRANSACTION_REPEATABLE_READ(4),\n   TRANSACTION_LAST_COMMITTED(5),\n   TRANSACTION_SERIALIZABLE(8),\n   TRANSACTION_SQL_SERVER_SNAPSHOT_ISOLATION_LEVEL(4096);\n\n   private final int levelId;\n\n   IsolationLevel(int levelId) {\n      this.levelId = levelId;\n   }\n\n   public int getLevelId() {\n      return levelId;\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/JavassistProxyFactory.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport com.zaxxer.hikari.pool.*;\nimport javassist.*;\nimport javassist.bytecode.ClassFile;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.reflect.Array;\nimport java.sql.*;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.LinkedHashSet;\nimport java.util.Set;\n\n/**\n * This class generates the proxy objects for {@link Connection}, {@link Statement},\n * {@link PreparedStatement}, and {@link CallableStatement}.  Additionally it injects\n * method bodies into the {@link ProxyFactory} class methods that can instantiate\n * instances of the generated proxies.\n *\n * @author Brett Wooldridge\n * @author Yanming Zhou\n * @hidden\n */\npublic final class JavassistProxyFactory\n{\n   private static ClassPool classPool;\n   private static String genDirectory = \"target\" + File.separator + \"classes\";\n\n   public static void main(String... args) throws Exception {\n      classPool = new ClassPool();\n      classPool.importPackage(\"java.sql\");\n      classPool.appendClassPath(new LoaderClassPath(JavassistProxyFactory.class.getClassLoader()));\n\n      if (args.length > 0) {\n         String parentDir = args[0];\n         if (!parentDir.endsWith(File.separator)) {\n            parentDir += File.separator;\n         }\n         genDirectory = parentDir + genDirectory;\n      }\n\n      System.out.println(\"Generating following classes to \" + genDirectory);\n\n      // Cast is not needed for these\n      String methodBody = \"{ try { return delegate.method($$); } catch (SQLException e) { throw checkException(e); } }\";\n      generateProxyClass(Connection.class, ProxyConnection.class.getName(), methodBody);\n      generateProxyClass(Statement.class, ProxyStatement.class.getName(), methodBody);\n      generateProxyClass(ResultSet.class, ProxyResultSet.class.getName(), methodBody);\n      generateProxyClass(DatabaseMetaData.class, ProxyDatabaseMetaData.class.getName(), methodBody);\n\n      // For these we have to cast the delegate\n      methodBody = \"{ try { return ((cast) delegate).method($$); } catch (SQLException e) { throw checkException(e); } }\";\n      generateProxyClass(PreparedStatement.class, ProxyPreparedStatement.class.getName(), methodBody);\n      generateProxyClass(CallableStatement.class, ProxyCallableStatement.class.getName(), methodBody);\n\n      modifyProxyFactory();\n   }\n\n   private static void modifyProxyFactory() throws NotFoundException, CannotCompileException, IOException {\n      System.out.println(\"Generating method bodies for com.zaxxer.hikari.proxy.ProxyFactory\");\n\n      var packageName = ProxyConnection.class.getPackage().getName();\n      var proxyCt = classPool.getCtClass(\"com.zaxxer.hikari.pool.ProxyFactory\");\n      for (var method : proxyCt.getMethods()) {\n         switch (method.getName()) {\n            case \"getProxyConnection\":\n               method.setBody(\"{return new \" + packageName + \".HikariProxyConnection($$);}\");\n               break;\n            case \"getProxyStatement\":\n               method.setBody(\"{return new \" + packageName + \".HikariProxyStatement($$);}\");\n               break;\n            case \"getProxyPreparedStatement\":\n               method.setBody(\"{return new \" + packageName + \".HikariProxyPreparedStatement($$);}\");\n               break;\n            case \"getProxyCallableStatement\":\n               method.setBody(\"{return new \" + packageName + \".HikariProxyCallableStatement($$);}\");\n               break;\n            case \"getProxyResultSet\":\n               method.setBody(\"{return new \" + packageName + \".HikariProxyResultSet($$);}\");\n               break;\n            case \"getProxyDatabaseMetaData\":\n               method.setBody(\"{return new \" + packageName + \".HikariProxyDatabaseMetaData($$);}\");\n               break;\n            default:\n               // unhandled method\n               break;\n         }\n      }\n\n      proxyCt.writeFile(genDirectory);\n   }\n\n   /**\n    *  Generate Javassist Proxy Classes\n    */\n   private static <T> void generateProxyClass(Class<T> primaryInterface, String superClassName, String methodBody) throws Exception\n   {\n      var newClassName = superClassName.replaceAll(\"(.+)\\\\.(\\\\w+)\", \"$1.Hikari$2\");\n\n      var superCt = classPool.getCtClass(superClassName);\n      var targetCt = classPool.makeClass(newClassName, superCt);\n      targetCt.setModifiers(Modifier.setPublic(Modifier.FINAL));\n\n      System.out.println(\"Generating \" + newClassName);\n\n      // Make a set of method signatures we inherit implementation for, so we don't generate delegates for these\n      var superSigs = new HashSet<String>();\n      for (var method : superCt.getMethods()) {\n         if ((method.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {\n            superSigs.add(method.getName() + method.getSignature());\n         }\n      }\n\n      var methods = new HashSet<String>();\n      for (var intf : getAllInterfaces(primaryInterface)) {\n         var intfCt = classPool.getCtClass(intf.getName());\n         targetCt.addInterface(intfCt);\n         for (var intfMethod : intfCt.getDeclaredMethods()) {\n            final var signature = intfMethod.getName() + intfMethod.getSignature();\n\n            // don't generate delegates for methods we override\n            if (superSigs.contains(signature)) {\n               continue;\n            }\n\n            // Ignore already added methods that come from other interfaces\n            if (methods.contains(signature)) {\n               continue;\n            }\n\n            // Track what methods we've added\n            methods.add(signature);\n\n            // Clone the method we want to inject into\n            var method = CtNewMethod.copy(intfMethod, targetCt, null);\n\n            var modifiedBody = methodBody;\n\n            // If the super-Proxy has concrete methods (non-abstract), transform the call into a simple super.method() call\n            var superMethod = superCt.getMethod(intfMethod.getName(), intfMethod.getSignature());\n            if ((superMethod.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT && !isDefaultMethod(intf, intfMethod)) {\n               modifiedBody = modifiedBody.replace(\"((cast) \", \"\");\n               modifiedBody = modifiedBody.replace(\"delegate\", \"super\");\n               modifiedBody = modifiedBody.replace(\"super)\", \"super\");\n            }\n\n            modifiedBody = modifiedBody.replace(\"cast\", primaryInterface.getName());\n\n            // Generate a method that simply invokes the same method on the delegate\n            if (isThrowsSqlException(intfMethod)) {\n               modifiedBody = modifiedBody.replace(\"method\", method.getName());\n            }\n            else {\n               modifiedBody = \"{ return ((cast) delegate).method($$); }\".replace(\"method\", method.getName()).replace(\"cast\", primaryInterface.getName());\n            }\n\n            if (method.getReturnType() == CtClass.voidType) {\n               modifiedBody = modifiedBody.replace(\"return\", \"\");\n            }\n\n            method.setBody(modifiedBody);\n            targetCt.addMethod(method);\n         }\n      }\n\n      targetCt.getClassFile().setMajorVersion(ClassFile.JAVA_8);\n      targetCt.writeFile(genDirectory);\n   }\n\n   private static boolean isThrowsSqlException(CtMethod method)\n   {\n      try {\n         for (var clazz : method.getExceptionTypes()) {\n            if (clazz.getSimpleName().equals(\"SQLException\")) {\n               return true;\n            }\n         }\n      }\n      catch (NotFoundException e) {\n         // fall thru\n      }\n\n      return false;\n   }\n\n   private static boolean isDefaultMethod(Class<?> intf, CtMethod intfMethod) throws Exception\n   {\n      var paramTypes = new ArrayList<Class<?>>();\n\n      for (var pt : intfMethod.getParameterTypes()) {\n         paramTypes.add(toJavaClass(pt));\n      }\n\n      return intf.getDeclaredMethod(intfMethod.getName(), paramTypes.toArray(new Class[0])).toString().contains(\"default \");\n   }\n\n   private static Set<Class<?>> getAllInterfaces(Class<?> clazz)\n   {\n      var interfaces = new LinkedHashSet<Class<?>>();\n      for (var intf : clazz.getInterfaces()) {\n         if (intf.getInterfaces().length > 0) {\n            interfaces.addAll(getAllInterfaces(intf));\n         }\n         interfaces.add(intf);\n      }\n      if (clazz.getSuperclass() != null) {\n         interfaces.addAll(getAllInterfaces(clazz.getSuperclass()));\n      }\n\n      if (clazz.isInterface()) {\n         interfaces.add(clazz);\n      }\n\n      return interfaces;\n   }\n\n   private static Class<?> toJavaClass(CtClass cls) throws Exception\n   {\n      if (cls.getName().endsWith(\"[]\")) {\n         return Array.newInstance(toJavaClass(cls.getName().replace(\"[]\", \"\")), 0).getClass();\n      }\n      else {\n         return toJavaClass(cls.getName());\n      }\n   }\n\n   private static Class<?> toJavaClass(String cn) throws Exception\n   {\n      switch (cn) {\n      case \"int\":\n         return int.class;\n      case \"long\":\n         return long.class;\n      case \"short\":\n         return short.class;\n      case \"byte\":\n         return byte.class;\n      case \"float\":\n         return float.class;\n      case \"double\":\n         return double.class;\n      case \"boolean\":\n         return boolean.class;\n      case \"char\":\n         return char.class;\n      case \"void\":\n         return void.class;\n      default:\n         return Class.forName(cn);\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/PropertyElf.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport org.slf4j.LoggerFactory;\n\nimport java.lang.reflect.Method;\nimport java.time.Duration;\nimport java.util.*;\nimport java.util.regex.Pattern;\n\n/**\n * A class that reflectively sets bean properties on a target object.\n *\n * @author Brett Wooldridge\n * @hidden\n */\npublic final class PropertyElf\n{\n   private static final char ESCAPE_CHAR = '\\\\';\n   private static final char SEPARATOR_CHAR = ',';\n   private static final Pattern DURATION_PATTERN = Pattern.compile(\"^(?<number>\\\\d+)(?<unit>ms|s|m|h|d)$\");\n\n   private PropertyElf() {\n      // cannot be constructed\n   }\n\n   public static void setTargetFromProperties(final Object target, final Properties properties)\n   {\n      if (target == null || properties == null) {\n         return;\n      }\n\n      var methods = Arrays.asList(target.getClass().getMethods());\n      properties.forEach((key, value) -> {\n         var keyName = key.toString();\n         if (target instanceof HikariConfig && keyName.startsWith(\"dataSource.\")) {\n            ((HikariConfig) target).addDataSourceProperty(keyName.substring(\"dataSource.\".length()), value);\n         }\n         else {\n            setProperty(target, keyName, value, methods);\n         }\n      });\n   }\n\n   /**\n    * Get the bean-style property names for the specified object.\n    *\n    * @param targetClass the target object\n    * @return a set of property names\n    */\n   public static Set<String> getPropertyNames(final Class<?> targetClass)\n   {\n      var set = new HashSet<String>();\n      for (var method : targetClass.getMethods()) {\n         var name = propertyNameFromGetterName(method.getName());\n         try {\n            if (method.getParameterTypes().length == 0 && name != null) {\n               targetClass.getMethod(\"set\" + capitalizedPropertyName(name), method.getReturnType()); // throws if method setter does not exist\n               set.add(name);\n            }\n         }\n         catch (Exception e) {\n            // fall thru (continue)\n         }\n      }\n\n      return set;\n   }\n\n   public static Object getProperty(final String propName, final Object target)\n   {\n      try {\n         // use the english locale to avoid the infamous turkish locale bug\n         var capitalized = \"get\" + capitalizedPropertyName(propName);\n         var method = target.getClass().getMethod(capitalized);\n         return method.invoke(target);\n      }\n      catch (Exception e) {\n         try {\n            var capitalized = \"is\" + capitalizedPropertyName(propName);\n            var method = target.getClass().getMethod(capitalized);\n            return method.invoke(target);\n         }\n         catch (Exception e2) {\n            return null;\n         }\n      }\n   }\n\n   public static Properties copyProperties(final Properties props)\n   {\n      var copy = new Properties();\n      props.forEach((key, value) -> copy.setProperty(key.toString(), value.toString()));\n      return copy;\n   }\n\n   private static String propertyNameFromGetterName(final String methodName)\n   {\n      String name = null;\n      if (methodName.startsWith(\"get\") && methodName.length() > 3) {\n         name = methodName.substring(3);\n      }\n      else if (methodName.startsWith(\"is\") && methodName.length() > 2) {\n         name = methodName.substring(2);\n      }\n\n      if (name != null) {\n         return Character.toLowerCase(name.charAt(0)) + name.substring(1);\n      }\n\n      return null;\n   }\n\n   private static void setProperty(final Object target, final String propName, final Object propValue, final List<Method> methods)\n   {\n      final var logger = LoggerFactory.getLogger(PropertyElf.class);\n\n      // use the english locale to avoid the infamous turkish locale bug\n      var methodName = \"set\" + propName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propName.substring(1);\n      var writeMethod = methods.stream().filter(m -> m.getName().equals(methodName) && m.getParameterCount() == 1).findFirst().orElse(null);\n\n      if (writeMethod == null) {\n         var methodName2 = \"set\" + propName.toUpperCase(Locale.ENGLISH);\n         writeMethod = methods.stream().filter(m -> m.getName().equals(methodName2) && m.getParameterCount() == 1).findFirst().orElse(null);\n      }\n\n      if (writeMethod == null) {\n         logger.error(\"Property {} does not exist on target {}\", propName, target.getClass());\n         throw new RuntimeException(String.format(\"Property %s does not exist on target %s\", propName, target.getClass()));\n      }\n\n      try {\n         var paramClass = writeMethod.getParameterTypes()[0];\n         String value = propValue.toString();\n         if (paramClass == int.class) {\n            writeMethod.invoke(target, Integer.parseInt(propValue.toString()));\n         }\n         else if (paramClass == long.class) {\n            writeMethod.invoke(target, parseDuration(value).map(Duration::toMillis).orElseGet(() -> Long.parseLong(value)));\n         }\n         else if (paramClass == short.class) {\n            writeMethod.invoke(target, Short.parseShort(value));\n         }\n         else if (paramClass == boolean.class || paramClass == Boolean.class) {\n            writeMethod.invoke(target, Boolean.parseBoolean(value));\n         }\n         else if (paramClass.isArray() && char.class.isAssignableFrom(paramClass.getComponentType())) {\n            writeMethod.invoke(target, value.toCharArray());\n         }\n         else if (paramClass.isArray() && int.class.isAssignableFrom(paramClass.getComponentType())) {\n            writeMethod.invoke(target, parseIntArray(value));\n         }\n         else if (paramClass.isArray() && String.class.isAssignableFrom(paramClass.getComponentType())) {\n            writeMethod.invoke(target, new Object[]{parseStringArray(value)});\n         }\n         else if (paramClass == String.class) {\n            writeMethod.invoke(target, value);\n         }\n         else {\n            try {\n               logger.debug(\"Try to create a new instance of \\\"{}\\\"\", propValue);\n               writeMethod.invoke(target, Class.forName(propValue.toString()).getDeclaredConstructor().newInstance());\n            }\n            catch (InstantiationException | ClassNotFoundException e) {\n               logger.debug(\"Class \\\"{}\\\" not found or could not instantiate it (Default constructor)\", propValue);\n               writeMethod.invoke(target, propValue);\n            }\n         }\n      }\n      catch (Exception e) {\n         logger.error(\"Failed to set property {} on target {}\", propName, target.getClass(), e);\n         throw new RuntimeException(e);\n      }\n   }\n\n   private static String capitalizedPropertyName(String propertyName)\n   {\n      // use the english locale to avoid the infamous turkish locale bug\n      return propertyName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propertyName.substring(1);\n   }\n\n   private static int[] parseIntArray(String value)\n   {\n      if (value == null || value.isEmpty() ) {\n         return new int[0];\n      }\n\n      var split = value.split(\",\");\n      var intArray = new int[split.length];\n      for (int i = 0; i < split.length; i++) {\n         intArray[i] = Integer.parseInt(split[i]);\n      }\n      return intArray;\n   }\n\n   private static String[] parseStringArray(String value)\n   {\n      if (value == null || value.isEmpty()) {\n         return new String[0];\n      }\n\n      var resultList = new ArrayList<String>();\n      var inEscape = false;\n      var currentField = new StringBuilder();\n      for (var c : value.toCharArray())\n      {\n         if (inEscape) {\n            currentField.append(c);\n            inEscape = false;\n         }\n         else if (c == ESCAPE_CHAR) {\n            inEscape = true;\n         } else if (c == SEPARATOR_CHAR) {\n            resultList.add(currentField.toString());\n            currentField.setLength(0);\n         }\n         else {\n            currentField.append(c);\n         }\n      }\n\n      if (inEscape) {\n         throw new IllegalArgumentException(String.format(\"Unterminated escape sequence in property value: %s\", value));\n      }\n\n      resultList.add(currentField.toString());\n      return resultList.toArray(new String[0]);\n   }\n\n   private static Optional<Duration> parseDuration(String value)\n   {\n      var matcher = DURATION_PATTERN.matcher(value);\n      if (matcher.matches()) {\n         var number = Long.parseLong(matcher.group(\"number\"));\n         var unit = matcher.group(\"unit\");\n         switch (unit) {\n            case \"ms\":\n               return Optional.of(Duration.ofMillis(number));\n            case \"s\":\n               return Optional.of(Duration.ofSeconds(number));\n            case \"m\":\n               return Optional.of(Duration.ofMinutes(number));\n            case \"h\":\n               return Optional.of(Duration.ofHours(number));\n            case \"d\":\n               return Optional.of(Duration.ofDays(number));\n            default:\n               throw new IllegalStateException(String.format(\"Could not match unit, got %s (from given value %s)\", unit, value));\n         }\n      } else {\n         return Optional.empty();\n      }\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/SuspendResumeLock.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport java.sql.SQLException;\nimport java.sql.SQLTransientException;\nimport java.util.concurrent.Semaphore;\n\n/**\n * This class implements a lock that can be used to suspend and resume the pool.  It\n * also provides a faux implementation that is used when the feature is disabled that\n * hopefully gets fully \"optimized away\" by the JIT.\n *\n * @author Brett Wooldridge\n * @hidden\n */\npublic class SuspendResumeLock\n{\n   public static final SuspendResumeLock FAUX_LOCK = new SuspendResumeLock(false) {\n      @Override\n      public void acquire() {}\n\n      @Override\n      public void release() {}\n\n      @Override\n      public void suspend() {}\n\n      @Override\n      public void resume() {}\n   };\n\n   private static final int MAX_PERMITS = 10000;\n   private final Semaphore acquisitionSemaphore;\n\n   /**\n    * Default constructor\n    */\n   public SuspendResumeLock()\n   {\n      this(true);\n   }\n\n   private SuspendResumeLock(final boolean createSemaphore)\n   {\n      acquisitionSemaphore = (createSemaphore ? new Semaphore(MAX_PERMITS, true) : null);\n   }\n\n   public void acquire() throws SQLException\n   {\n      if (acquisitionSemaphore.tryAcquire()) {\n         return;\n      }\n      else if (Boolean.getBoolean(\"com.zaxxer.hikari.throwIfSuspended\")) {\n         throw new SQLTransientException(\"The pool is currently suspended and configured to throw exceptions upon acquisition\");\n      }\n\n      acquisitionSemaphore.acquireUninterruptibly();\n   }\n\n   public void release()\n   {\n      acquisitionSemaphore.release();\n   }\n\n   public void suspend()\n   {\n      acquisitionSemaphore.acquireUninterruptibly(MAX_PERMITS);\n   }\n\n   public void resume()\n   {\n      acquisitionSemaphore.release(MAX_PERMITS);\n   }\n}\n"
  },
  {
    "path": "src/main/java/com/zaxxer/hikari/util/UtilityElf.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.lang.reflect.Constructor;\nimport java.util.Arrays;\nimport java.util.Locale;\nimport java.util.concurrent.*;\nimport java.util.regex.Pattern;\nimport java.util.stream.IntStream;\n\nimport static java.lang.Thread.currentThread;\nimport static java.util.concurrent.TimeUnit.SECONDS;\n\n/**\n * UtilityElf is a utility class that provides various helper methods\n * for string manipulation, thread management, and JDBC URL handling.\n * It includes methods for masking passwords in JDBC URLs, creating\n * instances of classes, and creating thread pool executors.\n *\n * @author Brett Wooldridge\n * @hidden\n */\npublic final class UtilityElf\n{\n   private static final Logger LOGGER = LoggerFactory.getLogger(UtilityElf.class);\n\n   /**\n    * A pattern to match and mask passwords in JDBC URLs.\n    * It looks for the \"password\" parameter in the URL and replaces its value with \"<masked>\".\n    */\n   private static final Pattern PASSWORD_MASKING_PATTERN = Pattern.compile(\"([?&;][^&#;=]*[pP]assword=)[^&#;]*\");\n\n   private UtilityElf()\n   {\n      // non-constructable\n   }\n\n   public static String maskPasswordInJdbcUrl(String jdbcUrl)\n   {\n      return PASSWORD_MASKING_PATTERN.matcher(jdbcUrl).replaceAll(\"$1<masked>\");\n   }\n\n   /**\n    * Get a trimmed string or null if the string is null or empty.\n    *\n    * @param text the string to check\n    * @return null if string is null or empty, trimmed string otherwise\n   */\n   public static String getNullIfEmpty(final String text)\n   {\n      return text == null ? null : text.trim().isEmpty() ? null : text.trim();\n   }\n\n   /**\n    * Sleep and suppress InterruptedException (but re-signal it).\n    *\n    * @param millis the number of milliseconds to sleep\n    */\n   public static void quietlySleep(final long millis)\n   {\n      try {\n         Thread.sleep(millis);\n      }\n      catch (InterruptedException e) {\n         // I said be quiet!\n         currentThread().interrupt();\n      }\n   }\n\n   /**\n    * Checks whether an object is an instance of given type without throwing exception when the class is not loaded.\n    * @param obj the object to check\n    * @param className String class\n    * @return true if object is assignable from the type, false otherwise or when the class cannot be loaded\n    */\n   public static boolean safeIsAssignableFrom(Object obj, String className) {\n      try {\n         var clazz = Class.forName(className);\n         return clazz.isAssignableFrom(obj.getClass());\n      } catch (ClassNotFoundException ignored) {\n         return false;\n      }\n   }\n\n   public static <T> T createInstance(final String className, final Class<T> clazz)\n   {\n      return createInstance(className, clazz, new Object[0]);\n   }\n\n   /**\n    * Create and instance of the specified class using the constructor matching the specified\n    * arguments.\n    *\n    * @param <T> the class type\n    * @param className the name of the class to instantiate\n    * @param clazz a class to cast the result as\n    * @param args arguments to a constructor\n    * @return an instance of the specified class\n    */\n   public static <T> T createInstance(final String className, final Class<T> clazz, final Object... args)\n   {\n      if (className == null) {\n         return null;\n      }\n\n      try {\n         var loaded = attemptFromContextLoader(className);\n         if (loaded == null) {\n            loaded = UtilityElf.class.getClassLoader().loadClass(className);\n            LOGGER.debug(\"Class {} loaded from classloader {}\", className, UtilityElf.class.getClassLoader());\n         }\n         var totalArgs = args.length;\n\n         if (totalArgs == 0) {\n            return clazz.cast(loaded.getDeclaredConstructor().newInstance());\n         }\n\n         var argClasses = new Class<?>[totalArgs];\n         for (int i = 0; i < totalArgs; i++) {\n            argClasses[i] = args[i].getClass();\n         }\n\n         Constructor<?> constructor = Arrays.stream(loaded.getConstructors())\n            .filter(c -> {\n               if (c.getParameterCount() != totalArgs) return false;\n\n               Class<?>[] params = c.getParameterTypes();\n               return IntStream.range(0, totalArgs)\n                  .allMatch(i -> params[i].isAssignableFrom(argClasses[i]));\n            })\n            .findFirst()\n            .orElseThrow(() -> new RuntimeException(\"No suitable constructor found for class \" + className + \" with arguments \" + Arrays.toString(args)));\n\n         return clazz.cast(constructor.newInstance(args));\n      }\n      catch (Exception e) {\n         throw new RuntimeException(\"Failed to load class \" + className, e);\n      }\n   }\n\n   /**\n    * Create a ThreadPoolExecutor.\n    *\n    * @param queueSize the queue size\n    * @param threadName the thread name\n    * @param threadFactory an optional ThreadFactory\n    * @param policy the RejectedExecutionHandler policy\n    * @return a ThreadPoolExecutor\n    */\n   public static ThreadPoolExecutor createThreadPoolExecutor(final int queueSize, final String threadName, ThreadFactory threadFactory, final RejectedExecutionHandler policy)\n   {\n      return createThreadPoolExecutor(new LinkedBlockingQueue<>(queueSize), threadName, threadFactory, policy);\n   }\n\n   /**\n    * Create a ThreadPoolExecutor.\n    *\n    * @param queue the BlockingQueue to use\n    * @param threadName the thread name\n    * @param threadFactory an optional ThreadFactory\n    * @param policy the RejectedExecutionHandler policy\n    * @return a ThreadPoolExecutor\n    */\n   public static ThreadPoolExecutor createThreadPoolExecutor(final BlockingQueue<Runnable> queue, final String threadName, ThreadFactory threadFactory, final RejectedExecutionHandler policy)\n   {\n      if (threadFactory == null) {\n         threadFactory = new DefaultThreadFactory(threadName);\n      }\n\n      var executor = new ThreadPoolExecutor(1 /*core*/, 1 /*max*/, 5 /*keepalive*/, SECONDS, queue, threadFactory, policy);\n      executor.allowCoreThreadTimeOut(true);\n      return executor;\n   }\n\n   // ***********************************************************************\n   //                       Misc. public methods\n   // ***********************************************************************\n\n   /**\n    * Get the int value of a transaction isolation level by name.\n    *\n    * @param transactionIsolationName the name of the transaction isolation level\n    * @return the int value of the isolation level or -1\n    */\n   public static int getTransactionIsolation(final String transactionIsolationName)\n   {\n      if (transactionIsolationName != null) {\n         try {\n            // use the english locale to avoid the infamous turkish locale bug\n            final var upperCaseIsolationLevelName = transactionIsolationName.toUpperCase(Locale.ENGLISH);\n            return IsolationLevel.valueOf(upperCaseIsolationLevelName).getLevelId();\n         } catch (IllegalArgumentException e) {\n            // legacy support for passing an integer version of the isolation level\n            try {\n               final var level = Integer.parseInt(transactionIsolationName);\n               for (var iso : IsolationLevel.values()) {\n                  if (iso.getLevelId() == level) {\n                     return iso.getLevelId();\n                  }\n               }\n\n               throw new IllegalArgumentException(\"Invalid transaction isolation value: \" + transactionIsolationName);\n            }\n            catch (NumberFormatException nfe) {\n               throw new IllegalArgumentException(\"Invalid transaction isolation value: \" + transactionIsolationName, nfe);\n            }\n         }\n      }\n\n      return -1;\n   }\n\n   /**\n    * Custom RejectedExecutionHandler that does nothing when a task is rejected.\n    *\n    * @see java.util.concurrent.RejectedExecutionHandler\n    * @see java.util.concurrent.ThreadPoolExecutor\n    * @hidden\n    */\n   public static class CustomDiscardPolicy implements RejectedExecutionHandler\n   {\n      @Override\n      public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {\n      }\n   }\n\n   /**\n    * Default ThreadFactory implementation that creates daemon threads with a specified name.\n    *\n    * @see java.util.concurrent.ThreadFactory\n    * @hidden\n    */\n   public static final class DefaultThreadFactory implements ThreadFactory\n   {\n      private final String threadName;\n      private final boolean daemon;\n\n      public DefaultThreadFactory(String threadName) {\n         this.threadName = threadName;\n         this.daemon = true;\n      }\n\n      @Override\n      @SuppressWarnings(\"NullableProblems\")\n      public Thread newThread(Runnable r) {\n         var thread = new Thread(r, threadName);\n         thread.setDaemon(daemon);\n         return thread;\n      }\n   }\n\n   // ***********************************************************************\n   //                          Private methods\n   // ***********************************************************************\n\n   private static Class<?> attemptFromContextLoader(final String className) {\n      final var threadContextClassLoader = Thread.currentThread().getContextClassLoader();\n      if (threadContextClassLoader != null) {\n         try {\n            final var clazz = threadContextClassLoader.loadClass(className);\n            LOGGER.debug(\"Class {} found in Thread context class loader {}\", className, threadContextClassLoader);\n            return clazz;\n         } catch (ClassNotFoundException e) {\n            LOGGER.debug(\"Class {} not found in Thread context class loader {}, trying classloader {}\",\n               className, threadContextClassLoader, UtilityElf.class.getClassLoader());\n         }\n      }\n\n      return null;\n   }\n}\n"
  },
  {
    "path": "src/main/java/module-info.java",
    "content": "module com.zaxxer.hikari\n{\n   requires java.sql;\n   requires java.management;\n   requires java.naming;\n   requires org.slf4j;\n   requires static org.hibernate.orm.core;\n   requires static simpleclient;\n   requires static metrics.core;\n   requires static metrics.healthchecks;\n   requires static io.dropwizard.metrics5;\n   requires static micrometer.core;\n   requires static org.javassist;\n\n   exports com.zaxxer.hikari;\n   exports com.zaxxer.hikari.hibernate;\n   exports com.zaxxer.hikari.metrics;\n   exports com.zaxxer.hikari.metrics.dropwizard;\n   exports com.zaxxer.hikari.metrics.micrometer;\n   exports com.zaxxer.hikari.metrics.prometheus;\n   exports com.zaxxer.hikari.pool;\n   exports com.zaxxer.hikari.util;\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/HikariConfigTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari;\n\nimport org.apache.logging.log4j.Level;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.core.Filter;\nimport org.apache.logging.log4j.core.Layout;\nimport org.apache.logging.log4j.core.LogEvent;\nimport org.apache.logging.log4j.core.LoggerContext;\nimport org.apache.logging.log4j.core.appender.AbstractAppender;\nimport org.apache.logging.log4j.core.config.Configuration;\nimport org.apache.logging.log4j.core.config.LoggerConfig;\nimport org.apache.logging.log4j.core.config.Property;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.junit.Assert.*;\n\npublic class HikariConfigTest {\n   private TestAppender testAppender = new TestAppender();\n\n   @Before\n   public void setup() {\n      getLoggerConfig().addAppender(testAppender, Level.ALL, null);\n   }\n\n   @After\n   public void tearDown() {\n      getLoggerConfig().removeAppender(testAppender.getName());\n   }\n\n   private static LoggerConfig getLoggerConfig() {\n      LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);\n      Configuration configuration = loggerContext.getConfiguration();\n      return configuration.getRootLogger();\n   }\n\n   @Test\n   public void testJdbcUrlLogging() {\n      List<String> urls = Arrays.asList(\n         \"jdbc:postgresql://host/d_dlq?user=USER&password=SECRET\",\n         \"jdbc:postgresql://host/d_dlq?user=USER&truststorePassword=SECRET\",\n         \"jdbc:postgresql://host/d_dlq?a=b&password=SECRET&user=USER\",\n         \"jdbc:postgresql://host/d_dlq?a=b&sslpassword=SECRET&user=USER\",\n         \"jdbc:postgresql://host/d_dlq?truststorePassword=SECRET;user=USER&password=SECRET#extra\",\n         \"jdbc:postgresql://host/d_dlq?a=b&sslpassword=SECRET&password=SECRET&user=USER\",\n         \"jdbc:postgresql://host/d_dlq?sslpassword=SECRET&password=SECRET&trustPassword=SECRET&user=USER\",\n         \"jdbc:postgresql://host/d_dlq?password=SECRET#user=USER;extra\"\n      );\n\n      for (String url : urls) {\n         testJdbcUrl(url);\n      }\n   }\n\n   private void testJdbcUrl(String jdbcUrl) {\n      HikariConfig config = newHikariConfig();\n      config.setJdbcUrl(jdbcUrl);\n      config.validate();\n\n      assertTrue(testAppender.getLog().contains(\"jdbc:postgresql://host/d_dlq\"));\n      assertTrue(testAppender.getLog().contains(\"user=USER\"));\n      assertFalse(\"Log should not contain password\", testAppender.getLog().contains(\"SECRET\"));\n   }\n\n\n   private static class TestAppender extends AbstractAppender {\n\n      private String log;\n\n      TestAppender() {\n         super(\"TestAppender\", (Filter)null, (Layout)null, true, Property.EMPTY_ARRAY);\n      }\n\n      @Override\n      public void append(LogEvent event) {\n         log += event.getMessage().getFormattedMessage() + \"\\n\";\n      }\n\n      String getLog() {\n         return log;\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/datasource/TestSealedConfig.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.datasource;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.util.Credentials;\nimport org.junit.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.junit.Assert.fail;\n\npublic class TestSealedConfig\n{\n   @Test(expected = IllegalStateException.class)\n   public void testSealed1() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n         fail(\"Exception should have been thrown\");\n      }\n   }\n\n   @Test(expected = IllegalStateException.class)\n   public void testSealed2() throws SQLException\n   {\n      HikariDataSource ds = new HikariDataSource();\n      ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource closeable = ds) {\n         try (Connection connection = ds.getConnection()) {\n            ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n            fail(\"Exception should have been thrown\");\n         }\n      }\n   }\n\n   @Test(expected = IllegalStateException.class)\n   public void testSealed3() throws SQLException\n   {\n      HikariDataSource ds = new HikariDataSource();\n      ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource closeable = ds) {\n         try (Connection connection = ds.getConnection()) {\n            ds.setAutoCommit(false);\n            fail(\"Exception should have been thrown\");\n         }\n      }\n   }\n\n   @Test\n   public void testSealedAccessibleMethods() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         ds.setConnectionTimeout(5000);\n         ds.setValidationTimeout(5000);\n         ds.setIdleTimeout(30000);\n         ds.setLeakDetectionThreshold(60000);\n         ds.setMaxLifetime(1800000);\n         ds.setMinimumIdle(5);\n         ds.setMaximumPoolSize(8);\n         ds.setPassword(\"password\");\n         ds.setUsername(\"username\");\n         ds.setCredentials(Credentials.of(\"anothername\", \"anotherpassword\"));\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/db/BasicPoolTest.java",
    "content": "/*\n * Copyright (C) 2016 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.db;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.pool.HikariPool;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.getUnsealedConfig;\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\n\n/**\n * @author brettw\n *\n */\npublic class BasicPoolTest\n{\n   @Before\n   public void setup() throws SQLException\n   {\n       HikariConfig config = newHikariConfig();\n       config.setMinimumIdle(1);\n       config.setMaximumPoolSize(2);\n       config.setConnectionTestQuery(\"SELECT 1\");\n       config.setDataSourceClassName(\"org.h2.jdbcx.JdbcDataSource\");\n       config.addDataSourceProperty(\"url\", \"jdbc:h2:mem:test;DB_CLOSE_DELAY=-1\");\n\n       try (HikariDataSource ds = new HikariDataSource(config);\n            Connection conn = ds.getConnection();\n            Statement stmt = conn.createStatement()) {\n          stmt.execute(\"DROP TABLE IF EXISTS basic_pool_test\");\n          stmt.execute(\"CREATE TABLE basic_pool_test (\"\n                            + \"id INTEGER NOT NULL PRIMARY KEY, \"\n                            + \"timestamp TIMESTAMP, \"\n                            + \"string VARCHAR(128), \"\n                            + \"string_from_number NUMERIC \"\n                            + \")\");\n       }\n   }\n\n   @Test\n   public void testIdleTimeout() throws InterruptedException, SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(5);\n      config.setMaximumPoolSize(10);\n      config.setConnectionTestQuery(\"SELECT 1\");\n      config.setDataSourceClassName(\"org.h2.jdbcx.JdbcDataSource\");\n      config.addDataSourceProperty(\"url\", \"jdbc:h2:mem:test;DB_CLOSE_DELAY=-1\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"1000\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         getUnsealedConfig(ds).setIdleTimeout(3000);\n\n         System.clearProperty(\"com.zaxxer.hikari.housekeeping.periodMs\");\n\n         SECONDS.sleep(1);\n\n         HikariPool pool = getPool(ds);\n\n         assertEquals(\"Total connections not as expected\", 5, pool.getTotalConnections());\n         assertEquals(\"Idle connections not as expected\", 5, pool.getIdleConnections());\n\n         try (Connection connection = ds.getConnection()) {\n            Assert.assertNotNull(connection);\n\n            MILLISECONDS.sleep(1500);\n\n            assertEquals(\"Second total connections not as expected\", 6, pool.getTotalConnections());\n            assertEquals(\"Second idle connections not as expected\", 5, pool.getIdleConnections());\n         }\n\n         assertEquals(\"Idle connections not as expected\", 6, pool.getIdleConnections());\n\n         MILLISECONDS.sleep(3000);\n\n         assertEquals(\"Third total connections not as expected\", 5, pool.getTotalConnections());\n         assertEquals(\"Third idle connections not as expected\", 5, pool.getIdleConnections());\n      }\n   }\n\n   @Test\n   public void testIdleTimeout2() throws InterruptedException, SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMaximumPoolSize(50);\n      config.setConnectionTestQuery(\"SELECT 1\");\n      config.setDataSourceClassName(\"org.h2.jdbcx.JdbcDataSource\");\n      config.addDataSourceProperty(\"url\", \"jdbc:h2:mem:test;DB_CLOSE_DELAY=-1\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"1000\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         System.clearProperty(\"com.zaxxer.hikari.housekeeping.periodMs\");\n\n         SECONDS.sleep(3);\n\n         HikariPool pool = getPool(ds);\n\n         getUnsealedConfig(ds).setIdleTimeout(3000);\n\n         assertEquals(\"Total connections not as expected\", 50, pool.getTotalConnections());\n         assertEquals(\"Idle connections not as expected\", 50, pool.getIdleConnections());\n\n         try (Connection connection = ds.getConnection()) {\n            assertNotNull(connection);\n\n            MILLISECONDS.sleep(1500);\n\n            assertEquals(\"Second total connections not as expected\", 50, pool.getTotalConnections());\n            assertEquals(\"Second idle connections not as expected\", 49, pool.getIdleConnections());\n         }\n\n         assertEquals(\"Idle connections not as expected\", 50, pool.getIdleConnections());\n\n         SECONDS.sleep(3);\n\n         assertEquals(\"Third total connections not as expected\", 50, pool.getTotalConnections());\n         assertEquals(\"Third idle connections not as expected\", 50, pool.getIdleConnections());\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/metrics/dropwizard/CodaHaleMetricsTrackerTest.java",
    "content": "package com.zaxxer.hikari.metrics.dropwizard;\n\nimport com.codahale.metrics.MetricRegistry;\nimport com.zaxxer.hikari.mocks.StubPoolStats;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport static org.mockito.Mockito.verify;\n\n@RunWith(MockitoJUnitRunner.class)\npublic class CodaHaleMetricsTrackerTest\n{\n\n   @Mock\n   public MetricRegistry mockMetricRegistry;\n\n   private CodaHaleMetricsTracker testee;\n\n   @Before\n   public void setup()\n   {\n      testee = new CodaHaleMetricsTracker(\"mypool\", new StubPoolStats(0), mockMetricRegistry);\n   }\n\n   @Test\n   public void close()\n   {\n      testee.close();\n\n      verify(mockMetricRegistry).remove(\"mypool.pool.Wait\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.Usage\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.ConnectionCreation\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.ConnectionTimeoutRate\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.TotalConnections\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.IdleConnections\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.ActiveConnections\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.PendingConnections\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.MaxConnections\");\n      verify(mockMetricRegistry).remove(\"mypool.pool.MinConnections\");\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerTest.java",
    "content": "package com.zaxxer.hikari.metrics.dropwizard;\n\nimport com.zaxxer.hikari.mocks.StubPoolStats;\nimport io.dropwizard.metrics5.MetricRegistry;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport static org.mockito.Mockito.verify;\n\n@RunWith(MockitoJUnitRunner.class)\npublic class Dropwizard5MetricsTrackerTest\n{\n   @Mock\n   public MetricRegistry mockMetricRegistry;\n\n   private Dropwizard5MetricsTracker testee;\n\n   @Before\n   public void setup()\n   {\n      testee = new Dropwizard5MetricsTracker(\"mypool\", new StubPoolStats(0), mockMetricRegistry);\n   }\n\n   @Test\n   public void close()\n   {\n      testee.close();\n\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.Wait\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.Usage\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.ConnectionCreation\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.ConnectionTimeoutRate\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.TotalConnections\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.IdleConnections\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.ActiveConnections\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.PendingConnections\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.MaxConnections\"));\n      verify(mockMetricRegistry).remove(MetricRegistry.name(\"mypool.pool.MinConnections\"));\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/metrics/micrometer/MicrometerMetricsTrackerTest.java",
    "content": "package com.zaxxer.hikari.metrics.micrometer;\n\nimport com.zaxxer.hikari.mocks.StubPoolStats;\nimport io.micrometer.core.instrument.MeterRegistry;\nimport io.micrometer.core.instrument.simple.SimpleMeterRegistry;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\npublic class MicrometerMetricsTrackerTest\n{\n\n   private MeterRegistry mockMeterRegistry = new SimpleMeterRegistry();\n\n   private MicrometerMetricsTracker testee;\n\n   @Before\n   public void setup()\n   {\n      testee = new MicrometerMetricsTracker(\"mypool\", new StubPoolStats(1000L), mockMeterRegistry);\n   }\n\n   @Test\n   public void close()\n   {\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.acquire\").tag(\"pool\", \"mypool\").timer());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.usage\").tag(\"pool\", \"mypool\").timer());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.creation\").tag(\"pool\", \"mypool\").timer());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.timeout\").tag(\"pool\", \"mypool\").counter());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections\").tag(\"pool\", \"mypool\").gauge());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.idle\").tag(\"pool\", \"mypool\").gauge());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.active\").tag(\"pool\", \"mypool\").gauge());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.pending\").tag(\"pool\", \"mypool\").gauge());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.max\").tag(\"pool\", \"mypool\").gauge());\n      Assert.assertNotNull(mockMeterRegistry.find(\"hikaricp.connections.min\").tag(\"pool\", \"mypool\").gauge());\n\n      testee.close();\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/metrics/prometheus/HikariCPCollectorTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.metrics.prometheus;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertNull;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\nimport java.sql.Connection;\nimport java.util.List;\n\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport io.prometheus.client.Collector;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubConnection;\n\nimport io.prometheus.client.CollectorRegistry;\n\npublic class HikariCPCollectorTest\n{\n\n   private CollectorRegistry collectorRegistry;\n\n   @Before\n   public void setupCollectorRegistry()\n   {\n      this.collectorRegistry = new CollectorRegistry();\n   }\n\n   @Test\n   public void noConnection()\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(this.collectorRegistry));\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      StubConnection.slowCreate = true;\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         assertThat(getValue(\"hikaricp_active_connections\", \"noConnection\"), is(0.0));\n         assertThat(getValue(\"hikaricp_idle_connections\", \"noConnection\"), is(0.0));\n         assertThat(getValue(\"hikaricp_pending_threads\", \"noConnection\"), is(0.0));\n         assertThat(getValue(\"hikaricp_connections\", \"noConnection\"), is(0.0));\n         assertThat(getValue(\"hikaricp_max_connections\", \"noConnection\"), is(10.0));\n         assertThat(getValue(\"hikaricp_min_connections\", \"noConnection\"), is(0.0));\n      }\n      finally {\n         StubConnection.slowCreate = false;\n      }\n   }\n\n   @Test\n   public void noConnectionWithoutPoolName()\n   {\n      HikariConfig config = new HikariConfig();\n      config.setMinimumIdle(0);\n      config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(this.collectorRegistry));\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      StubConnection.slowCreate = true;\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         String poolName = ds.getHikariConfigMXBean().getPoolName();\n         assertThat(getValue(\"hikaricp_active_connections\", poolName), is(0.0));\n         assertThat(getValue(\"hikaricp_idle_connections\", poolName), is(0.0));\n         assertThat(getValue(\"hikaricp_pending_threads\", poolName), is(0.0));\n         assertThat(getValue(\"hikaricp_connections\", poolName), is(0.0));\n         assertThat(getValue(\"hikaricp_max_connections\", poolName), is(10.0));\n         assertThat(getValue(\"hikaricp_min_connections\", poolName), is(0.0));\n      }\n      finally {\n         StubConnection.slowCreate = false;\n      }\n   }\n\n   @Test\n   public void connection1() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(this.collectorRegistry));\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setMaximumPoolSize(1);\n\n      StubConnection.slowCreate = true;\n      try (HikariDataSource ds = new HikariDataSource(config);\n         Connection connection1 = ds.getConnection()) {\n\n         quietlySleep(1000);\n\n         assertThat(getValue(\"hikaricp_active_connections\", \"connection1\"), is(1.0));\n         assertThat(getValue(\"hikaricp_idle_connections\", \"connection1\"), is(0.0));\n         assertThat(getValue(\"hikaricp_pending_threads\", \"connection1\"), is(0.0));\n         assertThat(getValue(\"hikaricp_connections\", \"connection1\"), is(1.0));\n         assertThat(getValue(\"hikaricp_max_connections\", \"connection1\"), is(1.0));\n         assertThat(getValue(\"hikaricp_min_connections\", \"connection1\"), is(1.0));\n      }\n      finally {\n         StubConnection.slowCreate = false;\n      }\n   }\n\n   @Test\n   public void connectionClosed() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(this.collectorRegistry));\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setMaximumPoolSize(1);\n\n      StubConnection.slowCreate = true;\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         try (Connection connection1 = ds.getConnection()) {\n            // close immediately\n         }\n\n         assertThat(getValue(\"hikaricp_active_connections\", \"connectionClosed\"), is(0.0));\n         assertThat(getValue(\"hikaricp_idle_connections\", \"connectionClosed\"), is(1.0));\n         assertThat(getValue(\"hikaricp_pending_threads\", \"connectionClosed\"), is(0.0));\n         assertThat(getValue(\"hikaricp_connections\", \"connectionClosed\"), is(1.0));\n         assertThat(getValue(\"hikaricp_max_connections\", \"connectionClosed\"), is(1.0));\n         assertThat(getValue(\"hikaricp_min_connections\", \"connectionClosed\"), is(1.0));\n      }\n      finally {\n         StubConnection.slowCreate = false;\n      }\n   }\n\n   @Test\n   public void poolStatsRemovedAfterShutDown() throws Exception\n   {\n      HikariConfig config = new HikariConfig();\n      config.setPoolName(\"shutDownPool\");\n      config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(this.collectorRegistry));\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setMaximumPoolSize(1);\n\n      StubConnection.slowCreate = true;\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         try (Connection connection1 = ds.getConnection()) {\n            // close immediately\n         }\n\n         assertThat(getValue(\"hikaricp_active_connections\", \"shutDownPool\"), is(0.0));\n         assertThat(getValue(\"hikaricp_idle_connections\", \"shutDownPool\"), is(1.0));\n         assertThat(getValue(\"hikaricp_pending_threads\", \"shutDownPool\"), is(0.0));\n         assertThat(getValue(\"hikaricp_connections\", \"shutDownPool\"), is(1.0));\n         assertThat(getValue(\"hikaricp_max_connections\", \"shutDownPool\"), is(1.0));\n         assertThat(getValue(\"hikaricp_min_connections\", \"shutDownPool\"), is(1.0));\n      }\n      finally {\n         StubConnection.slowCreate = false;\n      }\n\n      assertNull(getValue(\"hikaricp_active_connections\", \"shutDownPool\"));\n      assertNull(getValue(\"hikaricp_idle_connections\", \"shutDownPool\"));\n      assertNull(getValue(\"hikaricp_pending_threads\", \"shutDownPool\"));\n      assertNull(getValue(\"hikaricp_connections\", \"shutDownPool\"));\n      assertNull(getValue(\"hikaricp_max_connections\", \"shutDownPool\"));\n      assertNull(getValue(\"hikaricp_min_connections\", \"shutDownPool\"));\n   }\n\n   @Test\n   public void testHikariCPCollectorGaugesMetricsInitialization()\n   {\n      HikariCPCollector hikariCPCollector = new HikariCPCollector();\n      hikariCPCollector.add(\"collectorTestPool\", poolStatsWithPredefinedValues());\n      List<Collector.MetricFamilySamples> metrics = hikariCPCollector.collect();\n      hikariCPCollector.register(collectorRegistry);\n\n      assertThat(metrics.size(), is(6));\n      assertThat(metrics.stream().filter(metricFamilySamples -> metricFamilySamples.type == Collector.Type.GAUGE).count(), is(6L));\n      assertThat(getValue(\"hikaricp_active_connections\", \"collectorTestPool\"), is(58.0));\n      assertThat(getValue(\"hikaricp_idle_connections\", \"collectorTestPool\"), is(42.0));\n      assertThat(getValue(\"hikaricp_pending_threads\", \"collectorTestPool\"), is(1.0));\n      assertThat(getValue(\"hikaricp_connections\", \"collectorTestPool\"), is(100.0));\n      assertThat(getValue(\"hikaricp_max_connections\", \"collectorTestPool\"), is(100.0));\n      assertThat(getValue(\"hikaricp_min_connections\", \"collectorTestPool\"), is(3.0));\n   }\n\n   private Double getValue(String name, String poolName)\n   {\n      String[] labelNames = {\"pool\"};\n      String[] labelValues = {poolName};\n      return this.collectorRegistry.getSampleValue(name, labelNames, labelValues);\n   }\n\n   private PoolStats poolStatsWithPredefinedValues()\n   {\n      return new PoolStats(0) {\n         @Override\n         protected void update() {\n            totalConnections = 100;\n            idleConnections = 42;\n            activeConnections = 58;\n            pendingThreads = 1;\n            maxConnections = 100;\n            minConnections = 3;\n         }\n      };\n   }\n\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerFactoryTest.java",
    "content": "package com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.metrics.PoolStats;\nimport io.prometheus.client.Collector;\nimport io.prometheus.client.CollectorRegistry;\nimport org.junit.After;\nimport org.junit.Test;\n\nimport java.util.ArrayList;\nimport java.util.Enumeration;\nimport java.util.List;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class PrometheusHistogramMetricsTrackerFactoryTest {\n\n   @Test\n   public void registersToProvidedCollectorRegistry() {\n      CollectorRegistry collectorRegistry = new CollectorRegistry();\n      PrometheusHistogramMetricsTrackerFactory factory =\n         new PrometheusHistogramMetricsTrackerFactory(collectorRegistry);\n      factory.create(\"testpool-1\", poolStats());\n      assertHikariMetricsAreNotPresent(CollectorRegistry.defaultRegistry);\n      assertHikariMetricsArePresent(collectorRegistry);\n   }\n\n   @Test\n   public void registersToDefaultCollectorRegistry() {\n      PrometheusHistogramMetricsTrackerFactory factory = new PrometheusHistogramMetricsTrackerFactory();\n      factory.create(\"testpool-2\", poolStats());\n      assertHikariMetricsArePresent(CollectorRegistry.defaultRegistry);\n   }\n\n   @After\n   public void clearCollectorRegistry(){\n      CollectorRegistry.defaultRegistry.clear();\n   }\n\n   private void assertHikariMetricsArePresent(CollectorRegistry collectorRegistry) {\n      List<String> registeredMetrics = toMetricNames(collectorRegistry.metricFamilySamples());\n      assertTrue(registeredMetrics.contains(\"hikaricp_active_connections\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_idle_connections\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_pending_threads\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_connections\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_max_connections\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_min_connections\"));\n   }\n\n   private void assertHikariMetricsAreNotPresent(CollectorRegistry collectorRegistry) {\n      List<String> registeredMetrics = toMetricNames(collectorRegistry.metricFamilySamples());\n      assertFalse(registeredMetrics.contains(\"hikaricp_active_connections\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_idle_connections\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_pending_threads\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_connections\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_max_connections\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_min_connections\"));\n   }\n\n   private List<String> toMetricNames(Enumeration<Collector.MetricFamilySamples> enumeration) {\n      List<String> list = new ArrayList<>();\n      while (enumeration.hasMoreElements()) {\n         list.add(enumeration.nextElement().name);\n      }\n      return list;\n   }\n\n   private PoolStats poolStats() {\n      return new PoolStats(0) {\n         @Override\n         protected void update() {\n            // do nothing\n         }\n      };\n   }\n\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/metrics/prometheus/PrometheusHistogramMetricsTrackerTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport io.prometheus.client.CollectorRegistry;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLTransientConnectionException;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertNotNull;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\npublic class PrometheusHistogramMetricsTrackerTest {\n\n   private CollectorRegistry defaultCollectorRegistry;\n   private CollectorRegistry customCollectorRegistry;\n\n   private static final String POOL_LABEL_NAME = \"pool\";\n   private static final String[] LABEL_NAMES = {POOL_LABEL_NAME};\n\n   @Before\n   public void setupCollectorRegistry() {\n      this.defaultCollectorRegistry = new CollectorRegistry();\n      this.customCollectorRegistry = new CollectorRegistry();\n   }\n\n   @Test\n   public void recordConnectionTimeout() throws Exception {\n      HikariConfig config = newHikariConfig();\n      config.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));\n      config.setJdbcUrl(\"jdbc:h2:mem:\");\n      config.setMaximumPoolSize(2);\n      config.setConnectionTimeout(250);\n\n      String[] labelValues = {config.getPoolName()};\n\n      try (HikariDataSource hikariDataSource = new HikariDataSource(config)) {\n         try (Connection connection1 = hikariDataSource.getConnection();\n              Connection connection2 = hikariDataSource.getConnection()) {\n            try (Connection connection3 = hikariDataSource.getConnection()) {\n            } catch (SQLTransientConnectionException ignored) {\n            }\n         }\n\n         Double total = defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\",\n            LABEL_NAMES,\n            labelValues\n         );\n         assertThat(total, is(1.0));\n      }\n   }\n\n   @Test\n   public void connectionAcquisitionMetrics() {\n      checkSummaryMetricFamily(\"hikaricp_connection_acquired_nanos\");\n   }\n\n   @Test\n   public void connectionUsageMetrics() {\n      checkSummaryMetricFamily(\"hikaricp_connection_usage_millis\");\n   }\n\n   @Test\n   public void connectionCreationMetrics() {\n      checkSummaryMetricFamily(\"hikaricp_connection_creation_millis\");\n   }\n\n   @Test\n   public void testMultiplePoolNameWithOneCollectorRegistry()\n   {\n      HikariConfig configFirstPool = newHikariConfig();\n      configFirstPool.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));\n      configFirstPool.setPoolName(\"first\");\n      configFirstPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configFirstPool.setMaximumPoolSize(2);\n      configFirstPool.setConnectionTimeout(250);\n\n      HikariConfig configSecondPool = newHikariConfig();\n      configSecondPool.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));\n      configSecondPool.setPoolName(\"second\");\n      configSecondPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configSecondPool.setMaximumPoolSize(4);\n      configSecondPool.setConnectionTimeout(250);\n\n      String[] labelValuesFirstPool = {configFirstPool.getPoolName()};\n      String[] labelValuesSecondPool = {configSecondPool.getPoolName()};\n\n      try (HikariDataSource ignoredFirstPool = new HikariDataSource(configFirstPool)) {\n         assertThat(defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesFirstPool),\n            is(0.0));\n\n         try (HikariDataSource ignoredSecondPool = new HikariDataSource(configSecondPool)) {\n            assertThat(defaultCollectorRegistry.getSampleValue(\n               \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesSecondPool),\n               is(0.0));\n         }\n      }\n   }\n\n   @Test\n   public void testMultiplePoolNameWithDifferentCollectorRegistries()\n   {\n      HikariConfig configFirstPool = newHikariConfig();\n      configFirstPool.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));\n      configFirstPool.setPoolName(\"first\");\n      configFirstPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configFirstPool.setMaximumPoolSize(2);\n      configFirstPool.setConnectionTimeout(250);\n\n      HikariConfig configSecondPool = newHikariConfig();\n      configSecondPool.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(customCollectorRegistry));\n      configSecondPool.setPoolName(\"second\");\n      configSecondPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configSecondPool.setMaximumPoolSize(4);\n      configSecondPool.setConnectionTimeout(250);\n\n      String[] labelValuesFirstPool = {configFirstPool.getPoolName()};\n      String[] labelValuesSecondPool = {configSecondPool.getPoolName()};\n\n      try (HikariDataSource ignoredFirstPool = new HikariDataSource(configFirstPool)) {\n         assertThat(defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesFirstPool),\n            is(0.0));\n\n         try (HikariDataSource ignoredSecondPool = new HikariDataSource(configSecondPool)) {\n            assertThat(customCollectorRegistry.getSampleValue(\n               \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesSecondPool),\n               is(0.0));\n         }\n      }\n   }\n\n   private void checkSummaryMetricFamily(String metricName) {\n      HikariConfig config = newHikariConfig();\n      config.setMetricsTrackerFactory(new PrometheusHistogramMetricsTrackerFactory(defaultCollectorRegistry));\n      config.setJdbcUrl(\"jdbc:h2:mem:\");\n\n      try (HikariDataSource ignored = new HikariDataSource(config)) {\n         Double count = defaultCollectorRegistry.getSampleValue(\n            metricName + \"_count\",\n            LABEL_NAMES,\n            new String[]{config.getPoolName()}\n         );\n         assertNotNull(count);\n\n         Double sum = defaultCollectorRegistry.getSampleValue(\n            metricName + \"_sum\",\n            LABEL_NAMES,\n            new String[]{config.getPoolName()}\n         );\n         assertNotNull(sum);\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/metrics/prometheus/PrometheusMetricsTrackerFactoryTest.java",
    "content": "package com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.mocks.StubPoolStats;\nimport io.prometheus.client.Collector;\nimport io.prometheus.client.CollectorRegistry;\nimport org.junit.After;\nimport org.junit.Test;\n\nimport java.util.ArrayList;\nimport java.util.Enumeration;\nimport java.util.List;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class PrometheusMetricsTrackerFactoryTest\n{\n\n   @After\n   public void clearCollectorRegistry()\n   {\n      CollectorRegistry.defaultRegistry.clear();\n   }\n\n   @Test\n   public void registersToProvidedCollectorRegistry()\n   {\n      CollectorRegistry collectorRegistry = new CollectorRegistry();\n      PrometheusMetricsTrackerFactory factory = new PrometheusMetricsTrackerFactory(collectorRegistry);\n      factory.create(\"testpool-1\", new StubPoolStats(0));\n      assertHikariMetricsAreNotPresent(CollectorRegistry.defaultRegistry);\n      assertHikariMetricsArePresent(collectorRegistry);\n   }\n\n   @Test\n   public void registersToDefaultCollectorRegistry()\n   {\n      PrometheusMetricsTrackerFactory factory = new PrometheusMetricsTrackerFactory();\n      factory.create(\"testpool-2\", new StubPoolStats(0));\n      assertHikariMetricsArePresent(CollectorRegistry.defaultRegistry);\n   }\n\n   private void assertHikariMetricsArePresent(CollectorRegistry collectorRegistry)\n   {\n      List<String> registeredMetrics = toMetricNames(collectorRegistry.metricFamilySamples());\n      assertTrue(registeredMetrics.contains(\"hikaricp_active_connections\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_idle_connections\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_pending_threads\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_connections\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_max_connections\"));\n      assertTrue(registeredMetrics.contains(\"hikaricp_min_connections\"));\n   }\n\n   private void assertHikariMetricsAreNotPresent(CollectorRegistry collectorRegistry)\n   {\n      List<String> registeredMetrics = toMetricNames(collectorRegistry.metricFamilySamples());\n      assertFalse(registeredMetrics.contains(\"hikaricp_active_connections\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_idle_connections\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_pending_threads\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_connections\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_max_connections\"));\n      assertFalse(registeredMetrics.contains(\"hikaricp_min_connections\"));\n   }\n\n   private List<String> toMetricNames(Enumeration<Collector.MetricFamilySamples> enumeration)\n   {\n      List<String> list = new ArrayList<>();\n      while (enumeration.hasMoreElements()) {\n         list.add(enumeration.nextElement().name);\n      }\n      return list;\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/metrics/prometheus/PrometheusMetricsTrackerTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.metrics.prometheus;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.mocks.StubPoolStats;\nimport io.prometheus.client.CollectorRegistry;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLTransientConnectionException;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\npublic class PrometheusMetricsTrackerTest\n{\n\n   private CollectorRegistry defaultCollectorRegistry;\n   private CollectorRegistry customCollectorRegistry;\n\n   private static final String POOL_LABEL_NAME = \"pool\";\n   private static final String[] LABEL_NAMES = {POOL_LABEL_NAME};\n\n   private static final String QUANTILE_LABEL_NAME = \"quantile\";\n   private static final String[] QUANTILE_LABEL_VALUES = new String[]{\"0.5\", \"0.95\", \"0.99\"};\n\n   @Before\n   public void setupCollectorRegistry()\n   {\n      this.defaultCollectorRegistry = new CollectorRegistry();\n      this.customCollectorRegistry = new CollectorRegistry();\n   }\n\n   @Test\n   public void recordConnectionTimeout() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(defaultCollectorRegistry));\n      config.setJdbcUrl(\"jdbc:h2:mem:\");\n      config.setMaximumPoolSize(2);\n      config.setConnectionTimeout(250);\n\n      String[] labelValues = {config.getPoolName()};\n\n      try (HikariDataSource hikariDataSource = new HikariDataSource(config)) {\n         try (Connection connection1 = hikariDataSource.getConnection();\n              Connection connection2 = hikariDataSource.getConnection()) {\n            try (Connection connection3 = hikariDataSource.getConnection()) {\n            } catch (SQLTransientConnectionException ignored) {\n            }\n         }\n\n         Double total = defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValues\n         );\n         assertThat(total, is(1.0));\n      }\n   }\n\n   @Test\n   public void connectionAcquisitionMetrics()\n   {\n      checkSummaryMetricFamily(\"hikaricp_connection_acquired_nanos\");\n   }\n\n   @Test\n   public void connectionUsageMetrics()\n   {\n      checkSummaryMetricFamily(\"hikaricp_connection_usage_millis\");\n   }\n\n   @Test\n   public void connectionCreationMetrics()\n   {\n      checkSummaryMetricFamily(\"hikaricp_connection_creation_millis\");\n   }\n\n   @Test\n   public void testMultiplePoolNameWithOneCollectorRegistry()\n   {\n      HikariConfig configFirstPool = newHikariConfig();\n      configFirstPool.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(defaultCollectorRegistry));\n      configFirstPool.setPoolName(\"first\");\n      configFirstPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configFirstPool.setMaximumPoolSize(2);\n      configFirstPool.setConnectionTimeout(250);\n\n      HikariConfig configSecondPool = newHikariConfig();\n      configSecondPool.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(defaultCollectorRegistry));\n      configSecondPool.setPoolName(\"second\");\n      configSecondPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configSecondPool.setMaximumPoolSize(4);\n      configSecondPool.setConnectionTimeout(250);\n\n      String[] labelValuesFirstPool = {configFirstPool.getPoolName()};\n      String[] labelValuesSecondPool = {configSecondPool.getPoolName()};\n\n      try (HikariDataSource ignoredFirstPool = new HikariDataSource(configFirstPool)) {\n         assertThat(defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesFirstPool),\n            is(0.0));\n\n         try (HikariDataSource ignoredSecondPool = new HikariDataSource(configSecondPool)) {\n            assertThat(defaultCollectorRegistry.getSampleValue(\n               \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesSecondPool),\n               is(0.0));\n         }\n      }\n   }\n\n   @Test\n   public void testMultiplePoolNameWithDifferentCollectorRegistries()\n   {\n      HikariConfig configFirstPool = newHikariConfig();\n      configFirstPool.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(defaultCollectorRegistry));\n      configFirstPool.setPoolName(\"first\");\n      configFirstPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configFirstPool.setMaximumPoolSize(2);\n      configFirstPool.setConnectionTimeout(250);\n\n      HikariConfig configSecondPool = newHikariConfig();\n      configSecondPool.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(customCollectorRegistry));\n      configSecondPool.setPoolName(\"second\");\n      configSecondPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configSecondPool.setMaximumPoolSize(4);\n      configSecondPool.setConnectionTimeout(250);\n\n      String[] labelValuesFirstPool = {configFirstPool.getPoolName()};\n      String[] labelValuesSecondPool = {configSecondPool.getPoolName()};\n\n      try (HikariDataSource ignoredFirstPool = new HikariDataSource(configFirstPool)) {\n         assertThat(defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesFirstPool),\n            is(0.0));\n\n         try (HikariDataSource ignoredSecondPool = new HikariDataSource(configSecondPool)) {\n            assertThat(customCollectorRegistry.getSampleValue(\n               \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesSecondPool),\n               is(0.0));\n         }\n      }\n   }\n\n   @Test\n   public void testMetricsRemovedAfterShutDown()\n   {\n      HikariConfig configFirstPool = newHikariConfig();\n      configFirstPool.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(defaultCollectorRegistry));\n      configFirstPool.setPoolName(\"first\");\n      configFirstPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configFirstPool.setMaximumPoolSize(2);\n      configFirstPool.setConnectionTimeout(250);\n\n      HikariConfig configSecondPool = newHikariConfig();\n      configSecondPool.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(customCollectorRegistry));\n      configSecondPool.setPoolName(\"second\");\n      configSecondPool.setJdbcUrl(\"jdbc:h2:mem:\");\n      configSecondPool.setMaximumPoolSize(4);\n      configSecondPool.setConnectionTimeout(250);\n\n      String[] labelValuesFirstPool = {configFirstPool.getPoolName()};\n      String[] labelValuesSecondPool = {configSecondPool.getPoolName()};\n\n      try (HikariDataSource ignoredFirstPool = new HikariDataSource(configFirstPool)) {\n         assertThat(defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesFirstPool),\n            is(0.0));\n\n         try (HikariDataSource ignoredSecondPool = new HikariDataSource(configSecondPool)) {\n            assertThat(customCollectorRegistry.getSampleValue(\n               \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesSecondPool),\n               is(0.0));\n         }\n\n         assertNull(defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesSecondPool));\n\n         assertThat(defaultCollectorRegistry.getSampleValue(\n            \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValuesFirstPool),\n            is(0.0));\n      }\n   }\n\n   @Test\n   public void testCloseMethod()\n   {\n      String[] labelValues = {\"testPool\"};\n      PrometheusMetricsTrackerFactory prometheusFactory = new PrometheusMetricsTrackerFactory(defaultCollectorRegistry);\n      IMetricsTracker prometheusTracker = prometheusFactory.create(\"testPool\", new StubPoolStats(0));\n\n      prometheusTracker.recordConnectionTimeout();\n      prometheusTracker.recordConnectionAcquiredNanos(42L);\n      prometheusTracker.recordConnectionUsageMillis(111L);\n      prometheusTracker.recordConnectionCreatedMillis(101L);\n\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValues),\n         is(1.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connection_acquired_nanos_sum\", LABEL_NAMES, labelValues),\n         is(42.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connection_usage_millis_sum\", LABEL_NAMES, labelValues),\n         is(111.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connection_creation_millis_sum\", LABEL_NAMES, labelValues),\n         is(101.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_active_connections\", LABEL_NAMES, labelValues),\n         is(0.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_idle_connections\", LABEL_NAMES, labelValues),\n         is(0.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_pending_threads\", LABEL_NAMES, labelValues),\n         is(0.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connections\", LABEL_NAMES, labelValues),\n         is(0.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_max_connections\", LABEL_NAMES, labelValues),\n         is(0.0));\n      assertThat(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_min_connections\", LABEL_NAMES, labelValues),\n         is(0.0));\n\n      prometheusTracker.close();\n\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connection_timeout_total\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connection_acquired_nanos_sum\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connection_usage_millis_sum\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connection_creation_millis_sum\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_active_connections\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_idle_connections\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_pending_threads\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connections\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_connections\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_max_connections\", LABEL_NAMES, labelValues));\n      assertNull(defaultCollectorRegistry.getSampleValue(\n         \"hikaricp_min_connections\", LABEL_NAMES, labelValues));\n   }\n\n   private void checkSummaryMetricFamily(String metricName)\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(defaultCollectorRegistry));\n      config.setJdbcUrl(\"jdbc:h2:mem:\");\n\n      try (HikariDataSource ignored = new HikariDataSource(config)) {\n         Double count = defaultCollectorRegistry.getSampleValue(\n            metricName + \"_count\",\n            LABEL_NAMES,\n            new String[]{config.getPoolName()}\n         );\n         assertNotNull(count);\n\n         Double sum = defaultCollectorRegistry.getSampleValue(\n            metricName + \"_sum\",\n            LABEL_NAMES,\n            new String[]{config.getPoolName()}\n         );\n         assertNotNull(sum);\n\n         for (String quantileLabelValue : QUANTILE_LABEL_VALUES) {\n            Double quantileValue = defaultCollectorRegistry.getSampleValue(\n               metricName,\n               new String[]{POOL_LABEL_NAME, QUANTILE_LABEL_NAME},\n               new String[]{config.getPoolName(), quantileLabelValue}\n            );\n            assertNotNull(\"q = \" + quantileLabelValue, quantileValue);\n         }\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/MockDataSource.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.mocks;\n\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doAnswer;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport java.io.PrintWriter;\nimport java.sql.CallableStatement;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.sql.Statement;\nimport java.util.logging.Logger;\n\nimport javax.sql.DataSource;\n\nimport org.mockito.invocation.InvocationOnMock;\nimport org.mockito.stubbing.Answer;\n\n/**\n *\n * @author Brett Wooldridge\n */\npublic class MockDataSource implements DataSource\n{\n    @Override\n    public Connection getConnection() throws SQLException\n    {\n        return createMockConnection();\n    }\n\n    @Override\n    public Connection getConnection(String username, String password) throws SQLException\n    {\n        return getConnection();\n    }\n\n    @Override\n    public PrintWriter getLogWriter() throws SQLException\n    {\n        return null;\n    }\n\n    @Override\n    public void setLogWriter(PrintWriter out) throws SQLException\n    {\n    }\n\n    @Override\n    public void setLoginTimeout(int seconds) throws SQLException\n    {\n    }\n\n    @Override\n    public int getLoginTimeout() throws SQLException\n    {\n        return 0;\n    }\n\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException\n    {\n        return null;\n    }\n\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException\n    {\n        return null;\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException\n    {\n        return false;\n    }\n\n    public static Connection createMockConnection() throws SQLException {\n        // Setup mock connection\n        final Connection mockConnection = mock(Connection.class);\n\n        // Autocommit is always true by default\n        when(mockConnection.getAutoCommit()).thenReturn(true);\n\n        // Handle Connection.createStatement()\n        Statement statement = mock(Statement.class);\n        when(mockConnection.createStatement()).thenReturn(statement);\n        when(mockConnection.createStatement(anyInt(), anyInt())).thenReturn(statement);\n        when(mockConnection.createStatement(anyInt(), anyInt(), anyInt())).thenReturn(statement);\n        when(mockConnection.isValid(anyInt())).thenReturn(true);\n\n        // Handle Connection.prepareStatement()\n        PreparedStatement mockPreparedStatement = mock(PreparedStatement.class);\n        when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement);\n        when(mockConnection.prepareStatement(anyString(), anyInt())).thenReturn(mockPreparedStatement);\n        when(mockConnection.prepareStatement(anyString(), any(int[].class))).thenReturn(mockPreparedStatement);\n        when(mockConnection.prepareStatement(anyString(), any(String[].class))).thenReturn(mockPreparedStatement);\n        when(mockConnection.prepareStatement(anyString(), anyInt(), anyInt())).thenReturn(mockPreparedStatement);\n        when(mockConnection.prepareStatement(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(mockPreparedStatement);\n        doAnswer(new Answer<Void>() {\n            @Override\n            public Void answer(InvocationOnMock invocation) throws Throwable\n            {\n                return null;\n            }\n        }).doNothing().when(mockPreparedStatement).setInt(anyInt(), anyInt());\n\n        ResultSet mockResultSet = mock(ResultSet.class);\n        when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet);\n        when(mockResultSet.getString(anyInt())).thenReturn(\"aString\");\n        when(mockResultSet.next()).thenReturn(true);\n\n        // Handle Connection.prepareCall()\n        CallableStatement mockCallableStatement = mock(CallableStatement.class);\n        when(mockConnection.prepareCall(anyString())).thenReturn(mockCallableStatement);\n        when(mockConnection.prepareCall(anyString(), anyInt(), anyInt())).thenReturn(mockCallableStatement);\n        when(mockConnection.prepareCall(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(mockCallableStatement);\n\n        // Handle Connection.close()\n//        doAnswer(new Answer<Void>() {\n//            public Void answer(InvocationOnMock invocation) throws Throwable {\n//                return null;\n//            }\n//        }).doThrow(new SQLException(\"Connection is already closed\")).when(mockConnection).close();\n\n        // Handle Connection.commit()\n//        doAnswer(new Answer<Void>() {\n//            public Void answer(InvocationOnMock invocation) throws Throwable {\n//                return null;\n//            }\n//        }).doThrow(new SQLException(\"Transaction already committed\")).when(mockConnection).commit();\n\n        // Handle Connection.rollback()\n//        doAnswer(new Answer<Void>() {\n//            public Void answer(InvocationOnMock invocation) throws Throwable {\n//                return null;\n//            }\n//        }).doThrow(new SQLException(\"Transaction already rolledback\")).when(mockConnection).rollback();\n\n        return mockConnection;\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/StubBaseConnection.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.mocks;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\npublic abstract class StubBaseConnection implements Connection\n{\n   public volatile boolean throwException;\n\n   /** {@inheritDoc} */\n   @Override\n   public Statement createStatement() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return new StubStatement(this);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return new StubPreparedStatement(this);\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/StubConnection.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.mocks;\n\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.CallableStatement;\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.DatabaseMetaData;\nimport java.sql.NClob;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLClientInfoException;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Savepoint;\nimport java.sql.Statement;\nimport java.sql.Struct;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport com.zaxxer.hikari.util.UtilityElf;\n\n/**\n *\n * @author Brett Wooldridge\n * @author Yanming Zhou\n */\npublic class StubConnection extends StubBaseConnection\n{\n   public static final AtomicInteger count = new AtomicInteger();\n   public static volatile boolean slowCreate;\n   public static volatile boolean oldDriver;\n   public static volatile Callable<Void> networkTimeoutSetter;\n   private volatile boolean isClosed = false;\n\n   private static long foo;\n   private boolean autoCommit;\n   private int isolation = Connection.TRANSACTION_READ_COMMITTED;\n   private String catalog;\n   private String schema;\n   private long waitTimeout;\n   public boolean beginRequestCalled = false;\n   public boolean endRequestCalled = false;\n\n   private static ScheduledExecutorService connectionWaitTimeout = new ScheduledThreadPoolExecutor(1);\n   private ScheduledFuture<?> waitTimeoutTask;\n\n   static {\n      foo = System.currentTimeMillis();\n   }\n\n   public StubConnection() {\n      count.incrementAndGet();\n      if (slowCreate) {\n         UtilityElf.quietlySleep(1000);\n      }\n   }\n\n   public StubConnection(long waitTimeout) {\n      this.waitTimeout = waitTimeout;\n      count.incrementAndGet();\n      if (slowCreate) {\n         UtilityElf.quietlySleep(1000);\n      }\n\n      try {\n         refreshConnectionWaitTimeout();\n      } catch (Exception e){\n         //ignore\n      }\n   }\n\n\n   /** {@inheritDoc} */\n   @SuppressWarnings(\"unchecked\")\n   @Override\n   public <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n\n      if (iface.isInstance(this)) {\n         return (T) this;\n      }\n\n      throw new SQLException(\"Wrapped connection is not an instance of \" + iface);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public CallableStatement prepareCall(String sql) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String nativeSQL(String sql) throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setAutoCommit(boolean autoCommit) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      this.autoCommit = autoCommit;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean getAutoCommit() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return autoCommit;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void commit() throws SQLException\n   {\n      refreshConnectionWaitTimeout();\n   }\n\n   private void refreshConnectionWaitTimeout() throws SQLException {\n      if (this.isClosed) {\n         throw new SQLException(\"connection has been closed\");\n      }\n\n      if (waitTimeoutTask != null) {\n         waitTimeoutTask.cancel(true);\n      }\n\n      if (waitTimeout > 0) {\n         waitTimeoutTask = connectionWaitTimeout.schedule(() -> { this.isClosed = true;}, waitTimeout, TimeUnit.MILLISECONDS);\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void rollback() throws SQLException\n   {\n\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void close() throws SQLException\n   {\n\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isClosed() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return isClosed;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public DatabaseMetaData getMetaData() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setReadOnly(boolean readOnly) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isReadOnly() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setCatalog(String catalog) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      this.catalog = catalog;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String getCatalog() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return catalog;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setTransactionIsolation(int level) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      this.isolation = level;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getTransactionIsolation() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return isolation;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public SQLWarning getWarnings() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void clearWarnings() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return new StubPreparedStatement(this);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Map<String, Class<?>> getTypeMap() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setTypeMap(Map<String, Class<?>> map) throws SQLException\n   {\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setHoldability(int holdability) throws SQLException\n   {\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getHoldability() throws SQLException\n   {\n      return (int) foo;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Savepoint setSavepoint() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Savepoint setSavepoint(String name) throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void rollback(Savepoint savepoint) throws SQLException\n   {\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void releaseSavepoint(Savepoint savepoint) throws SQLException\n   {\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return new StubPreparedStatement(this);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return new StubPreparedStatement(this);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return new StubPreparedStatement(this);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return new StubPreparedStatement(this);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Clob createClob() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Blob createBlob() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public NClob createNClob() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public SQLXML createSQLXML() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isValid(int timeout) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      refreshConnectionWaitTimeout();\n      return !isClosed;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setClientInfo(String name, String value) throws SQLClientInfoException\n   {\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setClientInfo(Properties properties) throws SQLClientInfoException\n   {\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public String getClientInfo(String name) throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Properties getClientInfo() throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Array createArrayOf(String typeName, Object[] elements) throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Struct createStruct(String typeName, Object[] attributes) throws SQLException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   public void setSchema(String schema) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      this.schema = schema;\n   }\n\n   /** {@inheritDoc} */\n   public String getSchema() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      return schema;\n   }\n\n   /** {@inheritDoc} */\n   public void abort(Executor executor) throws SQLException\n   {\n      throw new SQLException(\"Intentional exception during abort\");\n   }\n\n   /** {@inheritDoc} */\n   public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n      if (networkTimeoutSetter != null) {\n         try {\n            networkTimeoutSetter.call();\n         }\n         catch (SQLException e) {\n            throw e;\n         }\n         catch (Exception e) {\n            throw new RuntimeException(e);\n         }\n      }\n   }\n\n   /** {@inheritDoc} */\n   public int getNetworkTimeout() throws SQLException\n   {\n      if (throwException) {\n         throw new SQLException();\n      }\n\n      if (oldDriver) {\n         throw new AbstractMethodError();\n      }\n\n      return 0;\n   }\n\n   @Override\n   public void beginRequest() {\n      beginRequestCalled = true;\n   }\n\n   @Override\n   public void endRequest() {\n      endRequestCalled = true;\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/StubDataSource.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.mocks;\n\nimport com.zaxxer.hikari.util.UtilityElf;\n\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.logging.Logger;\n\nimport javax.sql.DataSource;\n\n/**\n *\n * @author Brett Wooldridge\n */\npublic class StubDataSource implements DataSource\n{\n   private String user;\n   private String password;\n   private PrintWriter logWriter;\n   private SQLException throwException;\n   private long connectionAcquisitionTime = 0;\n   private int loginTimeout;\n   private int waitTimeout = 30000;\n\n   public String getUser()\n   {\n      return user;\n   }\n\n   public void setUser(String user)\n   {\n      this.user = user;\n   }\n\n   public String getPassword()\n   {\n      return password;\n   }\n\n   public void setPassword(String password)\n   {\n      this.password = password;\n   }\n\n   public int getWaitTimeout() {\n      return waitTimeout;\n   }\n\n   public void setWaitTimeout(int waitTimeout) {\n      this.waitTimeout = waitTimeout;\n   }\n\n   public void setURL(String url)\n   {\n      // we don't care\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public PrintWriter getLogWriter() throws SQLException\n   {\n      return logWriter;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setLogWriter(PrintWriter out) throws SQLException\n   {\n      this.logWriter = out;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setLoginTimeout(int seconds) throws SQLException\n   {\n      this.loginTimeout = seconds;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getLoginTimeout() throws SQLException\n   {\n      return loginTimeout;\n   }\n\n   /** {@inheritDoc} */\n   public Logger getParentLogger() throws SQLFeatureNotSupportedException\n   {\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @SuppressWarnings(\"unchecked\")\n   @Override\n   public <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      if (iface.isInstance(this)) {\n         return (T) this;\n      }\n\n      throw new SQLException(\"Wrapped DataSource is not an instance of \" + iface);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Connection getConnection() throws SQLException\n   {\n      if (throwException != null) {\n         throw throwException;\n      }\n      if (connectionAcquisitionTime > 0) {\n         UtilityElf.quietlySleep(connectionAcquisitionTime);\n      }\n      return new StubConnection(waitTimeout);\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Connection getConnection(String username, String password) throws SQLException\n   {\n      return new StubConnection(waitTimeout);\n   }\n\n   public void setThrowException(SQLException e)\n   {\n      this.throwException = e;\n   }\n\n   public void setConnectionAcquisitionTime(long connectionAcquisitionTime) {\n      this.connectionAcquisitionTime = connectionAcquisitionTime;\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/StubDriver.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.mocks;\n\nimport java.sql.Connection;\nimport java.sql.Driver;\nimport java.sql.DriverManager;\nimport java.sql.DriverPropertyInfo;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.Properties;\nimport java.util.logging.Logger;\n\n/**\n *\n * @author Brett Wooldridge\n */\npublic class StubDriver implements Driver\n{\n    private static final Driver driver;\n\n    static\n    {\n        driver = new StubDriver();\n        try\n        {\n            DriverManager.registerDriver(driver);\n        }\n        catch (SQLException e)\n        {\n            e.printStackTrace();\n        }\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Connection connect(String url, Properties info) throws SQLException\n    {\n        return new StubConnection();\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean acceptsURL(String url) throws SQLException\n    {\n        return \"jdbc:stub\".equals(url);\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getMajorVersion()\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getMinorVersion()\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean jdbcCompliant()\n    {\n        return true;\n    }\n\n    /** {@inheritDoc} */\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException\n    {\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/StubPoolStats.java",
    "content": "package com.zaxxer.hikari.mocks;\n\nimport com.zaxxer.hikari.metrics.PoolStats;\n\npublic class StubPoolStats extends PoolStats\n{\n\n   public StubPoolStats(long timeoutMs)\n   {\n      super(timeoutMs);\n   }\n\n   @Override\n   protected void update()\n   {\n      // Do nothing\n   }\n\n\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/StubPreparedStatement.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.mocks;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.Date;\nimport java.sql.NClob;\nimport java.sql.ParameterMetaData;\nimport java.sql.PreparedStatement;\nimport java.sql.Ref;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.RowId;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Time;\nimport java.sql.Timestamp;\nimport java.util.Calendar;\n\n/**\n *\n * @author Brett Wooldridge\n */\n@SuppressWarnings(\"RedundantThrows\")\npublic class StubPreparedStatement extends StubStatement implements PreparedStatement\n{\n    StubPreparedStatement(Connection connection)\n    {\n        super(connection);\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public ResultSet executeQuery(String sql) throws SQLException\n    {\n        return new StubResultSet();\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int executeUpdate(String sql) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getMaxFieldSize() throws SQLException\n    {\n        throw new SQLException(\"Simulated disconnection error\", \"08999\");\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setMaxFieldSize(int max) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getMaxRows() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setMaxRows(int max) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setEscapeProcessing(boolean enable) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getQueryTimeout() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setQueryTimeout(int seconds) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void cancel() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public SQLWarning getWarnings() throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void clearWarnings() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setCursorName(String name) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean execute(String sql) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public ResultSet getResultSet() throws SQLException\n    {\n        return new StubResultSet();\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getUpdateCount() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean getMoreResults() throws SQLException\n    {\n        if (isClosed())\n        {\n            throw new SQLException(\"Connection is closed\");\n        }\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setFetchDirection(int direction) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getFetchDirection() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setFetchSize(int rows) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getFetchSize() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getResultSetConcurrency() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getResultSetType() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void addBatch(String sql) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void clearBatch() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int[] executeBatch() throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean getMoreResults(int current) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public ResultSet getGeneratedKeys() throws SQLException\n    {\n        return new StubResultSet();\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int executeUpdate(String sql, int[] columnIndexes) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int executeUpdate(String sql, String[] columnNames) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean execute(String sql, int autoGeneratedKeys) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean execute(String sql, int[] columnIndexes) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean execute(String sql, String[] columnNames) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getResultSetHoldability() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setPoolable(boolean poolable) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isPoolable() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void closeOnCompletion() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isCloseOnCompletion() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException\n    {\n       if (iface.isInstance(this)) {\n          return (T) this;\n       }\n\n       throw new SQLException(\"Wrapped connection is not an instance of \" + iface);\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public ResultSet executeQuery() throws SQLException\n    {\n        return new StubResultSet();\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int executeUpdate() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setNull(int parameterIndex, int sqlType) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBoolean(int parameterIndex, boolean x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setByte(int parameterIndex, byte x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setShort(int parameterIndex, short x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setInt(int parameterIndex, int x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setLong(int parameterIndex, long x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setFloat(int parameterIndex, float x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setDouble(int parameterIndex, double x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setString(int parameterIndex, String x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBytes(int parameterIndex, byte[] x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setDate(int parameterIndex, Date x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setTime(int parameterIndex, Time x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void clearParameters() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setObject(int parameterIndex, Object x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean execute() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void addBatch() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setRef(int parameterIndex, Ref x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBlob(int parameterIndex, Blob x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setClob(int parameterIndex, Clob x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setArray(int parameterIndex, Array x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setURL(int parameterIndex, URL x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public ParameterMetaData getParameterMetaData() throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setRowId(int parameterIndex, RowId x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setNString(int parameterIndex, String value) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setNClob(int parameterIndex, NClob value) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setClob(int parameterIndex, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setClob(int parameterIndex, Reader reader) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setNClob(int parameterIndex, Reader reader) throws SQLException\n    {\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/StubResultSet.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.mocks;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.Date;\nimport java.sql.NClob;\nimport java.sql.Ref;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.RowId;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Statement;\nimport java.sql.Time;\nimport java.sql.Timestamp;\nimport java.util.Calendar;\nimport java.util.Map;\n\n/**\n *\n * @author Brett Wooldridge\n */\n@SuppressWarnings(\"RedundantThrows\")\npublic class StubResultSet implements ResultSet\n{\n    private int counter;\n    private boolean closed;\n\n    /** {@inheritDoc} */\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException\n    {\n\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean next() throws SQLException\n    {\n        return (counter > 100000);\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void close() throws SQLException\n    {\n        closed = true;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean wasNull() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public String getString(int columnIndex) throws SQLException\n    {\n        return \"aString\";\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean getBoolean(int columnIndex) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public byte getByte(int columnIndex) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public short getShort(int columnIndex) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getInt(int columnIndex) throws SQLException\n    {\n        return ++counter;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public long getLong(int columnIndex) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public float getFloat(int columnIndex) throws SQLException\n    {\n        throw new SQLException(\"Simulated disconnection error\", \"08999\");\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public double getDouble(int columnIndex) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public byte[] getBytes(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Date getDate(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Time getTime(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Timestamp getTimestamp(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public InputStream getAsciiStream(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InputStream getUnicodeStream(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public InputStream getBinaryStream(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public String getString(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean getBoolean(String columnLabel) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public byte getByte(String columnLabel) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public short getShort(String columnLabel) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getInt(String columnLabel) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public long getLong(String columnLabel) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public float getFloat(String columnLabel) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public double getDouble(String columnLabel) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public byte[] getBytes(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Date getDate(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Time getTime(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Timestamp getTimestamp(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public InputStream getAsciiStream(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    @SuppressWarnings(\"deprecation\")\n    public InputStream getUnicodeStream(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public InputStream getBinaryStream(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public SQLWarning getWarnings() throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void clearWarnings() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public String getCursorName() throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Object getObject(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Object getObject(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int findColumn(String columnLabel) throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Reader getCharacterStream(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Reader getCharacterStream(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public BigDecimal getBigDecimal(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public BigDecimal getBigDecimal(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isBeforeFirst() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isAfterLast() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isFirst() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isLast() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void beforeFirst() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void afterLast() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean first() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean last() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getRow() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean absolute(int row) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean relative(int rows) throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean previous() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setFetchDirection(int direction) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getFetchDirection() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void setFetchSize(int rows) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getFetchSize() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getType() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getConcurrency() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean rowUpdated() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean rowInserted() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean rowDeleted() throws SQLException\n    {\n        return false;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNull(int columnIndex) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBoolean(int columnIndex, boolean x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateByte(int columnIndex, byte x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateShort(int columnIndex, short x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateInt(int columnIndex, int x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateLong(int columnIndex, long x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateFloat(int columnIndex, float x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateDouble(int columnIndex, double x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateString(int columnIndex, String x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBytes(int columnIndex, byte[] x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateDate(int columnIndex, Date x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateTime(int columnIndex, Time x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateObject(int columnIndex, Object x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNull(String columnLabel) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBoolean(String columnLabel, boolean x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateByte(String columnLabel, byte x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateShort(String columnLabel, short x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateInt(String columnLabel, int x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateLong(String columnLabel, long x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateFloat(String columnLabel, float x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateDouble(String columnLabel, double x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateString(String columnLabel, String x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBytes(String columnLabel, byte[] x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateDate(String columnLabel, Date x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateTime(String columnLabel, Time x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateObject(String columnLabel, Object x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void insertRow() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateRow() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void deleteRow() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void refreshRow() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void cancelRowUpdates() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void moveToInsertRow() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void moveToCurrentRow() throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Statement getStatement() throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Ref getRef(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Blob getBlob(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Clob getClob(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Array getArray(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Ref getRef(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Blob getBlob(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Clob getClob(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Array getArray(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Date getDate(int columnIndex, Calendar cal) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Date getDate(String columnLabel, Calendar cal) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Time getTime(int columnIndex, Calendar cal) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Time getTime(String columnLabel, Calendar cal) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public URL getURL(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public URL getURL(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateRef(int columnIndex, Ref x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateRef(String columnLabel, Ref x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBlob(int columnIndex, Blob x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBlob(String columnLabel, Blob x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateClob(int columnIndex, Clob x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateClob(String columnLabel, Clob x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateArray(int columnIndex, Array x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateArray(String columnLabel, Array x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public RowId getRowId(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public RowId getRowId(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateRowId(int columnIndex, RowId x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateRowId(String columnLabel, RowId x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public int getHoldability() throws SQLException\n    {\n        return 0;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public boolean isClosed() throws SQLException\n    {\n        return closed;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNString(int columnIndex, String nString) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNString(String columnLabel, String nString) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNClob(int columnIndex, NClob nClob) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNClob(String columnLabel, NClob nClob) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public NClob getNClob(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public NClob getNClob(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public SQLXML getSQLXML(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public SQLXML getSQLXML(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public String getNString(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public String getNString(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Reader getNCharacterStream(int columnIndex) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public Reader getNCharacterStream(String columnLabel) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateClob(int columnIndex, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateClob(String columnLabel, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateClob(int columnIndex, Reader reader) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateClob(String columnLabel, Reader reader) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNClob(int columnIndex, Reader reader) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    @Override\n    public void updateNClob(String columnLabel, Reader reader) throws SQLException\n    {\n    }\n\n    /** {@inheritDoc} */\n    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException\n    {\n        return null;\n    }\n\n    /** {@inheritDoc} */\n    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException\n    {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/StubStatement.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.mocks;\n\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.sql.SQLWarning;\nimport java.sql.Statement;\n\n/**\n *\n * @author Brett Wooldridge\n */\npublic class StubStatement implements Statement\n{\n   public static volatile boolean oldDriver;\n\n   private static volatile long simulatedQueryTime;\n   private boolean closed;\n   private Connection connection;\n\n   public StubStatement(Connection connection) {\n      this.connection = connection;\n   }\n\n   public static void setSimulatedQueryTime(long time) {\n      simulatedQueryTime = time;\n   }\n\n   /** {@inheritDoc} */\n   @SuppressWarnings(\"unchecked\")\n   @Override\n   public <T> T unwrap(Class<T> iface) throws SQLException\n   {\n      checkClosed();\n      return (T) this;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isWrapperFor(Class<?> iface) throws SQLException\n   {\n      checkClosed();\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ResultSet executeQuery(String sql) throws SQLException\n   {\n      checkClosed();\n      StubResultSet resultSet = new StubResultSet();\n      connection.commit();\n      return resultSet;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate(String sql) throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void close() throws SQLException\n   {\n      closed = true;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getMaxFieldSize() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setMaxFieldSize(int max) throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getMaxRows() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setMaxRows(int max) throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setEscapeProcessing(boolean enable) throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getQueryTimeout() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setQueryTimeout(int seconds) throws SQLException\n   {\n      if (oldDriver) {\n         throw new SQLFeatureNotSupportedException();\n      }\n\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void cancel() throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public SQLWarning getWarnings() throws SQLException\n   {\n      checkClosed();\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void clearWarnings() throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setCursorName(String name) throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute(String sql) throws SQLException\n   {\n      checkClosed();\n      if (simulatedQueryTime > 0) {\n         quietlySleep(simulatedQueryTime);\n      }\n      connection.commit();\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ResultSet getResultSet() throws SQLException\n   {\n      checkClosed();\n      return new StubResultSet();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getUpdateCount() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean getMoreResults() throws SQLException\n   {\n      checkClosed();\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setFetchDirection(int direction) throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getFetchDirection() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setFetchSize(int rows) throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getFetchSize() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getResultSetConcurrency() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getResultSetType() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void addBatch(String sql) throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void clearBatch() throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int[] executeBatch() throws SQLException\n   {\n      checkClosed();\n      return null;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public Connection getConnection() throws SQLException\n   {\n      checkClosed();\n      return connection;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean getMoreResults(int current) throws SQLException\n   {\n      checkClosed();\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public ResultSet getGeneratedKeys() throws SQLException\n   {\n      checkClosed();\n      return new StubResultSet();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate(String sql, int[] columnIndexes) throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int executeUpdate(String sql, String[] columnNames) throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute(String sql, int autoGeneratedKeys) throws SQLException\n   {\n      checkClosed();\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute(String sql, int[] columnIndexes) throws SQLException\n   {\n      checkClosed();\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean execute(String sql, String[] columnNames) throws SQLException\n   {\n      checkClosed();\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public int getResultSetHoldability() throws SQLException\n   {\n      checkClosed();\n      return 0;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isClosed() throws SQLException\n   {\n      return closed;\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public void setPoolable(boolean poolable) throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   @Override\n   public boolean isPoolable() throws SQLException\n   {\n      checkClosed();\n      return false;\n   }\n\n   /** {@inheritDoc} */\n   public void closeOnCompletion() throws SQLException\n   {\n      checkClosed();\n   }\n\n   /** {@inheritDoc} */\n   public boolean isCloseOnCompletion() throws SQLException\n   {\n      checkClosed();\n      return false;\n   }\n\n   private void checkClosed() throws SQLException\n   {\n      if (closed) {\n         throw new SQLException(\"Statement is closed\");\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/mocks/TestObject.java",
    "content": "package com.zaxxer.hikari.mocks;\n\npublic class TestObject\n{\n   private TestObject testObject;\n   private String string;\n   private short shortRaw;\n   private char[] charArray;\n   private String[] stringArray;\n   private int[] intArray;\n\n   public void setTestObject(TestObject testObject)\n   {\n      this.testObject = testObject;\n   }\n\n   public void setString(String string)\n   {\n      this.string = string;\n   }\n\n   public TestObject getTestObject()\n   {\n      return testObject;\n   }\n\n   public String getString()\n   {\n      return string;\n   }\n\n   public short getShortRaw() {\n      return shortRaw;\n   }\n\n   public void setShortRaw(short shortRaw) {\n      this.shortRaw = shortRaw;\n   }\n\n   public void setCharArray(char[] charArray)\n   {\n      this.charArray = charArray;\n   }\n\n   public char[] getCharArray()\n   {\n      return charArray;\n   }\n\n   public void setStringArray(String[] stringArray)\n   {\n      this.stringArray = stringArray;\n   }\n\n   public String[] getStringArray()\n   {\n      return stringArray;\n   }\n\n   public void setIntArray(int[] intArray)\n   {\n      this.intArray = intArray;\n   }\n\n   public int[] getIntArray()\n   {\n      return intArray;\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/osgi/OSGiBundleTest.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.osgi;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runner.manipulation.Filter;\nimport org.junit.runner.manipulation.NoTestsRemainException;\nimport org.junit.runner.notification.RunNotifier;\nimport org.junit.runners.model.InitializationError;\nimport org.ops4j.pax.exam.Configuration;\nimport org.ops4j.pax.exam.Option;\nimport org.ops4j.pax.exam.junit.PaxExam;\nimport org.osgi.framework.Bundle;\nimport org.osgi.framework.BundleContext;\n\nimport javax.inject.Inject;\nimport java.io.File;\n\nimport static com.zaxxer.hikari.pool.TestElf.isJava11;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.ops4j.pax.exam.CoreOptions.*;\n\n/**\n * @author lburgazzoli\n */\n@RunWith(OSGiBundleTest.ConditionalPaxExam.class)\npublic class OSGiBundleTest\n{\n   @Test\n   public void checkInject()\n   {\n      assertNotNull(context);\n   }\n\n   @Test\n   public void checkBundle()\n   {\n      Boolean bundleFound = false;\n      Boolean bundleActive = false;\n\n      Bundle[] bundles = context.getBundles();\n      for (Bundle bundle : bundles) {\n         if (bundle != null) {\n            if (bundle.getSymbolicName().equals(\"com.zaxxer.HikariCP\")) {\n               bundleFound = true;\n               if (bundle.getState() == Bundle.ACTIVE) {\n                  bundleActive = true;\n               }\n            }\n         }\n      }\n\n      assertTrue(bundleFound);\n      assertTrue(bundleActive);\n   }\n\n   @Inject\n   BundleContext context;\n\n   @Configuration\n   public Option[] config()\n   {\n      return options(\n         systemProperty(\"org.osgi.framework.storage.clean\").value(\"true\"),\n         systemProperty(\"org.ops4j.pax.logging.DefaultServiceLog.level\").value(\"WARN\"),\n         mavenBundle(\"org.slf4j\", \"slf4j-api\", \"1.7.36\"),\n         mavenBundle(\"org.slf4j\", \"slf4j-simple\", \"1.7.36\").noStart(),\n         new File(\"target/classes\").exists()\n            ? bundle(\"reference:file:target/classes\")\n            : bundle(\"reference:file:../target/classes\"),\n         junitBundles(),\n         cleanCaches()\n      );\n   }\n\n   public static class ConditionalPaxExam extends PaxExam\n   {\n      public ConditionalPaxExam(Class<?> klass) throws InitializationError {\n         super(klass);\n      }\n\n      @Override\n      public void run(RunNotifier notifier) {\n         if (!isJava11()) {\n            super.run(notifier);\n         }\n      }\n\n      @Override\n      public void filter(Filter filter) throws NoTestsRemainException {\n         if (isJava11()) {\n            throw new NoTestsRemainException();\n         }\n\n         super.filter(filter);\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/CodahaleMetricsTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.SortedMap;\nimport java.util.concurrent.TimeUnit;\n\nimport com.codahale.metrics.Histogram;\nimport com.codahale.metrics.Metric;\nimport com.codahale.metrics.MetricFilter;\nimport com.codahale.metrics.MetricRegistry;\nimport com.codahale.metrics.Timer;\nimport com.codahale.metrics.health.HealthCheck;\nimport com.codahale.metrics.health.HealthCheckRegistry;\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory;\nimport com.zaxxer.hikari.util.UtilityElf;\nimport org.junit.Test;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariDataSource;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\nimport static org.junit.Assume.assumeFalse;\n\n/**\n * Test HikariCP/CodaHale metrics integration.\n *\n * @author Brett Wooldridge\n */\npublic class CodahaleMetricsTest extends TestMetricsBase<MetricRegistry>\n{\n   @Override\n   protected MetricsTrackerFactory metricsTrackerFactory(final MetricRegistry metricRegistry)\n   {\n      return new CodahaleMetricsTrackerFactory(metricRegistry);\n   }\n\n   @Override\n   protected MetricRegistry metricRegistry()\n   {\n      return new MetricRegistry();\n   }\n\n   @Test\n   public void testHealthChecks() throws Exception\n   {\n      MetricRegistry metricRegistry = metricRegistry();\n      HealthCheckRegistry healthRegistry = new HealthCheckRegistry();\n\n      HikariConfig config = newHikariConfig();\n      config.setMaximumPoolSize(10);\n      config.setMetricRegistry(metricRegistry);\n      config.setHealthCheckRegistry(healthRegistry);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.addHealthCheckProperty(\"connectivityCheckTimeoutMs\", \"1000\");\n      config.addHealthCheckProperty(\"expected99thPercentileMs\", \"100\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         quietlySleep(TimeUnit.SECONDS.toMillis(2));\n\n         try (Connection connection = ds.getConnection()) {\n            // close immediately\n         }\n\n         try (Connection connection = ds.getConnection()) {\n            // close immediately\n         }\n\n         SortedMap<String, HealthCheck.Result> healthChecks = healthRegistry.runHealthChecks();\n\n         HealthCheck.Result connectivityResult = healthChecks.get(\"testHealthChecks.pool.ConnectivityCheck\");\n         assertTrue(connectivityResult.isHealthy());\n\n         HealthCheck.Result slaResult = healthChecks.get(\"testHealthChecks.pool.Connection99Percent\");\n         assertTrue(slaResult.isHealthy());\n      }\n   }\n\n   @Test\n   public void testSetters1() throws Exception\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         MetricRegistry metricRegistry = metricRegistry();\n         HealthCheckRegistry healthRegistry = new HealthCheckRegistry();\n\n         try {\n            try (Connection connection = ds.getConnection()) {\n               // close immediately\n            }\n\n            // After the pool as started, we can only set them once...\n            ds.setMetricRegistry(metricRegistry);\n            ds.setHealthCheckRegistry(healthRegistry);\n\n            // and never again...\n            ds.setMetricRegistry(metricRegistry);\n            fail(\"Should not have been allowed to set registry after pool started\");\n         }\n         catch (IllegalStateException ise) {\n            // pass\n            try {\n               ds.setHealthCheckRegistry(healthRegistry);\n               fail(\"Should not have been allowed to set registry after pool started\");\n            }\n            catch (IllegalStateException ise2) {\n               // pass\n            }\n         }\n      }\n   }\n\n   @Test\n   public void testSetters2() throws Exception\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         MetricRegistry metricRegistry = metricRegistry();\n         HealthCheckRegistry healthRegistry = new HealthCheckRegistry();\n\n         ds.setMetricRegistry(metricRegistry);\n         ds.setHealthCheckRegistry(healthRegistry);\n\n         // before the pool is started, we can set it any number of times...\n         ds.setMetricRegistry(metricRegistry);\n         ds.setHealthCheckRegistry(healthRegistry);\n\n         try (Connection connection = ds.getConnection()) {\n\n            // after the pool is started, we cannot set it any more\n            ds.setMetricRegistry(metricRegistry);\n            fail(\"Should not have been allowed to set registry after pool started\");\n         }\n         catch (IllegalStateException ise) {\n            // pass\n         }\n      }\n   }\n\n   @Test\n   public void testMetricWait() throws SQLException\n   {\n      MetricRegistry metricRegistry = new MetricRegistry();\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setMetricRegistry(metricRegistry);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         ds.getConnection().close();\n\n         Timer timer = metricRegistry.getTimers(new MetricFilter() {\n            /** {@inheritDoc} */\n            @Override\n            public boolean matches(String name, Metric metric)\n            {\n               return name.equals(MetricRegistry.name(\"testMetricWait\", \"pool\", \"Wait\"));\n            }\n         }).values().iterator().next();\n\n         assertEquals(1, timer.getCount());\n         assertTrue(timer.getMeanRate() > 0.0);\n      }\n   }\n\n   @Test\n   public void testMetricUsage() throws SQLException\n   {\n      assumeFalse(System.getProperty(\"os.name\").contains(\"Windows\"));\n      MetricRegistry metricRegistry = new MetricRegistry();\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setMetricRegistry(metricRegistry);\n      config.setInitializationFailTimeout(0);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         try (Connection connection = ds.getConnection()) {\n            UtilityElf.quietlySleep(250L);\n         }\n\n         Histogram histo = metricRegistry.getHistograms(new MetricFilter() {\n            /** {@inheritDoc} */\n            @Override\n            public boolean matches(String name, Metric metric)\n            {\n               return name.equals(MetricRegistry.name(\"testMetricUsage\", \"pool\", \"Usage\"));\n            }\n         }).values().iterator().next();\n\n         assertEquals(1, histo.getCount());\n         double seventyFifth = histo.getSnapshot().get75thPercentile();\n         assertTrue(\"Seventy-fith percentile less than 250ms: \" + seventyFifth, seventyFifth >= 250.0);\n      }\n   }\n\n   @Test\n   public void testMetricRegistrySubclassIsAllowed()\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         ds.setMetricRegistry(new MetricRegistry() {\n            @Override\n            public Timer timer(String name) {\n               return super.timer(name);\n            }\n         });\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/ConcurrentCloseConnectionTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\n\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\n\n/**\n * @author Matthew Tambara (matthew.tambara@liferay.com)\n */\npublic class ConcurrentCloseConnectionTest\n{\n   @Test\n   public void testConcurrentClose() throws Exception\n   {\n\t  HikariConfig config = newHikariConfig();\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n\t  try (HikariDataSource ds = new HikariDataSource(config);\n\t      final Connection connection = ds.getConnection()) {\n\n\t\t  ExecutorService executorService = Executors.newFixedThreadPool(10);\n\n\t\t  List<Future<?>> futures = new ArrayList<>();\n\n\t\t  for (int i = 0; i < 500; i++) {\n\t\t\t  final PreparedStatement preparedStatement =\n\t\t\t\t  connection.prepareStatement(\"\");\n\n\t\t\t  futures.add(executorService.submit(new Callable<Void>() {\n\n\t\t\t\t  @Override\n\t\t\t\t  public Void call() throws Exception {\n\t\t\t\t\t  preparedStatement.close();\n\n\t\t\t\t\t  return null;\n\t\t\t\t  }\n\n\t\t\t  }));\n\t\t  }\n\n\t\t  executorService.shutdown();\n\n\t\t  for (Future<?> future : futures) {\n\t\t\t  future.get();\n\t\t  }\n\t  }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/ConnectionPoolSizeVsThreadsTest.java",
    "content": "/*\n * Copyright (C) 2013, 2017 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\nimport static com.zaxxer.hikari.util.ClockSource.elapsedMillis;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static java.util.concurrent.Executors.newFixedThreadPool;\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubDataSource;\n\n/**\n * @author Matthew Tambara (matthew.tambara@liferay.com)\n */\npublic class ConnectionPoolSizeVsThreadsTest {\n\n   private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionPoolSizeVsThreadsTest.class);\n\n   private static final int ITERATIONS = 50_000;\n\n   @Test\n   public void testPoolSizeAboutSameSizeAsThreadCount() throws Exception {\n      final int threadCount = 50;\n      final Counts counts = testPoolSize(2 /*minIdle*/,\n                                         100 /*maxPoolSize*/,\n                                         threadCount,\n                                         1 /*workTimeMs*/,\n                                         0 /*restTimeMs*/,\n                                         20 /*connectionAcquisitionTimeMs*/,\n                                         ITERATIONS,\n                                         SECONDS.toMillis(2) /*postTestTimeMs*/);\n\n      // maxActive may never make it to threadCount but it shouldn't be any higher\n      assertEquals(threadCount, counts.maxActive, 15 /*delta*/);\n      assertEquals(threadCount, counts.maxTotal,  5 /*delta*/);\n   }\n\n   @Test\n   public void testSlowConnectionTimeBurstyWork() throws Exception {\n      // setup a bursty work load, 50 threads all needing to do around 100 units of work.\n      // Using a more realistic time for connection startup of 250 ms and only 5 seconds worth of work will mean that we end up finishing\n      // all of the work before we actually have setup 50 connections even though we have requested 50 connections\n      final int threadCount = 50;\n      final int workItems = threadCount * 100;\n      final int workTimeMs = 0;\n      final int connectionAcquisitionTimeMs = 250;\n      final Counts counts = testPoolSize(2 /*minIdle*/,\n                                         100 /*maxPoolSize*/,\n                                         threadCount,\n                                         workTimeMs,\n                                         0 /*restTimeMs*/,\n                                         connectionAcquisitionTimeMs,\n                                         workItems /*iterations*/,\n                                         SECONDS.toMillis(3) /*postTestTimeMs*/);\n\n      // hard to put exact bounds on how many thread we will use but we can put an upper bound on usage (if there was only one thread)\n      final long totalWorkTime = workItems * workTimeMs;\n      final long connectionMax = totalWorkTime / connectionAcquisitionTimeMs;\n      assertTrue(connectionMax <= counts.maxActive);\n      assertEquals(connectionMax, counts.maxTotal, 2 + 2 /*delta*/);\n   }\n\n   private Counts testPoolSize(final int minIdle, final int maxPoolSize, final int threadCount,\n                               final long workTimeMs, final long restTimeMs, final long connectionAcquisitionTimeMs,\n                               final int iterations, final long postTestTimeMs) throws Exception {\n\n      LOGGER.info(\"Starting test (minIdle={}, maxPoolSize={}, threadCount={}, workTimeMs={}, restTimeMs={}, connectionAcquisitionTimeMs={}, iterations={}, postTestTimeMs={})\",\n                  minIdle, maxPoolSize, threadCount, workTimeMs, restTimeMs, connectionAcquisitionTimeMs, iterations, postTestTimeMs);\n\n      final HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(minIdle);\n      config.setMaximumPoolSize(maxPoolSize);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setConnectionTimeout(2500);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      final AtomicReference<Exception> ref = new AtomicReference<>(null);\n\n      // Initialize HikariPool with no initial connections and room to grow\n      try (final HikariDataSource ds = new HikariDataSource(config)) {\n         final StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);\n         // connection acquisition takes more than 0 ms in a real system\n         stubDataSource.setConnectionAcquisitionTime(connectionAcquisitionTimeMs);\n\n         final ExecutorService threadPool = newFixedThreadPool(threadCount);\n         final CountDownLatch allThreadsDone = new CountDownLatch(iterations);\n         for (int i = 0; i < iterations; i++) {\n            threadPool.submit(() -> {\n               if (ref.get() == null) {\n                  quietlySleep(restTimeMs);\n                  try (Connection c2 = ds.getConnection()) {\n                     quietlySleep(workTimeMs);\n                  }\n                  catch (Exception e) {\n                     ref.set(e);\n                  }\n               }\n               allThreadsDone.countDown();\n            });\n         }\n\n         final HikariPool pool = getPool(ds);\n\n         // collect pool usage data while work is still being done\n         final Counts underLoad = new Counts();\n         while (allThreadsDone.getCount() > 0 || pool.getTotalConnections() < minIdle) {\n            quietlySleep(50);\n            underLoad.updateMaxCounts(pool);\n         }\n\n         // wait for long enough any pending acquisitions have already been done\n         LOGGER.info(\"Test Over, waiting for post delay time {}ms \", postTestTimeMs);\n         quietlySleep(connectionAcquisitionTimeMs + workTimeMs + restTimeMs);\n\n         // collect pool data while there is no work to do.\n         final Counts postLoad = new Counts();\n         final long start = currentTime();\n         while (elapsedMillis(start) < postTestTimeMs) {\n            quietlySleep(50);\n            postLoad.updateMaxCounts(pool);\n         }\n\n         allThreadsDone.await();\n\n         threadPool.shutdown();\n         threadPool.awaitTermination(30, SECONDS);\n\n         if (ref.get() != null) {\n            LOGGER.error(\"Task failed\", ref.get());\n            fail(\"Task failed\");\n         }\n\n         LOGGER.info(\"Under Load... {}\", underLoad);\n         LOGGER.info(\"Post Load.... {}\", postLoad);\n\n         // verify that the no connections created after the work has stopped\n         if (postTestTimeMs > 0) {\n            if (postLoad.maxActive != 0) {\n               fail(\"Max Active was greater than 0 after test was done\");\n            }\n\n            final int createdAfterWorkAllFinished = postLoad.maxTotal - underLoad.maxTotal;\n            assertEquals(\"Connections were created when there was no waiting consumers\", 0, createdAfterWorkAllFinished, 1 /*delta*/);\n         }\n\n         return underLoad;\n      }\n   }\n\n   private static class Counts {\n      int maxTotal = 0;\n      int maxActive = 0;\n\n      void updateMaxCounts(final HikariPool pool) {\n         maxTotal = Math.max(pool.getTotalConnections(), maxTotal);\n         maxActive = Math.max(pool.getActiveConnections(), maxActive);\n      }\n\n      @Override\n      public String toString() {\n         return \"Counts{\" +\n            \"maxTotal=\" + maxTotal +\n            \", maxActive=\" + maxActive +\n            '}';\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/ConnectionRaceConditionTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jLogLevel;\nimport static org.junit.Assert.fail;\n\nimport java.sql.Connection;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.apache.logging.log4j.Level;\nimport org.junit.After;\nimport org.junit.Test;\nimport org.slf4j.LoggerFactory;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.util.ConcurrentBag;\n\n/**\n * @author Matthew Tambara (matthew.tambara@liferay.com)\n */\npublic class ConnectionRaceConditionTest\n{\n\n   public static final int ITERATIONS = 10_000;\n\n   @Test\n   public void testRaceCondition() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(10);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setConnectionTimeout(5000);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      setSlf4jLogLevel(ConcurrentBag.class, Level.INFO);\n\n      final AtomicReference<Exception> ref = new AtomicReference<>(null);\n\n      // Initialize HikariPool with no initial connections and room to grow\n      try (final HikariDataSource ds = new HikariDataSource(config)) {\n         ExecutorService threadPool = Executors.newFixedThreadPool(2);\n         for (int i = 0; i < ITERATIONS; i++) {\n            threadPool.submit(new Callable<Exception>() {\n               /** {@inheritDoc} */\n               @Override\n               public Exception call() throws Exception\n               {\n                  if (ref.get() == null) {\n                     Connection c2;\n                     try {\n                        c2 = ds.getConnection();\n                        ds.evictConnection(c2);\n                     }\n                     catch (Exception e) {\n                        ref.set(e);\n                     }\n                  }\n                  return null;\n               }\n            });\n         }\n\n         threadPool.shutdown();\n         threadPool.awaitTermination(30, TimeUnit.SECONDS);\n\n         if (ref.get() != null) {\n            LoggerFactory.getLogger(ConnectionRaceConditionTest.class).error(\"Task failed\", ref.get());\n            fail(\"Task failed\");\n         }\n      }\n      catch (Exception e) {\n         throw e;\n      }\n   }\n\n   @After\n   public void after()\n   {\n      System.getProperties().remove(\"com.zaxxer.hikari.housekeeping.periodMs\");\n\n      setSlf4jLogLevel(HikariPool.class, Level.WARN);\n      setSlf4jLogLevel(ConcurrentBag.class, Level.WARN);\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/ConnectionStateTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariDataSource;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.assertFalse;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.util.UtilityElf;\n\npublic class ConnectionStateTest\n{\n   @Test\n   public void testAutoCommit() throws SQLException\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setAutoCommit(true);\n         ds.setMinimumIdle(1);\n         ds.setMaximumPoolSize(1);\n         ds.setConnectionTestQuery(\"VALUES 1\");\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n         ds.addDataSourceProperty(\"user\", \"bar\");\n         ds.addDataSourceProperty(\"password\", \"secret\");\n         ds.addDataSourceProperty(\"url\", \"baf\");\n         ds.addDataSourceProperty(\"loginTimeout\", \"10\");\n\n         try (Connection connection = ds.getConnection()) {\n            Connection unwrap = connection.unwrap(Connection.class);\n            connection.setAutoCommit(false);\n            connection.close();\n\n            assertTrue(unwrap.getAutoCommit());\n         }\n      }\n   }\n\n   @Test\n   public void testTransactionIsolation() throws SQLException\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setTransactionIsolation(\"TRANSACTION_READ_COMMITTED\");\n         ds.setMinimumIdle(1);\n         ds.setMaximumPoolSize(1);\n         ds.setConnectionTestQuery(\"VALUES 1\");\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         try (Connection connection = ds.getConnection()) {\n            Connection unwrap = connection.unwrap(Connection.class);\n            connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);\n            connection.close();\n\n            assertEquals(Connection.TRANSACTION_READ_COMMITTED, unwrap.getTransactionIsolation());\n         }\n      }\n   }\n\n   @Test\n   public void testIsolation() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setTransactionIsolation(\"TRANSACTION_REPEATABLE_READ\");\n      config.validate();\n\n      int transactionIsolation = UtilityElf.getTransactionIsolation(config.getTransactionIsolation());\n      assertSame(Connection.TRANSACTION_REPEATABLE_READ, transactionIsolation);\n   }\n\n   @Test\n   public void testReadOnly() throws Exception\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setCatalog(\"test\");\n         ds.setMinimumIdle(1);\n         ds.setMaximumPoolSize(1);\n         ds.setConnectionTestQuery(\"VALUES 1\");\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         try (Connection connection = ds.getConnection()) {\n            Connection unwrap = connection.unwrap(Connection.class);\n            connection.setReadOnly(true);\n            connection.close();\n\n            assertFalse(unwrap.isReadOnly());\n         }\n      }\n   }\n\n   @Test\n   public void testCatalog() throws SQLException\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setCatalog(\"test\");\n         ds.setMinimumIdle(1);\n         ds.setMaximumPoolSize(1);\n         ds.setConnectionTestQuery(\"VALUES 1\");\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         try (Connection connection = ds.getConnection()) {\n            Connection unwrap = connection.unwrap(Connection.class);\n            connection.setCatalog(\"other\");\n            connection.close();\n\n            assertEquals(\"test\", unwrap.getCatalog());\n         }\n      }\n   }\n\n   @Test\n   public void testCommitTracking() throws SQLException\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setAutoCommit(false);\n         ds.setMinimumIdle(1);\n         ds.setMaximumPoolSize(1);\n         ds.setConnectionTestQuery(\"VALUES 1\");\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         try (Connection connection = ds.getConnection()) {\n            Statement statement = connection.createStatement();\n            statement.execute(\"SELECT something\");\n            assertTrue(TestElf.getConnectionCommitDirtyState(connection));\n\n            connection.commit();\n            assertFalse(TestElf.getConnectionCommitDirtyState(connection));\n\n            statement.execute(\"SELECT something\", Statement.NO_GENERATED_KEYS);\n            assertTrue(TestElf.getConnectionCommitDirtyState(connection));\n\n            connection.rollback();\n            assertFalse(TestElf.getConnectionCommitDirtyState(connection));\n\n            ResultSet resultSet = statement.executeQuery(\"SELECT something\");\n            assertTrue(TestElf.getConnectionCommitDirtyState(connection));\n\n            connection.rollback(null);\n            assertTrue(TestElf.getConnectionCommitDirtyState(connection));\n\n            resultSet.updateRow();\n            assertTrue(TestElf.getConnectionCommitDirtyState(connection));\n\n            connection.setReadOnly(!connection.isReadOnly());\n            assertTrue(TestElf.getConnectionCommitDirtyState(connection));\n         }\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/Dropwizard5MetricsTest.java",
    "content": "package com.zaxxer.hikari.pool;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport com.codahale.metrics.health.HealthCheckRegistry;\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.dropwizard.Dropwizard5MetricsTrackerFactory;\nimport com.zaxxer.hikari.util.UtilityElf;\nimport io.dropwizard.metrics5.Histogram;\nimport io.dropwizard.metrics5.Metric;\nimport io.dropwizard.metrics5.MetricFilter;\nimport io.dropwizard.metrics5.MetricName;\nimport io.dropwizard.metrics5.MetricRegistry;\nimport io.dropwizard.metrics5.Timer;\nimport org.junit.Test;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariDataSource;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\nimport static org.junit.Assume.assumeFalse;\n\n/**\n * Test HikariCP/Dropwizard 5 metrics integration.\n */\npublic class Dropwizard5MetricsTest extends TestMetricsBase<MetricRegistry>\n{\n   @Override\n   protected MetricsTrackerFactory metricsTrackerFactory(final MetricRegistry metricRegistry)\n   {\n      return new Dropwizard5MetricsTrackerFactory(metricRegistry);\n   }\n\n   @Override\n   protected MetricRegistry metricRegistry()\n   {\n      return new MetricRegistry();\n   }\n\n   @Test\n   public void testSetters1() throws Exception\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         MetricRegistry metricRegistry = metricRegistry();\n\n         try {\n            try (Connection connection = ds.getConnection()) {\n               // close immediately\n            }\n\n            // After the pool as started, we can only set it once...\n            ds.setMetricRegistry(metricRegistry);\n\n            // and never again...\n            ds.setMetricRegistry(metricRegistry);\n            fail(\"Should not have been allowed to set registry after pool started\");\n         }\n         catch (IllegalStateException ise) {\n            // pass\n         }\n      }\n   }\n\n   @Test\n   public void testSetters2() throws Exception\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         MetricRegistry metricRegistry = metricRegistry();\n\n         ds.setMetricRegistry(metricRegistry);\n\n         // before the pool is started, we can set it any number of times...\n         ds.setMetricRegistry(metricRegistry);\n\n         try (Connection connection = ds.getConnection()) {\n\n            // after the pool is started, we cannot set it any more\n            ds.setMetricRegistry(metricRegistry);\n            fail(\"Should not have been allowed to set registry after pool started\");\n         }\n         catch (IllegalStateException ise) {\n            // pass\n         }\n      }\n   }\n\n   @Test\n   public void testMetricWait() throws SQLException\n   {\n      MetricRegistry metricRegistry = new MetricRegistry();\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setMetricRegistry(metricRegistry);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         ds.getConnection().close();\n\n         Timer timer = metricRegistry.getTimers(new MetricFilter() {\n            /** {@inheritDoc} */\n            @Override\n            public boolean matches(MetricName name, Metric metric)\n            {\n               return name.equals(MetricRegistry.name(\"testMetricWait\", \"pool\", \"Wait\"));\n            }\n         }).values().iterator().next();\n\n         assertEquals(1, timer.getCount());\n         assertTrue(timer.getMeanRate() > 0.0);\n      }\n   }\n\n   @Test\n   public void testMetricUsage() throws SQLException\n   {\n      assumeFalse(System.getProperty(\"os.name\").contains(\"Windows\"));\n      MetricRegistry metricRegistry = new MetricRegistry();\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setMetricRegistry(metricRegistry);\n      config.setInitializationFailTimeout(0);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         try (Connection connection = ds.getConnection()) {\n            UtilityElf.quietlySleep(250L);\n         }\n\n         Histogram histo = metricRegistry.getHistograms(new MetricFilter() {\n            /** {@inheritDoc} */\n            @Override\n            public boolean matches(MetricName name, Metric metric)\n            {\n               return name.equals(MetricRegistry.name(\"testMetricUsage\", \"pool\", \"Usage\"));\n            }\n         }).values().iterator().next();\n\n         assertEquals(1, histo.getCount());\n         double seventyFifth = histo.getSnapshot().get75thPercentile();\n         assertTrue(\"Seventy-fith percentile less than 250ms: \" + seventyFifth, seventyFifth >= 250.0);\n      }\n   }\n\n   @Test\n   public void testMetricRegistrySubclassIsAllowed()\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         ds.setMetricRegistry(new MetricRegistry() {\n            @Override\n            public Timer timer(String name) {\n               return super.timer(name);\n            }\n         });\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/ExceptionTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\n\npublic class ExceptionTest\n{\n   private HikariDataSource ds;\n\n   private final int CONNECTION_TIMEOUT_SECS = 5;\n   @Before\n   public void setup()\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(2);\n      config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(CONNECTION_TIMEOUT_SECS));\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      ds = new HikariDataSource(config);\n   }\n\n   @After\n   public void teardown()\n   {\n      ds.close();\n   }\n\n   @Test\n   public void testException1() throws SQLException\n   {\n      try (Connection connection = ds.getConnection()) {\n         assertNotNull(connection);\n\n         PreparedStatement statement = connection.prepareStatement(\"SELECT some, thing FROM somewhere WHERE something=?\");\n         assertNotNull(statement);\n\n         ResultSet resultSet = statement.executeQuery();\n         assertNotNull(resultSet);\n\n         try {\n            statement.getMaxFieldSize();\n            fail();\n         }\n         catch (Exception e) {\n            assertSame(SQLException.class, e.getClass());\n         }\n      }\n\n      HikariPool pool = getPool(ds);\n      assertTrue(\"Total (3) connections not as expected\", pool.getTotalConnections() >= 0);\n      assertTrue(\"Idle (3) connections not as expected\", pool.getIdleConnections() >= 0);\n   }\n\n   @Test\n   public void testUseAfterStatementClose() throws SQLException\n   {\n      Connection connection = ds.getConnection();\n      assertNotNull(connection);\n\n      try (Statement statement = connection.prepareStatement(\"SELECT some, thing FROM somewhere WHERE something=?\")) {\n         statement.close();\n         statement.getMoreResults();\n\n         fail();\n      }\n      catch (SQLException e) {\n         assertSame(\"Connection is closed\", e.getMessage());\n      }\n   }\n\n   @Test\n   public void testUseAfterClose() throws SQLException\n   {\n      try (Connection connection = ds.getConnection()) {\n         assertNotNull(connection);\n         connection.close();\n\n         try (Statement statement = connection.prepareStatement(\"SELECT some, thing FROM somewhere WHERE something=?\")) {\n            fail();\n         }\n         catch (SQLException e) {\n            assertSame(\"Connection is closed\", e.getMessage());\n         }\n      }\n   }\n\n   /**\n    * This test verifies that in an isConnectionDead call if an exception is thrown from setNetworkTimeout we will not\n    * call setNetworkTimeout a second time resulting in the exception from second hiding the exception from the first.\n    */\n   @Test\n   public void testLastErrorTimeout() throws Exception\n   {\n      // take one connection so there is only one left.\n      try (Connection ignored1 = ds.getConnection()) {\n         try (Connection ignored = ds.getConnection()) {\n            // no-op\n            assertTrue(true);\n         }\n\n         // force the last access of this connection to be older than 'aliveBypassWindowMs'\n         // thus forcing isConnectionDead to be called (and setNetworkTimeout)\n         Thread.sleep(505);\n\n         AtomicInteger callCount = new AtomicInteger();\n         StubConnection.networkTimeoutSetter = () -> {\n            Thread.sleep(TimeUnit.SECONDS.toMillis(CONNECTION_TIMEOUT_SECS + 1)); // wait longer than the connection timeout\n            throw new SQLException(\"Exception \" + callCount.incrementAndGet());\n         };\n\n         try (Connection ignored = ds.getConnection()) {\n            fail(\"getConnection should have failed\");\n         }\n         catch (SQLException e) {\n            e.printStackTrace();\n            Throwable cause = e.getCause();\n            assertNotNull(cause);\n            Throwable causeCause = e.getCause();\n            assertNotNull(causeCause);\n            assertEquals(\"Exception 1\", causeCause.getMessage());\n         }\n         finally {\n            // Remove the callback so that we don't interfere with any other tests that might run in the same jvm instance.\n            StubConnection.networkTimeoutSetter = null;\n         }\n\n         assertEquals(1, callCount.get());\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/HouseKeeperCleanupTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.junit.Assert.assertEquals;\n\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.util.UtilityElf;\n\n/**\n * @author Martin Stříž (striz@raynet.cz)\n */\npublic class HouseKeeperCleanupTest\n{\n\n   private ScheduledThreadPoolExecutor executor;\n\n   @Before\n   public void before() throws Exception\n   {\n      ThreadFactory threadFactory = new UtilityElf.DefaultThreadFactory(\"global housekeeper\");\n\n      executor = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy());\n      executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);\n      executor.setRemoveOnCancelPolicy(true);\n   }\n\n   @Test\n   public void testHouseKeeperCleanupWithCustomExecutor() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(10);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setConnectionTimeout(2500);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setScheduledExecutor(executor);\n\n      HikariConfig config2 = newHikariConfig();\n      config.copyStateTo(config2);\n\n      try (\n         final HikariDataSource ds1 = new HikariDataSource(config);\n         final HikariDataSource ds2 = new HikariDataSource(config2)\n      ) {\n         assertEquals(\"Scheduled tasks count not as expected, \", 2, executor.getQueue().size());\n      }\n\n      assertEquals(\"Scheduled tasks count not as expected, \", 0, executor.getQueue().size());\n   }\n\n   @After\n   public void after() throws Exception\n   {\n      executor.shutdown();\n      executor.awaitTermination(5, TimeUnit.SECONDS);\n   }\n\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/IsolationTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariDataSource;\nimport static org.junit.Assert.assertNotSame;\nimport static org.junit.Assert.assertSame;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariDataSource;\n\npublic class IsolationTest\n{\n   @Test\n   public void testIsolation() throws SQLException\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMinimumIdle(1);\n         ds.setMaximumPoolSize(1);\n         ds.setIsolateInternalQueries(true);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         try (Connection connection = ds.getConnection()) {\n            connection.close();\n\n            try (Connection connection2 = ds.getConnection()) {\n               connection2.close();\n\n               assertNotSame(connection, connection2);\n               assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));\n            }\n         }\n      }\n   }\n\n   @Test\n   public void testNonIsolation() throws SQLException\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMinimumIdle(1);\n         ds.setMaximumPoolSize(1);\n         ds.setIsolateInternalQueries(false);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         try (Connection connection = ds.getConnection()) {\n            connection.close();\n\n            try (Connection connection2 = ds.getConnection()) {\n               connection2.close();\n\n               assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class));\n            }\n         }\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/JdbcDriverTest.java",
    "content": "/*\n * Copyright (C) 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport org.junit.After;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.util.DriverDataSource;\n\npublic class JdbcDriverTest\n{\n   private HikariDataSource ds;\n\n   @After\n   public void teardown()\n   {\n      if (ds != null) {\n         ds.close();\n      }\n   }\n\n   @Test\n   public void driverTest1() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDriverClassName(\"com.zaxxer.hikari.mocks.StubDriver\");\n      config.setJdbcUrl(\"jdbc:stub\");\n      config.addDataSourceProperty(\"user\", \"bart\");\n      config.addDataSourceProperty(\"password\", \"simpson\");\n\n      ds = new HikariDataSource(config);\n\n      assertTrue(ds.isWrapperFor(DriverDataSource.class));\n\n      DriverDataSource unwrap = ds.unwrap(DriverDataSource.class);\n      assertNotNull(unwrap);\n\n      try (Connection connection = ds.getConnection()) {\n         // test that getConnection() succeeds\n      }\n   }\n\n   @Test\n   public void driverTest2() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDriverClassName(\"com.zaxxer.hikari.mocks.StubDriver\");\n      config.setJdbcUrl(\"jdbc:invalid\");\n\n      try {\n         ds = new HikariDataSource(config);\n      }\n      catch (RuntimeException e) {\n         assertTrue(e.getMessage().contains(\"claims to not accept\"));\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/MetricsTrackerTest.java",
    "content": "package com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.metrics.IMetricsTracker;\nimport com.zaxxer.hikari.mocks.StubDataSource;\nimport org.junit.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLTransientConnectionException;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariDataSource;\nimport static junit.framework.TestCase.fail;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.junit.Assert.assertThrows;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * @author wvuong@chariotsolutions.com on 2/16/17.\n */\npublic class MetricsTrackerTest\n{\n   @Test\n   public void connectionTimeoutIsRecorded() throws Exception\n   {\n      assertThrows(SQLTransientConnectionException.class, () -> {\n         int timeoutMillis = 1000;\n         int timeToCreateNewConnectionMillis = timeoutMillis * 2;\n\n         StubDataSource stubDataSource = new StubDataSource();\n         stubDataSource.setConnectionAcquisitionTime(timeToCreateNewConnectionMillis);\n\n         StubMetricsTracker metricsTracker = new StubMetricsTracker();\n\n         try (HikariDataSource ds = newHikariDataSource()) {\n            ds.setMinimumIdle(0);\n            ds.setMaximumPoolSize(1);\n            ds.setConnectionTimeout(timeoutMillis);\n            ds.setDataSource(stubDataSource);\n            ds.setMetricsTrackerFactory((poolName, poolStats) -> metricsTracker);\n\n            try (Connection c = ds.getConnection()) {\n               fail(\"Connection shouldn't have been successfully created due to configured connection timeout\");\n\n            } finally {\n               // assert that connection timeout was measured\n               assertThat(metricsTracker.connectionTimeoutRecorded, is(true));\n               // assert that measured time to acquire connection should be roughly equal or greater than the configured connection timeout time\n               assertTrue(metricsTracker.connectionAcquiredNanos >= TimeUnit.NANOSECONDS.convert(timeoutMillis, TimeUnit.MILLISECONDS));\n\n               metricsTracker.close();\n            }\n         }\n      });\n   }\n\n   @SuppressWarnings(\"unused\")\n   private static class StubMetricsTracker implements IMetricsTracker\n   {\n      private Long connectionCreatedMillis;\n      private Long connectionAcquiredNanos;\n      private Long connectionBorrowedMillis;\n      private boolean connectionTimeoutRecorded;\n\n      @Override\n      public void recordConnectionCreatedMillis(long connectionCreatedMillis)\n      {\n         this.connectionCreatedMillis = connectionCreatedMillis;\n      }\n\n      @Override\n      public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos)\n      {\n         this.connectionAcquiredNanos = elapsedAcquiredNanos;\n      }\n\n      @Override\n      public void recordConnectionUsageMillis(long elapsedBorrowedMillis)\n      {\n         this.connectionBorrowedMillis = elapsedBorrowedMillis;\n      }\n\n      @Override\n      public void recordConnectionTimeout()\n      {\n         this.connectionTimeoutRecorded = true;\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/MiscTest.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.pool.TestElf.setConfigUnitTest;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jLogLevel;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jTargetStream;\nimport static com.zaxxer.hikari.util.UtilityElf.createInstance;\nimport static com.zaxxer.hikari.util.UtilityElf.getTransactionIsolation;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\n\nimport org.apache.logging.log4j.Level;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\n\n/**\n * @author Brett Wooldridge\n */\npublic class MiscTest\n{\n   @Test\n   public void testLogWriter() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(4);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      setConfigUnitTest(true);\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         PrintWriter writer = new PrintWriter(System.out);\n         ds.setLogWriter(writer);\n         assertSame(writer, ds.getLogWriter());\n         assertEquals(\"testLogWriter\", config.getPoolName());\n      }\n      finally\n      {\n         setConfigUnitTest(false);\n      }\n   }\n\n   @Test\n   public void testInvalidIsolation()\n   {\n      try {\n         getTransactionIsolation(\"INVALID\");\n         fail();\n      }\n      catch (Exception e) {\n         assertTrue(e instanceof IllegalArgumentException);\n      }\n   }\n\n   @Test\n   public void testCreateInstance()\n   {\n      try {\n         createInstance(\"invalid\", null);\n         fail();\n      }\n      catch (RuntimeException e) {\n         assertTrue(e.getCause() instanceof ClassNotFoundException);\n      }\n   }\n\n   @Test\n   public void testLeakDetection() throws Exception\n   {\n      ByteArrayOutputStream baos = new ByteArrayOutputStream();\n      try (PrintStream ps = new PrintStream(baos, true)) {\n         setSlf4jTargetStream(Class.forName(\"com.zaxxer.hikari.pool.ProxyLeakTask\"), ps);\n         setConfigUnitTest(true);\n\n         HikariConfig config = newHikariConfig();\n         config.setMinimumIdle(0);\n         config.setMaximumPoolSize(4);\n         config.setThreadFactory(Executors.defaultThreadFactory());\n         config.setMetricRegistry(null);\n         config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(1));\n         config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         try (HikariDataSource ds = new HikariDataSource(config)) {\n            setSlf4jLogLevel(HikariPool.class, Level.DEBUG);\n            getPool(ds).logPoolState();\n\n            try (Connection connection = ds.getConnection()) {\n               quietlySleep(SECONDS.toMillis(4));\n               connection.close();\n               quietlySleep(SECONDS.toMillis(1));\n               ps.close();\n               String s = new String(baos.toByteArray());\n               assertNotNull(\"Exception string was null\", s);\n               assertTrue(\"Expected exception to contain 'Connection leak detection' but contains *\" + s + \"*\", s.contains(\"Connection leak detection\"));\n            }\n         }\n         finally\n         {\n            setConfigUnitTest(false);\n            setSlf4jLogLevel(HikariPool.class, Level.INFO);\n         }\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/PostgresTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\nimport static com.zaxxer.hikari.util.ClockSource.elapsedMillis;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.junit.Assert.*;\n\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport com.zaxxer.hikari.util.Credentials;\nimport org.junit.After;\nimport org.junit.Before;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport org.junit.Test;\nimport org.testcontainers.containers.PostgreSQLContainer;\nimport org.testcontainers.utility.DockerImageName;\n\npublic class PostgresTest\n{\n   private static final DockerImageName IMAGE_NAME = DockerImageName.parse(\"postgres:16\");\n   private static final String SCHEMA_NAME = \"test\";\n\n   private PostgreSQLContainer<?> postgres;\n\n   @Before\n   public void beforeTest() {\n     postgres = new PostgreSQLContainer<>(IMAGE_NAME).withInitScript(\"postgres_init_script.sql\");\n     postgres.start();\n   }\n\n   @After\n   public void afterTest() {\n     postgres.stop();\n   }\n\n   @Test\n   public void testCase1() throws Exception {\n      HikariConfig config = createConfig(postgres);\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(10);\n      config.setConnectionTimeout(3000);\n      config.setIdleTimeout(SECONDS.toMillis(10));\n      config.setValidationTimeout(SECONDS.toMillis(2));\n\n      exerciseConfig(config, 3);\n   }\n\n   @Test\n   public void testCase2() throws Exception\n   {\n      HikariConfig config = createConfig(postgres);\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(10);\n      config.setConnectionTimeout(1000);\n      config.setIdleTimeout(SECONDS.toMillis(20));\n\n      exerciseConfig(config, 3);\n   }\n\n   @Test\n   public void testCase3() throws Exception\n   {\n      HikariConfig config = createConfig(postgres);\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(10);\n      config.setConnectionTimeout(1000);\n      config.setIdleTimeout(SECONDS.toMillis(20));\n\n      exerciseConfig(config, 3);\n   }\n\n   @Test\n   public void testCase4() throws Exception\n   {\n      HikariConfig config = createConfig(postgres);\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(15);\n      config.setConnectionTimeout(10000);\n      config.setIdleTimeout(2000);\n      config.setMaxLifetime(5);\n      config.setRegisterMbeans(true);\n\n      exerciseConfig(config, 3);\n   }\n\n   @Test\n   public void testPgsqlJdbcUrl()\n   {\n      HikariConfig config = newHikariConfig();\n      config.setJdbcUrl(postgres.getJdbcUrl());\n      config.setUsername(postgres.getUsername());\n      config.setPassword(postgres.getPassword());\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(10);\n      config.setConnectionTimeout(1000);\n      config.setIdleTimeout(SECONDS.toMillis(20));\n\n      exerciseConfig(config, 3);\n   }\n\n   @Test\n   public void testCredentialRotation()\n   {\n      HikariConfig config = createConfig(postgres);\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(10);\n      config.setConnectionTimeout(1000);\n      config.setIdleTimeout(SECONDS.toMillis(20));\n\n      exerciseConfig(config, 3);\n\n      updatePostgresCredentials(\"newuser\", \"newpassword\");\n      config.setJdbcUrl(postgres.getJdbcUrl());\n      config.setCredentials(Credentials.of(\"newuser\", \"newpassword\"));\n\n      exerciseConfig(config, 3);\n   }\n\n   @Test\n   public void testSchema() throws Exception {\n      HikariConfig config = createConfig(postgres);\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setSchema(SCHEMA_NAME);\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         assertTrue(ds.isRunning());\n         try (Connection connection = ds.getConnection()) {\n            // The connection should be using the schema specified in the config\n            assertEquals(SCHEMA_NAME, connection.getSchema());\n            // Explicitly set the schema to an invalid schema\n            connection.setSchema(\"invalid\");\n            // The connection should have a null schema after setting to an invalid schema\n            assertNull(connection.getSchema());\n         }\n         try (Connection connection = ds.getConnection()) {\n            // The connection should be reset to the schema specified in the config\n            assertEquals(SCHEMA_NAME, connection.getSchema());\n         }\n         assertTrue(ds.isRunning());\n      }\n   }\n\n   static private void exerciseConfig(HikariConfig config, int numThreads) {\n      try (final HikariDataSource ds = new HikariDataSource(config)) {\n         assertTrue(ds.isRunning());\n         exerciseDataSource(ds, numThreads);\n         assertTrue(ds.isRunning());\n      }\n   }\n\n   static private void exerciseDataSource(HikariDataSource ds, int numThreads) {\n      final long start = currentTime();\n      List<PostgresWorkerThread> threads = startThreads(ds, numThreads);\n      do {\n         quietlySleep(SECONDS.toMillis(1));\n         assertZeroErrors(threads);\n      } while (elapsedMillis(start) < SECONDS.toMillis(15));\n      stopThreads(threads);\n   }\n\n   static private void assertZeroErrors(List<PostgresWorkerThread> threads) {\n     for (PostgresWorkerThread t : threads) {\n        assertEquals(0, t.getErrorCount());\n     }\n   }\n\n   static List<PostgresWorkerThread> startThreads(HikariDataSource ds, int numThreads) {\n     List<PostgresWorkerThread> threads = new ArrayList<>();\n     for (int i = 0; i < numThreads; i++) {\n        PostgresWorkerThread t = new PostgresWorkerThread(ds);\n        t.start();\n        threads.add(t);\n     }\n     return threads;\n   }\n\n   static void stopThreads(List<PostgresWorkerThread> threads) {\n      for (PostgresWorkerThread t : threads) {\n         t.requestStop();\n      }\n   }\n\n   static class PostgresWorkerThread extends Thread {\n      static private final AtomicInteger id = new AtomicInteger(0);\n      private final HikariDataSource dataSource;\n      private int errorCount = 0;\n      private AtomicBoolean stopRequested = new AtomicBoolean(false);\n\n      public PostgresWorkerThread(HikariDataSource ds) {\n         this.dataSource = ds;\n         this.setName(getClass().getSimpleName() + \"-\" + id.getAndIncrement());\n         this.setDaemon(true);\n      }\n\n      public void requestStop() {\n        stopRequested.set(true);\n         System.err.println(\"[\" + getName() + \"] stopRequested()\");\n      }\n\n      public void run() {\n         System.err.println(\"[\" + getName() + \"] run()\");\n         while (!stopRequested.get()) {\n            try (Connection connection = dataSource.getConnection()) {\n               quietlySleep(5);\n            } catch (Exception e) {\n               e.printStackTrace();\n               errorCount++;\n            }\n         }\n      }\n\n      public int getErrorCount() {\n         return errorCount;\n      }\n   }\n\n   @Before\n   public void before()\n   {\n      System.err.println(\"\\n\");\n   }\n\n   static private HikariConfig createConfig(PostgreSQLContainer<?> postgres) {\n      HikariConfig config = newHikariConfig();\n      config.setJdbcUrl(postgres.getJdbcUrl());\n      config.setUsername(postgres.getUsername());\n      config.setPassword(postgres.getPassword());\n      config.setDriverClassName(postgres.getDriverClassName());\n      return config;\n   }\n\n   private void updatePostgresCredentials(String username, String password) {\n      postgres.stop();\n      postgres = new PostgreSQLContainer<>(IMAGE_NAME)\n         .withUsername(username)\n         .withPassword(password);\n      postgres.start();\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/RampUpDown.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static org.junit.Assert.assertSame;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\n\npublic class RampUpDown\n{\n    @Test\n    public void rampUpDownTest() throws SQLException\n    {\n        HikariConfig config = newHikariConfig();\n        config.setMinimumIdle(5);\n        config.setMaximumPoolSize(60);\n        config.setInitializationFailTimeout(0);\n        config.setConnectionTestQuery(\"VALUES 1\");\n        config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n        System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"250\");\n\n        try (HikariDataSource ds = new HikariDataSource(config)) {\n\n           ds.setIdleTimeout(1000);\n           HikariPool pool = getPool(ds);\n\n           // wait two housekeeping periods so we don't fail if this part of test runs too quickly\n           quietlySleep(500);\n\n           Assert.assertSame(\"Total connections not as expected\", 5, pool.getTotalConnections());\n\n           Connection[] connections = new Connection[ds.getMaximumPoolSize()];\n           for (int i = 0; i < connections.length; i++)\n           {\n               connections[i] = ds.getConnection();\n           }\n\n           assertSame(\"Total connections not as expected\", 60, pool.getTotalConnections());\n\n           for (Connection connection : connections)\n           {\n               connection.close();\n           }\n\n           quietlySleep(500);\n\n           assertSame(\"Total connections not as expected\", 5, pool.getTotalConnections());\n        }\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/RequestBoundariesTest.java",
    "content": "package com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport java.sql.Connection;\n\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\n\npublic class RequestBoundariesTest {\n\n   private static final HikariConfig config;\n   static {\n      config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(10);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n   }\n\n   private HikariPool getHikariPool(boolean enableRequestBoundaries) {\n      System.setProperty(\"com.zaxxer.hikari.enableRequestBoundaries\", String.valueOf(enableRequestBoundaries));\n      HikariDataSource ds = new HikariDataSource(config);\n      HikariPool pool = getPool(ds);\n      return pool;\n   }\n\n   @Test\n   public void requestBoundaryEnabledTest() throws Exception {\n      HikariPool pool = getHikariPool(true);\n      Connection conn = pool.getConnection();\n      StubConnection stubConnection = conn.unwrap(StubConnection.class);\n      Assert.assertTrue(\"Begin request called\", stubConnection.beginRequestCalled);\n      Assert.assertFalse(\"End request called\", stubConnection.endRequestCalled);\n      conn.close();\n      Assert.assertTrue(\"Begin request called\", stubConnection.beginRequestCalled);\n      Assert.assertTrue(\"End request called\", stubConnection.endRequestCalled);\n   }\n\n   @Test\n   public void requestBoundaryDisabledTest() throws Exception {\n      HikariPool pool = getHikariPool(false);\n      Connection conn = pool.getConnection();\n      StubConnection stubConnection = conn.unwrap(StubConnection.class);\n      Assert.assertFalse(\"Begin request called\", stubConnection.beginRequestCalled);\n      Assert.assertFalse(\"End request called\", stubConnection.endRequestCalled);\n      conn.close();\n      Assert.assertFalse(\"Begin request called\", stubConnection.beginRequestCalled);\n      Assert.assertFalse(\"End request called\", stubConnection.endRequestCalled);\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/ShutdownTest.java",
    "content": "/*\n * Copyright (C) 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jLogLevel;\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\nimport static com.zaxxer.hikari.util.ClockSource.elapsedMillis;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport org.apache.logging.log4j.Level;\nimport org.junit.After;\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport com.zaxxer.hikari.util.UtilityElf;\n\n/**\n * @author Brett Wooldridge\n */\npublic class ShutdownTest\n{\n   @Before\n   public void beforeTest()\n   {\n      setSlf4jLogLevel(PoolBase.class, Level.DEBUG);\n      setSlf4jLogLevel(HikariPool.class, Level.DEBUG);\n      StubConnection.count.set(0);\n   }\n\n   @After\n   public void afterTest()\n   {\n      setSlf4jLogLevel(PoolBase.class, Level.WARN);\n      setSlf4jLogLevel(HikariPool.class, Level.WARN);\n      StubConnection.slowCreate = false;\n   }\n\n   @Test\n   public void testShutdown1() throws SQLException\n   {\n      Assert.assertSame(\"StubConnection count not as expected\", 0, StubConnection.count.get());\n\n      StubConnection.slowCreate = true;\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(10);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPool pool = getPool(ds);\n\n         Thread[] threads = new Thread[10];\n         for (int i = 0; i < 10; i++) {\n            threads[i] = new Thread() {\n               @Override\n               public void run()\n               {\n                  try {\n                     if (ds.getConnection() != null) {\n                        quietlySleep(SECONDS.toMillis(1));\n                     }\n                  }\n                  catch (SQLException e) {\n                  }\n               }\n            };\n            threads[i].setDaemon(true);\n         }\n         for (int i = 0; i < 10; i++) {\n            threads[i].start();\n         }\n\n         quietlySleep(1800L);\n\n         assertTrue(\"Total connection count not as expected, \", pool.getTotalConnections() > 0);\n\n         ds.close();\n\n         assertSame(\"Active connection count not as expected, \", 0, pool.getActiveConnections());\n         assertSame(\"Idle connection count not as expected, \", 0, pool.getIdleConnections());\n         assertSame(\"Total connection count not as expected, \", 0, pool.getTotalConnections());\n         assertTrue(ds.isClosed());\n      }\n   }\n\n   @Test\n   public void testShutdown2() throws SQLException\n   {\n      assertSame(\"StubConnection count not as expected\", 0, StubConnection.count.get());\n\n      StubConnection.slowCreate = true;\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(10);\n      config.setMaximumPoolSize(10);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPool pool = getPool(ds);\n\n         quietlySleep(1200L);\n\n         assertTrue(\"Total connection count not as expected, \", pool.getTotalConnections() > 0);\n\n         ds.close();\n\n         assertSame(\"Active connection count not as expected, \", 0, pool.getActiveConnections());\n         assertSame(\"Idle connection count not as expected, \", 0, pool.getIdleConnections());\n         assertSame(\"Total connection count not as expected, \", 0, pool.getTotalConnections());\n         assertTrue(ds.toString().startsWith(\"HikariDataSource (\") && ds.toString().endsWith(\")\"));\n      }\n   }\n\n   @Test\n   public void testShutdown3() throws SQLException\n   {\n      assertSame(\"StubConnection count not as expected\", 0, StubConnection.count.get());\n\n      StubConnection.slowCreate = false;\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(5);\n      config.setMaximumPoolSize(5);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPool pool = getPool(ds);\n\n         quietlySleep(1200L);\n\n         assertTrue(\"Total connection count not as expected, \", pool.getTotalConnections() == 5);\n\n         ds.close();\n\n         assertSame(\"Active connection count not as expected, \", 0, pool.getActiveConnections());\n         assertSame(\"Idle connection count not as expected, \", 0, pool.getIdleConnections());\n         assertSame(\"Total connection count not as expected, \", 0, pool.getTotalConnections());\n      }\n   }\n\n   @Test\n   public void testShutdown4() throws SQLException\n   {\n      StubConnection.slowCreate = true;\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(10);\n      config.setMaximumPoolSize(10);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         quietlySleep(500L);\n\n         ds.close();\n\n         long startTime = currentTime();\n         while (elapsedMillis(startTime) < SECONDS.toMillis(5) && threadCount() > 0) {\n            quietlySleep(250);\n         }\n\n         assertSame(\"Unreleased connections after shutdown\", 0, getPool(ds).getTotalConnections());\n      }\n   }\n\n   @Test\n   public void testShutdown5() throws SQLException\n   {\n      Assert.assertSame(\"StubConnection count not as expected\", 0, StubConnection.count.get());\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(5);\n      config.setMaximumPoolSize(5);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPool pool = getPool(ds);\n\n         Connection[] connections = new Connection[5];\n         for (int i = 0; i < 5; i++) {\n            connections[i] = ds.getConnection();\n         }\n\n         Assert.assertTrue(\"Total connection count not as expected, \", pool.getTotalConnections() == 5);\n\n         ds.close();\n\n         Assert.assertSame(\"Active connection count not as expected, \", 0, pool.getActiveConnections());\n         Assert.assertSame(\"Idle connection count not as expected, \", 0, pool.getIdleConnections());\n         Assert.assertSame(\"Total connection count not as expected, \", 0, pool.getTotalConnections());\n      }\n   }\n\n   @Test\n   public void testAfterShutdown() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(5);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         ds.close();\n         try {\n            ds.getConnection();\n         }\n         catch (SQLException e) {\n            Assert.assertTrue(e.getMessage().contains(\"has been closed.\"));\n         }\n      }\n   }\n\n   @Test\n   public void testShutdownDuringInit() throws Exception\n   {\n      final HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(5);\n      config.setMaximumPoolSize(5);\n      config.setConnectionTimeout(1000);\n      config.setValidationTimeout(1000);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         StubConnection.slowCreate = true;\n         UtilityElf.quietlySleep(3000L);\n      }\n   }\n\n   @Test\n   public void testThreadedShutdown() throws Exception\n   {\n      final HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(5);\n      config.setMaximumPoolSize(5);\n      config.setConnectionTimeout(1000);\n      config.setValidationTimeout(1000);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      for (int i = 0; i < 4; i++) {\n         try (final HikariDataSource ds = new HikariDataSource(config)) {\n            Thread t = new Thread() {\n               @Override\n               public void run()\n               {\n                  try (Connection connection = ds.getConnection()) {\n                     for (int i = 0; i < 10; i++) {\n                        Connection connection2 = null;\n                        try {\n                           connection2 = ds.getConnection();\n                           PreparedStatement stmt = connection2.prepareStatement(\"SOMETHING\");\n                           UtilityElf.quietlySleep(20);\n                           stmt.getMaxFieldSize();\n                        }\n                        catch (SQLException e) {\n                           try {\n                              if (connection2 != null) {\n                                 connection2.close();\n                              }\n                           }\n                           catch (SQLException e2) {\n                              if (e2.getMessage().contains(\"shutdown\") || e2.getMessage().contains(\"evicted\")) {\n                                 break;\n                              }\n                           }\n                        }\n                     }\n                  }\n                  catch (Exception e) {\n                     Assert.fail(e.getMessage());\n                  }\n                  finally {\n                     ds.close();\n                  }\n               }\n            };\n            t.start();\n\n            Thread t2 = new Thread() {\n               @Override\n               public void run()\n               {\n                  UtilityElf.quietlySleep(100);\n                  try {\n                     ds.close();\n                  }\n                  catch (IllegalStateException e) {\n                     Assert.fail(e.getMessage());\n                  }\n               }\n            };\n            t2.start();\n\n            t.join();\n            t2.join();\n\n            ds.close();\n         }\n      }\n   }\n\n   private int threadCount()\n   {\n      Thread[] threads = new Thread[Thread.activeCount() * 2];\n      Thread.enumerate(threads);\n\n      int count = 0;\n      for (Thread thread : threads) {\n         count += (thread != null && thread.getName().startsWith(\"Hikari\")) ? 1 : 0;\n      }\n\n      return count;\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/StatementTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\n\npublic class StatementTest\n{\n   private HikariDataSource ds;\n\n   @Before\n   public void setup()\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(2);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      ds = new HikariDataSource(config);\n   }\n\n   @After\n   public void teardown()\n   {\n      ds.close();\n   }\n\n   @Test\n   public void testStatementClose() throws SQLException\n   {\n      ds.getConnection().close();\n\n      HikariPool pool = getPool(ds);\n      assertTrue(\"Total connections not as expected\", pool.getTotalConnections() >= 1);\n      assertTrue(\"Idle connections not as expected\", pool.getIdleConnections() >= 1);\n\n      try (Connection connection = ds.getConnection()) {\n         assertNotNull(connection);\n\n         assertTrue(\"Total connections not as expected\", pool.getTotalConnections() >= 1);\n         assertTrue(\"Idle connections not as expected\", pool.getIdleConnections() >= 0);\n\n         Statement statement = connection.createStatement();\n         assertNotNull(statement);\n\n         connection.close();\n\n         assertTrue(statement.isClosed());\n      }\n   }\n\n   @Test\n   public void testAutoStatementClose() throws SQLException\n   {\n      try (Connection connection = ds.getConnection()) {\n         assertNotNull(connection);\n\n         Statement statement1 = connection.createStatement();\n         assertNotNull(statement1);\n         Statement statement2 = connection.createStatement();\n         assertNotNull(statement2);\n\n         connection.close();\n\n         assertTrue(statement1.isClosed());\n         assertTrue(statement2.isClosed());\n      }\n   }\n\n   @Test\n   public void testStatementResultSetProxyClose() throws SQLException {\n      try (Connection connection = ds.getConnection()) {\n         assertNotNull(connection);\n\n         Statement statement1 = connection.createStatement();\n         assertNotNull(statement1);\n         Statement statement2 = connection.createStatement();\n         assertNotNull(statement2);\n\n         statement1.getResultSet().getStatement().close();\n         statement2.getGeneratedKeys().getStatement().close();\n\n         assertTrue(statement1.isClosed());\n         assertTrue(statement2.isClosed());\n      }\n   }\n\n   @Test\n   public void testDoubleStatementClose() throws SQLException\n   {\n      try (Connection connection = ds.getConnection();\n            Statement statement1 = connection.createStatement()) {\n         statement1.close();\n         statement1.close();\n      }\n   }\n\n   @Test\n   public void testOutOfOrderStatementClose() throws SQLException\n   {\n      try (Connection connection = ds.getConnection();\n            Statement statement1 = connection.createStatement();\n            Statement statement2 = connection.createStatement()) {\n         statement1.close();\n         statement2.close();\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestConcurrentBag.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jTargetStream;\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport java.util.concurrent.CompletableFuture;\n\nimport org.junit.AfterClass;\nimport org.junit.BeforeClass;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.util.ConcurrentBag;\n\n/**\n *\n * @author Brett Wooldridge\n */\npublic class TestConcurrentBag\n{\n   private static HikariDataSource ds;\n   private static HikariPool pool;\n\n   @BeforeClass\n   public static void setup()\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(2);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      ds = new HikariDataSource(config);\n      pool = getPool(ds);\n   }\n\n   @AfterClass\n   public static void teardown()\n   {\n      ds.close();\n   }\n\n   @Test\n   public void testConcurrentBag() throws Exception\n   {\n      try (ConcurrentBag<PoolEntry> bag = new ConcurrentBag<>(x -> CompletableFuture.completedFuture(Boolean.TRUE))) {\n         assertEquals(0, bag.values(8).size());\n\n         PoolEntry reserved = pool.newPoolEntry(false);\n         bag.add(reserved);\n         bag.reserve(reserved);      // reserved\n\n         PoolEntry inuse = pool.newPoolEntry(false);\n         bag.add(inuse);\n         bag.borrow(2, MILLISECONDS); // in use\n\n         PoolEntry notinuse = pool.newPoolEntry(false);\n         bag.add(notinuse); // not in use\n\n         bag.dumpState();\n\n         ByteArrayOutputStream baos = new ByteArrayOutputStream();\n         PrintStream ps = new PrintStream(baos, true);\n         setSlf4jTargetStream(ConcurrentBag.class, ps);\n\n         bag.requite(reserved);\n\n         bag.remove(notinuse);\n         assertTrue(new String(baos.toByteArray()).contains(\"not borrowed or reserved\"));\n\n         bag.unreserve(notinuse);\n         assertTrue(new String(baos.toByteArray()).contains(\"was not reserved\"));\n\n         bag.remove(inuse);\n         bag.remove(inuse);\n         assertTrue(new String(baos.toByteArray()).contains(\"not borrowed or reserved\"));\n\n         bag.close();\n         try {\n            PoolEntry bagEntry = pool.newPoolEntry(false);\n            bag.add(bagEntry);\n            assertNotEquals(bagEntry, bag.borrow(100, MILLISECONDS));\n         }\n         catch (IllegalStateException e) {\n            assertTrue(new String(baos.toByteArray()).contains(\"ignoring add()\"));\n         }\n\n         assertNotNull(notinuse.toString());\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestConnectionCloseBlocking.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\n/**\n *\n */\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\nimport static com.zaxxer.hikari.util.ClockSource.elapsedMillis;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.junit.Assert.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.Mockito.doAnswer;\nimport static org.mockito.Mockito.when;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport org.mockito.invocation.InvocationOnMock;\nimport org.mockito.stubbing.Answer;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.MockDataSource;\n\n/**\n * Test for cases when db network connectivity goes down and close is called on existing connections. By default Hikari\n * blocks longer than getMaximumTimeout (it can hang for a lot of time depending on driver timeout settings). Closing\n * async the connections fixes this issue.\n *\n */\npublic class TestConnectionCloseBlocking {\n   private static volatile boolean shouldFail = false;\n\n   // @Test\n   public void testConnectionCloseBlocking() throws SQLException {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(1500);\n      config.setDataSource(new CustomMockDataSource());\n\n      long start = currentTime();\n      try (HikariDataSource ds = new HikariDataSource(config);\n            Connection connection = ds.getConnection()) {\n\n            connection.close();\n\n            // Hikari only checks for validity for connections with lastAccess > 1000 ms so we sleep for 1001 ms to force\n            // Hikari to do a connection validation which will fail and will trigger the connection to be closed\n            quietlySleep(1100L);\n\n            shouldFail = true;\n\n            // on physical connection close we sleep 2 seconds\n            try (Connection connection2 = ds.getConnection()) {\n               assertTrue(\"Waited longer than timeout\", (elapsedMillis(start) < config.getConnectionTimeout()));\n            }\n      } catch (SQLException e) {\n         assertTrue(\"getConnection failed because close connection took longer than timeout\", (elapsedMillis(start) < config.getConnectionTimeout()));\n      }\n   }\n\n   private static class CustomMockDataSource extends MockDataSource {\n      @Override\n      public Connection getConnection() throws SQLException {\n         Connection mockConnection = super.getConnection();\n         when(mockConnection.isValid(anyInt())).thenReturn(!shouldFail);\n         doAnswer(new Answer<Void>() {\n            @Override\n            public Void answer(InvocationOnMock invocation) throws Throwable {\n               if (shouldFail) {\n                  SECONDS.sleep(2);\n               }\n               return null;\n            }\n         }).when(mockConnection).close();\n         return mockConnection;\n      }\n   }\n\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestConnectionTimeoutRetry.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jLogLevel;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jTargetStream;\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\nimport static com.zaxxer.hikari.util.ClockSource.elapsedMillis;\nimport static java.lang.Thread.sleep;\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\nimport org.apache.logging.log4j.Level;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport com.zaxxer.hikari.mocks.StubDataSource;\n\npublic class TestConnectionTimeoutRetry\n{\n   @Test\n   public void testConnectionRetries() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2800);\n      config.setValidationTimeout(2800);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);\n         stubDataSource.setThrowException(new SQLException(\"Connection refused\"));\n\n         long start = currentTime();\n         try (Connection connection = ds.getConnection()) {\n            connection.close();\n            fail(\"Should not have been able to get a connection.\");\n         }\n         catch (SQLException e) {\n            long elapsed = elapsedMillis(start);\n            long timeout = config.getConnectionTimeout();\n            assertTrue(\"Didn't wait long enough for timeout\", (elapsed >= timeout));\n         }\n      }\n   }\n\n   @Test\n   public void testConnectionRetries2() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2800);\n      config.setValidationTimeout(2800);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         final StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);\n         stubDataSource.setThrowException(new SQLException(\"Connection refused\"));\n\n         ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);\n         scheduler.schedule(new Runnable() {\n            @Override\n            public void run()\n            {\n               stubDataSource.setThrowException(null);\n            }\n         }, 300, TimeUnit.MILLISECONDS);\n\n         long start = currentTime();\n         try {\n            try (Connection connection = ds.getConnection()) {\n               // close immediately\n            }\n\n            long elapsed = elapsedMillis(start);\n            assertTrue(\"Connection returned too quickly, something is wrong.\", elapsed > 250);\n            assertTrue(\"Waited too long to get a connection.\", elapsed < config.getConnectionTimeout());\n         }\n         catch (SQLException e) {\n            fail(\"Should not have timed out: \" + e.getMessage());\n         }\n         finally {\n            scheduler.shutdownNow();\n         }\n      }\n   }\n\n   @Test\n   public void testConnectionRetries3() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(2);\n      config.setConnectionTimeout(2800);\n      config.setValidationTimeout(2800);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         final Connection connection1 = ds.getConnection();\n         final Connection connection2 = ds.getConnection();\n         assertNotNull(connection1);\n         assertNotNull(connection2);\n\n         ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);\n         scheduler.schedule(new Runnable() {\n            @Override\n            public void run()\n            {\n               try {\n                  connection1.close();\n               }\n               catch (Exception e) {\n                  e.printStackTrace(System.err);\n               }\n            }\n         }, 800, MILLISECONDS);\n\n         long start = currentTime();\n         try {\n            try (Connection connection3 = ds.getConnection()) {\n               // close immediately\n            }\n\n            long elapsed = elapsedMillis(start);\n            assertTrue(\"Waited too long to get a connection.\", (elapsed >= 700) && (elapsed < 950));\n         }\n         catch (SQLException e) {\n            fail(\"Should not have timed out.\");\n         }\n         finally {\n            scheduler.shutdownNow();\n         }\n      }\n   }\n\n   @Test\n   public void testConnectionRetries5() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(2);\n      config.setConnectionTimeout(1000);\n      config.setValidationTimeout(1000);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         final Connection connection1 = ds.getConnection();\n\n         long start = currentTime();\n\n         ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);\n         scheduler.schedule(new Runnable() {\n            @Override\n            public void run()\n            {\n               try {\n                  connection1.close();\n               }\n               catch (Exception e) {\n                  e.printStackTrace(System.err);\n               }\n            }\n         }, 250, MILLISECONDS);\n\n         StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);\n         stubDataSource.setThrowException(new SQLException(\"Connection refused\"));\n\n         try {\n            try (Connection connection2 = ds.getConnection()) {\n               // close immediately\n            }\n\n            long elapsed = elapsedMillis(start);\n            assertTrue(\"Waited too long to get a connection.\", (elapsed >= 250) && (elapsed < config.getConnectionTimeout()));\n         }\n         catch (SQLException e) {\n            fail(\"Should not have timed out.\");\n         }\n         finally {\n            scheduler.shutdownNow();\n         }\n      }\n   }\n\n   @Test\n   public void testConnectionIdleFill() throws Exception\n   {\n      StubConnection.slowCreate = false;\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(5);\n      config.setMaximumPoolSize(10);\n      config.setConnectionTimeout(2000);\n      config.setValidationTimeout(2000);\n      config.setConnectionTestQuery(\"VALUES 2\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"400\");\n\n      ByteArrayOutputStream baos = new ByteArrayOutputStream();\n      PrintStream ps = new PrintStream(baos, true);\n      setSlf4jTargetStream(HikariPool.class, ps);\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         setSlf4jLogLevel(HikariPool.class, Level.DEBUG);\n\n         HikariPool pool = getPool(ds);\n         try (\n            Connection connection1 = ds.getConnection();\n            Connection connection2 = ds.getConnection();\n            Connection connection3 = ds.getConnection();\n            Connection connection4 = ds.getConnection();\n            Connection connection5 = ds.getConnection();\n            Connection connection6 = ds.getConnection();\n            Connection connection7 = ds.getConnection()) {\n\n            sleep(1300);\n\n            assertSame(\"Total connections not as expected\", 10, pool.getTotalConnections());\n            assertSame(\"Idle connections not as expected\", 3, pool.getIdleConnections());\n         }\n\n         assertSame(\"Total connections not as expected\", 10, pool.getTotalConnections());\n         assertSame(\"Idle connections not as expected\", 10, pool.getIdleConnections());\n      }\n   }\n\n   @Before\n   public void before()\n   {\n      setSlf4jLogLevel(HikariPool.class, Level.INFO);\n   }\n\n   @After\n   public void after()\n   {\n      System.getProperties().remove(\"com.zaxxer.hikari.housekeeping.periodMs\");\n      setSlf4jLogLevel(HikariPool.class, Level.INFO);\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestConnections.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.HikariPoolMXBean;\nimport com.zaxxer.hikari.SQLExceptionOverride;\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport com.zaxxer.hikari.mocks.StubDataSource;\nimport com.zaxxer.hikari.mocks.StubStatement;\nimport com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;\nimport org.apache.logging.log4j.Level;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.sql.*;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static com.zaxxer.hikari.pool.TestElf.*;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.junit.Assert.*;\n\n/**\n * @author Brett Wooldridge\n */\n@SuppressWarnings({\"SqlDialectInspection\", \"SqlNoDataSourceInspection\"})\npublic class TestConnections\n{\n   @Before\n   public void before()\n   {\n      setSlf4jTargetStream(HikariPool.class, System.err);\n      setSlf4jLogLevel(HikariPool.class, Level.DEBUG);\n      setSlf4jLogLevel(PoolBase.class, Level.DEBUG);\n   }\n\n   @After\n   public void after()\n   {\n      System.getProperties().remove(\"com.zaxxer.hikari.housekeeping.periodMs\");\n      setSlf4jLogLevel(HikariPool.class, Level.WARN);\n      setSlf4jLogLevel(PoolBase.class, Level.WARN);\n   }\n\n   @Test\n   public void testCreate() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setConnectionInitSql(\"SELECT 1\");\n      config.setReadOnly(true);\n      config.setConnectionTimeout(2500);\n      config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(30));\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         ds.setLoginTimeout(10);\n         assertSame(10, ds.getLoginTimeout());\n\n         HikariPool pool = getPool(ds);\n         ds.getConnection().close();\n         assertSame(\"Total connections not as expected\", 1, pool.getTotalConnections());\n         assertSame(\"Idle connections not as expected\", 1, pool.getIdleConnections());\n\n         try (Connection connection = ds.getConnection();\n              PreparedStatement statement = connection.prepareStatement(\"SELECT * FROM device WHERE device_id=?\")) {\n\n            assertNotNull(connection);\n            assertNotNull(statement);\n\n            assertSame(\"Total connections not as expected\", 1, pool.getTotalConnections());\n            assertSame(\"Idle connections not as expected\", 0, pool.getIdleConnections());\n\n            statement.setInt(1, 0);\n\n            try (ResultSet resultSet = statement.executeQuery()) {\n               assertNotNull(resultSet);\n\n               assertFalse(resultSet.next());\n            }\n         }\n\n         assertSame(\"Total connections not as expected\", 1, pool.getTotalConnections());\n         assertSame(\"Idle connections not as expected\", 1, pool.getIdleConnections());\n      }\n   }\n\n   @Test\n   public void testMaxLifetime() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"100\");\n\n      setConfigUnitTest(true);\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         System.clearProperty(\"com.zaxxer.hikari.housekeeping.periodMs\");\n\n         getUnsealedConfig(ds).setMaxLifetime(700);\n\n         HikariPool pool = getPool(ds);\n\n         assertSame(\"Total connections not as expected\", 0, pool.getTotalConnections());\n         assertSame(\"Idle connections not as expected\", 0, pool.getIdleConnections());\n\n         Connection unwrap;\n         Connection unwrap2;\n         try (Connection connection = ds.getConnection()) {\n            unwrap = connection.unwrap(Connection.class);\n            assertNotNull(connection);\n\n            assertSame(\"Second total connections not as expected\", 1, pool.getTotalConnections());\n            assertSame(\"Second idle connections not as expected\", 0, pool.getIdleConnections());\n         }\n\n         assertSame(\"Idle connections not as expected\", 1, pool.getIdleConnections());\n\n         try (Connection connection = ds.getConnection()) {\n            unwrap2 = connection.unwrap(Connection.class);\n            assertSame(unwrap, unwrap2);\n            assertSame(\"Second total connections not as expected\", 1, pool.getTotalConnections());\n            assertSame(\"Second idle connections not as expected\", 0, pool.getIdleConnections());\n         }\n\n         quietlySleep(TimeUnit.SECONDS.toMillis(2));\n\n         try (Connection connection = ds.getConnection()) {\n            unwrap2 = connection.unwrap(Connection.class);\n            assertNotSame(\"Expected a different connection\", unwrap, unwrap2);\n         }\n\n         assertSame(\"Post total connections not as expected\", 1, pool.getTotalConnections());\n         assertSame(\"Post idle connections not as expected\", 1, pool.getIdleConnections());\n      }\n      finally {\n         setConfigUnitTest(false);\n      }\n   }\n\n   @Test\n   public void testMaxLifetime2() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"100\");\n\n      setConfigUnitTest(true);\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         getUnsealedConfig(ds).setMaxLifetime(700);\n\n         HikariPool pool = getPool(ds);\n         assertSame(\"Total connections not as expected\", 0, pool.getTotalConnections());\n         assertSame(\"Idle connections not as expected\", 0, pool.getIdleConnections());\n\n         Connection unwrap;\n         Connection unwrap2;\n         try (Connection connection = ds.getConnection()) {\n            unwrap = connection.unwrap(Connection.class);\n            assertNotNull(connection);\n\n            assertSame(\"Second total connections not as expected\", 1, pool.getTotalConnections());\n            assertSame(\"Second idle connections not as expected\", 0, pool.getIdleConnections());\n         }\n\n         assertSame(\"Idle connections not as expected\", 1, pool.getIdleConnections());\n\n         try (Connection connection = ds.getConnection()) {\n            unwrap2 = connection.unwrap(Connection.class);\n            assertSame(unwrap, unwrap2);\n            assertSame(\"Second total connections not as expected\", 1, pool.getTotalConnections());\n            assertSame(\"Second idle connections not as expected\", 0, pool.getIdleConnections());\n         }\n\n         quietlySleep(800);\n\n         try (Connection connection = ds.getConnection()) {\n            unwrap2 = connection.unwrap(Connection.class);\n            assertNotSame(\"Expected a different connection\", unwrap, unwrap2);\n         }\n\n         assertSame(\"Post total connections not as expected\", 1, pool.getTotalConnections());\n         assertSame(\"Post idle connections not as expected\", 1, pool.getIdleConnections());\n      }\n      finally {\n         setConfigUnitTest(false);\n      }\n   }\n\n   @Test\n   public void testKeepalive() throws Exception{\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      StubDataSource sds = new StubDataSource();\n      sds.setWaitTimeout(700);\n      config.setDataSource(sds);\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"100\");\n\n      setConfigUnitTest(true);\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         getUnsealedConfig(ds).setKeepaliveTime(500);\n\n         HikariPool pool = getPool(ds);\n         Connection conn = pool.getConnection();\n         Connection unwrap = conn.unwrap(Connection.class);\n         //recycle, change IN_USE state\n         conn.close();\n         assertFalse(\"Connection should be open\", unwrap.isClosed());\n         quietlySleep(1200);\n         assertFalse(\"Connection should be open\", unwrap.isClosed());\n      }\n      finally {\n         setConfigUnitTest(false);\n      }\n   }\n\n   @Test\n   public void testKeepalive2() throws Exception{\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      StubDataSource sds = new StubDataSource();\n      sds.setWaitTimeout(500);\n      config.setDataSource(sds);\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"100\");\n\n      setConfigUnitTest(true);\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         getUnsealedConfig(ds).setKeepaliveTime(700);\n\n         HikariPool pool = getPool(ds);\n         Connection conn = pool.getConnection();\n         Connection unwrap = conn.unwrap(Connection.class);\n         //recycle, change IN_USE state\n         conn.close();\n         assertFalse(\"Connection should be open\", unwrap.isClosed());\n         quietlySleep(1200);\n         assertTrue(\"Connection should have closed:\" + unwrap, unwrap.isClosed());\n\n         Connection conn2 = pool.getConnection();\n         Connection unwrap2 = conn2.unwrap(Connection.class);\n\n         assertNotSame(\"Expected a different connection\", unwrap, unwrap2);\n         assertFalse(\"Connection should be open\", unwrap2.isClosed());\n\n         conn2.close();\n      }\n      finally {\n         setConfigUnitTest(false);\n      }\n   }\n\n   @Test\n   public void testDoubleClose() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config);\n         Connection connection = ds.getConnection()) {\n         connection.close();\n\n         // should no-op\n         connection.abort(null);\n\n         assertTrue(\"Connection should have closed\", connection.isClosed());\n         assertFalse(\"Connection should have closed\", connection.isValid(5));\n         assertTrue(\"Expected to contain ClosedConnection, but was \" + connection, connection.toString().contains(\"ClosedConnection\"));\n      }\n   }\n\n   @Test\n   public void testCloseMarkEvicted() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(5);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         ProxyConnection connection = (ProxyConnection) ds.getConnection();\n\n         HikariPool pool = getPool(ds);\n         assertEquals(1, pool.getTotalConnections());\n         connection.getPoolEntry().markEvicted();\n         connection.close();\n\n         assertEquals(\"Connection should have been evicted after close\", 0, pool.getTotalConnections());\n      }\n   }\n\n   @Test\n   public void testEviction() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(5);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         Connection connection = ds.getConnection();\n\n         HikariPool pool = getPool(ds);\n         assertEquals(1, pool.getTotalConnections());\n         ds.evictConnection(connection);\n         assertEquals(0, pool.getTotalConnections());\n      }\n   }\n\n   @Test\n   public void testEviction2() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMaximumPoolSize(5);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setExceptionOverrideClassName(OverrideHandler.class.getName());\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPool pool = getPool(ds);\n\n         while (pool.getTotalConnections() < 5) {\n            quietlySleep(100L);\n         }\n\n         try (Connection connection = ds.getConnection()) {\n            assertNotNull(connection);\n\n            PreparedStatement statement = connection.prepareStatement(\"SELECT some, thing FROM somewhere WHERE something=?\");\n            assertNotNull(statement);\n\n            ResultSet resultSet = statement.executeQuery();\n            assertNotNull(resultSet);\n\n            try {\n               statement.getMaxFieldSize();\n            } catch (Exception e) {\n               assertSame(SQLException.class, e.getClass());\n            }\n         }\n\n         assertEquals(\"Total connections not as expected\", 5, pool.getTotalConnections());\n         assertEquals(\"Idle connections not as expected\", 5, pool.getIdleConnections());\n      }\n   }\n\n   @Test\n   public void testEviction3() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMaximumPoolSize(5);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPool pool = getPool(ds);\n\n         while (pool.getTotalConnections() < 5) {\n            quietlySleep(100L);\n         }\n\n         try (Connection connection = ds.getConnection()) {\n            assertNotNull(connection);\n\n            PreparedStatement statement = connection.prepareStatement(\"SELECT some, thing FROM somewhere WHERE something=?\");\n            assertNotNull(statement);\n\n            ResultSet resultSet = statement.executeQuery();\n            assertNotNull(resultSet);\n\n            try {\n               statement.getMaxFieldSize();\n            } catch (Exception e) {\n               assertSame(SQLException.class, e.getClass());\n            }\n         }\n\n         assertEquals(\"Total connections not as expected\", 4, pool.getTotalConnections());\n         assertEquals(\"Idle connections not as expected\", 4, pool.getIdleConnections());\n      }\n   }\n\n   @Test\n   public void testEvictAllRefill() throws Exception {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(5);\n      config.setMaximumPoolSize(10);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"100\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPoolMXBean poolMXBean = ds.getHikariPoolMXBean();\n\n         while (poolMXBean.getIdleConnections() < 5) { // wait until the pool fills\n            quietlySleep(100);\n         }\n\n         // Get and evict all the idle connections\n         for (int i = 0; i < 5; i++) {\n            final Connection conn = ds.getConnection();\n            ds.evictConnection(conn);\n         }\n\n         assertTrue(\"Expected idle connections to be less than idle\", poolMXBean.getIdleConnections() < 5);\n\n         // Wait a bit\n         quietlySleep(SECONDS.toMillis(2));\n\n         int count = 0;\n         while (poolMXBean.getIdleConnections() < 5 && count++ < 20) {\n            quietlySleep(100);\n         }\n\n         // Assert that the pool as returned to 5 connections\n         assertEquals(\"After eviction, refill did not reach expected 5 connections.\", 5, poolMXBean.getIdleConnections());\n      }\n      finally {\n         System.clearProperty(\"com.zaxxer.hikari.housekeeping.periodMs\");\n      }\n   }\n\n   @Test\n   public void testBackfill() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(4);\n      config.setConnectionTimeout(1000);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      StubConnection.slowCreate = true;\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n\n         HikariPool pool = getPool(ds);\n         quietlySleep(1250);\n\n         assertSame(\"Total connections not as expected\", 1, pool.getTotalConnections());\n         assertSame(\"Idle connections not as expected\", 1, pool.getIdleConnections());\n\n         // This will take the pool down to zero\n         try (Connection connection = ds.getConnection()) {\n            assertNotNull(connection);\n\n            assertSame(\"Total connections not as expected\", 1, pool.getTotalConnections());\n            assertSame(\"Idle connections not as expected\", 0, pool.getIdleConnections());\n\n            PreparedStatement statement = connection.prepareStatement(\"SELECT some, thing FROM somewhere WHERE something=?\");\n            assertNotNull(statement);\n\n            ResultSet resultSet = statement.executeQuery();\n            assertNotNull(resultSet);\n\n            try {\n               statement.getMaxFieldSize();\n               fail();\n            }\n            catch (Exception e) {\n               assertSame(SQLException.class, e.getClass());\n            }\n\n            pool.logPoolState(\"testBackfill() before close...\");\n\n            // The connection will be ejected from the pool here\n         }\n\n         assertSame(\"Total connections not as expected\", 0, pool.getTotalConnections());\n\n         pool.logPoolState(\"testBackfill() after  close...\");\n\n         quietlySleep(1250);\n\n         assertSame(\"Total connections not as expected\", 1, pool.getTotalConnections());\n         assertSame(\"Idle connections not as expected\", 1, pool.getIdleConnections());\n      }\n      finally {\n         StubConnection.slowCreate = false;\n      }\n   }\n\n   @Test\n   public void testMaximumPoolLimit() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(4);\n      config.setConnectionTimeout(20000);\n      config.setInitializationFailTimeout(0);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      final AtomicReference<Exception> ref = new AtomicReference<>();\n\n      StubConnection.count.set(0); // reset counter\n\n      try (final HikariDataSource ds = new HikariDataSource(config)) {\n\n         final HikariPool pool = getPool(ds);\n\n         Thread[] threads = new Thread[20];\n         for (int i = 0; i < threads.length; i++) {\n            threads[i] = new Thread(() -> {\n               try {\n                  pool.logPoolState(\"Before acquire \");\n                  try (Connection ignored = ds.getConnection()) {\n                     pool.logPoolState(\"After  acquire \");\n                     quietlySleep(500);\n                  }\n               }\n               catch (Exception e) {\n                  ref.set(e);\n               }\n            });\n         }\n\n         for (Thread thread : threads) {\n            thread.start();\n         }\n\n         for (Thread thread : threads) {\n            thread.join();\n         }\n\n         pool.logPoolState(\"before check \");\n         assertNull((ref.get() != null ? ref.get().toString() : \"\"), ref.get());\n         assertSame(\"StubConnection count not as expected\", 4, StubConnection.count.get());\n      }\n   }\n\n   @Test\n   @SuppressWarnings(\"EmptyTryBlock\")\n   public void testOldDriver() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      StubConnection.oldDriver = true;\n      StubStatement.oldDriver = true;\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         quietlySleep(500);\n\n         try (Connection ignored = ds.getConnection()) {\n            // close\n         }\n\n         quietlySleep(500);\n         try (Connection ignored = ds.getConnection()) {\n            // close\n         }\n      }\n      finally {\n         StubConnection.oldDriver = false;\n         StubStatement.oldDriver = false;\n      }\n   }\n\n   @Test\n   public void testSuspendResume() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(3);\n      config.setConnectionTimeout(2500);\n      config.setAllowPoolSuspension(true);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (final HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPool pool = getPool(ds);\n         while (pool.getTotalConnections() < 3) {\n            quietlySleep(50);\n         }\n\n         Thread t = new Thread(() -> {\n            try {\n               ds.getConnection();\n               ds.getConnection();\n            }\n            catch (Exception e) {\n               fail();\n            }\n         });\n\n         try (Connection ignored = ds.getConnection()) {\n            assertEquals(2, pool.getIdleConnections());\n\n            pool.suspendPool();\n            t.start();\n\n            quietlySleep(500);\n            assertEquals(2, pool.getIdleConnections());\n         }\n         assertEquals(3, pool.getIdleConnections());\n         pool.resumePool();\n         quietlySleep(500);\n         assertEquals(1, pool.getIdleConnections());\n      }\n   }\n\n   @Test\n   public void testSuspendResumeWithThrow() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(3);\n      config.setConnectionTimeout(2500);\n      config.setAllowPoolSuspension(true);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      System.setProperty(\"com.zaxxer.hikari.throwIfSuspended\", \"true\");\n      try (final HikariDataSource ds = new HikariDataSource(config)) {\n         HikariPool pool = getPool(ds);\n         while (pool.getTotalConnections() < 3) {\n            quietlySleep(50);\n         }\n\n         AtomicReference<Exception> exception = new AtomicReference<>();\n         Thread t = new Thread(() -> {\n            try {\n               ds.getConnection();\n               ds.getConnection();\n            }\n            catch (Exception e) {\n               exception.set(e);\n            }\n         });\n\n         try (Connection ignored = ds.getConnection()) {\n            assertEquals(2, pool.getIdleConnections());\n\n            pool.suspendPool();\n            t.start();\n\n            quietlySleep(500);\n            assertEquals(SQLTransientException.class, exception.get().getClass());\n            assertEquals(2, pool.getIdleConnections());\n         }\n\n         assertEquals(3, pool.getIdleConnections());\n         pool.resumePool();\n\n         try (Connection ignored = ds.getConnection()) {\n            assertEquals(2, pool.getIdleConnections());\n         }\n      }\n      finally {\n         System.getProperties().remove(\"com.zaxxer.hikari.throwIfSuspended\");\n      }\n   }\n\n   @Test\n   public void testInitializationFailure1()\n   {\n      StubDataSource stubDataSource = new StubDataSource();\n      stubDataSource.setThrowException(new SQLException(\"Connection refused\"));\n\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMinimumIdle(1);\n         ds.setMaximumPoolSize(1);\n         ds.setConnectionTimeout(2500);\n         ds.setConnectionTestQuery(\"VALUES 1\");\n         ds.setDataSource(stubDataSource);\n\n         try (Connection ignored = ds.getConnection()) {\n            fail(\"Initialization should have failed\");\n         }\n         catch (SQLException e) {\n            // passed\n         }\n      }\n   }\n\n   @Test\n   public void testInitializationFailure2() throws SQLException\n   {\n      StubDataSource stubDataSource = new StubDataSource();\n      stubDataSource.setThrowException(new SQLException(\"Connection refused\"));\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSource(stubDataSource);\n\n      try (HikariDataSource ds = new HikariDataSource(config);\n           Connection ignored = ds.getConnection()) {\n         fail(\"Initialization should have failed\");\n      }\n      catch (PoolInitializationException e) {\n         // passed\n      }\n   }\n\n   @Test\n   public void testInvalidConnectionTestQuery()\n   {\n      class BadConnection extends StubConnection {\n         /** {@inheritDoc} */\n         @Override\n         public Statement createStatement() throws SQLException\n         {\n            throw new SQLException(\"Simulated exception in createStatement()\");\n         }\n      }\n\n      StubDataSource stubDataSource = new StubDataSource() {\n         /** {@inheritDoc} */\n         @Override\n         public Connection getConnection()\n         {\n            return new BadConnection();\n         }\n      };\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(2);\n      config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(3));\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setInitializationFailTimeout(TimeUnit.SECONDS.toMillis(2));\n      config.setDataSource(stubDataSource);\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         try (Connection ignored = ds.getConnection()) {\n            fail(\"getConnection() should have failed\");\n         }\n         catch (SQLException e) {\n            assertSame(\"Simulated exception in createStatement()\", e.getNextException().getMessage());\n         }\n      }\n      catch (PoolInitializationException e) {\n         assertSame(\"Simulated exception in createStatement()\", e.getCause().getMessage());\n      }\n\n      config.setInitializationFailTimeout(0);\n      try (HikariDataSource ignored = new HikariDataSource(config)) {\n         fail(\"Initialization should have failed\");\n      }\n      catch (PoolInitializationException e) {\n         // passed\n      }\n   }\n\n   @Test\n   public void testDataSourceRaisesErrorWhileInitializationTestQuery() throws SQLException\n   {\n      StubDataSourceWithErrorSwitch stubDataSource = new StubDataSourceWithErrorSwitch();\n      stubDataSource.setErrorOnConnection(true);\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSource(stubDataSource);\n\n      try (HikariDataSource ds = new HikariDataSource(config);\n         Connection ignored = ds.getConnection()) {\n         fail(\"Initialization should have failed\");\n      }\n      catch (PoolInitializationException e) {\n         // passed\n      }\n   }\n\n   @Test\n   public void testDataSourceRaisesErrorAfterInitializationTestQuery()\n   {\n      StubDataSourceWithErrorSwitch stubDataSource = new StubDataSourceWithErrorSwitch();\n\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(2);\n      config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(3));\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setInitializationFailTimeout(TimeUnit.SECONDS.toMillis(2));\n      config.setDataSource(stubDataSource);\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         // this will make datasource throws Error, which will become uncaught\n         stubDataSource.setErrorOnConnection(true);\n         try (Connection ignored = ds.getConnection()) {\n            fail(\"SQLException should occur!\");\n         } catch (SQLException e) {\n            // request will get timed-out\n            assertTrue(e.getMessage().contains(\"request timed out\"));\n         }\n      }\n   }\n\n   @Test\n   public void testPopulationSlowAcquisition() throws InterruptedException, SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMaximumPoolSize(20);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"1000\");\n\n      StubConnection.slowCreate = true;\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         System.clearProperty(\"com.zaxxer.hikari.housekeeping.periodMs\");\n\n         getUnsealedConfig(ds).setIdleTimeout(3000);\n\n         SECONDS.sleep(2);\n\n         HikariPool pool = getPool(ds);\n         assertSame(\"Total connections not as expected\", 2, pool.getTotalConnections());\n         assertSame(\"Idle connections not as expected\", 2, pool.getIdleConnections());\n\n         try (Connection connection = ds.getConnection()) {\n            assertNotNull(connection);\n\n            SECONDS.sleep(20);\n\n            assertSame(\"Second total connections not as expected\", 20, pool.getTotalConnections());\n            assertSame(\"Second idle connections not as expected\", 19, pool.getIdleConnections());\n         }\n\n         assertSame(\"Idle connections not as expected\", 20, pool.getIdleConnections());\n\n         SECONDS.sleep(5);\n\n         assertSame(\"Third total connections not as expected\", 20, pool.getTotalConnections());\n         assertSame(\"Third idle connections not as expected\", 20, pool.getIdleConnections());\n      }\n      finally {\n         StubConnection.slowCreate = false;\n      }\n   }\n\n   @Test\n   @SuppressWarnings(\"EmptyTryBlock\")\n   public void testMinimumIdleZero() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(5);\n      config.setConnectionTimeout(1000L);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config);\n           Connection ignored = ds.getConnection()) {\n         // passed\n      }\n      catch (SQLTransientConnectionException sqle) {\n         fail(\"Failed to obtain connection\");\n      }\n   }\n\n   static class StubDataSourceWithErrorSwitch extends StubDataSource\n   {\n      private boolean errorOnConnection = false;\n\n      /** {@inheritDoc} */\n      @Override\n      public Connection getConnection() {\n         if (!errorOnConnection) {\n            return new StubConnection();\n         }\n\n         throw new RuntimeException(\"Bad thing happens on datasource.\");\n      }\n\n      public void setErrorOnConnection(boolean errorOnConnection) {\n         this.errorOnConnection = errorOnConnection;\n      }\n   }\n\n   public static class OverrideHandler implements SQLExceptionOverride\n   {\n      @java.lang.Override\n      public Override adjudicate(SQLException sqlException) {\n         return (sqlException.getSQLState().equals(\"08999\")) ? Override.DO_NOT_EVICT : Override.CONTINUE_EVICT;\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestCredentials.java",
    "content": "package com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariCredentialsProvider;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.util.Credentials;\nimport org.junit.Test;\n\nimport java.time.Duration;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.apache.commons.lang3.ThreadUtils.sleepQuietly;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\npublic class TestCredentials {\n   @Test\n   public void testCredentialsProvider() {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(2500);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setCredentialsProvider(new TestCredentialsProvider());\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         sleepQuietly(Duration.ofMillis(250L)); // Allow time for the credentials provider to be called\n\n         assertTrue(\"CredentialsProvider was not called\", ((TestCredentialsProvider) ds.getCredentialsProvider()).called.get());\n      } catch (Exception e) {\n         fail(\"Exception occurred: \" + e.getMessage());\n      }\n   }\n\n   public static class TestCredentialsProvider implements HikariCredentialsProvider {\n      AtomicBoolean called = new AtomicBoolean();\n\n      @Override\n      public Credentials getCredentials() {\n         called.set(true);\n         return new Credentials(\"user\", \"password\");\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestElf.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.util.ConcurrentBag;\nimport org.apache.logging.log4j.Level;\nimport org.apache.logging.log4j.core.Appender;\nimport org.apache.logging.log4j.core.LogEvent;\nimport org.apache.logging.log4j.core.Logger;\nimport org.apache.logging.log4j.core.appender.AbstractAppender;\nimport org.apache.logging.log4j.core.config.Property;\nimport org.apache.logging.log4j.core.layout.CsvLogEventLayout;\nimport org.apache.logging.slf4j.Log4jLogger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.DataInputStream;\nimport java.io.IOException;\nimport java.io.PrintStream;\nimport java.lang.reflect.Field;\nimport java.net.URL;\nimport java.sql.Connection;\n\n/**\n * Utility methods for testing.\n *\n * @author Brett Wooldridge\n */\npublic final class TestElf\n{\n   private TestElf() {\n      // default constructor\n   }\n\n   public static boolean isJava11() {\n      return Integer.parseInt(System.getProperty(\"java.version\").split(\"\\\\.\")[0]) >= 11;\n   }\n\n   public static HikariPool getPool(final HikariDataSource ds)\n   {\n      try {\n         Field field = ds.getClass().getDeclaredField(\"pool\");\n         field.setAccessible(true);\n         return (HikariPool) field.get(ds);\n      }\n      catch (Exception e) {\n         throw new RuntimeException(e);\n      }\n   }\n\n   static ConcurrentBag<?> getConcurrentBag(final HikariDataSource ds)\n   {\n      try {\n         Field field = HikariPool.class.getDeclaredField(\"connectionBag\");\n         field.setAccessible(true);\n         return (ConcurrentBag<?>) field.get(getPool(ds));\n      }\n      catch (Exception e) {\n         throw new RuntimeException(e);\n      }\n   }\n\n   public static HikariConfig getUnsealedConfig(final HikariDataSource ds)\n   {\n      try {\n         HikariPool pool = getPool(ds);\n         Field configField = PoolBase.class.getDeclaredField(\"config\");\n         configField.setAccessible(true);\n         HikariConfig config = (HikariConfig) configField.get(pool);\n\n         Field field = HikariConfig.class.getDeclaredField(\"sealed\");\n         field.setAccessible(true);\n         field.setBoolean(config, false);\n         return config;\n      }\n      catch (Exception e) {\n         throw new RuntimeException(e);\n      }\n   }\n\n   static boolean getConnectionCommitDirtyState(final Connection connection)\n   {\n      try {\n         Field field = ProxyConnection.class.getDeclaredField(\"isCommitStateDirty\");\n         field.setAccessible(true);\n         return field.getBoolean(connection);\n      }\n      catch (Exception e) {\n         throw new RuntimeException(e);\n      }\n   }\n\n   static void setConfigUnitTest(final boolean unitTest)\n   {\n      try {\n         Field field = HikariConfig.class.getDeclaredField(\"unitTest\");\n         field.setAccessible(true);\n         field.setBoolean(null, unitTest);\n      }\n      catch (Exception e) {\n         throw new RuntimeException(e);\n      }\n   }\n\n   static void setSlf4jTargetStream(final Class<?> clazz, final PrintStream stream)\n   {\n      try {\n         Log4jLogger log4Jlogger = (Log4jLogger) LoggerFactory.getLogger(clazz);\n\n         Field field = clazz.getClassLoader().loadClass(\"org.apache.logging.slf4j.Log4jLogger\").getDeclaredField(\"logger\");\n         field.setAccessible(true);\n\n         Logger logger = (Logger) field.get(log4Jlogger);\n         if (logger.getAppenders().containsKey(\"string\")) {\n            Appender appender = logger.getAppenders().get(\"string\");\n            logger.removeAppender(appender);\n         }\n\n         logger.addAppender(new StringAppender(\"string\", stream));\n      }\n      catch (Exception e) {\n         throw new RuntimeException(e);\n      }\n   }\n\n   static void setSlf4jLogLevel(final Class<?> clazz, final Level logLevel)\n   {\n      try {\n         Log4jLogger log4Jlogger = (Log4jLogger) LoggerFactory.getLogger(clazz);\n\n         Field field = clazz.getClassLoader().loadClass(\"org.apache.logging.slf4j.Log4jLogger\").getDeclaredField(\"logger\");\n         field.setAccessible(true);\n\n         Logger logger = (Logger) field.get(log4Jlogger);\n         logger.setLevel(logLevel);\n      }\n      catch (Exception e) {\n         throw new RuntimeException(e);\n      }\n   }\n\n   public static HikariConfig newHikariConfig()\n   {\n      final StackTraceElement callerStackTrace = Thread.currentThread().getStackTrace()[2];\n\n      String poolName = callerStackTrace.getMethodName();\n      if (\"setup\".equals(poolName)) {\n         poolName = callerStackTrace.getClassName();\n      }\n\n      final HikariConfig config = new HikariConfig();\n      config.setPoolName(poolName);\n      return config;\n   }\n\n   static HikariDataSource newHikariDataSource()\n   {\n      final StackTraceElement callerStackTrace = Thread.currentThread().getStackTrace()[2];\n\n      String poolName = callerStackTrace.getMethodName();\n      if (\"setup\".equals(poolName)) {\n         poolName = callerStackTrace.getClassName();\n      }\n\n      final HikariDataSource ds = new HikariDataSource();\n      ds.setPoolName(poolName);\n      return ds;\n   }\n\n   private static class StringAppender extends AbstractAppender\n   {\n      private PrintStream stream;\n\n      StringAppender(final String name, final PrintStream stream)\n      {\n         super(name, null, CsvLogEventLayout.createDefaultLayout(), true, Property.EMPTY_ARRAY);\n         this.stream = stream;\n      }\n\n      @Override\n      public void append(final LogEvent event)\n      {\n         stream.println(event.getMessage().getFormattedMessage());\n      }\n   }\n\n   public static class FauxWebClassLoader extends ClassLoader\n   {\n      static final byte[] classBytes = new byte[16_000];\n\n      @Override\n      public Class<?> loadClass(final String name) throws ClassNotFoundException\n      {\n         if (name.startsWith(\"java\") || name.startsWith(\"org\")) {\n            return super.loadClass(name, true);\n         }\n\n         final String resourceName = \"/\" + name.replace('.', '/') + \".class\";\n         final URL resource = this.getClass().getResource(resourceName);\n         try (DataInputStream is = new DataInputStream(resource.openStream())) {\n            int read = 0;\n            while (read < classBytes.length) {\n               final int rc = is.read(classBytes, read, classBytes.length - read);\n               if (rc == -1) {\n                  break;\n               }\n               read += rc;\n            }\n\n            return defineClass(name, classBytes, 0, read);\n         }\n         catch (IOException e) {\n            throw new ClassNotFoundException(name);\n         }\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestHibernate.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.fail;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport org.hibernate.service.UnknownUnwrapTypeException;\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.hibernate.HikariConnectionProvider;\n\npublic class TestHibernate\n{\n   @Test\n   public void testConnectionProvider() throws Exception\n   {\n      HikariConnectionProvider provider = new HikariConnectionProvider();\n\n      Properties props = new Properties();\n      props.load(getClass().getResourceAsStream(\"/hibernate.properties\"));\n\n      provider.configure(props);\n      Connection connection = provider.getConnection();\n      provider.closeConnection(connection);\n\n      assertNotNull(provider.unwrap(HikariConnectionProvider.class));\n      assertFalse(provider.supportsAggressiveRelease());\n\n      try {\n         provider.unwrap(TestHibernate.class);\n         fail(\"Expected exception\");\n      }\n      catch (UnknownUnwrapTypeException e) {\n      }\n\n      provider.stop();\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestIsRunning.java",
    "content": "package com.zaxxer.hikari.pool;\r\n\r\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\r\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\r\nimport static com.zaxxer.hikari.pool.TestElf.newHikariDataSource;\r\nimport static org.junit.Assert.assertFalse;\r\nimport static org.junit.Assert.assertNull;\r\nimport static org.junit.Assert.assertTrue;\r\n\r\nimport java.util.concurrent.TimeUnit;\r\n\r\nimport org.junit.Test;\r\n\r\nimport com.zaxxer.hikari.HikariConfig;\r\nimport com.zaxxer.hikari.HikariDataSource;\r\n\r\n/**\r\n * Tests for {@link HikariDataSource#isRunning()}.\r\n */\r\npublic class TestIsRunning\r\n{\r\n    @Test\r\n    public void testRunningNormally()\r\n    {\r\n        try (HikariDataSource ds = new HikariDataSource(basicConfig()))\r\n        {\r\n            assertTrue(ds.isRunning());\r\n        }\r\n    }\r\n\r\n\r\n    @Test\r\n    public void testNoPool()\r\n    {\r\n        try (HikariDataSource ds = newHikariDataSource())\r\n        {\r\n            assertNull(\"Pool should not be initialized.\", getPool(ds));\r\n            assertFalse(ds.isRunning());\r\n        }\r\n    }\r\n\r\n\r\n    @Test\r\n    public void testSuspendAndResume()\r\n    {\r\n        try (HikariDataSource ds = new HikariDataSource(basicConfig()))\r\n        {\r\n            ds.getHikariPoolMXBean().suspendPool();\r\n            assertFalse(ds.isRunning());\r\n\r\n            ds.getHikariPoolMXBean().resumePool();\r\n            assertTrue(ds.isRunning());\r\n        }\r\n    }\r\n\r\n\r\n    @Test\r\n    public void testShutdown()\r\n    {\r\n        try (HikariDataSource ds = new HikariDataSource(basicConfig()))\r\n        {\r\n            ds.close();\r\n            assertFalse(ds.isRunning());\r\n        }\r\n    }\r\n\r\n\r\n    private HikariConfig basicConfig()\r\n    {\r\n        HikariConfig config = newHikariConfig();\r\n        config.setMinimumIdle(1);\r\n        config.setMaximumPoolSize(1);\r\n        config.setConnectionTestQuery(\"VALUES 1\");\r\n        config.setConnectionInitSql(\"SELECT 1\");\r\n        config.setReadOnly(true);\r\n        config.setConnectionTimeout(2500);\r\n        config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(30));\r\n        config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\r\n        config.setAllowPoolSuspension(true);\r\n\r\n        return config;\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestJNDI.java",
    "content": "/*\n * Copyright (C) 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.HikariJNDIFactory;\nimport com.zaxxer.hikari.mocks.StubDataSource;\nimport org.junit.Test;\nimport org.osjava.sj.jndi.AbstractContext;\n\nimport javax.naming.*;\nimport java.sql.Connection;\n\nimport static com.zaxxer.hikari.pool.TestElf.getUnsealedConfig;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.junit.Assert.*;\n\npublic class TestJNDI\n{\n   @Test\n   public void testJndiLookup1() throws Exception\n   {\n      HikariJNDIFactory jndi = new HikariJNDIFactory();\n      Reference ref = new Reference(\"javax.sql.DataSource\");\n      ref.add(new BogusRef(\"driverClassName\", \"com.zaxxer.hikari.mocks.StubDriver\"));\n      ref.add(new BogusRef(\"jdbcUrl\", \"jdbc:stub\"));\n      ref.add(new BogusRef(\"username\", \"foo\"));\n      ref.add(new BogusRef(\"password\", \"foo\"));\n      ref.add(new BogusRef(\"minimumIdle\", \"0\"));\n      ref.add(new BogusRef(\"maxLifetime\", \"30000\"));\n      ref.add(new BogusRef(\"maximumPoolSize\", \"10\"));\n      ref.add(new BogusRef(\"dataSource.loginTimeout\", \"10\"));\n      Context nameCtx = new BogusContext();\n\n      try (HikariDataSource ds = (HikariDataSource) jndi.getObjectInstance(ref, null, nameCtx, null)) {\n         assertNotNull(ds);\n         assertEquals(\"foo\", getUnsealedConfig(ds).getUsername());\n      }\n   }\n\n   @Test\n   public void testJndiLookup2() throws Exception\n   {\n      HikariJNDIFactory jndi = new HikariJNDIFactory();\n      Reference ref = new Reference(\"javax.sql.DataSource\");\n      ref.add(new BogusRef(\"dataSourceJNDI\", \"java:comp/env/HikariDS\"));\n      ref.add(new BogusRef(\"driverClassName\", \"com.zaxxer.hikari.mocks.StubDriver\"));\n      ref.add(new BogusRef(\"jdbcUrl\", \"jdbc:stub\"));\n      ref.add(new BogusRef(\"username\", \"foo\"));\n      ref.add(new BogusRef(\"password\", \"foo\"));\n      ref.add(new BogusRef(\"minimumIdle\", \"0\"));\n      ref.add(new BogusRef(\"maxLifetime\", \"30000\"));\n      ref.add(new BogusRef(\"maximumPoolSize\", \"10\"));\n      ref.add(new BogusRef(\"dataSource.loginTimeout\", \"10\"));\n      Context nameCtx = new BogusContext2();\n\n      try (HikariDataSource ds = (HikariDataSource) jndi.getObjectInstance(ref, null, nameCtx, null)) {\n         assertNotNull(ds);\n         assertEquals(\"foo\", getUnsealedConfig(ds).getUsername());\n      }\n   }\n\n   @Test\n   public void testJndiLookup3() throws Exception\n   {\n      HikariJNDIFactory jndi = new HikariJNDIFactory();\n\n      Reference ref = new Reference(\"javax.sql.DataSource\");\n      ref.add(new BogusRef(\"dataSourceJNDI\", \"java:comp/env/HikariDS\"));\n      try {\n         jndi.getObjectInstance(ref, null, null, null);\n         fail();\n      }\n      catch (RuntimeException e) {\n         assertTrue(e.getMessage().contains(\"JNDI context does not found\"));\n      }\n   }\n\n   @Test\n   public void testJndiLookup4() throws Exception\n   {\n      System.setProperty(Context.INITIAL_CONTEXT_FACTORY, \"org.osjava.sj.memory.MemoryContextFactory\");\n      System.setProperty(\"org.osjava.sj.jndi.shared\", \"true\");\n      InitialContext ic = new InitialContext();\n\n      StubDataSource ds = new StubDataSource();\n\n      Context subcontext = ic.createSubcontext(\"java:/comp/env/jdbc\");\n      subcontext.bind(\"java:/comp/env/jdbc/myDS\", ds);\n\n      HikariConfig config = newHikariConfig();\n      config.setDataSourceJNDI(\"java:/comp/env/jdbc/myDS\");\n\n      try (HikariDataSource hds = new HikariDataSource(config);\n           Connection conn = hds.getConnection()) {\n         assertNotNull(conn);\n      }\n   }\n\n   @SuppressWarnings(\"unchecked\")\n   private class BogusContext extends AbstractContext\n   {\n      @Override\n      public Context createSubcontext(Name name)\n      {\n         return null;\n      }\n\n      @Override\n      public Object lookup(String name)\n      {\n         final HikariDataSource ds = new HikariDataSource();\n         ds.setPoolName(\"TestJNDI\");\n         return ds;\n      }\n   }\n\n   @SuppressWarnings(\"unchecked\")\n   private class BogusContext2 extends AbstractContext\n   {\n      @Override\n      public Context createSubcontext(Name name)\n      {\n         return null;\n      }\n\n      @Override\n      public Object lookup(String name)\n      {\n         return new StubDataSource();\n      }\n   }\n\n   private class BogusRef extends RefAddr\n   {\n      private static final long serialVersionUID = 1L;\n\n      private String content;\n      BogusRef(String type, String content)\n      {\n         super(type);\n         this.content = content;\n      }\n\n      @Override\n      public Object getContent()\n      {\n         return content;\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestJavassistCodegen.java",
    "content": "package com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport com.zaxxer.hikari.pool.TestElf.FauxWebClassLoader;\nimport com.zaxxer.hikari.util.JavassistProxyFactory;\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.sql.Connection;\nimport java.sql.Statement;\nimport java.util.stream.Stream;\n\npublic class TestJavassistCodegen {\n   @Test\n   public void testCodegen() throws Exception {\n      String tmp = System.getProperty(\"java.io.tmpdir\");\n      JavassistProxyFactory.main(tmp);\n\n      Path base = Paths.get(tmp, \"target/classes/com/zaxxer/hikari/pool\".split(\"/\"));\n      Assert.assertTrue(\"\", Files.isRegularFile(base.resolve(\"HikariProxyConnection.class\")));\n      Assert.assertTrue(\"\", Files.isRegularFile(base.resolve(\"HikariProxyStatement.class\")));\n      Assert.assertTrue(\"\", Files.isRegularFile(base.resolve(\"HikariProxyCallableStatement.class\")));\n      Assert.assertTrue(\"\", Files.isRegularFile(base.resolve(\"HikariProxyPreparedStatement.class\")));\n      Assert.assertTrue(\"\", Files.isRegularFile(base.resolve(\"HikariProxyResultSet.class\")));\n      Assert.assertTrue(\"\", Files.isRegularFile(base.resolve(\"ProxyFactory.class\")));\n\n      FauxWebClassLoader fauxClassLoader = new FauxWebClassLoader();\n\n      int mod = fauxClassLoader.loadClass(\"com.zaxxer.hikari.pool.HikariProxyConnection\").getModifiers();\n      Assert.assertTrue(\"Generated proxy class should be public\", Modifier.isPublic(mod));\n      Assert.assertTrue(\"Generated proxy class should be final\", Modifier.isFinal(mod));\n\n      Class<?> proxyFactoryClass = fauxClassLoader.loadClass(\"com.zaxxer.hikari.pool.ProxyFactory\");\n\n      Connection connection = new StubConnection();\n\n      Class<?> fastListClass = fauxClassLoader.loadClass(\"com.zaxxer.hikari.util.FastList\");\n      Object fastList = fastListClass.getConstructor(Class.class).newInstance(Statement.class);\n\n      Object proxyConnection = getMethod(proxyFactoryClass, \"getProxyConnection\")\n         .invoke(null,\n            null /*poolEntry*/,\n            connection,\n            fastList,\n            null /*leakTask*/,\n            Boolean.FALSE /*isReadOnly*/,\n            Boolean.FALSE /*isAutoCommit*/);\n      Assert.assertNotNull(proxyConnection);\n\n      Object proxyStatement = getMethod(proxyConnection.getClass(), \"createStatement\", 0)\n         .invoke(proxyConnection);\n      Assert.assertNotNull(proxyStatement);\n   }\n\n   private Method getMethod(Class<?> clazz, String methodName, Integer... parameterCount)\n   {\n      return Stream.of(clazz.getDeclaredMethods())\n          .filter(method -> method.getName().equals(methodName))\n          .filter(method -> (parameterCount.length == 0 || parameterCount[0] == method.getParameterCount()))\n          .peek(method -> method.setAccessible(true))\n          .findFirst()\n          .orElseThrow(RuntimeException::new);\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestMBean.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariConfigMXBean;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.HikariPoolMXBean;\nimport com.zaxxer.hikari.mocks.StubDataSource;\nimport com.zaxxer.hikari.util.Credentials;\nimport org.junit.Test;\n\nimport javax.management.JMX;\nimport javax.management.MBeanServer;\nimport javax.management.MalformedObjectNameException;\nimport javax.management.ObjectName;\nimport java.lang.management.ManagementFactory;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.zaxxer.hikari.pool.TestElf.getUnsealedConfig;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\npublic class TestMBean\n{\n   @Test\n   public void testMBeanRegistration() {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setRegisterMbeans(true);\n      config.setConnectionTimeout(2800);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      new HikariDataSource(config).close();\n   }\n\n   @Test\n   public void testMBeanReporting() throws SQLException, InterruptedException, MalformedObjectNameException {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(5);\n      config.setRegisterMbeans(true);\n      config.setConnectionTimeout(2800);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"100\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n\n         TimeUnit.SECONDS.sleep(1);\n\n         getUnsealedConfig(ds).setIdleTimeout(3000);\n\n         MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();\n         ObjectName poolName = new ObjectName(\"com.zaxxer.hikari:type=Pool (testMBeanReporting)\");\n         HikariPoolMXBean hikariPoolMXBean = JMX.newMXBeanProxy(mBeanServer, poolName, HikariPoolMXBean.class);\n\n         assertEquals(0, hikariPoolMXBean.getActiveConnections());\n         assertEquals(3, hikariPoolMXBean.getIdleConnections());\n\n         try (Connection ignored = ds.getConnection()) {\n            assertEquals(1, hikariPoolMXBean.getActiveConnections());\n\n            TimeUnit.SECONDS.sleep(1);\n\n            assertEquals(3, hikariPoolMXBean.getIdleConnections());\n            assertEquals(4, hikariPoolMXBean.getTotalConnections());\n         }\n\n         TimeUnit.SECONDS.sleep(3);\n\n         assertEquals(0, hikariPoolMXBean.getActiveConnections());\n         assertEquals(3, hikariPoolMXBean.getIdleConnections());\n         assertEquals(3, hikariPoolMXBean.getTotalConnections());\n      }\n      finally {\n         System.clearProperty(\"com.zaxxer.hikari.housekeeping.periodMs\");\n      }\n\n      System.setProperty(\"hikaricp.jmx.register2.0\", \"true\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n\n         getUnsealedConfig(ds).setIdleTimeout(3000);\n\n         TimeUnit.SECONDS.sleep(1);\n\n         MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();\n         ObjectName poolName = new ObjectName(\"com.zaxxer.hikari:type=Pool,name=testMBeanReporting\");\n         HikariPoolMXBean hikariPoolMXBean = JMX.newMXBeanProxy(mBeanServer, poolName, HikariPoolMXBean.class);\n\n         assertEquals(0, hikariPoolMXBean.getActiveConnections());\n         assertEquals(3, hikariPoolMXBean.getIdleConnections());\n      }\n      finally {\n         System.clearProperty(\"hikaricp.jmx.register2.0\");\n      }\n   }\n\n   @Test\n   public void testMBeanChange() {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(5);\n      config.setRegisterMbeans(true);\n      config.setConnectionTimeout(2800);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariConfigMXBean hikariConfigMXBean = ds.getHikariConfigMXBean();\n         hikariConfigMXBean.setIdleTimeout(3000);\n\n         assertEquals(3000, ds.getIdleTimeout());\n      }\n   }\n\n   @Test\n   public void testMBeanConnectionTimeoutChange() throws SQLException {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(1);\n      config.setMaximumPoolSize(2);\n      config.setRegisterMbeans(true);\n      config.setConnectionTimeout(2800);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"250\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariConfigMXBean hikariConfigMXBean = ds.getHikariConfigMXBean();\n         assertEquals(2800, hikariConfigMXBean.getConnectionTimeout());\n\n         final StubDataSource stubDataSource = ds.unwrap(StubDataSource.class);\n         // connection acquisition takes more than 0 ms in a real system\n         stubDataSource.setConnectionAcquisitionTime(1200);\n\n         hikariConfigMXBean.setConnectionTimeout(1000);\n\n         quietlySleep(500);\n\n         try (Connection conn1 = ds.getConnection();\n              Connection conn2 = ds.getConnection()) {\n            fail(\"Connection should have timed out.\");\n         }\n         catch (SQLException e) {\n            assertEquals(1000, ds.getConnectionTimeout());\n         }\n      }\n      finally {\n         System.clearProperty(\"com.zaxxer.hikari.housekeeping.periodMs\");\n      }\n   }\n\n   @Test\n   public void testMBeanCredentialRotation() {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(3);\n      config.setMaximumPoolSize(5);\n      config.setRegisterMbeans(true);\n      config.setConnectionTimeout(2800);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setCredentials(Credentials.of(\"foo\", \"bar\"));\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         HikariConfigMXBean hikariConfigMXBean = ds.getHikariConfigMXBean();\n         hikariConfigMXBean.setCredentials(Credentials.of(\"newFoo\", \"newBar\"));\n\n         assertEquals(\"newFoo\", ds.getUsername());\n         assertEquals(\"newBar\", ds.getPassword());\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestMetrics.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariDataSource;\nimport org.junit.Test;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariDataSource;\n\n/**\n * Test HikariCP metrics integration.\n *\n * @author Brett Wooldridge\n */\npublic class TestMetrics\n{\n   @Test(expected = IllegalArgumentException.class)\n   public void testFakeMetricRegistryThrowsIllegalArgumentException()\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         FakeMetricRegistry metricRegistry = new FakeMetricRegistry();\n\n         ds.setMetricRegistry(metricRegistry);\n      }\n   }\n\n   private static class FakeMetricRegistry {}\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestMetricsBase.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.SortedMap;\nimport java.util.concurrent.TimeUnit;\n\nimport com.codahale.metrics.Histogram;\nimport com.codahale.metrics.Metric;\nimport com.codahale.metrics.MetricFilter;\nimport com.codahale.metrics.MetricRegistry;\nimport com.codahale.metrics.Timer;\nimport com.codahale.metrics.health.HealthCheck.Result;\nimport com.codahale.metrics.health.HealthCheckRegistry;\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.metrics.MetricsTrackerFactory;\nimport com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory;\nimport com.zaxxer.hikari.util.UtilityElf;\nimport org.junit.Test;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariDataSource;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\nimport static org.junit.Assume.assumeFalse;\n\n/**\n * Test HikariCP/CodaHale/Dropwizard 5 metrics integration.\n *\n * <p>\n * This base test class contains tests common to Codahale metrics testing (pre-5) and Dropwizard 5 metrics testing.\n * That's the idea behind the registry type parameterization and abstract methods.\n * Include health checks when implemented for Dropwizard 5.\n * There's still a bit of duplication between the extending classes.\n *\n * @author Brett Wooldridge\n */\nabstract class TestMetricsBase<M>\n{\n   protected abstract MetricsTrackerFactory metricsTrackerFactory(M metricRegistry);\n   protected abstract M metricRegistry();\n\n   @Test\n   public void testSetters3() throws Exception\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         M metricRegistry = metricRegistry();\n         MetricsTrackerFactory metricsTrackerFactory = metricsTrackerFactory(metricRegistry);\n\n         try (Connection connection = ds.getConnection()) {\n\n            // After the pool as started, we can only set them once...\n            ds.setMetricsTrackerFactory(metricsTrackerFactory);\n\n            // and never again...\n            ds.setMetricsTrackerFactory(metricsTrackerFactory);\n            fail(\"Should not have been allowed to set metricsTrackerFactory after pool started\");\n         }\n         catch (IllegalStateException ise) {\n            // pass\n            try {\n               // and never again... (even when calling another method)\n               ds.setMetricRegistry(metricRegistry);\n               fail(\"Should not have been allowed to set registry after pool started\");\n            }\n            catch (IllegalStateException ise2) {\n               // pass\n            }\n         }\n      }\n   }\n\n   @Test\n   public void testSetters4() throws Exception\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         M metricRegistry = metricRegistry();\n\n         // before the pool is started, we can set it any number of times using either setter\n         ds.setMetricRegistry(metricRegistry);\n         ds.setMetricRegistry(metricRegistry);\n         ds.setMetricRegistry(metricRegistry);\n\n         try (Connection connection = ds.getConnection()) {\n\n            // after the pool is started, we cannot set it any more\n            ds.setMetricRegistry(metricRegistry);\n            fail(\"Should not have been allowed to set registry after pool started\");\n         }\n         catch (IllegalStateException ise) {\n            // pass\n         }\n      }\n   }\n\n   @Test\n   public void testSetters5() throws Exception\n   {\n      try (HikariDataSource ds = newHikariDataSource()) {\n         ds.setMaximumPoolSize(1);\n         ds.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n         M metricRegistry = metricRegistry();\n         MetricsTrackerFactory metricsTrackerFactory = metricsTrackerFactory(metricRegistry);\n\n         // before the pool is started, we can set it any number of times using either setter\n         ds.setMetricsTrackerFactory(metricsTrackerFactory);\n         ds.setMetricsTrackerFactory(metricsTrackerFactory);\n         ds.setMetricsTrackerFactory(metricsTrackerFactory);\n\n         try (Connection connection = ds.getConnection()) {\n\n            // after the pool is started, we cannot set it any more\n            ds.setMetricsTrackerFactory(metricsTrackerFactory);\n            fail(\"Should not have been allowed to set registry factory after pool started\");\n         }\n         catch (IllegalStateException ise) {\n            // pass\n         }\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestPropertySetter.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertThrows;\nimport static org.junit.Assert.assertTrue;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintWriter;\nimport java.time.Duration;\nimport java.util.Properties;\nimport java.util.Set;\n\nimport javax.sql.DataSource;\n\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.util.PropertyElf;\n\npublic class TestPropertySetter\n{\n   @Test\n   public void testProperty1() throws Exception\n   {\n      Properties propfile1 = new Properties();\n      propfile1.load(TestPropertySetter.class.getResourceAsStream(\"/propfile1.properties\"));\n      HikariConfig config = new HikariConfig(propfile1);\n      config.validate();\n\n      assertEquals(5, config.getMinimumIdle());\n      assertEquals(\"SELECT 1\", config.getConnectionTestQuery());\n   }\n\n   @Test\n   public void testProperty2() throws Exception\n   {\n      Properties propfile2 = new Properties();\n      propfile2.load(TestPropertySetter.class.getResourceAsStream(\"/propfile2.properties\"));\n      HikariConfig config = new HikariConfig(propfile2);\n      config.validate();\n\n      Class<?> clazz = this.getClass().getClassLoader().loadClass(config.getDataSourceClassName());\n      DataSource dataSource = (DataSource) clazz.getDeclaredConstructor().newInstance();\n      PropertyElf.setTargetFromProperties(dataSource, config.getDataSourceProperties());\n   }\n\n   @Test\n   public void testObjectProperty() throws Exception\n   {\n      HikariConfig config = newHikariConfig();\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      PrintWriter writer = new PrintWriter(new ByteArrayOutputStream());\n      config.addDataSourceProperty(\"logWriter\", writer);\n\n      Class<?> clazz = this.getClass().getClassLoader().loadClass(config.getDataSourceClassName());\n      DataSource dataSource = (DataSource) clazz.getDeclaredConstructor().newInstance();\n      PropertyElf.setTargetFromProperties(dataSource, config.getDataSourceProperties());\n\n      assertSame(PrintWriter.class, dataSource.getLogWriter().getClass());\n   }\n\n   @Test\n   public void testPropertyUpperCase() throws Exception\n   {\n      Properties propfile3 = new Properties();\n      propfile3.load(TestPropertySetter.class.getResourceAsStream(\"/propfile3.properties\"));\n      HikariConfig config = new HikariConfig(propfile3);\n      config.validate();\n\n      Class<?> clazz = this.getClass().getClassLoader().loadClass(config.getDataSourceClassName());\n      DataSource dataSource = (DataSource) clazz.getDeclaredConstructor().newInstance();\n      PropertyElf.setTargetFromProperties(dataSource, config.getDataSourceProperties());\n   }\n\n   @Test\n   public void testDurationPropertiesSet() throws Exception\n   {\n      Properties durationProperties = new Properties();\n      durationProperties.load(TestPropertySetter.class.getResourceAsStream(\"/duration-config.properties\"));\n      HikariConfig config = new HikariConfig(durationProperties);\n      config.validate();\n\n      assertEquals(Duration.ofMillis(2000), Duration.ofMillis(config.getConnectionTimeout()));\n      assertEquals(Duration.ofSeconds(22), Duration.ofMillis(config.getValidationTimeout()));\n      assertEquals(Duration.ofMinutes(33), Duration.ofMillis(config.getIdleTimeout()));\n      assertEquals(Duration.ofHours(44), Duration.ofMillis(config.getLeakDetectionThreshold()));\n      assertEquals(Duration.ofDays(55), Duration.ofMillis(config.getMaxLifetime()));\n\n      Class<?> clazz = this.getClass().getClassLoader().loadClass(config.getDataSourceClassName());\n      DataSource dataSource = (DataSource) clazz.getDeclaredConstructor().newInstance();\n      PropertyElf.setTargetFromProperties(dataSource, config.getDataSourceProperties());\n\n      assertEquals(Duration.ofMinutes(1), Duration.ofMillis(dataSource.getLoginTimeout()));\n   }\n\n   @Test\n   public void testGetPropertyNames() throws Exception\n   {\n      Set<String> propertyNames = PropertyElf.getPropertyNames(HikariConfig.class);\n      assertTrue(propertyNames.contains(\"dataSourceClassName\"));\n   }\n\n   @Test\n   public void testSetNonExistantPropertyName() throws Exception\n   {\n      RuntimeException e = assertThrows(RuntimeException.class, () -> {\n         Properties props = new Properties();\n         props.put(\"what\", \"happened\");\n         PropertyElf.setTargetFromProperties(new HikariConfig(), props);\n      });\n      assertEquals(\"Property what does not exist on target class com.zaxxer.hikari.HikariConfig\", e.getMessage());\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestProxies.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.concurrent.TimeUnit;\n\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport com.zaxxer.hikari.mocks.StubStatement;\n\npublic class TestProxies\n{\n   @Test\n   public void testProxyCreation() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         Connection conn = ds.getConnection();\n\n         assertNotNull(conn.createStatement(ResultSet.FETCH_FORWARD, ResultSet.TYPE_SCROLL_INSENSITIVE));\n         assertNotNull(conn.createStatement(ResultSet.FETCH_FORWARD, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.HOLD_CURSORS_OVER_COMMIT));\n         assertNotNull(conn.prepareCall(\"some sql\"));\n         assertNotNull(conn.prepareCall(\"some sql\", ResultSet.FETCH_FORWARD, ResultSet.TYPE_SCROLL_INSENSITIVE));\n         assertNotNull(conn.prepareCall(\"some sql\", ResultSet.FETCH_FORWARD, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.HOLD_CURSORS_OVER_COMMIT));\n         assertNotNull(conn.prepareStatement(\"some sql\", PreparedStatement.NO_GENERATED_KEYS));\n         assertNotNull(conn.prepareStatement(\"some sql\", new int[3]));\n         assertNotNull(conn.prepareStatement(\"some sql\", new String[3]));\n         assertNotNull(conn.prepareStatement(\"some sql\", ResultSet.FETCH_FORWARD, ResultSet.TYPE_SCROLL_INSENSITIVE));\n         assertNotNull(conn.prepareStatement(\"some sql\", ResultSet.FETCH_FORWARD, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.HOLD_CURSORS_OVER_COMMIT));\n         assertNotNull(conn.toString());\n\n         assertTrue(conn.isWrapperFor(Connection.class));\n         assertTrue(conn.isValid(10));\n         assertFalse(conn.isClosed());\n         assertTrue(conn.unwrap(StubConnection.class) instanceof StubConnection);\n         try {\n            conn.unwrap(TestProxies.class);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n      }\n   }\n\n   @Test\n   public void testStatementProxy() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         Connection conn = ds.getConnection();\n\n         PreparedStatement stmt = conn.prepareStatement(\"some sql\");\n         stmt.executeQuery();\n         stmt.executeQuery(\"some sql\");\n         assertFalse(stmt.isClosed());\n         assertNotNull(stmt.getGeneratedKeys());\n         assertNotNull(stmt.getResultSet());\n         assertNotNull(stmt.getConnection());\n         assertTrue(stmt.unwrap(StubStatement.class) instanceof StubStatement);\n         try {\n            stmt.unwrap(TestProxies.class);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n      }\n   }\n\n   @Test\n   public void testStatementExceptions() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(1));\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         Connection conn = ds.getConnection();\n         StubConnection stubConnection = conn.unwrap(StubConnection.class);\n         stubConnection.throwException = true;\n\n         try {\n            conn.createStatement();\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.createStatement(0, 0);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.createStatement(0, 0, 0);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareCall(\"\");\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareCall(\"\", 0, 0);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareCall(\"\", 0, 0, 0);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareStatement(\"\");\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareStatement(\"\", 0);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareStatement(\"\", new int[0]);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareStatement(\"\", new String[0]);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareStatement(\"\", 0, 0);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n\n         try {\n            conn.prepareStatement(\"\", 0, 0, 0);\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n      }\n   }\n\n   @Test\n   public void testOtherExceptions() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setConnectionTestQuery(\"VALUES 1\");\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         try (Connection conn = ds.getConnection()) {\n            StubConnection stubConnection = conn.unwrap(StubConnection.class);\n            stubConnection.throwException = true;\n\n            try {\n               conn.setTransactionIsolation(Connection.TRANSACTION_NONE);\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.isReadOnly();\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.setReadOnly(false);\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.setCatalog(\"\");\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.setAutoCommit(false);\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.clearWarnings();\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.isValid(0);\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.isWrapperFor(getClass());\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.unwrap(getClass());\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               conn.close();\n               fail();\n            }\n            catch (SQLException e) {\n               // pass\n            }\n\n            try {\n               assertFalse(conn.isValid(0));\n            }\n            catch (SQLException e) {\n               fail();\n            }\n         }\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestSaturatedPool830.java",
    "content": "/*\n * Copyright (C) 2017 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jLogLevel;\nimport static com.zaxxer.hikari.util.ClockSource.currentTime;\nimport static com.zaxxer.hikari.util.ClockSource.elapsedMillis;\nimport static com.zaxxer.hikari.util.UtilityElf.quietlySleep;\nimport static java.util.concurrent.TimeUnit.SECONDS;\nimport static org.junit.Assert.assertEquals;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.Arrays;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport org.apache.logging.log4j.Level;\nimport org.junit.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport com.zaxxer.hikari.mocks.StubStatement;\n\n/**\n * @author Brett Wooldridge\n */\npublic class TestSaturatedPool830\n{\n   private static final Logger LOGGER = LoggerFactory.getLogger(TestSaturatedPool830.class);\n   private static final int MAX_POOL_SIZE = 10;\n\n   @Test\n   public void saturatedPoolTest() throws Exception {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(5);\n      config.setMaximumPoolSize(MAX_POOL_SIZE);\n      config.setInitializationFailTimeout(Long.MAX_VALUE);\n      config.setConnectionTimeout(1000);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      StubConnection.slowCreate = true;\n      StubStatement.setSimulatedQueryTime(1000);\n      setSlf4jLogLevel(HikariPool.class, Level.DEBUG);\n      System.setProperty(\"com.zaxxer.hikari.housekeeping.periodMs\", \"5000\");\n\n      final long start = currentTime();\n\n      try (final HikariDataSource ds = new HikariDataSource(config)) {\n         LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();\n         ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 50 /*core*/, 50 /*max*/, 2 /*keepalive*/, SECONDS, queue, new ThreadPoolExecutor.CallerRunsPolicy());\n         threadPool.allowCoreThreadTimeOut(true);\n\n         AtomicInteger windowIndex = new AtomicInteger();\n         boolean[] failureWindow = new boolean[100];\n         Arrays.fill(failureWindow, true);\n\n         // Initial saturation\n         for (int i = 0; i < 50; i++) {\n            threadPool.execute(() -> {\n               try (Connection conn = ds.getConnection();\n                    Statement stmt = conn.createStatement()) {\n                  stmt.execute(\"SELECT bogus FROM imaginary\");\n               }\n               catch (SQLException e) {\n                  LOGGER.info(e.getMessage());\n               }\n            });\n         }\n\n         long sleep = 80;\nouter:   while (true) {\n            quietlySleep(sleep);\n\n            if (elapsedMillis(start) > SECONDS.toMillis(12) && sleep < 100) {\n               sleep = 100;\n               LOGGER.warn(\"Switching to 100ms sleep\");\n            }\n            else if (elapsedMillis(start) > SECONDS.toMillis(6) && sleep < 90) {\n               sleep = 90;\n               LOGGER.warn(\"Switching to 90ms sleep\");\n            }\n\n            threadPool.execute(() -> {\n               int ndx = windowIndex.incrementAndGet() % failureWindow.length;\n\n               try (Connection conn = ds.getConnection();\n                    Statement stmt = conn.createStatement()) {\n                  stmt.execute(\"SELECT bogus FROM imaginary\");\n                  failureWindow[ndx] = false;\n               }\n               catch (SQLException e) {\n                  LOGGER.info(e.getMessage());\n                  failureWindow[ndx] = true;\n               }\n            });\n\n            for (int i = 0; i < failureWindow.length; i++) {\n               if (failureWindow[i]) {\n                  if (elapsedMillis(start) % (SECONDS.toMillis(1) - sleep) < sleep) {\n                     LOGGER.info(\"Active threads {}, submissions per second {}, waiting threads {}\",\n                                 threadPool.getActiveCount(),\n                                 SECONDS.toMillis(1) / sleep,\n                                 getPool(ds).getThreadsAwaitingConnection());\n                  }\n                  continue outer;\n               }\n            }\n\n            LOGGER.info(\"Timeouts have subsided.\");\n            LOGGER.info(\"Active threads {}, submissions per second {}, waiting threads {}\",\n                        threadPool.getActiveCount(),\n                        SECONDS.toMillis(1) / sleep,\n                        getPool(ds).getThreadsAwaitingConnection());\n            break;\n         }\n\n         LOGGER.info(\"Waiting for completion of {} active tasks.\", threadPool.getActiveCount());\n         while (getPool(ds).getActiveConnections() > 0) {\n            quietlySleep(50);\n         }\n\n         assertEquals(\"Rate not in balance at 10req/s\", 10L, SECONDS.toMillis(1) / sleep);\n      }\n      finally {\n         StubStatement.setSimulatedQueryTime(0);\n         StubConnection.slowCreate = false;\n         System.clearProperty(\"com.zaxxer.hikari.housekeeping.periodMs\");\n         setSlf4jLogLevel(HikariPool.class, Level.INFO);\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestStates.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.pool;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport org.junit.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static org.junit.Assert.fail;\n\n/**\n * @author Yanming Zhou\n */\npublic class TestStates\n{\n   @Test\n   public void testGetBeforeSet() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         Connection conn = ds.getConnection();\n         StubConnection stub = conn.unwrap(StubConnection.class);\n         stub.throwException = true;\n         try {\n            conn.isReadOnly();\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n         try {\n            conn.getAutoCommit();\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n         try {\n            conn.getTransactionIsolation();\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n         try {\n            conn.getCatalog();\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n         try {\n            conn.getNetworkTimeout();\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n         try {\n            conn.getSchema();\n            fail();\n         }\n         catch (SQLException e) {\n            // pass\n         }\n      }\n   }\n\n   @Test\n   public void testGetAfterSet() throws SQLException\n   {\n      HikariConfig config = newHikariConfig();\n      config.setMinimumIdle(0);\n      config.setMaximumPoolSize(1);\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n      try (HikariDataSource ds = new HikariDataSource(config)) {\n         Connection conn = ds.getConnection();\n         StubConnection stub = conn.unwrap(StubConnection.class);\n\n         conn.setReadOnly(true);\n         conn.setAutoCommit(true);\n         conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);\n         conn.setCatalog(\"catalog\");\n         conn.setNetworkTimeout(null, 10);\n         conn.setSchema(\"schema\");\n\n         stub.throwException = true;\n\n         // should not throw exception even if stub throws exception\n         conn.isReadOnly();\n         conn.getAutoCommit();\n         conn.getTransactionIsolation();\n         conn.getCatalog();\n         conn.getNetworkTimeout();\n         conn.getSchema();\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/TestValidation.java",
    "content": "/*\n * Copyright (C) 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.setSlf4jTargetStream;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport java.util.concurrent.TimeUnit;\n\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\n\n/**\n * @author Brett Wooldridge\n */\npublic class TestValidation\n{\n   @Test\n   public void validateLoadProperties()\n   {\n      System.setProperty(\"hikaricp.configurationFile\", \"/propfile1.properties\");\n      HikariConfig config = newHikariConfig();\n      System.clearProperty(\"hikaricp.configurationFile\");\n      assertEquals(5, config.getMinimumIdle());\n   }\n\n   @Test\n   public void validateMissingProperties()\n   {\n      try {\n         HikariConfig config = new HikariConfig(\"missing\");\n         config.validate();\n      }\n      catch (IllegalArgumentException ise) {\n         assertTrue(ise.getMessage().contains(\"property file\"));\n      }\n   }\n\n   @Test\n   public void validateMissingDS()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.validate();\n         fail();\n      }\n      catch (IllegalArgumentException ise) {\n         assertTrue(ise.getMessage().contains(\"dataSource or dataSourceClassName or jdbcUrl is required.\"));\n      }\n   }\n\n   @Test\n   public void validateMissingUrl()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setDriverClassName(\"com.zaxxer.hikari.mocks.StubDriver\");\n         config.validate();\n         fail();\n      }\n      catch (IllegalArgumentException ise) {\n         assertTrue(ise.getMessage().contains(\"jdbcUrl is required with driverClassName\"));\n      }\n   }\n\n   @Test\n   public void validateDriverAndUrl()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setDriverClassName(\"com.zaxxer.hikari.mocks.StubDriver\");\n         config.setJdbcUrl(\"jdbc:stub\");\n         config.validate();\n      }\n      catch (Throwable t) {\n          fail(t.getMessage());\n      }\n   }\n\n   @Test\n   public void validateBadDriver()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setDriverClassName(\"invalid\");\n         config.validate();\n         fail();\n      }\n      catch (RuntimeException ise) {\n         assertTrue(ise.getMessage().startsWith(\"Failed to load driver class invalid\"));\n      }\n   }\n\n   @Test\n   public void validateInvalidConnectionTimeout()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setConnectionTimeout(10L);\n         fail();\n      }\n      catch (IllegalArgumentException ise) {\n         assertTrue(ise.getMessage().contains(\"connectionTimeout cannot be less than 250ms\"));\n      }\n   }\n\n   @Test\n   public void validateInvalidValidationTimeout()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setValidationTimeout(10L);\n         fail();\n      }\n      catch (IllegalArgumentException ise) {\n         assertTrue(ise.getMessage().contains(\"validationTimeout cannot be less than 250ms\"));\n      }\n   }\n\n   @Test\n   public void validateInvalidIdleTimeout()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setIdleTimeout(-1L);\n         fail(\"negative idle timeout accepted\");\n      }\n      catch (IllegalArgumentException ise) {\n         assertTrue(ise.getMessage().contains(\"idleTimeout cannot be negative\"));\n      }\n   }\n\n   @Test\n   public void validateIdleTimeoutTooSmall()\n   {\n      ByteArrayOutputStream baos = new ByteArrayOutputStream();\n      PrintStream ps = new PrintStream(baos, true);\n      setSlf4jTargetStream(HikariConfig.class, ps);\n\n      HikariConfig config = newHikariConfig();\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setMinimumIdle(5);\n      config.setIdleTimeout(TimeUnit.SECONDS.toMillis(5));\n      config.validate();\n      assertTrue(new String(baos.toByteArray()).contains(\"less than 10000ms\"));\n   }\n\n   @Test\n   public void validateIdleTimeoutExceedsLifetime()\n   {\n      ByteArrayOutputStream baos = new ByteArrayOutputStream();\n      PrintStream ps = new PrintStream(baos, true);\n      setSlf4jTargetStream(HikariConfig.class, ps);\n\n      HikariConfig config = newHikariConfig();\n      config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n      config.setMinimumIdle(5);\n      config.setMaxLifetime(TimeUnit.MINUTES.toMillis(2));\n      config.setIdleTimeout(TimeUnit.MINUTES.toMillis(3));\n      config.validate();\n\n      String s = new String(baos.toByteArray());\n      assertTrue(\"idleTimeout is close to or more than maxLifetime, disabling it.\" + s + \"*\", s.contains(\"is close to or more than maxLifetime\"));\n   }\n\n   @Test\n   public void validateInvalidMinIdle()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setMinimumIdle(-1);\n         fail();\n      }\n      catch (IllegalArgumentException ise) {\n         assertTrue(ise.getMessage().contains(\"minimumIdle cannot be negative\"));\n      }\n   }\n\n   @Test\n   public void validateInvalidMaxPoolSize()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setMaximumPoolSize(0);\n         fail();\n      }\n      catch (IllegalArgumentException ise) {\n         assertTrue(ise.getMessage().contains(\"maxPoolSize cannot be less than 1\"));\n      }\n   }\n\n   @Test\n   public void validateInvalidLifetime()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setConnectionTimeout(Integer.MAX_VALUE);\n         config.setIdleTimeout(1000L);\n         config.setMaxLifetime(-1L);\n         config.setLeakDetectionThreshold(1000L);\n         config.validate();\n         fail();\n      }\n      catch (IllegalArgumentException ise) {\n         // pass\n      }\n   }\n\n   @Test\n   public void validateInvalidLeakDetection()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setLeakDetectionThreshold(1000L);\n         config.validate();\n         fail();\n      }\n      catch (IllegalArgumentException ise) {\n      // pass\n      }\n   }\n\n   @Test\n   public void validateZeroConnectionTimeout()\n   {\n      try {\n         HikariConfig config = newHikariConfig();\n         config.setConnectionTimeout(0);\n         config.validate();\n         assertEquals(Integer.MAX_VALUE, config.getConnectionTimeout());\n      }\n      catch (IllegalArgumentException ise) {\n         // pass\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/pool/UnwrapTest.java",
    "content": "/*\n * Copyright (C) 2013 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.pool;\n\nimport static com.zaxxer.hikari.pool.TestElf.newHikariConfig;\nimport static com.zaxxer.hikari.pool.TestElf.getPool;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport com.zaxxer.hikari.mocks.StubConnection;\nimport com.zaxxer.hikari.mocks.StubDataSource;\n\n/**\n * @author Brett Wooldridge\n */\npublic class UnwrapTest\n{\n    @Test\n    public void testUnwrapConnection() throws SQLException\n    {\n        HikariConfig config = newHikariConfig();\n        config.setMinimumIdle(1);\n        config.setMaximumPoolSize(1);\n        config.setInitializationFailTimeout(0);\n        config.setConnectionTestQuery(\"VALUES 1\");\n        config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n       try (HikariDataSource ds = new HikariDataSource(config)) {\n          ds.getConnection().close();\n          assertSame(\"Idle connections not as expected\", 1, getPool(ds).getIdleConnections());\n\n          Connection connection = ds.getConnection();\n          assertNotNull(connection);\n\n          StubConnection unwrapped = connection.unwrap(StubConnection.class);\n          assertTrue(\"unwrapped connection is not instance of StubConnection: \" + unwrapped, (unwrapped instanceof StubConnection));\n       }\n    }\n\n    @Test\n    public void testUnwrapDataSource() throws SQLException\n    {\n       HikariConfig config = newHikariConfig();\n       config.setMinimumIdle(1);\n       config.setMaximumPoolSize(1);\n       config.setInitializationFailTimeout(0);\n       config.setConnectionTestQuery(\"VALUES 1\");\n       config.setDataSourceClassName(\"com.zaxxer.hikari.mocks.StubDataSource\");\n\n       try (HikariDataSource ds = new HikariDataSource(config)) {\n          StubDataSource unwrap = ds.unwrap(StubDataSource.class);\n          assertNotNull(unwrap);\n          assertTrue(unwrap instanceof StubDataSource);\n\n          assertTrue(ds.isWrapperFor(HikariDataSource.class));\n          assertTrue(ds.unwrap(HikariDataSource.class) instanceof HikariDataSource);\n\n          assertFalse(ds.isWrapperFor(getClass()));\n          try {\n             ds.unwrap(getClass());\n          }\n          catch (SQLException e) {\n             assertTrue(e.getMessage().contains(\"Wrapped DataSource\"));\n          }\n       }\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/util/ClockSourceTest.java",
    "content": "/*\n * Copyright (C) 2016 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport static java.util.concurrent.TimeUnit.DAYS;\nimport static java.util.concurrent.TimeUnit.HOURS;\nimport static java.util.concurrent.TimeUnit.MICROSECONDS;\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\nimport static java.util.concurrent.TimeUnit.MINUTES;\nimport static java.util.concurrent.TimeUnit.NANOSECONDS;\nimport static java.util.concurrent.TimeUnit.SECONDS;\n\n/**\n *\n * @author Brett Wooldridge\n */\npublic class ClockSourceTest\n{\n   @Test\n   public void testClockSourceDisplay()\n   {\n      ClockSource msSource = new ClockSource.MillisecondClockSource();\n\n      final long sTime = DAYS.toMillis(3) + HOURS.toMillis(9) + MINUTES.toMillis(24) + SECONDS.toMillis(18) + MILLISECONDS.toMillis(572);\n\n      final long eTime = DAYS.toMillis(4) + HOURS.toMillis(9) + MINUTES.toMillis(55) + SECONDS.toMillis(23) + MILLISECONDS.toMillis(777);\n      String ds1 = msSource.elapsedDisplayString0(sTime, eTime);\n      Assert.assertEquals(\"1d31m5s205ms\", ds1);\n\n      final long eTime2 = DAYS.toMillis(3) + HOURS.toMillis(8) + MINUTES.toMillis(24) + SECONDS.toMillis(23) + MILLISECONDS.toMillis(777);\n      String ds2 = msSource.elapsedDisplayString0(sTime, eTime2);\n      Assert.assertEquals(\"-59m54s795ms\", ds2);\n\n\n      ClockSource nsSource = new ClockSource.NanosecondClockSource();\n\n      final long sTime2 = DAYS.toNanos(3) + HOURS.toNanos(9) + MINUTES.toNanos(24) + SECONDS.toNanos(18) + MILLISECONDS.toNanos(572) + MICROSECONDS.toNanos(324) + NANOSECONDS.toNanos(823);\n\n      final long eTime3 = DAYS.toNanos(4) + HOURS.toNanos(19) + MINUTES.toNanos(55) + SECONDS.toNanos(23) + MILLISECONDS.toNanos(777) + MICROSECONDS.toNanos(0) + NANOSECONDS.toNanos(982);\n      String ds3 = nsSource.elapsedDisplayString0(sTime2, eTime3);\n      Assert.assertEquals(\"1d10h31m5s204ms676µs159ns\", ds3);\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/util/DriverDataSourceTest.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.util;\n\nimport org.junit.Test;\n\nimport java.lang.reflect.Field;\nimport java.time.Duration;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Properties;\n\nimport static org.junit.Assert.*;\n\npublic class DriverDataSourceTest {\n\n   @Test\n   public void testDriverProperties() throws Exception {\n      Properties properties = new Properties();\n      Duration timeout = Duration.ofSeconds(60);\n      properties.put(\"timeout\", timeout);\n      var driverDataSource = new DriverDataSource(\"jdbc:h2:mem:test;DB_CLOSE_DELAY=-1\", null, properties, \"\", \"\");\n      Field field = DriverDataSource.class.getDeclaredField(\"driverProperties\");\n      field.setAccessible(true);\n      Properties driverProperties = (Properties) field.get(driverDataSource);\n      assertEquals(timeout, driverProperties.get(\"timeout\"));\n   }\n\n   @Test\n   public void testJdbcUrlLogging() {\n      List<String> urls = Arrays.asList(\n         \"jdbc:invalid://host/d_dlq?user=USER&password=SECRET\",\n         \"jdbc:invalid://host/d_dlq?user=USER&truststorePassword=SECRET\",\n         \"jdbc:invalid://host/d_dlq?a=b&password=SECRET&user=USER\",\n         \"jdbc:invalid://host/d_dlq?a=b&sslpassword=SECRET&user=USER\",\n         \"jdbc:invalid://host/d_dlq?a=b&sslpassword=SECRET&password=SECRET&user=USER\",\n         \"jdbc:invalid://host/d_dlq?truststorePassword=SECRET;user=USER&password=SECRET#extra\",\n         \"jdbc:invalid://host/d_dlq?sslpassword=SECRET&password=SECRET&trustPassword=SECRET&user=USER\",\n         \"jdbc:invalid://host/d_dlq?password=SECRET#user=USER;extra\"\n      );\n\n      for (String url : urls) {\n         testExceptionMessage(url);\n      }\n   }\n\n   private void testExceptionMessage(String jdbcUrl) {\n      try {\n         new DriverDataSource(jdbcUrl, null, new Properties(), null, null);\n         fail();\n      } catch (RuntimeException e) {\n         String msg = e.getMessage();\n         assertTrue(msg.contains(\"jdbc:invalid://host/d_dlq\"));\n         assertTrue(msg.contains(\"user=USER\"));\n         assertFalse(\"Exception message should not contain password\", msg.contains(\"SECRET\"));\n      }\n\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java",
    "content": "package com.zaxxer.hikari.util;\n\nimport org.junit.Test;\nimport com.zaxxer.hikari.mocks.TestObject;\n\nimport java.util.Properties;\n\nimport static org.junit.Assert.*;\n\npublic class PropertyElfTest\n{\n   @Test\n   public void setTargetFromProperties() throws Exception\n   {\n      Properties properties = new Properties();\n      properties.setProperty(\"string\", \"aString\");\n      properties.setProperty(\"testObject\", \"com.zaxxer.hikari.mocks.TestObject\");\n      properties.setProperty(\"shortRaw\", \"1\");\n      properties.setProperty(\"charArray\", \"aCharArray\");\n      TestObject testObject = new TestObject();\n      PropertyElf.setTargetFromProperties(testObject, properties);\n      assertEquals(\"aString\", testObject.getString());\n      assertEquals((short) 1, testObject.getShortRaw());\n      assertArrayEquals(\"aCharArray\".toCharArray(), testObject.getCharArray());\n      assertEquals(com.zaxxer.hikari.mocks.TestObject.class, testObject.getTestObject().getClass());\n      assertNotSame(testObject, testObject.getTestObject());\n   }\n\n   @Test\n   public void setTargetFromPropertiesNotAClass() throws Exception\n   {\n      Properties properties = new Properties();\n      properties.setProperty(\"string\", \"aString\");\n      properties.setProperty(\"testObject\", \"it is not a class\");\n      TestObject testObject = new TestObject();\n      try {\n         PropertyElf.setTargetFromProperties(testObject, properties);\n         fail(\"Could never come here\");\n      }\n      catch (RuntimeException e) {\n         assertEquals(\"argument type mismatch\", e.getCause().getMessage());\n      }\n   }\n\n   @Test\n   public void setStringArray()\n   {\n      Properties properties = new Properties();\n      TestObject testObject = new TestObject();\n\n      properties.setProperty(\"stringArray\", \"abc,123\");\n      PropertyElf.setTargetFromProperties(testObject, properties);\n      assertArrayEquals(new String[] {\"abc\", \"123\"}, testObject.getStringArray());\n\n      properties.setProperty(\"stringArray\", \"abc\\\\,123\");\n      PropertyElf.setTargetFromProperties(testObject, properties);\n      assertArrayEquals(new String[] {\"abc,123\"}, testObject.getStringArray());\n\n      properties.setProperty(\"stringArray\", \"abc\\\\\\\\,123\");\n      PropertyElf.setTargetFromProperties(testObject, properties);\n      assertArrayEquals(new String[] {\"abc\\\\\",\"123\"}, testObject.getStringArray());\n\n      properties.setProperty(\"stringArray\", \"\");\n      PropertyElf.setTargetFromProperties(testObject, properties);\n      assertArrayEquals(new String[] {}, testObject.getStringArray());\n\n      properties.setProperty(\"stringArray\", \"abc,12\\\\3\");\n      PropertyElf.setTargetFromProperties(testObject, properties);\n      assertArrayEquals(new String[] {\"abc\",\"123\"}, testObject.getStringArray());\n\n      properties.setProperty(\"stringArray\", \"abc,123\\\\\");\n      assertThrows(RuntimeException.class, () -> PropertyElf.setTargetFromProperties(testObject, properties));\n   }\n\n   @Test\n   public void setIntArray()\n   {\n      Properties properties = new Properties();\n      TestObject testObject = new TestObject();\n\n      properties.setProperty(\"intArray\", \"1,2,3\");\n      PropertyElf.setTargetFromProperties(testObject, properties);\n      assertArrayEquals(new int[] {1,2,3}, testObject.getIntArray());\n\n      properties.setProperty(\"intArray\", \"\");\n      PropertyElf.setTargetFromProperties(testObject, properties);\n      assertArrayEquals(new int[] {}, testObject.getIntArray());\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/util/TestFastList.java",
    "content": "/*\n * Copyright (C) 2013, 2014 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n*/\n\npackage com.zaxxer.hikari.util;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertSame;\n\nimport java.sql.Statement;\nimport java.util.ArrayList;\nimport java.util.Iterator;\n\nimport org.junit.Test;\n\nimport com.zaxxer.hikari.mocks.StubStatement;\n\npublic class TestFastList\n{\n    @Test\n    public void testAddRemove()\n    {\n        ArrayList<Statement> verifyList = new ArrayList<>();\n\n        FastList<Statement> list = new FastList<>(Statement.class);\n        for (int i = 0; i < 32; i++)\n        {\n            StubStatement statement = new StubStatement(null);\n            list.add(statement);\n            verifyList.add(statement);\n        }\n\n        for (int i = 0; i < 32; i++)\n        {\n            assertNotNull(\"Element \" + i + \" was null but should be \" + verifyList.get(i), list.get(0));\n            int size = list.size();\n            list.remove(verifyList.get(i));\n            assertSame(size - 1, list.size());\n        }\n    }\n\n    @Test\n    public void testAddRemoveTail()\n    {\n        ArrayList<Statement> verifyList = new ArrayList<>();\n\n        FastList<Statement> list = new FastList<>(Statement.class);\n        for (int i = 0; i < 32; i++)\n        {\n            StubStatement statement = new StubStatement(null);\n            list.add(statement);\n            verifyList.add(statement);\n        }\n\n        for (int i = 31; i >= 0; i--)\n        {\n            assertNotNull(\"Element \" + i, list.get(i));\n            int size = list.size();\n            list.remove(verifyList.get(i));\n            assertSame(size - 1, list.size());\n        }\n    }\n\n    @Test\n    public void testOverflow()\n    {\n        ArrayList<Statement> verifyList = new ArrayList<>();\n\n        FastList<Statement> list = new FastList<>(Statement.class);\n        for (int i = 0; i < 100; i++)\n        {\n            StubStatement statement = new StubStatement(null);\n            list.add(statement);\n            verifyList.add(statement);\n        }\n\n        for (int i = 0; i < 100; i++)\n        {\n            assertNotNull(\"Element \" + i, list.get(i));\n            assertSame(verifyList.get(i), list.get(i));\n        }\n    }\n\n    @Test\n    public void testIterator()\n    {\n       FastList<Statement> list = new FastList<>(Statement.class);\n       for (int i = 0; i < 100; i++)\n       {\n           StubStatement statement = new StubStatement(null);\n           list.add(statement);\n       }\n\n       Iterator<Statement> iter = list.iterator();\n       for (int i = 0;  i < list.size(); i++) {\n          assertSame(list.get(i), iter.next());\n       }\n    }\n\n    @Test\n    public void testClear()\n    {\n       FastList<Statement> list = new FastList<>(Statement.class);\n       for (int i = 0; i < 100; i++)\n       {\n           StubStatement statement = new StubStatement(null);\n           list.add(statement);\n       }\n\n       assertNotEquals(0, list.size());\n       list.clear();\n       assertEquals(0, list.size());\n       // also check that all elements are now null\n       for (int i = 0; i < 100; i++) {\n           assertEquals(null, list.get(i));\n       }\n    }\n\n    @Test\n    public void testRemoveLast()\n    {\n       FastList<Statement> list = new FastList<>(Statement.class);\n\n       Statement last = null;\n       for (int i = 0; i < 100; i++)\n       {\n           StubStatement statement = new StubStatement(null);\n           list.add(statement);\n           last = statement;\n       }\n\n       assertEquals(last, list.removeLast());\n       assertEquals(99, list.size());\n    }\n\n    @Test\n    public void testPolyMorphism1()\n    {\n       class Foo implements Base2 {\n\n       }\n\n       class Bar extends Foo {\n\n       }\n\n       FastList<Base> list = new FastList<>(Base.class, 2);\n       list.add(new Foo());\n       list.add(new Foo());\n       list.add(new Bar());\n    }\n\n    interface Base\n    {\n\n    }\n\n    interface Base2 extends Base\n    {\n\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/util/TomcatConcurrentBagLeakTest.java",
    "content": "/*\n * Copyright (C) 2017 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport com.zaxxer.hikari.pool.TestElf.FauxWebClassLoader;\nimport com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry;\nimport org.junit.FixMethodOrder;\nimport org.junit.Test;\nimport org.junit.runners.MethodSorters;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.lang.ref.Reference;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.Collection;\nimport java.util.ConcurrentModificationException;\nimport java.util.Iterator;\nimport java.util.concurrent.CompletableFuture;\n\nimport static com.zaxxer.hikari.pool.TestElf.isJava11;\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assume.assumeTrue;\n\n/**\n * @author Brett Wooldridge\n */\n@FixMethodOrder(MethodSorters.NAME_ASCENDING)\npublic class TomcatConcurrentBagLeakTest\n{\n   @Test\n   public void testConcurrentBagForLeaks() throws Exception\n   {\n      assumeTrue(!isJava11());\n\n      ClassLoader cl = new FauxWebClassLoader();\n      Class<?> clazz = cl.loadClass(this.getClass().getName() + \"$FauxWebContext\");\n      Object fauxWebContext = clazz.getDeclaredConstructor().newInstance();\n\n      Method createConcurrentBag = clazz.getDeclaredMethod(\"createConcurrentBag\");\n      createConcurrentBag.invoke(fauxWebContext);\n\n      Field failureException = clazz.getDeclaredField(\"failureException\");\n      Exception ex = (Exception) failureException.get(fauxWebContext);\n      assertNull(ex);\n   }\n\n   @Test\n   public void testConcurrentBagForLeaks2() throws Exception\n   {\n      assumeTrue(!isJava11());\n\n      ClassLoader cl = this.getClass().getClassLoader();\n      Class<?> clazz = cl.loadClass(this.getClass().getName() + \"$FauxWebContext\");\n      Object fauxWebContext = clazz.getDeclaredConstructor().newInstance();\n\n      Method createConcurrentBag = clazz.getDeclaredMethod(\"createConcurrentBag\");\n      createConcurrentBag.invoke(fauxWebContext);\n\n      Field failureException = clazz.getDeclaredField(\"failureException\");\n      Exception ex = (Exception) failureException.get(fauxWebContext);\n      assertNotNull(ex);\n   }\n\n   public static class PoolEntry implements IConcurrentBagEntry\n   {\n      private int state;\n\n      @Override\n      public boolean compareAndSet(int expectState, int newState)\n      {\n         this.state = newState;\n         return true;\n      }\n\n      @Override\n      public void setState(int newState)\n      {\n         this.state = newState;\n      }\n\n      @Override\n      public int getState()\n      {\n         return state;\n      }\n   }\n\n   public static class FauxWebContext\n   {\n      private static final Logger log = LoggerFactory.getLogger(FauxWebContext.class);\n\n      @SuppressWarnings(\"WeakerAccess\")\n      public Exception failureException;\n\n      @SuppressWarnings({\"ResultOfMethodCallIgnored\"})\n      public void createConcurrentBag() throws InterruptedException\n      {\n         try (ConcurrentBag<PoolEntry> bag = new ConcurrentBag<>(x -> CompletableFuture.completedFuture(Boolean.TRUE))) {\n\n            PoolEntry entry = new PoolEntry();\n            bag.add(entry);\n\n            PoolEntry borrowed = bag.borrow(100, MILLISECONDS);\n            bag.requite(borrowed);\n\n            PoolEntry removed = bag.borrow(100, MILLISECONDS);\n            bag.remove(removed);\n         }\n\n         checkThreadLocalsForLeaks();\n      }\n\n      private void checkThreadLocalsForLeaks()\n      {\n         Thread[] threads = getThreads();\n\n         try {\n            // Make the fields in the Thread class that store ThreadLocals\n            // accessible\n            Field threadLocalsField = Thread.class.getDeclaredField(\"threadLocals\");\n            threadLocalsField.setAccessible(true);\n            Field inheritableThreadLocalsField = Thread.class.getDeclaredField(\"inheritableThreadLocals\");\n            inheritableThreadLocalsField.setAccessible(true);\n            // Make the underlying array of ThreadLoad.ThreadLocalMap.Entry objects\n            // accessible\n            Class<?> tlmClass = Class.forName(\"java.lang.ThreadLocal$ThreadLocalMap\");\n            Field tableField = tlmClass.getDeclaredField(\"table\");\n            tableField.setAccessible(true);\n            Method expungeStaleEntriesMethod = tlmClass.getDeclaredMethod(\"expungeStaleEntries\");\n            expungeStaleEntriesMethod.setAccessible(true);\n\n            for (Thread thread : threads) {\n               Object threadLocalMap;\n               if (thread != null) {\n\n                  // Clear the first map\n                  threadLocalMap = threadLocalsField.get(thread);\n                  if (null != threadLocalMap) {\n                     expungeStaleEntriesMethod.invoke(threadLocalMap);\n                     checkThreadLocalMapForLeaks(threadLocalMap, tableField);\n                  }\n\n                  // Clear the second map\n                  threadLocalMap = inheritableThreadLocalsField.get(thread);\n                  if (null != threadLocalMap) {\n                     expungeStaleEntriesMethod.invoke(threadLocalMap);\n                     checkThreadLocalMapForLeaks(threadLocalMap, tableField);\n                  }\n               }\n            }\n         }\n         catch (Throwable t) {\n            log.warn(\"Failed to check for ThreadLocal references for web application [{}]\", getContextName(), t);\n            failureException = new Exception();\n         }\n      }\n\n      private Object getContextName()\n      {\n         return this.getClass().getName();\n      }\n\n      // THE FOLLOWING CODE COPIED FROM APACHE TOMCAT (2017/01/08)\n\n      /**\n      * Analyzes the given thread local map object. Also pass in the field that\n      * points to the internal table to save re-calculating it on every\n      * call to this method.\n      */\n      private void checkThreadLocalMapForLeaks(Object map, Field internalTableField) throws IllegalAccessException, NoSuchFieldException\n      {\n         if (map != null) {\n            Object[] table = (Object[]) internalTableField.get(map);\n            if (table != null) {\n               for (Object obj : table) {\n                  if (obj != null) {\n                     boolean keyLoadedByWebapp = false;\n                     boolean valueLoadedByWebapp = false;\n                     // Check the key\n                     Object key = ((Reference<?>) obj).get();\n                     if (this.equals(key) || loadedByThisOrChild(key)) {\n                        keyLoadedByWebapp = true;\n                     }\n                     // Check the value\n                     Field valueField = obj.getClass().getDeclaredField(\"value\");\n                     valueField.setAccessible(true);\n                     Object value = valueField.get(obj);\n                     if (this.equals(value) || loadedByThisOrChild(value)) {\n                        valueLoadedByWebapp = true;\n                     }\n                     if (keyLoadedByWebapp || valueLoadedByWebapp) {\n                        Object[] args = new Object[5];\n                        args[0] = getContextName();\n                        if (key != null) {\n                           args[1] = getPrettyClassName(key.getClass());\n                           try {\n                              args[2] = key.toString();\n                           } catch (Exception e) {\n                              log.warn(\"Unable to determine string representation of key of type [{}]\", args[1], e);\n                              args[2] = \"Unknown\";\n                           }\n                        }\n                        if (value != null) {\n                           args[3] = getPrettyClassName(value.getClass());\n                           try {\n                              args[4] = value.toString();\n                           } catch (Exception e) {\n                              log.warn(\"webappClassLoader.checkThreadLocalsForLeaks.badValue {}\", args[3], e);\n                              args[4] = \"Unknown\";\n                           }\n                        }\n\n                        if (valueLoadedByWebapp) {\n                           log.error(\"The web application [{}] created a ThreadLocal with key of type [{}] \" +\n                              \"(value [{}]) and a value of type [{}] (value [{}]) but failed to remove \" +\n                              \"it when the web application was stopped. Threads are going to be renewed \" +\n                              \"over time to try and avoid a probable memory leak.\", args);\n                           failureException = new Exception();\n                        } else if (value == null) {\n                           log.debug(\"The web application [{}] created a ThreadLocal with key of type [{}] \" +\n                              \"(value [{}]). The ThreadLocal has been correctly set to null and the \" +\n                              \"key will be removed by GC.\", args);\n                           failureException = new Exception();\n                        } else {\n                           log.debug(\"The web application [{}] created a ThreadLocal with key of type [{}] \" +\n                              \"(value [{}]) and a value of type [{}] (value [{}]). Since keys are only \" +\n                              \"weakly held by the ThreadLocal Map this is not a memory leak.\", args);\n                           failureException = new Exception();\n                        }\n                     }\n                  }\n               }\n            }\n         }\n      }\n\n      /**\n       * @param o object to test, may be null\n       * @return <code>true</code> if o has been loaded by the current classloader\n       * or one of its descendants.\n       */\n      private boolean loadedByThisOrChild(Object o) {\n         if (o == null) {\n            return false;\n         }\n\n         Class<?> clazz;\n         if (o instanceof Class) {\n            clazz = (Class<?>) o;\n         } else {\n            clazz = o.getClass();\n         }\n\n         ClassLoader cl = clazz.getClassLoader();\n         while (cl != null) {\n            if (cl == this.getClass().getClassLoader()) {\n               return true;\n            }\n            cl = cl.getParent();\n         }\n\n         if (o instanceof Collection<?>) {\n            Iterator<?> iter = ((Collection<?>) o).iterator();\n            try {\n               while (iter.hasNext()) {\n                  Object entry = iter.next();\n                  if (loadedByThisOrChild(entry)) {\n                     return true;\n                  }\n               }\n            } catch (ConcurrentModificationException e) {\n               log.warn(\"Failed to check for ThreadLocal references for web application [{}]\", getContextName(), e);\n            }\n         }\n         return false;\n      }\n\n      /*\n      * Get the set of current threads as an array.\n      */\n      private Thread[] getThreads()\n      {\n         // Get the current thread group\n         ThreadGroup tg = Thread.currentThread().getThreadGroup();\n         // Find the root thread group\n         try {\n            while (tg.getParent() != null) {\n               tg = tg.getParent();\n            }\n         }\n         catch (SecurityException se) {\n            log.warn(\"Unable to obtain the parent for ThreadGroup [{}]. It will not be possible to check all threads for potential memory leaks\", tg.getName(), se);\n         }\n\n         int threadCountGuess = tg.activeCount() + 50;\n         Thread[] threads = new Thread[threadCountGuess];\n         int threadCountActual = tg.enumerate(threads);\n         // Make sure we don't miss any threads\n         while (threadCountActual == threadCountGuess) {\n            threadCountGuess *= 2;\n            threads = new Thread[threadCountGuess];\n            // Note tg.enumerate(Thread[]) silently ignores any threads that\n            // can't fit into the array\n            threadCountActual = tg.enumerate(threads);\n         }\n\n         return threads;\n      }\n\n      private String getPrettyClassName(Class<?> clazz)\n      {\n         String name = clazz.getCanonicalName();\n         if (name == null) {\n            name = clazz.getName();\n         }\n         return name;\n      }\n   }\n}\n"
  },
  {
    "path": "src/test/java/com/zaxxer/hikari/util/UtilityElfTest.java",
    "content": "/*\n * Copyright (C) 2013, 2019 Brett Wooldridge\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.zaxxer.hikari.util;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\n\npublic class UtilityElfTest\n{\n   @Test\n   public void shouldReturnValidTransactionIsolationLevel()\n   {\n      //Act\n      int expectedLevel = UtilityElf.getTransactionIsolation(\"TRANSACTION_SQL_SERVER_SNAPSHOT_ISOLATION_LEVEL\");\n\n      //Assert\n      assertEquals(4096, expectedLevel);\n   }\n\n   @Test(expected = IllegalArgumentException.class)\n   public void shouldThrowWhenInvalidTransactionNameGiven()\n   {\n      //Act\n      UtilityElf.getTransactionIsolation(\"INVALID_TRANSACTION\");\n   }\n\n   @Test\n   public void shouldReturnTransationIsolationLevelFromInteger()\n   {\n      int expectedLevel = UtilityElf.getTransactionIsolation(\"4096\");\n      assertEquals(4096, expectedLevel);\n   }\n\n   @Test(expected = IllegalArgumentException.class)\n   public void shouldThrowWhenInvalidTransactionIntegerGiven()\n   {\n      //Act\n      UtilityElf.getTransactionIsolation(\"9999\");\n   }\n\n   @Test\n   public void shouldCreateInstanceOfClassWithConstructorThatAcceptsSuperClassAndInterfaceAndClassOfArguments() {\n      //Act\n      UtilityElf.createInstance(\"com.zaxxer.hikari.util.UtilityElfTest$ClassZ\",\n         Object.class,\n         new ClassB(),\n         new ClassC(),\n         new ClassD());\n   }\n\n   public static class ClassA {}\n\n   public static final class ClassB extends ClassA {}\n\n   public interface InterfaceC {}\n\n   public final static class ClassC implements InterfaceC {}\n\n   public final static class ClassD {}\n\n   public final static class ClassZ {\n      public ClassZ(ClassA _superClassA, InterfaceC _interfaceC, ClassD _classD) {}\n   }\n}\n"
  },
  {
    "path": "src/test/resources/duration-config.properties",
    "content": "connectionTimeout = 2000ms\nvalidationTimeout = 22s\nidleTimeout = 33m\nleakDetectionThreshold = 44h\nmaxLifetime = 55d\n\ndataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource\ndataSource.loginTimeout = 60000\n"
  },
  {
    "path": "src/test/resources/hibernate.properties",
    "content": "hibernate.hikari.minimumIdle=5\nhibernate.hikari.connectionTestQuery=SELECT 1\nhibernate.hikari.dataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource\nhibernate.connection.autocommit=false\n"
  },
  {
    "path": "src/test/resources/log4j2-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration status=\"OFF\">\n  <appenders>\n    <Console name=\"Console\" target=\"SYSTEM_ERR\">\n      <PatternLayout pattern=\"%d{ABSOLUTE_MICROS} [seq%5sn] [%-40.40t] %-5level %-20c{1} - %msg%n\" />\n    </Console>\n  </appenders>\n  <Loggers>\n    <Root level=\"debug\">\n      <AppenderRef ref=\"Console\" />\n    </Root>\n  </Loggers>\n</configuration>\n"
  },
  {
    "path": "src/test/resources/postgres_init_script.sql",
    "content": "CREATE SCHEMA IF NOT EXISTS test;\n"
  },
  {
    "path": "src/test/resources/propfile1.properties",
    "content": "minimumIdle=5\nconnectionTestQuery=SELECT 1\nautoCommit=false\ndataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource\n"
  },
  {
    "path": "src/test/resources/propfile2.properties",
    "content": "connectionTestQuery=SELECT 1\nautoCommit=false\ndataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource\ndataSource.user=test\ndataSource.password=test"
  },
  {
    "path": "src/test/resources/propfile3.properties",
    "content": "connectionTestQuery=SELECT 1\nautoCommit=false\ndataSourceClassName=com.zaxxer.hikari.mocks.StubDataSource\ndataSource.user=test\ndataSource.password=test\ndataSource.url=jdbc:stub:foo\n"
  }
]