diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 13dec553b3..8a163a4770 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -46,10 +46,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - with: - persist-credentials: false - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # 3.25.8 + uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # 3.25.8 + uses: github/codeql-action/autobuild@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # 3.25.8 + uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index 178f5a32a9..0000000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,59 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -name: Coverage - -on: - workflow_dispatch: #Allows to run workflow manually - push: - branches: - - master - - 'DBCP_2_**' - pull_request: - -permissions: - contents: read - -jobs: - build: - if: false - - runs-on: ubuntu-latest - strategy: - matrix: - java: [ 8 ] - - steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - with: - persist-credentials: false - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 - with: - distribution: 'temurin' - java-version: ${{ matrix.java }} - - name: Build with Maven - run: mvn --show-version --batch-mode --no-transfer-progress test jacoco:report - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1 - with: - files: ./target/site/jacoco/jacoco.xml diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000000..c6ece650e2 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,31 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: 'Dependency Review PR' + uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index ab2e52876a..7129611314 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -33,24 +33,24 @@ jobs: continue-on-error: ${{ matrix.experimental }} strategy: matrix: - java: [ 11, 17, 21 ] + java: [ 11, 17, 21, 23 ] experimental: [false] -# include: -# - java: 22-ea -# experimental: true + include: + - java: 24-ea + experimental: true steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - with: - persist-credentials: false - - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index a1580a2f8e..8e3eb3fa72 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -41,12 +41,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # 2.3.3 + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # 2.4.0 with: results_file: results.sarif results_format: sarif @@ -58,13 +58,13 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # 4.3.3 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # 4.4.3 with: name: SARIF file path: results.sarif retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # 3.25.8 + uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5 with: sarif_file: results.sarif diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf9b8149fd..5f23f94fbe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,9 +41,8 @@ Contributing to Apache Commons DBCP ====================== -You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to -the open source community. Before you dig right into the code there are a few guidelines that we need contributors to -follow so that we can have a chance of keeping on top of things. +Have you found a bug or have an idea for a cool new feature? Contributing code is a great way to give something back to the open-source community. +Before you dig right into the code, we need contributors to follow a few guidelines to have a chance of keeping on top of things. Getting Started --------------- @@ -62,7 +61,7 @@ Making Changes + Create a _topic branch_ for your isolated work. * Usually you should base your branch on the `master` branch. - * A good topic branch name can be the JIRA bug id plus a keyword, e.g. `DBCP-123-InputStream`. + * A good topic branch name can be the JIRA bug ID plus a keyword, e.g. `DBCP-123-InputStream`. * If you have submitted multiple JIRA issues, try to maintain separate branches and pull requests. + Make commits of logical units. * Make sure your commit messages are meaningful and in the proper format. Your commit message should contain the key of the JIRA issue. @@ -72,7 +71,7 @@ Making Changes + Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first. + Check for unnecessary whitespace with `git diff` -- check before committing. + Make sure you have added the necessary tests for your changes, typically in `src/test/java`. -+ Run all the tests with `mvn clean verify` to assure nothing else was accidentally broken. ++ Run all the tests with `mvn clean verify` to ensure nothing else was accidentally broken. Making Trivial Changes ---------------------- diff --git a/NOTICE.txt b/NOTICE.txt index d4901a2c38..75a281ea6c 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ -Apache Commons DBCP -Copyright 2001-2024 The Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (https://www.apache.org/). +Apache Commons DBCP +Copyright 2001-2024 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (https://www.apache.org/). diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 9bee95bd41..642e0405ac 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,4 +1,56 @@ Apache Commons DBCP +Version 2.13.0 +RELEASE NOTES + +The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.13.0. + +Apache Commons DBCP software implements Database Connection Pooling. + +This is a minor release, including bug fixes and enhancements. + +Changes +------- +New features: +* Add support for ignoring non-fatal SQL state codes #421. Thanks to Johno Crawford, Gary Gregory. +* Add @FunctionalInterface to SwallowedExceptionListener. Thanks to Johno Crawford, Gary Gregory. +* Add missing Javadoc comments and descriptions. Thanks to Gary Gregory. +* Add tests, raise the bar for JaCoCo checks. Thanks to Gary Gregory. + +Fixed Bugs +---------- +* Avoid object creation when invoking isDisconnectionSqlException #422. Thanks to Johno Crawford. +* DBCP-599: PoolableConnectionFactory.destroyObject() method behaves incorrectly on ABANDONED connection, issue with unhandled AbstractMethodError. DelegatingConnection.abort(Executor) should delegate to Jdbc41Bridge Thanks to denixx baykin, Phil Steitz, Gary Gregory. +* DelegatingConnection.setSchema(String) should delegate to Jdbc41Bridge. Thanks to Gary Gregory. +* Fix possible NullPointerException in PoolingConnection.close(). Thanks to Gary Gregory. +* PerUserPoolDataSource.registerPool() incorrectly replacing a CPDSConnectionFactory into managers map before throwing an IllegalStateException. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in AbandonedTrace. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in PoolableCallableStatement. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in PoolablePreparedStatement. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in Utils. Thanks to Gary Gregory. +* Fix PMD UnnecessaryFullyQualifiedName in LocalXAConnectionFactory. Thanks to Gary Gregory. +* Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in PerUserPoolDataSource. Thanks to Gary Gregory. +* Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in SharedPoolDataSource. Thanks to Gary Gregory. + +Changes +------- +* Bump org.apache.commons:commons-parent from 66 to 78 #360, #371, #395, #420, #426, #436, #441, #449. Thanks to Gary Gregory. +* Bump commons-logging:commons-logging from 1.3.0 to 1.3.4 #368, #399, #423. Thanks to Gary Gregory, Dependabot. +* Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #404, #412, #427. Thanks to Gary Gregory, Dependabot. +* Bump org.hamcrest:hamcrest from 2.2 to 3.0 #410. Thanks to Gary Gregory, Dependabot. +* Bump org.slf4j:slf4j-simple from 2.0.13 to 2.0.16 #413, #418. Thanks to Gary Gregory, Dependabot. + + +The list of changes is here: https://commons.apache.org/proper/commons-dbcp/changes-report.html + +For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, +patches, or suggestions for improvement, see the Apache Commons DBCP website: + +https://commons.apache.org/proper/commons-dbcp/ + +Download page: https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi + +----------------------------------------------------------------------------- +Apache Commons DBCP Version 2.12.0 RELEASE NOTES diff --git a/pom.xml b/pom.xml index 4a9f85e499..8df87657b3 100644 --- a/pom.xml +++ b/pom.xml @@ -22,11 +22,11 @@ org.apache.commons commons-parent - 71 + 78 4.0.0 commons-dbcp2 - 2.12.1-NX02-SNAPSHOT + 2.13.0 Apache Commons DBCP 2001 @@ -59,40 +59,28 @@ commons-pool2 ${commons.pool.version} - commons-logging commons-logging - 1.3.2 + 1.3.4 - org.junit.jupiter junit-jupiter test - - - org.hamcrest - hamcrest - 2.2 - test - - org.mockito mockito-core 4.11.0 test - org.apache.commons commons-lang3 - 3.14.0 + 3.17.0 test - jakarta.transaction @@ -111,7 +99,6 @@ 2.0.1 true - tomcat @@ -119,14 +106,12 @@ 5.0.28 test - tomcat naming-java 5.0.28 test - org.apache.geronimo.components @@ -147,7 +132,7 @@ org.slf4j slf4j-simple - 2.0.13 + 2.0.16 test @@ -187,15 +172,15 @@ UTF-8 UTF-8 - 2024-06-12T11:33:27Z + 2024-11-23T22:28:37Z 1.8 1.8 dbcp RC1 org.apache.commons.dbcp2 - 2.12.0 - 2.12.1 + 2.13.0 + 2.13.1 for JDBC 4.2 on Java 8 sha512 @@ -213,7 +198,7 @@ javax.transaction;version="1.1.0",javax.transaction.xa;version="1.1.0";partial=true;mandatory:=partial,* true - 2.11.0 + 2.12.0 true false false @@ -223,12 +208,13 @@ true + 0.98 - 0.68 - 0.87 + 0.74 + 0.89 0.66 0.62 - 0.76 + 0.78 clean verify apache-rat:check checkstyle:check spotbugs:check pmd:check pmd:cpd-check javadoc:javadoc @@ -267,9 +253,8 @@ ${commons.javadoc.version} - http://docs.oracle.com/javase/8/docs/api https://commons.apache.org/proper/commons-pool/apidocs - http://docs.oracle.com/javaee/7/api/ + ${commons.javadoc.javaee.link} diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bbbafc3ade..f005fccec6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -62,19 +62,31 @@ The type attribute can be add,update,fix,remove. EvictionTimer --> - + - Fix PMD UnnecessaryFullyQualifiedName in AbandonedTrace. - Fix PMD UnnecessaryFullyQualifiedName in PoolableCallableStatement. - Fix PMD UnnecessaryFullyQualifiedName in PoolablePreparedStatement. - Fix PMD UnnecessaryFullyQualifiedName in Utils. - Fix PMD UnnecessaryFullyQualifiedName in LocalXAConnectionFactory. - Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in PerUserPoolDataSource. - Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in SharedPoolDataSource. + Avoid object creation when invoking isDisconnectionSqlException #422. + PoolableConnectionFactory.destroyObject() method behaves incorrectly on ABANDONED connection, issue with unhandled AbstractMethodError. DelegatingConnection.abort(Executor) should delegate to Jdbc41Bridge + DelegatingConnection.setSchema(String) should delegate to Jdbc41Bridge. + Fix possible NullPointerException in PoolingConnection.close(). + PerUserPoolDataSource.registerPool() incorrectly replacing a CPDSConnectionFactory into managers map before throwing an IllegalStateException. + Fix PMD UnnecessaryFullyQualifiedName in AbandonedTrace. + Fix PMD UnnecessaryFullyQualifiedName in PoolableCallableStatement. + Fix PMD UnnecessaryFullyQualifiedName in PoolablePreparedStatement. + Fix PMD UnnecessaryFullyQualifiedName in Utils. + Fix PMD UnnecessaryFullyQualifiedName in LocalXAConnectionFactory. + Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in PerUserPoolDataSource. + Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in SharedPoolDataSource. + Add support for ignoring non-fatal SQL state codes #421. + Add @FunctionalInterface to SwallowedExceptionListener. + Add missing Javadoc comments and descriptions. + Add tests, raise the bar for JaCoCo checks. - Bump org.apache.commons:commons-parent from 66 to 71 #360, #371, #395. - Bump commons-logging:commons-logging from 1.3.0 to 1.3.2 #368. + Bump org.apache.commons:commons-parent from 66 to 78 #360, #371, #395, #420, #426, #436, #441, #449. + Bump commons-logging:commons-logging from 1.3.0 to 1.3.4 #368, #399, #423. + Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #404, #412, #427. + Bump org.hamcrest:hamcrest from 2.2 to 3.0 #410. + Bump org.slf4j:slf4j-simple from 2.0.13 to 2.0.16 #413, #418. diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java index ed58c7aef2..259835df2f 100644 --- a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java +++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java @@ -30,12 +30,14 @@ import java.time.Duration; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.function.BiConsumer; import java.util.logging.Logger; +import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -58,7 +60,6 @@ /** * Basic implementation of {@code javax.sql.DataSource} that is configured via JavaBeans properties. - * *

* This is not the only way to combine the commons-dbcp2 and commons-pool2 packages, but provides a * one-stop solution for basic requirements. @@ -346,6 +347,13 @@ protected static void validateConnectionFactory(final PoolableConnectionFactory private volatile Set disconnectionSqlCodes; + /** + * A collection of SQL State codes that are not considered fatal disconnection codes. + * + * @since 2.13.0 + */ + private volatile Set disconnectionIgnoreSqlCodes; + private boolean fastFailValidation; /** @@ -629,6 +637,7 @@ protected PoolableConnectionFactory createPoolableConnectionFactory(final Connec connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration()); connectionFactory.setFastFailValidation(fastFailValidation); connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes); + connectionFactory.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); validateConnectionFactory(connectionFactory); } catch (final RuntimeException e) { throw e; @@ -853,7 +862,33 @@ public int getDefaultTransactionIsolation() { } /** - * Gets the set of SQL_STATE codes considered to signal fatal conditions. + * Gets the set of SQL State codes that are not considered fatal disconnection codes. + *

+ * This method returns the set of SQL State codes that have been specified to be ignored + * when determining if a {@link SQLException} signals a disconnection. These codes will not + * trigger a disconnection even if they match other disconnection criteria. + *

+ * + * @return a set of SQL State codes that should be ignored for disconnection checks, or an empty set if none have been specified. + * @since 2.13.0 + */ + public Set getDisconnectionIgnoreSqlCodes() { + final Set result = disconnectionIgnoreSqlCodes; + return result == null ? Collections.emptySet() : result; + } + + /** + * Provides the same data as {@link #getDisconnectionIgnoreSqlCodes()} but in an array, so it is accessible via JMX. + * + * @since 2.13.0 + */ + @Override + public String[] getDisconnectionIgnoreSqlCodesAsArray() { + return getDisconnectionIgnoreSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY); + } + + /** + * Gets the set of SQL State codes considered to signal fatal conditions. * * @return fatal disconnection state codes * @see #setDisconnectionSqlCodes(Collection) @@ -950,10 +985,11 @@ public synchronized String getEvictionPolicyClassName() { /** * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with - * SQL_STATE indicating fatal disconnection errors. + * SQL State indicating fatal disconnection errors. * * @return true if connections created by this datasource will fast fail validation. * @see #setDisconnectionSqlCodes(Collection) + * @see #setDisconnectionIgnoreSqlCodes(Collection) * @since 2.1 */ @Override @@ -1445,7 +1481,7 @@ public synchronized String getUrl() { * Gets the JDBC connection {code userName} property. * * @return the {code userName} passed to the JDBC driver to establish connections - * @deprecated + * @deprecated Use {@link #getUserName()}. */ @Deprecated @Override @@ -1608,10 +1644,10 @@ protected void log(final String message) { } /** - * Logs the given throwable. - * @param message TODO - * @param throwable the throwable. + * Logs the given message and throwable. * + * @param message value to be log. + * @param throwable the throwable. * @since 2.7.0 */ protected void log(final String message, final Throwable throwable) { @@ -1729,8 +1765,8 @@ public void setAbandonedUsageTracking(final boolean usageTracking) { * the underlying connection. (Default: false) *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param allow Access to the underlying connection is granted when true. @@ -1786,8 +1822,8 @@ public void setConnectionFactoryClassName(final String connectionFactoryClassNam * Sets the collection of SQL statements to be executed when a physical connection is first created. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param connectionInitSqls Collection of SQL statements to execute on connection creation @@ -1802,8 +1838,8 @@ public void setConnectionInitSqls(final Collection connectionInitSqls) { * Sets the list of SQL statements to be executed when a physical connection is first created. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param connectionInitSqls List of SQL statements to execute on connection creation @@ -1853,8 +1889,8 @@ public void setConnectionProperties(final String connectionProperties) { * Sets default auto-commit state of connections returned by this datasource. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param defaultAutoCommit default auto-commit value @@ -1867,8 +1903,8 @@ public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { * Sets the default catalog. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param defaultCatalog the default catalog @@ -1904,8 +1940,8 @@ public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { * Sets defaultReadonly property. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param defaultReadOnly default read-only value @@ -1918,8 +1954,8 @@ public void setDefaultReadOnly(final Boolean defaultReadOnly) { * Sets the default schema. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param defaultSchema the default catalog @@ -1933,8 +1969,8 @@ public void setDefaultSchema(final String defaultSchema) { * Sets the default transaction isolation state for returned connections. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param defaultTransactionIsolation the default transaction isolation state @@ -1945,11 +1981,41 @@ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation } /** - * Sets the SQL_STATE codes considered to signal fatal conditions. + * Sets the SQL State codes that should be ignored when determining fatal disconnection conditions. + *

+ * This method allows you to specify a collection of SQL State codes that will be excluded from + * disconnection checks. These codes will not trigger the "fatally disconnected" status even if they + * match the typical disconnection criteria. This can be useful in scenarios where certain SQL State + * codes (e.g., specific codes starting with "08") are known to be non-fatal in your environment. + *

+ *

+ * The effect of this method is similar to the one described in {@link #setDisconnectionSqlCodes(Collection)}, + * but instead of setting codes that signal fatal disconnections, it defines codes that should be ignored + * during such checks. + *

+ *

+ * Note: This method currently has no effect once the pool has been initialized. The pool is initialized the first + * time one of the following methods is invoked: {@code getConnection, setLogwriter, setLoginTimeout, + * getLoginTimeout, getLogWriter}. + *

+ * + * @param disconnectionIgnoreSqlCodes SQL State codes that should be ignored in disconnection checks + * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}. + * @since 2.13.0 + */ + public void setDisconnectionIgnoreSqlCodes(final Collection disconnectionIgnoreSqlCodes) { + Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes); + final Set collect = Utils.isEmpty(disconnectionIgnoreSqlCodes) ? null + : disconnectionIgnoreSqlCodes.stream().filter(s -> !isEmpty(s)).collect(toLinkedHashSet()); + this.disconnectionIgnoreSqlCodes = Utils.isEmpty(collect) ? null : collect; + } + + /** + * Sets the SQL State codes considered to signal fatal conditions. *

* Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()} - * is {@code true}, whenever connections created by this datasource generate exceptions with SQL_STATE codes in this + * is {@code true}, whenever connections created by this datasource generate exceptions with SQL State codes in this * list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at * isValid or validation query). *

@@ -1962,12 +2028,14 @@ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation * setLoginTimeout, getLoginTimeout, getLogWriter}. *

* - * @param disconnectionSqlCodes SQL_STATE codes considered to signal fatal conditions + * @param disconnectionSqlCodes SQL State codes considered to signal fatal conditions * @since 2.1 + * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. */ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCodes) { + Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes); final Set collect = Utils.isEmpty(disconnectionSqlCodes) ? null - : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(Collectors.toSet()); + : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(toLinkedHashSet()); this.disconnectionSqlCodes = Utils.isEmpty(collect) ? null : collect; } @@ -1975,8 +2043,8 @@ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCo * Sets the JDBC Driver instance to use for this pool. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param driver The JDBC Driver instance to use for this pool. @@ -1989,8 +2057,8 @@ public synchronized void setDriver(final Driver driver) { * Sets the class loader to be used to load the JDBC driver. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param driverClassLoader the class loader with which to load the JDBC driver @@ -2003,8 +2071,8 @@ public synchronized void setDriverClassLoader(final ClassLoader driverClassLoade * Sets the JDBC driver class name. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param driverClassName the class name of the JDBC driver @@ -2062,8 +2130,8 @@ public void setFastFailValidation(final boolean fastFailValidation) { * Sets the initial size of the connection pool. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param initialSize the number of connections created when the pool is initialized @@ -2155,8 +2223,8 @@ public void setLogWriter(final PrintWriter logWriter) throws SQLException { * infinite lifetime. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param maxConnDuration The maximum permitted lifetime of a connection. @@ -2171,8 +2239,8 @@ public void setMaxConn(final Duration maxConnDuration) { * infinite lifetime. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds. @@ -2199,8 +2267,8 @@ public synchronized void setMaxIdle(final int maxIdle) { * Sets the value of the {@code maxOpenPreparedStatements} property. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param maxOpenStatements the new maximum number of prepared statements @@ -2297,8 +2365,8 @@ public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEviction * Sets the {code password}. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param password new value for the password @@ -2311,8 +2379,8 @@ public void setPassword(final String password) { * Sets whether to pool statements or not. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param poolingStatements pooling on or off @@ -2483,8 +2551,8 @@ public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetween * Sets the {code connection string}. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param connectionString the new value for the JDBC connection connectionString @@ -2497,8 +2565,8 @@ public synchronized void setUrl(final String connectionString) { * Sets the {code userName}. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param userName the new value for the JDBC connection user name @@ -2511,8 +2579,8 @@ public void setUsername(final String userName) { * Sets the {code validationQuery}. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param validationQuery the new value for the validation query @@ -2526,8 +2594,8 @@ public void setValidationQuery(final String validationQuery) { * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param validationQueryTimeoutDuration new validation query timeout value in seconds @@ -2542,8 +2610,8 @@ public void setValidationQueryTimeout(final Duration validationQueryTimeoutDurat * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. *

* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, + * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}. *

* * @param validationQueryTimeoutSeconds new validation query timeout value in seconds @@ -2586,6 +2654,10 @@ protected void startPoolMaintenance() { } } + private Collector> toLinkedHashSet() { + return Collectors.toCollection(LinkedHashSet::new); + } + @Override public T unwrap(final Class iface) throws SQLException { if (isWrapperFor(iface)) { diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java index a28b21bf52..11a154c90a 100644 --- a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java @@ -120,6 +120,18 @@ public class BasicDataSourceFactory implements ObjectFactory { */ private static final String PROP_DISCONNECTION_SQL_CODES = "disconnectionSqlCodes"; + /** + * Property key for specifying the SQL State codes that should be ignored during disconnection checks. + *

+ * The value for this property must be a comma-separated string of SQL State codes, where each code represents + * a state that will be excluded from being treated as a fatal disconnection. The expected format is a series + * of SQL State codes separated by commas, with no spaces between them (e.g., "08003,08004"). + *

+ * @since 2.13.0 + */ + private static final String PROP_DISCONNECTION_IGNORE_SQL_CODES = "disconnectionIgnoreSqlCodes"; + + /* * Block with obsolete properties from DBCP 1.x. Warn users that these are ignored and they should use the 2.x * properties. @@ -149,8 +161,8 @@ public class BasicDataSourceFactory implements ObjectFactory { PROP_CLEAR_STATEMENT_POOL_ON_RETURN, PROP_MAX_OPEN_PREPARED_STATEMENTS, PROP_CONNECTION_PROPERTIES, PROP_MAX_CONN_LIFETIME_MILLIS, PROP_LOG_EXPIRED_CONNECTIONS, PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTO_COMMIT_ON_RETURN, - PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_JMX_NAME, - PROP_REGISTER_CONNECTION_MBEAN, PROP_CONNECTION_FACTORY_CLASS_NAME); + PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_DISCONNECTION_IGNORE_SQL_CODES, + PROP_JMX_NAME, PROP_REGISTER_CONNECTION_MBEAN, PROP_CONNECTION_FACTORY_CLASS_NAME); /** * Obsolete properties from DBCP 1.x. with warning strings suggesting new properties. LinkedHashMap will guarantee @@ -227,17 +239,23 @@ public static BasicDataSource createDataSource(final Properties properties) thro getOptional(properties, PROP_DEFAULT_TRANSACTION_ISOLATION).ifPresent(value -> { value = value.toUpperCase(Locale.ROOT); int level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; - if ("NONE".equals(value)) { + switch (value) { + case "NONE": level = Connection.TRANSACTION_NONE; - } else if ("READ_COMMITTED".equals(value)) { + break; + case "READ_COMMITTED": level = Connection.TRANSACTION_READ_COMMITTED; - } else if ("READ_UNCOMMITTED".equals(value)) { + break; + case "READ_UNCOMMITTED": level = Connection.TRANSACTION_READ_UNCOMMITTED; - } else if ("REPEATABLE_READ".equals(value)) { + break; + case "REPEATABLE_READ": level = Connection.TRANSACTION_REPEATABLE_READ; - } else if ("SERIALIZABLE".equals(value)) { + break; + case "SERIALIZABLE": level = Connection.TRANSACTION_SERIALIZABLE; - } else { + break; + default: try { level = Integer.parseInt(value); } catch (final NumberFormatException e) { @@ -246,6 +264,7 @@ public static BasicDataSource createDataSource(final Properties properties) thro System.err.println("using default value of database driver"); level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; } + break; } dataSource.setDefaultTransactionIsolation(level); }); @@ -302,6 +321,7 @@ public static BasicDataSource createDataSource(final Properties properties) thro acceptDurationOfSeconds(properties, PROP_DEFAULT_QUERY_TIMEOUT, dataSource::setDefaultQueryTimeout); acceptBoolean(properties, PROP_FAST_FAIL_VALIDATION, dataSource::setFastFailValidation); getOptional(properties, PROP_DISCONNECTION_SQL_CODES).ifPresent(v -> dataSource.setDisconnectionSqlCodes(parseList(v, ','))); + getOptional(properties, PROP_DISCONNECTION_IGNORE_SQL_CODES).ifPresent(v -> dataSource.setDisconnectionIgnoreSqlCodes(parseList(v, ','))); acceptString(properties, PROP_CONNECTION_FACTORY_CLASS_NAME, dataSource::setConnectionFactoryClassName); // DBCP-215 diff --git a/src/main/java/org/apache/commons/dbcp2/Constants.java b/src/main/java/org/apache/commons/dbcp2/Constants.java index 26bf3df1a1..7094d62498 100644 --- a/src/main/java/org/apache/commons/dbcp2/Constants.java +++ b/src/main/java/org/apache/commons/dbcp2/Constants.java @@ -23,13 +23,29 @@ */ public class Constants { + /** + * Constant used to build JMX strings. + */ public static final String JMX_CONNECTION_POOL_BASE_EXT = ",connectionpool="; + + /** + * Constant used to build JMX strings. + */ public static final String JMX_CONNECTION_POOL_PREFIX = "connections"; - public static final String JMX_CONNECTION_BASE_EXT = JMX_CONNECTION_POOL_BASE_EXT + JMX_CONNECTION_POOL_PREFIX - + ",connection="; + /** + * Constant used to build JMX strings. + */ + public static final String JMX_CONNECTION_BASE_EXT = JMX_CONNECTION_POOL_BASE_EXT + JMX_CONNECTION_POOL_PREFIX + ",connection="; + /** + * Constant used to build JMX strings. + */ public static final String JMX_STATEMENT_POOL_BASE_EXT = JMX_CONNECTION_BASE_EXT; + + /** + * Constant used to build JMX strings. + */ public static final String JMX_STATEMENT_POOL_PREFIX = ",statementpool=statements"; /** diff --git a/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java b/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java index d3208c20f5..c28bd1f616 100644 --- a/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java +++ b/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java @@ -85,6 +85,16 @@ default String getDefaultSchema() { */ int getDefaultTransactionIsolation(); + /** + * See {@link BasicDataSource#getDisconnectionIgnoreSqlCodesAsArray()}. + * + * @return {@link BasicDataSource#getDisconnectionIgnoreSqlCodesAsArray()}. + * @since 2.13.0 + */ + default String[] getDisconnectionIgnoreSqlCodesAsArray() { + return Utils.EMPTY_STRING_ARRAY; + } + /** * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}. * diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java index 9231246a4d..996d31f2b4 100644 --- a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java +++ b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java @@ -95,6 +95,9 @@ public void abort(final Executor executor) throws SQLException { } } + /** + * Marks this instance as used and delegates to a wrapped {@link DelegatingConnection#activate()}. + */ protected void activate() { closed = false; setLastUsed(); @@ -103,6 +106,11 @@ protected void activate() { } } + /** + * Throws a SQLException if this connection is not open. + * + * @throws SQLException Thrown if this connection is not open. + */ protected void checkOpen() throws SQLException { if (closed) { if (null != connection) { @@ -317,7 +325,13 @@ public boolean getAutoCommit() throws SQLException { } /** - * Returns the state caching flag. + * Gets whether to cache properties. The cached properties are: + *
    + *
  • auto-commit
  • + *
  • catalog
  • + *
  • schema
  • + *
  • read-only
  • + *
* * @return the state caching flag */ @@ -578,6 +592,11 @@ public boolean isClosed() throws SQLException { return closed || connection == null || connection.isClosed(); } + /** + * Tests the raw internal closed state. + * + * @return the raw internal closed state. + */ protected boolean isClosedInternal() { return closed; } @@ -649,6 +668,11 @@ public String nativeSQL(final String sql) throws SQLException { } } + /** + * Clears the list of objects being traced by this object. + * + * @throws SQLException Thrown if not all traced objects were closed. + */ protected void passivate() throws SQLException { // The JDBC specification requires that a Connection close any open // Statements when it is closed. @@ -826,10 +850,15 @@ public void setAutoCommit(final boolean autoCommit) throws SQLException { } /** - * Sets the state caching flag. + * Sets whether to cache properties. The cached properties are: + *
    + *
  • auto-commit
  • + *
  • catalog
  • + *
  • schema
  • + *
  • read-only
  • + *
* - * @param cacheState - * The new value for the state caching flag + * @param cacheState The new value for the state caching flag */ public void setCacheState(final boolean cacheState) { this.cacheState = cacheState; @@ -873,6 +902,11 @@ public void setClientInfo(final String name, final String value) throws SQLClien } } + /** + * Sets the raw internal closed state. + * + * @param closed the raw internal closed state. + */ protected void setClosedInternal(final boolean closed) { this.closed = closed; } @@ -974,7 +1008,7 @@ public void setSchema(final String schema) throws SQLException { try { Jdbc41Bridge.setSchema(connection, schema); if (cacheState) { - cachedSchema = connection.getSchema(); + cachedSchema = Jdbc41Bridge.getSchema(connection); } } catch (final SQLException e) { cachedSchema = null; diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingDatabaseMetaData.java b/src/main/java/org/apache/commons/dbcp2/DelegatingDatabaseMetaData.java index ccbc52bbac..d77ab697de 100644 --- a/src/main/java/org/apache/commons/dbcp2/DelegatingDatabaseMetaData.java +++ b/src/main/java/org/apache/commons/dbcp2/DelegatingDatabaseMetaData.java @@ -22,14 +22,15 @@ import java.sql.RowIdLifetime; import java.sql.SQLException; import java.util.Objects; +import java.util.concurrent.Callable; /** *

* A base delegating implementation of {@link DatabaseMetaData}. *

*

- * Methods that create {@link ResultSet} objects are wrapped to create {@link DelegatingResultSet} objects and the - * remaining methods simply call the corresponding method on the "delegate" provided in the constructor. + * Methods that create {@link ResultSet} objects are wrapped to create {@link DelegatingResultSet} objects and the remaining methods simply call the + * corresponding method on the "delegate" provided in the constructor. *

* * @since 2.0 @@ -45,190 +46,115 @@ public class DelegatingDatabaseMetaData implements DatabaseMetaData { /** * Constructs a new instance for the given delegating connection and database meta data. * - * @param connection - * the delegating connection - * @param databaseMetaData - * the database meta data + * @param connection the delegating connection + * @param databaseMetaData the database meta data */ - public DelegatingDatabaseMetaData(final DelegatingConnection connection, - final DatabaseMetaData databaseMetaData) { + public DelegatingDatabaseMetaData(final DelegatingConnection connection, final DatabaseMetaData databaseMetaData) { this.connection = Objects.requireNonNull(connection, "connection"); this.databaseMetaData = Objects.requireNonNull(databaseMetaData, "databaseMetaData"); } @Override public boolean allProceduresAreCallable() throws SQLException { - try { - return databaseMetaData.allProceduresAreCallable(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::allProceduresAreCallable); } @Override public boolean allTablesAreSelectable() throws SQLException { - try { - return databaseMetaData.allTablesAreSelectable(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::allTablesAreSelectable); } @Override public boolean autoCommitFailureClosesAllResultSets() throws SQLException { - try { - return databaseMetaData.autoCommitFailureClosesAllResultSets(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::autoCommitFailureClosesAllResultSets); } @Override public boolean dataDefinitionCausesTransactionCommit() throws SQLException { - try { - return databaseMetaData.dataDefinitionCausesTransactionCommit(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::dataDefinitionCausesTransactionCommit); } @Override public boolean dataDefinitionIgnoredInTransactions() throws SQLException { - try { - return databaseMetaData.dataDefinitionIgnoredInTransactions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::dataDefinitionIgnoredInTransactions); } @Override public boolean deletesAreDetected(final int type) throws SQLException { - try { - return databaseMetaData.deletesAreDetected(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.deletesAreDetected(type)); } @Override public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { - try { - return databaseMetaData.doesMaxRowSizeIncludeBlobs(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::doesMaxRowSizeIncludeBlobs); } @Override public boolean generatedKeyAlwaysReturned() throws SQLException { connection.checkOpen(); + return getB(() -> Jdbc41Bridge.generatedKeyAlwaysReturned(databaseMetaData)); + } + + private T get(final Callable s) throws SQLException { + return get(s, null); + } + + private T get(final Callable s, final T defaultValue) throws SQLException { try { - return Jdbc41Bridge.generatedKeyAlwaysReturned(databaseMetaData); - } catch (final SQLException e) { - handleException(e); - return false; + return s.call(); + } catch (final Exception e) { + if (e instanceof SQLException) { + handleException((SQLException) e); + } + return defaultValue; } } @Override - public ResultSet getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, - final String attributeNamePattern) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, final String attributeNamePattern) + throws SQLException { + return getRS(() -> databaseMetaData.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern)); + } + + private boolean getB(final Callable s) throws SQLException { + return get(s, false); } @Override - public ResultSet getBestRowIdentifier(final String catalog, final String schema, final String table, - final int scope, final boolean nullable) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getBestRowIdentifier(catalog, schema, table, scope, nullable)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, final boolean nullable) + throws SQLException { + return getRS(() -> databaseMetaData.getBestRowIdentifier(catalog, schema, table, scope, nullable)); } @Override public ResultSet getCatalogs() throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getCatalogs()); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return getRS(databaseMetaData::getCatalogs); } @Override public String getCatalogSeparator() throws SQLException { - try { - return databaseMetaData.getCatalogSeparator(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getCatalogSeparator); } @Override public String getCatalogTerm() throws SQLException { - try { - return databaseMetaData.getCatalogTerm(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getCatalogTerm); } @Override public ResultSet getClientInfoProperties() throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getClientInfoProperties()); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return getRS(databaseMetaData::getClientInfoProperties); } @Override - public ResultSet getColumnPrivileges(final String catalog, final String schema, final String table, - final String columnNamePattern) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getColumnPrivileges(catalog, schema, table, columnNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getColumnPrivileges(final String catalog, final String schema, final String table, final String columnNamePattern) throws SQLException { + return getRS(() -> databaseMetaData.getColumnPrivileges(catalog, schema, table, columnNamePattern)); } @Override - public ResultSet getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, - final String columnNamePattern) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) + throws SQLException { + return getRS(() -> databaseMetaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern)); } @Override @@ -237,66 +163,34 @@ public Connection getConnection() throws SQLException { } @Override - public ResultSet getCrossReference(final String parentCatalog, final String parentSchema, final String parentTable, - final String foreignCatalog, final String foreignSchema, final String foreignTable) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getCrossReference(parentCatalog, - parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getCrossReference(final String parentCatalog, final String parentSchema, final String parentTable, final String foreignCatalog, + final String foreignSchema, final String foreignTable) throws SQLException { + return getRS(() -> databaseMetaData.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable)); } @Override public int getDatabaseMajorVersion() throws SQLException { - try { - return databaseMetaData.getDatabaseMajorVersion(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getDatabaseMajorVersion); } @Override public int getDatabaseMinorVersion() throws SQLException { - try { - return databaseMetaData.getDatabaseMinorVersion(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getDatabaseMinorVersion); } @Override public String getDatabaseProductName() throws SQLException { - try { - return databaseMetaData.getDatabaseProductName(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getDatabaseProductName); } @Override public String getDatabaseProductVersion() throws SQLException { - try { - return databaseMetaData.getDatabaseProductVersion(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getDatabaseProductVersion); } @Override public int getDefaultTransactionIsolation() throws SQLException { - try { - return databaseMetaData.getDefaultTransactionIsolation(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getDefaultTransactionIsolation); } /** @@ -320,119 +214,63 @@ public int getDriverMinorVersion() { @Override public String getDriverName() throws SQLException { - try { - return databaseMetaData.getDriverName(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getDriverName); } @Override public String getDriverVersion() throws SQLException { - try { - return databaseMetaData.getDriverVersion(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getDriverVersion); } @Override - public ResultSet getExportedKeys(final String catalog, final String schema, final String table) - throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getExportedKeys(catalog, schema, table)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getExportedKeys(final String catalog, final String schema, final String table) throws SQLException { + return getRS(() -> databaseMetaData.getExportedKeys(catalog, schema, table)); } @Override public String getExtraNameCharacters() throws SQLException { - try { - return databaseMetaData.getExtraNameCharacters(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getExtraNameCharacters); } @Override - public ResultSet getFunctionColumns(final String catalog, final String schemaPattern, - final String functionNamePattern, final String columnNamePattern) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getFunctionColumns(catalog, - schemaPattern, functionNamePattern, columnNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, final String columnNamePattern) + throws SQLException { + return getRS(() -> databaseMetaData.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern)); } @Override - public ResultSet getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern) - throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getFunctions(catalog, schemaPattern, functionNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern) throws SQLException { + return getRS(() -> databaseMetaData.getFunctions(catalog, schemaPattern, functionNamePattern)); + } + + private int getI(final Callable s) throws SQLException { + return get(s, 0); } @Override public String getIdentifierQuoteString() throws SQLException { - try { - return databaseMetaData.getIdentifierQuoteString(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getIdentifierQuoteString); } @Override - public ResultSet getImportedKeys(final String catalog, final String schema, final String table) - throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getImportedKeys(catalog, schema, table)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getImportedKeys(final String catalog, final String schema, final String table) throws SQLException { + return getRS(() -> databaseMetaData.getImportedKeys(catalog, schema, table)); } @Override - public ResultSet getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, - final boolean approximate) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getIndexInfo(catalog, schema, table, unique, approximate)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, final boolean approximate) + throws SQLException { + return getRS(() -> databaseMetaData.getIndexInfo(catalog, schema, table, unique, approximate)); } /** - * If my underlying {@link ResultSet} is not a {@code DelegatingResultSet}, returns it, otherwise recursively - * invokes this method on my delegate. + * If my underlying {@link ResultSet} is not a {@code DelegatingResultSet}, returns it, otherwise recursively invokes this method on my delegate. *

- * Hence this method will return the first delegate that is not a {@code DelegatingResultSet}, or {@code null} when - * no non-{@code DelegatingResultSet} delegate can be found by traversing this chain. + * Hence this method will return the first delegate that is not a {@code DelegatingResultSet}, or {@code null} when no non-{@code DelegatingResultSet} + * delegate can be found by traversing this chain. *

*

- * This method is useful when you may have nested {@code DelegatingResultSet}s, and you want to make sure to obtain - * a "genuine" {@link ResultSet}. + * This method is useful when you may have nested {@code DelegatingResultSet}s, and you want to make sure to obtain a "genuine" {@link ResultSet}. *

* * @return the innermost database meta data. @@ -450,142 +288,76 @@ public DatabaseMetaData getInnermostDelegate() { @Override public int getJDBCMajorVersion() throws SQLException { - try { - return databaseMetaData.getJDBCMajorVersion(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getJDBCMajorVersion); } @Override public int getJDBCMinorVersion() throws SQLException { - try { - return databaseMetaData.getJDBCMinorVersion(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getJDBCMinorVersion); + } + + private long getL(final Callable s) throws SQLException { + return get(s, 0L); } @Override public int getMaxBinaryLiteralLength() throws SQLException { - try { - return databaseMetaData.getMaxBinaryLiteralLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxBinaryLiteralLength); } @Override public int getMaxCatalogNameLength() throws SQLException { - try { - return databaseMetaData.getMaxCatalogNameLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxCatalogNameLength); } @Override public int getMaxCharLiteralLength() throws SQLException { - try { - return databaseMetaData.getMaxCharLiteralLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxCharLiteralLength); } @Override public int getMaxColumnNameLength() throws SQLException { - try { - return databaseMetaData.getMaxColumnNameLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxColumnNameLength); } @Override public int getMaxColumnsInGroupBy() throws SQLException { - try { - return databaseMetaData.getMaxColumnsInGroupBy(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxColumnsInGroupBy); } @Override public int getMaxColumnsInIndex() throws SQLException { - try { - return databaseMetaData.getMaxColumnsInIndex(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxColumnsInIndex); } @Override public int getMaxColumnsInOrderBy() throws SQLException { - try { - return databaseMetaData.getMaxColumnsInOrderBy(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxColumnsInOrderBy); } @Override public int getMaxColumnsInSelect() throws SQLException { - try { - return databaseMetaData.getMaxColumnsInSelect(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxColumnsInSelect); } @Override public int getMaxColumnsInTable() throws SQLException { - try { - return databaseMetaData.getMaxColumnsInTable(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxColumnsInTable); } @Override public int getMaxConnections() throws SQLException { - try { - return databaseMetaData.getMaxConnections(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxConnections); } @Override public int getMaxCursorNameLength() throws SQLException { - try { - return databaseMetaData.getMaxCursorNameLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxCursorNameLength); } @Override public int getMaxIndexLength() throws SQLException { - try { - return databaseMetaData.getMaxIndexLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxIndexLength); } /** @@ -593,397 +365,198 @@ public int getMaxIndexLength() throws SQLException { */ @Override public long getMaxLogicalLobSize() throws SQLException { - try { - return databaseMetaData.getMaxLogicalLobSize(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getL(databaseMetaData::getMaxLogicalLobSize); } @Override public int getMaxProcedureNameLength() throws SQLException { - try { - return databaseMetaData.getMaxProcedureNameLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxProcedureNameLength); } @Override public int getMaxRowSize() throws SQLException { - try { - return databaseMetaData.getMaxRowSize(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxRowSize); } @Override public int getMaxSchemaNameLength() throws SQLException { - try { - return databaseMetaData.getMaxSchemaNameLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxSchemaNameLength); } @Override public int getMaxStatementLength() throws SQLException { - try { - return databaseMetaData.getMaxStatementLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxStatementLength); } @Override public int getMaxStatements() throws SQLException { - try { - return databaseMetaData.getMaxStatements(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxStatements); } @Override public int getMaxTableNameLength() throws SQLException { - try { - return databaseMetaData.getMaxTableNameLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxTableNameLength); } @Override public int getMaxTablesInSelect() throws SQLException { - try { - return databaseMetaData.getMaxTablesInSelect(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxTablesInSelect); } @Override public int getMaxUserNameLength() throws SQLException { - try { - return databaseMetaData.getMaxUserNameLength(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getMaxUserNameLength); } @Override public String getNumericFunctions() throws SQLException { - try { - return databaseMetaData.getNumericFunctions(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getNumericFunctions); } @Override public ResultSet getPrimaryKeys(final String catalog, final String schema, final String table) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getPrimaryKeys(catalog, schema, table)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return getRS(() -> databaseMetaData.getPrimaryKeys(catalog, schema, table)); } @Override - public ResultSet getProcedureColumns(final String catalog, final String schemaPattern, - final String procedureNamePattern, final String columnNamePattern) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getProcedureColumns(catalog, - schemaPattern, procedureNamePattern, columnNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getProcedureColumns(final String catalog, final String schemaPattern, final String procedureNamePattern, final String columnNamePattern) + throws SQLException { + return getRS(() -> databaseMetaData.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern)); } @Override - public ResultSet getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) - throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getProcedures(catalog, schemaPattern, procedureNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) throws SQLException { + return getRS(() -> databaseMetaData.getProcedures(catalog, schemaPattern, procedureNamePattern)); } @Override public String getProcedureTerm() throws SQLException { - try { - return databaseMetaData.getProcedureTerm(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getProcedureTerm); } @Override - public ResultSet getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, - final String columnNamePattern) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, Jdbc41Bridge.getPseudoColumns(databaseMetaData, - catalog, schemaPattern, tableNamePattern, columnNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) + throws SQLException { + return getRS(() -> Jdbc41Bridge.getPseudoColumns(databaseMetaData, catalog, schemaPattern, tableNamePattern, columnNamePattern)); } @Override public int getResultSetHoldability() throws SQLException { - try { - return databaseMetaData.getResultSetHoldability(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getResultSetHoldability); } @Override public RowIdLifetime getRowIdLifetime() throws SQLException { - try { - return databaseMetaData.getRowIdLifetime(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getRowIdLifetime); + } + + @SuppressWarnings("resource") + private ResultSet getRS(final Callable s) throws SQLException { + connection.checkOpen(); + return DelegatingResultSet.wrapResultSet(connection, get(s)); } @Override public ResultSet getSchemas() throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getSchemas()); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return getRS(databaseMetaData::getSchemas); } @Override public ResultSet getSchemas(final String catalog, final String schemaPattern) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getSchemas(catalog, schemaPattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return getRS(() -> databaseMetaData.getSchemas(catalog, schemaPattern)); } @Override public String getSchemaTerm() throws SQLException { - try { - return databaseMetaData.getSchemaTerm(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getSchemaTerm); } @Override public String getSearchStringEscape() throws SQLException { - try { - return databaseMetaData.getSearchStringEscape(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getSearchStringEscape); } @Override public String getSQLKeywords() throws SQLException { - try { - return databaseMetaData.getSQLKeywords(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getSQLKeywords); } @Override public int getSQLStateType() throws SQLException { - try { - return databaseMetaData.getSQLStateType(); - } catch (final SQLException e) { - handleException(e); - return 0; - } + return getI(databaseMetaData::getSQLStateType); } @Override public String getStringFunctions() throws SQLException { - try { - return databaseMetaData.getStringFunctions(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getStringFunctions); } @Override - public ResultSet getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern) - throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getSuperTables(catalog, schemaPattern, tableNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { + return getRS(() -> databaseMetaData.getSuperTables(catalog, schemaPattern, tableNamePattern)); } @Override - public ResultSet getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern) - throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getSuperTypes(catalog, schemaPattern, typeNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern) throws SQLException { + return getRS(() -> databaseMetaData.getSuperTypes(catalog, schemaPattern, typeNamePattern)); } @Override public String getSystemFunctions() throws SQLException { - try { - return databaseMetaData.getSystemFunctions(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getSystemFunctions); } @Override - public ResultSet getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern) - throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getTablePrivileges(catalog, schemaPattern, tableNamePattern)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { + return getRS(() -> databaseMetaData.getTablePrivileges(catalog, schemaPattern, tableNamePattern)); } @Override - public ResultSet getTables(final String catalog, final String schemaPattern, final String tableNamePattern, - final String[] types) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getTables(catalog, schemaPattern, tableNamePattern, types)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getTables(final String catalog, final String schemaPattern, final String tableNamePattern, final String[] types) throws SQLException { + return getRS(() -> databaseMetaData.getTables(catalog, schemaPattern, tableNamePattern, types)); } @Override public ResultSet getTableTypes() throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getTableTypes()); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return getRS(databaseMetaData::getTableTypes); } @Override public String getTimeDateFunctions() throws SQLException { - try { - return databaseMetaData.getTimeDateFunctions(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getTimeDateFunctions); } @Override public ResultSet getTypeInfo() throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getTypeInfo()); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return getRS(databaseMetaData::getTypeInfo); } @Override - public ResultSet getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, - final int[] types) throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getUDTs(catalog, schemaPattern, typeNamePattern, types)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, final int[] types) throws SQLException { + return getRS(() -> databaseMetaData.getUDTs(catalog, schemaPattern, typeNamePattern, types)); } @Override public String getURL() throws SQLException { - try { - return databaseMetaData.getURL(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getURL); } @Override public String getUserName() throws SQLException { - try { - return databaseMetaData.getUserName(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + return get(databaseMetaData::getUserName); } @Override - public ResultSet getVersionColumns(final String catalog, final String schema, final String table) - throws SQLException { - connection.checkOpen(); - try { - return DelegatingResultSet.wrapResultSet(connection, - databaseMetaData.getVersionColumns(catalog, schema, table)); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); - } + public ResultSet getVersionColumns(final String catalog, final String schema, final String table) throws SQLException { + return getRS(() -> databaseMetaData.getVersionColumns(catalog, schema, table)); } + /** + * Delegates to the connection's {@link DelegatingConnection#handleException(SQLException)}. + * + * @param e the exception to throw or delegate. + * @throws SQLException the exception to throw. + */ protected void handleException(final SQLException e) throws SQLException { if (connection == null) { throw e; @@ -993,32 +566,17 @@ protected void handleException(final SQLException e) throws SQLException { @Override public boolean insertsAreDetected(final int type) throws SQLException { - try { - return databaseMetaData.insertsAreDetected(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.insertsAreDetected(type)); } @Override public boolean isCatalogAtStart() throws SQLException { - try { - return databaseMetaData.isCatalogAtStart(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::isCatalogAtStart); } @Override public boolean isReadOnly() throws SQLException { - try { - return databaseMetaData.isReadOnly(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::isReadOnly); } @Override @@ -1034,632 +592,318 @@ public boolean isWrapperFor(final Class iface) throws SQLException { @Override public boolean locatorsUpdateCopy() throws SQLException { - try { - return databaseMetaData.locatorsUpdateCopy(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::locatorsUpdateCopy); } @Override public boolean nullPlusNonNullIsNull() throws SQLException { - try { - return databaseMetaData.nullPlusNonNullIsNull(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::nullPlusNonNullIsNull); } @Override public boolean nullsAreSortedAtEnd() throws SQLException { - try { - return databaseMetaData.nullsAreSortedAtEnd(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::nullsAreSortedAtEnd); } @Override public boolean nullsAreSortedAtStart() throws SQLException { - try { - return databaseMetaData.nullsAreSortedAtStart(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::nullsAreSortedAtStart); } @Override public boolean nullsAreSortedHigh() throws SQLException { - try { - return databaseMetaData.nullsAreSortedHigh(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::nullsAreSortedHigh); } @Override public boolean nullsAreSortedLow() throws SQLException { - try { - return databaseMetaData.nullsAreSortedLow(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::nullsAreSortedLow); } @Override public boolean othersDeletesAreVisible(final int type) throws SQLException { - try { - return databaseMetaData.othersDeletesAreVisible(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.othersDeletesAreVisible(type)); } @Override public boolean othersInsertsAreVisible(final int type) throws SQLException { - try { - return databaseMetaData.othersInsertsAreVisible(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.othersInsertsAreVisible(type)); } @Override public boolean othersUpdatesAreVisible(final int type) throws SQLException { - try { - return databaseMetaData.othersUpdatesAreVisible(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.othersUpdatesAreVisible(type)); } @Override public boolean ownDeletesAreVisible(final int type) throws SQLException { - try { - return databaseMetaData.ownDeletesAreVisible(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.ownDeletesAreVisible(type)); } @Override public boolean ownInsertsAreVisible(final int type) throws SQLException { - try { - return databaseMetaData.ownInsertsAreVisible(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.ownInsertsAreVisible(type)); } @Override public boolean ownUpdatesAreVisible(final int type) throws SQLException { - try { - return databaseMetaData.ownUpdatesAreVisible(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.ownUpdatesAreVisible(type)); } @Override public boolean storesLowerCaseIdentifiers() throws SQLException { - try { - return databaseMetaData.storesLowerCaseIdentifiers(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::storesLowerCaseIdentifiers); } @Override public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { - try { - return databaseMetaData.storesLowerCaseQuotedIdentifiers(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::storesLowerCaseQuotedIdentifiers); } @Override public boolean storesMixedCaseIdentifiers() throws SQLException { - try { - return databaseMetaData.storesMixedCaseIdentifiers(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::storesMixedCaseIdentifiers); } @Override public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { - try { - return databaseMetaData.storesMixedCaseQuotedIdentifiers(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::storesMixedCaseQuotedIdentifiers); } @Override public boolean storesUpperCaseIdentifiers() throws SQLException { - try { - return databaseMetaData.storesUpperCaseIdentifiers(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::storesUpperCaseIdentifiers); + } @Override public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { - try { - return databaseMetaData.storesUpperCaseQuotedIdentifiers(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::storesUpperCaseQuotedIdentifiers); } @Override public boolean supportsAlterTableWithAddColumn() throws SQLException { - try { - return databaseMetaData.supportsAlterTableWithAddColumn(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsAlterTableWithAddColumn); } @Override public boolean supportsAlterTableWithDropColumn() throws SQLException { - try { - return databaseMetaData.supportsAlterTableWithDropColumn(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsAlterTableWithDropColumn); } @Override public boolean supportsANSI92EntryLevelSQL() throws SQLException { - try { - return databaseMetaData.supportsANSI92EntryLevelSQL(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsANSI92EntryLevelSQL); } @Override public boolean supportsANSI92FullSQL() throws SQLException { - try { - return databaseMetaData.supportsANSI92FullSQL(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsANSI92FullSQL); } @Override public boolean supportsANSI92IntermediateSQL() throws SQLException { - try { - return databaseMetaData.supportsANSI92IntermediateSQL(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsANSI92IntermediateSQL); } @Override public boolean supportsBatchUpdates() throws SQLException { - try { - return databaseMetaData.supportsBatchUpdates(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsBatchUpdates); } @Override public boolean supportsCatalogsInDataManipulation() throws SQLException { - try { - return databaseMetaData.supportsCatalogsInDataManipulation(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsCatalogsInDataManipulation); } @Override public boolean supportsCatalogsInIndexDefinitions() throws SQLException { - try { - return databaseMetaData.supportsCatalogsInIndexDefinitions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsCatalogsInIndexDefinitions); } @Override public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { - try { - return databaseMetaData.supportsCatalogsInPrivilegeDefinitions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsCatalogsInPrivilegeDefinitions); } @Override public boolean supportsCatalogsInProcedureCalls() throws SQLException { - try { - return databaseMetaData.supportsCatalogsInProcedureCalls(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsCatalogsInProcedureCalls); } @Override public boolean supportsCatalogsInTableDefinitions() throws SQLException { - try { - return databaseMetaData.supportsCatalogsInTableDefinitions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsCatalogsInTableDefinitions); } @Override public boolean supportsColumnAliasing() throws SQLException { - try { - return databaseMetaData.supportsColumnAliasing(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsColumnAliasing); } @Override public boolean supportsConvert() throws SQLException { - try { - return databaseMetaData.supportsConvert(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsConvert); } @Override public boolean supportsConvert(final int fromType, final int toType) throws SQLException { - try { - return databaseMetaData.supportsConvert(fromType, toType); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.supportsConvert(fromType, toType)); } @Override public boolean supportsCoreSQLGrammar() throws SQLException { - try { - return databaseMetaData.supportsCoreSQLGrammar(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsCoreSQLGrammar); } @Override public boolean supportsCorrelatedSubqueries() throws SQLException { - try { - return databaseMetaData.supportsCorrelatedSubqueries(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsCorrelatedSubqueries); } @Override public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { - try { - return databaseMetaData.supportsDataDefinitionAndDataManipulationTransactions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsDataDefinitionAndDataManipulationTransactions); } @Override public boolean supportsDataManipulationTransactionsOnly() throws SQLException { - try { - return databaseMetaData.supportsDataManipulationTransactionsOnly(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsDataManipulationTransactionsOnly); } @Override public boolean supportsDifferentTableCorrelationNames() throws SQLException { - try { - return databaseMetaData.supportsDifferentTableCorrelationNames(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsDifferentTableCorrelationNames); } @Override public boolean supportsExpressionsInOrderBy() throws SQLException { - try { - return databaseMetaData.supportsExpressionsInOrderBy(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsExpressionsInOrderBy); } @Override public boolean supportsExtendedSQLGrammar() throws SQLException { - try { - return databaseMetaData.supportsExtendedSQLGrammar(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsExtendedSQLGrammar); } @Override public boolean supportsFullOuterJoins() throws SQLException { - try { - return databaseMetaData.supportsFullOuterJoins(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsFullOuterJoins); } @Override public boolean supportsGetGeneratedKeys() throws SQLException { - try { - return databaseMetaData.supportsGetGeneratedKeys(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsGetGeneratedKeys); } @Override public boolean supportsGroupBy() throws SQLException { - try { - return databaseMetaData.supportsGroupBy(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsGroupBy); } @Override public boolean supportsGroupByBeyondSelect() throws SQLException { - try { - return databaseMetaData.supportsGroupByBeyondSelect(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsGroupByBeyondSelect); } @Override public boolean supportsGroupByUnrelated() throws SQLException { - try { - return databaseMetaData.supportsGroupByUnrelated(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsGroupByUnrelated); } @Override public boolean supportsIntegrityEnhancementFacility() throws SQLException { - try { - return databaseMetaData.supportsIntegrityEnhancementFacility(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsIntegrityEnhancementFacility); } @Override public boolean supportsLikeEscapeClause() throws SQLException { - try { - return databaseMetaData.supportsLikeEscapeClause(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsLikeEscapeClause); } @Override public boolean supportsLimitedOuterJoins() throws SQLException { - try { - return databaseMetaData.supportsLimitedOuterJoins(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsLimitedOuterJoins); } @Override public boolean supportsMinimumSQLGrammar() throws SQLException { - try { - return databaseMetaData.supportsMinimumSQLGrammar(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsMinimumSQLGrammar); } @Override public boolean supportsMixedCaseIdentifiers() throws SQLException { - try { - return databaseMetaData.supportsMixedCaseIdentifiers(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsMixedCaseIdentifiers); } @Override public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { - try { - return databaseMetaData.supportsMixedCaseQuotedIdentifiers(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsMixedCaseQuotedIdentifiers); } @Override public boolean supportsMultipleOpenResults() throws SQLException { - try { - return databaseMetaData.supportsMultipleOpenResults(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsMultipleOpenResults); } @Override public boolean supportsMultipleResultSets() throws SQLException { - try { - return databaseMetaData.supportsMultipleResultSets(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsMultipleResultSets); } @Override public boolean supportsMultipleTransactions() throws SQLException { - try { - return databaseMetaData.supportsMultipleTransactions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsMultipleTransactions); } @Override public boolean supportsNamedParameters() throws SQLException { - try { - return databaseMetaData.supportsNamedParameters(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsNamedParameters); } @Override public boolean supportsNonNullableColumns() throws SQLException { - try { - return databaseMetaData.supportsNonNullableColumns(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsNonNullableColumns); } @Override public boolean supportsOpenCursorsAcrossCommit() throws SQLException { - try { - return databaseMetaData.supportsOpenCursorsAcrossCommit(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsOpenCursorsAcrossCommit); } @Override public boolean supportsOpenCursorsAcrossRollback() throws SQLException { - try { - return databaseMetaData.supportsOpenCursorsAcrossRollback(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsOpenCursorsAcrossRollback); } @Override public boolean supportsOpenStatementsAcrossCommit() throws SQLException { - try { - return databaseMetaData.supportsOpenStatementsAcrossCommit(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsOpenStatementsAcrossCommit); } @Override public boolean supportsOpenStatementsAcrossRollback() throws SQLException { - try { - return databaseMetaData.supportsOpenStatementsAcrossRollback(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsOpenStatementsAcrossRollback); } @Override public boolean supportsOrderByUnrelated() throws SQLException { - try { - return databaseMetaData.supportsOrderByUnrelated(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsOrderByUnrelated); } @Override public boolean supportsOuterJoins() throws SQLException { - try { - return databaseMetaData.supportsOuterJoins(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsOuterJoins); } @Override public boolean supportsPositionedDelete() throws SQLException { - try { - return databaseMetaData.supportsPositionedDelete(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsPositionedDelete); } @Override public boolean supportsPositionedUpdate() throws SQLException { - try { - return databaseMetaData.supportsPositionedUpdate(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsPositionedUpdate); } /** @@ -1667,232 +911,117 @@ public boolean supportsPositionedUpdate() throws SQLException { */ @Override public boolean supportsRefCursors() throws SQLException { - try { - return databaseMetaData.supportsRefCursors(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsRefCursors); } @Override public boolean supportsResultSetConcurrency(final int type, final int concurrency) throws SQLException { - try { - return databaseMetaData.supportsResultSetConcurrency(type, concurrency); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.supportsResultSetConcurrency(type, concurrency)); } @Override public boolean supportsResultSetHoldability(final int holdability) throws SQLException { - try { - return databaseMetaData.supportsResultSetHoldability(holdability); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.supportsResultSetHoldability(holdability)); } @Override public boolean supportsResultSetType(final int type) throws SQLException { - try { - return databaseMetaData.supportsResultSetType(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.supportsResultSetType(type)); } @Override public boolean supportsSavepoints() throws SQLException { - try { - return databaseMetaData.supportsSavepoints(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSavepoints); } @Override public boolean supportsSchemasInDataManipulation() throws SQLException { - try { - return databaseMetaData.supportsSchemasInDataManipulation(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSchemasInDataManipulation); } @Override public boolean supportsSchemasInIndexDefinitions() throws SQLException { - try { - return databaseMetaData.supportsSchemasInIndexDefinitions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSchemasInIndexDefinitions); } @Override public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { - try { - return databaseMetaData.supportsSchemasInPrivilegeDefinitions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSchemasInPrivilegeDefinitions); } @Override public boolean supportsSchemasInProcedureCalls() throws SQLException { - try { - return databaseMetaData.supportsSchemasInProcedureCalls(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSchemasInProcedureCalls); } @Override public boolean supportsSchemasInTableDefinitions() throws SQLException { - try { - return databaseMetaData.supportsSchemasInTableDefinitions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSchemasInTableDefinitions); } @Override public boolean supportsSelectForUpdate() throws SQLException { - try { - return databaseMetaData.supportsSelectForUpdate(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSelectForUpdate); } @Override public boolean supportsStatementPooling() throws SQLException { - try { - return databaseMetaData.supportsStatementPooling(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsStatementPooling); } @Override public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { - try { - return databaseMetaData.supportsStoredFunctionsUsingCallSyntax(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsStoredFunctionsUsingCallSyntax); } @Override public boolean supportsStoredProcedures() throws SQLException { - try { - return databaseMetaData.supportsStoredProcedures(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsStoredProcedures); } @Override public boolean supportsSubqueriesInComparisons() throws SQLException { - try { - return databaseMetaData.supportsSubqueriesInComparisons(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSubqueriesInComparisons); } @Override public boolean supportsSubqueriesInExists() throws SQLException { - try { - return databaseMetaData.supportsSubqueriesInExists(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSubqueriesInExists); } @Override public boolean supportsSubqueriesInIns() throws SQLException { - try { - return databaseMetaData.supportsSubqueriesInIns(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSubqueriesInIns); } @Override public boolean supportsSubqueriesInQuantifieds() throws SQLException { - try { - return databaseMetaData.supportsSubqueriesInQuantifieds(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsSubqueriesInQuantifieds); } @Override public boolean supportsTableCorrelationNames() throws SQLException { - try { - return databaseMetaData.supportsTableCorrelationNames(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsTableCorrelationNames); } @Override public boolean supportsTransactionIsolationLevel(final int level) throws SQLException { - try { - return databaseMetaData.supportsTransactionIsolationLevel(level); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.supportsTransactionIsolationLevel(level)); } @Override public boolean supportsTransactions() throws SQLException { - try { - return databaseMetaData.supportsTransactions(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsTransactions); } @Override public boolean supportsUnion() throws SQLException { - try { - return databaseMetaData.supportsUnion(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsUnion); } @Override public boolean supportsUnionAll() throws SQLException { - try { - return databaseMetaData.supportsUnionAll(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::supportsUnionAll); } @Override @@ -1908,31 +1037,16 @@ public T unwrap(final Class iface) throws SQLException { @Override public boolean updatesAreDetected(final int type) throws SQLException { - try { - return databaseMetaData.updatesAreDetected(type); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(() -> databaseMetaData.updatesAreDetected(type)); } @Override public boolean usesLocalFilePerTable() throws SQLException { - try { - return databaseMetaData.usesLocalFilePerTable(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::usesLocalFilePerTable); } @Override public boolean usesLocalFiles() throws SQLException { - try { - return databaseMetaData.usesLocalFiles(); - } catch (final SQLException e) { - handleException(e); - return false; - } + return getB(databaseMetaData::usesLocalFiles); } } diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java b/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java index 3114f42b07..6c30b5555e 100644 --- a/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java +++ b/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java @@ -95,7 +95,7 @@ public void cancel() throws SQLException { protected void checkOpen() throws SQLException { if (isClosed()) { - throw new SQLException(this.getClass().getName() + " with address: \"" + this.toString() + "\" is closed."); + throw new SQLException(this.getClass().getName() + " with address: \"" + toString() + "\" is closed."); } } diff --git a/src/main/java/org/apache/commons/dbcp2/DriverConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/DriverConnectionFactory.java index 99b0ddfc52..3f59e2d210 100644 --- a/src/main/java/org/apache/commons/dbcp2/DriverConnectionFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/DriverConnectionFactory.java @@ -53,6 +53,8 @@ public Connection createConnection() throws SQLException { } /** + * Gets the connection String. + * * @return The connection String. * @since 2.6.0 */ @@ -61,7 +63,9 @@ public String getConnectionString() { } /** - * @return The Driver. + * Gets the JDBC Driver. + * + * @return The JDBC Driver. * @since 2.6.0 */ public Driver getDriver() { @@ -69,7 +73,9 @@ public Driver getDriver() { } /** - * @return The Properties. + * Gets the properties. + * + * @return The properties. * @since 2.6.0 */ public Properties getProperties() { diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java index c99e789a55..7a8dca461c 100644 --- a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java +++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java @@ -71,11 +71,19 @@ public class PoolableConnection extends DelegatingConnection impleme private boolean fatalSqlExceptionThrown; /** - * SQL_STATE codes considered to signal fatal conditions. Overrides the defaults in + * SQL State codes considered to signal fatal conditions. Overrides the defaults in * {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). */ private final Collection disconnectionSqlCodes; + /** + * A collection of SQL State codes that are not considered fatal disconnection codes. + * + * @since 2.13.0 + */ + private final Collection disconnectionIgnoreSqlCodes; + + /** Whether or not to fast fail validation after fatal connection errors */ private final boolean fastFailValidation; @@ -104,18 +112,43 @@ public PoolableConnection(final Connection conn, final ObjectPool pool, + final ObjectName jmxObjectName, final Collection disconnectSqlCodes, + final boolean fastFailValidation) { + this(conn, pool, jmxObjectName, disconnectSqlCodes, null, fastFailValidation); + } + + /** + * Creates a new {@link PoolableConnection} instance. + * + * @param conn + * my underlying connection + * @param pool + * the pool to which I should return when closed + * @param jmxObjectName + * JMX name + * @param disconnectSqlCodes + * SQL State codes considered fatal disconnection errors + * @param disconnectionIgnoreSqlCodes + * SQL State codes that should be ignored when determining fatal disconnection errors + * @param fastFailValidation + * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to + * run query or isValid) + * @since 2.13.0 + */ public PoolableConnection(final Connection conn, final ObjectPool pool, final ObjectName jmxObjectName, final Collection disconnectSqlCodes, - final boolean fastFailValidation) { + final Collection disconnectionIgnoreSqlCodes, final boolean fastFailValidation) { super(conn); this.pool = pool; this.jmxObjectName = ObjectNameWrapper.wrap(jmxObjectName); this.disconnectionSqlCodes = disconnectSqlCodes; + this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes; this.fastFailValidation = fastFailValidation; if (jmxObjectName != null) { @@ -141,7 +174,7 @@ public void abort(final Executor executor) throws SQLException { } /** - * Returns me to my pool. + * Returns this instance to my containing pool. */ @Override public void close() throws SQLException { @@ -214,7 +247,7 @@ public Collection getDisconnectionSqlCodes() { } /** - * Expose the {@link #toString()} method via a bean getter, so it can be read as a property via JMX. + * Gets the value of the {@link #toString()} method via a bean getter, so it can be read as a property via JMX. */ @Override public String getToString() { @@ -257,7 +290,8 @@ public boolean isClosed() throws SQLException { * If {@link #disconnectionSqlCodes} has been set, sql states are compared to those in the configured list of fatal * exception codes. If this property is not set, codes are compared against the default codes in * {@link Utils#getDisconnectionSqlCodes()} and in this case anything starting with #{link - * Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection. + * Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection. Additionally, any SQL state + * listed in {@link #disconnectionIgnoreSqlCodes} will be ignored and not treated as fatal. *

* * @param e SQLException to be examined @@ -267,8 +301,11 @@ boolean isDisconnectionSqlException(final SQLException e) { boolean fatalException = false; final String sqlState = e.getSQLState(); if (sqlState != null) { + if (disconnectionIgnoreSqlCodes != null && disconnectionIgnoreSqlCodes.contains(sqlState)) { + return false; + } fatalException = disconnectionSqlCodes == null - ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.getDisconnectionSqlCodes().contains(sqlState) + ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.isDisconnectionSqlCode(sqlState) : disconnectionSqlCodes.contains(sqlState); } return fatalException; @@ -319,7 +356,7 @@ protected void passivate() throws SQLException { } /** - * Actually close my underlying {@link Connection}. + * Closes the underlying {@link Connection}. */ @Override public void reallyClose() throws SQLException { diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java index 923032f0d2..0b7cdf6868 100644 --- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java @@ -64,6 +64,8 @@ public class PoolableConnectionFactory implements PooledObjectFactory disconnectionSqlCodes; + private Collection disconnectionIgnoreSqlCodes; + private boolean fastFailValidation = true; private volatile ObjectPool pool; @@ -147,14 +149,14 @@ public void destroyObject(final PooledObject p) throws SQLEx @Override public void destroyObject(final PooledObject p, final DestroyMode mode) throws SQLException { if (mode == DestroyMode.ABANDONED) { - p.getObject().getInnermostDelegate().abort(Runnable::run); + Jdbc41Bridge.abort(p.getObject().getInnermostDelegate(), Runnable::run); } else { p.getObject().reallyClose(); } } /** - * Gets the cache state. + * Gets the cache state to propagate in {@link #makeObject()}. * * @return The cache state. * @since 2.6.0. @@ -173,11 +175,18 @@ public ConnectionFactory getConnectionFactory() { return connectionFactory; } + /** + * Gets how many connections were created in {@link #makeObject()}. + * + * @return the connection count. + */ protected AtomicLong getConnectionIndex() { return connectionIndex; } /** + * Gets the collection of initialization SQL statements. + * * @return The collection of initialization SQL statements. * @since 2.6.0 */ @@ -186,7 +195,9 @@ public Collection getConnectionInitSqls() { } /** - * @return The data source JMX ObjectName + * Gets data source JMX ObjectName. + * + * @return The data source JMX ObjectName. * @since 2.6.0. */ public ObjectName getDataSourceJmxName() { @@ -194,7 +205,9 @@ public ObjectName getDataSourceJmxName() { } /** - * @return The data source JMS ObjectName. + * Gets the data source JMX ObjectName. + * + * @return The data source JMX ObjectName. * @since 2.6.0 */ public ObjectName getDataSourceJmxObjectName() { @@ -202,7 +215,9 @@ public ObjectName getDataSourceJmxObjectName() { } /** - * @return Default auto-commit value. + * Gets the Default auto-commit value. + * + * @return The default auto-commit value. * @since 2.6.0 */ public Boolean getDefaultAutoCommit() { @@ -210,7 +225,9 @@ public Boolean getDefaultAutoCommit() { } /** - * @return Default catalog. + * Gets the default catalog. + * + * @return The default catalog. * @since 2.6.0 */ public String getDefaultCatalog() { @@ -218,7 +235,9 @@ public String getDefaultCatalog() { } /** - * @return Default query timeout in seconds. + * Gets the default query timeout in seconds. + * + * @return The default query timeout in seconds. * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. */ @Deprecated @@ -229,7 +248,7 @@ public Integer getDefaultQueryTimeout() { /** * Gets the default query timeout Duration. * - * @return Default query timeout Duration. + * @return The default query timeout Duration. * @since 2.10.0 */ public Duration getDefaultQueryTimeoutDuration() { @@ -237,7 +256,9 @@ public Duration getDefaultQueryTimeoutDuration() { } /** - * @return Default query timeout in seconds. + * Gets the default query timeout in seconds. + * + * @return The default query timeout in seconds. * @since 2.6.0 * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. */ @@ -247,7 +268,9 @@ public Integer getDefaultQueryTimeoutSeconds() { } /** - * @return Default read-only-value. + * Gets the default read-only-value. + * + * @return The default read-only-value. * @since 2.6.0 */ public Boolean getDefaultReadOnly() { @@ -255,7 +278,9 @@ public Boolean getDefaultReadOnly() { } /** - * @return Default schema. + * Gets the default schema. + * + * @return The default schema. * @since 2.6.0 */ public String getDefaultSchema() { @@ -263,7 +288,9 @@ public String getDefaultSchema() { } /** - * @return Default transaction isolation. + * Gets the default transaction isolation. + * + * @return The default transaction isolation. * @since 2.6.0 */ public int getDefaultTransactionIsolation() { @@ -271,11 +298,26 @@ public int getDefaultTransactionIsolation() { } /** - * SQL_STATE codes considered to signal fatal conditions. + * Gets the collection of SQL State codes that are not considered fatal disconnection codes. + *

+ * This method returns the collection of SQL State codes that have been set to be ignored when + * determining if a {@link SQLException} signals a disconnection. These codes are excluded from + * being treated as fatal even if they match the typical disconnection criteria. + *

+ * + * @return a {@link Collection} of SQL State codes that should be ignored for disconnection checks. + * @since 2.13.0 + */ + public Collection getDisconnectionIgnoreSqlCodes() { + return disconnectionIgnoreSqlCodes; + } + + /** + * Gets SQL State codes considered to signal fatal conditions. *

* Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #isFastFailValidation()} is - * {@code true}, whenever connections created by this factory generate exceptions with SQL_STATE codes in this list, + * {@code true}, whenever connections created by this factory generate exceptions with SQL State codes in this list, * they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at isValid or * validation query). *

@@ -283,7 +325,7 @@ public int getDefaultTransactionIsolation() { * If {@link #isFastFailValidation()} is {@code false} setting this property has no effect. *

* - * @return SQL_STATE codes overriding defaults + * @return SQL State codes overriding defaults * @since 2.1 */ public Collection getDisconnectionSqlCodes() { @@ -310,9 +352,15 @@ public long getMaxConnLifetimeMillis() { return maxConnDuration.toMillis(); } + /** + * Gets the maximum number of open prepared statements. + * + * @return The maximum number of open prepared statements. + */ protected int getMaxOpenPreparedStatements() { return maxOpenPreparedStatements; } + /** * Returns the {@link ObjectPool} in which {@link Connection}s are pooled. * @@ -321,14 +369,20 @@ protected int getMaxOpenPreparedStatements() { public synchronized ObjectPool getPool() { return pool; } + /** + * Tests whether to pool statements. + * * @return Whether to pool statements. * @since 2.6.0. */ public boolean getPoolStatements() { return poolStatements; } + /** + * Gets the validation query. + * * @return Validation query. * @since 2.6.0 */ @@ -358,6 +412,13 @@ public int getValidationQueryTimeoutSeconds() { return (int) validationQueryTimeoutDuration.getSeconds(); } + /** + * Initializes the given connection with the collection of SQL statements set in {@link #setConnectionInitSql(Collection)}. + * + * @param conn the connection to initialize. + * @throws SQLException if a database access error occurs or this method is called on a closed connection. + * @see #setConnectionInitSql(Collection) + */ protected void initializeConnection(final Connection conn) throws SQLException { final Collection sqls = connectionInitSqls; if (conn.isClosed()) { @@ -373,7 +434,9 @@ protected void initializeConnection(final Connection conn) throws SQLException { } /** - * @return Whether to auto-commit on return. + * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}. + * + * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}. * @since 2.6.0 */ public boolean isAutoCommitOnReturn() { @@ -381,7 +444,9 @@ public boolean isAutoCommitOnReturn() { } /** - * @return Whether to auto-commit on return. + * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}. + * + * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}. * @deprecated Use {@link #isAutoCommitOnReturn()}. */ @Deprecated @@ -391,7 +456,7 @@ public boolean isEnableAutoCommitOnReturn() { /** * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with - * SQL_STATE indicating fatal disconnection errors. + * SQL State indicating fatal disconnection errors. * * @return true if connections created by this factory will fast fail validation. * @see #setDisconnectionSqlCodes(Collection) @@ -403,6 +468,8 @@ public boolean isFastFailValidation() { } /** + * Tests whether to rollback on return. + * * @return Whether to rollback on return. */ public boolean isRollbackOnReturn() { @@ -464,7 +531,8 @@ public PooledObject makeObject() throws SQLException { } } - final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, fastFailValidation); + final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, + disconnectionSqlCodes, disconnectionIgnoreSqlCodes, fastFailValidation); pc.setCacheState(cacheState); return new DefaultPooledObject<>(pc); @@ -500,10 +568,20 @@ public void passivateObject(final PooledObject p) throws SQL conn.passivate(); } + /** + * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}. + * + * @param autoCommitOnReturn whether to set auto-commit. + */ public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { this.autoCommitOnReturn = autoCommitOnReturn; } + /** + * Sets the cache state to propagate in {@link #makeObject()}. + * + * @param cacheState the cache state to propagate. + */ public void setCacheState(final boolean cacheState) { this.cacheState = cacheState; } @@ -602,18 +680,37 @@ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation } /** + * Sets the disconnection SQL codes to ignore. + * + * @param disconnectionIgnoreSqlCodes + * The collection of SQL State codes to be ignored. + * @see #getDisconnectionIgnoreSqlCodes() + * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}. + * @since 2.13.0 + */ + public void setDisconnectionIgnoreSqlCodes(final Collection disconnectionIgnoreSqlCodes) { + Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes); + this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes; + } + + /** + * Sets the disconnection SQL codes. + * * @param disconnectionSqlCodes * The disconnection SQL codes. * @see #getDisconnectionSqlCodes() * @since 2.1 + * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. */ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCodes) { + Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes); this.disconnectionSqlCodes = disconnectionSqlCodes; } /** - * @param autoCommitOnReturn Whether to auto-commit on return. - * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}. + * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}. + * + * @param autoCommitOnReturn whether to set auto-commit. */ @Deprecated public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) { @@ -690,10 +787,20 @@ public synchronized void setPool(final ObjectPool pool) { this.pool = pool; } + /** + * Sets whether to pool statements. + * + * @param poolStatements whether to pool statements. + */ public void setPoolStatements(final boolean poolStatements) { this.poolStatements = poolStatements; } + /** + * Sets whether to rollback on return. + * + * @param rollbackOnReturn whether to rollback on return. + */ public void setRollbackOnReturn(final boolean rollbackOnReturn) { this.rollbackOnReturn = rollbackOnReturn; } diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java index b23365080e..a31b3f3716 100644 --- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java +++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java @@ -16,6 +16,7 @@ */ package org.apache.commons.dbcp2; +import java.sql.Connection; import java.sql.SQLException; /** @@ -25,43 +26,166 @@ */ public interface PoolableConnectionMXBean { + /** + * Clears the cached state. Call when you know that the underlying connection may have been accessed directly. + */ void clearCachedState(); + /** + * See {@link Connection#clearWarnings()}. + * + * @throws SQLException See {@link Connection#clearWarnings()}. + */ void clearWarnings() throws SQLException; + /** + * Returns this instance to my containing pool. + * + * @throws SQLException Throw if this instance cannot be returned. + */ void close() throws SQLException; + /** + * See {@link Connection#getAutoCommit()}. + * + * @return See {@link Connection#getAutoCommit()}. + * @throws SQLException See {@link Connection#getAutoCommit()}. + */ boolean getAutoCommit() throws SQLException; + /** + * Gets whether to cache properties. The cached properties are: + *
    + *
  • auto-commit
  • + *
  • catalog
  • + *
  • schema
  • + *
  • read-only
  • + *
+ * + * @return The value for the state caching flag. + */ boolean getCacheState(); + /** + * See {@link Connection#getCatalog()}. + * + * @return See {@link Connection#getCatalog()}. + * @throws SQLException See {@link Connection#getCatalog()}. + */ String getCatalog() throws SQLException; + /** + * See {@link Connection#getHoldability()}. + * + * @return See {@link Connection#getHoldability()}. + * @throws SQLException See {@link Connection#getHoldability()}. + */ int getHoldability() throws SQLException; + /** + * See {@link Connection#getSchema()}. + * + * @return See {@link Connection#getSchema()}. + * @throws SQLException See {@link Connection#getSchema()}. + */ String getSchema() throws SQLException; + /** + * Gets the value of the {@link Object#toString()} method via a bean getter, so it can be read as a property via JMX. + * + * @return the value of the {@link Object#toString()}. + */ String getToString(); + /** + * See {@link Connection#getTransactionIsolation()}. + * + * @return See {@link Connection#getTransactionIsolation()}. + * @throws SQLException See {@link Connection#getTransactionIsolation()}. + */ int getTransactionIsolation() throws SQLException; + /** + * See {@link Connection#isClosed()}. + * + * @return See {@link Connection#isClosed()}. + * @throws SQLException See {@link Connection#isClosed()}. + */ boolean isClosed() throws SQLException; + /** + * See {@link Connection#isReadOnly()}. + * + * @return See {@link Connection#isReadOnly()}. + * @throws SQLException See {@link Connection#isReadOnly()}. + */ boolean isReadOnly() throws SQLException; + /** + * Closes the underlying {@link Connection}. + * + * @throws SQLException Thrown if the connection can be closed. + */ void reallyClose() throws SQLException; + /** + * See {@link Connection#setAutoCommit(boolean)}. + * + * @param autoCommit See {@link Connection#setAutoCommit(boolean)}. + * @throws SQLException See {@link Connection#setAutoCommit(boolean)}. + */ void setAutoCommit(boolean autoCommit) throws SQLException; + /** + * Sets whether to cache properties. The cached properties are: + *
    + *
  • auto-commit
  • + *
  • catalog
  • + *
  • schema
  • + *
  • read-only
  • + *
+ * + * @param cacheState The new value for the state caching flag + */ void setCacheState(boolean cacheState); + /** + * See {@link Connection#setCatalog(String)}. + * + * @param catalog See {@link Connection#setCatalog(String)}. + * @throws SQLException See {@link Connection#setCatalog(String)}. + */ void setCatalog(String catalog) throws SQLException; + /** + * See {@link Connection#setHoldability(int)}. + * + * @param holdability {@link Connection#setHoldability(int)}. + * @throws SQLException See {@link Connection#setHoldability(int)}. + */ void setHoldability(int holdability) throws SQLException; + /** + * See {@link Connection#setReadOnly(boolean)}. + * + * @param readOnly See {@link Connection#setReadOnly(boolean)}. + * @throws SQLException See {@link Connection#setReadOnly(boolean)}. + */ void setReadOnly(boolean readOnly) throws SQLException; + /** + * See {@link Connection#setSchema(String)}. + * + * @param schema See {@link Connection#setSchema(String)}. + * @throws SQLException See {@link Connection#setSchema(String)}. + */ void setSchema(String schema) throws SQLException; + /** + * See {@link Connection#setTransactionIsolation(int)}. + * + * @param level See {@link Connection#setTransactionIsolation(int)}. + * @throws SQLException See {@link Connection#setTransactionIsolation(int)}. + */ void setTransactionIsolation(int level) throws SQLException; } diff --git a/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java b/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java index b4ce3eb619..a5fe2b34d5 100644 --- a/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java +++ b/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java @@ -122,7 +122,11 @@ public synchronized void close() throws SQLException { } } finally { try { - getDelegateInternal().close(); + @SuppressWarnings("resource") + final Connection delegateInternal = getDelegateInternal(); + if (delegateInternal != null) { + delegateInternal.close(); + } } finally { setClosedInternal(true); } diff --git a/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java b/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java index 1f7c0aa000..fe019b959d 100644 --- a/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java +++ b/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java @@ -164,7 +164,6 @@ public Connection getConnection(final String userName, final String password) th throw new UnsupportedOperationException(); } - // --- DataSource methods ----------------------------------------- /** * Throws {@link UnsupportedOperationException}. @@ -193,6 +192,11 @@ public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } + /** + * Gets the backing object pool. + * + * @return the backing object pool. + */ protected ObjectPool getPool() { return pool; } diff --git a/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java b/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java index f553740fb7..d1aacd288c 100644 --- a/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java +++ b/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java @@ -87,14 +87,24 @@ public Connection getInnermostDelegate() { /** The map of registered pools. */ protected static final HashMap> pools = new HashMap<>(); - /** My URL prefix */ + /** + * The Apache Commons connection string prefix {@value}. + */ public static final String URL_PREFIX = "jdbc:apache:commons:dbcp:"; + /** + * The String length of {@link #URL_PREFIX}. + */ protected static final int URL_PREFIX_LEN = URL_PREFIX.length(); - // version numbers + /** + * Major version number. + */ protected static final int MAJOR_VERSION = 1; + /** + * Minor version number. + */ protected static final int MINOR_VERSION = 0; /** Controls access to the underlying connection */ @@ -147,7 +157,6 @@ public synchronized void closePool(final String name) throws SQLException { public Connection connect(final String url, final Properties info) throws SQLException { if (acceptsURL(url)) { final ObjectPool pool = getConnectionPool(url.substring(URL_PREFIX_LEN)); - try { final Connection conn = pool.borrowObject(); if (conn == null) { diff --git a/src/main/java/org/apache/commons/dbcp2/Utils.java b/src/main/java/org/apache/commons/dbcp2/Utils.java index 8652cae12e..3020f89339 100644 --- a/src/main/java/org/apache/commons/dbcp2/Utils.java +++ b/src/main/java/org/apache/commons/dbcp2/Utils.java @@ -49,7 +49,9 @@ public final class Utils { @Deprecated public static final boolean IS_SECURITY_ENABLED = isSecurityEnabled(); - /** Any SQL_STATE starting with this value is considered a fatal disconnect */ + /** + * Any SQL State starting with this value is considered a fatal disconnect. + */ public static final String DISCONNECTION_SQL_CODE_PREFIX = "08"; /** @@ -80,6 +82,27 @@ public final class Utils { DISCONNECTION_SQL_CODES.add("JZ0C1"); // Sybase disconnect error } + /** + * Checks for conflicts between two collections. + *

+ * If any overlap is found between the two provided collections, an {@link IllegalArgumentException} is thrown. + *

+ * + * @param codes1 The first collection of SQL state codes. + * @param codes2 The second collection of SQL state codes. + * @throws IllegalArgumentException if any codes overlap between the two collections. + * @since 2.13.0 + */ + static void checkSqlCodes(final Collection codes1, final Collection codes2) { + if (codes1 != null && codes2 != null) { + final Set test = new HashSet<>(codes1); + test.retainAll(codes2); + if (!test.isEmpty()) { + throw new IllegalArgumentException(test + " cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes."); + } + } + } + /** * Clones the given char[] if not null. * @@ -179,7 +202,7 @@ public static void closeQuietly(final Statement statement) { *
  • JZ0C0 (Sybase disconnect error)
  • *
  • JZ0C1 (Sybase disconnect error)
  • * - * @return SQL codes of fatal connection errors. + * @return A copy SQL codes of fatal connection errors. * @since 2.10.0 */ public static Set getDisconnectionSqlCodes() { @@ -212,6 +235,17 @@ public static String getMessage(final String key, final Object... args) { return mf.format(args, new StringBuffer(), null).toString(); } + /** + * Checks if the given SQL state corresponds to a fatal connection error. + * + * @param sqlState the SQL state to check. + * @return true if the SQL state is a fatal connection error, false otherwise. + * @since 2.13.0 + */ + static boolean isDisconnectionSqlCode(final String sqlState) { + return DISCONNECTION_SQL_CODES.contains(sqlState); + } + static boolean isEmpty(final Collection collection) { return collection == null || collection.isEmpty(); } @@ -240,6 +274,13 @@ public static String toString(final char[] value) { return value == null ? null : String.valueOf(value); } + /** + * Throws a LifetimeExceededException if the given pooled object's lifetime has exceeded a maximum duration. + * + * @param p The pooled object to test. + * @param maxDuration The maximum lifetime. + * @throws LifetimeExceededException Thrown if the given pooled object's lifetime has exceeded a maximum duration. + */ public static void validateLifetime(final PooledObject p, final Duration maxDuration) throws LifetimeExceededException { if (maxDuration.compareTo(Duration.ZERO) > 0) { final Duration lifetimeDuration = Duration.between(p.getCreateInstant(), Instant.now()); diff --git a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java index 481acaf355..6281592127 100644 --- a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java +++ b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java @@ -700,7 +700,7 @@ public void setMinEvictableIdleTimeMillis(final int minEvictableIdleTimeMillis) *

    * When a negative value is supplied, * {@code ceil({@link BasicDataSource#getNumIdle})/abs({@link #getNumTestsPerEvictionRun})} tests will be run. - * I.e., when the value is -n, roughly one nth of the idle objects will be tested per run. + * I.e., when the value is -n, roughly one nth of the idle objects will be tested per run. *

    * * @param numTestsPerEvictionRun number of statements to examine per run diff --git a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java index 2fc938ed5b..9bb326f316 100644 --- a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java +++ b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java @@ -16,10 +16,12 @@ */ package org.apache.commons.dbcp2.cpdsadapter; +import java.sql.PreparedStatement; + import org.apache.commons.dbcp2.PStmtKey; /** - * A key uniquely identifying a {@link java.sql.PreparedStatement PreparedStatement}. + * A key uniquely identifying a {@link PreparedStatement}. * * @since 2.0 * @deprecated Use {@link PStmtKey}. diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java index 9ec3451b27..4fd5ff293e 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java @@ -1109,18 +1109,15 @@ public void setLogWriter(final PrintWriter logWriter) { /** *

    - * Sets the maximum permitted lifetime of a connection. A value of zero or less indicates an - * infinite lifetime. + * Sets the maximum permitted lifetime of a connection. A value of zero or less indicates an infinite lifetime. *

    *

    - * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first time one of the following methods is + * invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, {@link #setLoginTimeout(Duration)}, {@link #getLoginTimeoutDuration()}, + * {@link #getLogWriter()}. *

    * - * @param maxConnLifetimeMillis - * The maximum permitted lifetime of a connection. A value of zero or less indicates an - * infinite lifetime. + * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection. A value of zero or less indicates an infinite lifetime. * @since 2.9.0 */ public void setMaxConnLifetime(final Duration maxConnLifetimeMillis) { @@ -1129,18 +1126,15 @@ public void setMaxConnLifetime(final Duration maxConnLifetimeMillis) { /** *

    - * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an - * infinite lifetime. + * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an infinite lifetime. *

    *

    - * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first time one of the following methods is + * invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, {@link #setLoginTimeout(Duration)}, {@link #getLoginTimeoutDuration()}, + * {@link #getLogWriter()}. *

    * - * @param maxConnLifetimeMillis - * The maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an - * infinite lifetime. + * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an infinite lifetime. * @deprecated Use {@link #setMaxConnLifetime(Duration)}. */ @Deprecated diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java index afd5c8f241..a9f8c28082 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java @@ -118,6 +118,10 @@ static void removeInstance(final String key) { } } + private Boolean booleanValueOf(RefAddr refAddr) { + return Boolean.valueOf(toString(refAddr)); + } + /** * Creates an instance of the subclass and sets any properties contained in the Reference. * @@ -146,7 +150,7 @@ public Object getObjectInstance(final Object refObj, final Name name, final Cont final Reference ref = (Reference) refObj; if (isCorrectClass(ref.getClassName())) { final RefAddr refAddr = ref.get("instanceKey"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { // object was bound to JNDI via Referenceable API. obj = INSTANCE_MAP.get(refAddr.getContent()); } else { @@ -172,6 +176,10 @@ public Object getObjectInstance(final Object refObj, final Name name, final Cont return obj; } + private boolean hasContent(final RefAddr refAddr) { + return refAddr != null && refAddr.getContent() != null; + } + /** * Tests if className is the value returned from getClass().getName().toString(). * @@ -198,143 +206,151 @@ private void setCommonProperties(final Reference ref, final InstanceKeyDataSourc throws IOException, ClassNotFoundException { RefAddr refAddr = ref.get("dataSourceName"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDataSourceName(toString(refAddr)); } refAddr = ref.get("description"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDescription(toString(refAddr)); } refAddr = ref.get("jndiEnvironment"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { final byte[] serialized = (byte[]) refAddr.getContent(); ikds.setJndiEnvironment((Properties) deserialize(serialized)); } refAddr = ref.get("loginTimeout"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setLoginTimeout(Duration.ofSeconds(parseInt(refAddr))); + if (hasContent(refAddr)) { + ikds.setLoginTimeout(toDurationFromSeconds(refAddr)); } // Pool properties refAddr = ref.get("blockWhenExhausted"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultBlockWhenExhausted(parseBoolean(refAddr)); } refAddr = ref.get("evictionPolicyClassName"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultEvictionPolicyClassName(toString(refAddr)); } // Pool properties refAddr = ref.get("lifo"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultLifo(parseBoolean(refAddr)); } refAddr = ref.get("maxIdlePerKey"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultMaxIdle(parseInt(refAddr)); } refAddr = ref.get("maxTotalPerKey"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultMaxTotal(parseInt(refAddr)); } refAddr = ref.get("maxWaitMillis"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setDefaultMaxWait(Duration.ofMillis(parseLong(refAddr))); + if (hasContent(refAddr)) { + ikds.setDefaultMaxWait(toDurationFromMillis(refAddr)); } refAddr = ref.get("minEvictableIdleTimeMillis"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setDefaultMinEvictableIdle(Duration.ofMillis(parseLong(refAddr))); + if (hasContent(refAddr)) { + ikds.setDefaultMinEvictableIdle(toDurationFromMillis(refAddr)); } refAddr = ref.get("minIdlePerKey"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultMinIdle(parseInt(refAddr)); } refAddr = ref.get("numTestsPerEvictionRun"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultNumTestsPerEvictionRun(parseInt(refAddr)); } refAddr = ref.get("softMinEvictableIdleTimeMillis"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setDefaultSoftMinEvictableIdle(Duration.ofMillis(parseLong(refAddr))); + if (hasContent(refAddr)) { + ikds.setDefaultSoftMinEvictableIdle(toDurationFromMillis(refAddr)); } refAddr = ref.get("testOnCreate"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultTestOnCreate(parseBoolean(refAddr)); } refAddr = ref.get("testOnBorrow"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultTestOnBorrow(parseBoolean(refAddr)); } refAddr = ref.get("testOnReturn"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultTestOnReturn(parseBoolean(refAddr)); } refAddr = ref.get("testWhileIdle"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultTestWhileIdle(parseBoolean(refAddr)); } refAddr = ref.get("timeBetweenEvictionRunsMillis"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setDefaultDurationBetweenEvictionRuns(Duration.ofMillis(parseLong(refAddr))); + if (hasContent(refAddr)) { + ikds.setDefaultDurationBetweenEvictionRuns(toDurationFromMillis(refAddr)); } // Connection factory properties refAddr = ref.get("validationQuery"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setValidationQuery(toString(refAddr)); } refAddr = ref.get("validationQueryTimeout"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setValidationQueryTimeout(Duration.ofSeconds(parseInt(refAddr))); + if (hasContent(refAddr)) { + ikds.setValidationQueryTimeout(toDurationFromSeconds(refAddr)); } refAddr = ref.get("rollbackAfterValidation"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setRollbackAfterValidation(parseBoolean(refAddr)); } refAddr = ref.get("maxConnLifetimeMillis"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setMaxConnLifetime(Duration.ofMillis(parseLong(refAddr))); + if (hasContent(refAddr)) { + ikds.setMaxConnLifetime(toDurationFromMillis(refAddr)); } // Connection properties refAddr = ref.get("defaultAutoCommit"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setDefaultAutoCommit(Boolean.valueOf(toString(refAddr))); + if (hasContent(refAddr)) { + ikds.setDefaultAutoCommit(booleanValueOf(refAddr)); } refAddr = ref.get("defaultTransactionIsolation"); - if (refAddr != null && refAddr.getContent() != null) { + if (hasContent(refAddr)) { ikds.setDefaultTransactionIsolation(parseInt(refAddr)); } refAddr = ref.get("defaultReadOnly"); - if (refAddr != null && refAddr.getContent() != null) { - ikds.setDefaultReadOnly(Boolean.valueOf(toString(refAddr))); + if (hasContent(refAddr)) { + ikds.setDefaultReadOnly(booleanValueOf(refAddr)); } } + private Duration toDurationFromMillis(RefAddr refAddr) { + return Duration.ofMillis(parseLong(refAddr)); + } + + private Duration toDurationFromSeconds(RefAddr refAddr) { + return Duration.ofSeconds(parseInt(refAddr)); + } + String toString(final RefAddr refAddr) { return refAddr.getContent().toString(); } diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java index 3b21c653c7..db7fee5c22 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java @@ -38,8 +38,7 @@ import org.apache.commons.pool2.impl.DefaultPooledObject; /** - * A {@link KeyedPooledObjectFactory} that creates {@link org.apache.commons.dbcp2.PoolableConnection - * PoolableConnection}s. + * A {@link KeyedPooledObjectFactory} that creates {@link PoolableConnection}s. * * @since 2.0 */ diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java b/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java index 85d7491ad0..7d5344ab44 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; +import java.util.function.Supplier; import javax.naming.NamingException; import javax.naming.Reference; @@ -35,6 +36,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.pool2.ObjectPool; +import org.apache.commons.pool2.impl.EvictionPolicy; import org.apache.commons.pool2.impl.GenericObjectPool; /** @@ -67,23 +69,94 @@ private static HashMap createMap() { return new HashMap<>(); } + /** + * Maps user names to a data source property: BlockWhenExhausted. + */ private Map perUserBlockWhenExhausted; + + /** + * Maps user names to a data source property: EvictionPolicyClassName. + */ private Map perUserEvictionPolicyClassName; + + /** + * Maps user names to a data source property: Lifo. + */ private Map perUserLifo; + + /** + * Maps user names to a data source property: MaxIdle. + */ private Map perUserMaxIdle; + + /** + * Maps user names to a data source property: MaxTotal. + */ private Map perUserMaxTotal; + + /** + * Maps user names to a data source property: MaxWaitDuration. + */ private Map perUserMaxWaitDuration; + + /** + * Maps user names to a data source property: MinEvictableIdleDuration. + */ private Map perUserMinEvictableIdleDuration; + + /** + * Maps user names to a data source property: MinIdle. + */ private Map perUserMinIdle; + + /** + * Maps user names to a data source property: NumTestsPerEvictionRun. + */ private Map perUserNumTestsPerEvictionRun; + + /** + * Maps user names to a data source property: SoftMinEvictableIdleDuration. + */ private Map perUserSoftMinEvictableIdleDuration; + + /** + * Maps user names to a data source property: TestOnCreate. + */ private Map perUserTestOnCreate; + + /** + * Maps user names to a data source property: TestOnBorrow. + */ private Map perUserTestOnBorrow; + + /** + * Maps user names to a data source property: TestOnReturn. + */ private Map perUserTestOnReturn; + + /** + * Maps user names to a data source property: TestWhileIdle. + */ private Map perUserTestWhileIdle; + + /** + * Maps user names to a data source property: DurationBetweenEvictionRuns. + */ private Map perUserDurationBetweenEvictionRuns; + + /** + * Maps user names to a data source property: DefaultAutoCommit. + */ private Map perUserDefaultAutoCommit; + + /** + * Maps user names to a data source property: DefaultTransactionIsolation. + */ private Map perUserDefaultTransactionIsolation; + + /** + * Maps user names to a data source property: DefaultReadOnly. + */ private Map perUserDefaultReadOnly; /** @@ -92,7 +165,7 @@ private static HashMap createMap() { private transient Map managers = createMap(); /** - * Default no-arg constructor for Serialization. + * Constructs a new instance. */ public PerUserPoolDataSource() { } @@ -103,6 +176,7 @@ public PerUserPoolDataSource() { * @see org.apache.commons.pool2.ObjectPool#clear() * @since 2.3.0 */ + @SuppressWarnings("resource") // does not allocate a pool public void clear() { managers.values().forEach(manager -> { try { @@ -140,13 +214,34 @@ private Map convertMap(final Map currentMap, } + /** + * Gets the user specific default value in a map for the specified user's pool. + * + * @param userName The user name key. + * @return The user specific value. + */ + private V get(final Map map, final String userName) { + return map != null ? map.get(userName) : null; + } + + /** + * Gets the user specific default value in a map for the specified user's pool. + * + * @param userName The user name key. + * @return The user specific value. + */ + private V get(final Map map, final String userName, final Supplier defaultSupplier) { + final V v = get(map, userName); + return v != null ? v : defaultSupplier.get(); + } + @Override protected PooledConnectionManager getConnectionManager(final UserPassKey upKey) { return managers.get(getPoolKey(upKey.getUserName())); } /** - * Gets the underlying pool but does NOT allocate it. + * Gets the underlying pre-allocated pool (does NOT allocate). * * @param manager A CPDSConnectionFactory. * @return the underlying pool. @@ -208,14 +303,7 @@ public int getNumIdle(final String userName) { * @return The user specific value. */ public boolean getPerUserBlockWhenExhausted(final String userName) { - Boolean value = null; - if (perUserBlockWhenExhausted != null) { - value = perUserBlockWhenExhausted.get(userName); - } - if (value == null) { - return getDefaultBlockWhenExhausted(); - } - return value; + return get(perUserBlockWhenExhausted, userName, this::getDefaultBlockWhenExhausted); } /** @@ -226,11 +314,7 @@ public boolean getPerUserBlockWhenExhausted(final String userName) { * @return The user specific value. */ public Boolean getPerUserDefaultAutoCommit(final String userName) { - Boolean value = null; - if (perUserDefaultAutoCommit != null) { - value = perUserDefaultAutoCommit.get(userName); - } - return value; + return get(perUserDefaultAutoCommit, userName); } /** @@ -241,11 +325,7 @@ public Boolean getPerUserDefaultAutoCommit(final String userName) { * @return The user specific value. */ public Boolean getPerUserDefaultReadOnly(final String userName) { - Boolean value = null; - if (perUserDefaultReadOnly != null) { - value = perUserDefaultReadOnly.get(userName); - } - return value; + return get(perUserDefaultReadOnly, userName); } /** @@ -257,11 +337,7 @@ public Boolean getPerUserDefaultReadOnly(final String userName) { * @return The user specific value. */ public Integer getPerUserDefaultTransactionIsolation(final String userName) { - Integer value = null; - if (perUserDefaultTransactionIsolation != null) { - value = perUserDefaultTransactionIsolation.get(userName); - } - return value; + return get(perUserDefaultTransactionIsolation, userName); } /** @@ -274,33 +350,22 @@ public Integer getPerUserDefaultTransactionIsolation(final String userName) { * @since 2.10.0 */ public Duration getPerUserDurationBetweenEvictionRuns(final String userName) { - Duration value = null; - if (perUserDurationBetweenEvictionRuns != null) { - value = perUserDurationBetweenEvictionRuns.get(userName); - } - if (value == null) { - return getDefaultDurationBetweenEvictionRuns(); - } - return value; + return get(perUserDurationBetweenEvictionRuns, userName, this::getDefaultDurationBetweenEvictionRuns); } /** * Gets the user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's * pool or the default if no user specific value is defined. + *

    + * The class must implement {@link EvictionPolicy}. + *

    * * @param userName * The user name key. * @return The user specific value. */ public String getPerUserEvictionPolicyClassName(final String userName) { - String value = null; - if (perUserEvictionPolicyClassName != null) { - value = perUserEvictionPolicyClassName.get(userName); - } - if (value == null) { - return getDefaultEvictionPolicyClassName(); - } - return value; + return get(perUserEvictionPolicyClassName, userName, this::getDefaultEvictionPolicyClassName); } /** @@ -312,14 +377,7 @@ public String getPerUserEvictionPolicyClassName(final String userName) { * @return The user specific value. */ public boolean getPerUserLifo(final String userName) { - Boolean value = null; - if (perUserLifo != null) { - value = perUserLifo.get(userName); - } - if (value == null) { - return getDefaultLifo(); - } - return value; + return get(perUserLifo, userName, this::getDefaultLifo); } /** @@ -331,14 +389,7 @@ public boolean getPerUserLifo(final String userName) { * @return The user specific value. */ public int getPerUserMaxIdle(final String userName) { - Integer value = null; - if (perUserMaxIdle != null) { - value = perUserMaxIdle.get(userName); - } - if (value == null) { - return getDefaultMaxIdle(); - } - return value; + return get(perUserMaxIdle, userName, this::getDefaultMaxIdle); } /** @@ -350,14 +401,7 @@ public int getPerUserMaxIdle(final String userName) { * @return The user specific value. */ public int getPerUserMaxTotal(final String userName) { - Integer value = null; - if (perUserMaxTotal != null) { - value = perUserMaxTotal.get(userName); - } - if (value == null) { - return getDefaultMaxTotal(); - } - return value; + return get(perUserMaxTotal, userName, this::getDefaultMaxTotal); } /** @@ -370,14 +414,7 @@ public int getPerUserMaxTotal(final String userName) { * @since 2.10.0 */ public Duration getPerUserMaxWaitDuration(final String userName) { - Duration value = null; - if (perUserMaxWaitDuration != null) { - value = perUserMaxWaitDuration.get(userName); - } - if (value == null) { - return getDefaultMaxWait(); - } - return value; + return get(perUserMaxWaitDuration, userName, this::getDefaultMaxWait); } /** @@ -404,14 +441,7 @@ public long getPerUserMaxWaitMillis(final String userName) { * @since 2.10.0 */ public Duration getPerUserMinEvictableIdleDuration(final String userName) { - Duration value = null; - if (perUserMinEvictableIdleDuration != null) { - value = perUserMinEvictableIdleDuration.get(userName); - } - if (value == null) { - return getDefaultMinEvictableIdleDuration(); - } - return value; + return get(perUserMinEvictableIdleDuration, userName, this::getDefaultMinEvictableIdleDuration); } /** @@ -437,14 +467,7 @@ public long getPerUserMinEvictableIdleTimeMillis(final String userName) { * @return The user specific value. */ public int getPerUserMinIdle(final String userName) { - Integer value = null; - if (perUserMinIdle != null) { - value = perUserMinIdle.get(userName); - } - if (value == null) { - return getDefaultMinIdle(); - } - return value; + return get(perUserMinIdle, userName, this::getDefaultMinIdle); } /** @@ -456,14 +479,7 @@ public int getPerUserMinIdle(final String userName) { * @return The user specific value. */ public int getPerUserNumTestsPerEvictionRun(final String userName) { - Integer value = null; - if (perUserNumTestsPerEvictionRun != null) { - value = perUserNumTestsPerEvictionRun.get(userName); - } - if (value == null) { - return getDefaultNumTestsPerEvictionRun(); - } - return value; + return get(perUserNumTestsPerEvictionRun, userName, this::getDefaultNumTestsPerEvictionRun); } /** @@ -476,14 +492,7 @@ public int getPerUserNumTestsPerEvictionRun(final String userName) { * @since 2.10.0 */ public Duration getPerUserSoftMinEvictableIdleDuration(final String userName) { - Duration value = null; - if (perUserSoftMinEvictableIdleDuration != null) { - value = perUserSoftMinEvictableIdleDuration.get(userName); - } - if (value == null) { - return getDefaultSoftMinEvictableIdleDuration(); - } - return value; + return get(perUserSoftMinEvictableIdleDuration, userName, this::getDefaultSoftMinEvictableIdleDuration); } /** @@ -509,14 +518,7 @@ public long getPerUserSoftMinEvictableIdleTimeMillis(final String userName) { * @return The user specific value. */ public boolean getPerUserTestOnBorrow(final String userName) { - Boolean value = null; - if (perUserTestOnBorrow != null) { - value = perUserTestOnBorrow.get(userName); - } - if (value == null) { - return getDefaultTestOnBorrow(); - } - return value; + return get(perUserTestOnBorrow, userName, this::getDefaultTestOnBorrow); } /** @@ -528,14 +530,7 @@ public boolean getPerUserTestOnBorrow(final String userName) { * @return The user specific value. */ public boolean getPerUserTestOnCreate(final String userName) { - Boolean value = null; - if (perUserTestOnCreate != null) { - value = perUserTestOnCreate.get(userName); - } - if (value == null) { - return getDefaultTestOnCreate(); - } - return value; + return get(perUserTestOnCreate, userName, this::getDefaultTestOnCreate); } /** @@ -547,14 +542,7 @@ public boolean getPerUserTestOnCreate(final String userName) { * @return The user specific value. */ public boolean getPerUserTestOnReturn(final String userName) { - Boolean value = null; - if (perUserTestOnReturn != null) { - value = perUserTestOnReturn.get(userName); - } - if (value == null) { - return getDefaultTestOnReturn(); - } - return value; + return get(perUserTestOnReturn, userName, this::getDefaultTestOnReturn); } /** @@ -566,14 +554,7 @@ public boolean getPerUserTestOnReturn(final String userName) { * @return The user specific value. */ public boolean getPerUserTestWhileIdle(final String userName) { - Boolean value = null; - if (perUserTestWhileIdle != null) { - value = perUserTestWhileIdle.get(userName); - } - if (value == null) { - return getDefaultTestWhileIdle(); - } - return value; + return get(perUserTestWhileIdle, userName, this::getDefaultTestWhileIdle); } /** @@ -602,10 +583,9 @@ private ObjectPool getPool(final PoolKey poolKey) { return mgr == null ? null : mgr.getPool(); } + @SuppressWarnings("resource") // does not allocate a pool @Override - protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userName, final String password) - throws SQLException { - + protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userName, final String password) throws SQLException { final PoolKey key = getPoolKey(userName); ObjectPool pool; PooledConnectionManager manager; @@ -621,7 +601,6 @@ protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userNa } pool = getCPDSConnectionFactoryPool(manager); } - PooledConnectionAndInfo info = null; try { info = pool.borrowObject(); @@ -684,14 +663,11 @@ Map put(Map map, final K key, final V value) { } /** - * Supports Serialization interface. + * Deserializes an instance from an ObjectInputStream. * - * @param in - * a {@link java.io.ObjectInputStream} value - * @throws IOException - * if an error occurs - * @throws ClassNotFoundException - * if an error occurs + * @param in The source ObjectInputStream. + * @throws IOException Any of the usual Input/Output related exceptions. + * @throws ClassNotFoundException A class of a serialized object cannot be found. */ @SuppressWarnings("resource") private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { @@ -707,19 +683,16 @@ private PerUserPoolDataSource readObjectImpl() throws IOException, ClassNotFound } } - private synchronized void registerPool(final String userName, final String password) - throws NamingException, SQLException { - + private synchronized void registerPool(final String userName, final String password) throws NamingException, SQLException { final ConnectionPoolDataSource cpds = testCPDS(userName, password); - // Set up the factory we will use (passing the pool associates // the factory with the pool, so we do not have to do so // explicitly) final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, getValidationQuery(), getValidationQueryTimeoutDuration(), - isRollbackAfterValidation(), userName, password); + isRollbackAfterValidation(), userName, password); factory.setMaxConn(getMaxConnDuration()); - // Create an object pool to contain our PooledConnections + @SuppressWarnings("resource") final GenericObjectPool pool = new GenericObjectPool<>(factory); factory.setPool(pool); pool.setBlockWhenExhausted(getPerUserBlockWhenExhausted(userName)); @@ -737,13 +710,13 @@ private synchronized void registerPool(final String userName, final String passw pool.setTestOnReturn(getPerUserTestOnReturn(userName)); pool.setTestWhileIdle(getPerUserTestWhileIdle(userName)); pool.setDurationBetweenEvictionRuns(getPerUserDurationBetweenEvictionRuns(userName)); - pool.setSwallowedExceptionListener(new SwallowedExceptionLogger(log)); - - final PooledConnectionManager old = managers.put(getPoolKey(userName), factory); - if (old != null) { + final PoolKey poolKey = getPoolKey(userName); + if (managers.containsKey(poolKey)) { + pool.close(); throw new IllegalStateException("Pool already contains an entry for this user/password: " + userName); } + managers.put(poolKey, factory); } private Map replaceAll(final Map currentMap, final Map newMap) { @@ -860,7 +833,9 @@ void setPerUserEvictionPolicyClassName(final Map newMap) { /** * Sets a user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's * pool. - * + *

    + * The class must implement {@link EvictionPolicy}. + *

    * @param userName * The user name key. * @param value diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java b/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java index 01d8675a94..31be5411fb 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java @@ -20,6 +20,8 @@ import java.util.Objects; /** + * The key type for entries in a {@link PerUserPoolDataSource}. + * * @since 2.0 */ final class PoolKey implements Serializable { diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java b/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java index 04e066dd54..01deb37744 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java @@ -30,15 +30,6 @@ final class PooledConnectionAndInfo { private final UserPassKey userPassKey; - /** - * Constructs a new instance. - * - * @since 2.4.0 - */ - PooledConnectionAndInfo(final PooledConnection pooledConnection, final char[] userName, final char[] userPassword) { - this(pooledConnection, new UserPassKey(userName, userPassword)); - } - PooledConnectionAndInfo(final PooledConnection pooledConnection, final UserPassKey userPassKey) { this.pooledConnection = pooledConnection; this.userPassKey = userPassKey; diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSource.java b/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSource.java index d14ff58362..1de7ccff7c 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSource.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSource.java @@ -27,6 +27,7 @@ import javax.sql.ConnectionPoolDataSource; import org.apache.commons.pool2.KeyedObjectPool; +import org.apache.commons.pool2.KeyedPooledObjectFactory; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; @@ -51,10 +52,19 @@ public class SharedPoolDataSource extends InstanceKeyDataSource { private static final long serialVersionUID = -1458539734480586454L; - // Pool properties + /** + * Max total defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MAX_TOTAL}. + */ private int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; + /** + * Maps user credentials to pooled connection with credentials. + */ private transient KeyedObjectPool pool; + + /** + * A {@link KeyedPooledObjectFactory} that creates {@link PoolableConnection}s. + */ private transient KeyedCPDSConnectionFactory factory; /** @@ -89,9 +99,6 @@ public int getMaxTotal() { return this.maxTotal; } - // ---------------------------------------------------------------------- - // Instrumentation Methods - /** * Gets the number of active connections in the pool. * @@ -142,14 +149,11 @@ public Reference getReference() throws NamingException { } /** - * Supports Serialization interface. + * Deserializes an instance from an ObjectInputStream. * - * @param in - * a {@link java.io.ObjectInputStream} value - * @throws IOException - * if an error occurs - * @throws ClassNotFoundException - * if an error occurs + * @param in The source ObjectInputStream. + * @throws IOException Any of the usual Input/Output related exceptions. + * @throws ClassNotFoundException A class of a serialized object cannot be found. */ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); @@ -159,7 +163,7 @@ private void readObject(final ObjectInputStream in) throws IOException, ClassNot private KeyedObjectPool readObjectImpl() throws IOException, ClassNotFoundException { try { return ((SharedPoolDataSource) new SharedPoolDataSourceFactory().getObjectInstance(getReference(), null, null, null)).pool; - } catch (NamingException e) { + } catch (final NamingException e) { throw new IOException("NamingException: " + e); } } diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSourceFactory.java b/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSourceFactory.java index 937ccd1f1d..b2014365c3 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSourceFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSourceFactory.java @@ -25,8 +25,16 @@ * @since 2.0 */ public class SharedPoolDataSourceFactory extends InstanceKeyDataSourceFactory { + private static final String SHARED_POOL_CLASSNAME = SharedPoolDataSource.class.getName(); + /** + * Constructs a new instance. + */ + public SharedPoolDataSourceFactory() { + // empty + } + @Override protected InstanceKeyDataSource getNewInstance(final Reference ref) { final SharedPoolDataSource spds = new SharedPoolDataSource(); diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java b/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java index 94643c8070..cde1bf15dd 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java @@ -42,10 +42,6 @@ final class UserPassKey implements Serializable { private final CharArray name; private final CharArray password; - UserPassKey(final char[] userName, final char[] password) { - this(new CharArray(userName), new CharArray(password)); - } - UserPassKey(final CharArray userName, final CharArray userPassword) { this.name = userName; this.password = userPassword; diff --git a/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java b/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java index 50373ff370..b11746928a 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java @@ -127,8 +127,7 @@ protected PoolableConnectionFactory createPoolableConnectionFactory(final Connec throws SQLException { PoolableConnectionFactory connectionFactory = null; try { - connectionFactory = new PoolableManagedConnectionFactory((XAConnectionFactory) driverConnectionFactory, - getRegisteredJmxName()); + connectionFactory = new PoolableManagedConnectionFactory((XAConnectionFactory) driverConnectionFactory, getRegisteredJmxName()); connectionFactory.setValidationQuery(getValidationQuery()); connectionFactory.setValidationQueryTimeout(getValidationQueryTimeoutDuration()); connectionFactory.setConnectionInitSql(getConnectionInitSqls()); @@ -147,6 +146,7 @@ protected PoolableConnectionFactory createPoolableConnectionFactory(final Connec connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration()); connectionFactory.setFastFailValidation(getFastFailValidation()); connectionFactory.setDisconnectionSqlCodes(getDisconnectionSqlCodes()); + connectionFactory.setDisconnectionIgnoreSqlCodes(getDisconnectionIgnoreSqlCodes()); validateConnectionFactory(connectionFactory); } catch (final RuntimeException e) { throw e; @@ -235,17 +235,14 @@ public synchronized void setXADataSource(final String xaDataSource) { } /** - *

    * Sets the XADataSource instance used by the XAConnectionFactory. - *

    *

    - * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter. + * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first time one of the following methods is + * invoked: {@link #getConnection()}, {@link #setLogWriter(java.io.PrintWriter)}, {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, + * {@link #getLogWriter()}. *

    * - * @param xaDataSourceInstance - * XADataSource instance + * @param xaDataSourceInstance XADataSource instance */ public synchronized void setXaDataSourceInstance(final XADataSource xaDataSourceInstance) { this.xaDataSourceInstance = xaDataSourceInstance; diff --git a/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java index 108abb5425..84be596444 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java @@ -212,7 +212,7 @@ public synchronized int prepare(final Xid xid) { } /** - * Always returns a zero length Xid array. The LocalXAConnectionFactory can not support recovery, so no xids + * Always returns a zero length Xid array. The LocalXAConnectionFactory cannot support recovery, so no xids * will ever be found. * * @param flag @@ -369,6 +369,8 @@ public Connection createConnection() throws SQLException { } /** + * Gets the connection factory. + * * @return The connection factory. * @since 2.6.0 */ @@ -376,6 +378,11 @@ public ConnectionFactory getConnectionFactory() { return connectionFactory; } + /** + * Gets the transaction registry. + * + * @return The transaction registry. + */ @Override public TransactionRegistry getTransactionRegistry() { return transactionRegistry; diff --git a/src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java b/src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java index 126a39d2bd..a5a72d1a28 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java @@ -122,7 +122,7 @@ public void close() throws SQLException { @Override public void commit() throws SQLException { if (transactionContext != null) { - throw new SQLException("Commit can not be set while enrolled in a transaction"); + throw new SQLException("Commit cannot be set while enrolled in a transaction"); } super.commit(); } @@ -148,6 +148,8 @@ public Connection getInnermostDelegate() { } /** + * Gets the transaction context. + * * @return The transaction context. * @since 2.6.0 */ @@ -156,6 +158,8 @@ public TransactionContext getTransactionContext() { } /** + * Gets the transaction registry. + * * @return The transaction registry. * @since 2.6.0 */ @@ -175,7 +179,7 @@ public boolean isAccessToUnderlyingConnectionAllowed() { @Override public void rollback() throws SQLException { if (transactionContext != null) { - throw new SQLException("Commit can not be set while enrolled in a transaction"); + throw new SQLException("Commit cannot be set while enrolled in a transaction"); } super.rollback(); } @@ -183,7 +187,7 @@ public void rollback() throws SQLException { @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { if (transactionContext != null) { - throw new SQLException("Auto-commit can not be set while enrolled in a transaction"); + throw new SQLException("Auto-commit cannot be set while enrolled in a transaction"); } super.setAutoCommit(autoCommit); } @@ -191,7 +195,7 @@ public void setAutoCommit(final boolean autoCommit) throws SQLException { @Override public void setReadOnly(final boolean readOnly) throws SQLException { if (transactionContext != null) { - throw new SQLException("Read-only can not be set while enrolled in a transaction"); + throw new SQLException("Read-only cannot be set while enrolled in a transaction"); } super.setReadOnly(readOnly); } @@ -240,7 +244,7 @@ private void updateTransactionStatus() throws SQLException { if (transactionContext != null && !transactionContext.isTransactionComplete()) { if (transactionContext.isActive()) { if (transactionContext != transactionRegistry.getActiveTransactionContext()) { - throw new SQLException("Connection can not be used while enlisted in another transaction"); + throw new SQLException("Connection cannot be used while enlisted in another transaction"); } return; } diff --git a/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnection.java b/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnection.java index 858a0c4401..2be2e1a4f1 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnection.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnection.java @@ -33,7 +33,7 @@ public class PoolableManagedConnection extends PoolableConnection { private final TransactionRegistry transactionRegistry; /** - * Create a PoolableManagedConnection. + * Creates a PoolableManagedConnection. * * @param transactionRegistry * transaction registry @@ -42,13 +42,12 @@ public class PoolableManagedConnection extends PoolableConnection { * @param pool * connection pool */ - public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, - final ObjectPool pool) { + public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool) { this(transactionRegistry, conn, pool, null, true); } /** - * Create a PoolableManagedConnection. + * Creates a PoolableManagedConnection. * * @param transactionRegistry * transaction registry @@ -57,19 +56,43 @@ public PoolableManagedConnection(final TransactionRegistry transactionRegistry, * @param pool * connection pool * @param disconnectSqlCodes - * SQL_STATE codes considered fatal disconnection errors + * SQL State codes considered fatal disconnection errors * @param fastFailValidation * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to * run query or isValid) */ - public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, - final ObjectPool pool, final Collection disconnectSqlCodes, - final boolean fastFailValidation) { - super(conn, pool, null, disconnectSqlCodes, fastFailValidation); + public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool, + final Collection disconnectSqlCodes, final boolean fastFailValidation) { + this(transactionRegistry, conn, pool, disconnectSqlCodes, null, fastFailValidation); + } + + /** + * Creates a PoolableManagedConnection. + * + * @param transactionRegistry + * transaction registry + * @param conn + * underlying connection + * @param pool + * connection pool + * @param disconnectSqlCodes + * SQL State codes considered fatal disconnection errors + * @param disconnectionIgnoreSqlCodes + * SQL State codes considered fatal disconnection errors + * @param fastFailValidation + * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to + * run query or isValid) + * @since 2.13.0 + */ + public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool, + final Collection disconnectSqlCodes, final Collection disconnectionIgnoreSqlCodes, final boolean fastFailValidation) { + super(conn, pool, null, disconnectSqlCodes, disconnectionIgnoreSqlCodes, fastFailValidation); this.transactionRegistry = transactionRegistry; } /** + * Gets the transaction registry. + * * @return The transaction registry. * @since 2.6.0 */ diff --git a/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnectionFactory.java index 7eb810154d..9dc80ccb29 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnectionFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnectionFactory.java @@ -58,6 +58,8 @@ public PoolableManagedConnectionFactory(final XAConnectionFactory connFactory, f } /** + * Gets the transaction registry. + * * @return The transaction registry. * @since 2.6.0 */ @@ -104,7 +106,7 @@ public synchronized PooledObject makeObject() throws SQLExce ((PoolingConnection) conn).setCacheState(getCacheState()); } final PoolableManagedConnection pmc = new PoolableManagedConnection(transactionRegistry, conn, getPool(), - getDisconnectionSqlCodes(), isFastFailValidation()); + getDisconnectionSqlCodes(), getDisconnectionIgnoreSqlCodes(), isFastFailValidation()); pmc.setCacheState(getCacheState()); return new DefaultPooledObject<>(pmc); } diff --git a/src/main/java/org/apache/commons/dbcp2/managed/TransactionContextListener.java b/src/main/java/org/apache/commons/dbcp2/managed/TransactionContextListener.java index 4ebb7e7133..cc1b34c1c7 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/TransactionContextListener.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/TransactionContextListener.java @@ -22,13 +22,14 @@ * @since 2.0 */ public interface TransactionContextListener { + /** - * Occurs after the transaction commits or rolls back. + * Called after a transaction commits or rolls back. * * @param transactionContext - * the transaction context that completed + * the transaction context that completed. * @param committed - * true if the transaction committed; false otherwise + * true if the transaction committed; false otherwise. */ void afterCompletion(TransactionContext transactionContext, boolean committed); } diff --git a/src/main/java/org/apache/commons/dbcp2/managed/XAConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/managed/XAConnectionFactory.java index 3421fda810..abef80981a 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/XAConnectionFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/XAConnectionFactory.java @@ -30,16 +30,16 @@ * @since 2.0 */ public interface XAConnectionFactory extends ConnectionFactory { + /** - * Create a new {@link java.sql.Connection} in an implementation specific fashion. + * Creates a new {@link Connection} in an implementation specific fashion. *

    * An implementation can assume that the caller of this will wrap the connection in a proxy that protects access to * the setAutoCommit, commit and rollback when enrolled in a XA transaction. *

    * - * @return a new {@link java.sql.Connection} - * @throws java.sql.SQLException - * if a database error occurs creating the connection + * @return a new {@link Connection} + * @throws SQLException if a database error occurs creating the connection */ @Override Connection createConnection() throws SQLException; diff --git a/src/main/java/org/apache/commons/dbcp2/managed/package-info.java b/src/main/java/org/apache/commons/dbcp2/managed/package-info.java index f0bc5210fe..7e613e7b9c 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/package-info.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/package-info.java @@ -19,7 +19,7 @@ *

    * This package provides support for pooling of ManagedConnections. A managed * connection is responsible for managing a database connection in a - * transactional environment (typically called Container Managed). + * transactional environment (typically called Container Managed). * A managed connection operates like any other connection when no global * transaction (a.k.a. XA transaction or JTA Transaction) is in progress. * When a global transaction is active a single physical connection to the diff --git a/src/main/java/org/apache/commons/dbcp2/package-info.java b/src/main/java/org/apache/commons/dbcp2/package-info.java index 7fbc736a5d..61d0e38c28 100644 --- a/src/main/java/org/apache/commons/dbcp2/package-info.java +++ b/src/main/java/org/apache/commons/dbcp2/package-info.java @@ -19,7 +19,7 @@ *

    * Database Connection Pool API. *

    - * Overview in Dialog Form + * Overview in Dialog Form *

    * Q: How do I use the DBCP package? *

    diff --git a/src/site/xdoc/configuration.xml b/src/site/xdoc/configuration.xml index 9579736544..9f6ce90011 100644 --- a/src/site/xdoc/configuration.xml +++ b/src/site/xdoc/configuration.xml @@ -498,6 +498,14 @@ the parent connection. fastFailValidation is set to true. + + disconnectionIgnoreSqlCodes + null + Comma-delimited list of SQL State codes that should be ignored when determining fatal disconnection errors. + These codes will not trigger a fatal disconnection status, even if they match the usual criteria. + Setting this property has no effect unless fastFailValidation is set to true. + + jmxName diff --git a/src/site/xdoc/download_dbcp.xml b/src/site/xdoc/download_dbcp.xml index 6488e7a615..175bee975f 100644 --- a/src/site/xdoc/download_dbcp.xml +++ b/src/site/xdoc/download_dbcp.xml @@ -1,186 +1,186 @@ - - - - - - Download Apache Commons DBCP - Apache Commons Documentation Team - - -
    - -

    - We recommend you use a mirror to download our release - builds, but you must verify the integrity of - the downloaded files using signatures downloaded from our main - distribution directories. Recent releases (48 hours) may not yet - be available from all the mirrors. -

    - -

    - You are currently using [preferred]. If you - encounter a problem with this mirror, please select another - mirror. If all mirrors are failing, there are backup - mirrors (at the end of the mirrors list) that should be - available. -

    - [if-any logo][end] -

    - -
    -

    - Other mirrors: - - -

    -
    - -

    - It is essential that you - verify the integrity - of downloaded files, preferably using the PGP signature (*.asc files); - failing that using the SHA512 hash (*.sha512 checksum files). -

    -

    - The KEYS - file contains the public PGP keys used by Apache Commons developers - to sign releases. -

    -
    -
    -
    - - - - - - - - - - - - -
    commons-dbcp2-2.12.0-bin.tar.gzsha512pgp
    commons-dbcp2-2.12.0-bin.zipsha512pgp
    -
    - - - - - - - - - - - - -
    commons-dbcp2-2.12.0-src.tar.gzsha512pgp
    commons-dbcp2-2.12.0-src.zipsha512pgp
    -
    -
    -
    - - - - - - - - - - - - -
    commons-dbcp2-2.4.0-bin.tar.gzsha256pgp
    commons-dbcp2-2.4.0-bin.zipsha256pgp
    -
    - - - - - - - - - - - - -
    commons-dbcp2-2.4.0-src.tar.gzsha256pgp
    commons-dbcp2-2.4.0-src.zipsha256pgp
    -
    -
    -
    -

    - Older releases can be obtained from the archives. -

    - -
    - -
    + + + + + + Download Apache Commons DBCP + Apache Commons Documentation Team + + +
    + +

    + We recommend you use a mirror to download our release + builds, but you must verify the integrity of + the downloaded files using signatures downloaded from our main + distribution directories. Recent releases (48 hours) may not yet + be available from all the mirrors. +

    + +

    + You are currently using [preferred]. If you + encounter a problem with this mirror, please select another + mirror. If all mirrors are failing, there are backup + mirrors (at the end of the mirrors list) that should be + available. +

    + [if-any logo][end] +

    + +
    +

    + Other mirrors: + + +

    +
    + +

    + It is essential that you + verify the integrity + of downloaded files, preferably using the PGP signature (*.asc files); + failing that using the SHA512 hash (*.sha512 checksum files). +

    +

    + The KEYS + file contains the public PGP keys used by Apache Commons developers + to sign releases. +

    +
    +
    +
    + + + + + + + + + + + + +
    commons-dbcp2-2.13.0-bin.tar.gzsha512pgp
    commons-dbcp2-2.13.0-bin.zipsha512pgp
    +
    + + + + + + + + + + + + +
    commons-dbcp2-2.13.0-src.tar.gzsha512pgp
    commons-dbcp2-2.13.0-src.zipsha512pgp
    +
    +
    +
    + + + + + + + + + + + + +
    commons-dbcp2-2.4.0-bin.tar.gzsha256pgp
    commons-dbcp2-2.4.0-bin.zipsha256pgp
    +
    + + + + + + + + + + + + +
    commons-dbcp2-2.4.0-src.tar.gzsha256pgp
    commons-dbcp2-2.4.0-src.zipsha256pgp
    +
    +
    +
    +

    + Older releases can be obtained from the archives. +

    + +
    + +
    diff --git a/src/site/xdoc/issue-tracking.xml b/src/site/xdoc/issue-tracking.xml index eefb84c44a..64bb739fde 100644 --- a/src/site/xdoc/issue-tracking.xml +++ b/src/site/xdoc/issue-tracking.xml @@ -1,102 +1,102 @@ - - - - - - Apache Commons DBCP Issue tracking - Apache Commons Documentation Team - - - -
    -

    - Apache Commons DBCP uses ASF JIRA for tracking issues. - See the Apache Commons DBCP JIRA project page. -

    - -

    - To use JIRA you may need to create an account - (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically - created and you can use the Forgot Password - page to get a new password). -

    - -

    - If you would like to report a bug, or raise an enhancement request with - Apache Commons DBCP please do the following: -

      -
    1. Search existing open bugs. - If you find your issue listed then please add a comment with your details.
    2. -
    3. Search the mailing list archive(s). - You may find your issue or idea has already been discussed.
    4. -
    5. Decide if your issue is a bug or an enhancement.
    6. -
    7. Submit either a bug report - or enhancement request.
    8. -
    -

    - -

    - Please also remember these points: -

      -
    • the more information you provide, the better we can help you
    • -
    • test cases are vital, particularly for any proposed enhancements
    • -
    • the developers of Apache Commons DBCP are all unpaid volunteers
    • -
    -

    - -

    - For more information on creating patches see the - Apache Contributors Guide. -

    - -

    - You may also find these links useful: -

    -

    -
    - -
    + + + + + + Apache Commons DBCP Issue tracking + Apache Commons Documentation Team + + + +
    +

    + Apache Commons DBCP uses ASF JIRA for tracking issues. + See the Apache Commons DBCP JIRA project page. +

    + +

    + To use JIRA you may need to create an account + (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically + created and you can use the Forgot Password + page to get a new password). +

    + +

    + If you would like to report a bug, or raise an enhancement request with + Apache Commons DBCP please do the following: +

      +
    1. Search existing open bugs. + If you find your issue listed then please add a comment with your details.
    2. +
    3. Search the mailing list archive(s). + You may find your issue or idea has already been discussed.
    4. +
    5. Decide if your issue is a bug or an enhancement.
    6. +
    7. Submit either a bug report + or enhancement request.
    8. +
    +

    + +

    + Please also remember these points: +

      +
    • the more information you provide, the better we can help you
    • +
    • test cases are vital, particularly for any proposed enhancements
    • +
    • the developers of Apache Commons DBCP are all unpaid volunteers
    • +
    +

    + +

    + For more information on creating patches see the + Apache Contributors Guide. +

    + +

    + You may also find these links useful: +

    +

    +
    + +
    diff --git a/src/test/java/org/apache/commons/dbcp2/AbstractDriverTest.java b/src/test/java/org/apache/commons/dbcp2/AbstractDriverTest.java new file mode 100644 index 0000000000..b1f28dac91 --- /dev/null +++ b/src/test/java/org/apache/commons/dbcp2/AbstractDriverTest.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.dbcp2; + +import java.sql.DriverManager; +import java.sql.SQLException; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +/** + * Abstracts testing a JDBC driver. + */ +public abstract class AbstractDriverTest { + + //private static final String KEY_JDBC_DRIVERS = "jdbc.drivers"; + + @AfterAll + public static void afterClass() throws SQLException { + //System.clearProperty(KEY_JDBC_DRIVERS); + DriverManager.deregisterDriver(TesterDriver.INSTANCE); + } + + @BeforeAll + public static void beforeClass() throws SQLException { + //System.setProperty(KEY_JDBC_DRIVERS, "org.apache.commons.dbcp2.TesterDriver"); + DriverManager.registerDriver(TesterDriver.INSTANCE); + } + +} diff --git a/src/test/java/org/apache/commons/dbcp2/Jdbc41BridgeTest.java b/src/test/java/org/apache/commons/dbcp2/Jdbc41BridgeTest.java new file mode 100644 index 0000000000..d982909e1f --- /dev/null +++ b/src/test/java/org/apache/commons/dbcp2/Jdbc41BridgeTest.java @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.dbcp2; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.h2.jdbcx.JdbcDataSource; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +/** + * Tests {@link Jdbc41Bridge}. + */ +public class Jdbc41BridgeTest { + + private Connection getConnection() throws SQLException { + return DriverManager.getConnection("jdbc:h2:mem:test"); + } + + @SuppressWarnings("resource") + @Test + public void testAbort() throws SQLException { + // Normal + try (Connection conn = getConnection()) { + Jdbc41Bridge.abort(conn, r -> { + // empty for now + }); + } + // Force AbstractMethodError + try (Connection conn = getConnection()) { + final Connection spy = Mockito.spy(conn); + Mockito.doThrow(new AbstractMethodError()).when(spy).abort(r -> { + // empty for now + }); + Jdbc41Bridge.abort(spy, r -> { + // empty for now + }); + } + } + + @SuppressWarnings("resource") + @Test + public void testCloseOnCompletion() throws SQLException { + // Normal + try (Connection conn = getConnection(); + Statement stmt = conn.createStatement()) { + Jdbc41Bridge.closeOnCompletion(stmt); + } + // Force AbstractMethodError + try (Connection conn = getConnection(); + Statement stmt = conn.createStatement()) { + final Statement spy = Mockito.spy(stmt); + Mockito.doThrow(new AbstractMethodError()).when(spy).closeOnCompletion(); + Jdbc41Bridge.closeOnCompletion(spy); + } + } + + @SuppressWarnings("resource") + @Test + public void testGeneratedKeyAlwaysReturned() throws SQLException { + // Normal + try (Connection conn = getConnection()) { + assertTrue(Jdbc41Bridge.generatedKeyAlwaysReturned(conn.getMetaData())); + } + // Cannot mock a final class + // Force AbstractMethodError +// try (Connection conn = getConnection()) { +// final DatabaseMetaData spy = Mockito.spy(conn.getMetaData()); +// Mockito.when(spy.generatedKeyAlwaysReturned()).thenThrow(AbstractMethodError.class); +// assertTrue(Jdbc41Bridge.generatedKeyAlwaysReturned(spy)); +// } + } + + @Test + public void testGetNetworkTimeout() throws SQLException { + // Normal + try (Connection conn = getConnection()) { + Jdbc41Bridge.setNetworkTimeout(conn, r -> { + }, 30_000); + // noop in H2 + assertEquals(0, Jdbc41Bridge.getNetworkTimeout(conn)); + } + } + + @Test + public void testGetObjectIndex() throws SQLException { + // Normal + try (Connection conn = getConnection(); + ResultSet rs = conn.getMetaData().getTypeInfo()) { + rs.next(); + assertNotNull(Jdbc41Bridge.getObject(rs, 1, String.class)); + // + assertNotNull(Jdbc41Bridge.getObject(rs, 2, Integer.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, 2, Long.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, 2, Double.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, 2, Float.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, 2, Byte.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, 2, BigDecimal.class)); + // + assertNotNull(Jdbc41Bridge.getObject(rs, 7, Short.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, 8, Boolean.class)); + } + } + + @Test + public void testGetObjectName() throws SQLException { + // Normal + try (Connection conn = getConnection(); + ResultSet rs = conn.getMetaData().getTypeInfo()) { + rs.next(); + assertNotNull(Jdbc41Bridge.getObject(rs, "TYPE_NAME", String.class)); + // + assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Integer.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Long.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Double.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Float.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Byte.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", BigDecimal.class)); + // + assertNotNull(Jdbc41Bridge.getObject(rs, "NULLABLE", Short.class)); + assertNotNull(Jdbc41Bridge.getObject(rs, "CASE_SENSITIVE", Boolean.class)); + } + } + + @Test + public void testGetParentLogger() throws SQLException { + // Normal + try (Connection conn = getConnection(); + Statement stmt = conn.createStatement()) { + // returns null for H2 (not supported). + Jdbc41Bridge.getParentLogger(new JdbcDataSource()); + } + } + + @SuppressWarnings("resource") + @Test + public void testGetSchema() throws SQLException { + // Normal + try (Connection conn = getConnection()) { + assertNotNull(Jdbc41Bridge.getSchema(conn)); + final Connection spy = Mockito.spy(conn); + Mockito.when(spy.getSchema()).thenThrow(AbstractMethodError.class); + assertNull(Jdbc41Bridge.getSchema(spy)); + } + } + + @Test + public void testIsCloseOnCompletion() throws SQLException { + // Normal + try (Connection conn = getConnection(); + Statement stmt = conn.createStatement()) { + assertFalse(Jdbc41Bridge.isCloseOnCompletion(stmt)); + } + } + + @Test + public void testSetNetworkTimeout() throws SQLException { + // Normal + try (Connection conn = getConnection(); + Statement stmt = conn.createStatement()) { + // noop in H2 + Jdbc41Bridge.setNetworkTimeout(conn, r -> { + // empty for now + }, 30_0000); + assertEquals(0, Jdbc41Bridge.getNetworkTimeout(conn)); + } + } + + @Test + public void testSetSchema() throws SQLException { + // Normal + try (Connection conn = getConnection(); + Statement stmt = conn.createStatement()) { + Jdbc41Bridge.setSchema(conn, Jdbc41Bridge.getSchema(conn)); + final String expected = "PUBLIC"; + Jdbc41Bridge.setSchema(conn, expected); + assertEquals(expected, Jdbc41Bridge.getSchema(conn)); + } + } +} diff --git a/src/test/java/org/apache/commons/dbcp2/TestAbandonedBasicDataSource.java b/src/test/java/org/apache/commons/dbcp2/TestAbandonedBasicDataSource.java index bdaac7803b..0f6232a490 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestAbandonedBasicDataSource.java +++ b/src/test/java/org/apache/commons/dbcp2/TestAbandonedBasicDataSource.java @@ -53,7 +53,6 @@ private void assertAndReset(final DelegatingConnection con) { con.setLastUsed(Instant.EPOCH); } - // ---------- Abandoned Test ----------- /** * Verifies that PreparedStatement executeXxx methods update lastUsed on the parent connection diff --git a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java index 47a6d58062..bffe838723 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java +++ b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java @@ -17,9 +17,9 @@ package org.apache.commons.dbcp2; -import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashSet; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; @@ -47,7 +48,6 @@ import javax.management.ObjectName; import javax.sql.DataSource; -import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -111,7 +111,7 @@ public void testAccessToUnderlyingConnectionAllowed() throws Exception { dconn = ((DelegatingConnection) conn).getInnermostDelegate(); assertNotNull(dconn); - assertTrue(dconn instanceof TesterConnection); + assertInstanceOf(TesterConnection.class, dconn); } } @@ -439,6 +439,21 @@ public void testDeprecatedAccessors() throws SQLException { } } + @Test + public void testDisconnectionIgnoreSqlCodes() throws Exception { + final ArrayList disconnectionIgnoreSqlCodes = new ArrayList<>(); + disconnectionIgnoreSqlCodes.add("XXXX"); + ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); + ds.setFastFailValidation(true); + try (Connection conn = ds.getConnection()) { // Triggers initialization - pcf creation + // Make sure factory got the properties + final PoolableConnectionFactory pcf = (PoolableConnectionFactory) ds.getConnectionPool().getFactory(); + assertTrue(pcf.isFastFailValidation()); + assertTrue(pcf.getDisconnectionIgnoreSqlCodes().contains("XXXX")); + assertEquals(1, pcf.getDisconnectionIgnoreSqlCodes().size()); + } + } + /** * JIRA: DBCP-437 * Verify that BasicDataSource sets disconnect codes properties. @@ -468,7 +483,7 @@ public void testDriverClassLoader() throws Exception { try (Connection conn = getConnection()) { final ClassLoader cl = ds.getDriverClassLoader(); assertNotNull(cl); - assertTrue(cl instanceof TesterClassLoader); + assertInstanceOf(TesterClassLoader.class, cl); assertTrue(((TesterClassLoader) cl).didLoad(ds.getDriverClassName())); } } @@ -560,8 +575,7 @@ public void testInstanceNotFoundExceptionLogSuppressed() throws Exception { } StackMessageLog.clear(); ds.close(); - assertThat(StackMessageLog.popMessage(), - CoreMatchers.not(CoreMatchers.containsString("InstanceNotFoundException"))); + assertNull(StackMessageLog.popMessage()); assertNull(ds.getRegisteredJmxName()); } @@ -582,15 +596,15 @@ public void testInvalidateConnection() throws Exception { } @Test - public void testInvalidConnectionInitSqlList() { - ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "invalid")); + public void testInvalidConnectionInitSqlCollection() { + ds.setConnectionInitSqls((Collection) Arrays.asList("SELECT 1", "invalid")); final SQLException e = assertThrows(SQLException.class, ds::getConnection); assertTrue(e.toString().contains("invalid")); } @Test - public void testInvalidConnectionInitSqlCollection() { - ds.setConnectionInitSqls((Collection) Arrays.asList("SELECT 1", "invalid")); + public void testInvalidConnectionInitSqlList() { + ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "invalid")); final SQLException e = assertThrows(SQLException.class, ds::getConnection); assertTrue(e.toString().contains("invalid")); } @@ -658,23 +672,14 @@ public void testJmxDisabled() throws Exception { @Test public void testJmxDoesNotExposePassword() throws Exception { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - try (Connection c = ds.getConnection()) { // nothing } final ObjectName objectName = new ObjectName(ds.getJmxName()); - final MBeanAttributeInfo[] attributes = mbs.getMBeanInfo(objectName).getAttributes(); - assertTrue(attributes != null && attributes.length > 0); - - Arrays.asList(attributes).forEach(attrInfo -> { - assertFalse("password".equalsIgnoreCase(attrInfo.getName())); - }); - - assertThrows(AttributeNotFoundException.class, () -> { - mbs.getAttribute(objectName, "Password"); - }); + Arrays.asList(attributes).forEach(attrInfo -> assertFalse("password".equalsIgnoreCase(attrInfo.getName()))); + assertThrows(AttributeNotFoundException.class, () -> mbs.getAttribute(objectName, "Password")); } @Test @@ -784,6 +789,33 @@ public void testNoAccessToUnderlyingConnectionAllowed() throws Exception { } } + @Test + public void testNoOverlapBetweenDisconnectionAndIgnoreSqlCodes() { + // Set disconnection SQL codes without overlap + final HashSet disconnectionSqlCodes = new HashSet<>(Arrays.asList("XXX", "ZZZ")); + ds.setDisconnectionSqlCodes(disconnectionSqlCodes); + + // Set ignore SQL codes without overlap + final HashSet disconnectionIgnoreSqlCodes = new HashSet<>(Arrays.asList("YYY", "AAA")); + ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); + + assertEquals(disconnectionSqlCodes, ds.getDisconnectionSqlCodes(), "Disconnection SQL codes should match the set values."); + assertEquals(disconnectionIgnoreSqlCodes, ds.getDisconnectionIgnoreSqlCodes(), "Disconnection Ignore SQL codes should match the set values."); + } + + @Test + public void testOverlapBetweenDisconnectionAndIgnoreSqlCodes() { + // Set initial disconnection SQL codes + final HashSet disconnectionSqlCodes = new HashSet<>(Arrays.asList("XXX", "ZZZ")); + ds.setDisconnectionSqlCodes(disconnectionSqlCodes); + // Try setting ignore SQL codes with overlap + final HashSet disconnectionIgnoreSqlCodes = new HashSet<>(Arrays.asList("YYY", "XXX")); + + final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes)); + assertEquals("[XXX] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); + } + /** * Verifies correct handling of exceptions generated by the underlying pool as it closes * connections in response to BDS#close. Exceptions have to be either swallowed by the diff --git a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSourceMXBean.java b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSourceMXBean.java index 246fef1511..56b78fc710 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSourceMXBean.java +++ b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSourceMXBean.java @@ -78,6 +78,11 @@ public int getDefaultTransactionIsolation() { return 0; } + @Override + public String[] getDisconnectionIgnoreSqlCodesAsArray() { + return null; + } + @Override public String[] getDisconnectionSqlCodesAsArray() { return null; diff --git a/src/test/java/org/apache/commons/dbcp2/TestConnectionPool.java b/src/test/java/org/apache/commons/dbcp2/TestConnectionPool.java index 597d2cab59..7f09aab92a 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestConnectionPool.java +++ b/src/test/java/org/apache/commons/dbcp2/TestConnectionPool.java @@ -164,37 +164,37 @@ public void stop() { } final class TestThread implements Runnable { - final java.util.Random _random = new java.util.Random(); - boolean _complete; - boolean _failed; - int _iter = 100; - int _delay = 50; + final Random random = new Random(); + boolean complete; + boolean failed; + int iter = 100; + int delay = 50; public TestThread() { } public TestThread(final int iter) { - _iter = iter; + this.iter = iter; } public TestThread(final int iter, final int delay) { - _iter = iter; - _delay = delay; + this.iter = iter; + this.delay = delay; } public boolean complete() { - return _complete; + return complete; } public boolean failed() { - return _failed; + return failed; } @Override public void run() { - for (int i = 0; i < _iter; i++) { + for (int i = 0; i < iter; i++) { try { - Thread.sleep(_random.nextInt(_delay)); + Thread.sleep(random.nextInt(delay)); } catch (final Exception e) { // ignored } @@ -202,18 +202,18 @@ public void run() { PreparedStatement stmt = conn.prepareStatement("select 'literal', SYSDATE from dual"); ResultSet rset = stmt.executeQuery()) { try { - Thread.sleep(_random.nextInt(_delay)); + Thread.sleep(random.nextInt(delay)); } catch (final Exception ignore) { // ignored } } catch (final Exception e) { e.printStackTrace(); - _failed = true; - _complete = true; + failed = true; + complete = true; break; } } - _complete = true; + complete = true; } } @@ -232,7 +232,6 @@ public void run() { /** Connections opened during the course of a test */ protected final Stack connectionStack = new Stack<>(); - // ----------- Utility Methods --------------------------------- protected void assertBackPointers(final Connection conn, final Statement statement) throws SQLException { assertFalse(conn.isClosed()); diff --git a/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java b/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java index 3519b171b4..f29273c66a 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java +++ b/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java @@ -20,33 +20,38 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; +import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Savepoint; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** + * Tests {@link DelegatingConnection}. */ public class TestDelegatingConnection { /** - * Delegate that doesn't support read-only or auto-commit. - * It will merely take the input value of setReadOnly and - * setAutoCommit and discard it, to keep false. + * Delegate that doesn't support read-only or auto-commit. It will merely take the input value of setReadOnly and setAutoCommit and discard it, to keep + * false. */ static class NoReadOnlyOrAutoCommitConnection extends TesterConnection { private final boolean readOnly = false; private final boolean autoCommit = false; public NoReadOnlyOrAutoCommitConnection() { - super("",""); + super("", ""); } @Override @@ -71,13 +76,12 @@ public void setReadOnly(final boolean readOnly) { } /** - * Delegate that will throw RTE on toString - * Used to validate fix for DBCP-241 + * Delegate that will throw RTE on toString Used to validate fix for DBCP-241 */ static class RTEGeneratingConnection extends TesterConnection { public RTEGeneratingConnection() { - super("",""); + super("", ""); } @Override @@ -90,9 +94,15 @@ public String toString() { private DelegatingConnection delegatingConnection; private Connection connection; private Connection connection2; + private DelegatingConnection h2DConnection; private TesterStatement testerStatement; private TesterResultSet testerResultSet; + @AfterEach + public void afterEach() throws SQLException { + h2DConnection.close(); + } + @BeforeEach public void setUp() throws Exception { connection = new TesterConnection("test", "test"); @@ -100,6 +110,13 @@ public void setUp() throws Exception { delegatingConnection = new DelegatingConnection<>(connection); testerStatement = new TesterStatement(delegatingConnection); testerResultSet = new TesterResultSet(testerStatement); + h2DConnection = new DelegatingConnection<>(DriverManager.getConnection("jdbc:h2:mem:test")); + } + + @Test + public void testAbort() throws Exception { + h2DConnection.abort(r -> { + }); } @Test @@ -153,7 +170,8 @@ public void testCheckOpenNull() throws Exception { delegatingConnection = new DelegatingConnection<>(pc); pc.close(); delegatingConnection.close(); - try (PreparedStatement ps = delegatingConnection.prepareStatement("")){} + try (PreparedStatement ps = delegatingConnection.prepareStatement("")) { + } fail("Expecting SQLException"); } catch (final SQLException ex) { assertTrue(ex.getMessage().endsWith("is closed.")); @@ -169,6 +187,11 @@ public void testCheckOpenNull() throws Exception { } } + @Test + public void testCommit() throws Exception { + h2DConnection.commit(); + } + @Test public void testConnectionToString() throws Exception { final String s = delegatingConnection.toString(); @@ -176,11 +199,82 @@ public void testConnectionToString() throws Exception { assertFalse(s.isEmpty()); } + @Test + public void testCreateArrayOf() throws Exception { + assertNotNull(h2DConnection.createArrayOf("CHARACTER", new Object[] { "A", "B" })); + } + + @Test + public void testCreateBlob() throws Exception { + assertNotNull(h2DConnection.createBlob()); + } + + @Test + public void testCreateClob() throws Exception { + assertNotNull(h2DConnection.createClob()); + } + + @Test + public void testCreateNClob() throws Exception { + assertNotNull(h2DConnection.createNClob()); + } + + @Test + public void testCreateSQLXML() throws Exception { + assertNotNull(h2DConnection.createSQLXML()); + } + + @Test + public void testCreateStruct() throws Exception { + // not supported by H2 + assertThrows(SQLException.class, () -> h2DConnection.createStruct("CHARACTER", new Object[] { "A", "B" })); + } + + @Test + public void testGetCacheState() throws Exception { + assertTrue(h2DConnection.getCacheState()); + } + + @Test + public void testGetClientInfo() throws Exception { + assertNotNull(h2DConnection.getClientInfo()); + } + + @Test + public void testGetClientInfoString() throws Exception { + assertNull(h2DConnection.getClientInfo("xyz")); + } + + @Test + public void testGetDefaultQueryTimeout() throws Exception { + assertNull(h2DConnection.getDefaultQueryTimeout()); + } + + @Test + public void testGetDefaultQueryTimeoutDuration() throws Exception { + assertNull(h2DConnection.getDefaultQueryTimeoutDuration()); + } + @Test public void testGetDelegate() throws Exception { assertEquals(connection, delegatingConnection.getDelegate()); } + @Test + public void testGetHoldability() throws Exception { + assertEquals(1, h2DConnection.getHoldability()); + } + + @Test + public void testGetNetworkTimeout() throws Exception { + assertEquals(0, h2DConnection.getNetworkTimeout()); + } + + @Test + public void testGetTypeMap() throws Exception { + assertNull(h2DConnection.getTypeMap()); + } + @Test public void testIsClosed() throws Exception { delegatingConnection.checkOpen(); @@ -197,6 +291,19 @@ public void testIsClosedNullDelegate() throws Exception { assertTrue(delegatingConnection.isClosed()); } + @SuppressWarnings("resource") + @Test + public void testIsWrapperFor() throws Exception { + assertTrue(delegatingConnection.isWrapperFor(delegatingConnection.getClass())); + assertTrue(delegatingConnection.isWrapperFor(delegatingConnection.getDelegate().getClass())); + assertThrows(SQLException.class, () -> delegatingConnection.isWrapperFor(Integer.class)); + } + + @Test + public void testNativeSQL() throws Exception { + assertNotNull(h2DConnection.nativeSQL("select 1")); + } + @Test public void testPassivateWithResultSetCloseException() { try { @@ -205,7 +312,7 @@ public void testPassivateWithResultSetCloseException() { delegatingConnection.passivate(); Assertions.fail("Expected SQLExceptionList"); } catch (final SQLException e) { - Assertions.assertTrue(e instanceof SQLExceptionList); + Assertions.assertInstanceOf(SQLExceptionList.class, e); Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size()); } finally { testerResultSet.setSqlExceptionOnClose(false); @@ -222,11 +329,11 @@ public void testPassivateWithResultSetCloseExceptionAndStatementCloseException() delegatingConnection.passivate(); Assertions.fail("Expected SQLExceptionList"); } catch (final SQLException e) { - Assertions.assertTrue(e instanceof SQLExceptionList); + Assertions.assertInstanceOf(SQLExceptionList.class, e); Assertions.assertEquals(2, ((SQLExceptionList) e).getCauseList().size()); } finally { testerStatement.setSqlExceptionOnClose(false); - testerResultSet.setSqlExceptionOnClose(false); + testerResultSet.setSqlExceptionOnClose(false); } } @@ -238,7 +345,7 @@ public void testPassivateWithStatementCloseException() { delegatingConnection.passivate(); Assertions.fail("Expected SQLExceptionList"); } catch (final SQLException e) { - Assertions.assertTrue(e instanceof SQLExceptionList); + Assertions.assertInstanceOf(SQLExceptionList.class, e); Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size()); } finally { testerStatement.setSqlExceptionOnClose(false); @@ -256,4 +363,64 @@ public void testReadOnlyCaching() throws SQLException { assertFalse(delCon.isReadOnly()); } + @Test + public void testReleaseSavepoint() throws Exception { + final Savepoint s = h2DConnection.setSavepoint(); + h2DConnection.releaseSavepoint(s); + } + + @Test + public void testRollback() throws Exception { + h2DConnection.rollback(); + } + + @Test + public void testRollbackSavepoint() throws Exception { + h2DConnection.setAutoCommit(false); + try { + h2DConnection.rollback(h2DConnection.setSavepoint()); + } finally { + h2DConnection.setAutoCommit(true); + } + } + + @Test + public void testSetClientInfo() throws Exception { + // TODO + // h2DConnection.setClientInfo("ApplicationName", "app1"); + } + + @Test + public void testSetDefaultQueryTimeout() throws Exception { + final int expected = 1; + delegatingConnection.setDefaultQueryTimeout(expected); + assertEquals(expected, delegatingConnection.getDefaultQueryTimeout()); + } + + @Test + public void testSetHoldability() throws Exception { + final int expected = 1; + h2DConnection.setHoldability(expected); + assertEquals(expected, h2DConnection.getHoldability()); + } + + @Test + public void testSetNetworkTimeout() throws Exception { + h2DConnection.setNetworkTimeout(r -> {}, 1); + assertEquals(0, h2DConnection.getNetworkTimeout()); + } + + @Test + public void testSetSavepoint() throws Exception { + h2DConnection.setSavepoint(); + } + + @SuppressWarnings("javadoc") + @Test + public void testUnwrap() throws Exception { + assertNotNull(delegatingConnection.unwrap(delegatingConnection.getClass())); + assertNotNull(delegatingConnection.unwrap(delegatingConnection.getDelegate().getClass())); + assertThrows(SQLException.class, () -> delegatingConnection.unwrap(Integer.class)); + } + } diff --git a/src/test/java/org/apache/commons/dbcp2/TestDelegatingDatabaseMetaData.java b/src/test/java/org/apache/commons/dbcp2/TestDelegatingDatabaseMetaData.java index 74886cccac..4ede9de2ef 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestDelegatingDatabaseMetaData.java +++ b/src/test/java/org/apache/commons/dbcp2/TestDelegatingDatabaseMetaData.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -32,6 +33,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; /** * Test suite for {@link DelegatingDatabaseMetaData}. @@ -41,6 +43,7 @@ public class TestDelegatingDatabaseMetaData { private TesterConnection testConn; private DelegatingConnection conn; private DelegatingDatabaseMetaData delegate; + private DelegatingDatabaseMetaData delegateSpy; private DatabaseMetaData obj; @BeforeEach @@ -49,30 +52,49 @@ public void setUp() throws Exception { testConn = new TesterConnection("test", "test"); conn = new DelegatingConnection<>(testConn); delegate = new DelegatingDatabaseMetaData(conn, obj); + delegateSpy = Mockito.spy(delegate); } @Test public void testAllProceduresAreCallable() throws Exception { try { delegate.allProceduresAreCallable(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).allProceduresAreCallable(); + // SQLException + Mockito.when(obj.allProceduresAreCallable()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::allProceduresAreCallable); } @Test public void testAllTablesAreSelectable() throws Exception { try { delegate.allTablesAreSelectable(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).allTablesAreSelectable(); + // SQLException + Mockito.when(obj.allTablesAreSelectable()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::allTablesAreSelectable); } @Test public void testAutoCommitFailureClosesAllResultSets() throws Exception { try { delegate.autoCommitFailureClosesAllResultSets(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).autoCommitFailureClosesAllResultSets(); + // SQLException + Mockito.when(obj.autoCommitFailureClosesAllResultSets()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::autoCommitFailureClosesAllResultSets); } @Test @@ -88,156 +110,242 @@ public void testCheckOpen() throws Exception { public void testDataDefinitionCausesTransactionCommit() throws Exception { try { delegate.dataDefinitionCausesTransactionCommit(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).dataDefinitionCausesTransactionCommit(); + // SQLException + Mockito.when(obj.dataDefinitionCausesTransactionCommit()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::dataDefinitionCausesTransactionCommit); } @Test public void testDataDefinitionIgnoredInTransactions() throws Exception { try { delegate.dataDefinitionIgnoredInTransactions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).dataDefinitionIgnoredInTransactions(); + // SQLException + Mockito.when(obj.dataDefinitionIgnoredInTransactions()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::dataDefinitionIgnoredInTransactions); } @Test public void testDeletesAreDetectedInteger() throws Exception { try { delegate.deletesAreDetected(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).deletesAreDetected(1); + // SQLException + Mockito.when(obj.deletesAreDetected(1)).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, () -> delegate.deletesAreDetected(1)); } @Test public void testDoesMaxRowSizeIncludeBlobs() throws Exception { try { delegate.doesMaxRowSizeIncludeBlobs(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).doesMaxRowSizeIncludeBlobs(); + // SQLException + Mockito.when(obj.doesMaxRowSizeIncludeBlobs()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::doesMaxRowSizeIncludeBlobs); } @Test public void testGeneratedKeyAlwaysReturned() throws Exception { try { delegate.generatedKeyAlwaysReturned(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).generatedKeyAlwaysReturned(); + // SQLException + Mockito.when(obj.generatedKeyAlwaysReturned()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::generatedKeyAlwaysReturned); } @Test public void testGetAttributesStringStringStringString() throws Exception { try { - delegate.getAttributes("foo","foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getAttributes("foo","foo","foo","foo"); + delegate.getAttributes("foo", "foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getAttributes("foo", "foo", "foo", "foo"); } @Test public void testGetBestRowIdentifierStringStringStringIntegerBoolean() throws Exception { try { - delegate.getBestRowIdentifier("foo","foo","foo",1,Boolean.TRUE); - } catch (final SQLException e) {} - verify(obj, times(1)).getBestRowIdentifier("foo","foo","foo",1,Boolean.TRUE); + delegate.getBestRowIdentifier("foo", "foo", "foo", 1, Boolean.TRUE); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getBestRowIdentifier("foo", "foo", "foo", 1, Boolean.TRUE); } @Test public void testGetCatalogs() throws Exception { try { delegate.getCatalogs(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getCatalogs(); + // SQLException + Mockito.when(obj.getCatalogs()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::getCatalogs); } @Test public void testGetCatalogSeparator() throws Exception { try { delegate.getCatalogSeparator(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getCatalogSeparator(); + // SQLException + Mockito.when(obj.getCatalogSeparator()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::getCatalogSeparator); } @Test public void testGetCatalogTerm() throws Exception { try { delegate.getCatalogTerm(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getCatalogTerm(); + // SQLException + Mockito.when(obj.getCatalogTerm()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::getCatalogTerm); } @Test public void testGetClientInfoProperties() throws Exception { try { delegate.getClientInfoProperties(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getClientInfoProperties(); + // SQLException + Mockito.when(obj.getClientInfoProperties()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::getClientInfoProperties); } @Test public void testGetColumnPrivilegesStringStringStringString() throws Exception { try { - delegate.getColumnPrivileges("foo","foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getColumnPrivileges("foo","foo","foo","foo"); + delegate.getColumnPrivileges("foo", "foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getColumnPrivileges("foo", "foo", "foo", "foo"); } @Test public void testGetColumnsStringStringStringString() throws Exception { try { - delegate.getColumns("foo","foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getColumns("foo","foo","foo","foo"); + delegate.getColumns("foo", "foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getColumns("foo", "foo", "foo", "foo"); } /** - * This method is a bit special, and doesn't call the method on the wrapped object, - * instead returning the connection from the delegate object itself. + * This method is a bit special, and doesn't call the method on the wrapped object, instead returning the connection from the delegate object itself. + * * @throws Exception */ @Test public void testGetConnection() throws Exception { try { delegate.getConnection(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(0)).getConnection(); } @Test public void testGetCrossReferenceStringStringStringStringStringString() throws Exception { try { - delegate.getCrossReference("foo","foo","foo","foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getCrossReference("foo","foo","foo","foo","foo","foo"); + delegate.getCrossReference("foo", "foo", "foo", "foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getCrossReference("foo", "foo", "foo", "foo", "foo", "foo"); } @Test public void testGetDatabaseMajorVersion() throws Exception { try { delegate.getDatabaseMajorVersion(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getDatabaseMajorVersion(); + // SQLException + Mockito.when(obj.getDatabaseMajorVersion()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::getDatabaseMajorVersion); } @Test public void testGetDatabaseMinorVersion() throws Exception { try { delegate.getDatabaseMinorVersion(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getDatabaseMinorVersion(); + // SQLException + Mockito.when(obj.getDatabaseMinorVersion()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::getDatabaseMinorVersion); } @Test public void testGetDatabaseProductName() throws Exception { try { delegate.getDatabaseProductName(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getDatabaseProductName(); + // SQLException + Mockito.when(obj.getDatabaseProductName()).thenThrow(SQLException.class); + // The default handler rethrows + assertThrows(SQLException.class, delegate::getDatabaseProductName); } @Test public void testGetDatabaseProductVersion() throws Exception { try { delegate.getDatabaseProductVersion(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getDatabaseProductVersion(); } @@ -245,13 +353,15 @@ public void testGetDatabaseProductVersion() throws Exception { public void testGetDefaultTransactionIsolation() throws Exception { try { delegate.getDefaultTransactionIsolation(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getDefaultTransactionIsolation(); } @Test public void testGetDelegate() throws Exception { - assertEquals(obj ,delegate.getDelegate()); + assertEquals(obj, delegate.getDelegate()); } @Test @@ -270,7 +380,9 @@ public void testGetDriverMinorVersion() throws Exception { public void testGetDriverName() throws Exception { try { delegate.getDriverName(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getDriverName(); } @@ -278,71 +390,94 @@ public void testGetDriverName() throws Exception { public void testGetDriverVersion() throws Exception { try { delegate.getDriverVersion(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getDriverVersion(); } @Test public void testGetExportedKeysStringStringString() throws Exception { try { - delegate.getExportedKeys("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getExportedKeys("foo","foo","foo"); + delegate.getExportedKeys("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getExportedKeys("foo", "foo", "foo"); } @Test public void testGetExtraNameCharacters() throws Exception { try { delegate.getExtraNameCharacters(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getExtraNameCharacters(); } @Test public void testGetFunctionColumnsStringStringStringString() throws Exception { try { - delegate.getFunctionColumns("foo","foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getFunctionColumns("foo","foo","foo","foo"); + delegate.getFunctionColumns("foo", "foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getFunctionColumns("foo", "foo", "foo", "foo"); } @Test public void testGetFunctionsStringStringString() throws Exception { try { - delegate.getFunctions("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getFunctions("foo","foo","foo"); + delegate.getFunctions("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getFunctions("foo", "foo", "foo"); } @Test public void testGetIdentifierQuoteString() throws Exception { try { delegate.getIdentifierQuoteString(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getIdentifierQuoteString(); } @Test public void testGetImportedKeysStringStringString() throws Exception { try { - delegate.getImportedKeys("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getImportedKeys("foo","foo","foo"); + delegate.getImportedKeys("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getImportedKeys("foo", "foo", "foo"); } @Test public void testGetIndexInfoStringStringStringBooleanBoolean() throws Exception { try { - delegate.getIndexInfo("foo","foo","foo",Boolean.TRUE,Boolean.TRUE); - } catch (final SQLException e) {} - verify(obj, times(1)).getIndexInfo("foo","foo","foo",Boolean.TRUE,Boolean.TRUE); + delegate.getIndexInfo("foo", "foo", "foo", Boolean.TRUE, Boolean.TRUE); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getIndexInfo("foo", "foo", "foo", Boolean.TRUE, Boolean.TRUE); + } + + @Test + public void testGetInnermostDelegate() { + assertNotNull(delegate.getInnermostDelegate()); } @Test public void testGetJDBCMajorVersion() throws Exception { try { delegate.getJDBCMajorVersion(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getJDBCMajorVersion(); } @@ -350,7 +485,9 @@ public void testGetJDBCMajorVersion() throws Exception { public void testGetJDBCMinorVersion() throws Exception { try { delegate.getJDBCMinorVersion(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getJDBCMinorVersion(); } @@ -358,7 +495,9 @@ public void testGetJDBCMinorVersion() throws Exception { public void testGetMaxBinaryLiteralLength() throws Exception { try { delegate.getMaxBinaryLiteralLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxBinaryLiteralLength(); } @@ -366,7 +505,9 @@ public void testGetMaxBinaryLiteralLength() throws Exception { public void testGetMaxCatalogNameLength() throws Exception { try { delegate.getMaxCatalogNameLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxCatalogNameLength(); } @@ -374,7 +515,9 @@ public void testGetMaxCatalogNameLength() throws Exception { public void testGetMaxCharLiteralLength() throws Exception { try { delegate.getMaxCharLiteralLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxCharLiteralLength(); } @@ -382,7 +525,9 @@ public void testGetMaxCharLiteralLength() throws Exception { public void testGetMaxColumnNameLength() throws Exception { try { delegate.getMaxColumnNameLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxColumnNameLength(); } @@ -390,7 +535,9 @@ public void testGetMaxColumnNameLength() throws Exception { public void testGetMaxColumnsInGroupBy() throws Exception { try { delegate.getMaxColumnsInGroupBy(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxColumnsInGroupBy(); } @@ -398,7 +545,9 @@ public void testGetMaxColumnsInGroupBy() throws Exception { public void testGetMaxColumnsInIndex() throws Exception { try { delegate.getMaxColumnsInIndex(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxColumnsInIndex(); } @@ -406,7 +555,9 @@ public void testGetMaxColumnsInIndex() throws Exception { public void testGetMaxColumnsInOrderBy() throws Exception { try { delegate.getMaxColumnsInOrderBy(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxColumnsInOrderBy(); } @@ -414,7 +565,9 @@ public void testGetMaxColumnsInOrderBy() throws Exception { public void testGetMaxColumnsInSelect() throws Exception { try { delegate.getMaxColumnsInSelect(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxColumnsInSelect(); } @@ -422,7 +575,9 @@ public void testGetMaxColumnsInSelect() throws Exception { public void testGetMaxColumnsInTable() throws Exception { try { delegate.getMaxColumnsInTable(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxColumnsInTable(); } @@ -430,7 +585,9 @@ public void testGetMaxColumnsInTable() throws Exception { public void testGetMaxConnections() throws Exception { try { delegate.getMaxConnections(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxConnections(); } @@ -438,7 +595,9 @@ public void testGetMaxConnections() throws Exception { public void testGetMaxCursorNameLength() throws Exception { try { delegate.getMaxCursorNameLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxCursorNameLength(); } @@ -446,7 +605,9 @@ public void testGetMaxCursorNameLength() throws Exception { public void testGetMaxIndexLength() throws Exception { try { delegate.getMaxIndexLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxIndexLength(); } @@ -454,7 +615,9 @@ public void testGetMaxIndexLength() throws Exception { public void testGetMaxLogicalLobSize() throws Exception { try { delegate.getMaxLogicalLobSize(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxLogicalLobSize(); } @@ -462,7 +625,9 @@ public void testGetMaxLogicalLobSize() throws Exception { public void testGetMaxProcedureNameLength() throws Exception { try { delegate.getMaxProcedureNameLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxProcedureNameLength(); } @@ -470,7 +635,9 @@ public void testGetMaxProcedureNameLength() throws Exception { public void testGetMaxRowSize() throws Exception { try { delegate.getMaxRowSize(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxRowSize(); } @@ -478,7 +645,9 @@ public void testGetMaxRowSize() throws Exception { public void testGetMaxSchemaNameLength() throws Exception { try { delegate.getMaxSchemaNameLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxSchemaNameLength(); } @@ -486,7 +655,9 @@ public void testGetMaxSchemaNameLength() throws Exception { public void testGetMaxStatementLength() throws Exception { try { delegate.getMaxStatementLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxStatementLength(); } @@ -494,7 +665,9 @@ public void testGetMaxStatementLength() throws Exception { public void testGetMaxStatements() throws Exception { try { delegate.getMaxStatements(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxStatements(); } @@ -502,7 +675,9 @@ public void testGetMaxStatements() throws Exception { public void testGetMaxTableNameLength() throws Exception { try { delegate.getMaxTableNameLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxTableNameLength(); } @@ -510,7 +685,9 @@ public void testGetMaxTableNameLength() throws Exception { public void testGetMaxTablesInSelect() throws Exception { try { delegate.getMaxTablesInSelect(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxTablesInSelect(); } @@ -518,7 +695,9 @@ public void testGetMaxTablesInSelect() throws Exception { public void testGetMaxUserNameLength() throws Exception { try { delegate.getMaxUserNameLength(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getMaxUserNameLength(); } @@ -526,55 +705,69 @@ public void testGetMaxUserNameLength() throws Exception { public void testGetNumericFunctions() throws Exception { try { delegate.getNumericFunctions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getNumericFunctions(); } @Test public void testGetPrimaryKeysStringStringString() throws Exception { try { - delegate.getPrimaryKeys("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getPrimaryKeys("foo","foo","foo"); + delegate.getPrimaryKeys("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getPrimaryKeys("foo", "foo", "foo"); } @Test public void testGetProcedureColumnsStringStringStringString() throws Exception { try { - delegate.getProcedureColumns("foo","foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getProcedureColumns("foo","foo","foo","foo"); + delegate.getProcedureColumns("foo", "foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getProcedureColumns("foo", "foo", "foo", "foo"); } @Test public void testGetProceduresStringStringString() throws Exception { try { - delegate.getProcedures("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getProcedures("foo","foo","foo"); + delegate.getProcedures("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getProcedures("foo", "foo", "foo"); } @Test public void testGetProcedureTerm() throws Exception { try { delegate.getProcedureTerm(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getProcedureTerm(); } @Test public void testGetPseudoColumnsStringStringStringString() throws Exception { try { - delegate.getPseudoColumns("foo","foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getPseudoColumns("foo","foo","foo","foo"); + delegate.getPseudoColumns("foo", "foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getPseudoColumns("foo", "foo", "foo", "foo"); } @Test public void testGetResultSetHoldability() throws Exception { try { delegate.getResultSetHoldability(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getResultSetHoldability(); } @@ -582,7 +775,9 @@ public void testGetResultSetHoldability() throws Exception { public void testGetRowIdLifetime() throws Exception { try { delegate.getRowIdLifetime(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getRowIdLifetime(); } @@ -590,23 +785,29 @@ public void testGetRowIdLifetime() throws Exception { public void testGetSchemas() throws Exception { try { delegate.getSchemas(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getSchemas(); } @Test public void testGetSchemasStringString() throws Exception { try { - delegate.getSchemas("foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getSchemas("foo","foo"); + delegate.getSchemas("foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getSchemas("foo", "foo"); } @Test public void testGetSchemaTerm() throws Exception { try { delegate.getSchemaTerm(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getSchemaTerm(); } @@ -614,7 +815,9 @@ public void testGetSchemaTerm() throws Exception { public void testGetSearchStringEscape() throws Exception { try { delegate.getSearchStringEscape(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getSearchStringEscape(); } @@ -622,7 +825,9 @@ public void testGetSearchStringEscape() throws Exception { public void testGetSQLKeywords() throws Exception { try { delegate.getSQLKeywords(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getSQLKeywords(); } @@ -630,7 +835,9 @@ public void testGetSQLKeywords() throws Exception { public void testGetSQLStateType() throws Exception { try { delegate.getSQLStateType(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getSQLStateType(); } @@ -638,55 +845,69 @@ public void testGetSQLStateType() throws Exception { public void testGetStringFunctions() throws Exception { try { delegate.getStringFunctions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getStringFunctions(); } @Test public void testGetSuperTablesStringStringString() throws Exception { try { - delegate.getSuperTables("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getSuperTables("foo","foo","foo"); + delegate.getSuperTables("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getSuperTables("foo", "foo", "foo"); } @Test public void testGetSuperTypesStringStringString() throws Exception { try { - delegate.getSuperTypes("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getSuperTypes("foo","foo","foo"); + delegate.getSuperTypes("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getSuperTypes("foo", "foo", "foo"); } @Test public void testGetSystemFunctions() throws Exception { try { delegate.getSystemFunctions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getSystemFunctions(); } @Test public void testGetTablePrivilegesStringStringString() throws Exception { try { - delegate.getTablePrivileges("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getTablePrivileges("foo","foo","foo"); + delegate.getTablePrivileges("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getTablePrivileges("foo", "foo", "foo"); } @Test public void testGetTablesStringStringStringStringArray() throws Exception { try { - delegate.getTables("foo","foo","foo",(String[]) null); - } catch (final SQLException e) {} - verify(obj, times(1)).getTables("foo","foo","foo",(String[]) null); + delegate.getTables("foo", "foo", "foo", (String[]) null); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getTables("foo", "foo", "foo", (String[]) null); } @Test public void testGetTableTypes() throws Exception { try { delegate.getTableTypes(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getTableTypes(); } @@ -694,7 +915,9 @@ public void testGetTableTypes() throws Exception { public void testGetTimeDateFunctions() throws Exception { try { delegate.getTimeDateFunctions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getTimeDateFunctions(); } @@ -702,23 +925,29 @@ public void testGetTimeDateFunctions() throws Exception { public void testGetTypeInfo() throws Exception { try { delegate.getTypeInfo(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getTypeInfo(); } @Test public void testGetUDTsStringStringStringIntegerArray() throws Exception { try { - delegate.getUDTs("foo","foo","foo",(int[]) null); - } catch (final SQLException e) {} - verify(obj, times(1)).getUDTs("foo","foo","foo",(int[]) null); + delegate.getUDTs("foo", "foo", "foo", (int[]) null); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getUDTs("foo", "foo", "foo", (int[]) null); } @Test public void testGetURL() throws Exception { try { delegate.getURL(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getURL(); } @@ -726,23 +955,29 @@ public void testGetURL() throws Exception { public void testGetUserName() throws Exception { try { delegate.getUserName(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).getUserName(); } @Test public void testGetVersionColumnsStringStringString() throws Exception { try { - delegate.getVersionColumns("foo","foo","foo"); - } catch (final SQLException e) {} - verify(obj, times(1)).getVersionColumns("foo","foo","foo"); + delegate.getVersionColumns("foo", "foo", "foo"); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).getVersionColumns("foo", "foo", "foo"); } @Test public void testInsertsAreDetectedInteger() throws Exception { try { delegate.insertsAreDetected(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).insertsAreDetected(1); } @@ -750,7 +985,9 @@ public void testInsertsAreDetectedInteger() throws Exception { public void testIsCatalogAtStart() throws Exception { try { delegate.isCatalogAtStart(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).isCatalogAtStart(); } @@ -758,7 +995,9 @@ public void testIsCatalogAtStart() throws Exception { public void testIsReadOnly() throws Exception { try { delegate.isReadOnly(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).isReadOnly(); } @@ -766,25 +1005,25 @@ public void testIsReadOnly() throws Exception { public void testLocatorsUpdateCopy() throws Exception { try { delegate.locatorsUpdateCopy(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).locatorsUpdateCopy(); } @Test public void testNullArguments() throws Exception { - assertThrows(NullPointerException.class, () -> { - new DelegatingDatabaseMetaData(null, null); - }); - assertThrows(NullPointerException.class, () -> { - new DelegatingDatabaseMetaData(new DelegatingConnection(null), null); - }); + assertThrows(NullPointerException.class, () -> new DelegatingDatabaseMetaData(null, null)); + assertThrows(NullPointerException.class, () -> new DelegatingDatabaseMetaData(new DelegatingConnection(null), null)); } @Test public void testNullPlusNonNullIsNull() throws Exception { try { delegate.nullPlusNonNullIsNull(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).nullPlusNonNullIsNull(); } @@ -792,7 +1031,9 @@ public void testNullPlusNonNullIsNull() throws Exception { public void testNullsAreSortedAtEnd() throws Exception { try { delegate.nullsAreSortedAtEnd(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).nullsAreSortedAtEnd(); } @@ -800,7 +1041,9 @@ public void testNullsAreSortedAtEnd() throws Exception { public void testNullsAreSortedAtStart() throws Exception { try { delegate.nullsAreSortedAtStart(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).nullsAreSortedAtStart(); } @@ -808,7 +1051,9 @@ public void testNullsAreSortedAtStart() throws Exception { public void testNullsAreSortedHigh() throws Exception { try { delegate.nullsAreSortedHigh(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).nullsAreSortedHigh(); } @@ -816,7 +1061,9 @@ public void testNullsAreSortedHigh() throws Exception { public void testNullsAreSortedLow() throws Exception { try { delegate.nullsAreSortedLow(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).nullsAreSortedLow(); } @@ -824,7 +1071,9 @@ public void testNullsAreSortedLow() throws Exception { public void testOthersDeletesAreVisibleInteger() throws Exception { try { delegate.othersDeletesAreVisible(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).othersDeletesAreVisible(1); } @@ -832,7 +1081,9 @@ public void testOthersDeletesAreVisibleInteger() throws Exception { public void testOthersInsertsAreVisibleInteger() throws Exception { try { delegate.othersInsertsAreVisible(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).othersInsertsAreVisible(1); } @@ -840,7 +1091,9 @@ public void testOthersInsertsAreVisibleInteger() throws Exception { public void testOthersUpdatesAreVisibleInteger() throws Exception { try { delegate.othersUpdatesAreVisible(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).othersUpdatesAreVisible(1); } @@ -848,7 +1101,9 @@ public void testOthersUpdatesAreVisibleInteger() throws Exception { public void testOwnDeletesAreVisibleInteger() throws Exception { try { delegate.ownDeletesAreVisible(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).ownDeletesAreVisible(1); } @@ -856,7 +1111,9 @@ public void testOwnDeletesAreVisibleInteger() throws Exception { public void testOwnInsertsAreVisibleInteger() throws Exception { try { delegate.ownInsertsAreVisible(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).ownInsertsAreVisible(1); } @@ -864,7 +1121,9 @@ public void testOwnInsertsAreVisibleInteger() throws Exception { public void testOwnUpdatesAreVisibleInteger() throws Exception { try { delegate.ownUpdatesAreVisible(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).ownUpdatesAreVisible(1); } @@ -872,7 +1131,9 @@ public void testOwnUpdatesAreVisibleInteger() throws Exception { public void testStoresLowerCaseIdentifiers() throws Exception { try { delegate.storesLowerCaseIdentifiers(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).storesLowerCaseIdentifiers(); } @@ -880,7 +1141,9 @@ public void testStoresLowerCaseIdentifiers() throws Exception { public void testStoresLowerCaseQuotedIdentifiers() throws Exception { try { delegate.storesLowerCaseQuotedIdentifiers(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).storesLowerCaseQuotedIdentifiers(); } @@ -888,7 +1151,9 @@ public void testStoresLowerCaseQuotedIdentifiers() throws Exception { public void testStoresMixedCaseIdentifiers() throws Exception { try { delegate.storesMixedCaseIdentifiers(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).storesMixedCaseIdentifiers(); } @@ -896,7 +1161,9 @@ public void testStoresMixedCaseIdentifiers() throws Exception { public void testStoresMixedCaseQuotedIdentifiers() throws Exception { try { delegate.storesMixedCaseQuotedIdentifiers(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).storesMixedCaseQuotedIdentifiers(); } @@ -904,7 +1171,9 @@ public void testStoresMixedCaseQuotedIdentifiers() throws Exception { public void testStoresUpperCaseIdentifiers() throws Exception { try { delegate.storesUpperCaseIdentifiers(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).storesUpperCaseIdentifiers(); } @@ -912,7 +1181,9 @@ public void testStoresUpperCaseIdentifiers() throws Exception { public void testStoresUpperCaseQuotedIdentifiers() throws Exception { try { delegate.storesUpperCaseQuotedIdentifiers(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).storesUpperCaseQuotedIdentifiers(); } @@ -920,7 +1191,9 @@ public void testStoresUpperCaseQuotedIdentifiers() throws Exception { public void testSupportsAlterTableWithAddColumn() throws Exception { try { delegate.supportsAlterTableWithAddColumn(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsAlterTableWithAddColumn(); } @@ -928,7 +1201,9 @@ public void testSupportsAlterTableWithAddColumn() throws Exception { public void testSupportsAlterTableWithDropColumn() throws Exception { try { delegate.supportsAlterTableWithDropColumn(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsAlterTableWithDropColumn(); } @@ -936,7 +1211,9 @@ public void testSupportsAlterTableWithDropColumn() throws Exception { public void testSupportsANSI92EntryLevelSQL() throws Exception { try { delegate.supportsANSI92EntryLevelSQL(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsANSI92EntryLevelSQL(); } @@ -944,7 +1221,9 @@ public void testSupportsANSI92EntryLevelSQL() throws Exception { public void testSupportsANSI92FullSQL() throws Exception { try { delegate.supportsANSI92FullSQL(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsANSI92FullSQL(); } @@ -952,7 +1231,9 @@ public void testSupportsANSI92FullSQL() throws Exception { public void testSupportsANSI92IntermediateSQL() throws Exception { try { delegate.supportsANSI92IntermediateSQL(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsANSI92IntermediateSQL(); } @@ -960,7 +1241,9 @@ public void testSupportsANSI92IntermediateSQL() throws Exception { public void testSupportsBatchUpdates() throws Exception { try { delegate.supportsBatchUpdates(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsBatchUpdates(); } @@ -968,7 +1251,9 @@ public void testSupportsBatchUpdates() throws Exception { public void testSupportsCatalogsInDataManipulation() throws Exception { try { delegate.supportsCatalogsInDataManipulation(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsCatalogsInDataManipulation(); } @@ -976,7 +1261,9 @@ public void testSupportsCatalogsInDataManipulation() throws Exception { public void testSupportsCatalogsInIndexDefinitions() throws Exception { try { delegate.supportsCatalogsInIndexDefinitions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsCatalogsInIndexDefinitions(); } @@ -984,7 +1271,9 @@ public void testSupportsCatalogsInIndexDefinitions() throws Exception { public void testSupportsCatalogsInPrivilegeDefinitions() throws Exception { try { delegate.supportsCatalogsInPrivilegeDefinitions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsCatalogsInPrivilegeDefinitions(); } @@ -992,7 +1281,9 @@ public void testSupportsCatalogsInPrivilegeDefinitions() throws Exception { public void testSupportsCatalogsInProcedureCalls() throws Exception { try { delegate.supportsCatalogsInProcedureCalls(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsCatalogsInProcedureCalls(); } @@ -1000,7 +1291,9 @@ public void testSupportsCatalogsInProcedureCalls() throws Exception { public void testSupportsCatalogsInTableDefinitions() throws Exception { try { delegate.supportsCatalogsInTableDefinitions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsCatalogsInTableDefinitions(); } @@ -1008,7 +1301,9 @@ public void testSupportsCatalogsInTableDefinitions() throws Exception { public void testSupportsColumnAliasing() throws Exception { try { delegate.supportsColumnAliasing(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsColumnAliasing(); } @@ -1016,23 +1311,29 @@ public void testSupportsColumnAliasing() throws Exception { public void testSupportsConvert() throws Exception { try { delegate.supportsConvert(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsConvert(); } @Test public void testSupportsConvertIntegerInteger() throws Exception { try { - delegate.supportsConvert(1,1); - } catch (final SQLException e) {} - verify(obj, times(1)).supportsConvert(1,1); + delegate.supportsConvert(1, 1); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).supportsConvert(1, 1); } @Test public void testSupportsCoreSQLGrammar() throws Exception { try { delegate.supportsCoreSQLGrammar(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsCoreSQLGrammar(); } @@ -1040,7 +1341,9 @@ public void testSupportsCoreSQLGrammar() throws Exception { public void testSupportsCorrelatedSubqueries() throws Exception { try { delegate.supportsCorrelatedSubqueries(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsCorrelatedSubqueries(); } @@ -1048,7 +1351,9 @@ public void testSupportsCorrelatedSubqueries() throws Exception { public void testSupportsDataDefinitionAndDataManipulationTransactions() throws Exception { try { delegate.supportsDataDefinitionAndDataManipulationTransactions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsDataDefinitionAndDataManipulationTransactions(); } @@ -1056,7 +1361,9 @@ public void testSupportsDataDefinitionAndDataManipulationTransactions() throws E public void testSupportsDataManipulationTransactionsOnly() throws Exception { try { delegate.supportsDataManipulationTransactionsOnly(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsDataManipulationTransactionsOnly(); } @@ -1064,7 +1371,9 @@ public void testSupportsDataManipulationTransactionsOnly() throws Exception { public void testSupportsDifferentTableCorrelationNames() throws Exception { try { delegate.supportsDifferentTableCorrelationNames(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsDifferentTableCorrelationNames(); } @@ -1072,7 +1381,9 @@ public void testSupportsDifferentTableCorrelationNames() throws Exception { public void testSupportsExpressionsInOrderBy() throws Exception { try { delegate.supportsExpressionsInOrderBy(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsExpressionsInOrderBy(); } @@ -1080,7 +1391,9 @@ public void testSupportsExpressionsInOrderBy() throws Exception { public void testSupportsExtendedSQLGrammar() throws Exception { try { delegate.supportsExtendedSQLGrammar(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsExtendedSQLGrammar(); } @@ -1088,7 +1401,9 @@ public void testSupportsExtendedSQLGrammar() throws Exception { public void testSupportsFullOuterJoins() throws Exception { try { delegate.supportsFullOuterJoins(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsFullOuterJoins(); } @@ -1096,7 +1411,9 @@ public void testSupportsFullOuterJoins() throws Exception { public void testSupportsGetGeneratedKeys() throws Exception { try { delegate.supportsGetGeneratedKeys(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsGetGeneratedKeys(); } @@ -1104,7 +1421,9 @@ public void testSupportsGetGeneratedKeys() throws Exception { public void testSupportsGroupBy() throws Exception { try { delegate.supportsGroupBy(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsGroupBy(); } @@ -1112,7 +1431,9 @@ public void testSupportsGroupBy() throws Exception { public void testSupportsGroupByBeyondSelect() throws Exception { try { delegate.supportsGroupByBeyondSelect(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsGroupByBeyondSelect(); } @@ -1120,7 +1441,9 @@ public void testSupportsGroupByBeyondSelect() throws Exception { public void testSupportsGroupByUnrelated() throws Exception { try { delegate.supportsGroupByUnrelated(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsGroupByUnrelated(); } @@ -1128,7 +1451,9 @@ public void testSupportsGroupByUnrelated() throws Exception { public void testSupportsIntegrityEnhancementFacility() throws Exception { try { delegate.supportsIntegrityEnhancementFacility(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsIntegrityEnhancementFacility(); } @@ -1136,7 +1461,9 @@ public void testSupportsIntegrityEnhancementFacility() throws Exception { public void testSupportsLikeEscapeClause() throws Exception { try { delegate.supportsLikeEscapeClause(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsLikeEscapeClause(); } @@ -1144,7 +1471,9 @@ public void testSupportsLikeEscapeClause() throws Exception { public void testSupportsLimitedOuterJoins() throws Exception { try { delegate.supportsLimitedOuterJoins(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsLimitedOuterJoins(); } @@ -1152,7 +1481,9 @@ public void testSupportsLimitedOuterJoins() throws Exception { public void testSupportsMinimumSQLGrammar() throws Exception { try { delegate.supportsMinimumSQLGrammar(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsMinimumSQLGrammar(); } @@ -1160,7 +1491,9 @@ public void testSupportsMinimumSQLGrammar() throws Exception { public void testSupportsMixedCaseIdentifiers() throws Exception { try { delegate.supportsMixedCaseIdentifiers(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsMixedCaseIdentifiers(); } @@ -1168,7 +1501,9 @@ public void testSupportsMixedCaseIdentifiers() throws Exception { public void testSupportsMixedCaseQuotedIdentifiers() throws Exception { try { delegate.supportsMixedCaseQuotedIdentifiers(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsMixedCaseQuotedIdentifiers(); } @@ -1176,7 +1511,9 @@ public void testSupportsMixedCaseQuotedIdentifiers() throws Exception { public void testSupportsMultipleOpenResults() throws Exception { try { delegate.supportsMultipleOpenResults(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsMultipleOpenResults(); } @@ -1184,7 +1521,9 @@ public void testSupportsMultipleOpenResults() throws Exception { public void testSupportsMultipleResultSets() throws Exception { try { delegate.supportsMultipleResultSets(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsMultipleResultSets(); } @@ -1192,7 +1531,9 @@ public void testSupportsMultipleResultSets() throws Exception { public void testSupportsMultipleTransactions() throws Exception { try { delegate.supportsMultipleTransactions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsMultipleTransactions(); } @@ -1200,7 +1541,9 @@ public void testSupportsMultipleTransactions() throws Exception { public void testSupportsNamedParameters() throws Exception { try { delegate.supportsNamedParameters(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsNamedParameters(); } @@ -1208,7 +1551,9 @@ public void testSupportsNamedParameters() throws Exception { public void testSupportsNonNullableColumns() throws Exception { try { delegate.supportsNonNullableColumns(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsNonNullableColumns(); } @@ -1216,7 +1561,9 @@ public void testSupportsNonNullableColumns() throws Exception { public void testSupportsOpenCursorsAcrossCommit() throws Exception { try { delegate.supportsOpenCursorsAcrossCommit(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsOpenCursorsAcrossCommit(); } @@ -1224,7 +1571,9 @@ public void testSupportsOpenCursorsAcrossCommit() throws Exception { public void testSupportsOpenCursorsAcrossRollback() throws Exception { try { delegate.supportsOpenCursorsAcrossRollback(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsOpenCursorsAcrossRollback(); } @@ -1232,7 +1581,9 @@ public void testSupportsOpenCursorsAcrossRollback() throws Exception { public void testSupportsOpenStatementsAcrossCommit() throws Exception { try { delegate.supportsOpenStatementsAcrossCommit(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsOpenStatementsAcrossCommit(); } @@ -1240,7 +1591,9 @@ public void testSupportsOpenStatementsAcrossCommit() throws Exception { public void testSupportsOpenStatementsAcrossRollback() throws Exception { try { delegate.supportsOpenStatementsAcrossRollback(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsOpenStatementsAcrossRollback(); } @@ -1248,7 +1601,9 @@ public void testSupportsOpenStatementsAcrossRollback() throws Exception { public void testSupportsOrderByUnrelated() throws Exception { try { delegate.supportsOrderByUnrelated(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsOrderByUnrelated(); } @@ -1256,7 +1611,9 @@ public void testSupportsOrderByUnrelated() throws Exception { public void testSupportsOuterJoins() throws Exception { try { delegate.supportsOuterJoins(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsOuterJoins(); } @@ -1264,7 +1621,9 @@ public void testSupportsOuterJoins() throws Exception { public void testSupportsPositionedDelete() throws Exception { try { delegate.supportsPositionedDelete(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsPositionedDelete(); } @@ -1272,7 +1631,9 @@ public void testSupportsPositionedDelete() throws Exception { public void testSupportsPositionedUpdate() throws Exception { try { delegate.supportsPositionedUpdate(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsPositionedUpdate(); } @@ -1280,23 +1641,29 @@ public void testSupportsPositionedUpdate() throws Exception { public void testSupportsRefCursors() throws Exception { try { delegate.supportsRefCursors(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsRefCursors(); } @Test public void testSupportsResultSetConcurrencyIntegerInteger() throws Exception { try { - delegate.supportsResultSetConcurrency(1,1); - } catch (final SQLException e) {} - verify(obj, times(1)).supportsResultSetConcurrency(1,1); + delegate.supportsResultSetConcurrency(1, 1); + } catch (final SQLException e) { + // ignore + } + verify(obj, times(1)).supportsResultSetConcurrency(1, 1); } @Test public void testSupportsResultSetHoldabilityInteger() throws Exception { try { delegate.supportsResultSetHoldability(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsResultSetHoldability(1); } @@ -1304,7 +1671,9 @@ public void testSupportsResultSetHoldabilityInteger() throws Exception { public void testSupportsResultSetTypeInteger() throws Exception { try { delegate.supportsResultSetType(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsResultSetType(1); } @@ -1312,7 +1681,9 @@ public void testSupportsResultSetTypeInteger() throws Exception { public void testSupportsSavepoints() throws Exception { try { delegate.supportsSavepoints(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSavepoints(); } @@ -1320,7 +1691,9 @@ public void testSupportsSavepoints() throws Exception { public void testSupportsSchemasInDataManipulation() throws Exception { try { delegate.supportsSchemasInDataManipulation(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSchemasInDataManipulation(); } @@ -1328,7 +1701,9 @@ public void testSupportsSchemasInDataManipulation() throws Exception { public void testSupportsSchemasInIndexDefinitions() throws Exception { try { delegate.supportsSchemasInIndexDefinitions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSchemasInIndexDefinitions(); } @@ -1336,7 +1711,9 @@ public void testSupportsSchemasInIndexDefinitions() throws Exception { public void testSupportsSchemasInPrivilegeDefinitions() throws Exception { try { delegate.supportsSchemasInPrivilegeDefinitions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSchemasInPrivilegeDefinitions(); } @@ -1344,7 +1721,9 @@ public void testSupportsSchemasInPrivilegeDefinitions() throws Exception { public void testSupportsSchemasInProcedureCalls() throws Exception { try { delegate.supportsSchemasInProcedureCalls(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSchemasInProcedureCalls(); } @@ -1352,7 +1731,9 @@ public void testSupportsSchemasInProcedureCalls() throws Exception { public void testSupportsSchemasInTableDefinitions() throws Exception { try { delegate.supportsSchemasInTableDefinitions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSchemasInTableDefinitions(); } @@ -1360,7 +1741,9 @@ public void testSupportsSchemasInTableDefinitions() throws Exception { public void testSupportsSelectForUpdate() throws Exception { try { delegate.supportsSelectForUpdate(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSelectForUpdate(); } @@ -1368,7 +1751,9 @@ public void testSupportsSelectForUpdate() throws Exception { public void testSupportsStatementPooling() throws Exception { try { delegate.supportsStatementPooling(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsStatementPooling(); } @@ -1376,7 +1761,9 @@ public void testSupportsStatementPooling() throws Exception { public void testSupportsStoredFunctionsUsingCallSyntax() throws Exception { try { delegate.supportsStoredFunctionsUsingCallSyntax(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsStoredFunctionsUsingCallSyntax(); } @@ -1384,7 +1771,9 @@ public void testSupportsStoredFunctionsUsingCallSyntax() throws Exception { public void testSupportsStoredProcedures() throws Exception { try { delegate.supportsStoredProcedures(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsStoredProcedures(); } @@ -1392,7 +1781,9 @@ public void testSupportsStoredProcedures() throws Exception { public void testSupportsSubqueriesInComparisons() throws Exception { try { delegate.supportsSubqueriesInComparisons(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSubqueriesInComparisons(); } @@ -1400,7 +1791,9 @@ public void testSupportsSubqueriesInComparisons() throws Exception { public void testSupportsSubqueriesInExists() throws Exception { try { delegate.supportsSubqueriesInExists(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSubqueriesInExists(); } @@ -1408,7 +1801,9 @@ public void testSupportsSubqueriesInExists() throws Exception { public void testSupportsSubqueriesInIns() throws Exception { try { delegate.supportsSubqueriesInIns(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSubqueriesInIns(); } @@ -1416,7 +1811,9 @@ public void testSupportsSubqueriesInIns() throws Exception { public void testSupportsSubqueriesInQuantifieds() throws Exception { try { delegate.supportsSubqueriesInQuantifieds(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsSubqueriesInQuantifieds(); } @@ -1424,7 +1821,9 @@ public void testSupportsSubqueriesInQuantifieds() throws Exception { public void testSupportsTableCorrelationNames() throws Exception { try { delegate.supportsTableCorrelationNames(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsTableCorrelationNames(); } @@ -1432,7 +1831,9 @@ public void testSupportsTableCorrelationNames() throws Exception { public void testSupportsTransactionIsolationLevelInteger() throws Exception { try { delegate.supportsTransactionIsolationLevel(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsTransactionIsolationLevel(1); } @@ -1440,7 +1841,9 @@ public void testSupportsTransactionIsolationLevelInteger() throws Exception { public void testSupportsTransactions() throws Exception { try { delegate.supportsTransactions(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsTransactions(); } @@ -1448,7 +1851,9 @@ public void testSupportsTransactions() throws Exception { public void testSupportsUnion() throws Exception { try { delegate.supportsUnion(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsUnion(); } @@ -1456,7 +1861,9 @@ public void testSupportsUnion() throws Exception { public void testSupportsUnionAll() throws Exception { try { delegate.supportsUnionAll(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).supportsUnionAll(); } @@ -1464,7 +1871,9 @@ public void testSupportsUnionAll() throws Exception { public void testUpdatesAreDetectedInteger() throws Exception { try { delegate.updatesAreDetected(1); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).updatesAreDetected(1); } @@ -1472,7 +1881,9 @@ public void testUpdatesAreDetectedInteger() throws Exception { public void testUsesLocalFilePerTable() throws Exception { try { delegate.usesLocalFilePerTable(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).usesLocalFilePerTable(); } @@ -1480,7 +1891,9 @@ public void testUsesLocalFilePerTable() throws Exception { public void testUsesLocalFiles() throws Exception { try { delegate.usesLocalFiles(); - } catch (final SQLException e) {} + } catch (final SQLException e) { + // ignore + } verify(obj, times(1)).usesLocalFiles(); } diff --git a/src/test/java/org/apache/commons/dbcp2/TestDelegatingStatement.java b/src/test/java/org/apache/commons/dbcp2/TestDelegatingStatement.java index 770e379afc..770e8443ca 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestDelegatingStatement.java +++ b/src/test/java/org/apache/commons/dbcp2/TestDelegatingStatement.java @@ -142,7 +142,7 @@ public void testCloseWithResultSetCloseException() throws Exception { delegatingStatement.close(); Assertions.fail("Excpected a SQLExceptionList"); } catch (final SQLException e) { - Assertions.assertTrue(e instanceof SQLExceptionList); + Assertions.assertInstanceOf(SQLExceptionList.class, e); } finally { testerResultSet.setSqlExceptionOnClose(false); } @@ -156,7 +156,7 @@ public void testCloseWithStatementCloseException() throws Exception { delegatingTesterStatement.close(); Assertions.fail("Excpected a SQLExceptionList"); } catch (final SQLException e) { - Assertions.assertTrue(e instanceof SQLExceptionList); + Assertions.assertInstanceOf(SQLExceptionList.class, e); } finally { testerStatement.setSqlExceptionOnClose(false); } diff --git a/src/test/java/org/apache/commons/dbcp2/TestDriverManagerConnectionFactory.java b/src/test/java/org/apache/commons/dbcp2/TestDriverManagerConnectionFactory.java index 673f4bb162..ce6b368c9d 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestDriverManagerConnectionFactory.java +++ b/src/test/java/org/apache/commons/dbcp2/TestDriverManagerConnectionFactory.java @@ -28,8 +28,6 @@ import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; /** @@ -37,7 +35,7 @@ * the initialization of DriverManager. * Based on the test case for DBCP-212 written by Marcos Sanz */ -public class TestDriverManagerConnectionFactory { +public class TestDriverManagerConnectionFactory extends AbstractDriverTest { private static final class ConnectionThread implements Runnable { private final DataSource ds; @@ -77,18 +75,6 @@ public String toString() { } } - private static final String KEY_JDBC_DRIVERS = "jdbc.drivers"; - - @AfterAll - public static void afterClass() { - System.clearProperty(KEY_JDBC_DRIVERS); - } - - @BeforeAll - public static void beforeClass() { - System.setProperty(KEY_JDBC_DRIVERS, "org.apache.commons.dbcp2.TesterDriver"); - } - @Test public void testDriverManagerCredentialsInUrl() throws SQLException { final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver;user=foo;password=bar", null, (char[]) null); diff --git a/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java b/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java index c4f852fe4f..9a80ffc5e5 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java +++ b/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java @@ -16,7 +16,9 @@ */ package org.apache.commons.dbcp2; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -26,7 +28,6 @@ import java.util.Arrays; import org.apache.commons.dbcp2.PoolingConnection.StatementType; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -39,35 +40,35 @@ public class TestPStmtKey { */ @Test public void testCtorDifferentCatalog() { - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog2", "schema1")); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog2", "schema1")); + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog2", "schema1", 0)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog2", "schema1", 0, 0)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0)); // - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, StatementType.PREPARED_STATEMENT)); // - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog2", "schema1", (int[]) null)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog2", "schema1", new int[1])); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog2", "schema1", (String[]) null)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog2", "schema1", new String[] {"A" })); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", StatementType.PREPARED_STATEMENT)); - Assertions.assertNotEquals( + assertNotEquals( new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE), new PStmtKey("sql", "catalog2", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE)); } @@ -77,35 +78,35 @@ public void testCtorDifferentCatalog() { */ @Test public void testCtorDifferentSchema() { - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema2")); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema2")); + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog1", "schema2", 0)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog1", "schema2", 0, 0)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0)); // - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0, StatementType.CALLABLE_STATEMENT)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, StatementType.CALLABLE_STATEMENT)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, StatementType.PREPARED_STATEMENT)); // - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog1", "schema2", (int[]) null)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog1", "schema2", new int[1])); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog1", "schema2", (String[]) null)); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog1", "schema2", new String[] {"A" })); - Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), + assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", StatementType.PREPARED_STATEMENT)); - Assertions.assertNotEquals( + assertNotEquals( new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE), new PStmtKey("sql", "catalog1", "schema2", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE)); } @@ -115,35 +116,35 @@ public void testCtorDifferentSchema() { */ @Test public void testCtorEquals() { - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema1")); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0), + assertEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema1")); + assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog1", "schema1", 0)); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog1", "schema1", 0, 0)); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0)); // - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT)); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT)); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT)); // - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog1", "schema1", (int[]) null)); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog1", "schema1", new int[1])); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog1", "schema1", (String[]) null)); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" })); - Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), + assertEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT)); - Assertions.assertEquals( + assertEquals( new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE), new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE)); } @@ -157,10 +158,10 @@ public void testCtorEquals() { public void testCtorStringStringArrayOfInts() { final int[] input = {0, 0}; final PStmtKey pStmtKey = new PStmtKey("", "", "", input); - Assertions.assertArrayEquals(input, pStmtKey.getColumnIndexes()); + assertArrayEquals(input, pStmtKey.getColumnIndexes()); input[0] = 1; input[1] = 1; - Assertions.assertFalse(Arrays.equals(input, pStmtKey.getColumnIndexes())); + assertFalse(Arrays.equals(input, pStmtKey.getColumnIndexes())); } /** @@ -172,7 +173,7 @@ public void testCtorStringStringArrayOfInts() { public void testCtorStringStringArrayOfNullInts() { final int[] input = null; final PStmtKey pStmtKey = new PStmtKey("", "", "", input); - Assertions.assertArrayEquals(input, pStmtKey.getColumnIndexes()); + assertArrayEquals(input, pStmtKey.getColumnIndexes()); } /** @@ -184,7 +185,7 @@ public void testCtorStringStringArrayOfNullInts() { public void testCtorStringStringArrayOfNullStrings() { final String[] input = null; final PStmtKey pStmtKey = new PStmtKey("", "", "", input); - Assertions.assertArrayEquals(input, pStmtKey.getColumnNames()); + assertArrayEquals(input, pStmtKey.getColumnNames()); } /** @@ -196,10 +197,10 @@ public void testCtorStringStringArrayOfNullStrings() { public void testCtorStringStringArrayOfStrings() { final String[] input = {"A", "B"}; final PStmtKey pStmtKey = new PStmtKey("", "", "", input); - Assertions.assertArrayEquals(input, pStmtKey.getColumnNames()); + assertArrayEquals(input, pStmtKey.getColumnNames()); input[0] = "C"; input[1] = "D"; - Assertions.assertFalse(Arrays.equals(input, pStmtKey.getColumnNames())); + assertFalse(Arrays.equals(input, pStmtKey.getColumnNames())); } @Test diff --git a/src/test/java/org/apache/commons/dbcp2/TestParallelCreationWithNoIdle.java b/src/test/java/org/apache/commons/dbcp2/TestParallelCreationWithNoIdle.java index 395d4a1331..48ea4aace6 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestParallelCreationWithNoIdle.java +++ b/src/test/java/org/apache/commons/dbcp2/TestParallelCreationWithNoIdle.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Random; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,7 +37,7 @@ public class TestParallelCreationWithNoIdle { final class TestThread extends Thread { - final java.util.Random _random = new java.util.Random(); + final Random random = new Random(); final int iter; final int delay; final int delayAfter; @@ -72,7 +73,7 @@ private void sleepMax(final int timeMax) { return; } try { - Thread.sleep(_random.nextInt(timeMax)); + Thread.sleep(random.nextInt(timeMax)); } catch (final Exception e) { // ignored } diff --git a/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java b/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java index 3a9f2e2ac0..d36e1ff468 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java +++ b/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java @@ -19,11 +19,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; import javax.management.OperationsException; @@ -42,9 +44,7 @@ public class TestPoolableConnection { @BeforeEach public void setUp() throws Exception { final PoolableConnectionFactory factory = new PoolableConnectionFactory( - new DriverConnectionFactory( - new TesterDriver(),"jdbc:apache:commons:testdriver", null), - null); + new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", null), null); factory.setDefaultAutoCommit(Boolean.TRUE); factory.setDefaultReadOnly(Boolean.TRUE); @@ -90,6 +90,27 @@ public void testConnectionPool() throws Exception { assertEquals(0, pool.getNumActive(), "There should now be zero active objects in the pool"); } + @Test + public void testDisconnectionIgnoreSqlCodes() throws Exception { + pool.setTestOnReturn(true); + final PoolableConnectionFactory factory = (PoolableConnectionFactory) pool.getFactory(); + factory.setFastFailValidation(true); + factory.setDisconnectionIgnoreSqlCodes(Arrays.asList("08S02", "08007")); + + final PoolableConnection conn = pool.borrowObject(); + final TesterConnection nativeConnection = (TesterConnection) conn.getInnermostDelegate(); + + // set up non-fatal exception + nativeConnection.setFailure(new SQLException("Non-fatal connection error.", "08S02")); + assertThrows(SQLException.class, conn::createStatement); + nativeConnection.setFailure(null); + + // verify that non-fatal connection is returned to the pool + conn.close(); + assertEquals(0, pool.getNumActive(), "The pool should have no active connections"); + assertEquals(1, pool.getNumIdle(), "The pool should have one idle connection"); + } + @Test public void testFastFailValidation() throws Exception { pool.setTestOnReturn(true); @@ -149,14 +170,9 @@ public void testFastFailValidationCustomCodes() throws Exception { // Set up fatal exception nativeConnection.setFailure(new SQLException("Fatal connection error.", "XXX")); - - try { - conn.createStatement(); - fail("Should throw SQL exception."); - } catch (final SQLException ignored) { - // cleanup failure - nativeConnection.setFailure(null); - } + assertThrows(SQLException.class, conn::createStatement); + // cleanup failure + nativeConnection.setFailure(null); // verify that bad connection does not get returned to the pool conn.close(); // testOnReturn triggers validate, which should fail diff --git a/src/test/java/org/apache/commons/dbcp2/TestPoolingConnection.java b/src/test/java/org/apache/commons/dbcp2/TestPoolingConnection.java index 27fbccc6d1..e944f9ecab 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestPoolingConnection.java +++ b/src/test/java/org/apache/commons/dbcp2/TestPoolingConnection.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.sql.SQLException; import java.time.Duration; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; @@ -173,11 +174,14 @@ public void testPrepareStatementWithResultSetHoldability() throws Exception { * Tests DBCP-596 PoolingConnection.toString() causes StackOverflowError. */ @Test - public void testToStringStackOverflow() { - final PoolingConnection conn = new PoolingConnection(null); - final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); - final GenericKeyedObjectPool stmtPool = new GenericKeyedObjectPool<>(conn, config); - conn.setStatementPool(stmtPool); - conn.toString(); + public void testToStringStackOverflow() throws SQLException { + // Also tests a possible NullPointerException in PoolingConnection.close() + try (PoolingConnection conn = new PoolingConnection(null)) { + final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); + try (GenericKeyedObjectPool stmtPool = new GenericKeyedObjectPool<>(conn, config)) { + conn.setStatementPool(stmtPool); + } + conn.toString(); + } } } diff --git a/src/test/java/org/apache/commons/dbcp2/TestUtils.java b/src/test/java/org/apache/commons/dbcp2/TestUtils.java index 490ee6d6a7..0d0b157328 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestUtils.java +++ b/src/test/java/org/apache/commons/dbcp2/TestUtils.java @@ -17,6 +17,17 @@ package org.apache.commons.dbcp2; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; + import org.junit.jupiter.api.Test; public class TestUtils { @@ -25,8 +36,67 @@ public static PStmtKey getPStmtKey(final PoolablePreparedStatement poo return poolablePreparedStatement.getKey(); } + @Test + public void testCheckForConflictsBothCollectionsNull() { + assertDoesNotThrow(() -> Utils.checkSqlCodes(null, null)); + } + + @Test + public void testCheckForConflictsEmptyCollections() { + final Collection codes1 = Collections.emptySet(); + final Collection codes2 = Collections.emptySet(); + assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); + } + + @Test + public void testCheckForConflictsFirstCollectionNull() { + final Collection codes1 = null; + final Collection codes2 = new HashSet<>(Arrays.asList("08005", "08007")); + assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); + } + + @Test + public void testCheckForConflictsNoOverlap() { + final Collection codes1 = new HashSet<>(Arrays.asList("08003", "08006")); + final Collection codes2 = new HashSet<>(Arrays.asList("08005", "08007")); + assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); + } + + @Test + public void testCheckForConflictsSecondCollectionNull() { + final Collection codes1 = new HashSet<>(Arrays.asList("08003", "08006")); + final Collection codes2 = null; + assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); + } + + @Test + public void testCheckForConflictsWith1Overlap() { + final Collection codes1 = new HashSet<>(Arrays.asList("08003", "08006")); + final Collection codes2 = new HashSet<>(Arrays.asList("08005", "08006")); + final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Utils.checkSqlCodes(codes1, codes2)); + assertEquals("[08006] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); + } + + @Test + public void testCheckForConflictsWith2Overlap() { + final Collection codes1 = new HashSet<>(Arrays.asList("08003", "08006", "08007")); + final Collection codes2 = new HashSet<>(Arrays.asList("08005", "08006", "08007")); + final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Utils.checkSqlCodes(codes1, codes2)); + assertEquals("[08006, 08007] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); + } + @Test public void testClassLoads() { Utils.closeQuietly((AutoCloseable) null); } + + @Test + public void testIsDisconnectionSqlCode() { + assertTrue(Utils.isDisconnectionSqlCode("57P01"), "57P01 should be recognised as a disconnection SQL code."); + assertTrue(Utils.isDisconnectionSqlCode("01002"), "01002 should be recognised as a disconnection SQL code."); + assertTrue(Utils.isDisconnectionSqlCode("JZ0C0"), "JZ0C0 should be recognised as a disconnection SQL code."); + + assertFalse(Utils.isDisconnectionSqlCode("INVALID"), "INVALID should not be recognised as a disconnection SQL code."); + assertFalse(Utils.isDisconnectionSqlCode("00000"), "00000 should not be recognised as a disconnection SQL code."); + } } diff --git a/src/test/java/org/apache/commons/dbcp2/TesterConnection.java b/src/test/java/org/apache/commons/dbcp2/TesterConnection.java index 00b6075199..449801719c 100644 --- a/src/test/java/org/apache/commons/dbcp2/TesterConnection.java +++ b/src/test/java/org/apache/commons/dbcp2/TesterConnection.java @@ -40,15 +40,15 @@ */ public class TesterConnection extends AbandonedTrace implements Connection { - protected boolean _open = true; - protected boolean _aborted; - protected boolean _autoCommit = true; - protected int _transactionIsolation = 1; - protected final DatabaseMetaData _metaData = new TesterDatabaseMetaData(); - protected String _catalog; + protected boolean open = true; + protected boolean aborted; + protected boolean autoCommit = true; + protected int transactionIsolation = 1; + protected final DatabaseMetaData metaData = new TesterDatabaseMetaData(); + protected String catalog; protected String schema; - protected Map> _typeMap; - protected boolean _readOnly; + protected Map> typeMap; + protected boolean readOnly; protected SQLWarning warnings; protected final String userName; protected Exception failure; @@ -62,8 +62,8 @@ public class TesterConnection extends AbandonedTrace implements Connection { @Override public void abort(final Executor executor) throws SQLException { checkFailure(); - _aborted = true; - _open = false; + aborted = true; + open = false; } protected void checkFailure() throws SQLException { @@ -76,7 +76,7 @@ protected void checkFailure() throws SQLException { } protected void checkOpen() throws SQLException { - if (!_open) { + if (!open) { throw new SQLException("Connection is closed."); } checkFailure(); @@ -91,7 +91,7 @@ public void clearWarnings() throws SQLException { @Override public void close() throws SQLException { checkFailure(); - _open = false; + open = false; } @Override @@ -155,13 +155,13 @@ public Struct createStruct(final String typeName, final Object[] attributes) thr @Override public boolean getAutoCommit() throws SQLException { checkOpen(); - return _autoCommit; + return autoCommit; } @Override public String getCatalog() throws SQLException { checkOpen(); - return _catalog; + return catalog; } @Override @@ -182,7 +182,7 @@ public int getHoldability() throws SQLException { @Override public DatabaseMetaData getMetaData() throws SQLException { checkOpen(); - return _metaData; + return metaData; } @Override @@ -199,13 +199,13 @@ public String getSchema() throws SQLException { @Override public int getTransactionIsolation() throws SQLException { checkOpen(); - return _transactionIsolation; + return transactionIsolation; } @Override public Map> getTypeMap() throws SQLException { checkOpen(); - return _typeMap; + return typeMap; } public String getUserName() { @@ -220,19 +220,19 @@ public SQLWarning getWarnings() throws SQLException { public boolean isAborted() throws SQLException { checkFailure(); - return _aborted; + return aborted; } @Override public boolean isClosed() throws SQLException { checkFailure(); - return !_open; + return !open; } @Override public boolean isReadOnly() throws SQLException { checkOpen(); - return _readOnly; + return readOnly; } public boolean isSqlExceptionOnClose() { @@ -241,7 +241,7 @@ public boolean isSqlExceptionOnClose() { @Override public boolean isValid(final int timeout) throws SQLException { - return _open; + return open; } @Override @@ -282,14 +282,15 @@ public CallableStatement prepareCall(final String sql, final int resultSetType, @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { checkOpen(); - if ("null".equals(sql)) { + switch (sql) { + case "null": return null; - } - if ("invalid".equals(sql)) { + case "invalid": throw new SQLException("invalid query"); - } - if ("broken".equals(sql)) { + case "broken": throw new SQLException("broken connection"); + default: + break; } return new TesterPreparedStatement(this, sql); } @@ -352,13 +353,13 @@ public void rollback(final java.sql.Savepoint savepoint) throws SQLException { @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { checkOpen(); - _autoCommit = autoCommit; + this.autoCommit = autoCommit; } @Override public void setCatalog(final String catalog) throws SQLException { checkOpen(); - _catalog = catalog; + this.catalog = catalog; } @Override @@ -389,7 +390,7 @@ public void setNetworkTimeout(final Executor executor, final int milliseconds) @Override public void setReadOnly(final boolean readOnly) throws SQLException { checkOpen(); - _readOnly = readOnly; + this.readOnly = readOnly; } @Override @@ -415,13 +416,13 @@ public void setSqlExceptionOnClose(final boolean sqlExceptionOnClose) { @Override public void setTransactionIsolation(final int level) throws SQLException { checkOpen(); - _transactionIsolation = level; + this.transactionIsolation = level; } @Override public void setTypeMap(final Map> map) throws SQLException { checkOpen(); - _typeMap = map; + this.typeMap = map; } public void setWarnings(final SQLWarning warning) { diff --git a/src/test/java/org/apache/commons/dbcp2/TesterDriver.java b/src/test/java/org/apache/commons/dbcp2/TesterDriver.java index adf3b8c3d8..38e3d5cf63 100644 --- a/src/test/java/org/apache/commons/dbcp2/TesterDriver.java +++ b/src/test/java/org/apache/commons/dbcp2/TesterDriver.java @@ -27,8 +27,8 @@ import java.util.logging.Logger; /** - * Mock object implementing the java.sql.Driver interface. - * Returns TestConnection's from getConnection methods. + * Mock object implementing the {@link Driver} interface. + * Returns {@code TestConnection}'s from getConnection methods. * Valid user name, password combinations are: * * @@ -40,7 +40,11 @@ *
    */ public class TesterDriver implements Driver { + + static TesterDriver INSTANCE = new TesterDriver(); + private static final Properties validUserPasswords = new Properties(); + static { try { DriverManager.registerDriver(new TesterDriver()); diff --git a/src/test/java/org/apache/commons/dbcp2/TesterPreparedStatement.java b/src/test/java/org/apache/commons/dbcp2/TesterPreparedStatement.java index 3d11bbb7fa..b171c8577c 100644 --- a/src/test/java/org/apache/commons/dbcp2/TesterPreparedStatement.java +++ b/src/test/java/org/apache/commons/dbcp2/TesterPreparedStatement.java @@ -40,17 +40,17 @@ */ public class TesterPreparedStatement extends TesterStatement implements PreparedStatement { - private final ResultSetMetaData _resultSetMetaData = null; - private String _sql; - private String _catalog; - private int _autoGeneratedKeys = 1; - private int[] _columnIndexes; - private String[] _columnNames; + private final ResultSetMetaData resultSetMetaData = null; + private String sql; + private String catalog; + private int autoGeneratedKeys = 1; + private int[] columnIndexes; + private String[] columnNames; public TesterPreparedStatement(final Connection conn) { super(conn); try { - _catalog = conn.getCatalog(); + this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } @@ -58,9 +58,9 @@ public TesterPreparedStatement(final Connection conn) { public TesterPreparedStatement(final Connection conn, final String sql) { super(conn); - _sql = sql; + this.sql = sql; try { - _catalog = conn.getCatalog(); + this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } @@ -68,10 +68,10 @@ public TesterPreparedStatement(final Connection conn, final String sql) { public TesterPreparedStatement(final Connection conn, final String sql, final int autoGeneratedKeys) { super(conn); - _sql = sql; - _autoGeneratedKeys = autoGeneratedKeys; + this.sql = sql; + this.autoGeneratedKeys = autoGeneratedKeys; try { - _catalog = conn.getCatalog(); + this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } @@ -79,9 +79,9 @@ public TesterPreparedStatement(final Connection conn, final String sql, final in public TesterPreparedStatement(final Connection conn, final String sql, final int resultSetType, final int resultSetConcurrency) { super(conn, resultSetType, resultSetConcurrency); - _sql = sql; + this.sql = sql; try { - _catalog = conn.getCatalog(); + this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } @@ -90,9 +90,9 @@ public TesterPreparedStatement(final Connection conn, final String sql, final in public TesterPreparedStatement(final Connection conn, final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { super(conn, resultSetType, resultSetConcurrency, resultSetHoldability); - _sql = sql; + this.sql = sql; try { - _catalog = conn.getCatalog(); + this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } @@ -100,10 +100,10 @@ public TesterPreparedStatement(final Connection conn, final String sql, final in public TesterPreparedStatement(final Connection conn, final String sql, final int[] columnIndexes) { super(conn); - _sql = sql; - _columnIndexes = columnIndexes; + this.sql = sql; + this.columnIndexes = columnIndexes; try { - _catalog = conn.getCatalog(); + this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } @@ -111,10 +111,10 @@ public TesterPreparedStatement(final Connection conn, final String sql, final in public TesterPreparedStatement(final Connection conn, final String sql, final String[] columnNames) { super(conn); - _sql = sql; - _columnNames = columnNames; + this.sql = sql; + this.columnNames = columnNames; try { - _catalog = conn.getCatalog(); + this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } @@ -156,13 +156,13 @@ public boolean execute(final String sql, final String[] columnNames) throws SQLE @Override public long executeLargeUpdate() throws SQLException { checkOpen(); - return _rowsUpdated; + return rowsUpdated; } @Override public long executeLargeUpdate(final String sql) throws SQLException { checkOpen(); - return _rowsUpdated; + return rowsUpdated; } @Override @@ -186,14 +186,14 @@ public long executeLargeUpdate(final String sql, final String[] columnNames) thr @Override public ResultSet executeQuery() throws SQLException { checkOpen(); - if ("null".equals(_sql)) { + if ("null".equals(sql)) { return null; } - if (_queryTimeout > 0 && _queryTimeout < 5) { + if (queryTimeout > 0 && queryTimeout < 5) { // Simulate timeout if queryTimout is set to less than 5 seconds throw new SQLException("query timeout"); } - return new TesterResultSet(this, _resultSetType, _resultSetConcurrency); + return new TesterResultSet(this, resultSetType, resultSetConcurrency); } @Override @@ -202,19 +202,19 @@ public ResultSet executeQuery(final String sql) throws SQLException { if ("null".equals(sql)) { return null; } - return new TesterResultSet(this, _resultSetType, _resultSetConcurrency); + return new TesterResultSet(this, resultSetType, resultSetConcurrency); } @Override public int executeUpdate() throws SQLException { checkOpen(); - return (int) _rowsUpdated; + return (int) rowsUpdated; } @Override public int executeUpdate(final String sql) throws SQLException { checkOpen(); - return (int) _rowsUpdated; + return (int) rowsUpdated; } @Override @@ -236,30 +236,30 @@ public int executeUpdate(final String sql, final String[] columnNames) throws SQ } public int getAutoGeneratedKeys() { - return _autoGeneratedKeys; + return autoGeneratedKeys; } public String getCatalog() { - return _catalog; + return catalog; } public int[] getColumnIndexes() { - return _columnIndexes; + return columnIndexes; } public String[] getColumnNames() { - return _columnNames; + return columnNames; } @Override public ResultSet getGeneratedKeys() throws SQLException { - return new TesterResultSet(this, _resultSetType, _resultSetConcurrency); + return new TesterResultSet(this, resultSetType, resultSetConcurrency); } @Override public ResultSetMetaData getMetaData() throws SQLException { checkOpen(); - return _resultSetMetaData; + return resultSetMetaData; } @Override @@ -274,7 +274,7 @@ public java.sql.ParameterMetaData getParameterMetaData() throws SQLException { /** For junit test only */ public String getSql() { - return _sql; + return sql; } @Override @@ -531,6 +531,6 @@ public void setURL(final int parameterIndex, final java.net.URL x) throws SQLExc @Override public String toString() { - return _sql; + return sql; } } diff --git a/src/test/java/org/apache/commons/dbcp2/TesterResultSet.java b/src/test/java/org/apache/commons/dbcp2/TesterResultSet.java index dad25d5923..0150e26366 100644 --- a/src/test/java/org/apache/commons/dbcp2/TesterResultSet.java +++ b/src/test/java/org/apache/commons/dbcp2/TesterResultSet.java @@ -111,7 +111,7 @@ public void close() throws SQLException { // Not all result sets are generated from statements eg DatabaseMetaData if (_statement != null) { - ((TesterStatement) _statement)._resultSet = null; + ((TesterStatement) _statement).resultSet = null; } _open = false; diff --git a/src/test/java/org/apache/commons/dbcp2/TesterStatement.java b/src/test/java/org/apache/commons/dbcp2/TesterStatement.java index 3357543ca8..764372693d 100644 --- a/src/test/java/org/apache/commons/dbcp2/TesterStatement.java +++ b/src/test/java/org/apache/commons/dbcp2/TesterStatement.java @@ -28,39 +28,39 @@ */ public class TesterStatement extends AbandonedTrace implements Statement { - protected final Connection _connection; - protected boolean _open = true; - protected final long _rowsUpdated = 1; - protected final boolean _executeResponse = true; - protected int _maxFieldSize = 1024; - protected long _maxRows = 1024; - protected boolean _escapeProcessing; - protected int _queryTimeout = 1000; - protected String _cursorName; - protected int _fetchDirection = 1; - protected int _fetchSize = 1; - protected int _resultSetConcurrency = 1; - protected int _resultSetType = 1; - private int _resultSetHoldability = 1; - protected ResultSet _resultSet; - protected boolean _sqlExceptionOnClose; - - public TesterStatement(final Connection conn) { - _connection = conn; - } - - public TesterStatement(final Connection conn, final int resultSetType, final int resultSetConcurrency) { - _connection = conn; - _resultSetType = resultSetType; - _resultSetConcurrency = resultSetConcurrency; - } - - public TesterStatement(final Connection conn, final int resultSetType, final int resultSetConcurrency, + protected final Connection connection; + protected boolean open = true; + protected final long rowsUpdated = 1; + protected final boolean executeResponse = true; + protected int maxFieldSize = 1024; + protected long maxRows = 1024; + protected boolean escapeProcessing; + protected int queryTimeout = 1000; + protected String cursorName; + protected int fetchDirection = 1; + protected int fetchSize = 1; + protected int resultSetConcurrency = 1; + protected int resultSetType = 1; + private int resultSetHoldability = 1; + protected ResultSet resultSet; + protected boolean sqlExceptionOnClose; + + public TesterStatement(final Connection connection) { + this.connection = connection; + } + + public TesterStatement(final Connection connection, final int resultSetType, final int resultSetConcurrency) { + this.connection = connection; + this.resultSetType = resultSetType; + this.resultSetConcurrency = resultSetConcurrency; + } + + public TesterStatement(final Connection connection, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { - _connection = conn; - _resultSetType = resultSetType; - _resultSetConcurrency = resultSetConcurrency; - _resultSetHoldability = resultSetHoldability; + this.connection = connection; + this.resultSetType = resultSetType; + this.resultSetConcurrency = resultSetConcurrency; + this.resultSetHoldability = resultSetHoldability; } @Override @@ -74,7 +74,7 @@ public void cancel() throws SQLException { } protected void checkOpen() throws SQLException { - if (!_open) { + if (!open) { throw new SQLException("Connection is closed."); } } @@ -91,19 +91,19 @@ public void clearWarnings() throws SQLException { @Override public void close() throws SQLException { - if (_sqlExceptionOnClose) { + if (sqlExceptionOnClose) { throw new SQLException("TestSQLExceptionOnClose"); } // calling close twice has no effect - if (!_open) { + if (!open) { return; } - _open = false; - if (_resultSet != null) { - _resultSet.close(); - _resultSet = null; + open = false; + if (resultSet != null) { + resultSet.close(); + resultSet = null; } } @@ -118,7 +118,7 @@ public boolean execute(final String sql) throws SQLException { if ("invalid".equals(sql)) { throw new SQLException("invalid query"); } - return _executeResponse; + return executeResponse; } @Override @@ -154,7 +154,7 @@ public long[] executeLargeBatch() throws SQLException { @Override public long executeLargeUpdate(final String sql) throws SQLException { checkOpen(); - return _rowsUpdated; + return rowsUpdated; } @Override @@ -175,22 +175,23 @@ public long executeLargeUpdate(final String sql, final String[] columnNames) thr @Override public ResultSet executeQuery(final String sql) throws SQLException { checkOpen(); - if ("null".equals(sql)) { + switch (sql) { + case "null": return null; - } - if ("invalid".equals(sql)) { + case "invalid": throw new SQLException("invalid query"); - } - if ("broken".equals(sql)) { + case "broken": throw new SQLException("broken connection"); - } - if ("select username".equals(sql)) { - final String userName = ((TesterConnection) _connection).getUserName(); + case "select username": { + final String userName = ((TesterConnection) connection).getUserName(); final Object[][] data = { { userName } }; return new TesterResultSet(this, data); } + default: + break; + } // Simulate timeout if queryTimout is set to less than 5 seconds - if (_queryTimeout > 0 && _queryTimeout < 5) { + if (queryTimeout > 0 && queryTimeout < 5) { throw new SQLException("query timeout"); } return new TesterResultSet(this); @@ -199,7 +200,7 @@ public ResultSet executeQuery(final String sql) throws SQLException { @Override public int executeUpdate(final String sql) throws SQLException { checkOpen(); - return (int) _rowsUpdated; + return (int) rowsUpdated; } @Override @@ -220,19 +221,19 @@ public int executeUpdate(final String sql, final String[] columnNames) throws SQ @Override public Connection getConnection() throws SQLException { checkOpen(); - return _connection; + return connection; } @Override public int getFetchDirection() throws SQLException { checkOpen(); - return _fetchDirection; + return fetchDirection; } @Override public int getFetchSize() throws SQLException { checkOpen(); - return _fetchSize; + return fetchSize; } @Override @@ -243,25 +244,25 @@ public ResultSet getGeneratedKeys() throws SQLException { @Override public long getLargeMaxRows() throws SQLException { checkOpen(); - return _maxRows; + return maxRows; } @Override public long getLargeUpdateCount() throws SQLException { checkOpen(); - return _rowsUpdated; + return rowsUpdated; } @Override public int getMaxFieldSize() throws SQLException { checkOpen(); - return _maxFieldSize; + return maxFieldSize; } @Override public int getMaxRows() throws SQLException { checkOpen(); - return (int) _maxRows; + return (int) maxRows; } @Override @@ -278,40 +279,40 @@ public boolean getMoreResults(final int current) throws SQLException { @Override public int getQueryTimeout() throws SQLException { checkOpen(); - return _queryTimeout; + return queryTimeout; } @Override public ResultSet getResultSet() throws SQLException { checkOpen(); - if (_resultSet == null) { - _resultSet = new TesterResultSet(this); + if (resultSet == null) { + resultSet = new TesterResultSet(this); } - return _resultSet; + return resultSet; } @Override public int getResultSetConcurrency() throws SQLException { checkOpen(); - return _resultSetConcurrency; + return resultSetConcurrency; } @Override public int getResultSetHoldability() throws SQLException { checkOpen(); - return _resultSetHoldability; + return resultSetHoldability; } @Override public int getResultSetType() throws SQLException { checkOpen(); - return _resultSetType; + return resultSetType; } @Override public int getUpdateCount() throws SQLException { checkOpen(); - return (int) _rowsUpdated; + return (int) rowsUpdated; } @Override @@ -322,7 +323,7 @@ public SQLWarning getWarnings() throws SQLException { @Override public boolean isClosed() throws SQLException { - return !_open; + return !open; } @Override @@ -336,7 +337,7 @@ public boolean isPoolable() throws SQLException { } public boolean isSqlExceptionOnClose() { - return _sqlExceptionOnClose; + return sqlExceptionOnClose; } @Override @@ -347,43 +348,43 @@ public boolean isWrapperFor(final Class iface) throws SQLException { @Override public void setCursorName(final String name) throws SQLException { checkOpen(); - _cursorName = name; + this.cursorName = name; } @Override public void setEscapeProcessing(final boolean enable) throws SQLException { checkOpen(); - _escapeProcessing = enable; + this.escapeProcessing = enable; } @Override public void setFetchDirection(final int direction) throws SQLException { checkOpen(); - _fetchDirection = direction; + this.fetchDirection = direction; } @Override public void setFetchSize(final int rows) throws SQLException { checkOpen(); - _fetchSize = rows; + this.fetchSize = rows; } @Override public void setLargeMaxRows(final long max) throws SQLException { checkOpen(); - _maxRows = max; + this.maxRows = max; } @Override public void setMaxFieldSize(final int max) throws SQLException { checkOpen(); - _maxFieldSize = max; + this.maxFieldSize = max; } @Override public void setMaxRows(final int max) throws SQLException { checkOpen(); - _maxRows = max; + this.maxRows = max; } @Override @@ -394,11 +395,11 @@ public void setPoolable(final boolean poolable) throws SQLException { @Override public void setQueryTimeout(final int seconds) throws SQLException { checkOpen(); - _queryTimeout = seconds; + this.queryTimeout = seconds; } public void setSqlExceptionOnClose(final boolean _sqlExceptionOnClose) { - this._sqlExceptionOnClose = _sqlExceptionOnClose; + this.sqlExceptionOnClose = _sqlExceptionOnClose; } @Override diff --git a/src/test/java/org/apache/commons/dbcp2/cpdsadapter/TestDriverAdapterCPDS.java b/src/test/java/org/apache/commons/dbcp2/cpdsadapter/TestDriverAdapterCPDS.java index 6fc6042f1d..784eff84b5 100644 --- a/src/test/java/org/apache/commons/dbcp2/cpdsadapter/TestDriverAdapterCPDS.java +++ b/src/test/java/org/apache/commons/dbcp2/cpdsadapter/TestDriverAdapterCPDS.java @@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import java.io.PrintWriter; import java.sql.Connection; @@ -290,30 +289,15 @@ public void testGettersAndSetters() { * JIRA: DBCP-245 */ @Test - public void testIncorrectPassword() throws Exception - { + public void testIncorrectPassword() throws Exception { pcds.getPooledConnection("u2", "p2").close(); - try { - // Use bad password - pcds.getPooledConnection("u1", "zlsafjk"); - fail("Able to retrieve connection with incorrect password"); - } catch (final SQLException e1) { - // should fail - - } + // Use bad password + assertThrows(SQLException.class, () -> pcds.getPooledConnection("u1", "zlsafjk"), "Able to retrieve connection with incorrect password"); // Use good password - pcds.getPooledConnection("u1", "p1").close(); - try { - pcds.getPooledConnection("u1", "x"); - fail("Able to retrieve connection with incorrect password"); - } - catch (final SQLException e) { - if (!e.getMessage().startsWith("x is not the correct password")) { - throw e; - } - // else the exception was expected - } + final SQLException e = assertThrows(SQLException.class, () -> pcds.getPooledConnection("u1", "x"), "Able to retrieve connection with incorrect password"); + assertTrue(e.getMessage().startsWith("x is not the correct password")); + // else the exception was expected // Make sure we can still use our good password. pcds.getPooledConnection("u1", "p1").close(); diff --git a/src/test/java/org/apache/commons/dbcp2/datasources/TestFactory.java b/src/test/java/org/apache/commons/dbcp2/datasources/TestFactory.java index 610652fe58..9638b76902 100644 --- a/src/test/java/org/apache/commons/dbcp2/datasources/TestFactory.java +++ b/src/test/java/org/apache/commons/dbcp2/datasources/TestFactory.java @@ -29,20 +29,53 @@ import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; /** + * Tests SharedPoolDataSourceFactory. */ public class TestFactory { - // Bugzilla Bug 24082: bug in InstanceKeyDataSourceFactory - // There's a fatal bug in InstanceKeyDataSourceFactory that means you can't - // instantiate more than one factory. - // https://issues.apache.org/bugzilla/show_bug.cgi?id=24082 - @Test - public void testJNDI2Pools() throws Exception { + /** + * Tests Bugzilla Bug 24082: bug in InstanceKeyDataSourceFactory. + * + * There's a fatal bug in InstanceKeyDataSourceFactory that means you can't instantiate more than one factory. + * https://issues.apache.org/bugzilla/show_bug.cgi?id=24082 + */ + @ParameterizedTest + // @formatter:off + @CsvSource({ + "dataSourceName, java:comp/env/jdbc/bookstoreCPDS", + "description, This is a test.", + "jndiEnvironment, X", + "loginTimeout, 30000", + "blockWhenExhausted, false", + "evictionPolicyClassName, org.apache.commons.pool2.impl.DefaultEvictionPolicy", + "lifo, true", + "maxIdlePerKey, 4", + "maxTotalPerKey, 4", + "maxWaitMillis, 30001", + "minEvictableIdleTimeMillis, 30002", + "minIdlePerKey, 4", + "numTestsPerEvictionRun, 2", + "softMinEvictableIdleTimeMillis, 30003", + "testOnCreate, true", + "testOnBorrow, true", + "testOnReturn, true", + "testWhileIdle, true", + "timeBetweenEvictionRunsMillis, 30004", + "validationQuery, select 1", + "validationQueryTimeout, 30005", + "rollbackAfterValidation, false", + "maxConnLifetimeMillis, 60000", + "defaultAutoCommit, true", + "defaultTransactionIsolation, X", + "defaultReadOnly, true" }) + // @formatter:on + public void testJNDI2Pools(final String string, final String value) throws Exception { final Reference refObj = new Reference(SharedPoolDataSource.class.getName()); - refObj.add(new StringRefAddr("dataSourceName","java:comp/env/jdbc/bookstoreCPDS")); + refObj.add(new StringRefAddr(string, value)); final Context context = new InitialContext(); final Hashtable env = new Hashtable<>(); diff --git a/src/test/java/org/apache/commons/dbcp2/datasources/TestPerUserPoolDataSource.java b/src/test/java/org/apache/commons/dbcp2/datasources/TestPerUserPoolDataSource.java index 529c6beb71..4d3080edcb 100644 --- a/src/test/java/org/apache/commons/dbcp2/datasources/TestPerUserPoolDataSource.java +++ b/src/test/java/org/apache/commons/dbcp2/datasources/TestPerUserPoolDataSource.java @@ -90,7 +90,9 @@ public void tearDown() throws Exception { ((PerUserPoolDataSource) ds).close(); } - // See DBCP-8 + /** + * See DBCP-8 + */ @Test public void testChangePassword() throws Exception { assertThrows(SQLException.class, () -> ds.getConnection(user, "bay")); @@ -99,28 +101,23 @@ public void testChangePassword() throws Exception { final Connection con3 = ds.getConnection(user, "bar"); con1.close(); con2.close(); - TesterDriver.addUser(user,"bay"); // change the user/password setting + TesterDriver.addUser(user, "bay"); // change the user/password setting try { final Connection con4 = ds.getConnection(user, "bay"); // new password // Idle instances with old password should have been cleared - assertEquals(0, ((PerUserPoolDataSource) ds).getNumIdle(user), - "Should be no idle connections in the pool"); + assertEquals(0, ((PerUserPoolDataSource) ds).getNumIdle(user), "Should be no idle connections in the pool"); con4.close(); // Should be one idle instance with new pwd - assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user), - "Should be one idle connection in the pool"); - try (Connection c = ds.getConnection(user, "bar")) { // old password - fail("Should have generated SQLException"); - } catch (final SQLException expected) { + assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user), "Should be one idle connection in the pool"); + // old password + assertThrows(SQLException.class, () -> ds.getConnection(user, "bar"), "Should have generated SQLException"); + try (Connection con5 = ds.getConnection(user, "bay")) { // take the idle one + con3.close(); // Return a connection with the old password + ds.getConnection(user, "bay").close(); // will try bad returned connection and destroy it + assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user), "Should be one idle connection in the pool"); } - final Connection con5 = ds.getConnection(user, "bay"); // take the idle one - con3.close(); // Return a connection with the old password - ds.getConnection(user, "bay").close(); // will try bad returned connection and destroy it - assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user), - "Should be one idle connection in the pool"); - con5.close(); } finally { - TesterDriver.addUser(user,"bar"); + TesterDriver.addUser(user, "bar"); } } diff --git a/src/test/java/org/apache/commons/dbcp2/managed/TestConnectionWithNarayana.java b/src/test/java/org/apache/commons/dbcp2/managed/TestConnectionWithNarayana.java index cae8307d55..126ed05caa 100644 --- a/src/test/java/org/apache/commons/dbcp2/managed/TestConnectionWithNarayana.java +++ b/src/test/java/org/apache/commons/dbcp2/managed/TestConnectionWithNarayana.java @@ -119,7 +119,7 @@ public void testConnectionCommitAfterTimeout() throws Exception { fail("Should not work after timeout"); } catch (final SQLException e) { // Expected - Assertions.assertEquals("Commit can not be set while enrolled in a transaction", e.getMessage()); + Assertions.assertEquals("Commit cannot be set while enrolled in a transaction", e.getMessage()); } mds.getTransactionManager().rollback(); } diff --git a/src/test/java/org/apache/commons/dbcp2/managed/TestDataSourceXAConnectionFactory.java b/src/test/java/org/apache/commons/dbcp2/managed/TestDataSourceXAConnectionFactory.java index 6646bb13fc..870876589a 100644 --- a/src/test/java/org/apache/commons/dbcp2/managed/TestDataSourceXAConnectionFactory.java +++ b/src/test/java/org/apache/commons/dbcp2/managed/TestDataSourceXAConnectionFactory.java @@ -55,15 +55,16 @@ protected XAConnection getXAConnection() throws SQLException { public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { final String methodName = method.getName(); - if (methodName.equals("hashCode")) { + switch (methodName) { + case "hashCode": return System.identityHashCode(proxy); - } - if (methodName.equals("equals")) { + case "equals": return proxy == args[0]; - } - if (methodName.equals("getXAConnection")) { + case "getXAConnection": // both zero and 2-arg signatures return getXAConnection(); + default: + break; } try { return method.invoke(ds, args); diff --git a/src/test/java/org/apache/commons/dbcp2/managed/TestSynchronizationOrder.java b/src/test/java/org/apache/commons/dbcp2/managed/TestSynchronizationOrder.java index b0fd5e9a24..940f7742e3 100644 --- a/src/test/java/org/apache/commons/dbcp2/managed/TestSynchronizationOrder.java +++ b/src/test/java/org/apache/commons/dbcp2/managed/TestSynchronizationOrder.java @@ -18,6 +18,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.reflect.InvocationHandler; @@ -134,15 +135,16 @@ protected XAConnection getXAConnection() throws SQLException { public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { final String methodName = method.getName(); - if (methodName.equals("hashCode")) { + switch (methodName) { + case "hashCode": return System.identityHashCode(proxy); - } - if (methodName.equals("equals")) { + case "equals": return proxy == args[0]; - } - if (methodName.equals("getXAConnection")) { + case "getXAConnection": // both zero and 2-arg signatures return getXAConnection(); + default: + break; } try { return method.invoke(bds, args); @@ -188,7 +190,7 @@ public void testInterposedSynchronization() throws Exception { transactionManager.begin(); try (final Connection connectionA = ds.getConnection()) { // Check and close right away. - assertTrue(connectionA instanceof DelegatingConnection); + assertInstanceOf(DelegatingConnection.class, connectionA); } transactionManager.commit(); assertFalse(transactionManagerRegistered); @@ -221,7 +223,7 @@ public void testSessionSynchronization() throws Exception { transactionManager.begin(); try (final Connection connectionA = ds.getConnection()) { // Check and close right away. - assertTrue(connectionA instanceof DelegatingConnection); + assertInstanceOf(DelegatingConnection.class, connectionA); } transactionManager.commit(); assertTrue(transactionManagerRegistered); diff --git a/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java b/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java index 2c46cd8c38..211cca002e 100644 --- a/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java +++ b/src/test/java/org/apache/commons/dbcp2/managed/TestTransactionContext.java @@ -17,8 +17,8 @@ Licensed to the Apache Software Foundation (ASF) under one or more */ package org.apache.commons.dbcp2.managed; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.Connection; import java.sql.SQLException; @@ -62,7 +62,7 @@ public void testSetSharedConnectionEnlistFailure() throws Exception { basicManagedDataSource.setPassword("password"); basicManagedDataSource.setMaxIdle(1); try (final Connection conn = basicManagedDataSource.getConnection()) { - assertTrue(conn instanceof ManagedConnection); + assertInstanceOf(ManagedConnection.class, conn); final UncooperativeTransaction transaction = new UncooperativeTransaction(); final TransactionContext transactionContext = new TransactionContext(basicManagedDataSource.getTransactionRegistry(), transaction); assertThrows(SQLException.class, () -> transactionContext.setSharedConnection(conn)); diff --git a/src/test/java/org/apache/commons/dbcp2/managed/TesterBasicXAConnection.java b/src/test/java/org/apache/commons/dbcp2/managed/TesterBasicXAConnection.java index 9d36c93c25..b5994ef594 100644 --- a/src/test/java/org/apache/commons/dbcp2/managed/TesterBasicXAConnection.java +++ b/src/test/java/org/apache/commons/dbcp2/managed/TesterBasicXAConnection.java @@ -75,17 +75,17 @@ public void closeHandle() { public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { final String methodName = method.getName(); - if (methodName.equals("hashCode")) { + switch (methodName) { + case "hashCode": return System.identityHashCode(proxy); - } - if (methodName.equals("equals")) { + case "equals": return proxy == args[0]; - } - if (methodName.equals("isClosed")) { + case "isClosed": return conn == null; - } - if (methodName.equals("close")) { + case "close": return close(); + default: + break; } if (conn == null) { throw new SQLException("Connection closed");