diff --git a/.asf.yaml b/.asf.yaml index 98c155e98..5db049546 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -5,7 +5,7 @@ # (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 +# https://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, @@ -23,7 +23,8 @@ notifications: pullrequests: issues@commons.apache.org jira_options: link label jobs: notifications@commons.apache.org - issues_bot_dependabot: notifications@commons.apache.org - pullrequests_bot_dependabot: notifications@commons.apache.org + # commits_bot_dependabot: dependabot@commons.apache.org + issues_bot_dependabot: dependabot@commons.apache.org + pullrequests_bot_dependabot: dependabot@commons.apache.org issues_bot_codecov-commenter: notifications@commons.apache.org pullrequests_bot_codecov-commenter: notifications@commons.apache.org diff --git a/.github/GH-ROBOTS.txt b/.github/GH-ROBOTS.txt index e3329e55f..64a88674f 100644 --- a/.github/GH-ROBOTS.txt +++ b/.github/GH-ROBOTS.txt @@ -5,7 +5,7 @@ # (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 +# https://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, diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9ebcd0ebb..90ec55f74 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ # (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 +# https://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, @@ -18,10 +18,8 @@ updates: - package-ecosystem: "maven" directory: "/" schedule: - interval: "weekly" - day: "friday" + interval: "quarterly" - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "weekly" - day: "friday" + interval: "quarterly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..9ff35c83e --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,30 @@ + + +Thanks for your contribution to [Apache Commons](https://commons.apache.org/)! Your help is appreciated! + +Before you push a pull request, review this list: + +- [ ] Read the [contribution guidelines](CONTRIBUTING.md) for this project. +- [ ] Read the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) if you use Artificial Intelligence (AI). +- [ ] I used AI to create any part of, or all of, this pull request. Which AI tool was used to create this pull request, and to what extent did it contribute? +- [ ] Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. +- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice. +- [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. +- [ ] Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process. diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4605ce109..25084aa7c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -5,7 +5,7 @@ # (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 +# https://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, @@ -45,19 +45,23 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - + - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 + with: + java-version: 17 + distribution: 'temurin' + # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@46ed16ded91731b2df79a2893d3aea8e9f03b5c4 # v2.20.3 + uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +72,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@46ed16ded91731b2df79a2893d3aea8e9f03b5c4 # v2.20.3 + uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +86,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@46ed16ded91731b2df79a2893d3aea8e9f03b5c4 # v2.20.3 + uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index d984e1f30..000000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,52 +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: [push, pull_request] - -permissions: - contents: read - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - matrix: - java: [ 8 ] - - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - persist-credentials: false - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 - 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@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'temurin' - java-version: ${{ matrix.java }} - - name: Build with Maven - run: mvn -V test jacoco:report --file pom.xml --no-transfer-progress - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 - 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 000000000..1df866604 --- /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 +# +# https://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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - name: 'Dependency Review PR' + uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d74eae20e..befc6da1e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -5,7 +5,7 @@ # (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 +# https://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, @@ -15,8 +15,12 @@ name: Java CI -on: [push, pull_request] - +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + permissions: contents: read @@ -27,26 +31,26 @@ jobs: continue-on-error: ${{ matrix.experimental }} strategy: matrix: - java: [ 8, 11, 17 ] + java: [ 17, 21, 24 ] experimental: [false] -# include: -# - java: 18-ea -# experimental: true + include: + - java: 25-ea + experimental: true steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 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@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} - name: Build with Maven - run: mvn -V -B --file pom.xml --no-transfer-progress + run: mvn --show-version --batch-mode --no-transfer-progress diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index eba354fe9..3c49b0d63 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -5,7 +5,7 @@ # (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 +# https://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, @@ -40,12 +40,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # 2.2.0 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # 2.4.3 with: results_file: results.sarif results_format: sarif @@ -57,13 +57,13 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # 3.1.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 6.0.0 with: name: SARIF file path: results.sarif retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@46ed16ded91731b2df79a2893d3aea8e9f03b5c4 # 2.20.3 + uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 with: sarif_file: results.sarif diff --git a/.gitignore b/.gitignore index 443c59a66..b39768638 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,9 @@ site-content /.settings/ /bin/ .idea/ +.vscode/ *.iml + +# NetBeans files +nb-configuration.xml +nbactions.xml diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 3ed501501..b4342f33c 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -6,7 +6,7 @@ (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 + https://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, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5814970db..8f8f321b5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ (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 + https://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, @@ -61,16 +61,15 @@ 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. `POOL-123-InputStream`. + * Usually you should base your branch from the `master` branch. + * A good topic branch name can be the JIRA bug id plus a keyword, for example, `POOL-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. - * e.g. `POOL-123: Close input stream earlier` + * For example, `[POOL-123] Close input stream earlier` + Respect the original code style: - + Only use spaces for indentation. + + Only use spaces for indentation; you can check for unnecessary whitespace with `git diff` before committing. + 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. @@ -80,8 +79,7 @@ Making Trivial Changes The JIRA tickets are used to generate the changelog for the next release. For changes of a trivial nature to comments and documentation, it is not always necessary to create a new ticket in JIRA. -In this case, it is appropriate to start the first line of a commit with '(doc)' instead of a ticket number. - +In this case, it is appropriate to start the first line of a commit with '[doc]' or '[javadoc]' instead of a ticket number. Submitting Changes ------------------ diff --git a/LICENSE.txt b/LICENSE.txt index 06b2ca877..167bbe266 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -193,16 +193,16 @@ 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 + https://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. - + APACHE COMMONS POOL DERIVATIVE WORKS: - + The LinkedBlockingDeque implementation is based on an implementation written by Doug Lea with assistance from members of JCP JSR-166 Expert Group and released to the public domain, as explained at diff --git a/NOTICE.txt b/NOTICE.txt index 2c90b4379..e7123c404 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ Apache Commons Pool -Copyright 2001-2023 The Apache Software Foundation +Copyright 2001-2026 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). diff --git a/README.md b/README.md index f07fdc8a8..867c1004b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ (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 + https://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, @@ -43,11 +43,10 @@ Apache Commons Pool =================== -[![GitHub Actions Status](https://github.com/apache/commons-pool/workflows/Java%20CI/badge.svg)](https://github.com/apache/commons-pool/actions) -[![Coverage Status](https://codecov.io/gh/apache/commons-pool/branch/master/graph/badge.svg)](https://app.codecov.io/gh/apache/commons-pool) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.commons/commons-pool2/badge.svg?gav=true)](https://maven-badges.herokuapp.com/maven-central/org.apache.commons/commons-pool2/?gav=true) +[![Java CI](https://github.com/apache/commons-pool/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/commons-pool/actions/workflows/maven.yml) +[![Maven Central](https://img.shields.io/maven-central/v/org.apache.commons/commons-pool2?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.commons/commons-pool2) [![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-pool2/2.12.0.svg)](https://javadoc.io/doc/org.apache.commons/commons-pool2/2.12.0) -[![CodeQL](https://github.com/apache/commons-pool/workflows/CodeQL/badge.svg)](https://github.com/apache/commons-pool/actions/workflows/codeql-analysis.yml?query=workflow%3ACodeQL) +[![CodeQL](https://github.com/apache/commons-pool/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/commons-pool/actions/workflows/codeql-analysis.yml) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/commons-pool/badge)](https://api.securityscorecards.dev/projects/github.com/apache/commons-pool) The Apache Commons Object Pooling Library. @@ -57,7 +56,7 @@ Documentation More information can be found on the [Apache Commons Pool homepage](https://commons.apache.org/proper/commons-pool). The [Javadoc](https://commons.apache.org/proper/commons-pool/apidocs) can be browsed. -Questions related to the usage of Apache Commons Pool should be posted to the [user mailing list][ml]. +Questions related to the usage of Apache Commons Pool should be posted to the [user mailing list](https://commons.apache.org/mail-lists.html). Where can I get the latest release? ----------------------------------- @@ -68,8 +67,8 @@ Alternatively, you can pull it from the central Maven repositories: ```xml org.apache.commons - commons-pool2 - 2.12.0 + commons-pool3 + 3.0.0 ``` @@ -81,14 +80,16 @@ There are some guidelines which will make applying PRs easier for us: + No tabs! Please use spaces for indentation. + Respect the code style. + 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. -+ Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running ```mvn```. ++ Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running `mvn`. ++ Before you pushing a PR, run `mvn` (by itself), this runs the default goal, which contains all build checks. ++ To see the code coverage report, regardless of coverage failures, run `mvn clean site -Dcommons.jacoco.haltOnFailure=false` If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas). You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md). License ------- -This code is under the [Apache Licence v2](https://www.apache.org/licenses/LICENSE-2.0). +This code is under the [Apache License v2](https://www.apache.org/licenses/LICENSE-2.0). See the `NOTICE.txt` file for required notices and attributions. diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 29f9dc6ac..9a23594a5 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,29 +1,73 @@ +Apache Commons Pool 2.12.1 Release Notes +---------------------------------------- + +The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.12.1. + +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. +In addition to performance and scalability improvements, version 2 includes robust instance +tracking and pool monitoring. + +Version 2.7.x and up requires Java 8 or above. +Version 2.6.x requires Java 7 or above. +Version 2.5.x requires Java 7 or above. +Version 2.0 requires 6 or above. + +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, + and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not + be able to upgrade to a new minor or patch release without requiring code + changes. + +Changes in version 2.12.1 include: + +Fixed Bugs: +o Use java.time.Instant precision in org.apache.commons.pool2.impl.ThrowableCallStack.Snapshot throwable message. Thanks to Gary Gregory. +o GenericObjectPool.borrowObject(Duration) doesn't obey its borrowMaxWait Duration argument when the argument is different from GenericObjectPool.getMaxWaitDuration(). Thanks to Gary Gregory. +o POOL-418: The maximum wait time for GenericObjectPool.borrowObject(*) may exceed expectations due to a spurious thread wakeup. Thanks to Gary Gregory. +o Javadoc is missing its Overview page. Thanks to Gary Gregory. +o Migrate site generation templates to https://maven.apache.org/xsd/xdoc-2.0.xsd. Thanks to Gary Gregory. + +Changes: +o Bump org.apache.commons:commons-parent from 62 to 79. Thanks to Gary Gregory. +o [test] Bump commons-lang3 from 3.13.0 to 3.17.0. Thanks to Gary Gregory. +o [site] Pickup org.apache.bcel:bcel version from parent POM. Thanks to Gary Gregory. +o [test] Bump org.ow2.asm:asm-util from 9.5 to 9.7.1. Thanks to Gary Gregory. + + +For complete information on Apache Commons Pool, including instructions on how to submit bug reports, +patches, or suggestions for improvement, see the Apache Commons Pool website: + +https://commons.apache.org/proper/commons-pool/ + +Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi + +----------------------------------------------------------------------------------------------- Apache Commons Pool 2.12.0 RELEASE NOTES The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.12.0. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. +tracking and pool monitoring. Version 2.7.x and up requires Java 8 or above. Version 2.6.x requires Java 7 or above. Version 2.5.x requires Java 7 or above. Version 2.0 requires 6 or above. -No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. -Users of version 1.x should consult the migration guide on the Commons Pool web site. - -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -This is a feature and maintenance release (Java 8). +This is a feature and maintenance release (Java 8 or above). Changes in version 2.12.0 include: @@ -33,23 +77,26 @@ o Add GenericKeyedObjectPool.getKeys(). Thanks to Vamsi Pavan Kumar S o Add KeyedObjectPool.getKeys(). Thanks to Gary Gregory. o Add github/codeql-action. o Add BaseGenericObjectPool.Evictor.toString(). -o BaseGenericObjectPool now implements AutoCloseable. +o Make BaseGenericObjectPool implement AutoCloseable. +o Add BaseGenericObjectPool methods that return Duration and deprecate equivalents that return milliseconds as long. +o Add BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS and deprecate BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS. Fixed Bugs: o POOL-401: Ensure that capacity freed by invalidateObject is available to all keyed pools. o POOL-391: Ensure capacity freed by clear is made available to GKOP borrowers. Thanks to Codievilky August. o POOL-402: Check blockWhenExhausted in hasBorrowWaiters #116. Thanks to Cp-John, Phil Steitz, Bruno P. Kinoshita, Gary Gregory. o Simplify test assertion with similar call but simpler. #131. Thanks to Arturo Bernal. -o POOL-269: Use generic exceptions instead of java.lang.Exception. Thanks to Gary Gregory. o POOL-405: NullPointerException GenericKeyedObjectPool.invalidateObject(GenericKeyedObjectPool.java:1343). Thanks to Gary Gregory. -o POOL-408: A typo of KeyedPooledObjectFactory on the site and Javadoc. Thanks to Zhenyu Luo, Gary Gregory. +o POOL-408: Fix a typo related to KeyedPooledObjectFactory on the site and Javadoc. Thanks to Zhenyu Luo, Gary Gregory. o Fail-fast on null input for DefaultPooledObjectInfo.DefaultPooledObjectInfo(PooledObject) with a NullPointerException. Thanks to Gary Gregory. o POOL-393: Improve BaseGenericObjectPool's JMX Register performance when creating many pools. Thanks to Shichao Yuan, Phil Steitz, Niall Pemberton. o Null-guard in GenericObjectPool.use(T) like other call sites of GenericObjectPool.getPooledObject(T). Thanks to Réda Housni Alaoui, Gary Gregory. -o POOL-411: NPE when deregistering key at end of borrow. Thanks to Richard Eckart de Castilho, Gary Gregory. -o Make private class GenericKeyedObjectPool.ObjectDeque class static. Thanks to Gary Gregory. -o Make private class BaseGenericObjectPool.StatsStore class static. Thanks to Gary Gregory. +o POOL-411: Guard against NPE when deregistering a key at the end of borrow. Thanks to Richard Eckart de Castilho, Gary Gregory. +o Make private GenericKeyedObjectPool.ObjectDeque class static. Thanks to Gary Gregory. +o Make private BaseGenericObjectPool.StatsStore class static. Thanks to Gary Gregory. o [StepSecurity] ci: Harden GitHub Actions #225. Thanks to step-security-bot, Gary Gregory. +o Fix possible NPE in DefaultPooledObjectInfo.getPooledObjectToString(). Thanks to Gary Gregory. +o Fix possible NPE in DefaultPooledObjectInfo.getPooledObjectType(). Thanks to Gary Gregory. Changes: o Bump actions/cache from 2.1.6 to 3.0.10 #117, #138, #158, #174, #178. Thanks to Dependabot, Gary Gregory. @@ -70,6 +117,7 @@ o Bump commons-parent from 52 to 58 #173, #195, #204, #222. Thanks to o Bump japicmp-maven-plugin from 0.15.3 to 0.16.0. Thanks to Gary Gregory. o Bump animal-sniffer-maven-plugin 1.20 to 1.21. Thanks to Gary Gregory. o Bump Apache Commons BCEL 6.5.0 to 6.7.0 #194. Thanks to Gary Gregory, Dependabot. +o Bump commons-lang3 from 3.12.0 to 3.13.0. Thanks to Gary Gregory. For complete information on Apache Commons Pool, including instructions on how to submit bug reports, @@ -85,10 +133,10 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.11.1. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. +tracking and pool monitoring. Version 2.7.x and up requires Java 8 or above. Version 2.6.x requires Java 7 or above. @@ -98,15 +146,15 @@ Version 2.0 requires 6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -This is a maintenance release (Java 8). +This is a maintenance release (Java 8 or above). Changes in version 2.11.1 include: @@ -144,10 +192,10 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.11.0. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. +tracking and pool monitoring. Version 2.10.x requires Java 8 or above. Version 2.9.x requires Java 8 or above. @@ -160,15 +208,15 @@ Version 2.0 requires 6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -This is a feature release (Java 8). +This is a feature release (Java 8 or above). Changes in version 2.11.0 include: @@ -231,10 +279,10 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.10.0. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. +tracking and pool monitoring. Version 2.10.x requires Java 8 or above. Version 2.9.x requires Java 8 or above. @@ -247,15 +295,15 @@ Version 2.0 requires 6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -This is a MMMM release (Java 8). +This is a MMMM release (Java 8 or above). Changes in version 2.10.0 include: @@ -303,10 +351,10 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.9.0. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. +tracking and pool monitoring. Version 2.9.x requires Java 8 or above. Version 2.8.x requires Java 8 or above. @@ -318,15 +366,15 @@ Version 2.0 requires 6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -This is a minor release (Java 8). +This is a minor release (Java 8 or above). Changes in version 2.9.0 include: @@ -350,23 +398,25 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.8.1. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. Version 2 requires JDK level 1.6 or above. +tracking and pool monitoring. + +Version 2 requires JDK level 1.6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -This is a maintenance release (Java 8). +This is a maintenance release (Java 8 or above). Changes in version 2.8.1 include: @@ -403,23 +453,25 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.8.0. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. Version 2 requires JDK level 1.6 or above. +tracking and pool monitoring. + +Version 2 requires JDK level 1.6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -This is a maintenance release (Java 8). +This is a maintenance release (Java 8 or above). Changes in version 2.8.0 include: @@ -455,23 +507,25 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.7.0. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. Version 2 requires JDK level 1.6 or above. +tracking and pool monitoring. + +Version 2 requires JDK level 1.6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -This is a feature release (Java 8). +This is a feature release (Java 8 or above). Changes in version 2.7.0 include: @@ -502,19 +556,21 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.6.2. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. Version 2 requires JDK level 1.6 or above. +tracking and pool monitoring. + +Version 2 requires JDK level 1.6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. @@ -540,19 +596,21 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.6.1. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. Version 2 requires JDK level 1.6 or above. +tracking and pool monitoring. + +Version 2 requires JDK level 1.6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. @@ -589,8 +647,8 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.6.0. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance tracking and pool monitoring. @@ -601,11 +659,11 @@ tracking and pool monitoring. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. @@ -643,19 +701,21 @@ Download page: https://commons.apache.org/proper/commons-pool/download_pool.cgi The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.5.0. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. Version 2 requires JDK level 1.6 or above. +tracking and pool monitoring. + +Version 2 requires JDK level 1.6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. @@ -686,19 +746,21 @@ https://commons.apache.org/proper/commons-pool/ The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.4.3. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. Version 2 requires JDK level 1.6 or above. +tracking and pool monitoring. + +Version 2 requires JDK level 1.6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.3. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. @@ -745,19 +807,21 @@ https://commons.apache.org/proper/commons-pool/ The Apache Commons Pool team is pleased to announce the release of Apache Commons Pool 2.4.2. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. Version 2 requires JDK level 1.6 or above. +tracking and pool monitoring. + +Version 2 requires JDK level 1.6 or above. No client code changes are required to migrate from versions 2.0-2.3 to version 2.4.2. Users of version 1.x should consult the migration guide on the Commons Pool web site. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. @@ -772,10 +836,7 @@ o POOL-298: Changed default jmxNameBase in BaseObjectPoolConfig to the correct o POOL-300: Added PrintWriter flush to DefaultPooledObject's printStackTrace method. - For complete information on Apache Commons Pool, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons Pool website: https://commons.apache.org/proper/commons-pool/ - - diff --git a/SECURITY.md b/SECURITY.md index 51943ba7b..744d4cddb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,7 @@ (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 + https://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, diff --git a/doc/ReaderUtil.java b/doc/ReaderUtil.java index 0720b9005..0c292a560 100644 --- a/doc/ReaderUtil.java +++ b/doc/ReaderUtil.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -24,7 +24,7 @@ import java.io.IOException; import java.io.Reader; -import org.apache.commons.pool2.ObjectPool; +import org.apache.commons.pool3.ObjectPool; /** * Maintains a pool of StringBuffers used to dump contents of Readers. diff --git a/doc/ReaderUtilClient.java b/doc/ReaderUtilClient.java index c6039e70e..878e19d78 100644 --- a/doc/ReaderUtilClient.java +++ b/doc/ReaderUtilClient.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -25,7 +25,7 @@ import java.io.Reader; import java.io.StringReader; -import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool3.impl.GenericObjectPool; /** * Instantiates and uses a ReaderUtil. The GenericObjectPool supplied to the constructor will have diff --git a/doc/StringBufferFactory.java b/doc/StringBufferFactory.java index 5bcb62f42..b96c862fe 100644 --- a/doc/StringBufferFactory.java +++ b/doc/StringBufferFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -21,9 +21,9 @@ * It is not intended to be included in a source release. */ -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * Example PooledObjectFactory for pooled StringBuffers. diff --git a/pom.xml b/pom.xml index c77bc54d9..cdf63099d 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,4 @@ - + @@ -156,20 +62,13 @@ junit-jupiter test - - org.hamcrest - hamcrest-library - 2.2 - test - org.apache.commons commons-lang3 - 3.12.0 + 3.20.0 test - @@ -178,37 +77,48 @@ scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-pool/ - UTF-8 UTF-8 - 1.8 - 1.8 + + 2024-02-01T03:27:02Z + 17 + 17 + 17 pool - org.apache.commons.pool2 + org.apache.commons.pool3 RC1 + ${basedir}/src/conf/checkstyle-suppressions.xml + + 3.0.0 + (Java 17) - 2.12.0 - (Java 8) + 2.12.0 + (Java 8 or above) - 2.6.2 - (Java 7) - + 2.6.2 + (Java 7 or above) POOL 12310488 site-content net.sf.cglib.proxy;resolution:=optional,* - - - 2.11.1 + + 3.0.0-SNAPSHOT true - Gary Gregory - 86fdc7e2a11262cb - - false + + true false + true + --add-opens java.base/java.lang=ALL-UNNAMED + + true + 0.98 + 0.86 + 0.87 + 0.83 + 0.86 + 0.80 - clean verify apache-rat:check checkstyle:check japicmp:cmp javadoc:javadoc spotbugs:check pmd:check pmd:cpd-check @@ -222,27 +132,15 @@ true - - - org.apache.maven.plugins - maven-project-info-reports-plugin - ${commons.project-info.version} - - - - org.apache.bcel - bcel - 6.7.0 - - - org.apache.maven.plugins maven-checkstyle-plugin ${basedir}/src/conf/checkstyle.xml - false + ${checkstyle.suppress.file} ${basedir}/license-header.txt + false + true @@ -252,6 +150,15 @@ ${basedir}/src/conf/findbugs-exclude-filter.xml + + maven-pmd-plugin + + ${maven.compiler.target} + + ${basedir}/src/conf/pmd-ruleset.xml + + + @@ -259,20 +166,21 @@ org.apache.rat apache-rat-plugin - - src/test/resources/test1 - src/test/resources/test2 - .checkstyle - .fbprefs - .pmd - + + src/test/resources/test1 + src/test/resources/test2 + .checkstyle + .fbprefs + .pmd + org.apache.maven.plugins maven-surefire-plugin - + ${argLine} ${surefire.argline} + 1800 **/Test*.java @@ -284,56 +192,61 @@ + + maven-assembly-plugin + + + src/assembly/bin.xml + src/assembly/src.xml + + gnu + + + + org.apache.maven.plugins + maven-scm-publish-plugin + + + api-* + + + - maven-assembly-plugin + com.github.siom79.japicmp + japicmp-maven-plugin - - src/assembly/bin.xml - src/assembly/src-tar-gz.xml - src/assembly/src-zip.xml - - gnu + + + + METHOD_NEW_DEFAULT + true + true + PATCH + + + org.apache.maven.plugins - maven-scm-publish-plugin + maven-jar-plugin - - api-* - + + + ${commons.module.name} + + - - com.github.siom79.japicmp - japicmp-maven-plugin - - - - - METHOD_NEW_DEFAULT - true - true - PATCH - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - ${commons.module.name} - - - - + + org.apache.maven.plugins + maven-javadoc-plugin + + src/main/java + + - @@ -365,13 +278,13 @@ org.apache.rat apache-rat-plugin - - src/test/resources/test1 - src/test/resources/test2 - .checkstyle - .fbprefs - .pmd - + + src/test/resources/test1 + src/test/resources/test2 + .checkstyle + .fbprefs + .pmd + @@ -406,39 +319,90 @@ - - - java9 - - 9 - + + + + Morgan Delagrange + morgand + + + + + Geir Magnusson + geirm + + + + + Craig McClanahan + craigmcc + + + + + Rodney Waldhoff + rwaldhoff + + + + + David Weinrich + dweinr1 + + + + + Dirk Verbeeck + dirkv + + + + + Robert Burrell Donkin + rdonkin + + The Apache Software Foundation + + + Sandy McArthur + sandymac + + The Apache Software Foundation + + + Simone Tripodi + simonetripodi + The Apache Software Foundation + + + ggregory + Gary Gregory + ggregory at apache.org + https://www.garygregory.com + The Apache Software Foundation + https://www.apache.org/ + + PMC Member + + America/New_York - - true + https://people.apache.org/~ggregory/img/garydgregory80.png - - - java16 - - - [16,) - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - --illegal-access=permit - --add-opens java.base/java.lang=ALL-UNNAMED - - - - - - - - + + + Matt Sicker + mattsicker + The Apache Software Foundation + + + + + Todd Carmichael + toddc@concur.com + + + Arturo Bernal + + diff --git a/pool-RC.sh b/pool-RC.sh index 3b37fbc81..74354d870 100755 --- a/pool-RC.sh +++ b/pool-RC.sh @@ -7,7 +7,7 @@ # (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 +# https://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, @@ -25,8 +25,6 @@ # svn pub/sub dev checkout. # 2) Nexus repo from previous RC has been dropped. # -# $Revision$ $Date$ -# ----------------------------------------------------------------------------- # Set script variables version=2.4.3 repo_path=~/.m2/repository/org/apache/commons/commons-pool2/${version} diff --git a/pool-pre-RC.sh b/pool-pre-RC.sh index 26b68a816..3cfa36859 100755 --- a/pool-pre-RC.sh +++ b/pool-pre-RC.sh @@ -7,7 +7,7 @@ # (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 +# https://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, @@ -23,7 +23,6 @@ # to checkin. Both RELEASE-NOTES.txt and the generated download # page need to be checked in after review. # -# $Revision$ $Date$ # ---------------------------------------------------------------------------- version=2.4.3 mvn changes:announcement-generate -Prelease-notes -Dchanges.version=${version} diff --git a/pool-release.sh b/pool-release.sh index 7ccf1c481..5290630e2 100755 --- a/pool-release.sh +++ b/pool-release.sh @@ -7,7 +7,7 @@ # (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 +# https://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, @@ -28,7 +28,6 @@ # 0) Commit the local changes to actually publish the artifacts # 1) Cleanup old versions in dist # -# $Revision$ $Date$ # ----------------------------------------------------------------------------- # Set script variables version=2.4.3 # version being released diff --git a/src/assembly/bin.xml b/src/assembly/bin.xml index 576229197..1d0d7f420 100644 --- a/src/assembly/bin.xml +++ b/src/assembly/bin.xml @@ -6,7 +6,7 @@ (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 + https://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, @@ -14,31 +14,33 @@ See the License for the specific language governing permissions and limitations under the License. --> - - bin - - tar.gz - zip - - false - - - - LICENSE.txt - NOTICE.txt - RELEASE-NOTES.txt - - - - target - - - *.jar - - - - target/site/apidocs - apidocs - - + + bin + + tar.gz + zip + + false + + + + LICENSE.txt + NOTICE.txt + RELEASE-NOTES.txt + + + + target + + + *.jar + + 644 + + + target/site/apidocs + apidocs + + diff --git a/src/assembly/src-tar-gz.xml b/src/assembly/src-tar-gz.xml deleted file mode 100644 index b2b9bfcdc..000000000 --- a/src/assembly/src-tar-gz.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - src - - tar.gz - - ${project.artifactId}-${project.version}-src - - - - build.xml - checkstyle.xml - LICENSE.txt - license-header.txt - NOTICE.txt - pom.xml - README.txt - RELEASE-NOTES.txt - findbugs-exclude-filter.xml - build.properties.sample - - lf - - - doc - lf - - - src/site/resources - - - src/site/xdoc - lf - - - src/site - - site.xml - - lf - - - src/changes - lf - - - src/main - lf - - - src/test/java - lf - - - src/test/resources - - - - diff --git a/src/assembly/src-zip.xml b/src/assembly/src-zip.xml deleted file mode 100644 index 5fafe189c..000000000 --- a/src/assembly/src-zip.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - src - - zip - - ${project.artifactId}-${project.version}-src - - - - build.xml - checkstyle.xml - LICENSE.txt - license-header.txt - NOTICE.txt - pom.xml - README.txt - RELEASE-NOTES.txt - findbugs-exclude-filter.xml - build.properties.sample - - crlf - - - doc - crlf - - - src/site/resources - - - src/site/xdoc - crlf - - - src/site - - site.xml - - crlf - - - src/changes - crlf - - - src/main - crlf - - - src/test/java - crlf - - - src/test/resources - - - diff --git a/src/assembly/src.xml b/src/assembly/src.xml new file mode 100644 index 000000000..9f9f8df5f --- /dev/null +++ b/src/assembly/src.xml @@ -0,0 +1,46 @@ + + + + src + + tar.gz + zip + + ${artifactId}-${version}-src + + + + BUILDING.txt + CODE_OF_CONDUCT.md + CONTRIBUTING.md + LICENSE.txt + NOTICE.txt + pom.xml + README.md + RELEASE-NOTES.txt + SECURITY.md + + + + src + + + diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 14ed56aa0..89f633895 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -7,7 +7,7 @@ (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 + https://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, @@ -37,15 +37,52 @@ and commit The type attribute can be add,update,fix,remove. --> - - + xsi:schemaLocation="http://maven.apache.org/changes/2.0.0 https://maven.apache.org/xsd/changes-2.0.0.xsd"> Apache Commons Pool Release Notes - + + + Add ReslientPooledObjectFactory to provide resilience against factory outages. + Add an option to JdkProxySource allowing to unwrap UndeclaredThrowableException #261. + Add org.apache.commons.pool3.proxy.CglibProxySource.Builder. + Add org.apache.commons.pool3.proxy.JdkProxySource.Builder. + Add org.apache.commons.pool3.proxy.AbstractProxySource. + Made statistics collection optional in BaseGenericObjectPool #429. + + Remove -nouses directive from maven-bundle-plugin. OSGi package imports now state 'uses' definitions for package imports, this doesn't affect JPMS (from org.apache.commons:commons-parent:80). + Operation on the "idleHighWaterMark" shared variable in "ErodingFactor" class is not atomic [org.apache.commons.pool3.PoolUtils$ErodingFactor] At PoolUtils.java:[line 101] AT_NONATOMIC_OPERATIONS_ON_SHARED_VARIABLE. + org.apache.commons.pool3.impl.GenericObjectPool.create(Duration) duration computation doesn't match 2.x. See also PR #409 from shengulong. + Fix potential ConcurrentModificationException in EvictionTimer thread clean-up. + Fix potential ConcurrentModificationException in EvictionTimer tasks. + Fix Apache RAT plugin console warnings. + + Deprecations from version 2.x have been removed. + + Bump Java from 8 to 17. + Bump org.apache.commons:commons-parent from 58 to 93 #297, #328, #338, #341, #347, #351, #354, #361, #431, #445, #448. + Bump org.ow2.asm:asm-util from 9.5 to 9.7.1 #252, #294, #355. + Bump org.apache.commons:commons-lang3 from 3.13.0 to 3.20.0 #326, #333, #342, #415. + Bump org.apache.bcel:bcel from 6.7.0 to 6.10.0 #263, #306, #327. + + + + Use java.time.Instant precision in org.apache.commons.pool2.impl.ThrowableCallStack.Snapshot throwable message. + GenericObjectPool.borrowObject(Duration) doesn't obey its borrowMaxWait Duration argument when the argument is different from GenericObjectPool.getMaxWaitDuration(). + The maximum wait time for GenericObjectPool.borrowObject(*) may exceed expectations due to a spurious thread wakeup. + Javadoc is missing its Overview page. + Migrate site generation templates to https://maven.apache.org/xsd/xdoc-2.0.xsd. + + + Bump org.apache.commons:commons-parent from 62 to 79. + [test] Bump commons-lang3 from 3.13.0 to 3.19.0. + [site] Pickup org.apache.bcel:bcel version from parent POM. + [test] Bump org.ow2.asm:asm-util from 9.5 to 9.7.1. + + Ensure that capacity freed by invalidateObject is available to all keyed pools. @@ -169,8 +206,11 @@ The type attribute can be add,update,fix,remove. Bump Apache Commons BCEL 6.5.0 to 6.7.0 #194. + + Bump commons-lang3 from 3.12.0 to 3.13.0. + - + Getting a PooledObject's active duration returns a negative duration when the object is borrowed but not returned. Affects: @@ -211,7 +251,7 @@ The type attribute can be add,update,fix,remove. Bump spotbugs from 4.2.3 to 4.3.0 and ignore new medium warnings EI_EXPOSE_REP and EI_EXPOSE_REP2. - + Fix "[WARNING] Old version of checkstyle detected. Consider updating to >= v8.30." Update Checktyle to 8.44. @@ -290,7 +330,7 @@ The type attribute can be add,update,fix,remove. Bump checkstyle from 8.44 to 8.45 #92. - + Add and use java.time.Duration APIs timeouts instead of using ints for seconds. @@ -365,7 +405,7 @@ The type attribute can be add,update,fix,remove. Bump animal-sniffer-maven-plugin from 1.19 to 1.20. - + Object factory destroy method should carry information on activation context. @@ -382,7 +422,7 @@ The type attribute can be add,update,fix,remove. Update optional asm-util from 8.0.1 to 9.0 #44. - + Refactored EvictionTimer usage tracking to fix POOL-386 and handle abandoned pools. #32. @@ -420,7 +460,7 @@ The type attribute can be add,update,fix,remove. Update animal-sniffer-maven-plugin from 1.16 to 1.19. - + GenericKeyedObjectPool.returnObject(K, T) should throw IllegalStateException instead of NullPointerException when a key is not found in the pool map. @@ -455,7 +495,7 @@ The type attribute can be add,update,fix,remove. [Javadoc] Add missing @throws comment in SoftReferenceObjectPool. #28. - + Update from Java 7 to Java 8. @@ -472,18 +512,18 @@ The type attribute can be add,update,fix,remove. Move validation for newly created objects into create(). Fixes #23. - Add org.apache.commons.pool2.PooledObject#getBorrowedCount(). + Add org.apache.commons.pool3.PooledObject#getBorrowedCount(). - Add org.apache.commons.pool2.PooledObject#setRequireFullStackTrace(boolean). + Add org.apache.commons.pool3.PooledObject#setRequireFullStackTrace(boolean). CallStackUtils mishandles security manager check part 1. - + - Always null out org.apache.commons.pool2.impl.BaseGenericObjectPool.evictionIterator to match org.apache.commons.pool2.impl.BaseGenericObjectPool.evictor. + Always null out org.apache.commons.pool3.impl.BaseGenericObjectPool.evictionIterator to match org.apache.commons.pool3.impl.BaseGenericObjectPool.evictor. Evictor Thread prevents Spring Context shutdown in standalone app. @@ -492,7 +532,7 @@ The type attribute can be add,update,fix,remove. The commons-pool-evictor-thread should run as a Deamon. - + Correct validateObject with concurrent borrowObject @@ -524,7 +564,7 @@ The type attribute can be add,update,fix,remove. CallStackUtils mishandles security manager check (partial fix.) - + GenericObjectPool's borrowObject lock if create() fails with Error. @@ -544,13 +584,13 @@ The type attribute can be add,update,fix,remove. GenericObjectPool constructor may throw an exception under OSGi. - org.apache.commons.pool2.impl.GenericObjectPool.getFactoryType() throws java.lang.ClassCastException. + org.apache.commons.pool3.impl.GenericObjectPool.getFactoryType() throws java.lang.ClassCastException. Delete repeated call startEvictor. - + Update from Java 6 to 7. @@ -564,7 +604,7 @@ The type attribute can be add,update,fix,remove. Update optional dependency asm-util from 5.2 to 6.0. - org.apache.commons.pool2.impl.ThrowableCallStack.Snapshot is missing serialVersionUID. + org.apache.commons.pool3.impl.ThrowableCallStack.Snapshot is missing serialVersionUID. Make abandoned logging stack trace requirements configurable. This also reverts @@ -575,7 +615,7 @@ The type attribute can be add,update,fix,remove. the default behavior introduced by POOL-320. - + Documentation with repeated words (sources, tests, and examples). @@ -628,7 +668,7 @@ The type attribute can be add,update,fix,remove. Update optional OW2 ASM from 5.0.4 to 5.2. - + Changed default jmxNameBase in BaseObjectPoolConfig to the correct (null) default. @@ -638,7 +678,7 @@ The type attribute can be add,update,fix,remove. @@ -646,7 +686,7 @@ to version 2.4."> + "This is a maintenance release that includes bug fixes and minor enhancements (Java 6 or above)."> Fixed capacity leak when an object is offered from a GenericKeyedObjectPool while it is being validated by the evictor. @@ -681,7 +721,7 @@ to version 2.4."> +"This is a maintenance release that includes bug fixes and minor enhancements (Java 6 or above)."> Eliminated possibility that DefaultPoolObject#getIdleTimeMillis() could return a negative value. Use by pool implementations would not hit this @@ -752,7 +792,7 @@ to version 2.4."> Ensure that if an attempt is made to return an object multiple times that @@ -770,7 +810,7 @@ and fixes a small number of bugs."> Added missing create counter decrement in GenericKeyedObjectPool create method on factory @@ -806,7 +846,7 @@ including bugfixes and test case improvements."> is prevented after they have been returned to the pool. - + Support Java 1.5 Generics in version 1.x. diff --git a/src/changes/release-notes.vm b/src/changes/release-notes.vm index e4b3356a4..ecc258c88 100644 --- a/src/changes/release-notes.vm +++ b/src/changes/release-notes.vm @@ -6,7 +6,7 @@ ## "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 +## https://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 @@ -14,29 +14,30 @@ ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. - ${project.name} ${version} RELEASE NOTES +${project.name} ${version} Release Notes +------------------------------------------------ The ${developmentTeam} is pleased to announce the release of ${project.name} ${version}. -Apache Commons Pool provides an object-pooling API and a number of object pool implementations. -Version 2 contains a completely re-written pooling implementation compared to the 1.x series. +Apache Commons Pool provides an object-pooling API and several object-pool implementations. +Version 2 contains a completely rewritten pooling implementation compared to the 1.x series. In addition to performance and scalability improvements, version 2 includes robust instance -tracking and pool monitoring. +tracking and pool monitoring. Version 2.7.x and up requires Java 8 or above. Version 2.6.x requires Java 7 or above. Version 2.5.x requires Java 7 or above. Version 2.0 requires 6 or above. -NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean +NOTE: The MBean interfaces (DefaultPooledObjectInfoMBean, GenericKeyedObjectPoolMXBean, and GenericKeyedObjectPoolMXBean) exist only to define the attributes and methods - that will be made available via JMX. They must not be implemented by clients as - they are subject to change between major, minor and patch version releases of - Commons Pool. Clients that implement any of these interfaces may not, therefore, + that will be made available via JMX. Clients must not implement them as + they are subject to change between major, minor, and patch version releases of + Commons Pool. Clients that implement any of these interfaces may not be able to upgrade to a new minor or patch release without requiring code changes. -## N.B. the available variables are described here: +## The available variables are described here: ## http://maven.apache.org/plugins/maven-changes-plugin/examples/using-a-custom-announcement-template.html ## ## Hack to get line breaks to work in release description. For this to work, each line break in the diff --git a/src/conf/checkstyle-suppressions.xml b/src/conf/checkstyle-suppressions.xml new file mode 100644 index 000000000..74924812f --- /dev/null +++ b/src/conf/checkstyle-suppressions.xml @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/src/conf/checkstyle.xml b/src/conf/checkstyle.xml index 3f884e113..36a9d49a9 100644 --- a/src/conf/checkstyle.xml +++ b/src/conf/checkstyle.xml @@ -7,7 +7,7 @@ (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 + https://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, @@ -16,66 +16,84 @@ limitations under the License. --> + "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" + "https://checkstyle.org/dtds/configuration_1_3.dtd"> - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + - - - - - - - - + + + + + + + + + + + + - - - + - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + - - - - - - - + + - - - - - diff --git a/src/conf/findbugs-exclude-filter.xml b/src/conf/findbugs-exclude-filter.xml index 40e75c3f8..a93b46edc 100644 --- a/src/conf/findbugs-exclude-filter.xml +++ b/src/conf/findbugs-exclude-filter.xml @@ -7,7 +7,7 @@ (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 + https://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, @@ -28,14 +28,14 @@ - + - - + + @@ -45,39 +45,39 @@ - + - + - + - + - + - + @@ -89,9 +89,9 @@ - - - + + + @@ -99,24 +99,24 @@ - - + + - + - - - - + + + + @@ -124,79 +124,79 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -206,4 +206,15 @@ + + + + + + + + + + + diff --git a/src/conf/pmd-ruleset.xml b/src/conf/pmd-ruleset.xml new file mode 100644 index 000000000..55d17e2e7 --- /dev/null +++ b/src/conf/pmd-ruleset.xml @@ -0,0 +1,75 @@ + + + + + This ruleset checks the code for discouraged programming constructs. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/apache/commons/pool2/overview.html b/src/main/java/org/apache/commons/pool2/overview.html deleted file mode 100644 index b301d1d64..000000000 --- a/src/main/java/org/apache/commons/pool2/overview.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - Overview of the org.apache.commons.pool2 component - - -

- Generic Object pooling API with several implementations. -

-

- The org.apache.commons.pool2 package defines a simple - interface for a pool of object instances, and a handful of base - classes that may be useful when creating pool implementations. - The API supports pooling of unique objects which can be requested - via a key as well as pools where all objects are equivalent. -

-

- The org.apache.commons.pool2.impl package contains - several pool implementations. - {@link org.apache.commons.pool2.impl.GenericObjectPool - GenericObjectPool} has many configuration options and can support - a limited set of objects such as would be useful in a database - connection pool. - {@link org.apache.commons.pool2.impl.SoftReferenceObjectPool - SoftReferenceObjectPool} has no limit on the number of objects in the - pool, but the garbage collector can remove idle objects from the pool - as needed. There is also a keyed version of - {@link org.apache.commons.pool2.impl.GenericObjectPool - GenericObjectPool}, - {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool - GenericKeyedObjectPool} -

- - \ No newline at end of file diff --git a/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java b/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java deleted file mode 100644 index 56613d99d..000000000 --- a/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java +++ /dev/null @@ -1,78 +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. - */ -package org.apache.commons.pool2.proxy; - -import org.apache.commons.pool2.UsageTracking; - -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.Factory; - -/** - * Provides proxy objects using CGLib. - * - * @param type of the pooled object to be proxied - * - * @since 2.0 - */ -public class CglibProxySource implements ProxySource { - - private final Class superclass; - - /** - * Constructs a new proxy source for the given class. - * - * @param superclass The class to proxy - */ - public CglibProxySource(final Class superclass) { - this.superclass = superclass; - } - - @SuppressWarnings("unchecked") // Case to T on return - @Override - public T createProxy(final T pooledObject, final UsageTracking usageTracking) { - final Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(superclass); - - final CglibProxyHandler proxyInterceptor = - new CglibProxyHandler<>(pooledObject, usageTracking); - enhancer.setCallback(proxyInterceptor); - - return (T) enhancer.create(); - } - - - @Override - public T resolveProxy(final T proxy) { - @SuppressWarnings("unchecked") - final - CglibProxyHandler cglibProxyHandler = - (CglibProxyHandler) ((Factory) proxy).getCallback(0); - return cglibProxyHandler.disableProxy(); - } - - /** - * @since 2.4.3 - */ - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("CglibProxySource [superclass="); - builder.append(superclass); - builder.append("]"); - return builder.toString(); - } -} diff --git a/src/main/java/org/apache/commons/pool2/proxy/JdkProxySource.java b/src/main/java/org/apache/commons/pool2/proxy/JdkProxySource.java deleted file mode 100644 index 32c57ae6c..000000000 --- a/src/main/java/org/apache/commons/pool2/proxy/JdkProxySource.java +++ /dev/null @@ -1,74 +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. - */ -package org.apache.commons.pool2.proxy; - -import java.lang.reflect.Proxy; -import java.util.Arrays; - -import org.apache.commons.pool2.UsageTracking; - -/** - * Provides proxy objects using Java reflection. - * - * @param type of the pooled object to be proxied - * - * @since 2.0 - */ -public class JdkProxySource implements ProxySource { - - private final ClassLoader classLoader; - private final Class[] interfaces; - - /** - * Constructs a new proxy source for the given interfaces. - * - * @param classLoader The class loader with which to create the proxy - * @param interfaces The interfaces to proxy - */ - public JdkProxySource(final ClassLoader classLoader, final Class[] interfaces) { - this.classLoader = classLoader; - // Defensive copy - this.interfaces = Arrays.copyOf(interfaces, interfaces.length); - } - - @SuppressWarnings("unchecked") // Cast to T on return. - @Override - public T createProxy(final T pooledObject, final UsageTracking usageTracking) { - return (T) Proxy.newProxyInstance(classLoader, interfaces, - new JdkProxyHandler<>(pooledObject, usageTracking)); - } - - @SuppressWarnings("unchecked") - @Override - public T resolveProxy(final T proxy) { - return ((JdkProxyHandler) Proxy.getInvocationHandler(proxy)).disableProxy(); - } - - /** - * @since 2.4.3 - */ - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("JdkProxySource [classLoader="); - builder.append(classLoader); - builder.append(", interfaces="); - builder.append(Arrays.toString(interfaces)); - builder.append("]"); - return builder.toString(); - } -} diff --git a/src/main/java/org/apache/commons/pool2/BaseKeyedPooledObjectFactory.java b/src/main/java/org/apache/commons/pool3/BaseKeyedPooledObjectFactory.java similarity index 95% rename from src/main/java/org/apache/commons/pool2/BaseKeyedPooledObjectFactory.java rename to src/main/java/org/apache/commons/pool3/BaseKeyedPooledObjectFactory.java index 7c65822aa..3e651d497 100644 --- a/src/main/java/org/apache/commons/pool2/BaseKeyedPooledObjectFactory.java +++ b/src/main/java/org/apache/commons/pool3/BaseKeyedPooledObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.util.Objects; @@ -28,15 +28,20 @@ *

* * @see KeyedPooledObjectFactory - * * @param The type of keys managed by this factory. * @param Type of element managed by this factory. * @param Type of exception thrown by this factory. - * * @since 2.0 */ public abstract class BaseKeyedPooledObjectFactory extends BaseObject implements KeyedPooledObjectFactory { + /** + * Constructs a new instance. + */ + public BaseKeyedPooledObjectFactory() { + // empty + } + /** * Reinitializes an instance to be returned by the pool. *

@@ -56,7 +61,6 @@ public void activateObject(final K key, final PooledObject p) throws E { * * @param key the key used when constructing the object * @return an instance that can be served by the pool - * * @throws E if there is a problem creating a new instance, * this will be propagated to the code requesting an object. */ diff --git a/src/main/java/org/apache/commons/pool2/BaseObject.java b/src/main/java/org/apache/commons/pool3/BaseObject.java similarity index 89% rename from src/main/java/org/apache/commons/pool2/BaseObject.java rename to src/main/java/org/apache/commons/pool3/BaseObject.java index cc7f37616..18c6b0d4f 100644 --- a/src/main/java/org/apache/commons/pool2/BaseObject.java +++ b/src/main/java/org/apache/commons/pool3/BaseObject.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * A base class for common functionality. @@ -23,6 +23,13 @@ */ public abstract class BaseObject { + /** + * Constructs a new instance. + */ + public BaseObject() { + // empty + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/src/main/java/org/apache/commons/pool2/BaseObjectPool.java b/src/main/java/org/apache/commons/pool3/BaseObjectPool.java similarity index 94% rename from src/main/java/org/apache/commons/pool2/BaseObjectPool.java rename to src/main/java/org/apache/commons/pool3/BaseObjectPool.java index 62b94d4b8..252d51765 100644 --- a/src/main/java/org/apache/commons/pool2/BaseObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/BaseObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * A simple base implementation of {@link ObjectPool}. @@ -26,13 +26,19 @@ * * @param Type of element pooled in this pool. * @param Type of exception thrown by this pool. - * * @since 2.0 */ public abstract class BaseObjectPool extends BaseObject implements ObjectPool { private volatile boolean closed; + /** + * Constructs a new instance. + */ + public BaseObjectPool() { + // empty + } + /** * Not supported in this base implementation. Subclasses should override * this behavior. @@ -50,7 +56,6 @@ public void addObject() throws E, UnsupportedOperationException { * closed. * * @throws IllegalStateException when this pool has been closed. - * * @see #isClosed() */ protected final void assertOpen() throws IllegalStateException { diff --git a/src/main/java/org/apache/commons/pool2/BasePooledObjectFactory.java b/src/main/java/org/apache/commons/pool3/BasePooledObjectFactory.java similarity index 93% rename from src/main/java/org/apache/commons/pool2/BasePooledObjectFactory.java rename to src/main/java/org/apache/commons/pool3/BasePooledObjectFactory.java index 56f21337b..87cfb8e37 100644 --- a/src/main/java/org/apache/commons/pool2/BasePooledObjectFactory.java +++ b/src/main/java/org/apache/commons/pool3/BasePooledObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.util.Objects; @@ -27,14 +27,19 @@ * * @param Type of element managed in this factory. * @param Type of exception thrown in this factory. - * * @see PooledObjectFactory * @see BaseKeyedPooledObjectFactory - * * @since 2.0 */ public abstract class BasePooledObjectFactory extends BaseObject implements PooledObjectFactory { + /** + * Constructs a new instance. + */ + public BasePooledObjectFactory() { + // empty + } + /** * No-op. * @@ -51,7 +56,6 @@ public void activateObject(final PooledObject p) throws E { * invocation.

* * @return an instance to be served by the pool, not null. - * * @throws E if there is a problem creating a new instance, * this will be propagated to the code requesting an object. */ @@ -86,7 +90,6 @@ public void passivateObject(final PooledObject p) throws E { * Always returns {@code true}. * * @param p ignored - * * @return {@code true} */ @Override @@ -99,7 +102,6 @@ public boolean validateObject(final PooledObject p) { * {@link PooledObject}. * * @param obj the instance to wrap, should not be null. - * * @return The provided instance, wrapped by a {@link PooledObject} */ public abstract PooledObject wrap(T obj); diff --git a/src/main/java/org/apache/commons/pool2/DestroyMode.java b/src/main/java/org/apache/commons/pool3/DestroyMode.java similarity index 92% rename from src/main/java/org/apache/commons/pool2/DestroyMode.java rename to src/main/java/org/apache/commons/pool3/DestroyMode.java index ec5b1b07d..555af4a43 100644 --- a/src/main/java/org/apache/commons/pool2/DestroyMode.java +++ b/src/main/java/org/apache/commons/pool3/DestroyMode.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * Destroy context provided to object factories via {@code destroyObject} and {@code invalidateObject} methods. Values diff --git a/src/main/java/org/apache/commons/pool2/KeyedObjectPool.java b/src/main/java/org/apache/commons/pool3/KeyedObjectPool.java similarity index 97% rename from src/main/java/org/apache/commons/pool2/KeyedObjectPool.java rename to src/main/java/org/apache/commons/pool3/KeyedObjectPool.java index 88a4fbc91..ac1c78468 100644 --- a/src/main/java/org/apache/commons/pool2/KeyedObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/KeyedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.io.Closeable; import java.util.Collection; @@ -49,24 +49,22 @@ * } * } *

- * {@link KeyedObjectPool} implementations may choose to store at most + * {@link KeyedObjectPool} implementations may choose to store at most * one instance per key value, or may choose to maintain a pool of instances * for each key (essentially creating a {@link java.util.Map Map} of * {@link ObjectPool pools}). *

*

- * See {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool + * See {@link org.apache.commons.pool3.impl.GenericKeyedObjectPool * GenericKeyedObjectPool} for an implementation. *

* * @param The type of keys maintained by this pool. * @param Type of element pooled in this pool. * @param Type of exception thrown by this pool. - * * @see KeyedPooledObjectFactory * @see ObjectPool - * @see org.apache.commons.pool2.impl.GenericKeyedObjectPool GenericKeyedObjectPool - * + * @see org.apache.commons.pool3.impl.GenericKeyedObjectPool GenericKeyedObjectPool * @since 2.0 */ public interface KeyedObjectPool extends Closeable { @@ -78,7 +76,6 @@ public interface KeyedObjectPool extends Closeable { * "pre-loading" a pool with idle objects (Optional operation). * * @param key the key a new instance should be added to - * * @throws E * when {@link KeyedPooledObjectFactory#makeObject} fails. * @throws IllegalStateException @@ -161,9 +158,7 @@ default void addObjects(final K key, final int count) throws E, IllegalArgumentE *

* * @param key the key used to obtain the object - * * @return an instance from this pool. - * * @throws IllegalStateException * after {@link #close close} has been called on this pool * @throws E @@ -190,7 +185,6 @@ default void addObjects(final K key, final int count) throws E, IllegalArgumentE * the given {@code key} (optional operation). * * @param key the key to clear - * * @throws UnsupportedOperationException when this implementation doesn't * support the operation * @@ -276,7 +270,6 @@ default List getKeys() { * * @param key the key used to obtain the object * @param obj a {@link #borrowObject borrowed} instance to be returned. - * * @throws E if the instance cannot be invalidated */ void invalidateObject(K key, V obj) throws E; @@ -299,7 +292,6 @@ default List getKeys() { * @param key the key used to obtain the object * @param obj a {@link #borrowObject borrowed} instance to be returned. * @param destroyMode destroy activation context provided to the factory - * * @throws E if the instance cannot be invalidated * @since 2.9.0 */ @@ -316,7 +308,6 @@ default void invalidateObject(final K key, final V obj, final DestroyMode destro * * @param key the key used to obtain the object * @param obj a {@link #borrowObject borrowed} instance to be returned. - * * @throws IllegalStateException * if an attempt is made to return an object to the pool that * is in any state other than allocated (i.e. borrowed). diff --git a/src/main/java/org/apache/commons/pool2/KeyedPooledObjectFactory.java b/src/main/java/org/apache/commons/pool3/KeyedPooledObjectFactory.java similarity index 96% rename from src/main/java/org/apache/commons/pool2/KeyedPooledObjectFactory.java rename to src/main/java/org/apache/commons/pool3/KeyedPooledObjectFactory.java index 60afa0aa3..0924d4bcd 100644 --- a/src/main/java/org/apache/commons/pool2/KeyedPooledObjectFactory.java +++ b/src/main/java/org/apache/commons/pool3/KeyedPooledObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * An interface defining life-cycle methods for @@ -62,17 +62,15 @@ * While clients of a {@link KeyedObjectPool} borrow and return instances of * the underlying value type V, the factory methods act on instances of * {@link PooledObject PooledObject<V>}. These are the object wrappers that - * pools use to track and maintain state informations about the objects that + * pools use to track and maintain state information about the objects that * they manage. *

* * @see KeyedObjectPool * @see BaseKeyedPooledObjectFactory - * * @param The type of keys managed by this factory. * @param Type of element managed by this factory. * @param Type of exception thrown by this factory. - * * @since 2.0 */ public interface KeyedPooledObjectFactory { @@ -82,7 +80,6 @@ public interface KeyedPooledObjectFactory { * * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be activated - * * @throws E if there is a problem activating {@code obj}, * this exception may be swallowed by the pool. * @@ -104,7 +101,6 @@ public interface KeyedPooledObjectFactory { * * @param key the key used when selecting the instance * @param p a {@code PooledObject} wrapping the instance to be destroyed - * * @throws E should be avoided as it may be swallowed by * the pool implementation. * @@ -119,7 +115,6 @@ public interface KeyedPooledObjectFactory { * @param key the key used when selecting the instance * @param p a {@code PooledObject} wrapping the instance to be destroyed * @param destroyMode DestroyMode providing context to the factory - * * @throws E should be avoided as it may be swallowed by * the pool implementation. * @@ -138,7 +133,6 @@ default void destroyObject(final K key, final PooledObject p, final DestroyMo * wrap it in a {@link PooledObject} to be managed by the pool. * * @param key the key used when constructing the object - * * @return a {@code PooledObject} wrapping an instance that can * be served by the pool. * @@ -152,7 +146,6 @@ default void destroyObject(final K key, final PooledObject p, final DestroyMo * * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be passivated - * * @throws E if there is a problem passivating {@code obj}, * this exception may be swallowed by the pool. * @@ -165,7 +158,6 @@ default void destroyObject(final K key, final PooledObject p, final DestroyMo * * @param key the key used when selecting the object * @param p a {@code PooledObject} wrapping the instance to be validated - * * @return {@code false} if {@code obj} is not valid and should * be dropped from the pool, {@code true} otherwise. */ diff --git a/src/main/java/org/apache/commons/pool2/ObjectPool.java b/src/main/java/org/apache/commons/pool3/ObjectPool.java similarity index 98% rename from src/main/java/org/apache/commons/pool2/ObjectPool.java rename to src/main/java/org/apache/commons/pool3/ObjectPool.java index 04f8e11d4..e16fcadfd 100644 --- a/src/main/java/org/apache/commons/pool2/ObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/ObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.io.Closeable; import java.util.NoSuchElementException; @@ -51,11 +51,9 @@ * * @param Type of element pooled in this pool. * @param Type of exception thrown by this pool. - * * @see PooledObjectFactory * @see KeyedObjectPool * @see BaseObjectPool - * * @since 2.0 */ public interface ObjectPool extends Closeable { @@ -111,7 +109,6 @@ default void addObjects(final int count) throws E { *

* * @return an instance from this pool. - * * @throws IllegalStateException * after {@link #close close} has been called on this pool. * @throws E @@ -177,7 +174,6 @@ default void addObjects(final int count) throws E { *

* * @param obj a {@link #borrowObject borrowed} instance to be disposed. - * * @throws E if the instance cannot be invalidated */ void invalidateObject(T obj) throws E; @@ -210,7 +206,6 @@ default void invalidateObject(final T obj, final DestroyMode destroyMode) throws * a related method as defined in an implementation or sub-interface. * * @param obj a {@link #borrowObject borrowed} instance to be returned. - * * @throws IllegalStateException * if an attempt is made to return an object to the pool that * is in any state other than allocated (i.e. borrowed). diff --git a/src/main/java/org/apache/commons/pool2/PoolUtils.java b/src/main/java/org/apache/commons/pool3/PoolUtils.java similarity index 91% rename from src/main/java/org/apache/commons/pool2/PoolUtils.java rename to src/main/java/org/apache/commons/pool3/PoolUtils.java index 9c350c310..4222f9028 100644 --- a/src/main/java/org/apache/commons/pool2/PoolUtils.java +++ b/src/main/java/org/apache/commons/pool3/PoolUtils.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.util.Collection; import java.util.Collections; @@ -24,6 +24,7 @@ import java.util.NoSuchElementException; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; @@ -49,6 +50,9 @@ public final class PoolUtils { * frequently. */ private static final class ErodingFactor { + + private static final float MAX_INTERVAL = 15f; + /** Determines frequency of "erosion" events */ private final float factor; @@ -56,7 +60,9 @@ private static final class ErodingFactor { private transient volatile long nextShrinkMillis; /** High water mark - largest numIdle encountered */ - private transient volatile int idleHighWaterMark; + private transient volatile int idleHighWaterMark = 1; + + private final ReentrantLock lock = new ReentrantLock(); /** * Creates a new ErodingFactor with the given erosion factor. @@ -64,10 +70,9 @@ private static final class ErodingFactor { * @param factor * erosion factor */ - public ErodingFactor(final float factor) { + ErodingFactor(final float factor) { this.factor = factor; - nextShrinkMillis = System.currentTimeMillis() + (long) (900000 * factor); // now + 15 min * factor - idleHighWaterMark = 1; + nextShrinkMillis = System.currentTimeMillis() + (long) (90_0000 * factor); // now + 15 min * factor } /** @@ -84,7 +89,7 @@ public long getNextShrink() { */ @Override public String toString() { - return "ErodingFactor{" + "factor=" + factor + + return "ErodingFactor{factor=" + factor + ", idleHighWaterMark=" + idleHighWaterMark + '}'; } @@ -98,11 +103,14 @@ public String toString() { */ public void update(final long nowMillis, final int numIdle) { final int idle = Math.max(0, numIdle); - idleHighWaterMark = Math.max(idle, idleHighWaterMark); - final float maxInterval = 15f; - final float minutes = maxInterval + - (1f - maxInterval) / idleHighWaterMark * idle; - nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor); + lock.lock(); + try { + idleHighWaterMark = Math.max(idle, idleHighWaterMark); + final float minutes = MAX_INTERVAL + (1f - MAX_INTERVAL) / idleHighWaterMark * idle; + nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor); + } finally { + lock.unlock(); + } } } /** @@ -133,11 +141,9 @@ private static class ErodingKeyedObjectPool implement * events * @see #erodingFactor */ - protected ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, - final ErodingFactor erodingFactor) { + ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final ErodingFactor erodingFactor) { if (keyedPool == null) { - throw new IllegalArgumentException( - MSG_NULL_KEYED_POOL); + throw new IllegalArgumentException(MSG_NULL_KEYED_POOL); } this.keyedPool = keyedPool; this.erodingFactor = erodingFactor; @@ -154,8 +160,7 @@ protected ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, * events * @see #erodingFactor */ - public ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, - final float factor) { + ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) { this(keyedPool, new ErodingFactor(factor)); } @@ -319,7 +324,7 @@ public void returnObject(final K key, final V obj) throws E { */ @Override public String toString() { - return "ErodingKeyedObjectPool{" + "factor=" + + return "ErodingKeyedObjectPool{factor=" + erodingFactor + ", keyedPool=" + keyedPool + '}'; } } @@ -332,7 +337,7 @@ public String toString() { * @param type of objects in the pool * @param type of exceptions from the pool */ - private static class ErodingObjectPool implements ObjectPool { + private static final class ErodingObjectPool implements ObjectPool { /** Underlying object pool */ private final ObjectPool pool; @@ -351,7 +356,7 @@ private static class ErodingObjectPool implements Object * events * @see #factor */ - public ErodingObjectPool(final ObjectPool pool, final float factor) { + ErodingObjectPool(final ObjectPool pool, final float factor) { this.pool = pool; this.factor = new ErodingFactor(factor); } @@ -360,7 +365,7 @@ public ErodingObjectPool(final ObjectPool pool, final float factor) { * {@inheritDoc} */ @Override - public void addObject() throws E, IllegalStateException, UnsupportedOperationException{ + public void addObject() throws E, IllegalStateException, UnsupportedOperationException { pool.addObject(); } @@ -462,7 +467,7 @@ public void returnObject(final T obj) { */ @Override public String toString() { - return "ErodingObjectPool{" + "factor=" + factor + ", pool=" + + return "ErodingObjectPool{factor=" + factor + ", pool=" + pool + '}'; } } @@ -492,7 +497,7 @@ private static final class ErodingPerKeyKeyedObjectPool keyedPool, final float factor) { + ErodingPerKeyKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) { super(keyedPool, null); this.factor = factor; } @@ -513,7 +518,7 @@ protected ErodingFactor getErodingFactor(final K key) { @SuppressWarnings("resource") // getKeyedPool(): ivar access @Override public String toString() { - return "ErodingPerKeyKeyedObjectPool{" + "factor=" + factor + + return "ErodingPerKeyKeyedObjectPool{factor=" + factor + ", keyedPool=" + getKeyedPool() + '}'; } } @@ -673,7 +678,7 @@ public String toString() { * A synchronized (thread-safe) KeyedObjectPool backed by the specified * KeyedObjectPool. *

- * Note: This should not be used on pool implementations that already + * Note: This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. Wrapping a pool that {@link #wait() waits} for poolable * objects to be returned before allowing another one to be borrowed with @@ -905,7 +910,7 @@ public String toString() { * KeyedPooledObjectFactory and synchronizes access to the wrapped factory * methods. *

- * Note: This should not be used on pool implementations that already + * Note: This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. *

@@ -1021,7 +1026,7 @@ public boolean validateObject(final K key, final PooledObject p) { * A synchronized (thread-safe) ObjectPool backed by the specified * ObjectPool. *

- * Note: This should not be used on pool implementations that already + * Note: This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. Wrapping a pool that {@link #wait() waits} for poolable * objects to be returned before allowing another one to be borrowed with @@ -1040,7 +1045,7 @@ private static final class SynchronizedObjectPool implem */ private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - /** the underlying object pool */ + /** The underlying object pool */ private final ObjectPool pool; /** @@ -1196,7 +1201,7 @@ public String toString() { * PooledObjectFactory and synchronizes access to the wrapped factory * methods. *

- * Note: This should not be used on pool implementations that already + * Note: This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. *

@@ -1655,93 +1660,6 @@ private static Timer getMinIdleTimer() { return TimerHolder.MIN_IDLE_TIMER; } - /** - * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with - * each key in {@code keys} for {@code count} number of times. This has - * the same effect as calling {@link #prefill(KeyedObjectPool, Object, int)} - * for each key in the {@code keys} collection. - * - * @param keyedPool - * the keyedPool to prefill. - * @param keys - * {@link Collection} of keys to add objects for. - * @param count - * the number of idle objects to add for each {@code key}. - * @param the type of the pool key - * @param the type of pool entries - * @param the type of exception thrown by a pool - * @throws E - * when {@link KeyedObjectPool#addObject(Object)} fails. - * @throws IllegalArgumentException - * when {@code keyedPool}, {@code keys}, or any value in - * {@code keys} is {@code null}. - * @see #prefill(KeyedObjectPool, Object, int) - * @deprecated Use {@link KeyedObjectPool#addObjects(Collection, int)}. - */ - @Deprecated - public static void prefill(final KeyedObjectPool keyedPool, - final Collection keys, final int count) throws E, - IllegalArgumentException { - if (keys == null) { - throw new IllegalArgumentException(MSG_NULL_KEYS); - } - keyedPool.addObjects(keys, count); - } - - /** - * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with - * {@code key} {@code count} number of times. - * - * @param keyedPool - * the keyedPool to prefill. - * @param key - * the key to add objects for. - * @param count - * the number of idle objects to add for {@code key}. - * @param the type of the pool key - * @param the type of pool entries - * @param the type of exception thrown by a pool - * @throws E - * when {@link KeyedObjectPool#addObject(Object)} fails. - * @throws IllegalArgumentException - * when {@code keyedPool} or {@code key} is {@code null}. - * @deprecated Use {@link KeyedObjectPool#addObjects(Object, int)}. - */ - @Deprecated - public static void prefill(final KeyedObjectPool keyedPool, - final K key, final int count) throws E, - IllegalArgumentException { - if (keyedPool == null) { - throw new IllegalArgumentException(MSG_NULL_KEYED_POOL); - } - keyedPool.addObjects(key, count); - } - - /** - * Calls {@link ObjectPool#addObject()} on {@code pool} {@code count} number - * of times. - * - * @param pool - * the pool to prefill. - * @param count - * the number of idle objects to add. - * @param the type of objects in the pool - * @param type of exceptions from the pool - * @throws E - * when {@link ObjectPool#addObject()} fails. - * @throws IllegalArgumentException - * when {@code pool} is {@code null}. - * @deprecated Use {@link ObjectPool#addObjects(int)}. - */ - @Deprecated - public static void prefill(final ObjectPool pool, final int count) - throws E, IllegalArgumentException { - if (pool == null) { - throw new IllegalArgumentException(MSG_NULL_POOL); - } - pool.addObjects(count); - } - /** * Returns a synchronized (thread-safe) KeyedPooledObjectFactory backed by * the specified KeyedPooledObjectFactory. @@ -1763,7 +1681,7 @@ public static KeyedPooledObjectFactory sync * Returns a synchronized (thread-safe) KeyedObjectPool backed by the * specified KeyedObjectPool. *

- * Note: This should not be used on pool implementations that already + * Note: This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. Wrapping a pool that {@link #wait() waits} for poolable * objects to be returned before allowing another one to be borrowed with @@ -1796,7 +1714,7 @@ public static KeyedObjectPool synchronizedP * Returns a synchronized (thread-safe) ObjectPool backed by the specified * ObjectPool. *

- * Note: This should not be used on pool implementations that already + * Note: This should not be used on pool implementations that already * provide proper synchronization such as the pools provided in the Commons * Pool library. Wrapping a pool that {@link #wait() waits} for poolable * objects to be returned before allowing another one to be borrowed with diff --git a/src/main/java/org/apache/commons/pool2/PooledObject.java b/src/main/java/org/apache/commons/pool3/PooledObject.java similarity index 66% rename from src/main/java/org/apache/commons/pool2/PooledObject.java rename to src/main/java/org/apache/commons/pool3/PooledObject.java index dc76b46ef..43dc282ea 100644 --- a/src/main/java/org/apache/commons/pool2/PooledObject.java +++ b/src/main/java/org/apache/commons/pool3/PooledObject.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.io.PrintWriter; import java.time.Duration; @@ -34,14 +34,37 @@ public interface PooledObject extends Comparable> { /** - * Tests whether the given PooledObject is null or contains a null. + * Gets the wrapped object or null. * - * @param pooledObject the PooledObject to test. - * @return whether the given PooledObject is null or contains a null. + * @param the type of object in the pool. + * @param pooledObject the PooledObject to unwrap, may be null. + * @return the wrapped object or null. + * @since 2.13.0 + */ + static T getObject(final PooledObject pooledObject) { + return pooledObject != null ? pooledObject.getObject() : null; + } + + /** + * Tests whether the given PooledObject is null or wraps a null. + * + * @param pooledObject the PooledObject to test, may be null. + * @return whether the given PooledObject is null or wraps a null. * @since 2.12.0 */ static boolean isNull(final PooledObject pooledObject) { - return pooledObject == null || pooledObject.getObject() == null; + return getObject(pooledObject) == null; + } + + /** + * Tests whether the given PooledObject isn't null and doesn't wraps a null. + * + * @param pooledObject the PooledObject to test, may be null. + * @return whether the given PooledObject isn't null and doesn't wraps a null. + * @since 2.13.0 + */ + static boolean nonNull(final PooledObject pooledObject) { + return getObject(pooledObject) != null; } /** @@ -103,30 +126,6 @@ default Duration getActiveDuration() { // @formatter:on } - /** - * Gets the amount of time this object last spent in the active state (it may still be active in which case - * subsequent calls will return an increased value). - * - * @return The duration last spent in the active state. - * @since 2.10.0 - * @deprecated Use {@link #getActiveDuration()}. - */ - @Deprecated - default Duration getActiveTime() { - return getActiveDuration(); - } - - /** - * Gets the amount of time in milliseconds this object last spent in the - * active state (it may still be active in which case subsequent calls will - * return an increased value). - * - * @return The time in milliseconds last spent in the active state. - * @deprecated Use {@link #getActiveTime()} which offers the best precision. - */ - @Deprecated - long getActiveTimeMillis(); - /** * Gets the number of times this object has been borrowed. * @@ -143,19 +142,7 @@ default long getBorrowedCount() { * @return The creation time for the wrapped object. * @since 2.11.0 */ - default Instant getCreateInstant() { - return Instant.ofEpochMilli(getCreateTime()); - } - - /** - * Gets the time (using the same basis as - * {@link java.time.Clock#instant()}) that this object was created. - * - * @return The creation time for the wrapped object. - * @deprecated Use {@link #getCreateInstant()} which offers the best precision. - */ - @Deprecated - long getCreateTime(); + Instant getCreateInstant(); /** * Gets the duration since this object was created (using {@link Instant#now()}). @@ -175,34 +162,7 @@ default Duration getFullDuration() { * @return The amount of time in last spent in the idle state. * @since 2.11.0 */ - default Duration getIdleDuration() { - return Duration.ofMillis(getIdleTimeMillis()); - } - - /** - * Gets the amount of time that this object last spend in the - * idle state (it may still be idle in which case subsequent calls will - * return an increased value). - * - * @return The amount of time in last spent in the idle state. - * @since 2.10.0 - * @deprecated Use {@link #getIdleDuration()}. - */ - @Deprecated - default Duration getIdleTime() { - return Duration.ofMillis(getIdleTimeMillis()); - } - - /** - * Gets the amount of time in milliseconds that this object last spend in the - * idle state (it may still be idle in which case subsequent calls will - * return an increased value). - * - * @return The time in milliseconds last spent in the idle state. - * @deprecated Use {@link #getIdleTime()} which offers the best precision. - */ - @Deprecated - long getIdleTimeMillis(); + Duration getIdleDuration(); /** * Gets the time the wrapped object was last borrowed. @@ -210,18 +170,7 @@ default Duration getIdleTime() { * @return The time the object was last borrowed. * @since 2.11.0 */ - default Instant getLastBorrowInstant() { - return Instant.ofEpochMilli(getLastBorrowTime()); - } - - /** - * Gets the time the wrapped object was last borrowed. - * - * @return The time the object was last borrowed. - * @deprecated Use {@link #getLastBorrowInstant()} which offers the best precision. - */ - @Deprecated - long getLastBorrowTime(); + Instant getLastBorrowInstant(); /** * Gets the time the wrapped object was last borrowed. @@ -229,43 +178,17 @@ default Instant getLastBorrowInstant() { * @return The time the object was last borrowed. * @since 2.11.0 */ - default Instant getLastReturnInstant() { - return Instant.ofEpochMilli(getLastReturnTime()); - } - - /** - * Gets the time the wrapped object was last returned. - * - * @return The time the object was last returned. - * @deprecated Use {@link #getLastReturnInstant()} which offers the best precision. - */ - @Deprecated - long getLastReturnTime(); + Instant getLastReturnInstant(); /** * Gets an estimate of the last time this object was used. If the class of the pooled object implements * {@link TrackedUse}, what is returned is the maximum of {@link TrackedUse#getLastUsedInstant()} and - * {@link #getLastBorrowTime()}; otherwise this method gives the same value as {@link #getLastBorrowTime()}. + * {@link #getLastBorrowInstant()}; otherwise this method gives the same value as {@link #getLastBorrowInstant()}. * * @return the last time this object was used * @since 2.11.0 */ - default Instant getLastUsedInstant() { - return Instant.ofEpochMilli(getLastUsedTime()); - } - - /** - * Gets an estimate of the last time this object was used. If the class - * of the pooled object implements {@link TrackedUse}, what is returned is - * the maximum of {@link TrackedUse#getLastUsedInstant()} and - * {@link #getLastBorrowTime()}; otherwise this method gives the same - * value as {@link #getLastBorrowTime()}. - * - * @return the last time this object was used. - * @deprecated Use {@link #getLastUsedInstant()} which offers the best precision. - */ - @Deprecated - long getLastUsedTime(); + Instant getLastUsedInstant(); /** * Gets the underlying object that is wrapped by this instance of diff --git a/src/main/java/org/apache/commons/pool2/PooledObjectFactory.java b/src/main/java/org/apache/commons/pool3/PooledObjectFactory.java similarity index 97% rename from src/main/java/org/apache/commons/pool2/PooledObjectFactory.java rename to src/main/java/org/apache/commons/pool3/PooledObjectFactory.java index c9c97837b..390f6b57a 100644 --- a/src/main/java/org/apache/commons/pool2/PooledObjectFactory.java +++ b/src/main/java/org/apache/commons/pool3/PooledObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * An interface defining life-cycle methods for instances to be served by an @@ -66,9 +66,7 @@ * * @param Type of element managed in this factory. * @param Type of exception thrown in this factory. - * * @see ObjectPool - * * @since 2.0 */ public interface PooledObjectFactory { @@ -77,7 +75,6 @@ public interface PooledObjectFactory { * Reinitializes an instance to be returned by the pool. * * @param p a {@code PooledObject} wrapping the instance to be activated - * * @throws E if there is a problem activating {@code obj}, * this exception may be swallowed by the pool. * @@ -99,7 +96,6 @@ public interface PooledObjectFactory { *

* * @param p a {@code PooledObject} wrapping the instance to be destroyed - * * @throws E should be avoided as it may be swallowed by * the pool implementation. * @@ -114,7 +110,6 @@ public interface PooledObjectFactory { * * @param p a {@code PooledObject} wrapping the instance to be destroyed * @param destroyMode DestroyMode providing context to the factory - * * @throws E should be avoided as it may be swallowed by * the pool implementation. * @@ -133,7 +128,6 @@ default void destroyObject(final PooledObject p, final DestroyMode destroyMod * {@link PooledObject} to be managed by the pool. * * @return a {@code PooledObject} wrapping an instance that can be served by the pool, not null. - * * @throws E if there is a problem creating a new instance, * this will be propagated to the code requesting an object. */ @@ -143,7 +137,6 @@ default void destroyObject(final PooledObject p, final DestroyMode destroyMod * Uninitializes an instance to be returned to the idle object pool. * * @param p a {@code PooledObject} wrapping the instance to be passivated - * * @throws E if there is a problem passivating {@code obj}, * this exception may be swallowed by the pool. * @@ -155,7 +148,6 @@ default void destroyObject(final PooledObject p, final DestroyMode destroyMod * Ensures that the instance is safe to be returned by the pool. * * @param p a {@code PooledObject} wrapping the instance to be validated - * * @return {@code false} if {@code obj} is not valid and should * be dropped from the pool, {@code true} otherwise. */ diff --git a/src/main/java/org/apache/commons/pool2/PooledObjectState.java b/src/main/java/org/apache/commons/pool3/PooledObjectState.java similarity index 96% rename from src/main/java/org/apache/commons/pool2/PooledObjectState.java rename to src/main/java/org/apache/commons/pool3/PooledObjectState.java index f09dbb8a6..6094fdb20 100644 --- a/src/main/java/org/apache/commons/pool2/PooledObjectState.java +++ b/src/main/java/org/apache/commons/pool3/PooledObjectState.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * Provides all possible states of a {@link PooledObject}. diff --git a/src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java b/src/main/java/org/apache/commons/pool3/SwallowedExceptionListener.java similarity index 93% rename from src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java rename to src/main/java/org/apache/commons/pool3/SwallowedExceptionListener.java index 69df39676..808fd2e7c 100644 --- a/src/main/java/org/apache/commons/pool2/SwallowedExceptionListener.java +++ b/src/main/java/org/apache/commons/pool3/SwallowedExceptionListener.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * Pools that unavoidably swallow exceptions may be configured with an instance diff --git a/src/main/java/org/apache/commons/pool2/TrackedUse.java b/src/main/java/org/apache/commons/pool3/TrackedUse.java similarity index 76% rename from src/main/java/org/apache/commons/pool2/TrackedUse.java rename to src/main/java/org/apache/commons/pool3/TrackedUse.java index 0e7806a55..5e70b0475 100644 --- a/src/main/java/org/apache/commons/pool2/TrackedUse.java +++ b/src/main/java/org/apache/commons/pool3/TrackedUse.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.time.Instant; @@ -27,15 +27,6 @@ */ public interface TrackedUse { - /** - * Gets the last time this object was used in milliseconds. - * - * @return the last time this object was used in milliseconds. - * @deprecated Use {@link #getLastUsedInstant()} which offers the best precision. - */ - @Deprecated - long getLastUsed(); - /** * Gets the last Instant this object was used. *

@@ -46,7 +37,5 @@ public interface TrackedUse { * @return the last Instant this object was used. * @since 2.11.0 */ - default Instant getLastUsedInstant() { - return Instant.ofEpochMilli(getLastUsed()); - } + Instant getLastUsedInstant(); } diff --git a/src/main/java/org/apache/commons/pool2/UsageTracking.java b/src/main/java/org/apache/commons/pool3/UsageTracking.java similarity index 94% rename from src/main/java/org/apache/commons/pool2/UsageTracking.java rename to src/main/java/org/apache/commons/pool3/UsageTracking.java index 48bdb2f56..3a5a75a9b 100644 --- a/src/main/java/org/apache/commons/pool2/UsageTracking.java +++ b/src/main/java/org/apache/commons/pool3/UsageTracking.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * This interface may be implemented by an object pool to enable clients (primarily those clients that wrap pools to @@ -22,7 +22,6 @@ * more informed decisions and reporting to be made regarding abandoned objects. * * @param The type of object provided by the pool. - * * @since 2.0 */ public interface UsageTracking { diff --git a/src/main/java/org/apache/commons/pool3/doc-files/leaf.svg b/src/main/java/org/apache/commons/pool3/doc-files/leaf.svg new file mode 100644 index 000000000..71de588c6 --- /dev/null +++ b/src/main/java/org/apache/commons/pool3/doc-files/leaf.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/apache/commons/pool3/doc-files/logo.png b/src/main/java/org/apache/commons/pool3/doc-files/logo.png new file mode 100644 index 000000000..f1b03aff2 Binary files /dev/null and b/src/main/java/org/apache/commons/pool3/doc-files/logo.png differ diff --git a/src/main/java/org/apache/commons/pool2/impl/AbandonedConfig.java b/src/main/java/org/apache/commons/pool3/impl/AbandonedConfig.java similarity index 88% rename from src/main/java/org/apache/commons/pool2/impl/AbandonedConfig.java rename to src/main/java/org/apache/commons/pool3/impl/AbandonedConfig.java index 5b86a151e..b03f12c8c 100644 --- a/src/main/java/org/apache/commons/pool2/impl/AbandonedConfig.java +++ b/src/main/java/org/apache/commons/pool3/impl/AbandonedConfig.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,15 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.Charset; import java.time.Duration; -import org.apache.commons.pool2.TrackedUse; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.TrackedUse; +import org.apache.commons.pool3.UsageTracking; /** * Configuration settings for abandoned object removal. @@ -124,7 +124,6 @@ private AbandonedConfig(final AbandonedConfig abandonedConfig) { * * @return boolean true if stack trace logging is turned on for abandoned * objects - * */ public boolean getLogAbandoned() { return this.logAbandoned; @@ -176,23 +175,6 @@ public boolean getRemoveAbandonedOnMaintenance() { return this.removeAbandonedOnMaintenance; } - /** - *

Timeout in seconds before an abandoned object can be removed.

- * - *

The time of most recent use of an object is the maximum (latest) of - * {@link TrackedUse#getLastUsedInstant()} (if this class of the object implements - * TrackedUse) and the time when the object was borrowed from the pool.

- * - *

The default value is 300 seconds.

- * - * @return the abandoned object timeout in seconds. - * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}. - */ - @Deprecated - public int getRemoveAbandonedTimeout() { - return (int) this.removeAbandonedTimeoutDuration.getSeconds(); - } - /** *

Timeout before an abandoned object can be removed.

* @@ -241,7 +223,6 @@ public boolean getUseUsageTracking() { * * @param logAbandoned true turns on abandoned stack trace logging * @see #getLogAbandoned() - * */ public void setLogAbandoned(final boolean logAbandoned) { this.logAbandoned = logAbandoned; @@ -298,24 +279,6 @@ public void setRemoveAbandonedTimeout(final Duration removeAbandonedTimeout) { this.removeAbandonedTimeoutDuration = PoolImplUtils.nonNull(removeAbandonedTimeout, DEFAULT_REMOVE_ABANDONED_TIMEOUT_DURATION); } - /** - * Sets the timeout in seconds before an abandoned object can be - * removed. - * - *

Setting this property has no effect if - * {@link #getRemoveAbandonedOnBorrow() removeAbandonedOnBorrow} and - * {@link #getRemoveAbandonedOnMaintenance() removeAbandonedOnMaintenance} - * are both false.

- * - * @param removeAbandonedTimeoutSeconds new abandoned timeout in seconds - * @see #getRemoveAbandonedTimeoutDuration() - * @deprecated Use {@link #setRemoveAbandonedTimeout(Duration)}. - */ - @Deprecated - public void setRemoveAbandonedTimeout(final int removeAbandonedTimeoutSeconds) { - setRemoveAbandonedTimeout(Duration.ofSeconds(removeAbandonedTimeoutSeconds)); - } - /** * Sets the flag to require full stack traces for logging abandoned connections when enabled. * diff --git a/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java b/src/main/java/org/apache/commons/pool3/impl/BaseGenericObjectPool.java similarity index 81% rename from src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java rename to src/main/java/org/apache/commons/pool3/impl/BaseGenericObjectPool.java index 6b7612440..e128d52a1 100644 --- a/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/impl/BaseGenericObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.PrintWriter; import java.io.StringWriter; @@ -44,10 +44,10 @@ import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; -import org.apache.commons.pool2.BaseObject; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectState; -import org.apache.commons.pool2.SwallowedExceptionListener; +import org.apache.commons.pool3.BaseObject; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectState; +import org.apache.commons.pool3.SwallowedExceptionListener; /** * Base class that provides common functionality for {@link GenericObjectPool} @@ -66,7 +66,7 @@ public abstract class BaseGenericObjectPool extends Base /** * The idle object eviction iterator. Holds a reference to the idle objects. */ - class EvictionIterator implements Iterator> { + final class EvictionIterator implements Iterator> { private final Deque> idleObjects; private final Iterator> idleObjectIterator; @@ -118,7 +118,7 @@ public void remove() { * * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis */ - class Evictor implements Runnable { + final class Evictor implements Runnable { private ScheduledFuture scheduledFuture; @@ -203,18 +203,30 @@ public String toString() { * objects under management using maps keyed on the objects. This wrapper * class ensures that objects can work as hash keys. * - * @param type of objects in the pool + * @param type of objects in the pool. */ static class IdentityWrapper { + + /** + * Constructs a wrapper for the object in the {@link PooledObject}. + * + * @param type of objects in the {@link PooledObject}. + * @param pooledObject contains the object to wrap. + * @return a new instance wrapping the object in the {@link PooledObject}. + */ + static IdentityWrapper unwrap(final PooledObject pooledObject) { + return new IdentityWrapper<>(pooledObject.getObject()); + } + /** Wrapped object */ private final T instance; /** * Constructs a wrapper for an instance. * - * @param instance object to wrap + * @param instance object to wrap. */ - public IdentityWrapper(final T instance) { + IdentityWrapper(final T instance) { this.instance = instance; } @@ -250,7 +262,7 @@ public String toString() { * Maintains a cache of values for a single metric and reports * statistics on the cached values. */ - private static class StatsStore { + private static final class StatsStore { private static final int NULL = -1; private final AtomicLong[] values; @@ -286,15 +298,6 @@ synchronized void add(final long value) { } } - /** - * Gets the current values as a List. - * - * @return the current values as a List. - */ - synchronized List getCurrentValues() { - return Arrays.stream(values, 0, index).collect(Collectors.toList()); - } - /** * Gets the mean of the cached values. * @@ -313,12 +316,30 @@ public long getMean() { return (long) result; } + /** + * Gets the mean Duration of the cached values. + * + * @return the mean Duration of the cache, truncated to long milliseconds of a Duration. + */ + Duration getMeanDuration() { + return Duration.ofMillis(getMean()); + } + + /** + * Gets the current values as a List. + * + * @return the current values as a List. + */ + synchronized List getValues() { + return Arrays.stream(values, 0, index).collect(Collectors.toList()); + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append("StatsStore ["); // Only append what's been filled in. - builder.append(getCurrentValues()); + builder.append(getValues()); builder.append("], size="); builder.append(size); builder.append(", index="); @@ -347,7 +368,7 @@ public String toString() { private volatile boolean testOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW; private volatile boolean testOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN; private volatile boolean testWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE; - private volatile Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS; + private volatile Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS; private volatile int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; private volatile Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION; @@ -387,6 +408,7 @@ public String toString() { private volatile SwallowedExceptionListener swallowedExceptionListener; private volatile boolean messageStatistics; + private volatile boolean collectDetailedStatistics = BaseObjectPoolConfig.DEFAULT_COLLECT_DETAILED_STATISTICS; /** Additional configuration properties for abandoned object tracking. */ protected volatile AbandonedConfig abandonedConfig; @@ -582,9 +604,8 @@ public final long getDestroyedCount() { * object evictor thread. When non-positive, no idle object evictor thread * will be run. * - * @return number of milliseconds to sleep between evictor runs - * - * @see #setTimeBetweenEvictionRuns + * @return duration to sleep between evictor runs + * @see #setDurationBetweenEvictionRuns(Duration) * @since 2.11.0 */ public final Duration getDurationBetweenEvictionRuns() { @@ -607,28 +628,12 @@ public EvictionPolicy getEvictionPolicy() { * used by this pool. * * @return The fully qualified class name of the {@link EvictionPolicy} - * * @see #setEvictionPolicyClassName(String) */ public final String getEvictionPolicyClassName() { return evictionPolicy.getClass().getName(); } - /** - * Gets the timeout that will be used when waiting for the Evictor to - * shutdown if this pool is closed and it is the only pool still using the - * the value for the Evictor. - * - * @return The timeout that will be used while waiting for - * the Evictor to shut down. - * @since 2.10.0 - * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}. - */ - @Deprecated - public final Duration getEvictorShutdownTimeout() { - return evictorShutdownTimeoutDuration; - } - /** * Gets the timeout that will be used when waiting for the Evictor to * shutdown if this pool is closed and it is the only pool still using the @@ -642,20 +647,6 @@ public final Duration getEvictorShutdownTimeoutDuration() { return evictorShutdownTimeoutDuration; } - /** - * Gets the timeout that will be used when waiting for the Evictor to - * shutdown if this pool is closed and it is the only pool still using the - * the value for the Evictor. - * - * @return The timeout in milliseconds that will be used while waiting for - * the Evictor to shut down. - * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}. - */ - @Deprecated - public final long getEvictorShutdownTimeoutMillis() { - return evictorShutdownTimeoutDuration.toMillis(); - } - /** * Gets whether or not the pool serves threads waiting to borrow objects fairly. * True means that waiting threads are served as if waiting in a FIFO queue. @@ -757,7 +748,6 @@ public final Duration getMaxWaitDuration() { * * @return the maximum number of milliseconds {@code borrowObject()} * will block. - * * @see #setMaxWait * @see #setBlockWhenExhausted * @deprecated Use {@link #getMaxWaitDuration()}. @@ -767,6 +757,16 @@ public final long getMaxWaitMillis() { return maxWaitDuration.toMillis(); } + /** + * Gets the mean time objects are active for based on the last {@link + * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool. + * @return mean time an object has been checked out from the pool among + * recently returned objects + */ + public final Duration getMeanActiveDuration() { + return activeTimes.getMeanDuration(); + } + /** * Gets the mean time objects are active for based on the last {@link * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool. @@ -777,6 +777,18 @@ public final long getMeanActiveTimeMillis() { return activeTimes.getMean(); } + /** + * Gets the mean time threads wait to borrow an object based on the last {@link + * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool. + * + * @return mean time in milliseconds that a recently served thread has had + * to wait to borrow an object from the pool. + * @since 2.12.0 + */ + public final Duration getMeanBorrowWaitDuration() { + return waitTimes.getMeanDuration(); + } + /** * Gets the mean time threads wait to borrow an object based on the last {@link * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool. @@ -793,6 +805,19 @@ public final long getMeanBorrowWaitTimeMillis() { * @return mean time an object has been idle in the pool among recently * borrowed objects */ + public final Duration getMeanIdleDuration() { + return idleTimes.getMeanDuration(); + } + + /** + * Gets the mean time objects are idle for based on the last {@link + * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool. + * + * @return mean time an object has been idle in the pool among recently + * borrowed objects. + * @deprecated Use {@link #getMeanIdleDuration()}. + */ + @Deprecated public final long getMeanIdleTimeMillis() { return idleTimes.getMean(); } @@ -812,52 +837,47 @@ public boolean getMessageStatistics() { } /** - * Gets the minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive, - * no objects will be evicted from the pool due to idle time alone. - * - * @return minimum amount of time an object may sit idle in the pool before - * it is eligible for eviction + * Gets whether detailed timing statistics collection is enabled. + * When {@code false}, the pool will not collect detailed timing statistics for + * mean active time, mean idle time, and mean borrow wait time, + * improving performance under high load. * - * @see #setMinEvictableIdleTimeMillis - * @see #setTimeBetweenEvictionRunsMillis - * @since 2.11.0 + * @return {@code true} if detailed statistics collection is enabled, + * {@code false} if disabled for improved performance. + * @since 2.13.0 */ - public final Duration getMinEvictableIdleDuration() { - return minEvictableIdleDuration; + public boolean getCollectDetailedStatistics() { + return collectDetailedStatistics; } /** * Gets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive, + * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive, * no objects will be evicted from the pool due to idle time alone. * * @return minimum amount of time an object may sit idle in the pool before * it is eligible for eviction * - * @see #setMinEvictableIdleTimeMillis - * @see #setTimeBetweenEvictionRunsMillis - * @since 2.10.0 - * @deprecated Use {@link #getMinEvictableIdleDuration()}. + * @see #setMinEvictableIdleDuration(Duration) + * @see #setDurationBetweenEvictionRuns(Duration) + * @since 2.11.0 */ - @Deprecated - public final Duration getMinEvictableIdleTime() { + public final Duration getMinEvictableIdleDuration() { return minEvictableIdleDuration; } /** * Gets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive, + * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive, * no objects will be evicted from the pool due to idle time alone. * * @return minimum amount of time an object may sit idle in the pool before * it is eligible for eviction * - * @see #setMinEvictableIdleTimeMillis - * @see #setTimeBetweenEvictionRunsMillis + * @see #setMinEvictableIdleDuration(Duration) + * @see #setDurationBetweenEvictionRuns(Duration) * @deprecated Use {@link #getMinEvictableIdleDuration()}. */ @Deprecated @@ -882,9 +902,8 @@ public final long getMinEvictableIdleTimeMillis() { * tested per run. * * @return max number of objects to examine during each evictor run - * * @see #setNumTestsPerEvictionRun - * @see #setTimeBetweenEvictionRunsMillis + * @see #setDurationBetweenEvictionRuns(Duration) */ public final int getNumTestsPerEvictionRun() { return numTestsPerEvictionRun; @@ -964,66 +983,23 @@ public final long getReturnedCount() { /** * Gets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRuns(Duration)}), + * see {@link #setDurationBetweenEvictionRuns(Duration)}), * with the extra condition that at least {@code minIdle} object * instances remain in the pool. This setting is overridden by - * {@link #getMinEvictableIdleTime} (that is, if - * {@link #getMinEvictableIdleTime} is positive, then - * {@link #getSoftMinEvictableIdleTime} is ignored). + * {@link #getMinEvictableIdleDuration} (that is, if + * {@link #getMinEvictableIdleDuration} is positive, then + * {@link #getSoftMinEvictableIdleDuration()} is ignored). * * @return minimum amount of time an object may sit idle in the pool before * it is eligible for eviction if minIdle instances are available * - * @see #setSoftMinEvictableIdle(Duration) + * @see #setSoftMinEvictableIdleDuration(Duration) * @since 2.11.0 */ public final Duration getSoftMinEvictableIdleDuration() { return softMinEvictableIdleDuration; } - /** - * Gets the minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRuns(Duration)}), - * with the extra condition that at least {@code minIdle} object - * instances remain in the pool. This setting is overridden by - * {@link #getMinEvictableIdleTime} (that is, if - * {@link #getMinEvictableIdleTime} is positive, then - * {@link #getSoftMinEvictableIdleTime} is ignored). - * - * @return minimum amount of time an object may sit idle in the pool before - * it is eligible for eviction if minIdle instances are available - * - * @see #setSoftMinEvictableIdle(Duration) - * @since 2.10.0 - * @deprecated Use {@link #getSoftMinEvictableIdleDuration}. - */ - @Deprecated - public final Duration getSoftMinEvictableIdleTime() { - return softMinEvictableIdleDuration; - } - - /** - * Gets the minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRunsMillis(long)}), - * with the extra condition that at least {@code minIdle} object - * instances remain in the pool. This setting is overridden by - * {@link #getMinEvictableIdleTimeMillis} (that is, if - * {@link #getMinEvictableIdleTimeMillis} is positive, then - * {@link #getSoftMinEvictableIdleTimeMillis} is ignored). - * - * @return minimum amount of time an object may sit idle in the pool before - * it is eligible for eviction if minIdle instances are available - * - * @see #setSoftMinEvictableIdleTimeMillis - * @deprecated Use {@link #getSoftMinEvictableIdleTime()}. - */ - @Deprecated - public final long getSoftMinEvictableIdleTimeMillis() { - return softMinEvictableIdleDuration.toMillis(); - } - /** * Gets the stack trace of an exception as a string. * @param e exception to trace @@ -1052,10 +1028,10 @@ String getStatsString() { "maxTotal=%s, maxWaitDuration=%s, minEvictableIdleDuration=%s, numTestsPerEvictionRun=%s, returnedCount=%s, " + "softMinEvictableIdleDuration=%s, testOnBorrow=%s, testOnCreate=%s, testOnReturn=%s, testWhileIdle=%s, " + "durationBetweenEvictionRuns=%s, waitTimes=%s", - activeTimes.getCurrentValues(), blockWhenExhausted, borrowedCount.get(), closed, createdCount.get(), destroyedByBorrowValidationCount.get(), - destroyedByEvictorCount.get(), evictorShutdownTimeoutDuration, fairness, idleTimes.getCurrentValues(), lifo, maxBorrowWaitDuration.get(), + activeTimes.getValues(), blockWhenExhausted, borrowedCount.get(), closed, createdCount.get(), destroyedByBorrowValidationCount.get(), + destroyedByEvictorCount.get(), evictorShutdownTimeoutDuration, fairness, idleTimes.getValues(), lifo, maxBorrowWaitDuration.get(), maxTotal, maxWaitDuration, minEvictableIdleDuration, numTestsPerEvictionRun, returnedCount, softMinEvictableIdleDuration, testOnBorrow, - testOnCreate, testOnReturn, testWhileIdle, durationBetweenEvictionRuns, waitTimes.getCurrentValues()); + testOnCreate, testOnReturn, testWhileIdle, durationBetweenEvictionRuns, waitTimes.getValues()); } /** @@ -1096,7 +1072,6 @@ public final boolean getTestOnBorrow() { * being returned from the {@code borrowObject()} method * * @see #setTestOnCreate - * * @since 2.2 */ public final boolean getTestOnCreate() { @@ -1122,44 +1097,26 @@ public final boolean getTestOnReturn() { /** * Gets whether objects sitting idle in the pool will be validated by the * idle object evictor (if any - see - * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed + * {@link #setDurationBetweenEvictionRuns(Duration)}). Validation is performed * by the {@code validateObject()} method of the factory associated * with the pool. If the object fails to validate, it will be removed from * the pool and destroyed. * * @return {@code true} if objects will be validated by the evictor - * * @see #setTestWhileIdle - * @see #setTimeBetweenEvictionRunsMillis + * @see #setDurationBetweenEvictionRuns(Duration) */ public final boolean getTestWhileIdle() { return testWhileIdle; } - /** - * Gets the duration to sleep between runs of the idle - * object evictor thread. When non-positive, no idle object evictor thread - * will be run. - * - * @return number of milliseconds to sleep between evictor runs - * - * @see #setTimeBetweenEvictionRuns - * @since 2.10.0 - * @deprecated {@link #getDurationBetweenEvictionRuns()}. - */ - @Deprecated - public final Duration getTimeBetweenEvictionRuns() { - return durationBetweenEvictionRuns; - } - /** * Gets the number of milliseconds to sleep between runs of the idle * object evictor thread. When non-positive, no idle object evictor thread * will be run. * * @return number of milliseconds to sleep between evictor runs - * - * @see #setTimeBetweenEvictionRunsMillis + * @see #setDurationBetweenEvictionRuns(Duration) * @deprecated Use {@link #getDurationBetweenEvictionRuns()}. */ @Deprecated @@ -1179,8 +1136,9 @@ public boolean isAbandonedConfig() { } /** - * Tests whether this pool instance been closed. - * @return {@code true} when this pool has been closed. + * Tests whether this pool instance is closed. + * + * @return {@code true} when this pool is closed. */ public final boolean isClosed() { return closed; @@ -1211,7 +1169,7 @@ private ObjectName jmxRegister(final BaseObjectPoolConfig config, } while (!registered) { try { - ObjectName objName; + final ObjectName objName; // Skip the numeric suffix for the first pool in case there is // only one so the names are cleaner. if (i == 1) { @@ -1279,7 +1237,6 @@ protected void markReturningState(final PooledObject pooledObject) { * Sets the abandoned object removal configuration. * * @param abandonedConfig the new configuration to use. This is used by value. - * * @see AbandonedConfig * @since 2.11.0 */ @@ -1316,9 +1273,9 @@ protected void setConfig(final BaseObjectPoolConfig config) { setTestOnReturn(config.getTestOnReturn()); setTestWhileIdle(config.getTestWhileIdle()); setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun()); - setMinEvictableIdle(config.getMinEvictableIdleDuration()); - setTimeBetweenEvictionRuns(config.getDurationBetweenEvictionRuns()); - setSoftMinEvictableIdle(config.getSoftMinEvictableIdleDuration()); + setMinEvictableIdleDuration(config.getMinEvictableIdleDuration()); + setDurationBetweenEvictionRuns(config.getDurationBetweenEvictionRuns()); + setSoftMinEvictableIdleDuration(config.getSoftMinEvictableIdleDuration()); final EvictionPolicy policy = config.getEvictionPolicy(); if (policy == null) { // Use the class name (pre-2.6.0 compatible) @@ -1328,6 +1285,24 @@ protected void setConfig(final BaseObjectPoolConfig config) { setEvictionPolicy(policy); } setEvictorShutdownTimeout(config.getEvictorShutdownTimeoutDuration()); + setCollectDetailedStatistics(config.getCollectDetailedStatistics()); + } + + /** + * Sets the number of milliseconds to sleep between runs of the idle object evictor thread. + *
    + *
  • When positive, the idle object evictor thread starts.
  • + *
  • When non-positive, no idle object evictor thread runs.
  • + *
+ * + * @param timeBetweenEvictionRuns + * duration to sleep between evictor runs + * + * @see #getDurationBetweenEvictionRuns() + */ + public final void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) { + this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS); + startEvictor(this.durationBetweenEvictionRuns); } /** @@ -1432,19 +1407,6 @@ public final void setEvictorShutdownTimeout(final Duration evictorShutdownTimeou this.evictorShutdownTimeoutDuration = PoolImplUtils.nonNull(evictorShutdownTimeout, BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT); } - /** - * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the - * only pool still using the value for the Evictor. - * - * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor - * to shut down. - * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}. - */ - @Deprecated - public final void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) { - setEvictorShutdownTimeout(Duration.ofMillis(evictorShutdownTimeoutMillis)); - } - /** * Sets whether the pool has LIFO (last in, first out) behavior with * respect to idle objects - always returning the most recently used object @@ -1495,26 +1457,6 @@ public final void setMaxWait(final Duration maxWaitDuration) { this.maxWaitDuration = PoolImplUtils.nonNull(maxWaitDuration, BaseObjectPoolConfig.DEFAULT_MAX_WAIT); } - /** - * Sets the maximum amount of time (in milliseconds) the - * {@code borrowObject()} method should block before throwing an - * exception when the pool is exhausted and - * {@link #getBlockWhenExhausted} is true. When less than 0, the - * {@code borrowObject()} method may block indefinitely. - * - * @param maxWaitMillis the maximum number of milliseconds - * {@code borrowObject()} will block or negative - * for indefinitely. - * - * @see #getMaxWaitDuration - * @see #setBlockWhenExhausted - * @deprecated Use {@link #setMaxWait}. - */ - @Deprecated - public final void setMaxWaitMillis(final long maxWaitMillis) { - setMaxWait(Duration.ofMillis(maxWaitMillis)); - } - /** * Sets whether to include statistics in exception messages. *

@@ -1530,62 +1472,37 @@ public void setMessagesStatistics(final boolean messagesDetails) { } /** - * Sets the minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive, - * no objects will be evicted from the pool due to idle time alone. - * - * @param minEvictableIdleTime - * minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction + * Sets whether detailed timing statistics collection is enabled. + * When {@code false}, the pool will not collect detailed timing statistics, + * improving performance under high load at the cost of reduced monitoring capabilities. + *

+ * This setting affects data collection for mean active time, mean idle time, and mean borrow wait time. + *

* - * @see #getMinEvictableIdleTime - * @see #setTimeBetweenEvictionRuns - * @since 2.11.0 + * @param collectDetailedStatistics whether to collect detailed statistics. + * @since 2.13.0 */ - public final void setMinEvictableIdle(final Duration minEvictableIdleTime) { - this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION); + public void setCollectDetailedStatistics(final boolean collectDetailedStatistics) { + this.collectDetailedStatistics = collectDetailedStatistics; } /** * Sets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive, + * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive, * no objects will be evicted from the pool due to idle time alone. * * @param minEvictableIdleTime * minimum amount of time an object may sit idle in the pool * before it is eligible for eviction * - * @see #getMinEvictableIdleTime - * @see #setTimeBetweenEvictionRuns - * @since 2.10.0 - * @deprecated Use {@link #setMinEvictableIdle(Duration)}. + * @see #getMinEvictableIdleDuration + * @see #setDurationBetweenEvictionRuns(Duration) */ - @Deprecated - public final void setMinEvictableIdleTime(final Duration minEvictableIdleTime) { + public final void setMinEvictableIdleDuration(final Duration minEvictableIdleTime) { this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION); } - /** - * Sets the minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive, - * no objects will be evicted from the pool due to idle time alone. - * - * @param minEvictableIdleTimeMillis - * minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction - * - * @see #getMinEvictableIdleTimeMillis - * @see #setTimeBetweenEvictionRunsMillis - * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}. - */ - @Deprecated - public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { - setMinEvictableIdleTime(Duration.ofMillis(minEvictableIdleTimeMillis)); - } - /** * Sets the maximum number of objects to examine during each run (if any) * of the idle object evictor thread. When positive, the number of tests @@ -1600,7 +1517,7 @@ public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeM * max number of objects to examine during each evictor run * * @see #getNumTestsPerEvictionRun - * @see #setTimeBetweenEvictionRunsMillis + * @see #setDurationBetweenEvictionRuns(Duration) */ public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { this.numTestsPerEvictionRun = numTestsPerEvictionRun; @@ -1609,72 +1526,25 @@ public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { /** * Sets the minimum amount of time an object may sit idle in the pool * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRuns(Duration)}), + * see {@link #setDurationBetweenEvictionRuns(Duration)}), * with the extra condition that at least {@code minIdle} object * instances remain in the pool. This setting is overridden by - * {@link #getMinEvictableIdleTime} (that is, if - * {@link #getMinEvictableIdleTime} is positive, then - * {@link #getSoftMinEvictableIdleTime} is ignored). + * {@link #getMinEvictableIdleDuration} (that is, if + * {@link #getMinEvictableIdleDuration} is positive, then + * {@link #getSoftMinEvictableIdleDuration} is ignored). * * @param softMinEvictableIdleTime * minimum amount of time an object may sit idle in the pool * before it is eligible for eviction if minIdle instances are * available * - * @see #getSoftMinEvictableIdleTimeMillis + * @see #getSoftMinEvictableIdleDuration * @since 2.11.0 */ - public final void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTime) { - this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION); - } - - /** - * Sets the minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRuns(Duration)}), - * with the extra condition that at least {@code minIdle} object - * instances remain in the pool. This setting is overridden by - * {@link #getMinEvictableIdleTime} (that is, if - * {@link #getMinEvictableIdleTime} is positive, then - * {@link #getSoftMinEvictableIdleTime} is ignored). - * - * @param softMinEvictableIdleTime - * minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction if minIdle instances are - * available - * - * @see #getSoftMinEvictableIdleTimeMillis - * @since 2.10.0 - * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}. - */ - @Deprecated - public final void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) { + public final void setSoftMinEvictableIdleDuration(final Duration softMinEvictableIdleTime) { this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION); } - /** - * Sets the minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction by the idle object evictor (if any - - * see {@link #setTimeBetweenEvictionRunsMillis(long)}), - * with the extra condition that at least {@code minIdle} object - * instances remain in the pool. This setting is overridden by - * {@link #getMinEvictableIdleTimeMillis} (that is, if - * {@link #getMinEvictableIdleTimeMillis} is positive, then - * {@link #getSoftMinEvictableIdleTimeMillis} is ignored). - * - * @param softMinEvictableIdleTimeMillis - * minimum amount of time an object may sit idle in the pool - * before it is eligible for eviction if minIdle instances are - * available - * - * @see #getSoftMinEvictableIdleTimeMillis - * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}. - */ - @Deprecated - public final void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { - setSoftMinEvictableIdleTime(Duration.ofMillis(softMinEvictableIdleTimeMillis)); - } - /** * Sets the listener used (if any) to receive notifications of exceptions * unavoidably swallowed by the pool. @@ -1717,7 +1587,6 @@ public final void setTestOnBorrow(final boolean testOnBorrow) { * {@code borrowObject()} method * * @see #getTestOnCreate - * * @since 2.2 */ public final void setTestOnCreate(final boolean testOnCreate) { @@ -1744,7 +1613,7 @@ public final void setTestOnReturn(final boolean testOnReturn) { /** * Sets whether objects sitting idle in the pool will be validated by the * idle object evictor (if any - see - * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed + * {@link #setDurationBetweenEvictionRuns(Duration)}). Validation is performed * by the {@code validateObject()} method of the factory associated * with the pool. If the object fails to validate, it will be removed from * the pool and destroyed. Note that setting this property has no effect @@ -1755,48 +1624,12 @@ public final void setTestOnReturn(final boolean testOnReturn) { * {@code true} so objects will be validated by the evictor * * @see #getTestWhileIdle - * @see #setTimeBetweenEvictionRuns + * @see #setDurationBetweenEvictionRuns(Duration) */ public final void setTestWhileIdle(final boolean testWhileIdle) { this.testWhileIdle = testWhileIdle; } - /** - * Sets the number of milliseconds to sleep between runs of the idle object evictor thread. - *
    - *
  • When positive, the idle object evictor thread starts.
  • - *
  • When non-positive, no idle object evictor thread runs.
  • - *
- * - * @param timeBetweenEvictionRuns - * duration to sleep between evictor runs - * - * @see #getDurationBetweenEvictionRuns() - * @since 2.10.0 - */ - public final void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) { - this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS); - startEvictor(this.durationBetweenEvictionRuns); - } - - /** - * Sets the number of milliseconds to sleep between runs of the idle object evictor thread. - *
    - *
  • When positive, the idle object evictor thread starts.
  • - *
  • When non-positive, no idle object evictor thread runs.
  • - *
- * - * @param timeBetweenEvictionRunsMillis - * number of milliseconds to sleep between evictor runs - * - * @see #getDurationBetweenEvictionRuns() - * @deprecated Use {@link #setTimeBetweenEvictionRuns(Duration)}. - */ - @Deprecated - public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { - setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis)); - } - /** *

Starts the evictor with the given delay. If there is an evictor * running when this method is called, it is stopped and replaced with a @@ -1805,7 +1638,7 @@ public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictio *

This method needs to be final, since it is called from a constructor. * See POOL-195.

* - * @param delay time in milliseconds before start and between eviction runs + * @param delay duration before start and between eviction runs. */ final void startEvictor(final Duration delay) { synchronized (evictionLock) { @@ -1936,20 +1769,19 @@ protected void toStringAppendFields(final StringBuilder builder) { */ final void updateStatsBorrow(final PooledObject p, final Duration waitDuration) { borrowedCount.incrementAndGet(); - idleTimes.add(p.getIdleDuration()); - waitTimes.add(waitDuration); - - // lock-free optimistic-locking maximum - Duration currentMaxDuration; - do { - currentMaxDuration = maxBorrowWaitDuration.get(); -// if (currentMaxDuration >= waitDuration) { -// break; -// } - if (currentMaxDuration.compareTo(waitDuration) >= 0) { - break; - } - } while (!maxBorrowWaitDuration.compareAndSet(currentMaxDuration, waitDuration)); + // Only collect detailed statistics if enabled + if (collectDetailedStatistics) { + idleTimes.add(p.getIdleDuration()); + waitTimes.add(waitDuration); + // lock-free optimistic-locking maximum + Duration currentMaxDuration; + do { + currentMaxDuration = maxBorrowWaitDuration.get(); + if (currentMaxDuration.compareTo(waitDuration) >= 0) { + break; + } + } while (!maxBorrowWaitDuration.compareAndSet(currentMaxDuration, waitDuration)); + } } /** @@ -1960,8 +1792,10 @@ final void updateStatsBorrow(final PooledObject p, final Duration waitDuratio */ final void updateStatsReturn(final Duration activeTime) { returnedCount.incrementAndGet(); - activeTimes.add(activeTime); + // Only collect detailed statistics if enabled + if (collectDetailedStatistics) { + activeTimes.add(activeTime); + } } - } diff --git a/src/main/java/org/apache/commons/pool2/impl/BaseObjectPoolConfig.java b/src/main/java/org/apache/commons/pool3/impl/BaseObjectPoolConfig.java similarity index 65% rename from src/main/java/org/apache/commons/pool2/impl/BaseObjectPoolConfig.java rename to src/main/java/org/apache/commons/pool3/impl/BaseObjectPoolConfig.java index 081105483..e47a04510 100644 --- a/src/main/java/org/apache/commons/pool2/impl/BaseObjectPoolConfig.java +++ b/src/main/java/org/apache/commons/pool3/impl/BaseObjectPoolConfig.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,11 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.time.Duration; -import org.apache.commons.pool2.BaseObject; +import org.apache.commons.pool3.BaseObject; /** * Provides the implementation for the common attributes shared by the @@ -47,32 +47,13 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon */ public static final boolean DEFAULT_FAIRNESS = false; - /** - * The default value for the {@code maxWait} configuration attribute. - * @see GenericObjectPool#getMaxWaitDuration() - * @see GenericKeyedObjectPool#getMaxWaitDuration() - * @deprecated Use {@link #DEFAULT_MAX_WAIT}. - */ - @Deprecated - public static final long DEFAULT_MAX_WAIT_MILLIS = -1L; - /** * The default value for the {@code maxWait} configuration attribute. * @see GenericObjectPool#getMaxWaitDuration() * @see GenericKeyedObjectPool#getMaxWaitDuration() * @since 2.10.0 */ - public static final Duration DEFAULT_MAX_WAIT = Duration.ofMillis(DEFAULT_MAX_WAIT_MILLIS); - - /** - * The default value for the {@code minEvictableIdleDuration} - * configuration attribute. - * @see GenericObjectPool#getMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getMinEvictableIdleDuration() - * @deprecated Use {@link #DEFAULT_MIN_EVICTABLE_IDLE_TIME}. - */ - @Deprecated - public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L; + public static final Duration DEFAULT_MAX_WAIT = Duration.ofMillis(-1L); /** * The default value for the {@code minEvictableIdleDuration} @@ -81,42 +62,7 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon * @see GenericKeyedObjectPool#getMinEvictableIdleDuration() * @since 2.11.0 */ - public static final Duration DEFAULT_MIN_EVICTABLE_IDLE_DURATION = - Duration.ofMillis(DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS); - - /** - * The default value for the {@code minEvictableIdleDuration} - * configuration attribute. - * @see GenericObjectPool#getMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getMinEvictableIdleDuration() - * @since 2.10.0 - * @deprecated Use {@link #DEFAULT_MIN_EVICTABLE_IDLE_DURATION}. - */ - @Deprecated - public static final Duration DEFAULT_MIN_EVICTABLE_IDLE_TIME = - Duration.ofMillis(DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS); - - /** - * The default value for the {@code softMinEvictableIdleTime} - * configuration attribute. - * @see GenericObjectPool#getSoftMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getSoftMinEvictableIdleDuration() - * @deprecated Use {@link #DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME}. - */ - @Deprecated - public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1; - - /** - * The default value for the {@code softMinEvictableIdleTime} - * configuration attribute. - * @see GenericObjectPool#getSoftMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getSoftMinEvictableIdleDuration() - * @since 2.10.0 - * @deprecated Use {@link #DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION}. - */ - @Deprecated - public static final Duration DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME = - Duration.ofMillis(DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS); + public static final Duration DEFAULT_MIN_EVICTABLE_IDLE_DURATION = Duration.ofMillis(1000L * 60L * 30L); /** * The default value for the {@code softMinEvictableIdleTime} @@ -125,18 +71,7 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon * @see GenericKeyedObjectPool#getSoftMinEvictableIdleDuration() * @since 2.11.0 */ - public static final Duration DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION = - Duration.ofMillis(DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS); - - /** - * The default value for {@code evictorShutdownTimeout} configuration - * attribute. - * @see GenericObjectPool#getEvictorShutdownTimeoutDuration() - * @see GenericKeyedObjectPool#getEvictorShutdownTimeoutDuration() - * @deprecated Use {@link #DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT}. - */ - @Deprecated - public static final long DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS = 10L * 1000L; + public static final Duration DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION = Duration.ofMillis(-1); /** * The default value for {@code evictorShutdownTimeout} configuration @@ -145,8 +80,7 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon * @see GenericKeyedObjectPool#getEvictorShutdownTimeoutDuration() * @since 2.10.0 */ - public static final Duration DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT = - Duration.ofMillis(DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS); + public static final Duration DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT = Duration.ofMillis(10L * 1000L); /** * The default value for the {@code numTestsPerEvictionRun} configuration @@ -160,7 +94,6 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon * The default value for the {@code testOnCreate} configuration attribute. * @see GenericObjectPool#getTestOnCreate() * @see GenericKeyedObjectPool#getTestOnCreate() - * * @since 2.2 */ public static final boolean DEFAULT_TEST_ON_CREATE = false; @@ -186,24 +119,13 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon */ public static final boolean DEFAULT_TEST_WHILE_IDLE = false; - /** - * The default value for the {@code timeBetweenEvictionRuns} - * configuration attribute. - * @see GenericObjectPool#getDurationBetweenEvictionRuns() - * @see GenericKeyedObjectPool#getDurationBetweenEvictionRuns() - * @deprecated Use {@link #DEFAULT_TIME_BETWEEN_EVICTION_RUNS}. - */ - @Deprecated - public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L; - /** * The default value for the {@code timeBetweenEvictionRuns} * configuration attribute. * @see GenericObjectPool#getDurationBetweenEvictionRuns() * @see GenericKeyedObjectPool#getDurationBetweenEvictionRuns() */ - public static final Duration DEFAULT_TIME_BETWEEN_EVICTION_RUNS = Duration - .ofMillis(DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS); + public static final Duration DEFAULT_DURATION_BETWEEN_EVICTION_RUNS = Duration.ofMillis(-1L); /** * The default value for the {@code blockWhenExhausted} configuration @@ -244,17 +166,30 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon */ public static final String DEFAULT_EVICTION_POLICY_CLASS_NAME = DefaultEvictionPolicy.class.getName(); + /** + * The default value for the {@code collectDetailedStatistics} configuration + * attribute. When {@code true}, the pool will collect detailed timing statistics + * for monitoring purposes. When {@code false}, detailed statistics collection + * is disabled, improving performance under high load. + *

+ * This setting affects data collection for mean active time, mean idle time, and mean borrow wait time. + *

+ * + * @since 2.13.0 + */ + public static final boolean DEFAULT_COLLECT_DETAILED_STATISTICS = true; + private boolean lifo = DEFAULT_LIFO; private boolean fairness = DEFAULT_FAIRNESS; private Duration maxWaitDuration = DEFAULT_MAX_WAIT; - private Duration minEvictableIdleDuration = DEFAULT_MIN_EVICTABLE_IDLE_TIME; + private Duration minEvictableIdleDuration = DEFAULT_MIN_EVICTABLE_IDLE_DURATION; private Duration evictorShutdownTimeoutDuration = DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT; - private Duration softMinEvictableIdleDuration = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME; + private Duration softMinEvictableIdleDuration = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION; private int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN; @@ -270,7 +205,7 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon private boolean testWhileIdle = DEFAULT_TEST_WHILE_IDLE; - private Duration durationBetweenEvictionRuns = DEFAULT_TIME_BETWEEN_EVICTION_RUNS; + private Duration durationBetweenEvictionRuns = DEFAULT_DURATION_BETWEEN_EVICTION_RUNS; private boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED; @@ -281,6 +216,14 @@ public abstract class BaseObjectPoolConfig extends BaseObject implements Clon private String jmxNameBase = DEFAULT_JMX_NAME_BASE; + private boolean collectDetailedStatistics = DEFAULT_COLLECT_DETAILED_STATISTICS; + + /** + * Constructs a new instance. + */ + public BaseObjectPoolConfig() { + // empty + } /** * Gets the value for the {@code blockWhenExhausted} configuration attribute @@ -296,6 +239,23 @@ public boolean getBlockWhenExhausted() { return blockWhenExhausted; } + /** + * Gets the value for the {@code collectDetailedStatistics} configuration attribute + * for pools created with this configuration instance. + *

+ * This setting affects data collection for mean active time, mean idle time, and mean borrow wait time. + *

+ * + * @return {@code true} if detailed statistics collection is enabled, + * {@code false} if disabled for improved performance. + * @see GenericObjectPool#getCollectDetailedStatistics() + * @see GenericKeyedObjectPool#getCollectDetailedStatistics() + * @since 2.13.0 + */ + public boolean getCollectDetailedStatistics() { + return collectDetailedStatistics; + } + /** * Gets the value for the {@code timeBetweenEvictionRuns} configuration * attribute for pools created with this configuration instance. @@ -340,23 +300,6 @@ public String getEvictionPolicyClassName() { return evictionPolicyClassName; } - /** - * Gets the value for the {@code evictorShutdownTimeout} configuration - * attribute for pools created with this configuration instance. - * - * @return The current setting of {@code evictorShutdownTimeout} for - * this configuration instance - * - * @see GenericObjectPool#getEvictorShutdownTimeoutDuration() - * @see GenericKeyedObjectPool#getEvictorShutdownTimeoutDuration() - * @since 2.10.0 - * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}. - */ - @Deprecated - public Duration getEvictorShutdownTimeout() { - return evictorShutdownTimeoutDuration; - } - /** * Gets the value for the {@code evictorShutdownTimeout} configuration * attribute for pools created with this configuration instance. @@ -372,22 +315,6 @@ public Duration getEvictorShutdownTimeoutDuration() { return evictorShutdownTimeoutDuration; } - /** - * Gets the value for the {@code evictorShutdownTimeout} configuration - * attribute for pools created with this configuration instance. - * - * @return The current setting of {@code evictorShutdownTimeout} for - * this configuration instance - * - * @see GenericObjectPool#getEvictorShutdownTimeoutDuration() - * @see GenericKeyedObjectPool#getEvictorShutdownTimeoutDuration() - * @deprecated Use {@link #getEvictorShutdownTimeout()}. - */ - @Deprecated - public long getEvictorShutdownTimeoutMillis() { - return evictorShutdownTimeoutDuration.toMillis(); - } - /** * Gets the value for the {@code fairness} configuration attribute for pools * created with this configuration instance. @@ -467,22 +394,6 @@ public Duration getMaxWaitDuration() { return maxWaitDuration; } - /** - * Gets the value for the {@code maxWait} configuration attribute for pools - * created with this configuration instance. - * - * @return The current setting of {@code maxWait} for this - * configuration instance - * - * @see GenericObjectPool#getMaxWaitDuration() - * @see GenericKeyedObjectPool#getMaxWaitDuration() - * @deprecated Use {@link #getMaxWaitDuration()}. - */ - @Deprecated - public long getMaxWaitMillis() { - return maxWaitDuration.toMillis(); - } - /** * Gets the value for the {@code minEvictableIdleTime} configuration * attribute for pools created with this configuration instance. @@ -498,39 +409,6 @@ public Duration getMinEvictableIdleDuration() { return minEvictableIdleDuration; } - /** - * Gets the value for the {@code minEvictableIdleTime} configuration - * attribute for pools created with this configuration instance. - * - * @return The current setting of {@code minEvictableIdleTime} for - * this configuration instance - * - * @see GenericObjectPool#getMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getMinEvictableIdleDuration() - * @since 2.10.0 - * @deprecated Use {@link #getMinEvictableIdleDuration()}. - */ - @Deprecated - public Duration getMinEvictableIdleTime() { - return minEvictableIdleDuration; - } - - /** - * Gets the value for the {@code minEvictableIdleTime} configuration - * attribute for pools created with this configuration instance. - * - * @return The current setting of {@code minEvictableIdleTime} for - * this configuration instance - * - * @see GenericObjectPool#getMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getMinEvictableIdleDuration() - * @deprecated Use {@link #getMinEvictableIdleTime()}. - */ - @Deprecated - public long getMinEvictableIdleTimeMillis() { - return minEvictableIdleDuration.toMillis(); - } - /** * Gets the value for the {@code numTestsPerEvictionRun} configuration * attribute for pools created with this configuration instance. @@ -561,41 +439,6 @@ public Duration getSoftMinEvictableIdleDuration() { return softMinEvictableIdleDuration; } - /** - * Gets the value for the {@code softMinEvictableIdleTime} - * configuration attribute for pools created with this configuration - * instance. - * - * @return The current setting of {@code softMinEvictableIdleTime} - * for this configuration instance - * - * @see GenericObjectPool#getSoftMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getSoftMinEvictableIdleDuration() - * @since 2.10.0 - * @deprecated Use {@link #getSoftMinEvictableIdleDuration()}. - */ - @Deprecated - public Duration getSoftMinEvictableIdleTime() { - return softMinEvictableIdleDuration; - } - - /** - * Gets the value for the {@code softMinEvictableIdleTime} - * configuration attribute for pools created with this configuration - * instance. - * - * @return The current setting of {@code softMinEvictableIdleTime} - * for this configuration instance - * - * @see GenericObjectPool#getSoftMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getSoftMinEvictableIdleDuration() - * @deprecated Use {@link #getSoftMinEvictableIdleDuration()}. - */ - @Deprecated - public long getSoftMinEvictableIdleTimeMillis() { - return softMinEvictableIdleDuration.toMillis(); - } - /** * Gets the value for the {@code testOnBorrow} configuration attribute for * pools created with this configuration instance. @@ -619,7 +462,6 @@ public boolean getTestOnBorrow() { * * @see GenericObjectPool#getTestOnCreate() * @see GenericKeyedObjectPool#getTestOnCreate() - * * @since 2.2 */ public boolean getTestOnCreate() { @@ -655,50 +497,53 @@ public boolean getTestWhileIdle() { } /** - * Gets the value for the {@code timeBetweenEvictionRuns} configuration - * attribute for pools created with this configuration instance. + * Sets the value for the {@code blockWhenExhausted} configuration attribute + * for pools created with this configuration instance. * - * @return The current setting of {@code timeBetweenEvictionRuns} for - * this configuration instance + * @param blockWhenExhausted The new setting of {@code blockWhenExhausted} + * for this configuration instance * - * @see GenericObjectPool#getDurationBetweenEvictionRuns() - * @see GenericKeyedObjectPool#getDurationBetweenEvictionRuns() - * @since 2.10.0 - * @deprecated Use {@link #getDurationBetweenEvictionRuns()}. + * @see GenericObjectPool#getBlockWhenExhausted() + * @see GenericKeyedObjectPool#getBlockWhenExhausted() */ - @Deprecated - public Duration getTimeBetweenEvictionRuns() { - return durationBetweenEvictionRuns; + public void setBlockWhenExhausted(final boolean blockWhenExhausted) { + this.blockWhenExhausted = blockWhenExhausted; } /** - * Gets the value for the {@code timeBetweenEvictionRuns} configuration - * attribute for pools created with this configuration instance. + * Sets the value for the {@code collectDetailedStatistics} configuration attribute + * for pools created with this configuration instance. When {@code false}, the pool + * will not collect detailed timing statistics, improving performance under high load + * at the cost of reduced monitoring capabilities. + *

+ * This setting affects data collection for mean active time, mean idle time, and mean borrow wait time. + *

* - * @return The current setting of {@code timeBetweenEvictionRuns} for - * this configuration instance + * @param collectDetailedStatistics The new setting of {@code collectDetailedStatistics} + * for this configuration instance. * - * @see GenericObjectPool#getDurationBetweenEvictionRuns() - * @see GenericKeyedObjectPool#getDurationBetweenEvictionRuns() - * @deprecated Use {@link #getDurationBetweenEvictionRuns()}. + * @see GenericObjectPool#getCollectDetailedStatistics() + * @see GenericKeyedObjectPool#getCollectDetailedStatistics() + * @since 2.13.0 */ - @Deprecated - public long getTimeBetweenEvictionRunsMillis() { - return durationBetweenEvictionRuns.toMillis(); + public void setCollectDetailedStatistics(final boolean collectDetailedStatistics) { + this.collectDetailedStatistics = collectDetailedStatistics; } /** - * Sets the value for the {@code blockWhenExhausted} configuration attribute - * for pools created with this configuration instance. + * Sets the value for the {@code timeBetweenEvictionRuns} configuration + * attribute for pools created with this configuration instance. * - * @param blockWhenExhausted The new setting of {@code blockWhenExhausted} - * for this configuration instance + * @param timeBetweenEvictionRuns The new setting of + * {@code timeBetweenEvictionRuns} for this configuration + * instance * - * @see GenericObjectPool#getBlockWhenExhausted() - * @see GenericKeyedObjectPool#getBlockWhenExhausted() + * @see GenericObjectPool#getDurationBetweenEvictionRuns() + * @see GenericKeyedObjectPool#getDurationBetweenEvictionRuns() + * @since 2.10.0 */ - public void setBlockWhenExhausted(final boolean blockWhenExhausted) { - this.blockWhenExhausted = blockWhenExhausted; + public void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) { + this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, DEFAULT_DURATION_BETWEEN_EVICTION_RUNS); } /** @@ -746,41 +591,6 @@ public void setEvictorShutdownTimeout(final Duration evictorShutdownTimeoutDurat this.evictorShutdownTimeoutDuration = PoolImplUtils.nonNull(evictorShutdownTimeoutDuration, DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT); } - /** - * Sets the value for the {@code evictorShutdownTimeout} configuration - * attribute for pools created with this configuration instance. - * - * @param evictorShutdownTimeout The new setting of - * {@code evictorShutdownTimeout} for this configuration - * instance - * - * @see GenericObjectPool#getEvictorShutdownTimeoutDuration() - * @see GenericKeyedObjectPool#getEvictorShutdownTimeoutDuration() - * @since 2.10.0 - * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}. - */ - @Deprecated - public void setEvictorShutdownTimeoutMillis(final Duration evictorShutdownTimeout) { - setEvictorShutdownTimeout(evictorShutdownTimeout); - } - - /** - * Sets the value for the {@code evictorShutdownTimeout} configuration - * attribute for pools created with this configuration instance. - * - * @param evictorShutdownTimeoutMillis The new setting of - * {@code evictorShutdownTimeout} for this configuration - * instance - * - * @see GenericObjectPool#getEvictorShutdownTimeoutDuration() - * @see GenericKeyedObjectPool#getEvictorShutdownTimeoutDuration() - * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}. - */ - @Deprecated - public void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) { - setEvictorShutdownTimeout(Duration.ofMillis(evictorShutdownTimeoutMillis)); - } - /** * Sets the value for the {@code fairness} configuration attribute for pools * created with this configuration instance. @@ -860,22 +670,6 @@ public void setMaxWait(final Duration maxWaitDuration) { this.maxWaitDuration = PoolImplUtils.nonNull(maxWaitDuration, DEFAULT_MAX_WAIT); } - /** - * Sets the value for the {@code maxWait} configuration attribute for pools - * created with this configuration instance. - * - * @param maxWaitMillis The new setting of {@code maxWaitMillis} - * for this configuration instance - * - * @see GenericObjectPool#getMaxWaitDuration() - * @see GenericKeyedObjectPool#getMaxWaitDuration() - * @deprecated Use {@link #setMaxWait(Duration)}. - */ - @Deprecated - public void setMaxWaitMillis(final long maxWaitMillis) { - setMaxWait(Duration.ofMillis(maxWaitMillis)); - } - /** * Sets the value for the {@code minEvictableIdleTime} configuration * attribute for pools created with this configuration instance. @@ -887,24 +681,8 @@ public void setMaxWaitMillis(final long maxWaitMillis) { * @see GenericKeyedObjectPool#getMinEvictableIdleDuration() * @since 2.10.0 */ - public void setMinEvictableIdleTime(final Duration minEvictableIdleTime) { - this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, DEFAULT_MIN_EVICTABLE_IDLE_TIME); - } - - /** - * Sets the value for the {@code minEvictableIdleTime} configuration - * attribute for pools created with this configuration instance. - * - * @param minEvictableIdleTimeMillis The new setting of - * {@code minEvictableIdleTime} for this configuration instance - * - * @see GenericObjectPool#getMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getMinEvictableIdleDuration() - * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}. - */ - @Deprecated - public void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { - this.minEvictableIdleDuration = Duration.ofMillis(minEvictableIdleTimeMillis); + public void setMinEvictableIdleDuration(final Duration minEvictableIdleTime) { + this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, DEFAULT_MIN_EVICTABLE_IDLE_DURATION); } /** @@ -934,27 +712,8 @@ public void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { * @see GenericKeyedObjectPool#getSoftMinEvictableIdleDuration() * @since 2.10.0 */ - public void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) { - this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME); - } - - /** - * Sets the value for the {@code softMinEvictableIdleTime} - * configuration attribute for pools created with this configuration - * instance. - * - * @param softMinEvictableIdleTimeMillis The new setting of - * {@code softMinEvictableIdleTime} for this configuration - * instance - * - * @see GenericObjectPool#getSoftMinEvictableIdleDuration() - * @see GenericKeyedObjectPool#getSoftMinEvictableIdleDuration() - * @deprecated Use {@link #setSoftMinEvictableIdleTime(Duration)}. - */ - @Deprecated - public void setSoftMinEvictableIdleTimeMillis( - final long softMinEvictableIdleTimeMillis) { - setSoftMinEvictableIdleTime(Duration.ofMillis(softMinEvictableIdleTimeMillis)); + public void setSoftMinEvictableIdleDuration(final Duration softMinEvictableIdleTime) { + this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION); } /** @@ -980,7 +739,6 @@ public void setTestOnBorrow(final boolean testOnBorrow) { * * @see GenericObjectPool#getTestOnCreate() * @see GenericKeyedObjectPool#getTestOnCreate() - * * @since 2.2 */ public void setTestOnCreate(final boolean testOnCreate) { @@ -1015,39 +773,6 @@ public void setTestWhileIdle(final boolean testWhileIdle) { this.testWhileIdle = testWhileIdle; } - /** - * Sets the value for the {@code timeBetweenEvictionRuns} configuration - * attribute for pools created with this configuration instance. - * - * @param timeBetweenEvictionRuns The new setting of - * {@code timeBetweenEvictionRuns} for this configuration - * instance - * - * @see GenericObjectPool#getDurationBetweenEvictionRuns() - * @see GenericKeyedObjectPool#getDurationBetweenEvictionRuns() - * @since 2.10.0 - */ - public void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) { - this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, DEFAULT_TIME_BETWEEN_EVICTION_RUNS); - } - - /** - * Sets the value for the {@code timeBetweenEvictionRuns} configuration - * attribute for pools created with this configuration instance. - * - * @param timeBetweenEvictionRunsMillis The new setting of - * {@code timeBetweenEvictionRuns} for this configuration - * instance - * - * @see GenericObjectPool#getDurationBetweenEvictionRuns() - * @see GenericKeyedObjectPool#getDurationBetweenEvictionRuns() - * @deprecated Use {@link #setTimeBetweenEvictionRuns(Duration)}. - */ - @Deprecated - public void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { - setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis)); - } - @Override protected void toStringAppendFields(final StringBuilder builder) { builder.append("lifo="); @@ -1082,5 +807,7 @@ protected void toStringAppendFields(final StringBuilder builder) { builder.append(jmxNamePrefix); builder.append(", jmxNameBase="); builder.append(jmxNameBase); + builder.append(", collectDetailedStatistics="); + builder.append(collectDetailedStatistics); } } diff --git a/src/main/java/org/apache/commons/pool2/impl/CallStack.java b/src/main/java/org/apache/commons/pool3/impl/CallStack.java similarity index 89% rename from src/main/java/org/apache/commons/pool2/impl/CallStack.java rename to src/main/java/org/apache/commons/pool3/impl/CallStack.java index 9db0452a7..7c63558cb 100644 --- a/src/main/java/org/apache/commons/pool2/impl/CallStack.java +++ b/src/main/java/org/apache/commons/pool3/impl/CallStack.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,12 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.PrintWriter; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.UsageTracking; /** * Strategy for obtaining and printing the current call stack. This is primarily useful for @@ -50,5 +50,5 @@ public interface CallStack { * @param writer a PrintWriter to write the current stack trace to if available * @return true if a stack trace was available to print or false if nothing was printed */ - boolean printStackTrace(final PrintWriter writer); + boolean printStackTrace(PrintWriter writer); } diff --git a/src/main/java/org/apache/commons/pool2/impl/CallStackUtils.java b/src/main/java/org/apache/commons/pool3/impl/CallStackUtils.java similarity index 78% rename from src/main/java/org/apache/commons/pool2/impl/CallStackUtils.java rename to src/main/java/org/apache/commons/pool3/impl/CallStackUtils.java index 1fdcad23e..a9e1f4426 100644 --- a/src/main/java/org/apache/commons/pool2/impl/CallStackUtils.java +++ b/src/main/java/org/apache/commons/pool3/impl/CallStackUtils.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.security.AccessControlException; @@ -44,20 +44,6 @@ private static boolean canCreateSecurityManager() { } } - /** - * Constructs a new {@link CallStack} using the fastest allowed strategy. - * - * @param messageFormat message (or format) to print first in stack traces - * @param useTimestamp if true, interpret message as a SimpleDateFormat and print the created timestamp; otherwise, - * print message format literally - * @return a new CallStack - * @deprecated use {@link #newCallStack(String, boolean, boolean)} - */ - @Deprecated - public static CallStack newCallStack(final String messageFormat, final boolean useTimestamp) { - return newCallStack(messageFormat, useTimestamp, false); - } - /** * Constructs a new {@link CallStack} using the fasted allowed strategy. * diff --git a/src/main/java/org/apache/commons/pool2/impl/DefaultEvictionPolicy.java b/src/main/java/org/apache/commons/pool3/impl/DefaultEvictionPolicy.java similarity index 88% rename from src/main/java/org/apache/commons/pool2/impl/DefaultEvictionPolicy.java rename to src/main/java/org/apache/commons/pool3/impl/DefaultEvictionPolicy.java index 06a2eb8db..27e41550a 100644 --- a/src/main/java/org/apache/commons/pool2/impl/DefaultEvictionPolicy.java +++ b/src/main/java/org/apache/commons/pool3/impl/DefaultEvictionPolicy.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,9 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; /** * Provides the default implementation of {@link EvictionPolicy} used by the pools. @@ -31,18 +31,24 @@ * {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} idle objects in * the pool and the object has been idle for longer than * {@link GenericObjectPool#getSoftMinEvictableIdleDuration()} / - * {@link GenericKeyedObjectPool#getSoftMinEvictableIdleDuration()} + * {@link GenericKeyedObjectPool#getSoftMinEvictableIdleDuration()} * *

* This class is immutable and thread-safe. *

* * @param the type of objects in the pool. - * * @since 2.0 */ public class DefaultEvictionPolicy implements EvictionPolicy { + /** + * Constructs a new instance. + */ + public DefaultEvictionPolicy() { + // empty + } + @Override public boolean evict(final EvictionConfig config, final PooledObject underTest, final int idleCount) { // @formatter:off diff --git a/src/main/java/org/apache/commons/pool2/impl/DefaultPooledObject.java b/src/main/java/org/apache/commons/pool3/impl/DefaultPooledObject.java similarity index 85% rename from src/main/java/org/apache/commons/pool2/impl/DefaultPooledObject.java rename to src/main/java/org/apache/commons/pool3/impl/DefaultPooledObject.java index 93ae2be43..0f67bd42f 100644 --- a/src/main/java/org/apache/commons/pool2/impl/DefaultPooledObject.java +++ b/src/main/java/org/apache/commons/pool3/impl/DefaultPooledObject.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,17 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.PrintWriter; import java.time.Clock; import java.time.Duration; import java.time.Instant; import java.util.Deque; +import java.util.Objects; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectState; -import org.apache.commons.pool2.TrackedUse; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectState; +import org.apache.commons.pool3.TrackedUse; /** * This wrapper is used to track the additional information, such as state, for @@ -34,7 +35,6 @@ *

* * @param the type of object in the pool - * * @since 2.0 */ public class DefaultPooledObject implements PooledObject { @@ -136,11 +136,6 @@ public synchronized boolean endEvictionTest( return false; } - @Override - public long getActiveTimeMillis() { - return getActiveDuration().toMillis(); - } - /** * Gets the number of times this object has been borrowed. * @return The number of times this object has been borrowed. @@ -156,11 +151,6 @@ public Instant getCreateInstant() { return createInstant; } - @Override - public long getCreateTime() { - return createInstant.toEpochMilli(); - } - @Override public Duration getIdleDuration() { // elapsed may be negative if: @@ -170,42 +160,22 @@ public Duration getIdleDuration() { return elapsed.isNegative() ? Duration.ZERO : elapsed; } - @Override - public Duration getIdleTime() { - return getIdleDuration(); - } - - @Override - public long getIdleTimeMillis() { - return getIdleDuration().toMillis(); - } - @Override public Instant getLastBorrowInstant() { return lastBorrowInstant; } - @Override - public long getLastBorrowTime() { - return lastBorrowInstant.toEpochMilli(); - } - @Override public Instant getLastReturnInstant() { return lastReturnInstant; } - @Override - public long getLastReturnTime() { - return lastReturnInstant.toEpochMilli(); - } - /** * Gets an estimate of the last time this object was used. If the class * of the pooled object implements {@link TrackedUse}, what is returned is * the maximum of {@link TrackedUse#getLastUsedInstant()} and - * {@link #getLastBorrowTime()}; otherwise this method gives the same - * value as {@link #getLastBorrowTime()}. + * {@link #getLastBorrowInstant()}; otherwise this method gives the same + * value as {@link #getLastBorrowInstant()}. * * @return the last Instant this object was used. */ @@ -217,20 +187,6 @@ public Instant getLastUsedInstant() { return lastUseInstant; } - /** - * Gets an estimate of the last time this object was used. If the class - * of the pooled object implements {@link TrackedUse}, what is returned is - * the maximum of {@link TrackedUse#getLastUsedInstant()} and - * {@link #getLastBorrowTime()}; otherwise this method gives the same - * value as {@link #getLastBorrowTime()}. - * - * @return the last time this object was used - */ - @Override - public long getLastUsedTime() { - return getLastUsedInstant().toEpochMilli(); - } - @Override public T getObject() { return object; @@ -324,7 +280,7 @@ public synchronized boolean startEvictionTest() { public String toString() { final StringBuilder result = new StringBuilder(); result.append("Object: "); - result.append(object.toString()); + result.append(Objects.toString(object)); result.append(", State: "); synchronized (this) { result.append(state.toString()); @@ -339,5 +295,4 @@ public void use() { usedBy.fillInStackTrace(); } - -} \ No newline at end of file +} diff --git a/src/main/java/org/apache/commons/pool2/impl/DefaultPooledObjectInfo.java b/src/main/java/org/apache/commons/pool3/impl/DefaultPooledObjectInfo.java similarity index 93% rename from src/main/java/org/apache/commons/pool2/impl/DefaultPooledObjectInfo.java rename to src/main/java/org/apache/commons/pool3/impl/DefaultPooledObjectInfo.java index 9caf13994..5bf1647fc 100644 --- a/src/main/java/org/apache/commons/pool2/impl/DefaultPooledObjectInfo.java +++ b/src/main/java/org/apache/commons/pool3/impl/DefaultPooledObjectInfo.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,18 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.PrintWriter; import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.Objects; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; /** - * Implementation of object that is used to provide information on pooled - * objects via JMX. + * Implements providing information on pooled objects via JMX. * * @since 2.0 */ @@ -65,7 +64,6 @@ public long getLastBorrowTime() { return pooledObject.getLastBorrowInstant().toEpochMilli(); } - @Override public String getLastBorrowTimeFormatted() { return getTimeMillisFormatted(getLastBorrowTime()); diff --git a/src/main/java/org/apache/commons/pool2/impl/DefaultPooledObjectInfoMBean.java b/src/main/java/org/apache/commons/pool3/impl/DefaultPooledObjectInfoMBean.java similarity index 61% rename from src/main/java/org/apache/commons/pool2/impl/DefaultPooledObjectInfoMBean.java rename to src/main/java/org/apache/commons/pool3/impl/DefaultPooledObjectInfoMBean.java index 33ce08a7b..9b7eeebd8 100644 --- a/src/main/java/org/apache/commons/pool2/impl/DefaultPooledObjectInfoMBean.java +++ b/src/main/java/org/apache/commons/pool3/impl/DefaultPooledObjectInfoMBean.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,18 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; /** - * The interface that defines the information about pooled objects that will be - * exposed via JMX. + * The interface that defines the information about pooled objects that will be exposed via JMX. + *

Note

*

- * NOTE: This interface exists only to define those attributes and methods that - * will be made available via JMX. It must not be implemented by clients - * as it is subject to change between major, minor and patch version - * releases of commons pool. Clients that implement this interface may - * not, therefore, be able to upgrade to a new minor or patch release - * without requiring code changes. + * This interface exists only to define those attributes and methods that will be made available via JMX. It must not be implemented by clients as it is subject + * to change between major, minor and patch version releases of commons pool. Clients that implement this interface may not, therefore, be able to upgrade to a + * new minor or patch release without requiring code changes. *

* * @since 2.0 @@ -34,73 +31,65 @@ public interface DefaultPooledObjectInfoMBean { /** * Gets the number of times this object has been borrowed. + * * @return The number of times this object has been borrowed. * @since 2.1 */ long getBorrowedCount(); /** - * Gets the time (using the same basis as - * {@link java.time.Clock#instant()}) that pooled object was created. + * Gets the time (using the same basis as {@link java.time.Clock#instant()}) that pooled object was created. * - * @return The creation time for the pooled object + * @return The creation time for the pooled object. */ long getCreateTime(); /** * Gets the time that pooled object was created. * - * @return The creation time for the pooled object formatted as - * {@code yyyy-MM-dd HH:mm:ss Z} + * @return The creation time for the pooled object formatted as {@code yyyy-MM-dd HH:mm:ss Z}. */ String getCreateTimeFormatted(); /** - * Gets the time (using the same basis as - * {@link java.time.Clock#instant()}) the polled object was last borrowed. + * Gets the time (using the same basis as {@link java.time.Clock#instant()}) the polled object was last borrowed. * - * @return The time the pooled object was last borrowed + * @return The time the pooled object was last borrowed. */ long getLastBorrowTime(); /** * Gets the time that pooled object was last borrowed. * - * @return The last borrowed time for the pooled object formatted as - * {@code yyyy-MM-dd HH:mm:ss Z} + * @return The last borrowed time for the pooled object formatted as {@code yyyy-MM-dd HH:mm:ss Z}. */ String getLastBorrowTimeFormatted(); /** * Gets the stack trace recorded when the pooled object was last borrowed. * - * @return The stack trace showing which code last borrowed the pooled - * object + * @return The stack trace showing which code last borrowed the pooled object. */ String getLastBorrowTrace(); /** - * Gets the time (using the same basis as - * {@link java.time.Clock#instant()})the wrapped object was last returned. + * Gets the time (using the same basis as {@link java.time.Clock#instant()})the wrapped object was last returned. * - * @return The time the object was last returned + * @return The time the object was last returned. */ long getLastReturnTime(); /** * Gets the time that pooled object was last returned. * - * @return The last returned time for the pooled object formatted as - * {@code yyyy-MM-dd HH:mm:ss Z} + * @return The last returned time for the pooled object formatted as {@code yyyy-MM-dd HH:mm:ss Z}. */ String getLastReturnTimeFormatted(); /** - * Gets a String form of the wrapper for debug purposes. The format is - * not fixed and may change at any time. - * - * @return A string representation of the pooled object + * Gets a String form of the wrapper for debug purposes. The format is not fixed and may change at any time. * + * @return A string representation of the pooled object. * @see Object#toString() */ String getPooledObjectToString(); @@ -108,8 +97,7 @@ public interface DefaultPooledObjectInfoMBean { /** * Gets the name of the class of the pooled object. * - * @return The pooled object's class name - * + * @return The pooled object's class name. * @see Class#getName() */ String getPooledObjectType(); diff --git a/src/main/java/org/apache/commons/pool2/impl/EvictionConfig.java b/src/main/java/org/apache/commons/pool3/impl/EvictionConfig.java similarity index 57% rename from src/main/java/org/apache/commons/pool2/impl/EvictionConfig.java rename to src/main/java/org/apache/commons/pool3/impl/EvictionConfig.java index a54868e55..15c9e4c10 100644 --- a/src/main/java/org/apache/commons/pool2/impl/EvictionConfig.java +++ b/src/main/java/org/apache/commons/pool3/impl/EvictionConfig.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.time.Duration; @@ -54,24 +54,6 @@ public EvictionConfig(final Duration idleEvictDuration, final Duration idleSoftE this.minIdle = minIdle; } - /** - * Creates a new eviction configuration with the specified parameters. - * Instances are immutable. - * - * @param poolIdleEvictMillis Expected to be provided by - * {@link BaseGenericObjectPool#getMinEvictableIdleDuration()} - * @param poolIdleSoftEvictMillis Expected to be provided by - * {@link BaseGenericObjectPool#getSoftMinEvictableIdleDuration()} - * @param minIdle Expected to be provided by - * {@link GenericObjectPool#getMinIdle()} or - * {@link GenericKeyedObjectPool#getMinIdlePerKey()} - * @deprecated Use {@link #EvictionConfig(Duration, Duration, int)}. - */ - @Deprecated - public EvictionConfig(final long poolIdleEvictMillis, final long poolIdleSoftEvictMillis, final int minIdle) { - this(Duration.ofMillis(poolIdleEvictMillis), Duration.ofMillis(poolIdleSoftEvictMillis), minIdle); - } - /** * Gets the {@code idleEvictTime} for this eviction configuration * instance. @@ -87,39 +69,6 @@ public Duration getIdleEvictDuration() { return idleEvictDuration; } - /** - * Gets the {@code idleEvictTime} for this eviction configuration - * instance. - *

- * How the evictor behaves based on this value will be determined by the - * configured {@link EvictionPolicy}. - *

- * - * @return The {@code idleEvictTime} in milliseconds - * @deprecated Use {@link #getIdleEvictDuration()}. - */ - @Deprecated - public long getIdleEvictTime() { - return idleEvictDuration.toMillis(); - } - - /** - * Gets the {@code idleEvictTime} for this eviction configuration - * instance. - *

- * How the evictor behaves based on this value will be determined by the - * configured {@link EvictionPolicy}. - *

- * - * @return The {@code idleEvictTime}. - * @since 2.10.0 - * @deprecated Use {@link #getIdleEvictDuration()}. - */ - @Deprecated - public Duration getIdleEvictTimeDuration() { - return idleEvictDuration; - } - /** * Gets the {@code idleSoftEvictTime} for this eviction configuration * instance. @@ -135,38 +84,6 @@ public Duration getIdleSoftEvictDuration() { return idleSoftEvictDuration; } - /** - * Gets the {@code idleSoftEvictTime} for this eviction configuration - * instance. - *

- * How the evictor behaves based on this value will be determined by the - * configured {@link EvictionPolicy}. - *

- * - * @return The (@code idleSoftEvictTime} in milliseconds - * @deprecated Use {@link #getIdleSoftEvictDuration()}. - */ - @Deprecated - public long getIdleSoftEvictTime() { - return idleSoftEvictDuration.toMillis(); - } - - /** - * Gets the {@code idleSoftEvictTime} for this eviction configuration - * instance. - *

- * How the evictor behaves based on this value will be determined by the - * configured {@link EvictionPolicy}. - *

- * - * @return The (@code idleSoftEvictTime} in milliseconds - * @deprecated Use {@link #getIdleSoftEvictDuration()}. - */ - @Deprecated - public Duration getIdleSoftEvictTimeDuration() { - return idleSoftEvictDuration; - } - /** * Gets the {@code minIdle} for this eviction configuration instance. *

diff --git a/src/main/java/org/apache/commons/pool2/impl/EvictionPolicy.java b/src/main/java/org/apache/commons/pool3/impl/EvictionPolicy.java similarity index 86% rename from src/main/java/org/apache/commons/pool2/impl/EvictionPolicy.java rename to src/main/java/org/apache/commons/pool3/impl/EvictionPolicy.java index ee14f58f9..58bc76cfc 100644 --- a/src/main/java/org/apache/commons/pool2/impl/EvictionPolicy.java +++ b/src/main/java/org/apache/commons/pool3/impl/EvictionPolicy.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,9 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; /** * To provide a custom eviction policy (i.e. something other than {@link @@ -24,14 +24,12 @@ * this interface that provides the required eviction policy. * * @param the type of objects in the pool - * * @since 2.0 */ public interface EvictionPolicy { /** - * This method is called to test if an idle object in the pool should be - * evicted or not. + * Tests if an idle object in the pool should be evicted or not. * * @param config The pool configuration settings related to eviction * @param underTest The pooled object being tested for eviction diff --git a/src/main/java/org/apache/commons/pool2/impl/EvictionTimer.java b/src/main/java/org/apache/commons/pool3/impl/EvictionTimer.java similarity index 85% rename from src/main/java/org/apache/commons/pool2/impl/EvictionTimer.java rename to src/main/java/org/apache/commons/pool3/impl/EvictionTimer.java index 6f5c57a9d..c48bb780c 100644 --- a/src/main/java/org/apache/commons/pool2/impl/EvictionTimer.java +++ b/src/main/java/org/apache/commons/pool3/impl/EvictionTimer.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,26 +14,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.lang.ref.WeakReference; import java.security.AccessController; import java.security.PrivilegedAction; import java.time.Duration; import java.util.HashMap; +import java.util.Iterator; import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; - /** * Provides a shared idle object eviction timer for all pools. *

* This class is currently implemented using {@link ScheduledThreadPoolExecutor}. This implementation may change in any * future release. This class keeps track of how many pools are using it. If no pools are using the timer, it is - * cancelled. This prevents a thread being left running which, in application server environments, can lead to memory + * canceled. This prevents a thread being left running which, in application server environments, can lead to memory * leads and/or prevent applications from shutting down or reloading cleanly. *

*

@@ -46,12 +46,12 @@ * * @since 2.0 */ -class EvictionTimer { +final class EvictionTimer { /** * Thread factory that creates a daemon thread, with the context class loader from this class. */ - private static class EvictorThreadFactory implements ThreadFactory { + private static final class EvictorThreadFactory implements ThreadFactory { @Override public Thread newThread(final Runnable runnable) { @@ -70,15 +70,21 @@ public Thread newThread(final Runnable runnable) { * Task that removes references to abandoned tasks and shuts * down the executor if there are no live tasks left. */ - private static class Reaper implements Runnable { + private static final class Reaper implements Runnable { @Override public void run() { synchronized (EvictionTimer.class) { - for (final Entry.Evictor>, WeakRunner.Evictor>> entry : TASK_MAP - .entrySet()) { + /* + * Need to use iterator over TASK_MAP so entries can be removed when iterating without triggering a + * ConcurrentModificationException. + */ + final Iterator.Evictor>, WeakRunner.Evictor>>> iterator = + TASK_MAP.entrySet().iterator(); + while (iterator.hasNext()) { + final Entry.Evictor>, WeakRunner.Evictor>> entry = iterator.next(); if (entry.getKey().get() == null) { executor.remove(entry.getValue()); - TASK_MAP.remove(entry.getKey()); + iterator.remove(); } } if (TASK_MAP.isEmpty() && executor != null) { @@ -95,7 +101,7 @@ public void run() { * no longer reachable, run is no-op. * @param The kind of Runnable. */ - private static class WeakRunner implements Runnable { + private static final class WeakRunner implements Runnable { private final WeakReference ref; @@ -114,13 +120,14 @@ public void run() { if (task != null) { task.run(); } else { - executor.remove(this); - TASK_MAP.remove(ref); + synchronized (EvictionTimer.class) { + executor.remove(this); + TASK_MAP.remove(ref); + } } } } - /** Executor instance */ private static ScheduledThreadPoolExecutor executor; //@GuardedBy("EvictionTimer.class") @@ -132,7 +139,7 @@ public void run() { /** * Removes the specified eviction task from the timer. * - * @param evictor Task to be cancelled. + * @param evictor Task to be canceled. * @param timeout If the associated executor is no longer required, how * long should this thread wait for the executor to * terminate? diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java b/src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPool.java similarity index 95% rename from src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java rename to src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPool.java index e00e60ac5..5c0f3d07b 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.time.Duration; import java.time.Instant; @@ -28,6 +28,7 @@ import java.util.NoSuchElementException; import java.util.Objects; import java.util.TreeMap; +import java.util.concurrent.BlockingDeque; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -38,14 +39,14 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; -import org.apache.commons.pool2.DestroyMode; -import org.apache.commons.pool2.KeyedObjectPool; -import org.apache.commons.pool2.KeyedPooledObjectFactory; -import org.apache.commons.pool2.PoolUtils; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectState; -import org.apache.commons.pool2.SwallowedExceptionListener; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.DestroyMode; +import org.apache.commons.pool3.KeyedObjectPool; +import org.apache.commons.pool3.KeyedPooledObjectFactory; +import org.apache.commons.pool3.PoolUtils; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectState; +import org.apache.commons.pool3.SwallowedExceptionListener; +import org.apache.commons.pool3.UsageTracking; /** * A configurable {@code KeyedObjectPool} implementation. @@ -83,11 +84,9 @@ *

* * @see GenericObjectPool - * * @param The type of keys maintained by this pool. * @param Type of element pooled in this pool. * @param Type of exception thrown in this pool. - * * @since 2.0 */ public class GenericKeyedObjectPool extends BaseGenericObjectPool @@ -98,7 +97,7 @@ public class GenericKeyedObjectPool extends BaseGener * * @param type of objects in the pool */ - private static class ObjectDeque { + private static final class ObjectDeque { private final LinkedBlockingDeque> idleObjects; @@ -106,7 +105,7 @@ private static class ObjectDeque { * Number of instances created - number destroyed. * Invariant: createCount <= maxTotalPerKey */ - private final AtomicInteger createCount = new AtomicInteger(0); + private final AtomicInteger createCount = new AtomicInteger(); private long makeObjectCount; private final Object makeObjectCountLock = new Object(); @@ -131,16 +130,16 @@ private static class ObjectDeque { * @param fairness true means client threads waiting to borrow / return instances * will be served as if waiting in a FIFO queue. */ - public ObjectDeque(final boolean fairness) { + ObjectDeque(final boolean fairness) { idleObjects = new LinkedBlockingDeque<>(fairness); } /** * Gets all the objects for the current key. * - * @return All the objects + * @return All the objects. */ - public Map, PooledObject> getAllObjects() { + Map, PooledObject> getAllObjects() { return allObjects; } @@ -148,27 +147,27 @@ public Map, PooledObject> getAllObjects() { * Gets the number of instances created - number destroyed. * Should always be less than or equal to maxTotalPerKey. * - * @return The net instance addition count for this deque + * @return The net instance addition count for this deque. */ - public AtomicInteger getCreateCount() { + AtomicInteger getCreateCount() { return createCount; } /** * Gets the idle objects for the current key. * - * @return The idle objects + * @return The idle objects. */ - public LinkedBlockingDeque> getIdleObjects() { + LinkedBlockingDeque> getIdleObjects() { return idleObjects; } /** * Gets the number of threads with an interest registered in this key. * - * @return The number of threads with a registered interest in this key + * @return The number of threads with a registered interest in this key. */ - public AtomicLong getNumInterested() { + AtomicLong getNumInterested() { return numInterested; } @@ -193,7 +192,7 @@ public String toString() { // JMX specific attributes private static final String ONAME_BASE = - "org.apache.commons.pool2:type=GenericKeyedObjectPool,name="; + "org.apache.commons.pool3:type=GenericKeyedObjectPool,name="; private volatile int maxIdlePerKey = GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY; @@ -201,7 +200,6 @@ public String toString() { private volatile int minIdlePerKey = GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY; - private volatile int maxTotalPerKey = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; @@ -210,16 +208,21 @@ public String toString() { private final boolean fairness; /* - * My hash of sub-pools (ObjectQueue). The list of keys must be kept + * My hash of sub-pools (ObjectQueue). The list of keys must be kept * in step with {@link #poolKeyList} using {@link #keyLock} to ensure any * changes to the list of current keys is made in a thread-safe manner. + * + * Correct operation of the pool requires that a Map implementation is used that + * supports concurrent read and write (e.g. ensureMinIdle() iterates over the key set + * while other threads may be adding or removing keys) therefore explicitly define + * this field as ConcurrentHashMap rather than Map. */ - private final Map> poolMap = + private final ConcurrentHashMap> poolMap = new ConcurrentHashMap<>(); // @GuardedBy("keyLock") for write access (and some read access) /* * List of pool keys - used to control eviction order. The list of keys - * must be kept in step with {@link #poolMap} using {@link #keyLock} + * must be kept in step with {@link #poolMap} using {@link #keyLock} * to ensure any changes to the list of current keys is made in a * thread-safe manner. */ @@ -233,11 +236,10 @@ public String toString() { * {@link #maxTotal} but there will never be more than {@link #maxTotal} * created at any one time. */ - private final AtomicInteger numTotal = new AtomicInteger(0); + private final AtomicInteger numTotal = new AtomicInteger(); private Iterator evictionKeyIterator; // @GuardedBy("evictionLock") - private K evictionKey; // @GuardedBy("evictionLock") /** @@ -300,13 +302,12 @@ public GenericKeyedObjectPool(final KeyedPooledObjectFactory factory, * * @param key The key to associate with the idle object * @param p The wrapped object to add. - * * @throws E If the associated factory fails to passivate the object */ private void addIdleObject(final K key, final PooledObject p) throws E { - if (!PooledObject.isNull(p)) { + if (PooledObject.nonNull(p)) { factory.passivateObject(key, p); - final LinkedBlockingDeque> idleObjects = poolMap.get(key).getIdleObjects(); + final BlockingDeque> idleObjects = poolMap.get(key).getIdleObjects(); if (getLifo()) { idleObjects.addFirst(p); } else { @@ -330,7 +331,6 @@ private void addIdleObject(final K key, final PooledObject p) throws E { *

* * @param key the key a new instance should be added to - * * @throws E when {@link KeyedPooledObjectFactory#makeObject} * fails. */ @@ -411,7 +411,6 @@ public T borrowObject(final K key) throws E { * to become available * * @return object instance from the keyed pool - * * @throws NoSuchElementException if a keyed object instance cannot be * returned because the pool is exhausted. * @@ -443,7 +442,7 @@ public T borrowObject(final K key, final long borrowMaxWaitMillis) throws E { p = objectDeque.getIdleObjects().pollFirst(); if (p == null) { p = create(key); - if (!PooledObject.isNull(p)) { + if (PooledObject.nonNull(p)) { create = true; } } @@ -525,7 +524,6 @@ public T borrowObject(final K key, final long borrowMaxWaitMillis) throws E { * on the maximum number of objects either per key or totally. * * @param objectDeque The set of objects to check - * * @return The number of new objects to create */ private int calculateDeficit(final ObjectDeque objectDeque) { @@ -620,7 +618,7 @@ public void clear(final K key, final boolean reuseCapacity) { final ObjectDeque objectDeque = register(key); int freedCapacity = 0; try { - final LinkedBlockingDeque> idleObjects = objectDeque.getIdleObjects(); + final BlockingDeque> idleObjects = objectDeque.getIdleObjects(); PooledObject p = idleObjects.poll(); while (p != null) { try { @@ -649,11 +647,9 @@ public void clearOldest() { // build sorted map of idle objects final TreeMap, K> map = new TreeMap<>(); - poolMap.forEach((key, value) -> { - // Each item into the map using the PooledObject object as the - // key. It then gets sorted based on the idle time - value.getIdleObjects().forEach(p -> map.put(p, key)); - }); + // Each item into the map using the PooledObject object as the + // key. It then gets sorted based on the idle time + poolMap.forEach((key, value) -> value.getIdleObjects().forEach(p -> map.put(p, key))); // Now iterate created map and kill the first 15% plus one to account // for zero @@ -662,9 +658,9 @@ public void clearOldest() { while (iter.hasNext() && itemsToRemove > 0) { final Entry, K> entry = iter.next(); - // kind of backwards on naming. In the map, each key is the + // kind of backwards on naming. In the map, each key is the // PooledObject because it has the ordering with the timestamp - // value. Each value that the key references is the key of the + // value. Each value that the key references is the key of the // list it belongs to. final K key = entry.getValue(); final PooledObject p = entry.getKey(); @@ -681,7 +677,6 @@ public void clearOldest() { } } - /** * Closes the keyed object pool. Once the pool is closed, * {@link #borrowObject(Object)} will fail with IllegalStateException, but @@ -714,21 +709,18 @@ public void close() { jmxUnregister(); // Release any threads that were waiting for an object - poolMap.values().forEach(e -> e.getIdleObjects().interuptTakeWaiters()); + poolMap.values().forEach(e -> e.getIdleObjects().interruptTakeWaiters()); // This clear cleans up the keys now any waiting threads have been // interrupted clear(); } } - /** * Creates a new pooled object or null. * * @param key Key associated with new pooled object. - * * @return The new, wrapped pooled object. May return null. - * * @throws E If the objection creation fails. */ private PooledObject create(final K key) throws E { @@ -831,7 +823,7 @@ private PooledObject create(final K key) throws E { } createdCount.incrementAndGet(); - objectDeque.getAllObjects().put(new IdentityWrapper<>(p.getObject()), p); + objectDeque.getAllObjects().put(IdentityWrapper.unwrap(p), p); return p; } @@ -875,7 +867,6 @@ private void deregister(final K k) { * @param always Should the object be destroyed even if it is not currently * in the set of idle objects for the given key * @param destroyMode DestroyMode context provided to the factory - * * @return {@code true} if the object was destroyed, otherwise {@code false} * @throws E If the object destruction failed */ @@ -895,7 +886,7 @@ private boolean destroy(final K key, final PooledObject toDestroy, final bool } } if (isIdle || always) { - objectDeque.getAllObjects().remove(new IdentityWrapper<>(toDestroy.getObject())); + objectDeque.getAllObjects().remove(IdentityWrapper.unwrap(toDestroy)); toDestroy.invalidate(); try { @@ -913,7 +904,6 @@ private boolean destroy(final K key, final PooledObject toDestroy, final bool } } - @Override void ensureMinIdle() throws E { final int minIdlePerKeySave = getMinIdlePerKey(); @@ -939,7 +929,6 @@ void ensureMinIdle() throws E { *

* * @param key The key to check for idle objects - * * @throws E If a new object is required and cannot be created */ private void ensureMinIdle(final K key) throws E { @@ -1114,7 +1103,6 @@ public void evict() throws E { } } - /** * Gets a reference to the factory used to create, destroy and validate * the objects used by this pool. @@ -1163,7 +1151,6 @@ public int getMaxIdlePerKey() { * is said to be exhausted. A negative value indicates no limit. * * @return the limit on the number of active instances per key - * * @see #setMaxTotalPerKey */ @Override @@ -1185,8 +1172,7 @@ public int getMaxTotalPerKey() { *

* * @return minimum size of the each keyed pool - * - * @see #setTimeBetweenEvictionRunsMillis + * @see #setDurationBetweenEvictionRuns(Duration) */ @Override public int getMinIdlePerKey() { @@ -1305,7 +1291,6 @@ private boolean hasBorrowWaiters() { * * @param key pool key * @param obj instance to invalidate - * * @throws E if an exception occurs destroying the * object * @throws IllegalStateException if obj does not belong to the pool @@ -1326,7 +1311,6 @@ public void invalidateObject(final K key, final T obj) throws E { * @param key pool key * @param obj instance to invalidate * @param destroyMode DestroyMode context provided to factory - * * @throws E if an exception occurs destroying the * object * @throws IllegalStateException if obj does not belong to the pool @@ -1362,7 +1346,7 @@ public void invalidateObject(final K key, final T obj, final DestroyMode destroy */ @Override public Map> listAllObjects() { - return poolMap.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().toString(), + return poolMap.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().getAllObjects().values().stream().map(DefaultPooledObjectInfo::new).collect(Collectors.toList()))); } @@ -1370,8 +1354,7 @@ public Map> listAllObjects() { * Registers a key for pool control and ensures that * {@link #getMinIdlePerKey()} idle instances are created. * - * @param key - The key to register for pool control. - * + * @param key The key to register for pool control. * @throws E If the associated factory throws an exception */ public void preparePool(final K key) throws E { @@ -1389,7 +1372,6 @@ public void preparePool(final K key) throws E { *

* * @param k The key to register - * * @return The objects currently associated with the given key. If this * method returns without throwing an exception then it will never * return null. @@ -1405,7 +1387,7 @@ private ObjectDeque register(final K k) { lock.unlock(); lock = keyLock.writeLock(); lock.lock(); - final AtomicBoolean allocated = new AtomicBoolean(); + final AtomicBoolean allocated = new AtomicBoolean(); objectDeque = poolMap.computeIfAbsent(k, key -> { allocated.set(true); final ObjectDeque deque = new ObjectDeque<>(fairness); @@ -1472,7 +1454,6 @@ private void removeAbandoned(final AbandonedConfig abandonedConfig) { * * @param key pool key * @param obj instance to return to the keyed pool - * * @throws IllegalStateException if an object is returned to the pool that * was not borrowed from it or if an object is * returned to the pool multiple times @@ -1525,7 +1506,7 @@ public void returnObject(final K key, final T obj) { } final int maxIdle = getMaxIdlePerKey(); - final LinkedBlockingDeque> idleObjects = objectDeque.getIdleObjects(); + final BlockingDeque> idleObjects = objectDeque.getIdleObjects(); if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) { try { @@ -1570,9 +1551,8 @@ public void returnObject(final K key, final T obj) { private void reuseCapacity() { final int maxTotalPerKeySave = getMaxTotalPerKey(); int maxQueueLength = 0; - LinkedBlockingDeque> mostLoadedPool = null; + BlockingDeque> mostLoadedPool = null; K mostLoadedKey = null; - // Find the most loaded pool that could take a new instance for (final Map.Entry> entry : poolMap.entrySet()) { final K k = entry.getKey(); @@ -1584,7 +1564,6 @@ private void reuseCapacity() { mostLoadedKey = k; } } - // Attempt to add an instance to the most loaded pool. if (mostLoadedPool != null) { register(mostLoadedKey); @@ -1618,7 +1597,6 @@ private void reuseCapacity(final int newCapacity) { * Sets the configuration. * * @param conf the new configuration to use. This is used by value. - * * @see GenericKeyedObjectPoolConfig */ public void setConfig(final GenericKeyedObjectPoolConfig conf) { @@ -1655,7 +1633,6 @@ public void setMaxIdlePerKey(final int maxIdlePerKey) { * is said to be exhausted. A negative value indicates no limit. * * @param maxTotalPerKey the limit on the number of active instances per key - * * @see #getMaxTotalPerKey */ public void setMaxTotalPerKey(final int maxTotalPerKey) { @@ -1676,10 +1653,9 @@ public void setMaxTotalPerKey(final int maxTotalPerKey) { *

* * @param minIdlePerKey The minimum size of the each keyed pool - * * @see #getMinIdlePerKey() * @see #getMaxIdlePerKey() - * @see #setTimeBetweenEvictionRuns(Duration) + * @see #setDurationBetweenEvictionRuns(Duration) */ public void setMinIdlePerKey(final int minIdlePerKey) { this.minIdlePerKey = minIdlePerKey; diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolConfig.java b/src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPoolConfig.java similarity index 89% rename from src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolConfig.java rename to src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPoolConfig.java index e9a7a29ef..3e88b0fdb 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolConfig.java +++ b/src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPoolConfig.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; /** * A simple structure encapsulating the configuration for a @@ -54,7 +54,6 @@ public class GenericKeyedObjectPoolConfig extends BaseObjectPoolConfig { */ public static final int DEFAULT_MAX_IDLE_PER_KEY = 8; - private int minIdlePerKey = DEFAULT_MIN_IDLE_PER_KEY; private int maxIdlePerKey = DEFAULT_MAX_IDLE_PER_KEY; @@ -80,7 +79,7 @@ public GenericKeyedObjectPoolConfig clone() { } /** - * Get the value for the {@code maxIdlePerKey} configuration attribute + * Gets the value for the {@code maxIdlePerKey} configuration attribute * for pools created with this configuration instance. * * @return The current setting of {@code maxIdlePerKey} for this @@ -93,7 +92,7 @@ public int getMaxIdlePerKey() { } /** - * Get the value for the {@code maxTotal} configuration attribute + * Gets the value for the {@code maxTotal} configuration attribute * for pools created with this configuration instance. * * @return The current setting of {@code maxTotal} for this @@ -106,7 +105,7 @@ public int getMaxTotal() { } /** - * Get the value for the {@code maxTotalPerKey} configuration attribute + * Gets the value for the {@code maxTotalPerKey} configuration attribute * for pools created with this configuration instance. * * @return The current setting of {@code maxTotalPerKey} for this @@ -119,7 +118,7 @@ public int getMaxTotalPerKey() { } /** - * Get the value for the {@code minIdlePerKey} configuration attribute + * Gets the value for the {@code minIdlePerKey} configuration attribute * for pools created with this configuration instance. * * @return The current setting of {@code minIdlePerKey} for this @@ -132,7 +131,7 @@ public int getMinIdlePerKey() { } /** - * Set the value for the {@code maxIdlePerKey} configuration attribute for + * Sets the value for the {@code maxIdlePerKey} configuration attribute for * pools created with this configuration instance. * * @param maxIdlePerKey The new setting of {@code maxIdlePerKey} @@ -145,7 +144,7 @@ public void setMaxIdlePerKey(final int maxIdlePerKey) { } /** - * Set the value for the {@code maxTotal} configuration attribute for + * Sets the value for the {@code maxTotal} configuration attribute for * pools created with this configuration instance. * * @param maxTotal The new setting of {@code maxTotal} @@ -158,7 +157,7 @@ public void setMaxTotal(final int maxTotal) { } /** - * Set the value for the {@code maxTotalPerKey} configuration attribute for + * Sets the value for the {@code maxTotalPerKey} configuration attribute for * pools created with this configuration instance. * * @param maxTotalPerKey The new setting of {@code maxTotalPerKey} @@ -171,7 +170,7 @@ public void setMaxTotalPerKey(final int maxTotalPerKey) { } /** - * Set the value for the {@code minIdlePerKey} configuration attribute for + * Sets the value for the {@code minIdlePerKey} configuration attribute for * pools created with this configuration instance. * * @param minIdlePerKey The new setting of {@code minIdlePerKey} diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMXBean.java b/src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPoolMXBean.java similarity index 67% rename from src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMXBean.java rename to src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPoolMXBean.java index 884a42ba1..97556700f 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPoolMXBean.java +++ b/src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPoolMXBean.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,23 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.util.List; import java.util.Map; /** * Defines the methods that will be made available via JMX. - * - * NOTE: This interface exists only to define those attributes and methods that - * will be made available via JMX. It must not be implemented by clients - * as it is subject to change between major, minor and patch version - * releases of commons pool. Clients that implement this interface may - * not, therefore, be able to upgrade to a new minor or patch release - * without requiring code changes. + *

Note

+ *

+ * This interface exists only to define those attributes and methods that will be made available via JMX. It must not be implemented by clients as it is subject + * to change between major, minor and patch version releases of commons pool. Clients that implement this interface may not, therefore, be able to upgrade to a + * new minor or patch release without requiring code changes. + *

* * @param The type of keys maintained by the pool. - * * @since 2.0 */ public interface GenericKeyedObjectPoolMXBean { @@ -38,62 +36,72 @@ public interface GenericKeyedObjectPoolMXBean { // Expose getters for configuration settings /** - * See {@link GenericKeyedObjectPool#getBlockWhenExhausted()} - * @return See {@link GenericKeyedObjectPool#getBlockWhenExhausted()} + * See {@link GenericKeyedObjectPool#getBlockWhenExhausted()}. + * + * @return See {@link GenericKeyedObjectPool#getBlockWhenExhausted()}. */ boolean getBlockWhenExhausted(); /** - * See {@link GenericKeyedObjectPool#getBorrowedCount()} - * @return See {@link GenericKeyedObjectPool#getBorrowedCount()} + * See {@link GenericKeyedObjectPool#getBorrowedCount()}. + * + * @return See {@link GenericKeyedObjectPool#getBorrowedCount()}. */ long getBorrowedCount(); /** - * See {@link GenericKeyedObjectPool#getCreatedCount()} - * @return See {@link GenericKeyedObjectPool#getCreatedCount()} + * See {@link GenericKeyedObjectPool#getCreatedCount()}. + * + * @return See {@link GenericKeyedObjectPool#getCreatedCount()}. */ long getCreatedCount(); /** - * See {@link GenericKeyedObjectPool#getCreationStackTrace()} - * @return See {@link GenericKeyedObjectPool#getCreationStackTrace()} + * See {@link GenericKeyedObjectPool#getCreationStackTrace()}. + * + * @return See {@link GenericKeyedObjectPool#getCreationStackTrace()}. */ String getCreationStackTrace(); /** - * See {@link GenericKeyedObjectPool#getDestroyedByBorrowValidationCount()} - * @return See {@link GenericKeyedObjectPool#getDestroyedByBorrowValidationCount()} + * See {@link GenericKeyedObjectPool#getDestroyedByBorrowValidationCount()}. + * + * @return See {@link GenericKeyedObjectPool#getDestroyedByBorrowValidationCount()}. */ long getDestroyedByBorrowValidationCount(); /** - * See {@link GenericKeyedObjectPool#getDestroyedByEvictorCount()} - * @return See {@link GenericKeyedObjectPool#getDestroyedByEvictorCount()} + * See {@link GenericKeyedObjectPool#getDestroyedByEvictorCount()}. + * + * @return See {@link GenericKeyedObjectPool#getDestroyedByEvictorCount()}. */ long getDestroyedByEvictorCount(); /** - * See {@link GenericKeyedObjectPool#getDestroyedCount()} - * @return See {@link GenericKeyedObjectPool#getDestroyedCount()} + * See {@link GenericKeyedObjectPool#getDestroyedCount()}. + * + * @return See {@link GenericKeyedObjectPool#getDestroyedCount()}. */ long getDestroyedCount(); /** - * See {@link GenericKeyedObjectPool#getFairness()} - * @return See {@link GenericKeyedObjectPool#getFairness()} + * See {@link GenericKeyedObjectPool#getFairness()}. + * + * @return See {@link GenericKeyedObjectPool#getFairness()}. */ boolean getFairness(); /** - * See {@link GenericKeyedObjectPool#getLifo()} - * @return See {@link GenericKeyedObjectPool#getLifo()} + * See {@link GenericKeyedObjectPool#getLifo()}. + * + * @return See {@link GenericKeyedObjectPool#getLifo()}. */ boolean getLifo(); /** - * See {@link GenericKeyedObjectPool#getLogAbandoned()} - * @return See {@link GenericKeyedObjectPool#getLogAbandoned()} + * See {@link GenericKeyedObjectPool#getLogAbandoned()}. + * + * @return See {@link GenericKeyedObjectPool#getLogAbandoned()}. * @since 2.10.0 */ default boolean getLogAbandoned() { @@ -101,106 +109,123 @@ default boolean getLogAbandoned() { } /** - * See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()} - * @return See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()} + * See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()}. + * + * @return See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()}. */ long getMaxBorrowWaitTimeMillis(); /** - * See {@link GenericKeyedObjectPool#getMaxIdlePerKey()} - * @return See {@link GenericKeyedObjectPool#getMaxIdlePerKey()} + * See {@link GenericKeyedObjectPool#getMaxIdlePerKey()}. + * + * @return See {@link GenericKeyedObjectPool#getMaxIdlePerKey()}. */ int getMaxIdlePerKey(); /** - * See {@link GenericKeyedObjectPool#getMaxTotal()} - * @return See {@link GenericKeyedObjectPool#getMaxTotal()} + * See {@link GenericKeyedObjectPool#getMaxTotal()}. + * + * @return See {@link GenericKeyedObjectPool#getMaxTotal()}. */ int getMaxTotal(); /** - * See {@link GenericKeyedObjectPool#getMaxTotalPerKey()} - * @return See {@link GenericKeyedObjectPool#getMaxTotalPerKey()} + * See {@link GenericKeyedObjectPool#getMaxTotalPerKey()}. + * + * @return See {@link GenericKeyedObjectPool#getMaxTotalPerKey()}. */ int getMaxTotalPerKey(); /** - * See {@link GenericKeyedObjectPool#getMaxWaitDuration()} - * @return See {@link GenericKeyedObjectPool#getMaxWaitDuration()} + * See {@link GenericKeyedObjectPool#getMaxWaitDuration()}. + * + * @return See {@link GenericKeyedObjectPool#getMaxWaitDuration()}. */ long getMaxWaitMillis(); /** - * See {@link GenericKeyedObjectPool#getMeanActiveTimeMillis()} - * @return See {@link GenericKeyedObjectPool#getMeanActiveTimeMillis()} + * See {@link GenericKeyedObjectPool#getMeanActiveTimeMillis()}. + * + * @return See {@link GenericKeyedObjectPool#getMeanActiveTimeMillis()}. */ long getMeanActiveTimeMillis(); /** - * See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()} - * @return See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()} + * See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()}. + * + * @return See {@link GenericKeyedObjectPool#getMaxBorrowWaitTimeMillis()}. */ long getMeanBorrowWaitTimeMillis(); /** - * See {@link GenericKeyedObjectPool#getMeanIdleTimeMillis()} - * @return See {@link GenericKeyedObjectPool#getMeanIdleTimeMillis()} + * See {@link GenericKeyedObjectPool#getMeanIdleTimeMillis()}. + * + * @return See {@link GenericKeyedObjectPool#getMeanIdleTimeMillis()}. */ long getMeanIdleTimeMillis(); /** - * See {@link GenericKeyedObjectPool#getMinEvictableIdleDuration()} - * @return See {@link GenericKeyedObjectPool#getMinEvictableIdleDuration()} + * See {@link GenericKeyedObjectPool#getMinEvictableIdleDuration()}. + * + * @return See {@link GenericKeyedObjectPool#getMinEvictableIdleDuration()}. */ long getMinEvictableIdleTimeMillis(); // Expose getters for monitoring attributes /** - * See {@link GenericKeyedObjectPool#getMinIdlePerKey()} - * @return See {@link GenericKeyedObjectPool#getMinIdlePerKey()} + * See {@link GenericKeyedObjectPool#getMinIdlePerKey()}. + * + * @return See {@link GenericKeyedObjectPool#getMinIdlePerKey()}. */ int getMinIdlePerKey(); /** - * See {@link GenericKeyedObjectPool#getNumActive()} - * @return See {@link GenericKeyedObjectPool#getNumActive()} + * See {@link GenericKeyedObjectPool#getNumActive()}. + * + * @return See {@link GenericKeyedObjectPool#getNumActive()}. */ int getNumActive(); /** - * See {@link GenericKeyedObjectPool#getNumActivePerKey()} - * @return See {@link GenericKeyedObjectPool#getNumActivePerKey()} + * See {@link GenericKeyedObjectPool#getNumActivePerKey()}. + * + * @return See {@link GenericKeyedObjectPool#getNumActivePerKey()}. */ Map getNumActivePerKey(); /** - * See {@link GenericKeyedObjectPool#getNumIdle()} - * @return See {@link GenericKeyedObjectPool#getNumIdle()} + * See {@link GenericKeyedObjectPool#getNumIdle()}. + * + * @return See {@link GenericKeyedObjectPool#getNumIdle()}. */ int getNumIdle(); /** - * See {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun()} - * @return See {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun()} + * See {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun()}. + * + * @return See {@link GenericKeyedObjectPool#getNumTestsPerEvictionRun()}. */ int getNumTestsPerEvictionRun(); /** - * See {@link GenericKeyedObjectPool#getNumWaiters()} - * @return See {@link GenericKeyedObjectPool#getNumWaiters()} + * See {@link GenericKeyedObjectPool#getNumWaiters()}. + * + * @return See {@link GenericKeyedObjectPool#getNumWaiters()}. */ int getNumWaiters(); /** - * See {@link GenericKeyedObjectPool#getNumWaitersByKey()} - * @return See {@link GenericKeyedObjectPool#getNumWaitersByKey()} + * See {@link GenericKeyedObjectPool#getNumWaitersByKey()}. + * + * @return See {@link GenericKeyedObjectPool#getNumWaitersByKey()}. */ Map getNumWaitersByKey(); /** - * See {@link GenericKeyedObjectPool#getRemoveAbandonedOnBorrow()} - * @return See {@link GenericKeyedObjectPool#getRemoveAbandonedOnBorrow()} + * See {@link GenericKeyedObjectPool#getRemoveAbandonedOnBorrow()}. + * + * @return See {@link GenericKeyedObjectPool#getRemoveAbandonedOnBorrow()}. * @since 2.10.0 */ default boolean getRemoveAbandonedOnBorrow() { @@ -208,17 +233,19 @@ default boolean getRemoveAbandonedOnBorrow() { } /** - * See {@link GenericKeyedObjectPool#getRemoveAbandonedOnMaintenance()} - * @return See {@link GenericKeyedObjectPool#getRemoveAbandonedOnMaintenance()} + * See {@link GenericKeyedObjectPool#getRemoveAbandonedOnMaintenance()}. + * + * @return See {@link GenericKeyedObjectPool#getRemoveAbandonedOnMaintenance()}. * @since 2.10.0 */ - default boolean getRemoveAbandonedOnMaintenance() { + default boolean getRemoveAbandonedOnMaintenance() { return false; } /** - * See {@link GenericKeyedObjectPool#getRemoveAbandonedTimeoutDuration()} - * @return See {@link GenericKeyedObjectPool#getRemoveAbandonedTimeoutDuration()} + * See {@link GenericKeyedObjectPool#getRemoveAbandonedTimeoutDuration()}. + * + * @return See {@link GenericKeyedObjectPool#getRemoveAbandonedTimeoutDuration()}. * @since 2.10.0 */ default int getRemoveAbandonedTimeout() { @@ -226,45 +253,52 @@ default int getRemoveAbandonedTimeout() { } /** - * See {@link GenericKeyedObjectPool#getReturnedCount()} - * @return See {@link GenericKeyedObjectPool#getReturnedCount()} + * See {@link GenericKeyedObjectPool#getReturnedCount()}. + * + * @return See {@link GenericKeyedObjectPool#getReturnedCount()}. */ long getReturnedCount(); /** - * See {@link GenericKeyedObjectPool#getTestOnBorrow()} - * @return See {@link GenericKeyedObjectPool#getTestOnBorrow()} + * See {@link GenericKeyedObjectPool#getTestOnBorrow()}. + * + * @return See {@link GenericKeyedObjectPool#getTestOnBorrow()}. */ boolean getTestOnBorrow(); /** - * See {@link GenericKeyedObjectPool#getTestOnCreate()} - * @return See {@link GenericKeyedObjectPool#getTestOnCreate()} + * See {@link GenericKeyedObjectPool#getTestOnCreate()}. + * + * @return See {@link GenericKeyedObjectPool#getTestOnCreate()}. * @since 2.2 */ boolean getTestOnCreate(); /** - * See {@link GenericKeyedObjectPool#getTestOnReturn()} - * @return See {@link GenericKeyedObjectPool#getTestOnReturn()} + * See {@link GenericKeyedObjectPool#getTestOnReturn()}. + * + * @return See {@link GenericKeyedObjectPool#getTestOnReturn()}. */ boolean getTestOnReturn(); /** - * See {@link GenericKeyedObjectPool#getTestWhileIdle()} - * @return See {@link GenericKeyedObjectPool#getTestWhileIdle()} + * See {@link GenericKeyedObjectPool#getTestWhileIdle()}. + * + * @return See {@link GenericKeyedObjectPool#getTestWhileIdle()}. */ boolean getTestWhileIdle(); /** * See {@link GenericKeyedObjectPool#getDurationBetweenEvictionRuns} - * @return See {@link GenericKeyedObjectPool#getDurationBetweenEvictionRuns()} + * + * @return See {@link GenericKeyedObjectPool#getDurationBetweenEvictionRuns()}. */ long getTimeBetweenEvictionRunsMillis(); /** - * See {@link GenericKeyedObjectPool#isAbandonedConfig()} - * @return See {@link GenericKeyedObjectPool#isAbandonedConfig()} + * See {@link GenericKeyedObjectPool#isAbandonedConfig()}. + * + * @return See {@link GenericKeyedObjectPool#isAbandonedConfig()}. * @since 2.10.0 */ default boolean isAbandonedConfig() { @@ -272,14 +306,16 @@ default boolean isAbandonedConfig() { } /** - * See {@link GenericKeyedObjectPool#isClosed()} - * @return See {@link GenericKeyedObjectPool#isClosed()} + * See {@link GenericKeyedObjectPool#isClosed()}. + * + * @return See {@link GenericKeyedObjectPool#isClosed()}. */ boolean isClosed(); /** - * See {@link GenericKeyedObjectPool#listAllObjects()} - * @return See {@link GenericKeyedObjectPool#listAllObjects()} + * See {@link GenericKeyedObjectPool#listAllObjects()}. + * + * @return See {@link GenericKeyedObjectPool#listAllObjects()}. */ Map> listAllObjects(); } diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java b/src/main/java/org/apache/commons/pool3/impl/GenericObjectPool.java similarity index 92% rename from src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java rename to src/main/java/org/apache/commons/pool3/impl/GenericObjectPool.java index dbc1ef7a1..284052933 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/impl/GenericObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.time.Duration; import java.time.Instant; @@ -25,15 +25,15 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; -import org.apache.commons.pool2.DestroyMode; -import org.apache.commons.pool2.ObjectPool; -import org.apache.commons.pool2.PoolUtils; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectFactory; -import org.apache.commons.pool2.PooledObjectState; -import org.apache.commons.pool2.SwallowedExceptionListener; -import org.apache.commons.pool2.TrackedUse; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.DestroyMode; +import org.apache.commons.pool3.ObjectPool; +import org.apache.commons.pool3.PoolUtils; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; +import org.apache.commons.pool3.PooledObjectState; +import org.apache.commons.pool3.SwallowedExceptionListener; +import org.apache.commons.pool3.TrackedUse; +import org.apache.commons.pool3.UsageTracking; /** * A configurable {@link ObjectPool} implementation. @@ -74,10 +74,8 @@ *

* * @see GenericKeyedObjectPool - * * @param Type of element pooled in this pool. * @param Type of exception thrown in this pool. - * * @since 2.0 */ public class GenericObjectPool extends BaseGenericObjectPool @@ -85,10 +83,12 @@ public class GenericObjectPool extends BaseGenericObject // JMX specific attributes private static final String ONAME_BASE = - "org.apache.commons.pool2:type=GenericObjectPool,name="; + "org.apache.commons.pool3:type=GenericObjectPool,name="; private static void wait(final Object obj, final Duration duration) throws InterruptedException { - obj.wait(duration.toMillis(), duration.getNano() % 1_000_000); + if (!duration.isNegative()) { + obj.wait(duration.toMillis(), duration.getNano() % 1_000_000); + } } private volatile String factoryType; @@ -100,6 +100,8 @@ private static void wait(final Object obj, final Duration duration) throws Inter private final PooledObjectFactory factory; /* + * TODO The references to _maxActive are from 1.x and need to be updated. + * * All of the objects currently associated with this pool in any state. It * excludes objects that have been destroyed. The size of * {@link #allObjects} will always be less than or equal to {@link @@ -109,6 +111,8 @@ private static void wait(final Object obj, final Duration duration) throws Inter private final ConcurrentHashMap, PooledObject> allObjects = new ConcurrentHashMap<>(); /* + * TODO The references to _maxActive are from 1.x and need to be updated. + * * The combined count of the currently created objects and those in the * process of being created. Under load, it may exceed {@link #_maxActive} * if multiple threads try and create a new object at the same time but @@ -186,11 +190,10 @@ public GenericObjectPool(final PooledObjectFactory factory, * is null, this is a no-op (no exception, but no impact on the pool). * * @param p The object to make idle - * * @throws E If the factory fails to passivate the object */ private void addIdleObject(final PooledObject p) throws E { - if (!PooledObject.isNull(p)) { + if (PooledObject.nonNull(p)) { factory.passivateObject(p); if (getLifo()) { idleObjects.addFirst(p); @@ -212,7 +215,7 @@ private void addIdleObject(final PooledObject p) throws E { * is thrown. If there is no factory set (factory == null), an {@code IllegalStateException} * is thrown. *

- * + * */ @Override public void addObject() throws E { @@ -220,7 +223,7 @@ public void addObject() throws E { if (factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } - addIdleObject(create()); + addIdleObject(create(getMaxWaitDuration())); } /** @@ -274,53 +277,48 @@ public T borrowObject() throws E { * available instances in request arrival order. *

* - * @param borrowMaxWaitDuration The time to wait for an object - * to become available - * + * @param maxWaitDuration The time to wait for an object to become available, not null. * @return object instance from the pool * @throws NoSuchElementException if an instance cannot be returned * @throws E if an object instance cannot be returned due to an error * @since 2.10.0 */ - public T borrowObject(final Duration borrowMaxWaitDuration) throws E { + public T borrowObject(final Duration maxWaitDuration) throws E { assertOpen(); - + final Instant startInstant = Instant.now(); + final boolean negativeDuration = maxWaitDuration.isNegative(); + Duration remainingWaitDuration = maxWaitDuration; final AbandonedConfig ac = this.abandonedConfig; - if (ac != null && ac.getRemoveAbandonedOnBorrow() && getNumIdle() < 2 && - getNumActive() > getMaxTotal() - 3) { + if (ac != null && ac.getRemoveAbandonedOnBorrow() && getNumIdle() < 2 && getNumActive() > getMaxTotal() - 3) { removeAbandoned(ac); } - PooledObject p = null; - // Get local copy of current config so it is consistent for entire // method execution final boolean blockWhenExhausted = getBlockWhenExhausted(); - boolean create; - final Instant waitTime = Instant.now(); - while (p == null) { + remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant)); create = false; p = idleObjects.pollFirst(); if (p == null) { - p = create(); - if (!PooledObject.isNull(p)) { + p = create(remainingWaitDuration); + if (PooledObject.nonNull(p)) { create = true; } } if (blockWhenExhausted) { if (PooledObject.isNull(p)) { try { - p = borrowMaxWaitDuration.isNegative() ? idleObjects.takeFirst() : idleObjects.pollFirst(borrowMaxWaitDuration); + remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant)); + p = negativeDuration ? idleObjects.takeFirst() : idleObjects.pollFirst(maxWaitDuration); } catch (final InterruptedException e) { // Don't surface exception type of internal locking mechanism. throw cast(e); } } if (PooledObject.isNull(p)) { - throw new NoSuchElementException(appendStats( - "Timeout waiting for idle object, borrowMaxWaitDuration=" + borrowMaxWaitDuration)); + throw new NoSuchElementException(appendStats("Timeout waiting for idle object, borrowMaxWaitDuration=" + remainingWaitDuration)); } } else if (PooledObject.isNull(p)) { throw new NoSuchElementException(appendStats("Pool exhausted")); @@ -328,7 +326,6 @@ public T borrowObject(final Duration borrowMaxWaitDuration) throws E { if (!p.allocate()) { p = null; } - if (!PooledObject.isNull(p)) { try { factory.activateObject(p); @@ -340,8 +337,7 @@ public T borrowObject(final Duration borrowMaxWaitDuration) throws E { } p = null; if (create) { - final NoSuchElementException nsee = new NoSuchElementException( - appendStats("Unable to activate object")); + final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to activate object")); nsee.initCause(e); throw nsee; } @@ -364,8 +360,7 @@ public T borrowObject(final Duration borrowMaxWaitDuration) throws E { } p = null; if (create) { - final NoSuchElementException nsee = new NoSuchElementException( - appendStats("Unable to validate object")); + final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to validate object")); nsee.initCause(validationThrowable); throw nsee; } @@ -373,9 +368,7 @@ public T borrowObject(final Duration borrowMaxWaitDuration) throws E { } } } - - updateStatsBorrow(p, Duration.between(waitTime, Instant.now())); - + updateStatsBorrow(p, durationSince(startInstant)); return p.getObject(); } @@ -423,9 +416,7 @@ public T borrowObject(final Duration borrowMaxWaitDuration) throws E { * to become available * * @return object instance from the pool - * * @throws NoSuchElementException if an instance cannot be returned - * * @throws E if an object instance cannot be returned due to an * error */ @@ -496,7 +487,7 @@ public void close() { jmxUnregister(); // Release any threads that were waiting for an object - idleObjects.interuptTakeWaiters(); + idleObjects.interruptTakeWaiters(); } } @@ -510,20 +501,19 @@ public void close() { * If the factory makeObject returns null, this method throws a NullPointerException. *

* + * @param maxWaitDurationRequest The time to wait for an object to become available. * @return The new wrapped pooled object or null. * @throws E if the object factory's {@code makeObject} fails */ - private PooledObject create() throws E { + private PooledObject create(final Duration maxWaitDurationRequest) throws E { + final Instant startInstant = Instant.now(); + final Duration maxWaitDuration = maxWaitDurationRequest.isNegative() ? Duration.ZERO : maxWaitDurationRequest; int localMaxTotal = getMaxTotal(); // This simplifies the code later in this method if (localMaxTotal < 0) { localMaxTotal = Integer.MAX_VALUE; } - final Instant localStartInstant = Instant.now(); - final Duration maxWaitDurationRaw = getMaxWaitDuration(); - final Duration localMaxWaitDuration = maxWaitDurationRaw.isNegative() ? Duration.ZERO : maxWaitDurationRaw; - // Flag that indicates if create should: // - TRUE: call the factory to create an object // - FALSE: return null @@ -531,6 +521,8 @@ private PooledObject create() throws E { // call the factory Boolean create = null; while (create == null) { + // remainingWaitDuration handles spurious wakeup from wait(). + final Duration remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant)); synchronized (makeObjectCountLock) { final long newCreateCount = createCount.incrementAndGet(); if (newCreateCount > localMaxTotal) { @@ -548,7 +540,7 @@ private PooledObject create() throws E { // fail so wait until they complete and then re-test if // the pool is at capacity or not. try { - wait(makeObjectCountLock, localMaxWaitDuration); + wait(makeObjectCountLock, remainingWaitDuration); } catch (final InterruptedException e) { // Don't surface exception type of internal locking mechanism. throw cast(e); @@ -560,10 +552,9 @@ private PooledObject create() throws E { create = Boolean.TRUE; } } - - // Do not block more if maxWaitTimeMillis is set. - if (create == null && localMaxWaitDuration.compareTo(Duration.ZERO) > 0 && - Duration.between(localStartInstant, Instant.now()).compareTo(localMaxWaitDuration) >= 0) { + // Do not block more if remainingWaitDuration > 0. + if (create == null && remainingWaitDuration.compareTo(Duration.ZERO) > 0 && + durationSince(localStartInstant).compareTo(remainingWaitDuration) >= 0) { create = Boolean.FALSE; } } @@ -600,7 +591,7 @@ private PooledObject create() throws E { } createdCount.incrementAndGet(); - allObjects.put(new IdentityWrapper<>(p.getObject()), p); + allObjects.put(IdentityWrapper.unwrap(p), p); return p; } @@ -609,14 +600,13 @@ private PooledObject create() throws E { * * @param toDestroy The wrapped pooled object to destroy * @param destroyMode DestroyMode context provided to the factory - * * @throws E If the factory fails to destroy the pooled object * cleanly */ private void destroy(final PooledObject toDestroy, final DestroyMode destroyMode) throws E { toDestroy.invalidate(); idleObjects.remove(toDestroy); - allObjects.remove(new IdentityWrapper<>(toDestroy.getObject())); + allObjects.remove(IdentityWrapper.unwrap(toDestroy)); try { factory.destroyObject(toDestroy, destroyMode); } finally { @@ -625,6 +615,10 @@ private void destroy(final PooledObject toDestroy, final DestroyMode destroyM } } + private Duration durationSince(final Instant startInstant) { + return Duration.between(startInstant, Instant.now()); + } + /** * Tries to ensure that {@code idleCount} idle instances exist in the pool. *

@@ -648,7 +642,7 @@ private void ensureIdle(final int idleCount, final boolean always) throws E { } while (idleObjects.size() < idleCount) { - final PooledObject p = create(); + final PooledObject p = create(getMaxWaitDuration()); if (PooledObject.isNull(p)) { // Can't create objects, no reason to think another call to // create will work. Give up. @@ -856,10 +850,9 @@ public int getMaxIdle() { *

* * @return The minimum number of objects. - * * @see #setMinIdle(int) * @see #setMaxIdle(int) - * @see #setTimeBetweenEvictionRuns(Duration) + * @see #setDurationBetweenEvictionRuns(Duration) */ @Override public int getMinIdle() { @@ -979,11 +972,12 @@ public void invalidateObject(final T obj, final DestroyMode destroyMode) throws public Set listAllObjects() { return allObjects.values().stream().map(DefaultPooledObjectInfo::new).collect(Collectors.toSet()); } + /** * Tries to ensure that {@link #getMinIdle()} idle instances are available * in the pool. * - * @throws E If the associated factory throws an exception + * @throws E If the associated factory throws an exception. * @since 2.4 */ public void preparePool() throws E { @@ -1119,7 +1113,6 @@ public void returnObject(final T obj) { * Sets the base pool configuration. * * @param conf the new configuration to use. This is used by value. - * * @see GenericObjectPoolConfig */ public void setConfig(final GenericObjectPoolConfig conf) { diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolConfig.java b/src/main/java/org/apache/commons/pool3/impl/GenericObjectPoolConfig.java similarity index 87% rename from src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolConfig.java rename to src/main/java/org/apache/commons/pool3/impl/GenericObjectPoolConfig.java index 8bdd7f321..72437bf4c 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolConfig.java +++ b/src/main/java/org/apache/commons/pool3/impl/GenericObjectPoolConfig.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; /** * A simple structure encapsulating the configuration for a @@ -48,13 +48,19 @@ public class GenericObjectPoolConfig extends BaseObjectPoolConfig { */ public static final int DEFAULT_MIN_IDLE = 0; - private int maxTotal = DEFAULT_MAX_TOTAL; private int maxIdle = DEFAULT_MAX_IDLE; private int minIdle = DEFAULT_MIN_IDLE; + /** + * Constructs a new instance. + */ + public GenericObjectPoolConfig() { + // empty + } + @SuppressWarnings("unchecked") @Override public GenericObjectPoolConfig clone() { @@ -66,7 +72,7 @@ public GenericObjectPoolConfig clone() { } /** - * Get the value for the {@code maxIdle} configuration attribute + * Gets the value for the {@code maxIdle} configuration attribute * for pools created with this configuration instance. * * @return The current setting of {@code maxIdle} for this @@ -78,9 +84,8 @@ public int getMaxIdle() { return maxIdle; } - /** - * Get the value for the {@code maxTotal} configuration attribute + * Gets the value for the {@code maxTotal} configuration attribute * for pools created with this configuration instance. * * @return The current setting of {@code maxTotal} for this @@ -93,7 +98,7 @@ public int getMaxTotal() { } /** - * Get the value for the {@code minIdle} configuration attribute + * Gets the value for the {@code minIdle} configuration attribute * for pools created with this configuration instance. * * @return The current setting of {@code minIdle} for this @@ -105,9 +110,8 @@ public int getMinIdle() { return minIdle; } - /** - * Set the value for the {@code maxIdle} configuration attribute for + * Sets the value for the {@code maxIdle} configuration attribute for * pools created with this configuration instance. * * @param maxIdle The new setting of {@code maxIdle} @@ -120,7 +124,7 @@ public void setMaxIdle(final int maxIdle) { } /** - * Set the value for the {@code maxTotal} configuration attribute for + * Sets the value for the {@code maxTotal} configuration attribute for * pools created with this configuration instance. * * @param maxTotal The new setting of {@code maxTotal} @@ -133,7 +137,7 @@ public void setMaxTotal(final int maxTotal) { } /** - * Set the value for the {@code minIdle} configuration attribute for + * Sets the value for the {@code minIdle} configuration attribute for * pools created with this configuration instance. * * @param minIdle The new setting of {@code minIdle} diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java b/src/main/java/org/apache/commons/pool3/impl/GenericObjectPoolMXBean.java similarity index 55% rename from src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java rename to src/main/java/org/apache/commons/pool3/impl/GenericObjectPoolMXBean.java index 5f6d73a0c..3e0bd1266 100644 --- a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java +++ b/src/main/java/org/apache/commons/pool3/impl/GenericObjectPoolMXBean.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,244 +14,273 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.util.Set; /** * Defines the methods that will be made available via JMX. - * - * NOTE: This interface exists only to define those attributes and methods that - * will be made available via JMX. It must not be implemented by clients - * as it is subject to change between major, minor and patch version - * releases of commons pool. Clients that implement this interface may - * not, therefore, be able to upgrade to a new minor or patch release - * without requiring code changes. + *

Note

+ *

+ * This interface exists only to define those attributes and methods that will be made available via JMX. It must not be implemented by clients as it is subject + * to change between major, minor and patch version releases of commons pool. Clients that implement this interface may not, therefore, be able to upgrade to a + * new minor or patch release without requiring code changes. + *

* * @since 2.0 */ public interface GenericObjectPoolMXBean { - // Getters for basic configuration settings - /** - * See {@link GenericObjectPool#getBlockWhenExhausted()} - * @return See {@link GenericObjectPool#getBlockWhenExhausted()} + * See {@link GenericObjectPool#getBlockWhenExhausted()}. + * + * @return See {@link GenericObjectPool#getBlockWhenExhausted()}. */ boolean getBlockWhenExhausted(); /** - * See {@link GenericObjectPool#getBorrowedCount()} - * @return See {@link GenericObjectPool#getBorrowedCount()} + * See {@link GenericObjectPool#getBorrowedCount()}. + * + * @return See {@link GenericObjectPool#getBorrowedCount()}. */ long getBorrowedCount(); /** - * See {@link GenericObjectPool#getCreatedCount()} - * @return See {@link GenericObjectPool#getCreatedCount()} + * See {@link GenericObjectPool#getCreatedCount()}. + * + * @return See {@link GenericObjectPool#getCreatedCount()}. */ long getCreatedCount(); /** - * See {@link GenericObjectPool#getCreationStackTrace()} - * @return See {@link GenericObjectPool#getCreationStackTrace()} + * See {@link GenericObjectPool#getCreationStackTrace()}. + * + * @return See {@link GenericObjectPool#getCreationStackTrace()}. */ String getCreationStackTrace(); /** - * See {@link GenericObjectPool#getDestroyedByBorrowValidationCount()} - * @return See {@link GenericObjectPool#getDestroyedByBorrowValidationCount()} + * See {@link GenericObjectPool#getDestroyedByBorrowValidationCount()}. + * + * @return See {@link GenericObjectPool#getDestroyedByBorrowValidationCount()}. */ long getDestroyedByBorrowValidationCount(); /** - * See {@link GenericObjectPool#getDestroyedByEvictorCount()} - * @return See {@link GenericObjectPool#getDestroyedByEvictorCount()} + * See {@link GenericObjectPool#getDestroyedByEvictorCount()}. + * + * @return See {@link GenericObjectPool#getDestroyedByEvictorCount()}. */ long getDestroyedByEvictorCount(); /** - * See {@link GenericObjectPool#getDestroyedCount()} - * @return See {@link GenericObjectPool#getDestroyedCount()} + * See {@link GenericObjectPool#getDestroyedCount()}. + * + * @return See {@link GenericObjectPool#getDestroyedCount()}. */ long getDestroyedCount(); /** - * See {@link GenericObjectPool#getFactoryType()} - * @return See {@link GenericObjectPool#getFactoryType()} + * See {@link GenericObjectPool#getFactoryType()}. + * + * @return See {@link GenericObjectPool#getFactoryType()}. */ String getFactoryType(); /** - * See {@link GenericObjectPool#getLifo()} - * @return See {@link GenericObjectPool#getLifo()} + * See {@link GenericObjectPool#getLifo()}. + * + * @return See {@link GenericObjectPool#getLifo()}. */ boolean getFairness(); /** - * See {@link GenericObjectPool#getFairness()} - * @return See {@link GenericObjectPool#getFairness()} + * See {@link GenericObjectPool#getFairness()}. + * + * @return See {@link GenericObjectPool#getFairness()}. */ boolean getLifo(); /** - * See {@link GenericObjectPool#getLogAbandoned()} - * @return See {@link GenericObjectPool#getLogAbandoned()} + * See {@link GenericObjectPool#getLogAbandoned()}. + * + * @return See {@link GenericObjectPool#getLogAbandoned()}. */ boolean getLogAbandoned(); /** - * See {@link GenericObjectPool#getMaxBorrowWaitTimeMillis()} - * @return See {@link GenericObjectPool#getMaxBorrowWaitTimeMillis()} + * See {@link GenericObjectPool#getMaxBorrowWaitTimeMillis()}. + * + * @return See {@link GenericObjectPool#getMaxBorrowWaitTimeMillis()}. */ long getMaxBorrowWaitTimeMillis(); /** - * See {@link GenericObjectPool#getMaxIdle()} - * @return See {@link GenericObjectPool#getMaxIdle()} + * See {@link GenericObjectPool#getMaxIdle()}. + * + * @return See {@link GenericObjectPool#getMaxIdle()}. */ int getMaxIdle(); /** - * See {@link GenericObjectPool#getMaxTotal()} - * @return See {@link GenericObjectPool#getMaxTotal()} + * See {@link GenericObjectPool#getMaxTotal()}. + * + * @return See {@link GenericObjectPool#getMaxTotal()}. */ int getMaxTotal(); /** - * See {@link GenericObjectPool#getMaxWaitDuration()} - * @return See {@link GenericObjectPool#getMaxWaitDuration()} + * See {@link GenericObjectPool#getMaxWaitDuration()}. + * + * @return See {@link GenericObjectPool#getMaxWaitDuration()}. */ long getMaxWaitMillis(); /** - * See {@link GenericObjectPool#getMeanActiveTimeMillis()} - * @return See {@link GenericObjectPool#getMeanActiveTimeMillis()} + * See {@link GenericObjectPool#getMeanActiveTimeMillis()}. + * + * @return See {@link GenericObjectPool#getMeanActiveTimeMillis()}. */ long getMeanActiveTimeMillis(); /** - * See {@link GenericObjectPool#getMeanBorrowWaitTimeMillis()} - * @return See {@link GenericObjectPool#getMeanBorrowWaitTimeMillis()} + * See {@link GenericObjectPool#getMeanBorrowWaitTimeMillis()}. + * + * @return See {@link GenericObjectPool#getMeanBorrowWaitTimeMillis()}. */ long getMeanBorrowWaitTimeMillis(); - // Getters for monitoring attributes - /** - * See {@link GenericObjectPool#getMeanIdleTimeMillis()} - * @return See {@link GenericObjectPool#getMeanIdleTimeMillis()} + * See {@link GenericObjectPool#getMeanIdleTimeMillis()}. + * + * @return See {@link GenericObjectPool#getMeanIdleTimeMillis()}. */ long getMeanIdleTimeMillis(); /** - * See {@link GenericObjectPool#getMinEvictableIdleDuration()} - * @return See {@link GenericObjectPool#getMinEvictableIdleDuration()} + * See {@link GenericObjectPool#getMinEvictableIdleDuration()}. + * + * @return See {@link GenericObjectPool#getMinEvictableIdleDuration()}. */ long getMinEvictableIdleTimeMillis(); /** - * See {@link GenericObjectPool#getMinIdle()} - * @return See {@link GenericObjectPool#getMinIdle()} + * See {@link GenericObjectPool#getMinIdle()}. + * + * @return See {@link GenericObjectPool#getMinIdle()}. */ int getMinIdle(); /** - * See {@link GenericObjectPool#getNumActive()} - * @return See {@link GenericObjectPool#getNumActive()} + * See {@link GenericObjectPool#getNumActive()}. + * + * @return See {@link GenericObjectPool#getNumActive()}. */ int getNumActive(); /** - * See {@link GenericObjectPool#getNumIdle()} - * @return See {@link GenericObjectPool#getNumIdle()} + * See {@link GenericObjectPool#getNumIdle()}. + * + * @return See {@link GenericObjectPool#getNumIdle()}. */ int getNumIdle(); /** - * See {@link GenericObjectPool#getNumTestsPerEvictionRun()} - * @return See {@link GenericObjectPool#getNumTestsPerEvictionRun()} + * See {@link GenericObjectPool#getNumTestsPerEvictionRun()}. + * + * @return See {@link GenericObjectPool#getNumTestsPerEvictionRun()}. */ int getNumTestsPerEvictionRun(); /** - * See {@link GenericObjectPool#getNumWaiters()} - * @return See {@link GenericObjectPool#getNumWaiters()} + * See {@link GenericObjectPool#getNumWaiters()}. + * + * @return See {@link GenericObjectPool#getNumWaiters()}. */ int getNumWaiters(); /** - * See {@link GenericObjectPool#getRemoveAbandonedOnBorrow()} - * @return See {@link GenericObjectPool#getRemoveAbandonedOnBorrow()} + * See {@link GenericObjectPool#getRemoveAbandonedOnBorrow()}. + * + * @return See {@link GenericObjectPool#getRemoveAbandonedOnBorrow()}. */ boolean getRemoveAbandonedOnBorrow(); /** - * See {@link GenericObjectPool#getRemoveAbandonedOnMaintenance()} - * @return See {@link GenericObjectPool#getRemoveAbandonedOnMaintenance()} + * See {@link GenericObjectPool#getRemoveAbandonedOnMaintenance()}. + * + * @return See {@link GenericObjectPool#getRemoveAbandonedOnMaintenance()}. */ boolean getRemoveAbandonedOnMaintenance(); /** - * See {@link GenericObjectPool#getRemoveAbandonedTimeoutDuration()} - * @return See {@link GenericObjectPool#getRemoveAbandonedTimeoutDuration()} + * See {@link GenericObjectPool#getRemoveAbandonedTimeoutDuration()}. + * + * @return See {@link GenericObjectPool#getRemoveAbandonedTimeoutDuration()}. */ int getRemoveAbandonedTimeout(); /** - * See {@link GenericObjectPool#getReturnedCount()} - * @return See {@link GenericObjectPool#getReturnedCount()} + * See {@link GenericObjectPool#getReturnedCount()}. + * + * @return See {@link GenericObjectPool#getReturnedCount()}. */ long getReturnedCount(); /** - * See {@link GenericObjectPool#getTestOnBorrow()} - * @return See {@link GenericObjectPool#getTestOnBorrow()} + * See {@link GenericObjectPool#getTestOnBorrow()}. + * + * @return See {@link GenericObjectPool#getTestOnBorrow()}. */ boolean getTestOnBorrow(); - // Getters for abandoned object removal configuration - /** - * See {@link GenericObjectPool#getTestOnCreate()} - * @return See {@link GenericObjectPool#getTestOnCreate()} + * See {@link GenericObjectPool#getTestOnCreate()}. + * + * @return See {@link GenericObjectPool#getTestOnCreate()}. * @since 2.2 */ boolean getTestOnCreate(); /** - * See {@link GenericObjectPool#getTestOnReturn()} - * @return See {@link GenericObjectPool#getTestOnReturn()} + * See {@link GenericObjectPool#getTestOnReturn()}. + * + * @return See {@link GenericObjectPool#getTestOnReturn()}. */ boolean getTestOnReturn(); /** - * See {@link GenericObjectPool#getTestWhileIdle()} - * @return See {@link GenericObjectPool#getTestWhileIdle()} + * See {@link GenericObjectPool#getTestWhileIdle()}. + * + * @return See {@link GenericObjectPool#getTestWhileIdle()}. */ boolean getTestWhileIdle(); /** - * See {@link GenericObjectPool#getDurationBetweenEvictionRuns()} - * @return See {@link GenericObjectPool#getDurationBetweenEvictionRuns()} + * See {@link GenericObjectPool#getDurationBetweenEvictionRuns()}. + * + * @return See {@link GenericObjectPool#getDurationBetweenEvictionRuns()}. */ long getTimeBetweenEvictionRunsMillis(); /** - * See {@link GenericObjectPool#isAbandonedConfig()} - * @return See {@link GenericObjectPool#isAbandonedConfig()} + * See {@link GenericObjectPool#isAbandonedConfig()}. + * + * @return See {@link GenericObjectPool#isAbandonedConfig()}. */ boolean isAbandonedConfig(); /** - * See {@link GenericObjectPool#isClosed()} - * @return See {@link GenericObjectPool#isClosed()} + * See {@link GenericObjectPool#isClosed()}. + * + * @return See {@link GenericObjectPool#isClosed()}. */ boolean isClosed(); /** - * See {@link GenericObjectPool#listAllObjects()} - * @return See {@link GenericObjectPool#listAllObjects()} + * See {@link GenericObjectPool#listAllObjects()}. + * + * @return See {@link GenericObjectPool#listAllObjects()}. */ Set listAllObjects(); } diff --git a/src/main/java/org/apache/commons/pool2/impl/InterruptibleReentrantLock.java b/src/main/java/org/apache/commons/pool3/impl/InterruptibleReentrantLock.java similarity index 84% rename from src/main/java/org/apache/commons/pool2/impl/InterruptibleReentrantLock.java rename to src/main/java/org/apache/commons/pool3/impl/InterruptibleReentrantLock.java index fae6230e7..c964bc708 100644 --- a/src/main/java/org/apache/commons/pool2/impl/InterruptibleReentrantLock.java +++ b/src/main/java/org/apache/commons/pool3/impl/InterruptibleReentrantLock.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; @@ -29,7 +29,7 @@ * * @since 2.0 */ -class InterruptibleReentrantLock extends ReentrantLock { +final class InterruptibleReentrantLock extends ReentrantLock { private static final long serialVersionUID = 1L; @@ -37,18 +37,18 @@ class InterruptibleReentrantLock extends ReentrantLock { * Constructs a new InterruptibleReentrantLock with the given fairness policy. * * @param fairness true means threads should acquire contended locks as if - * waiting in a FIFO queue + * waiting in a FIFO queue. */ - public InterruptibleReentrantLock(final boolean fairness) { + InterruptibleReentrantLock(final boolean fairness) { super(fairness); } /** - * Interrupts the threads that are waiting on a specific condition + * Interrupts the threads that are waiting on a specific condition. * * @param condition the condition on which the threads are waiting. */ - public void interruptWaiters(final Condition condition) { + void interruptWaiters(final Condition condition) { getWaitingThreads(condition).forEach(Thread::interrupt); } } diff --git a/src/main/java/org/apache/commons/pool2/impl/LinkedBlockingDeque.java b/src/main/java/org/apache/commons/pool3/impl/LinkedBlockingDeque.java similarity index 95% rename from src/main/java/org/apache/commons/pool2/impl/LinkedBlockingDeque.java rename to src/main/java/org/apache/commons/pool3/impl/LinkedBlockingDeque.java index 15a3912ae..200a89a50 100644 --- a/src/main/java/org/apache/commons/pool2/impl/LinkedBlockingDeque.java +++ b/src/main/java/org/apache/commons/pool3/impl/LinkedBlockingDeque.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.IOException; import java.io.ObjectInputStream; @@ -22,10 +22,10 @@ import java.time.Duration; import java.util.AbstractQueue; import java.util.Collection; -import java.util.Deque; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.concurrent.BlockingDeque; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; @@ -65,8 +65,8 @@ * * @since 2.0 */ -class LinkedBlockingDeque extends AbstractQueue - implements Deque, Serializable { +final class LinkedBlockingDeque extends AbstractQueue + implements BlockingDeque, Serializable { /* * Implemented as a simple doubly-linked list protected by a @@ -90,7 +90,7 @@ class LinkedBlockingDeque extends AbstractQueue /* * We have "diamond" multiple interface/abstract class inheritance * here, and that introduces ambiguities. Often we want the - * BlockingDeque javadoc combined with the AbstractQueue + * BlockingDeque Javadoc combined with the AbstractQueue * implementation, so a lot of method specs are duplicated here. */ @@ -173,7 +173,6 @@ public E next() { * iterator. * * @param n given node - * * @return next node */ abstract Node nextNode(Node n); @@ -222,20 +221,30 @@ private Node succ(Node n) { } /** Descending iterator */ - private class DescendingItr extends AbstractItr { + private final class DescendingItr extends AbstractItr { @Override - Node firstNode() { return last; } + Node firstNode() { + return last; + } + @Override - Node nextNode(final Node n) { return n.prev; } + Node nextNode(final Node n) { + return n.prev; + } } /** Forward iterator */ - private class Itr extends AbstractItr { + private final class Itr extends AbstractItr { @Override - Node firstNode() { return first; } + Node firstNode() { + return first; + } + @Override - Node nextNode(final Node n) { return n.next; } + Node nextNode(final Node n) { + return n.next; } + } /** * Doubly-linked list node class. @@ -313,7 +322,7 @@ private static final class Node { * Creates a {@code LinkedBlockingDeque} with a capacity of * {@link Integer#MAX_VALUE}. */ - public LinkedBlockingDeque() { + LinkedBlockingDeque() { this(Integer.MAX_VALUE); } @@ -323,11 +332,10 @@ public LinkedBlockingDeque() { * @param fairness true means threads waiting on the deque should be served * as if waiting in a FIFO request queue */ - public LinkedBlockingDeque(final boolean fairness) { + LinkedBlockingDeque(final boolean fairness) { this(Integer.MAX_VALUE, fairness); } - // Basic linking and unlinking operations, called only while holding lock /** @@ -340,7 +348,7 @@ public LinkedBlockingDeque(final boolean fairness) { * @throws NullPointerException if the specified collection or any * of its elements are null */ - public LinkedBlockingDeque(final Collection c) { + LinkedBlockingDeque(final Collection c) { this(Integer.MAX_VALUE); lock.lock(); // Never contended, but necessary for visibility try { @@ -361,7 +369,7 @@ public LinkedBlockingDeque(final Collection c) { * @param capacity the capacity of this deque * @throws IllegalArgumentException if {@code capacity} is less than 1 */ - public LinkedBlockingDeque(final int capacity) { + LinkedBlockingDeque(final int capacity) { this(capacity, false); } @@ -374,7 +382,7 @@ public LinkedBlockingDeque(final int capacity) { * as if waiting in a FIFO request queue * @throws IllegalArgumentException if {@code capacity} is less than 1 */ - public LinkedBlockingDeque(final int capacity, final boolean fairness) { + LinkedBlockingDeque(final int capacity, final boolean fairness) { if (capacity <= 0) { throw new IllegalArgumentException(); } @@ -476,9 +484,7 @@ public Iterator descendingIterator() { * Drains the queue to the specified collection. * * @param c The collection to add the elements to - * * @return number of elements added to the collection - * * @throws UnsupportedOperationException if the add operation is not * supported by the specified collection * @throws ClassCastException if the class of the elements held by this @@ -487,6 +493,7 @@ public Iterator descendingIterator() { * @throws NullPointerException if c is null * @throws IllegalArgumentException if c is this instance */ + @Override public int drainTo(final Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -495,9 +502,8 @@ public int drainTo(final Collection c) { * Drains no more than the specified number of elements from the queue to the * specified collection. * - * @param c collection to add the elements to + * @param collection collection to add the elements to * @param maxElements maximum number of elements to remove from the queue - * * @return number of elements added to the collection * @throws UnsupportedOperationException if the add operation is not * supported by the specified collection @@ -507,16 +513,17 @@ public int drainTo(final Collection c) { * @throws NullPointerException if c is null * @throws IllegalArgumentException if c is this instance */ - public int drainTo(final Collection c, final int maxElements) { - Objects.requireNonNull(c, "c"); - if (c == this) { + @Override + public int drainTo(final Collection collection, final int maxElements) { + Objects.requireNonNull(collection, "c"); + if (collection == this) { throw new IllegalArgumentException(); } lock.lock(); try { final int n = Math.min(maxElements, count); for (int i = 0; i < n; i++) { - c.add(first.item); // In this order, in case add() throws. + collection.add(first.item); // In this order, in case add() throws. unlinkFirst(); } return n; @@ -570,7 +577,7 @@ public E getLast() { * * @return number of threads waiting on this deque's notEmpty condition. */ - public int getTakeQueueLength() { + int getTakeQueueLength() { lock.lock(); try { return lock.getWaitQueueLength(notEmpty); @@ -585,7 +592,7 @@ public int getTakeQueueLength() { * * @return true if there is at least one thread waiting on this deque's notEmpty condition. */ - public boolean hasTakeWaiters() { + boolean hasTakeWaiters() { lock.lock(); try { return lock.hasWaiters(notEmpty); @@ -598,7 +605,7 @@ public boolean hasTakeWaiters() { * Interrupts the threads currently waiting to take an object from the pool. See disclaimer on accuracy in * {@link java.util.concurrent.locks.ReentrantLock#getWaitingThreads(Condition)}. */ - public void interuptTakeWaiters() { + void interruptTakeWaiters() { lock.lock(); try { lock.interruptWaiters(notEmpty); @@ -628,7 +635,6 @@ public Iterator iterator() { * Links provided element as first element, or returns false if full. * * @param e The element to link as the first element. - * * @return {@code true} if successful, otherwise {@code false} */ private boolean linkFirst(final E e) { @@ -653,7 +659,6 @@ private boolean linkFirst(final E e) { * Links provided element as last element, or returns false if full. * * @param e The element to link as the last element. - * * @return {@code true} if successful, otherwise {@code false} */ private boolean linkLast(final E e) { @@ -690,9 +695,7 @@ public boolean offer(final E e) { * * @param e element to link * @param timeout length of time to wait - * * @return {@code true} if successful, otherwise {@code false} - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space @@ -710,13 +713,12 @@ boolean offer(final E e, final Duration timeout) throws InterruptedException { * @param e element to link * @param timeout length of time to wait * @param unit units that timeout is expressed in - * * @return {@code true} if successful, otherwise {@code false} - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { return offerLast(e, timeout, unit); } @@ -741,14 +743,12 @@ public boolean offerFirst(final E e) { * * @param e element to link * @param timeout length of time to wait - * * @return {@code true} if successful, otherwise {@code false} - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ - public boolean offerFirst(final E e, final Duration timeout) throws InterruptedException { + boolean offerFirst(final E e, final Duration timeout) throws InterruptedException { Objects.requireNonNull(e, "e"); long nanos = timeout.toNanos(); lock.lockInterruptibly(); @@ -772,13 +772,12 @@ public boolean offerFirst(final E e, final Duration timeout) throws InterruptedE * @param e element to link * @param timeout length of time to wait * @param unit units that timeout is expressed in - * * @return {@code true} if successful, otherwise {@code false} - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public boolean offerFirst(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { return offerFirst(e, PoolImplUtils.toDuration(timeout, unit)); } @@ -803,9 +802,7 @@ public boolean offerLast(final E e) { * * @param e element to link * @param timeout length of time to wait - * * @return {@code true} if successful, otherwise {@code false} - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whist waiting * for space @@ -834,13 +831,12 @@ boolean offerLast(final E e, final Duration timeout) throws InterruptedException * @param e element to link * @param timeout length of time to wait * @param unit units that timeout is expressed in - * * @return {@code true} if successful, otherwise {@code false} - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whist waiting * for space */ + @Override public boolean offerLast(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { return offerLast(e, PoolImplUtils.toDuration(timeout, unit)); } @@ -884,7 +880,6 @@ public E poll() { *

This method is equivalent to {@link #pollFirst(long, TimeUnit)}. * * @param timeout length of time to wait - * * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ @@ -900,10 +895,10 @@ E poll(final Duration timeout) throws InterruptedException { * * @param timeout length of time to wait * @param unit units that timeout is expressed in - * * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E poll(final long timeout, final TimeUnit unit) throws InterruptedException { return pollFirst(timeout, unit); } @@ -923,7 +918,6 @@ public E pollFirst() { * to do so if the queue is empty. * * @param timeout length of time to wait - * * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ @@ -950,10 +944,10 @@ E pollFirst(final Duration timeout) throws InterruptedException { * * @param timeout length of time to wait * @param unit units that timeout is expressed in - * * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E pollFirst(final long timeout, final TimeUnit unit) throws InterruptedException { return pollFirst(PoolImplUtils.toDuration(timeout, unit)); } @@ -973,17 +967,15 @@ public E pollLast() { * to do so if the queue is empty. * * @param timeout length of time to wait - * * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ - public E pollLast(final Duration timeout) - throws InterruptedException { + E pollLast(final Duration timeout) throws InterruptedException { long nanos = timeout.toNanos(); lock.lockInterruptibly(); try { E x; - while ( (x = unlinkLast()) == null) { + while ((x = unlinkLast()) == null) { if (nanos <= 0) { return null; } @@ -1001,10 +993,10 @@ public E pollLast(final Duration timeout) * * @param timeout length of time to wait * @param unit units that timeout is expressed in - * * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E pollLast(final long timeout, final TimeUnit unit) throws InterruptedException { return pollLast(PoolImplUtils.toDuration(timeout, unit)); @@ -1035,11 +1027,11 @@ public void push(final E e) { *

* * @param e element to link - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public void put(final E e) throws InterruptedException { putLast(e); } @@ -1049,11 +1041,11 @@ public void put(final E e) throws InterruptedException { * is space to do so if the queue is full. * * @param e element to link - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public void putFirst(final E e) throws InterruptedException { Objects.requireNonNull(e, "e"); lock.lock(); @@ -1071,11 +1063,11 @@ public void putFirst(final E e) throws InterruptedException { * is space to do so if the queue is full. * * @param e element to link - * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public void putLast(final E e) throws InterruptedException { Objects.requireNonNull(e, "e"); lock.lock(); @@ -1088,15 +1080,12 @@ public void putLast(final E e) throws InterruptedException { } } - // Stack methods - /** - * Reconstitutes this deque from a stream (that is, - * deserialize it). + * Reconstitutes this deque from a stream (that is, deserialize it). + * * @param s the stream */ - private void readObject(final ObjectInputStream s) - throws IOException, ClassNotFoundException { + private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); count = 0; first = null; @@ -1104,7 +1093,7 @@ private void readObject(final ObjectInputStream s) // Read in all elements and place in queue for (;;) { @SuppressWarnings("unchecked") - final E item = (E)s.readObject(); + final E item = (E) s.readObject(); if (item == null) { break; } @@ -1127,6 +1116,7 @@ private void readObject(final ObjectInputStream s) * * @return The number of additional elements the queue is able to accept */ + @Override public int remainingCapacity() { lock.lock(); try { @@ -1305,6 +1295,7 @@ public int size() { * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E take() throws InterruptedException { return takeFirst(); } @@ -1316,11 +1307,12 @@ public E take() throws InterruptedException { * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E takeFirst() throws InterruptedException { lock.lock(); try { E x; - while ( (x = unlinkFirst()) == null) { + while ((x = unlinkFirst()) == null) { notEmpty.await(); } return x; @@ -1336,11 +1328,12 @@ public E takeFirst() throws InterruptedException { * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E takeLast() throws InterruptedException { lock.lock(); try { E x; - while ( (x = unlinkLast()) == null) { + while ((x = unlinkLast()) == null) { notEmpty.await(); } return x; @@ -1389,12 +1382,11 @@ public T[] toArray(T[] a) { lock.lock(); try { if (a.length < count) { - a = (T[])java.lang.reflect.Array.newInstance - (a.getClass().getComponentType(), count); + a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), count); } int k = 0; for (Node p = first; p != null; p = p.next) { - a[k++] = (T)p.item; + a[k++] = (T) p.item; } if (a.length > k) { a[k] = null; diff --git a/src/main/java/org/apache/commons/pool2/impl/NoOpCallStack.java b/src/main/java/org/apache/commons/pool3/impl/NoOpCallStack.java similarity index 92% rename from src/main/java/org/apache/commons/pool2/impl/NoOpCallStack.java rename to src/main/java/org/apache/commons/pool3/impl/NoOpCallStack.java index 6cf4bd751..c01a9027c 100644 --- a/src/main/java/org/apache/commons/pool2/impl/NoOpCallStack.java +++ b/src/main/java/org/apache/commons/pool3/impl/NoOpCallStack.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.PrintWriter; @@ -27,7 +27,7 @@ public class NoOpCallStack implements CallStack { /** - * Singleton instance. + * The singleton instance. */ public static final CallStack INSTANCE = new NoOpCallStack(); diff --git a/src/main/java/org/apache/commons/pool2/impl/PoolImplUtils.java b/src/main/java/org/apache/commons/pool3/impl/PoolImplUtils.java similarity index 96% rename from src/main/java/org/apache/commons/pool2/impl/PoolImplUtils.java rename to src/main/java/org/apache/commons/pool3/impl/PoolImplUtils.java index 412c8f229..1abb5612f 100644 --- a/src/main/java/org/apache/commons/pool2/impl/PoolImplUtils.java +++ b/src/main/java/org/apache/commons/pool3/impl/PoolImplUtils.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -25,20 +25,19 @@ import java.util.Objects; import java.util.concurrent.TimeUnit; -import org.apache.commons.pool2.PooledObjectFactory; +import org.apache.commons.pool3.PooledObjectFactory; /** * Implementation specific utilities. * * @since 2.0 */ -class PoolImplUtils { +final class PoolImplUtils { /** * Identifies the concrete type of object that an object factory creates. * * @param factoryClass The factory to examine - * * @return the type of object the factory creates */ @SuppressWarnings("rawtypes") @@ -46,7 +45,7 @@ static Class getFactoryType(final Class factor final Class type = PooledObjectFactory.class; final Object genericType = getGenericType(type, factoryClass); if (genericType instanceof Integer) { - // POOL-324 org.apache.commons.pool2.impl.GenericObjectPool.getFactoryType() throws + // POOL-324 org.apache.commons.pool3.impl.GenericObjectPool.getFactoryType() throws // java.lang.ClassCastException // // A bit hackish, but we must handle cases when getGenericType() does not return a concrete types. @@ -73,7 +72,6 @@ static Class getFactoryType(final Class factor * @param type The interface that defines a generic type * @param clazz The class that implements the interface with a concrete type * @param The interface type - * * @return concrete type used by the implementation */ private static Object getGenericType(final Class type, final Class clazz) { @@ -135,7 +133,6 @@ private static ParameterizedType getParameterizedType(final Class type, f * * @param clazz defining class * @param argType the type argument of interest - * * @return An instance of {@link Class} representing the type used by the type parameter or an instance of * {@link Integer} representing the index for the type in the definition of the defining class */ @@ -227,7 +224,7 @@ static ChronoUnit toChronoUnit(final TimeUnit timeUnit) { * @return a Duration. */ static Duration toDuration(final long amount, final TimeUnit timeUnit) { - return Duration.of(amount, PoolImplUtils.toChronoUnit(timeUnit)); + return Duration.of(amount, toChronoUnit(timeUnit)); } } diff --git a/src/main/java/org/apache/commons/pool2/impl/PooledSoftReference.java b/src/main/java/org/apache/commons/pool3/impl/PooledSoftReference.java similarity index 97% rename from src/main/java/org/apache/commons/pool2/impl/PooledSoftReference.java rename to src/main/java/org/apache/commons/pool3/impl/PooledSoftReference.java index be10346c5..2c78fb6c6 100644 --- a/src/main/java/org/apache/commons/pool2/impl/PooledSoftReference.java +++ b/src/main/java/org/apache/commons/pool3/impl/PooledSoftReference.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.lang.ref.SoftReference; diff --git a/src/main/java/org/apache/commons/pool3/impl/ResilientPooledObjectFactory.java b/src/main/java/org/apache/commons/pool3/impl/ResilientPooledObjectFactory.java new file mode 100644 index 000000000..4d36c6e42 --- /dev/null +++ b/src/main/java/org/apache/commons/pool3/impl/ResilientPooledObjectFactory.java @@ -0,0 +1,541 @@ +/* + * 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 + * + * https://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.pool3.impl; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; + +/** + * Wraps a PooledObjectFactory, extending to provide resilient features. + *

+ * Maintains a circular log of makeObject calls and makes strategy-based + * decisions on whether to keep trying proactively to create objects. + * Decisions use data in the makeObject log and information reported by + * the pool that the factory is attached to. + *

+ * + * @param Type of object managed by the factory + * @param Type of exception that the factory may throw + */ +public class ResilientPooledObjectFactory implements PooledObjectFactory { + + /** + * Adder thread that adds objects to the pool, waiting for a fixed delay between + * adds. + *

+ * The adder thread will stop under any of the following conditions: + *

+ *
    + *
  • The pool is closed.
  • + *
  • The factory is down.
  • + *
  • The pool is full.
  • + *
  • The pool has no waiters.
  • + *
+ */ + final class Adder extends Thread { + + private static final int MAX_FAILURES = 5; + + private volatile boolean killed; + private volatile boolean running; + private int failures; + + public boolean isRunning() { + return running; + } + + public void kill() { + killed = true; + } + + @Override + public void run() { + running = true; + while (!up && !killed && !pool.isClosed()) { + try { + pool.addObject(); + if (pool.getNumWaiters() == 0 || pool.getNumActive() + pool.getNumIdle() == pool.getMaxTotal()) { + kill(); + } + } catch (final Throwable e) { + failures++; + if (failures > MAX_FAILURES) { + kill(); + } + } finally { + // Wait for delay + try { + sleep(delay.toMillis()); + } catch (final InterruptedException e) { + kill(); + } + } + } + kill(); + running = false; + } + } + + /** + * Record of a makeObject event. + */ + static final class MakeEvent { + private final Instant startTime; + private Instant endTime; + private boolean success; + private Throwable exception; + + /** + * Constructs a new instance and set statTime to now. + */ + MakeEvent() { + startTime = Instant.now(); + } + + /** + * Mark completion of makeObject call. + */ + public void end() { + this.endTime = Instant.now(); + } + + /** + * @return the time the makeObject call ended + */ + public Instant getEndTime() { + return endTime; + } + + /** + * @return the exception thrown by the makeObject call + */ + public Throwable getException() { + return exception; + } + + /** + * @return the start time of the makeObject call + */ + public Instant getStartTime() { + return startTime; + } + + /** + * @return true if the makeObject call succeeded + */ + public boolean isSuccess() { + return success; + } + + /** + * Set the exception thrown by the makeObject call. + * + * @param exception + */ + public void setException(final Throwable exception) { + this.exception = exception; + } + + /** + * Set the success status of the makeObject call. + * + * @param success + */ + public void setSuccess(final boolean success) { + this.success = success; + } + } + + /** + * Monitor thread that runs checks to examine the makeObject log and pool state. + */ + final class Monitor extends Thread { + @Override + public void run() { + while (monitoring && !pool.isClosed()) { + runChecks(); + try { + sleep(timeBetweenChecks.toMillis()); + } catch (final InterruptedException e) { + monitoring = false; + } catch (final Throwable e) { + monitoring = false; + throw e; + } + } + monitoring = false; + } + } + + private static final int DEFAULT_LOG_SIZE = 10; + private static final Duration DEFAULT_DELAY = Duration.ofSeconds(1); + private static final Duration DEFAULT_LOOK_BACK = Duration.ofMinutes(5); + private static final Duration DEFAULT_TIME_BETWEEN_CHECKS = Duration.ofSeconds(10); + + /** + * Gets the default time between makeObject calls by the adder thread. + * + * @return the default time between makeObject calls by the adder thread. + */ + public static Duration getDefaultDelay() { + return DEFAULT_DELAY; + } + + /** + * Gets the default makeObject log size. + * + * @return the default makeObject log size. + */ + public static int getDefaultLogSize() { + return DEFAULT_LOG_SIZE; + } + + /** + * Gets the default look back duration. + * + * @return the default look back duration. + */ + public static Duration getDefaultLookBack() { + return DEFAULT_LOOK_BACK; + } + + /** + * Gets the default time between monitor checks. + * + * @return the default time between monitor checks. + */ + public static Duration getDefaultTimeBetweenChecks() { + return DEFAULT_TIME_BETWEEN_CHECKS; + } + + /** Wrapped factory */ + private final PooledObjectFactory factory; + + /** GOP that factory is attached to. */ + private GenericObjectPool pool; + + /** Size of the circular log of makeObject events */ + private int logSize; + + /** Duration of time window for statistics */ + private final Duration lookBack; + + /** Circular log of makeObject events */ + private final ConcurrentLinkedQueue makeObjectLog = new ConcurrentLinkedQueue<>(); + + /** Time of last factory failure */ + private Instant downStart; + + /** Time factory last returned to "up" state. */ + private Instant upStart; + + /** Exception counts */ + @SuppressWarnings("rawtypes") + private final ConcurrentHashMap exceptionCounts = new ConcurrentHashMap<>(); + + /** Whether or not the factory is "up" */ + private boolean up = true; + + /** + * @return the factory wrapped by this resilient factory + */ + /** Whether or not the monitor thread is running */ + private boolean monitoring; + + /** Time to wait between object creations by the adder thread */ + private final Duration delay; + + /** Time between monitor checks */ + private Duration timeBetweenChecks = Duration.ofSeconds(10); + + // Delegate all other methods to the wrapped factory. + + /** Adder thread */ + private Adder adder; + + /** + * Construct a ResilientPooledObjectFactory from a factory and pool, using + * defaults for logSize, delay, and lookBack. + * + * @param factory PooledObjectFactory to wrap + */ + public ResilientPooledObjectFactory(final PooledObjectFactory factory) { + this(factory, DEFAULT_LOG_SIZE, DEFAULT_DELAY, DEFAULT_LOOK_BACK, DEFAULT_TIME_BETWEEN_CHECKS); + } + + /** + * Construct a ResilientPooledObjectFactory from a factory with specified + * parameters. + * + * @param factory PooledObjectFactory to wrap + * @param logSize length of the makeObject log + * @param delay time to wait between object creations by the adder + * thread + * @param lookBack length of time over which metrics are kept + * @param timeBetweenChecks time between checks by the monitor thread + */ + public ResilientPooledObjectFactory(final PooledObjectFactory factory, + final int logSize, final Duration delay, final Duration lookBack, final Duration timeBetweenChecks) { + this.logSize = logSize; + this.factory = factory; + this.delay = delay; + this.lookBack = lookBack; + this.timeBetweenChecks = timeBetweenChecks; + } + + @Override + public void activateObject(final PooledObject p) throws E { + factory.activateObject(p); + } + + @Override + public void destroyObject(final PooledObject p) throws E { + factory.destroyObject(p); + } + + /** + * Gets the time to wait between object creations by the adder thread. + * + * @return the time to wait between object creations by the adder thread. + */ + public Duration getDelay() { + return delay; + } + + /** + * Gets the start time of the last factory outage. + * + * @return the start time of the last factory outage. + */ + public Instant getDownStart() { + return downStart; + } + + /** + * Gets the size of the makeObject log. + * + * @return the size of the makeObject log. + */ + public int getLogSize() { + return logSize; + } + + /** + * Gets the look back duration. + * + * @return the look back duration. + */ + public Duration getLookBack() { + return lookBack; + } + + /** + * Gets a copy of the makeObject log. + * + * @return a copy of the makeObject log. + */ + public List getMakeObjectLog() { + final ArrayList makeObjectLog = new ArrayList<>(); + return new ArrayList<>(makeObjectLog.stream().toList()); + } + + /** + * Gets the duration between monitor checks. + * + * @return the duration between monitor checks. + */ + public Duration getTimeBetweenChecks() { + return timeBetweenChecks; + } + + /** + * Gets the time of the last factory outage recovery. + * + * @return the time of the last factory outage recovery. + */ + public Instant getUpStart() { + return upStart; + } + + /** + * Tests whether the adder is running. + * + * @return true if the adder is running. + */ + public boolean isAdderRunning() { + return adder != null && adder.isRunning(); + } + + /** + * Tests whether the monitor is running. + * + * @return true if the monitor is running. + */ + public boolean isMonitorRunning() { + return monitoring; + } + + /** + * Tests whether the factory is considered "up". + * + * @return true if the factory is considered "up". + */ + public boolean isUp() { + return up; + } + + /** + * Delegate to the wrapped factory, but log the makeObject call. + */ + @Override + public PooledObject makeObject() throws E { + final MakeEvent makeEvent = new MakeEvent(); + try { + final PooledObject obj = factory.makeObject(); + makeEvent.setSuccess(PooledObject.nonNull(obj)); + return obj; + } catch (final Throwable t) { + makeEvent.setSuccess(false); + makeEvent.setException(t); + exceptionCounts.put(t.getClass(), exceptionCounts.getOrDefault(t, 0) + 1); + throw t; + } finally { + makeEvent.end(); + makeObjectLog.add(makeEvent); + } + } + + @Override + public void passivateObject(final PooledObject p) throws E { + factory.passivateObject(p); + } + + /** + * Default implementation considers the factory down as soon as a single + * makeObject call fails and considers it back up if the last logSize makes have + * succeeded. + *

+ * Sets downStart to time of the first failure found in makeObjectLog and + * upStart to the time when logSize consecutive makes have succeeded. + *

+ *

+ * When a failure is observed, the adder thread is started if the pool + * is not closed and has take waiters. + *

+ *

+ * Removes the oldest event from the log if it is full. + *

+ */ + protected void runChecks() { + boolean upOverLog = true; + // 1. If the log is full, remove the oldest (first) event. + // + // 2. Walk the event log. If we find a failure, set downStart, set up to false + // and start the adder thread. + // + // 3. If the log contains only successes, if up is false, set upStart and up to + // true + // and kill the adder thread. + while (makeObjectLog.size() > logSize) { + makeObjectLog.poll(); + } + for (final MakeEvent makeEvent : makeObjectLog) { + if (!makeEvent.isSuccess()) { + upOverLog = false; + downStart = Instant.now(); + up = false; + if (pool.getNumWaiters() > 0 && !pool.isClosed() && adder == null) { + adder = new Adder(); + adder.start(); + } + } + + } + if (upOverLog && !up) { + // Kill adder thread and set up to true + upStart = Instant.now(); + up = true; + adder.kill(); + adder = null; + } + } + + /** + * Sets the makeObject log size. + * + * @param logSize the number of makeObject events to keep in the log + */ + public void setLogSize(final int logSize) { + this.logSize = logSize; + } + + /** + * Sets the underlying pool. For tests. + * + * @param pool the underlying pool. + */ + void setPool(final GenericObjectPool pool) { + this.pool = pool; + } + + /** + * Sets the time between monitor checks. + * + * @param timeBetweenChecks The time between monitor checks. + */ + public void setTimeBetweenChecks(final Duration timeBetweenChecks) { + this.timeBetweenChecks = timeBetweenChecks; + } + + /** + * Starts the monitor thread with the currently configured time between checks. + */ + public void startMonitor() { + monitoring = true; + new Monitor().start(); + } + + /** + * Starts the monitor thread with the given time between checks. + * + * @param timeBetweenChecks time between checks + */ + public void startMonitor(final Duration timeBetweenChecks) { + this.timeBetweenChecks = timeBetweenChecks; + startMonitor(); + } + + /** + * Stops the monitor thread. + */ + public void stopMonitor() { + monitoring = false; + } + + @Override + public boolean validateObject(final PooledObject p) { + return factory.validateObject(p); + } + +} diff --git a/src/main/java/org/apache/commons/pool2/impl/SecurityManagerCallStack.java b/src/main/java/org/apache/commons/pool3/impl/SecurityManagerCallStack.java similarity index 94% rename from src/main/java/org/apache/commons/pool2/impl/SecurityManagerCallStack.java rename to src/main/java/org/apache/commons/pool3/impl/SecurityManagerCallStack.java index 1276e1d77..93b2f0dad 100644 --- a/src/main/java/org/apache/commons/pool2/impl/SecurityManagerCallStack.java +++ b/src/main/java/org/apache/commons/pool3/impl/SecurityManagerCallStack.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.PrintWriter; import java.lang.ref.WeakReference; @@ -40,7 +40,7 @@ public class SecurityManagerCallStack implements CallStack { /** * A custom security manager. */ - private static class PrivateSecurityManager extends SecurityManager { + private static final class PrivateSecurityManager extends SecurityManager { /** * Gets the class stack. @@ -56,7 +56,7 @@ private List>> getCallStack() { /** * A snapshot of a class stack. */ - private static class Snapshot { + private static final class Snapshot { private final long timestampMillis = System.currentTimeMillis(); private final List>> stack; diff --git a/src/main/java/org/apache/commons/pool2/impl/SoftReferenceObjectPool.java b/src/main/java/org/apache/commons/pool3/impl/SoftReferenceObjectPool.java similarity index 80% rename from src/main/java/org/apache/commons/pool2/impl/SoftReferenceObjectPool.java rename to src/main/java/org/apache/commons/pool3/impl/SoftReferenceObjectPool.java index c00e7cc7c..b61e71b0e 100644 --- a/src/main/java/org/apache/commons/pool2/impl/SoftReferenceObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/impl/SoftReferenceObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,20 +14,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.ArrayList; -import java.util.Iterator; +import java.util.Collection; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Optional; +import java.util.concurrent.BlockingDeque; -import org.apache.commons.pool2.BaseObjectPool; -import org.apache.commons.pool2.ObjectPool; -import org.apache.commons.pool2.PoolUtils; -import org.apache.commons.pool2.PooledObjectFactory; +import org.apache.commons.pool3.BaseObjectPool; +import org.apache.commons.pool3.ObjectPool; +import org.apache.commons.pool3.PoolUtils; +import org.apache.commons.pool3.PooledObjectFactory; /** * A {@link java.lang.ref.SoftReference SoftReference} based {@link ObjectPool}. @@ -44,7 +46,7 @@ */ public class SoftReferenceObjectPool extends BaseObjectPool { - /** Factory to source pooled objects */ + /** Factory to source pooled objects. */ private final PooledObjectFactory factory; /** @@ -60,25 +62,22 @@ public class SoftReferenceObjectPool extends BaseObjectP /** Total number of instances that have been destroyed */ private long destroyCount; // @GuardedBy("this") - /** Total number of instances that have been created */ private long createCount; // @GuardedBy("this") /** Idle references - waiting to be borrowed */ - private final LinkedBlockingDeque> idleReferences = - new LinkedBlockingDeque<>(); + private final BlockingDeque> idleReferences = new LinkedBlockingDeque<>(); /** All references - checked out or waiting to be borrowed. */ - private final ArrayList> allReferences = - new ArrayList<>(); + private final ArrayList> allReferences = new ArrayList<>(); /** * Constructs a {@code SoftReferenceObjectPool} with the specified factory. * - * @param factory object factory to use. + * @param factory non-null object factory to use. */ public SoftReferenceObjectPool(final PooledObjectFactory factory) { - this.factory = factory; + this.factory = Objects.requireNonNull(factory, "factory"); } /** @@ -87,12 +86,12 @@ public SoftReferenceObjectPool(final PooledObjectFactory factory) { *

* Before being added to the pool, the newly created instance is * {@link PooledObjectFactory#validateObject( - * org.apache.commons.pool2.PooledObject) validated} and + * org.apache.commons.pool3.PooledObject) validated} and * {@link PooledObjectFactory#passivateObject( - * org.apache.commons.pool2.PooledObject) passivated}. If + * org.apache.commons.pool3.PooledObject) passivated}. If * validation fails, the new instance is * {@link PooledObjectFactory#destroyObject( - * org.apache.commons.pool2.PooledObject) destroyed}. Exceptions + * org.apache.commons.pool3.PooledObject) destroyed}. Exceptions * generated by the factory {@code makeObject} or * {@code passivate} are propagated to the caller. Exceptions * destroying instances are silently swallowed. @@ -107,15 +106,10 @@ public SoftReferenceObjectPool(final PooledObjectFactory factory) { @Override public synchronized void addObject() throws E { assertOpen(); - if (factory == null) { - throw new IllegalStateException( - "Cannot add objects without a factory."); - } final T obj = factory.makeObject().getObject(); createCount++; // Create and register with the queue - final PooledSoftReference ref = new PooledSoftReference<>( - new SoftReference<>(obj, refQueue)); + final PooledSoftReference ref = new PooledSoftReference<>(new SoftReference<>(obj, refQueue)); allReferences.add(ref); boolean success = true; @@ -147,13 +141,13 @@ public synchronized void addObject() throws E { * new instance. *

* All instances are {@link PooledObjectFactory#activateObject( - * org.apache.commons.pool2.PooledObject) activated} + * org.apache.commons.pool3.PooledObject) activated} * and {@link PooledObjectFactory#validateObject( - * org.apache.commons.pool2.PooledObject) + * org.apache.commons.pool3.PooledObject) * validated} before being returned by this method. If validation fails or * an exception occurs activating or validating an idle instance, the * failing instance is {@link PooledObjectFactory#destroyObject( - * org.apache.commons.pool2.PooledObject) + * org.apache.commons.pool3.PooledObject) * destroyed} and another instance is retrieved from the pool, validated and * activated. This process continues until either the pool is empty or an * instance passes validation. If the pool is empty on activation or it does @@ -184,9 +178,6 @@ public synchronized T borrowObject() throws E { PooledSoftReference ref = null; while (null == obj) { if (idleReferences.isEmpty()) { - if (null == factory) { - throw new NoSuchElementException(); - } newlyCreated = true; obj = factory.makeObject().getObject(); createCount++; @@ -202,7 +193,7 @@ public synchronized T borrowObject() throws E { ref.getReference().clear(); ref.setReference(new SoftReference<>(obj)); } - if (null != factory && null != obj) { + if (null != obj) { try { factory.activateObject(ref); if (!factory.validateObject(ref)) { @@ -234,17 +225,15 @@ public synchronized T borrowObject() throws E { */ @Override public synchronized void clear() { - if (null != factory) { - idleReferences.forEach(ref -> { - try { - if (null != ref.getObject()) { - factory.destroyObject(ref); - } - } catch (final Exception ignored) { - // ignored, keep destroying the rest + idleReferences.forEach(pooledSoftRef -> { + try { + if (null != pooledSoftRef.getObject()) { + factory.destroyObject(pooledSoftRef); } - }); - } + } catch (final Exception ignored) { + // ignored, keep destroying the rest + } + }); idleReferences.clear(); pruneClearedReferences(); } @@ -265,11 +254,10 @@ public void close() { } /** - * Destroys a {@code PooledSoftReference} and removes it from the idle and all + * Destroys a {@link PooledSoftReference} and removes it from the idle and all * references pools. * * @param toDestroy PooledSoftReference to destroy - * * @throws E If an error occurs while trying to destroy the object */ private void destroy(final PooledSoftReference toDestroy) throws E { @@ -292,7 +280,7 @@ private void destroy(final PooledSoftReference toDestroy) throws E { */ private PooledSoftReference findReference(final T obj) { final Optional> first = allReferences.stream() - .filter(reference -> reference.getObject() != null && reference.getObject().equals(obj)).findFirst(); + .filter(reference -> Objects.equals(reference.getObject(), obj)).findFirst(); return first.orElse(null); } @@ -335,12 +323,9 @@ public synchronized int getNumIdle() { public synchronized void invalidateObject(final T obj) throws E { final PooledSoftReference ref = findReference(obj); if (ref == null) { - throw new IllegalStateException( - "Object to invalidate is not currently part of this pool"); - } - if (factory != null) { - destroy(ref); + throw new IllegalStateException("Object to invalidate is not currently part of this pool"); } + destroy(ref); numActive--; notifyAll(); // numActive has changed } @@ -351,24 +336,20 @@ public synchronized void invalidateObject(final T obj) throws E { */ private void pruneClearedReferences() { // Remove wrappers for enqueued references from idle and allReferences lists - removeClearedReferences(idleReferences.iterator()); - removeClearedReferences(allReferences.iterator()); - while (refQueue.poll() != null) { // NOPMD + removeClearedReferences(idleReferences); + removeClearedReferences(allReferences); + while (refQueue.poll() != null) { + // loop until null } } /** - * Clears cleared references from iterator's collection - * @param iterator iterator over idle/allReferences + * Clears cleared references from the collection. + * + * @param collection collection of idle/allReferences */ - private void removeClearedReferences(final Iterator> iterator) { - PooledSoftReference ref; - while (iterator.hasNext()) { - ref = iterator.next(); - if (ref.getReference() == null || ref.getReference().isEnqueued()) { - iterator.remove(); - } - } + private void removeClearedReferences(final Collection> collection) { + collection.removeIf(ref -> ref.getReference() == null || ref.getReference().isEnqueued()); } /** @@ -378,10 +359,10 @@ private void removeClearedReferences(final Iterator> iter *

    *
  • the pool is closed
  • *
  • {@link PooledObjectFactory#validateObject( - * org.apache.commons.pool2.PooledObject) validation} fails + * org.apache.commons.pool3.PooledObject) validation} fails *
  • *
  • {@link PooledObjectFactory#passivateObject( - * org.apache.commons.pool2.PooledObject) passivation} + * org.apache.commons.pool3.PooledObject) passivation} * throws an exception
  • *
* Exceptions passivating or destroying instances are silently swallowed. @@ -397,18 +378,15 @@ public synchronized void returnObject(final T obj) throws E { boolean success = !isClosed(); final PooledSoftReference ref = findReference(obj); if (ref == null) { - throw new IllegalStateException( - "Returned object not currently part of this pool"); + throw new IllegalStateException("Returned object not currently part of this pool"); } - if (factory != null) { - if (!factory.validateObject(ref)) { + if (!factory.validateObject(ref)) { + success = false; + } else { + try { + factory.passivateObject(ref); + } catch (final Exception e) { success = false; - } else { - try { - factory.passivateObject(ref); - } catch (final Exception e) { - success = false; - } } } @@ -422,7 +400,7 @@ public synchronized void returnObject(final T obj) throws E { } notifyAll(); // numActive has changed - if (shouldDestroy && factory != null) { + if (shouldDestroy) { try { destroy(ref); } catch (final Exception ignored) { diff --git a/src/main/java/org/apache/commons/pool2/impl/ThrowableCallStack.java b/src/main/java/org/apache/commons/pool3/impl/ThrowableCallStack.java similarity index 94% rename from src/main/java/org/apache/commons/pool2/impl/ThrowableCallStack.java rename to src/main/java/org/apache/commons/pool3/impl/ThrowableCallStack.java index b220ab374..1af88d979 100644 --- a/src/main/java/org/apache/commons/pool2/impl/ThrowableCallStack.java +++ b/src/main/java/org/apache/commons/pool3/impl/ThrowableCallStack.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.io.PrintWriter; import java.text.DateFormat; @@ -33,7 +33,7 @@ public class ThrowableCallStack implements CallStack { /** * A snapshot of a throwable. */ - private static class Snapshot extends Throwable { + private static final class Snapshot extends Throwable { private static final long serialVersionUID = 1L; private final long timestampMillis = System.currentTimeMillis(); } diff --git a/src/main/java/org/apache/commons/pool2/impl/package-info.java b/src/main/java/org/apache/commons/pool3/impl/package-info.java similarity index 66% rename from src/main/java/org/apache/commons/pool2/impl/package-info.java rename to src/main/java/org/apache/commons/pool3/impl/package-info.java index 7bbd45666..f2bde5733 100644 --- a/src/main/java/org/apache/commons/pool2/impl/package-info.java +++ b/src/main/java/org/apache/commons/pool3/impl/package-info.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -18,16 +18,16 @@ /** * Object pooling API implementations. *

- * {@link org.apache.commons.pool2.impl.GenericObjectPool GenericObjectPool} ({@link org.apache.commons.pool2.impl.GenericKeyedObjectPool - * GenericKeyedObjectPool}) provides a more robust (but also more complicated) implementation of {@link org.apache.commons.pool2.ObjectPool ObjectPool} - * ({@link org.apache.commons.pool2.KeyedObjectPool KeyedObjectPool}). + * {@link org.apache.commons.pool3.impl.GenericObjectPool GenericObjectPool} ({@link org.apache.commons.pool3.impl.GenericKeyedObjectPool + * GenericKeyedObjectPool}) provides a more robust (but also more complicated) implementation of {@link org.apache.commons.pool3.ObjectPool ObjectPool} + * ({@link org.apache.commons.pool3.KeyedObjectPool KeyedObjectPool}). *

*

- * {@link org.apache.commons.pool2.impl.SoftReferenceObjectPool SoftReferenceObjectPool} provides a {@link java.lang.ref.SoftReference SoftReference} based - * {@link org.apache.commons.pool2.ObjectPool ObjectPool}. + * {@link org.apache.commons.pool3.impl.SoftReferenceObjectPool SoftReferenceObjectPool} provides a {@link java.lang.ref.SoftReference SoftReference} based + * {@link org.apache.commons.pool3.ObjectPool ObjectPool}. *

*

- * See also the {@link org.apache.commons.pool2} package. + * See also the {@link org.apache.commons.pool3} package. *

*/ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; diff --git a/src/main/java/org/apache/commons/pool2/package-info.java b/src/main/java/org/apache/commons/pool3/package-info.java similarity index 56% rename from src/main/java/org/apache/commons/pool2/package-info.java rename to src/main/java/org/apache/commons/pool3/package-info.java index 3a48b23f6..98f209f07 100644 --- a/src/main/java/org/apache/commons/pool2/package-info.java +++ b/src/main/java/org/apache/commons/pool3/package-info.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -18,26 +18,26 @@ /** * Object pooling API. *

- * The org.apache.commons.pool2 package defines a simple interface for a pool of object instances, and a handful of base classes that may be useful + * The {@code org.apache.commons.pool3} package defines a simple interface for a pool of object instances, and a handful of base classes that may be useful * when creating pool implementations. *

*

- * The pool package itself doesn't define a specific object pooling implementation, but rather a contract that implementations may support in order + * The {@code pool} package itself doesn't define a specific object pooling implementation, but rather a contract that implementations may support in order * to be fully interchangeable. *

*

- * The pool package separates the way in which instances are pooled from the way in which they are created, resulting in a pair of interfaces: + * The {@code pool} package separates the way in which instances are pooled from the way in which they are created, resulting in a pair of interfaces: *

*
- *
{@link org.apache.commons.pool2.ObjectPool ObjectPool}
+ *
{@link org.apache.commons.pool3.ObjectPool ObjectPool}
*
defines a simple object pooling interface, with methods for borrowing instances from and returning them to the pool.
- *
{@link org.apache.commons.pool2.PooledObjectFactory PooledObjectFactory}
+ *
{@link org.apache.commons.pool3.PooledObjectFactory PooledObjectFactory}
*
defines lifecycle methods for object instances contained within a pool. By associating a factory with a pool, the pool can create new object instances as * needed.
*
*

- * The pool package also provides a keyed pool interface, which pools instances of multiple types, accessed according to an arbitrary key. See - * {@link org.apache.commons.pool2.KeyedObjectPool KeyedObjectPool} and {@link org.apache.commons.pool2.KeyedPooledObjectFactory KeyedPooledObjectFactory}. + * The {@code pool} package also provides a keyed pool interface, which pools instances of multiple types, accessed according to an arbitrary key. See + * {@link org.apache.commons.pool3.KeyedObjectPool KeyedObjectPool} and {@link org.apache.commons.pool3.KeyedPooledObjectFactory KeyedPooledObjectFactory}. *

*/ -package org.apache.commons.pool2; +package org.apache.commons.pool3; diff --git a/src/main/java/org/apache/commons/pool3/proxy/AbstractProxySource.java b/src/main/java/org/apache/commons/pool3/proxy/AbstractProxySource.java new file mode 100644 index 000000000..fafc70224 --- /dev/null +++ b/src/main/java/org/apache/commons/pool3/proxy/AbstractProxySource.java @@ -0,0 +1,97 @@ +/* + * 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 + * + * https://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.pool3.proxy; + +import java.lang.reflect.InvocationTargetException; +import java.util.function.Supplier; + +/** + * Abstracts a proxy source implementation. + * + * @param type of the pooled object to be proxied. + * @since 3.0.0 + */ +public abstract class AbstractProxySource implements ProxySource { + + /** + * Abstract a builder implementations. + * + * @param type of the pooled object to be proxied. + * @param

the AbstractProxySource subclass + * @param the builder subclass. + */ + public abstract static class AbstractBuilder> implements Supplier

{ + + /** + * Whether the proxy throws {@link InvocationTargetException#getTargetException()} instead of {@link InvocationTargetException}. + */ + protected boolean unwrapInvocationTargetException; + + /** + * Constructs a new instance for a subclass. + */ + public AbstractBuilder() { + // empty + } + + /** + * Returns {@code this} instance typed as a subclass. + * + * @return {@code this} instance typed as a subclass. + */ + @SuppressWarnings("unchecked") + B asThis() { + return (B) this; + } + + /** + * Sets whether the proxy throws {@link InvocationTargetException#getTargetException()} instead of {@link InvocationTargetException}. + * + * @param unwrapInvocationTargetException whether the proxy throws {@link InvocationTargetException#getTargetException()} instead of + * {@link InvocationTargetException}. + * @return {@code this} instance. + */ + public B setUnwrapInvocationTargetException(final boolean unwrapInvocationTargetException) { + this.unwrapInvocationTargetException = unwrapInvocationTargetException; + return asThis(); + } + } + + /** + * Whether the proxy throws {@link InvocationTargetException#getTargetException()} instead of {@link InvocationTargetException}. + */ + private final boolean unwrapInvocationTargetException; + + /** + * Constructs a new instance. + * + * @param builder Information used to build the new instance. + */ + protected AbstractProxySource(final AbstractBuilder builder) { + this.unwrapInvocationTargetException = builder.unwrapInvocationTargetException; + } + + /** + * Tests whether the proxy throws {@link InvocationTargetException#getTargetException()} instead of {@link InvocationTargetException}. + * + * @return whether the proxy throws {@link InvocationTargetException#getTargetException()} instead of {@link InvocationTargetException}. + */ + protected boolean isUnwrapInvocationTargetException() { + return unwrapInvocationTargetException; + } +} diff --git a/src/main/java/org/apache/commons/pool2/proxy/BaseProxyHandler.java b/src/main/java/org/apache/commons/pool3/proxy/BaseProxyHandler.java similarity index 73% rename from src/main/java/org/apache/commons/pool2/proxy/BaseProxyHandler.java rename to src/main/java/org/apache/commons/pool3/proxy/BaseProxyHandler.java index c22798df1..085caab16 100644 --- a/src/main/java/org/apache/commons/pool2/proxy/BaseProxyHandler.java +++ b/src/main/java/org/apache/commons/pool3/proxy/BaseProxyHandler.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,40 +14,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.UsageTracking; /** * Base implementation for object wrappers when using a * {@link ProxiedObjectPool}. * * @param type of the wrapped pooled object - * * @since 2.0 */ class BaseProxyHandler { private volatile T pooledObject; private final UsageTracking usageTracking; - + private final boolean unwrapInvocationTargetException; /** * Constructs a new wrapper for the given pooled object. * - * @param pooledObject The object to wrap - * @param usageTracking The instance, if any (usually the object pool) to - * be provided with usage tracking information for this - * wrapped object + * @param pooledObject The object to wrap + * @param usageTracking The instance, if any (usually the object pool) to + * be provided with usage tracking information for this + * wrapped object + * @param unwrapInvocationTargetException True to make the proxy throw {@link InvocationTargetException#getTargetException()} + * instead of {@link InvocationTargetException} */ - BaseProxyHandler(final T pooledObject, final UsageTracking usageTracking) { + BaseProxyHandler(final T pooledObject, final UsageTracking usageTracking, final boolean unwrapInvocationTargetException) { this.pooledObject = pooledObject; this.usageTracking = usageTracking; + this.unwrapInvocationTargetException = unwrapInvocationTargetException; } - /** * Disable the proxy wrapper. Called when the object has been returned to * the pool. Further use of the wrapper should result in an @@ -61,7 +63,6 @@ T disableProxy() { return result; } - /** * Invoke the given method on the wrapped object. * @@ -76,10 +77,16 @@ Object doInvoke(final Method method, final Object[] args) throws Throwable { if (usageTracking != null) { usageTracking.use(object); } - return method.invoke(object, args); + try { + return method.invoke(object, args); + } catch (final InvocationTargetException e) { + if (unwrapInvocationTargetException) { + throw e.getTargetException(); + } + throw e; + } } - /** * Gets the wrapped, pooled object. * @@ -89,7 +96,6 @@ T getPooledObject() { return pooledObject; } - /** * @since 2.4.3 */ @@ -105,7 +111,6 @@ public String toString() { return builder.toString(); } - /** * Check that the proxy is still valid (i.e. that {@link #disableProxy()} * has not been called). diff --git a/src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java b/src/main/java/org/apache/commons/pool3/proxy/CglibProxyHandler.java similarity index 52% rename from src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java rename to src/main/java/org/apache/commons/pool3/proxy/CglibProxyHandler.java index 63ce61bc9..da3dd255c 100644 --- a/src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java +++ b/src/main/java/org/apache/commons/pool3/proxy/CglibProxyHandler.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,41 +14,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; + +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.UsageTracking; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** + * cglib is unmaintained and does not work well (or possibly at all?) in newer JDKs, particularly JDK17+; see https://github.com/cglib/cglib + *

* CGLib implementation of the proxy handler. + *

* * @param type of the wrapped pooled object - * * @since 2.0 */ -class CglibProxyHandler extends BaseProxyHandler - implements MethodInterceptor { - +final class CglibProxyHandler extends BaseProxyHandler implements MethodInterceptor { /** * Constructs a CGLib proxy instance. * - * @param pooledObject The object to wrap - * @param usageTracking The instance, if any (usually the object pool) to - * be provided with usage tracking information for this - * wrapped object + * @param pooledObject The object to wrap + * @param usageTracking The instance, if any (usually the object pool) to be provided with usage tracking information for this wrapped + * object + * @param unwrapInvocationTargetException True to make the proxy throw {@link InvocationTargetException#getTargetException()} instead of + * {@link InvocationTargetException} */ - CglibProxyHandler(final T pooledObject, final UsageTracking usageTracking) { - super(pooledObject, usageTracking); + CglibProxyHandler(final T pooledObject, final UsageTracking usageTracking, final boolean unwrapInvocationTargetException) { + super(pooledObject, usageTracking, unwrapInvocationTargetException); } @Override - public Object intercept(final Object object, final Method method, final Object[] args, - final MethodProxy methodProxy) throws Throwable { + public Object intercept(final Object object, final Method method, final Object[] args, final MethodProxy methodProxy) throws Throwable { return doInvoke(method, args); } } diff --git a/src/main/java/org/apache/commons/pool3/proxy/CglibProxySource.java b/src/main/java/org/apache/commons/pool3/proxy/CglibProxySource.java new file mode 100644 index 000000000..4bb9fde0b --- /dev/null +++ b/src/main/java/org/apache/commons/pool3/proxy/CglibProxySource.java @@ -0,0 +1,130 @@ +/* + * 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 + * + * https://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.pool3.proxy; + +import org.apache.commons.pool3.UsageTracking; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.Factory; + +/** + * cglib is unmaintained and does not work well (or possibly at all?) in newer JDKs, particularly JDK17+; see https://github.com/cglib/cglib + *

+ * Provides proxy objects using CGLib. + *

+ * + * @param type of the pooled object to be proxied. + * @since 2.0 + */ +public class CglibProxySource extends AbstractProxySource { + + /** + * Builds instances of {@link CglibProxySource}. + * + * @param type of the pooled object to be proxied. + * @since 3.0.0 + */ + public static class Builder extends AbstractBuilder, Builder> { + + private Class superclass; + + /** + * Constructs a new instance. + */ + public Builder() { + // empty + } + + @Override + public CglibProxySource get() { + return new CglibProxySource<>(this); + } + + /** + * Sets the superclass. + * + * @param superclass the superclass. + * @return {@code this} instance. + */ + public Builder setSuperclass(final Class superclass) { + this.superclass = superclass; + return asThis(); + } + } + + /** + * Constructs a new builder of {@link CglibProxySource}. + * + * @param type of the pooled object to be proxied. + * @return a new builder of {@link CglibProxySource}. + * @since 3.0.0 + */ + public static Builder builder() { + return new Builder<>(); + } + + private final Class superclass; + + private CglibProxySource(final Builder builder) { + super(builder); + this.superclass = builder.superclass; + } + + /** + * Constructs a new proxy source for the given class. + *

+ * For additional features, use a {@link #builder()}. + *

+ * @param superclass The class to proxy + */ + public CglibProxySource(final Class superclass) { + super(builder()); + this.superclass = superclass; + } + + @SuppressWarnings("unchecked") // Case to T on return + @Override + public T createProxy(final T pooledObject, final UsageTracking usageTracking) { + final Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(superclass); + final CglibProxyHandler proxyInterceptor = new CglibProxyHandler<>(pooledObject, usageTracking, isUnwrapInvocationTargetException()); + enhancer.setCallback(proxyInterceptor); + return (T) enhancer.create(); + } + + @Override + public T resolveProxy(final T proxy) { + @SuppressWarnings("unchecked") + final CglibProxyHandler cglibProxyHandler = (CglibProxyHandler) ((Factory) proxy).getCallback(0); + return cglibProxyHandler.disableProxy(); + } + + /** + * Converts this instance to a string suitable for debugging. + * + * @since 2.4.3 + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("CglibProxySource [superclass="); + builder.append(superclass); + builder.append("]"); + return builder.toString(); + } +} diff --git a/src/main/java/org/apache/commons/pool2/proxy/JdkProxyHandler.java b/src/main/java/org/apache/commons/pool3/proxy/JdkProxyHandler.java similarity index 56% rename from src/main/java/org/apache/commons/pool2/proxy/JdkProxyHandler.java rename to src/main/java/org/apache/commons/pool3/proxy/JdkProxyHandler.java index 451a6b7fb..d6d72e383 100644 --- a/src/main/java/org/apache/commons/pool2/proxy/JdkProxyHandler.java +++ b/src/main/java/org/apache/commons/pool3/proxy/JdkProxyHandler.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,40 +14,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; + +package org.apache.commons.pool3.proxy; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.UsageTracking; /** * Java reflection implementation of the proxy handler. * * @param type of the wrapped pooled object - * * @since 2.0 */ -class JdkProxyHandler extends BaseProxyHandler - implements InvocationHandler { +final class JdkProxyHandler extends BaseProxyHandler implements InvocationHandler { /** * Constructs a Java reflection proxy instance. * - * @param pooledObject The object to wrap - * @param usageTracking The instance, if any (usually the object pool) to - * be provided with usage tracking information for this - * wrapped object + * @param pooledObject The object to wrap + * @param usageTracking The instance, if any (usually the object pool) to be provided with usage tracking information for this wrapped + * object + * @param unwrapInvocationTargetException True to make the proxy throw {@link InvocationTargetException#getTargetException()} instead of + * {@link InvocationTargetException} */ - JdkProxyHandler(final T pooledObject, final UsageTracking usageTracking) { - super(pooledObject, usageTracking); + JdkProxyHandler(final T pooledObject, final UsageTracking usageTracking, final boolean unwrapInvocationTargetException) { + super(pooledObject, usageTracking, unwrapInvocationTargetException); } - @Override - public Object invoke(final Object proxy, final Method method, final Object[] args) - throws Throwable { + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { return doInvoke(method, args); } } - diff --git a/src/main/java/org/apache/commons/pool3/proxy/JdkProxySource.java b/src/main/java/org/apache/commons/pool3/proxy/JdkProxySource.java new file mode 100644 index 000000000..6d2b5dbed --- /dev/null +++ b/src/main/java/org/apache/commons/pool3/proxy/JdkProxySource.java @@ -0,0 +1,142 @@ +/* + * 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 + * + * https://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.pool3.proxy; + +import java.lang.reflect.Proxy; +import java.util.Arrays; + +import org.apache.commons.pool3.UsageTracking; + +/** + * Provides proxy objects using Java reflection. + * + * @param type of the pooled object to be proxied + * @since 2.0 + */ +public class JdkProxySource extends AbstractProxySource { + + /** + * Builds instances of {@link JdkProxySource}. + * + * @param type of the pooled object to be proxied. + * @since 3.0.0 + */ + public static class Builder extends AbstractBuilder, Builder> { + + private ClassLoader classLoader; + private Class[] interfaces; + + /** + * Constructs a new instance. + */ + public Builder() { + // empty + } + + @Override + public JdkProxySource get() { + return new JdkProxySource<>(this); + } + + /** + * Sets the class loader to define the proxy class. + * + * @param classLoader the class loader to define the proxy class. + * @return {@code this} instance. + */ + public Builder setClassLoader(final ClassLoader classLoader) { + this.classLoader = classLoader; + return asThis(); + } + + /** + * Sets the list of interfaces for the proxy class. + * + * @param interfaces the list of interfaces for the proxy class. + * @return {@code this} instance. + */ + public Builder setInterfaces(final Class... interfaces) { + this.interfaces = interfaces != null ? interfaces.clone() : null; + return asThis(); + } + } + + /** + * Constructs a new builder of {@link CglibProxySource}. + * + * @param type of the pooled object to be proxied. + * @return a new builder of {@link CglibProxySource}. + * @since 3.0.0 + */ + public static Builder builder() { + return new Builder<>(); + } + + /** The class loader to define the proxy class. */ + private final ClassLoader classLoader; + + /** The list of interfaces for the proxy class to implement. */ + private final Class[] interfaces; + + private JdkProxySource(final Builder builder) { + super(builder); + this.classLoader = builder.classLoader; + this.interfaces = builder.interfaces; + } + + /** + * Constructs a new proxy source for the given interfaces. + *

+ * For additional features, use a {@link #builder()}. + *

+ * + * @param classLoader The class loader with which to create the proxy + * @param interfaces The interfaces to proxy + */ + public JdkProxySource(final ClassLoader classLoader, final Class[] interfaces) { + super(builder()); + this.classLoader = classLoader; + this.interfaces = interfaces.clone(); + } + + @SuppressWarnings("unchecked") // Cast to T on return. + @Override + public T createProxy(final T pooledObject, final UsageTracking usageTracking) { + return (T) Proxy.newProxyInstance(classLoader, interfaces, new JdkProxyHandler<>(pooledObject, usageTracking, isUnwrapInvocationTargetException())); + } + + @SuppressWarnings("unchecked") + @Override + public T resolveProxy(final T proxy) { + return ((JdkProxyHandler) Proxy.getInvocationHandler(proxy)).disableProxy(); + } + + /** + * @since 2.4.3 + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("JdkProxySource [classLoader="); + builder.append(classLoader); + builder.append(", interfaces="); + builder.append(Arrays.toString(interfaces)); + builder.append("]"); + return builder.toString(); + } +} diff --git a/src/main/java/org/apache/commons/pool2/proxy/ProxiedKeyedObjectPool.java b/src/main/java/org/apache/commons/pool3/proxy/ProxiedKeyedObjectPool.java similarity index 95% rename from src/main/java/org/apache/commons/pool2/proxy/ProxiedKeyedObjectPool.java rename to src/main/java/org/apache/commons/pool3/proxy/ProxiedKeyedObjectPool.java index 38a6c4a59..b874d687f 100644 --- a/src/main/java/org/apache/commons/pool2/proxy/ProxiedKeyedObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/proxy/ProxiedKeyedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,13 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; import java.util.List; import java.util.NoSuchElementException; -import org.apache.commons.pool2.KeyedObjectPool; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.KeyedObjectPool; +import org.apache.commons.pool3.UsageTracking; /** * Create a new keyed object pool where the pooled objects are wrapped in @@ -31,7 +31,6 @@ * @param type of the key * @param type of the pooled object * @param type of exception thrown by this pool - * * @since 2.0 */ public class ProxiedKeyedObjectPool implements KeyedObjectPool { @@ -39,7 +38,6 @@ public class ProxiedKeyedObjectPool implements KeyedO private final KeyedObjectPool pool; private final ProxySource proxySource; - /** * Constructs a new proxied object pool. * @@ -52,7 +50,6 @@ public ProxiedKeyedObjectPool(final KeyedObjectPool pool, this.proxySource = proxySource; } - @Override public void addObject(final K key) throws E, IllegalStateException, UnsupportedOperationException { diff --git a/src/main/java/org/apache/commons/pool2/proxy/ProxiedObjectPool.java b/src/main/java/org/apache/commons/pool3/proxy/ProxiedObjectPool.java similarity index 94% rename from src/main/java/org/apache/commons/pool2/proxy/ProxiedObjectPool.java rename to src/main/java/org/apache/commons/pool3/proxy/ProxiedObjectPool.java index e0b7cd7a2..882ee2ad1 100644 --- a/src/main/java/org/apache/commons/pool2/proxy/ProxiedObjectPool.java +++ b/src/main/java/org/apache/commons/pool3/proxy/ProxiedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,12 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; import java.util.NoSuchElementException; -import org.apache.commons.pool2.ObjectPool; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.ObjectPool; +import org.apache.commons.pool3.UsageTracking; /** * Create a new object pool where the pooled objects are wrapped in proxies @@ -29,7 +29,6 @@ * * @param type of the pooled object * @param type of the exception - * * @since 2.0 */ public class ProxiedObjectPool implements ObjectPool { @@ -37,7 +36,6 @@ public class ProxiedObjectPool implements ObjectPool pool; private final ProxySource proxySource; - /** * Constructs a new proxied object pool. * @@ -54,7 +52,6 @@ public void addObject() throws E, IllegalStateException, UnsupportedOperationExc pool.addObject(); } - @SuppressWarnings("unchecked") @Override public T borrowObject() throws E, NoSuchElementException, IllegalStateException { @@ -65,37 +62,31 @@ public T borrowObject() throws E, NoSuchElementException, IllegalStateException return proxySource.createProxy(pool.borrowObject(), usageTracking); } - @Override public void clear() throws E, UnsupportedOperationException { pool.clear(); } - @Override public void close() { pool.close(); } - @Override public int getNumActive() { return pool.getNumActive(); } - @Override public int getNumIdle() { return pool.getNumIdle(); } - @Override public void invalidateObject(final T proxy) throws E { pool.invalidateObject(proxySource.resolveProxy(proxy)); } - @Override public void returnObject(final T proxy) throws E { pool.returnObject(proxySource.resolveProxy(proxy)); diff --git a/src/main/java/org/apache/commons/pool2/proxy/ProxySource.java b/src/main/java/org/apache/commons/pool3/proxy/ProxySource.java similarity index 91% rename from src/main/java/org/apache/commons/pool2/proxy/ProxySource.java rename to src/main/java/org/apache/commons/pool3/proxy/ProxySource.java index e756857a3..02ba68b6b 100644 --- a/src/main/java/org/apache/commons/pool2/proxy/ProxySource.java +++ b/src/main/java/org/apache/commons/pool3/proxy/ProxySource.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,16 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; -import org.apache.commons.pool2.UsageTracking; +import org.apache.commons.pool3.UsageTracking; /** * The interface that any provider of proxy instances must implement to allow the * {@link ProxiedObjectPool} to create proxies as required. * * @param type of the pooled object to be proxied - * * @since 2.0 */ interface ProxySource { @@ -44,7 +43,6 @@ interface ProxySource { * Resolves the wrapped object from the given proxy. * * @param proxy The proxy object - * * @return The pooled object wrapped by the given proxy */ T resolveProxy(T proxy); diff --git a/src/main/java/org/apache/commons/pool2/proxy/package-info.java b/src/main/java/org/apache/commons/pool3/proxy/package-info.java similarity index 68% rename from src/main/java/org/apache/commons/pool2/proxy/package-info.java rename to src/main/java/org/apache/commons/pool3/proxy/package-info.java index 75cfdc1b5..446c1eb26 100644 --- a/src/main/java/org/apache/commons/pool2/proxy/package-info.java +++ b/src/main/java/org/apache/commons/pool3/proxy/package-info.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -16,17 +16,20 @@ */ /** - * Object pooling proxy implementation. + * Object pooling proxy implementations. *

- * The org.apache.commons.pool2.proxy package defines a + * The {@code org.apache.commons.pool3.proxy} package defines a * object pool that wraps all objects returned to clients. This allows it * to disable those proxies when the objects are returned thereby enabling - * the continued use of those objects by clients to be detected.. + * the continued use of those objects by clients to be detected. *

*

- * Support is provided for java.lang.reflect.Proxy and for - * net.sf.cglib.proxy based proxies. The latter, requires the + * Support is provided for {@code java.lang.reflect.Proxy} and for + * {@code net.sf.cglib.proxy} based proxies. The latter, requires the * additional of the optional Code Generation Library (GCLib). *

+ *

+ * cglib is unmaintained and does not work well (or possibly at all?) in newer JDKs, particularly JDK17+; see https://github.com/cglib/cglib + *

*/ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; diff --git a/src/main/javadoc/overview.html b/src/main/javadoc/overview.html new file mode 100644 index 000000000..25dfad98a --- /dev/null +++ b/src/main/javadoc/overview.html @@ -0,0 +1,41 @@ + + + +Apache Commons Pool 3 + + + Apache Commons Pool + +

Generic Object pooling API with several implementations.

+

+ The + org.apache.commons.pool3 + package defines a simple interface for a pool of object instances, and a handful of base classes that may be useful when creating pool implementations. The + API supports pooling of unique objects which can be requested via a key as well as pools where all objects are equivalent. +

+

+ The + org.apache.commons.pool3.impl + package contains several pool implementations. {@link org.apache.commons.pool3.impl.GenericObjectPool GenericObjectPool} has many configuration options and + can support a limited set of objects such as would be useful in a database connection pool. {@link org.apache.commons.pool3.impl.SoftReferenceObjectPool + SoftReferenceObjectPool} has no limit on the number of objects in the pool, but the garbage collector can remove idle objects from the pool as needed. There + is also a keyed version of {@link org.apache.commons.pool3.impl.GenericObjectPool GenericObjectPool}, {@link + org.apache.commons.pool3.impl.GenericKeyedObjectPool GenericKeyedObjectPool} +

+ + diff --git a/src/site/resources/download_pool.cgi b/src/site/resources/download_pool.cgi index 7afe84106..ea2c6b9d6 100755 --- a/src/site/resources/download_pool.cgi +++ b/src/site/resources/download_pool.cgi @@ -7,7 +7,7 @@ # (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 +# https://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, diff --git a/src/site/resources/images/pool-logo-white.png b/src/site/resources/images/logo.png similarity index 100% rename from src/site/resources/images/pool-logo-white.png rename to src/site/resources/images/logo.png diff --git a/src/site/resources/profile.jacoco b/src/site/resources/profile.jacoco index e69de29bb..0314c63ff 100644 --- a/src/site/resources/profile.jacoco +++ b/src/site/resources/profile.jacoco @@ -0,0 +1,16 @@ +// 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 +// +// https://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. diff --git a/src/site/site.xml b/src/site/site.xml index feb801544..c494d0a4f 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -7,7 +7,7 @@ (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 + https://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, @@ -15,29 +15,32 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - Commons Pool - /images/pool-logo-white.png - /index.html - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/site/xdoc/download_pool.xml b/src/site/xdoc/download_pool.xml index a95fa034b..23ba9f55c 100644 --- a/src/site/xdoc/download_pool.xml +++ b/src/site/xdoc/download_pool.xml @@ -7,7 +7,7 @@ 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 + https://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, @@ -113,7 +113,7 @@ limitations under the License.

-
+
@@ -143,7 +143,7 @@ limitations under the License.
-
+
diff --git a/src/site/xdoc/examples.xml b/src/site/xdoc/examples.xml index 78f8f5b83..dfdc8afd5 100644 --- a/src/site/xdoc/examples.xml +++ b/src/site/xdoc/examples.xml @@ -7,7 +7,7 @@ (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 + https://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, @@ -15,11 +15,12 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Examples Apache Commons Documentation Team - $Id$ @@ -76,7 +77,7 @@ public class ReaderUtil { import java.io.IOException; import java.io.Reader; -import org.apache.commons.pool2.ObjectPool; +import org.apache.commons.pool3.ObjectPool; public class ReaderUtil { @@ -140,9 +141,9 @@ public class ReaderUtil { StringBuffers as used above.

-import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; public class StringBufferFactory extends BasePooledObjectFactory<StringBuffer> { diff --git a/src/site/xdoc/guide/index.xml b/src/site/xdoc/guide/index.xml index 0887cf815..e18b94792 100644 --- a/src/site/xdoc/guide/index.xml +++ b/src/site/xdoc/guide/index.xml @@ -7,7 +7,7 @@ (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 + https://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, @@ -16,8 +16,9 @@ limitations under the License. --> - - + Developers Guide Apache Commons Documentation Team diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index 997d7cff4..0775639c4 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -7,7 +7,7 @@ (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 + https://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, @@ -15,11 +15,12 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Overview Apache Commons Documentation Team - $Id$ @@ -33,6 +34,7 @@ instance tracking and pool monitoring.

    +
  • Version 3.0.0 and up requires Java 8 or above.
  • Version 2.7.x and up requires Java 8 or above.
  • Version 2.6.x requires Java 7 or above.
  • Version 2.5.x requires Java 7 or above.
  • @@ -50,7 +52,7 @@

    The - org.apache.commons.pool2 + org.apache.commons.pool3 package defines a handful of pooling interfaces and some base classes that may be useful when creating new pool implementations.

    @@ -112,7 +114,7 @@ public interface KeyedPooledObjectFactory<K,V> {

    The - org.apache.commons.pool2.impl + org.apache.commons.pool3.impl package provides some Pool implementations.

    @@ -156,7 +158,7 @@ public interface KeyedPooledObjectFactory<K,V> { The migration from Apache Commons Pool 1.x to 2.x will require some code changes. The most significant changes are the changes in package name from org.apache.commons.pool to - org.apache.commons.pool2 and the change in the implementation + org.apache.commons.pool3 and the change in the implementation classes to use PooledObjectFactorys, as described above.

    diff --git a/src/site/xdoc/issue-tracking.xml b/src/site/xdoc/issue-tracking.xml index 4137eff37..48cb540f3 100644 --- a/src/site/xdoc/issue-tracking.xml +++ b/src/site/xdoc/issue-tracking.xml @@ -7,7 +7,7 @@ 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 + https://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, diff --git a/src/site/xdoc/mail-lists.xml b/src/site/xdoc/mail-lists.xml index 030956f35..609b4514a 100644 --- a/src/site/xdoc/mail-lists.xml +++ b/src/site/xdoc/mail-lists.xml @@ -7,7 +7,7 @@ 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 + https://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, diff --git a/src/site/xdoc/releases.xml b/src/site/xdoc/releases.xml index 2240b17e6..24e1fb9d3 100644 --- a/src/site/xdoc/releases.xml +++ b/src/site/xdoc/releases.xml @@ -7,7 +7,7 @@ (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 + https://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, @@ -15,11 +15,12 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Downloads Apache Commons Documentation Team - $Id$ diff --git a/src/test/java/org/apache/commons/pool2/impl/TestBaseGenericObjectPool.java b/src/test/java/org/apache/commons/pool2/impl/TestBaseGenericObjectPool.java deleted file mode 100644 index 489ae9c49..000000000 --- a/src/test/java/org/apache/commons/pool2/impl/TestBaseGenericObjectPool.java +++ /dev/null @@ -1,143 +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. - */ - -package org.apache.commons.pool2.impl; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.lang.management.ManagementFactory; -import java.time.Duration; -import java.util.ArrayList; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.management.MBeanServer; -import javax.management.ObjectName; - -import org.apache.commons.pool2.TestException; -import org.apache.commons.pool2.Waiter; -import org.apache.commons.pool2.WaiterFactory; -import org.apache.commons.pool2.impl.TestGenericObjectPool.SimpleFactory; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; - -/** - */ -public class TestBaseGenericObjectPool { - - BaseGenericObjectPool pool; - SimpleFactory factory; - - @BeforeEach - public void setUp() { - factory = new SimpleFactory(); - pool = new GenericObjectPool<>(factory); - } - - @AfterEach - public void tearDown() { - pool.close(); - pool = null; - factory = null; - } - - @Test - public void testActiveTimeStatistics() { - for (int i = 0; i < 99; i++) { // must be < MEAN_TIMING_STATS_CACHE_SIZE - pool.updateStatsReturn(Duration.ofMillis(i)); - } - assertEquals(49, pool.getMeanActiveTimeMillis(), Double.MIN_VALUE); - } - - @Test - public void testBorrowWaitStatistics() { - final DefaultPooledObject p = (DefaultPooledObject) factory.makeObject(); - pool.updateStatsBorrow(p, Duration.ofMillis(10)); - pool.updateStatsBorrow(p, Duration.ofMillis(20)); - pool.updateStatsBorrow(p, Duration.ofMillis(20)); - pool.updateStatsBorrow(p, Duration.ofMillis(30)); - assertEquals(20, pool.getMeanBorrowWaitTimeMillis(), Double.MIN_VALUE); - assertEquals(30, pool.getMaxBorrowWaitTimeMillis(), 0); - } - - public void testBorrowWaitStatisticsMax() { - final DefaultPooledObject p = (DefaultPooledObject) factory.makeObject(); - assertEquals(0, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); - pool.updateStatsBorrow(p, Duration.ZERO); - assertEquals(0, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); - pool.updateStatsBorrow(p, Duration.ofMillis(20)); - assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); - pool.updateStatsBorrow(p, Duration.ofMillis(20)); - assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); - pool.updateStatsBorrow(p, Duration.ofMillis(10)); - assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); - } - - @Test - public void testEvictionTimerMultiplePools() throws InterruptedException { - final AtomicIntegerFactory factory = new AtomicIntegerFactory(); - factory.setValidateLatency(50); - try (final GenericObjectPool evictingPool = new GenericObjectPool<>(factory)) { - evictingPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); - evictingPool.setNumTestsPerEvictionRun(5); - evictingPool.setTestWhileIdle(true); - evictingPool.setMinEvictableIdleTime(Duration.ofMillis(50)); - for (int i = 0; i < 10; i++) { - try { - evictingPool.addObject(); - } catch (final Exception e) { - e.printStackTrace(); - } - } - - for (int i = 0; i < 1000; i++) { - try (final GenericObjectPool nonEvictingPool = new GenericObjectPool<>(factory)) { - // empty - } - } - - Thread.sleep(1000); - assertEquals(0, evictingPool.getNumIdle()); - } - } - - /** - * POOL-393 - * Tests JMX registration does not add too much latency to pool creation. - */ - @SuppressWarnings("resource") // pools closed in finally block - @Test - @Timeout(value = 10_000, unit = TimeUnit.MILLISECONDS) - public void testJMXRegistrationLatency() { - final int numPools = 1000; - final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - final ArrayList> pools = new ArrayList<>(); - try { - // final long startTime = System.currentTimeMillis(); - for (int i = 0; i < numPools; i++) { - pools.add(new GenericObjectPool<>(new WaiterFactory<>(0, 0, 0, 0, 0, 0), new GenericObjectPoolConfig<>())); - } - // System.out.println("Duration: " + (System.currentTimeMillis() - startTime)); - final ObjectName oname = pools.get(numPools - 1).getJmxName(); - assertEquals(1, mbs.queryNames(oname, null).size()); - } finally { - pools.forEach(GenericObjectPool::close); - } - } -} diff --git a/src/test/java/org/apache/commons/pool2/impl/TestSynchronizedPooledObjectFactory.java b/src/test/java/org/apache/commons/pool2/impl/TestSynchronizedPooledObjectFactory.java deleted file mode 100644 index ba5f7f923..000000000 --- a/src/test/java/org/apache/commons/pool2/impl/TestSynchronizedPooledObjectFactory.java +++ /dev/null @@ -1,136 +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. - */ - -package org.apache.commons.pool2.impl; - -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; - -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectFactory; - -/** - * Copies PoolUtil's private static class SynchronizedPooledObjectFactory. - * - * A fully synchronized PooledObjectFactory that wraps a PooledObjectFactory and - * synchronizes access to the wrapped factory methods. - *

    - * Note: This should not be used on pool implementations that already - * provide proper synchronization such as the pools provided in the Commons Pool - * library. - *

    - */ -final class TestSynchronizedPooledObjectFactory implements PooledObjectFactory { - - /** Synchronization lock */ - private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); - - /** Wrapped factory */ - private final PooledObjectFactory factory; - - /** - * Constructs a SynchronizedPoolableObjectFactory wrapping the given factory. - * - * @param factory - * underlying factory to wrap - * @throws IllegalArgumentException - * if the factory is null - */ - TestSynchronizedPooledObjectFactory(final PooledObjectFactory factory) throws IllegalArgumentException { - if (factory == null) { - throw new IllegalArgumentException("factory must not be null."); - } - this.factory = factory; - } - - /** - * {@inheritDoc} - */ - @Override - public void activateObject(final PooledObject p) throws E { - writeLock.lock(); - try { - factory.activateObject(p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void destroyObject(final PooledObject p) throws E { - writeLock.lock(); - try { - factory.destroyObject(p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public PooledObject makeObject() throws E { - writeLock.lock(); - try { - return factory.makeObject(); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void passivateObject(final PooledObject p) throws E { - writeLock.lock(); - try { - factory.passivateObject(p); - } finally { - writeLock.unlock(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append("SynchronizedPoolableObjectFactory"); - sb.append("{factory=").append(factory); - sb.append('}'); - return sb.toString(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean validateObject(final PooledObject p) { - writeLock.lock(); - try { - return factory.validateObject(p); - } finally { - writeLock.unlock(); - } - } -} diff --git a/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithJdkProxy.java b/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithJdkProxy.java deleted file mode 100644 index ec6bf618b..000000000 --- a/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithJdkProxy.java +++ /dev/null @@ -1,27 +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. - */ -package org.apache.commons.pool2.proxy; - -public class TestProxiedObjectPoolWithJdkProxy - extends AbstractTestProxiedObjectPool { - - @Override - protected ProxySource getproxySource() { - return new JdkProxySource<>(this.getClass().getClassLoader(), - new Class[] { TestObject.class }); - } -} diff --git a/src/test/java/org/apache/commons/pool2/AbstractTestKeyedObjectPool.java b/src/test/java/org/apache/commons/pool3/AbstractTestKeyedObjectPool.java similarity index 74% rename from src/test/java/org/apache/commons/pool2/AbstractTestKeyedObjectPool.java rename to src/test/java/org/apache/commons/pool3/AbstractTestKeyedObjectPool.java index cbd18860f..31410e500 100644 --- a/src/test/java/org/apache/commons/pool2/AbstractTestKeyedObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/AbstractTestKeyedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -24,8 +24,8 @@ import java.util.List; import java.util.NoSuchElementException; -import org.apache.commons.pool2.impl.DefaultPooledObject; -import org.apache.commons.pool2.impl.GenericKeyedObjectPool; +import org.apache.commons.pool3.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.GenericKeyedObjectPool; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -160,18 +160,19 @@ public boolean validateObject(final Object key, final PooledObject obj) } } - private static class TestFactory extends BaseKeyedPooledObjectFactory { + private static final class TestFactory extends BaseKeyedPooledObjectFactory { @Override public Object create(final Object key) { return new Object(); } + @Override public PooledObject wrap(final Object value) { return new DefaultPooledObject<>(value); } } - protected static final String KEY = "key"; + private static final String KEY = "key"; private KeyedObjectPool pool; @@ -187,12 +188,10 @@ private void clear(final FailingKeyedPooledObjectFactory factory, final Listth - * object (zero indexed) created by the pool - * for the given key. + * Return what we expect to be the nth object (zero indexed) created by the pool for the given key. + * * @param key Key for the object to be obtained * @param n index of the object to be obtained - * * @return the requested object */ protected abstract Object getNthObject(Object key, int n); @@ -202,24 +201,20 @@ private void clear(final FailingKeyedPooledObjectFactory factory, final ListminCapacity - * idle and active objects, or - * throw {@link IllegalArgumentException} - * if such a pool cannot be created. - * @param minCapacity Minimum capacity of the pool to create + * Creates an {@link KeyedObjectPool} instance that can contain at least minCapacity idle and active objects, or throw + * {@link IllegalArgumentException} if such a pool cannot be created. * + * @param Type of exception thrown by this pool. + * @param minCapacity Minimum capacity of the pool to create * @return the newly created keyed object pool */ protected abstract KeyedObjectPool makeEmptyPool(int minCapacity); /** - * Creates an {@code KeyedObjectPool} with the specified factory. - * The pool should be in a default configuration and conform to the expected - * behaviors described in {@link KeyedObjectPool}. - * Generally speaking there should be no limits on the various object counts. + * Creates an {@code KeyedObjectPool} with the specified factory. The pool should be in a default configuration and conform to the expected behaviors + * described in {@link KeyedObjectPool}. Generally speaking there should be no limits on the various object counts. * - * @param The type of exception thrown by the pool + * @param The type of exception thrown by the pool * @param factory Factory to use to associate with the pool * @return The newly created empty pool */ @@ -228,7 +223,7 @@ private void clear(final FailingKeyedPooledObjectFactory factory, final List void reset(final KeyedObjectPool pool, final FailingKeyedPooledObjectFactory factory, - final List expectedMethods) throws E { + final List expectedMethods) throws E { pool.clear(); clear(factory, expectedMethods); factory.reset(); @@ -240,7 +235,7 @@ public void tearDown() { } @Test - public void testBaseAddObject() { + void testBaseAddObject() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException uoe) { @@ -248,26 +243,26 @@ public void testBaseAddObject() { } final Object key = makeKey(0); try { - assertEquals(0,pool.getNumIdle()); - assertEquals(0,pool.getNumActive()); - assertEquals(0,pool.getNumIdle(key)); - assertEquals(0,pool.getNumActive(key)); + assertEquals(0, pool.getNumIdle()); + assertEquals(0, pool.getNumActive()); + assertEquals(0, pool.getNumIdle(key)); + assertEquals(0, pool.getNumActive(key)); pool.addObject(key); - assertEquals(1,pool.getNumIdle()); - assertEquals(0,pool.getNumActive()); - assertEquals(1,pool.getNumIdle(key)); - assertEquals(0,pool.getNumActive(key)); + assertEquals(1, pool.getNumIdle()); + assertEquals(0, pool.getNumActive()); + assertEquals(1, pool.getNumIdle(key)); + assertEquals(0, pool.getNumActive(key)); final Object obj = pool.borrowObject(key); - assertEquals(getNthObject(key,0),obj); - assertEquals(0,pool.getNumIdle()); - assertEquals(1,pool.getNumActive()); - assertEquals(0,pool.getNumIdle(key)); - assertEquals(1,pool.getNumActive(key)); - pool.returnObject(key,obj); - assertEquals(1,pool.getNumIdle()); - assertEquals(0,pool.getNumActive()); - assertEquals(1,pool.getNumIdle(key)); - assertEquals(0,pool.getNumActive(key)); + assertEquals(getNthObject(key, 0), obj); + assertEquals(0, pool.getNumIdle()); + assertEquals(1, pool.getNumActive()); + assertEquals(0, pool.getNumIdle(key)); + assertEquals(1, pool.getNumActive(key)); + pool.returnObject(key, obj); + assertEquals(1, pool.getNumIdle()); + assertEquals(0, pool.getNumActive()); + assertEquals(1, pool.getNumIdle(key)); + assertEquals(0, pool.getNumActive(key)); } catch (final UnsupportedOperationException e) { return; // skip this test if one of those calls is unsupported } finally { @@ -276,7 +271,7 @@ public void testBaseAddObject() { } @Test - public void testBaseBorrow() { + void testBaseBorrow() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException uoe) { @@ -284,17 +279,17 @@ public void testBaseBorrow() { } final Object keya = makeKey(0); final Object keyb = makeKey(1); - assertEquals(getNthObject(keya,0),pool.borrowObject(keya),"1"); - assertEquals(getNthObject(keyb,0),pool.borrowObject(keyb),"2"); - assertEquals(getNthObject(keyb,1),pool.borrowObject(keyb),"3"); - assertEquals(getNthObject(keya,1),pool.borrowObject(keya),"4"); - assertEquals(getNthObject(keyb,2),pool.borrowObject(keyb),"5"); - assertEquals(getNthObject(keya,2),pool.borrowObject(keya),"6"); + assertEquals(getNthObject(keya, 0), pool.borrowObject(keya), "1"); + assertEquals(getNthObject(keyb, 0), pool.borrowObject(keyb), "2"); + assertEquals(getNthObject(keyb, 1), pool.borrowObject(keyb), "3"); + assertEquals(getNthObject(keya, 1), pool.borrowObject(keya), "4"); + assertEquals(getNthObject(keyb, 2), pool.borrowObject(keyb), "5"); + assertEquals(getNthObject(keya, 2), pool.borrowObject(keya), "6"); pool.close(); } @Test - public void testBaseBorrowReturn() { + void testBaseBorrowReturn() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException uoe) { @@ -302,116 +297,116 @@ public void testBaseBorrowReturn() { } final Object keya = makeKey(0); Object obj0 = pool.borrowObject(keya); - assertEquals(getNthObject(keya,0),obj0); + assertEquals(getNthObject(keya, 0), obj0); Object obj1 = pool.borrowObject(keya); - assertEquals(getNthObject(keya,1),obj1); + assertEquals(getNthObject(keya, 1), obj1); Object obj2 = pool.borrowObject(keya); - assertEquals(getNthObject(keya,2),obj2); - pool.returnObject(keya,obj2); + assertEquals(getNthObject(keya, 2), obj2); + pool.returnObject(keya, obj2); obj2 = pool.borrowObject(keya); - assertEquals(getNthObject(keya,2),obj2); - pool.returnObject(keya,obj1); + assertEquals(getNthObject(keya, 2), obj2); + pool.returnObject(keya, obj1); obj1 = pool.borrowObject(keya); - assertEquals(getNthObject(keya,1),obj1); - pool.returnObject(keya,obj0); - pool.returnObject(keya,obj2); + assertEquals(getNthObject(keya, 1), obj1); + pool.returnObject(keya, obj0); + pool.returnObject(keya, obj2); obj2 = pool.borrowObject(keya); if (isLifo()) { - assertEquals(getNthObject(keya,2),obj2); + assertEquals(getNthObject(keya, 2), obj2); } if (isFifo()) { - assertEquals(getNthObject(keya,0),obj2); + assertEquals(getNthObject(keya, 0), obj2); } obj0 = pool.borrowObject(keya); if (isLifo()) { - assertEquals(getNthObject(keya,0),obj0); + assertEquals(getNthObject(keya, 0), obj0); } if (isFifo()) { - assertEquals(getNthObject(keya,2),obj0); + assertEquals(getNthObject(keya, 2), obj0); } pool.close(); } @Test - public void testBaseClear() { + void testBaseClear() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException uoe) { return; // skip this test if unsupported } final Object keya = makeKey(0); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); final Object obj0 = pool.borrowObject(keya); final Object obj1 = pool.borrowObject(keya); - assertEquals(2,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); - pool.returnObject(keya,obj1); - pool.returnObject(keya,obj0); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(2,pool.getNumIdle(keya)); + assertEquals(2, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); + pool.returnObject(keya, obj1); + pool.returnObject(keya, obj0); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(2, pool.getNumIdle(keya)); pool.clear(keya); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); final Object obj2 = pool.borrowObject(keya); - assertEquals(getNthObject(keya,2),obj2); + assertEquals(getNthObject(keya, 2), obj2); pool.close(); } @Test - public void testBaseInvalidateObject() { + void testBaseInvalidateObject() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException uoe) { return; // skip this test if unsupported } final Object keya = makeKey(0); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); final Object obj0 = pool.borrowObject(keya); final Object obj1 = pool.borrowObject(keya); - assertEquals(2,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); - pool.invalidateObject(keya,obj0); - assertEquals(1,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); - pool.invalidateObject(keya,obj1); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); + assertEquals(2, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); + pool.invalidateObject(keya, obj0); + assertEquals(1, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); + pool.invalidateObject(keya, obj1); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); pool.close(); } @Test - public void testBaseNumActiveNumIdle() { + void testBaseNumActiveNumIdle() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException uoe) { return; // skip this test if unsupported } final Object keya = makeKey(0); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); final Object obj0 = pool.borrowObject(keya); - assertEquals(1,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); + assertEquals(1, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); final Object obj1 = pool.borrowObject(keya); - assertEquals(2,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); - pool.returnObject(keya,obj1); - assertEquals(1,pool.getNumActive(keya)); - assertEquals(1,pool.getNumIdle(keya)); - pool.returnObject(keya,obj0); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(2,pool.getNumIdle(keya)); - - assertEquals(0,pool.getNumActive("xyzzy12345")); - assertEquals(0,pool.getNumIdle("xyzzy12345")); + assertEquals(2, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); + pool.returnObject(keya, obj1); + assertEquals(1, pool.getNumActive(keya)); + assertEquals(1, pool.getNumIdle(keya)); + pool.returnObject(keya, obj0); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(2, pool.getNumIdle(keya)); + + assertEquals(0, pool.getNumActive("xyzzy12345")); + assertEquals(0, pool.getNumIdle("xyzzy12345")); pool.close(); } @Test - public void testBaseNumActiveNumIdle2() { + void testBaseNumActiveNumIdle2() { try { pool = makeEmptyPool(6); } catch (final UnsupportedOperationException uoe) { @@ -419,58 +414,58 @@ public void testBaseNumActiveNumIdle2() { } final Object keya = makeKey(0); final Object keyb = makeKey(1); - assertEquals(0,pool.getNumActive()); - assertEquals(0,pool.getNumIdle()); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); - assertEquals(0,pool.getNumActive(keyb)); - assertEquals(0,pool.getNumIdle(keyb)); + assertEquals(0, pool.getNumActive()); + assertEquals(0, pool.getNumIdle()); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); + assertEquals(0, pool.getNumActive(keyb)); + assertEquals(0, pool.getNumIdle(keyb)); final Object objA0 = pool.borrowObject(keya); final Object objB0 = pool.borrowObject(keyb); - assertEquals(2,pool.getNumActive()); - assertEquals(0,pool.getNumIdle()); - assertEquals(1,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); - assertEquals(1,pool.getNumActive(keyb)); - assertEquals(0,pool.getNumIdle(keyb)); + assertEquals(2, pool.getNumActive()); + assertEquals(0, pool.getNumIdle()); + assertEquals(1, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); + assertEquals(1, pool.getNumActive(keyb)); + assertEquals(0, pool.getNumIdle(keyb)); final Object objA1 = pool.borrowObject(keya); final Object objB1 = pool.borrowObject(keyb); - assertEquals(4,pool.getNumActive()); - assertEquals(0,pool.getNumIdle()); - assertEquals(2,pool.getNumActive(keya)); - assertEquals(0,pool.getNumIdle(keya)); - assertEquals(2,pool.getNumActive(keyb)); - assertEquals(0,pool.getNumIdle(keyb)); - - pool.returnObject(keya,objA0); - pool.returnObject(keyb,objB0); - - assertEquals(2,pool.getNumActive()); - assertEquals(2,pool.getNumIdle()); - assertEquals(1,pool.getNumActive(keya)); - assertEquals(1,pool.getNumIdle(keya)); - assertEquals(1,pool.getNumActive(keyb)); - assertEquals(1,pool.getNumIdle(keyb)); - - pool.returnObject(keya,objA1); - pool.returnObject(keyb,objB1); - - assertEquals(0,pool.getNumActive()); - assertEquals(4,pool.getNumIdle()); - assertEquals(0,pool.getNumActive(keya)); - assertEquals(2,pool.getNumIdle(keya)); - assertEquals(0,pool.getNumActive(keyb)); - assertEquals(2,pool.getNumIdle(keyb)); + assertEquals(4, pool.getNumActive()); + assertEquals(0, pool.getNumIdle()); + assertEquals(2, pool.getNumActive(keya)); + assertEquals(0, pool.getNumIdle(keya)); + assertEquals(2, pool.getNumActive(keyb)); + assertEquals(0, pool.getNumIdle(keyb)); + + pool.returnObject(keya, objA0); + pool.returnObject(keyb, objB0); + + assertEquals(2, pool.getNumActive()); + assertEquals(2, pool.getNumIdle()); + assertEquals(1, pool.getNumActive(keya)); + assertEquals(1, pool.getNumIdle(keya)); + assertEquals(1, pool.getNumActive(keyb)); + assertEquals(1, pool.getNumIdle(keyb)); + + pool.returnObject(keya, objA1); + pool.returnObject(keyb, objB1); + + assertEquals(0, pool.getNumActive()); + assertEquals(4, pool.getNumIdle()); + assertEquals(0, pool.getNumActive(keya)); + assertEquals(2, pool.getNumIdle(keya)); + assertEquals(0, pool.getNumActive(keyb)); + assertEquals(2, pool.getNumIdle(keyb)); pool.close(); } @Test - public void testClosedPoolBehavior() { + void testClosedPoolBehavior() { final KeyedObjectPool pool; try { pool = makeEmptyPool(new TestFactory()); @@ -483,20 +478,19 @@ public void testClosedPoolBehavior() { pool.close(); - assertThrows(IllegalStateException.class, () -> pool.addObject(KEY), - "A closed pool must throw an IllegalStateException when addObject is called."); + assertThrows(IllegalStateException.class, () -> pool.addObject(KEY), "A closed pool must throw an IllegalStateException when addObject is called."); assertThrows(IllegalStateException.class, () -> pool.borrowObject(KEY), "A closed pool must throw an IllegalStateException when borrowObject is called."); // The following should not throw exceptions just because the pool is closed. - assertEquals( 0, pool.getNumIdle(KEY),"A closed pool shouldn't have any idle objects."); - assertEquals( 0, pool.getNumIdle(),"A closed pool shouldn't have any idle objects."); + assertEquals(0, pool.getNumIdle(KEY), "A closed pool shouldn't have any idle objects."); + assertEquals(0, pool.getNumIdle(), "A closed pool shouldn't have any idle objects."); pool.getNumActive(); pool.getNumActive(KEY); pool.returnObject(KEY, o1); - assertEquals( 0, pool.getNumIdle(KEY),"returnObject should not add items back into the idle object pool for a closed pool."); - assertEquals( 0, pool.getNumIdle(),"returnObject should not add items back into the idle object pool for a closed pool."); + assertEquals(0, pool.getNumIdle(KEY), "returnObject should not add items back into the idle object pool for a closed pool."); + assertEquals(0, pool.getNumIdle(), "returnObject should not add items back into the idle object pool for a closed pool."); pool.invalidateObject(KEY, o2); pool.clear(KEY); pool.clear(); @@ -504,7 +498,7 @@ public void testClosedPoolBehavior() { } @Test - public void testKPOFAddObjectUsage() { + void testKPOFAddObjectUsage() { final FailingKeyedPooledObjectFactory factory = new FailingKeyedPooledObjectFactory(); final KeyedObjectPool pool; try { @@ -542,7 +536,7 @@ public void testKPOFAddObjectUsage() { } @Test - public void testKPOFBorrowObjectUsages() { + void testKPOFBorrowObjectUsages() { final FailingKeyedPooledObjectFactory factory = new FailingKeyedPooledObjectFactory(); final KeyedObjectPool pool; try { @@ -551,7 +545,6 @@ public void testKPOFBorrowObjectUsages() { return; // test not supported } final List expectedMethods = new ArrayList<>(); - Object obj; if (pool instanceof GenericKeyedObjectPool) { ((GenericKeyedObjectPool) pool).setTestOnBorrow(true); @@ -562,7 +555,7 @@ public void testKPOFBorrowObjectUsages() { // existing idle object should be activated and validated pool.addObject(KEY); clear(factory, expectedMethods); - obj = pool.borrowObject(KEY); + final Object obj = pool.borrowObject(KEY); expectedMethods.add(new MethodCall("activateObject", KEY, ZERO)); expectedMethods.add(new MethodCall("validateObject", KEY, ZERO).returned(Boolean.TRUE)); assertEquals(expectedMethods, factory.getMethodCalls()); @@ -577,7 +570,6 @@ public void testKPOFBorrowObjectUsages() { expectedMethods.add(new MethodCall("makeObject", KEY)); assertEquals(expectedMethods, factory.getMethodCalls()); - // when activateObject fails in borrowObject, a new object should be borrowed/created reset(pool, factory, expectedMethods); pool.addObject(KEY); @@ -615,7 +607,7 @@ public void testKPOFBorrowObjectUsages() { } @Test - public void testKPOFClearUsages() { + void testKPOFClearUsages() { final FailingKeyedPooledObjectFactory factory = new FailingKeyedPooledObjectFactory(); final KeyedObjectPool pool; try { @@ -637,11 +629,10 @@ public void testKPOFClearUsages() { pool.close(); } - @Test - public void testKPOFCloseUsages() { + void testKPOFCloseUsages() { final FailingKeyedPooledObjectFactory factory = new FailingKeyedPooledObjectFactory(); - KeyedObjectPool pool; + final KeyedObjectPool pool; try { pool = makeEmptyPool(factory); } catch (final UnsupportedOperationException uoe) { @@ -654,7 +645,7 @@ public void testKPOFCloseUsages() { pool.close(); // Test exception handling close should swallow failures - try (final KeyedObjectPool pool2 = makeEmptyPool(factory)) { + try (KeyedObjectPool pool2 = makeEmptyPool(factory)) { reset(pool2, factory, expectedMethods); factory.setDestroyObjectFail(true); pool2.addObjects(KEY, 5); @@ -662,7 +653,7 @@ public void testKPOFCloseUsages() { } @Test - public void testKPOFInvalidateObjectUsages() throws InterruptedException { + void testKPOFInvalidateObjectUsages() throws InterruptedException { final FailingKeyedPooledObjectFactory factory = new FailingKeyedPooledObjectFactory(); final KeyedObjectPool pool; try { @@ -671,11 +662,10 @@ public void testKPOFInvalidateObjectUsages() throws InterruptedException { return; // test not supported } final List expectedMethods = new ArrayList<>(); - Object obj; // Test correct behavior code paths - obj = pool.borrowObject(KEY); + final Object obj = pool.borrowObject(KEY); clear(factory, expectedMethods); // invalidated object should be destroyed @@ -696,7 +686,7 @@ public void testKPOFInvalidateObjectUsages() throws InterruptedException { } @Test - public void testKPOFReturnObjectUsages() { + void testKPOFReturnObjectUsages() { final FailingKeyedPooledObjectFactory factory = new FailingKeyedPooledObjectFactory(); final KeyedObjectPool pool; try { @@ -734,7 +724,7 @@ public void testKPOFReturnObjectUsages() { expectedMethods.add(new MethodCall("passivateObject", KEY, obj)); AbstractTestObjectPool.removeDestroyObjectCall(factory.getMethodCalls()); // The exact timing of destroyObject is flexible here. assertEquals(expectedMethods, factory.getMethodCalls()); - assertEquals(1, pool.getNumIdle(KEY)); // Not added + assertEquals(1, pool.getNumIdle(KEY)); // Not added assertEquals(1, pool.getNumActive(KEY)); // But not active reset(pool, factory, expectedMethods); @@ -754,9 +744,9 @@ public void testKPOFReturnObjectUsages() { } @Test - public void testToString() { + void testToString() { final FailingKeyedPooledObjectFactory factory = new FailingKeyedPooledObjectFactory(); - try (final KeyedObjectPool pool = makeEmptyPool(factory)) { + try (KeyedObjectPool pool = makeEmptyPool(factory)) { pool.toString(); } catch (final UnsupportedOperationException uoe) { return; // test not supported diff --git a/src/test/java/org/apache/commons/pool2/AbstractTestObjectPool.java b/src/test/java/org/apache/commons/pool3/AbstractTestObjectPool.java similarity index 92% rename from src/test/java/org/apache/commons/pool2/AbstractTestObjectPool.java rename to src/test/java/org/apache/commons/pool3/AbstractTestObjectPool.java index 226224572..2c19bab3b 100644 --- a/src/test/java/org/apache/commons/pool2/AbstractTestObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/AbstractTestObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,8 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; - +package org.apache.commons.pool3; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -25,8 +24,8 @@ import java.util.List; import java.util.NoSuchElementException; -import org.apache.commons.pool2.impl.GenericObjectPool; -import org.apache.commons.pool2.impl.SoftReferenceObjectPool; +import org.apache.commons.pool3.impl.GenericObjectPool; +import org.apache.commons.pool3.impl.SoftReferenceObjectPool; import org.junit.jupiter.api.Test; /** @@ -43,11 +42,13 @@ static void removeDestroyObjectCall(final List calls) { calls.removeIf(call -> "destroyObject".equals(call.getName())); } - private static void reset(final ObjectPool pool, final MethodCallPoolableObjectFactory factory, final List expectedMethods) throws Exception { + private static void reset(final ObjectPool pool, final MethodCallPoolableObjectFactory factory, final List expectedMethods) + throws Exception { pool.clear(); clear(factory, expectedMethods); factory.reset(); } + // Deliberate choice to create a new object in case future unit tests check // for a specific object. private final Integer ZERO = Integer.valueOf(0); @@ -62,16 +63,14 @@ private static void reset(final ObjectPool pool, final MethodCallPool * * @param The exception type throws by the pool * @param factory The factory to be used by the object pool - * * @return the newly created empty pool - * * @throws UnsupportedOperationException if the pool being tested does not * follow pool contracts. */ protected abstract ObjectPool makeEmptyPool(PooledObjectFactory factory) throws UnsupportedOperationException; @Test - public void testClosedPoolBehavior() throws Exception { + void testClosedPoolBehavior() throws Exception { final ObjectPool pool; try { pool = makeEmptyPool(new MethodCallPoolableObjectFactory()); @@ -89,31 +88,31 @@ public void testClosedPoolBehavior() throws Exception { // The following should not throw exceptions just because the pool is closed. if (pool.getNumIdle() >= 0) { - assertEquals( 0, pool.getNumIdle(),"A closed pool shouldn't have any idle objects."); + assertEquals(0, pool.getNumIdle(), "A closed pool shouldn't have any idle objects."); } if (pool.getNumActive() >= 0) { - assertEquals( 2, pool.getNumActive(),"A closed pool should still keep count of active objects."); + assertEquals(2, pool.getNumActive(), "A closed pool should still keep count of active objects."); } pool.returnObject(o1); if (pool.getNumIdle() >= 0) { - assertEquals( 0, pool.getNumIdle(),"returnObject should not add items back into the idle object pool for a closed pool."); + assertEquals(0, pool.getNumIdle(), "returnObject should not add items back into the idle object pool for a closed pool."); } if (pool.getNumActive() >= 0) { - assertEquals( 1, pool.getNumActive(),"A closed pool should still keep count of active objects."); + assertEquals(1, pool.getNumActive(), "A closed pool should still keep count of active objects."); } pool.invalidateObject(o2); if (pool.getNumIdle() >= 0) { - assertEquals( 0, pool.getNumIdle(),"invalidateObject must not add items back into the idle object pool."); + assertEquals(0, pool.getNumIdle(), "invalidateObject must not add items back into the idle object pool."); } if (pool.getNumActive() >= 0) { - assertEquals( 0, pool.getNumActive(),"A closed pool should still keep count of active objects."); + assertEquals(0, pool.getNumActive(), "A closed pool should still keep count of active objects."); } pool.clear(); pool.close(); } @Test - public void testPOFAddObjectUsage() throws Exception { + void testPOFAddObjectUsage() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { @@ -164,7 +163,7 @@ public void testPOFAddObjectUsage() throws Exception { } @Test - public void testPOFBorrowObjectUsages() throws Exception { + void testPOFBorrowObjectUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { @@ -176,14 +175,13 @@ public void testPOFBorrowObjectUsages() throws Exception { ((GenericObjectPool) pool).setTestOnBorrow(true); } final List expectedMethods = new ArrayList<>(); - Object obj; // Test correct behavior code paths // existing idle object should be activated and validated pool.addObject(); clear(factory, expectedMethods); - obj = pool.borrowObject(); + final Object obj = pool.borrowObject(); expectedMethods.add(new MethodCall("activateObject", ZERO)); expectedMethods.add(new MethodCall("validateObject", ZERO).returned(Boolean.TRUE)); assertEquals(expectedMethods, factory.getMethodCalls()); @@ -198,7 +196,6 @@ public void testPOFBorrowObjectUsages() throws Exception { expectedMethods.add(new MethodCall("makeObject")); assertEquals(expectedMethods, factory.getMethodCalls()); - // when activateObject fails in borrowObject, a new object should be borrowed/created reset(pool, factory, expectedMethods); pool.addObject(); @@ -236,7 +233,7 @@ public void testPOFBorrowObjectUsages() throws Exception { } @Test - public void testPOFClearUsages() throws Exception { + void testPOFClearUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { @@ -259,7 +256,7 @@ public void testPOFClearUsages() throws Exception { } @Test - public void testPOFCloseUsages() throws Exception { + void testPOFCloseUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); ObjectPool pool; try { @@ -273,7 +270,6 @@ public void testPOFCloseUsages() throws Exception { pool.addObjects(5); pool.close(); - // Test exception handling close should swallow failures try { pool = makeEmptyPool(factory); @@ -287,7 +283,7 @@ public void testPOFCloseUsages() throws Exception { } @Test - public void testPOFInvalidateObjectUsages() throws Exception { + void testPOFInvalidateObjectUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { @@ -296,11 +292,10 @@ public void testPOFInvalidateObjectUsages() throws Exception { return; // test not supported } final List expectedMethods = new ArrayList<>(); - Object obj; // Test correct behavior code paths - obj = pool.borrowObject(); + final Object obj = pool.borrowObject(); clear(factory, expectedMethods); // invalidated object should be destroyed @@ -321,7 +316,7 @@ public void testPOFInvalidateObjectUsages() throws Exception { } @Test - public void testPOFReturnObjectUsages() throws Exception { + void testPOFReturnObjectUsages() throws Exception { final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory(); final ObjectPool pool; try { @@ -381,7 +376,7 @@ public void testPOFReturnObjectUsages() throws Exception { } @Test - public void testToString() { + void testToString() { final ObjectPool pool; try { pool = makeEmptyPool(new MethodCallPoolableObjectFactory()); diff --git a/src/test/java/org/apache/commons/pool2/MethodCall.java b/src/test/java/org/apache/commons/pool3/MethodCall.java similarity index 93% rename from src/test/java/org/apache/commons/pool2/MethodCall.java rename to src/test/java/org/apache/commons/pool3/MethodCall.java index 95e913c98..6084dbf62 100644 --- a/src/test/java/org/apache/commons/pool2/MethodCall.java +++ b/src/test/java/org/apache/commons/pool3/MethodCall.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.util.Arrays; import java.util.Collections; @@ -62,9 +62,7 @@ public boolean equals(final Object o) { if (o == null || getClass() != o.getClass()) { return false; } - - final MethodCall that = (MethodCall)o; - + final MethodCall that = (MethodCall) o; if (!Objects.equals(name, that.name)) { return false; } @@ -91,8 +89,7 @@ public int hashCode() { int result; result = name != null ? name.hashCode() : 0; result = 29 * result + (params != null ? params.hashCode() : 0); - result = 29 * result + (returned != null ? returned.hashCode() : 0); - return result; + return 29 * result + (returned != null ? returned.hashCode() : 0); } public MethodCall returned(final Object obj) { diff --git a/src/test/java/org/apache/commons/pool2/MethodCallPoolableObjectFactory.java b/src/test/java/org/apache/commons/pool3/MethodCallPoolableObjectFactory.java similarity index 97% rename from src/test/java/org/apache/commons/pool2/MethodCallPoolableObjectFactory.java rename to src/test/java/org/apache/commons/pool3/MethodCallPoolableObjectFactory.java index 7ab670973..afe4a1560 100644 --- a/src/test/java/org/apache/commons/pool2/MethodCallPoolableObjectFactory.java +++ b/src/test/java/org/apache/commons/pool3/MethodCallPoolableObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.util.ArrayList; import java.util.List; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * A poolable object factory that tracks how {@link MethodCall methods are called}. diff --git a/src/test/java/org/apache/commons/pool2/ObjectPoolIssue326.java b/src/test/java/org/apache/commons/pool3/ObjectPoolIssue326.java similarity index 86% rename from src/test/java/org/apache/commons/pool2/ObjectPoolIssue326.java rename to src/test/java/org/apache/commons/pool3/ObjectPoolIssue326.java index e200946a0..09511e808 100644 --- a/src/test/java/org/apache/commons/pool2/ObjectPoolIssue326.java +++ b/src/test/java/org/apache/commons/pool3/ObjectPoolIssue326.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.time.Duration; import java.time.Instant; @@ -28,10 +28,10 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; -import org.apache.commons.pool2.impl.BaseObjectPoolConfig; -import org.apache.commons.pool2.impl.DefaultPooledObject; -import org.apache.commons.pool2.impl.GenericKeyedObjectPool; -import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; +import org.apache.commons.pool3.impl.BaseObjectPoolConfig; +import org.apache.commons.pool3.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.GenericKeyedObjectPool; +import org.apache.commons.pool3.impl.GenericKeyedObjectPoolConfig; /** * On my box with 4 cores this test fails at between 5s and 900s with an average @@ -41,7 +41,7 @@ * negatively since you need to run it for a while. */ public final class ObjectPoolIssue326 { - private static class ObjectFactory extends BaseKeyedPooledObjectFactory { + private static final class ObjectFactory extends BaseKeyedPooledObjectFactory { @Override public Object create(final Integer s) { return new TestObject(); @@ -53,13 +53,13 @@ public PooledObject wrap(final Object o) { } } - private static class Task implements Callable { - private final GenericKeyedObjectPool m_pool; - private final int m_key; + private static final class Task implements Callable { + private final GenericKeyedObjectPool pool; + private final int key; Task(final GenericKeyedObjectPool pool, final int count) { - m_pool = pool; - m_key = count % 20; + this.pool = pool; + this.key = count % 20; } private void busyWait(final long timeMillis) { @@ -74,12 +74,12 @@ private void busyWait(final long timeMillis) { public Object call() throws E { try { final Object value; - value = m_pool.borrowObject(m_key); + value = pool.borrowObject(key); // don't make this too long or it won't reproduce, and don't make it zero or it // won't reproduce // constant low value also doesn't reproduce busyWait(System.currentTimeMillis() % 4); - m_pool.returnObject(m_key, value); + pool.returnObject(key, value); return "success"; } catch (final NoSuchElementException e) { // ignore, we've exhausted the pool @@ -90,7 +90,7 @@ public Object call() throws E { } } - private static class TestObject { + private static final class TestObject { } public static void main(final String[] args) { @@ -118,14 +118,14 @@ private void run() throws InterruptedException, ExecutionException { poolConfig.setLifo(true); poolConfig.setFairness(true); poolConfig.setMaxWait(Duration.ofSeconds(30)); - poolConfig.setMinEvictableIdleTime(Duration.ofMillis(-1)); - poolConfig.setSoftMinEvictableIdleTime(Duration.ofMillis(-1)); + poolConfig.setMinEvictableIdleDuration(Duration.ofMillis(-1)); + poolConfig.setSoftMinEvictableIdleDuration(Duration.ofMillis(-1)); poolConfig.setNumTestsPerEvictionRun(1); poolConfig.setTestOnCreate(false); poolConfig.setTestOnBorrow(false); poolConfig.setTestOnReturn(false); poolConfig.setTestWhileIdle(false); - poolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(5)); + poolConfig.setDurationBetweenEvictionRuns(Duration.ofSeconds(5)); poolConfig.setEvictionPolicyClassName(BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME); poolConfig.setBlockWhenExhausted(false); poolConfig.setJmxEnabled(false); @@ -173,7 +173,7 @@ private void run() throws InterruptedException, ExecutionException { * java:43) at java.lang.reflect.Method.invoke(Method.java:498) at * com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) Caused * by: java.lang.NullPointerException at - * org.apache.commons.pool2.impl.GenericKeyedObjectPool.returnObject( + * org.apache.commons.pool3.impl.GenericKeyedObjectPool.returnObject( * GenericKeyedObjectPool.java:474) at * threading_pool.ObjectPoolIssue$Task.call(ObjectPoolIssue.java:112) at * java.util.concurrent.FutureTask.run(FutureTask.java:266) at diff --git a/src/test/java/org/apache/commons/pool2/PoolTest.java b/src/test/java/org/apache/commons/pool3/PoolTest.java similarity index 75% rename from src/test/java/org/apache/commons/pool2/PoolTest.java rename to src/test/java/org/apache/commons/pool3/PoolTest.java index 9aa8a6bfd..5d87c8833 100644 --- a/src/test/java/org/apache/commons/pool2/PoolTest.java +++ b/src/test/java/org/apache/commons/pool3/PoolTest.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,27 +15,26 @@ * limitations under the License. */ -package org.apache.commons.pool2; - +package org.apache.commons.pool3; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import java.time.Duration; -import org.apache.commons.pool2.impl.DefaultPooledObject; -import org.apache.commons.pool2.impl.GenericObjectPool; -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.apache.commons.pool3.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.GenericObjectPool; +import org.apache.commons.pool3.impl.GenericObjectPoolConfig; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @Disabled -public class PoolTest { +class PoolTest { - private static class Foo { + private static final class Foo { } - private static class PooledFooFactory implements PooledObjectFactory { + private static final class PooledFooFactory implements PooledObjectFactory { private static final long VALIDATION_WAIT_IN_MILLIS = 1000; @Override @@ -70,17 +69,19 @@ public boolean validateObject(final PooledObject pooledObject) { private static final long EVICTION_PERIOD_IN_MILLIS = 100; + private static final Duration EVICTION_DURATION = Duration.ofMillis(100); + @Test - public void testPool() { + void testPool() { final GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setTestWhileIdle(true /* testWhileIdle */); final PooledFooFactory pooledFooFactory = new PooledFooFactory(); try (GenericObjectPool pool = new GenericObjectPool<>(pooledFooFactory, poolConfig)) { - pool.setTimeBetweenEvictionRunsMillis(EVICTION_PERIOD_IN_MILLIS); + pool.setDurationBetweenEvictionRuns(EVICTION_DURATION); + assertEquals(EVICTION_PERIOD_IN_MILLIS, pool.getDurationBetweenEvictionRuns().toMillis()); + assertEquals(EVICTION_PERIOD_IN_MILLIS, pool.getDurationBetweenEvictionRuns().toMillis()); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(EVICTION_PERIOD_IN_MILLIS)); assertEquals(EVICTION_PERIOD_IN_MILLIS, pool.getDurationBetweenEvictionRuns().toMillis()); - assertEquals(EVICTION_PERIOD_IN_MILLIS, pool.getTimeBetweenEvictionRuns().toMillis()); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(EVICTION_PERIOD_IN_MILLIS)); - assertEquals(EVICTION_PERIOD_IN_MILLIS, pool.getTimeBetweenEvictionRuns().toMillis()); pool.addObject(); try { Thread.sleep(EVICTION_PERIOD_IN_MILLIS); @@ -95,7 +96,7 @@ public void testPool() { continue; } final String name = thread.getName(); - assertFalse( name.contains(COMMONS_POOL_EVICTIONS_TIMER_THREAD_NAME),name); + assertFalse(name.contains(COMMONS_POOL_EVICTIONS_TIMER_THREAD_NAME), name); } } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool3/PooledObjectTest.java b/src/test/java/org/apache/commons/pool3/PooledObjectTest.java new file mode 100644 index 000000000..4ba2fc62f --- /dev/null +++ b/src/test/java/org/apache/commons/pool3/PooledObjectTest.java @@ -0,0 +1,53 @@ +/* + * 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 + * + * https://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.pool3; + +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 org.apache.commons.pool3.impl.DefaultPooledObject; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link PooledObject}. + */ +public class PooledObjectTest { + + @Test + void testGetObject() { + assertNull(PooledObject.getObject(null)); + assertNull(PooledObject.getObject(new DefaultPooledObject<>(null))); + assertNotNull(PooledObject.getObject(new DefaultPooledObject<>("a"))); + } + + @Test + void testIsNull() { + assertTrue(PooledObject.isNull(null)); + assertTrue(PooledObject.isNull(new DefaultPooledObject<>(null))); + assertFalse(PooledObject.isNull(new DefaultPooledObject<>("a"))); + } + + @Test + void testNonNull() { + assertFalse(PooledObject.nonNull(null)); + assertFalse(PooledObject.nonNull(new DefaultPooledObject<>(null))); + assertTrue(PooledObject.nonNull(new DefaultPooledObject<>("a"))); + } +} diff --git a/src/test/java/org/apache/commons/pool2/PrivateException.java b/src/test/java/org/apache/commons/pool3/PrivateException.java similarity index 92% rename from src/test/java/org/apache/commons/pool2/PrivateException.java rename to src/test/java/org/apache/commons/pool3/PrivateException.java index 3f0498aa9..1481f5267 100644 --- a/src/test/java/org/apache/commons/pool2/PrivateException.java +++ b/src/test/java/org/apache/commons/pool3/PrivateException.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * An exception that only is thrown by these tests. diff --git a/src/test/java/org/apache/commons/pool2/TestBaseKeyedPooledObjectFactory.java b/src/test/java/org/apache/commons/pool3/TestBaseKeyedPooledObjectFactory.java similarity index 67% rename from src/test/java/org/apache/commons/pool2/TestBaseKeyedPooledObjectFactory.java rename to src/test/java/org/apache/commons/pool3/TestBaseKeyedPooledObjectFactory.java index 628cd9995..e97a415f6 100644 --- a/src/test/java/org/apache/commons/pool2/TestBaseKeyedPooledObjectFactory.java +++ b/src/test/java/org/apache/commons/pool3/TestBaseKeyedPooledObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,22 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; import org.junit.jupiter.api.Test; /** */ -public class TestBaseKeyedPooledObjectFactory { +class TestBaseKeyedPooledObjectFactory { - private static class TestFactory extends BaseKeyedPooledObjectFactory { + private static final class TestFactory extends BaseKeyedPooledObjectFactory { @Override public Object create(final Object key) { return null; } + @Override public PooledObject wrap(final Object value) { return new DefaultPooledObject<>(value); @@ -37,12 +38,12 @@ public PooledObject wrap(final Object value) { } @Test - public void testDefaultMethods() { + void testDefaultMethods() { final KeyedPooledObjectFactory factory = new TestFactory(); - factory.activateObject("key",null); // a no-op - factory.passivateObject("key",null); // a no-op - factory.destroyObject("key",null); // a no-op - assertTrue(factory.validateObject("key",null)); // constant true + factory.activateObject("key", null); // a no-op + factory.passivateObject("key", null); // a no-op + factory.destroyObject("key", null); // a no-op + assertTrue(factory.validateObject("key", null)); // constant true } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool2/TestBaseObjectPool.java b/src/test/java/org/apache/commons/pool3/TestBaseObjectPool.java similarity index 89% rename from src/test/java/org/apache/commons/pool2/TestBaseObjectPool.java rename to src/test/java/org/apache/commons/pool3/TestBaseObjectPool.java index 376217035..d3a1b0a57 100644 --- a/src/test/java/org/apache/commons/pool2/TestBaseObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/TestBaseObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -27,7 +27,7 @@ */ public class TestBaseObjectPool extends AbstractTestObjectPool { - private static class TestObjectPool extends BaseObjectPool { + private static final class TestObjectPool extends BaseObjectPool { @Override public Object borrowObject() { @@ -47,7 +47,6 @@ public void returnObject(final Object obj) { /** * @param n Ignored by this implemented. Used by sub-classes. - * * @return the Nth object (zero indexed) */ protected Object getNthObject(final int n) { @@ -73,8 +72,9 @@ protected boolean isLifo() { /** * @param minCapacity Ignored by this implemented. Used by sub-classes. + * @return A newly created empty pool. * - * @return A newly created empty pool + * @param Type of exception thrown by the pool. */ protected ObjectPool makeEmptyPool(final int minCapacity) { if (this.getClass() != TestBaseObjectPool.class) { @@ -92,7 +92,7 @@ protected ObjectPool makeEmptyPool(final Pooled } @Test - public void testBaseAddObject() { + void testBaseAddObject() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException e) { @@ -119,7 +119,7 @@ public void testBaseAddObject() { } @Test - public void testBaseBorrow() { + void testBaseBorrow() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException e) { @@ -132,7 +132,7 @@ public void testBaseBorrow() { } @Test - public void testBaseBorrowReturn() { + void testBaseBorrowReturn() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException e) { @@ -154,24 +154,24 @@ public void testBaseBorrowReturn() { pool.returnObject(obj2); obj2 = pool.borrowObject(); if (isLifo()) { - assertEquals(getNthObject(2),obj2); + assertEquals(getNthObject(2), obj2); } if (isFifo()) { - assertEquals(getNthObject(0),obj2); + assertEquals(getNthObject(0), obj2); } obj0 = pool.borrowObject(); if (isLifo()) { - assertEquals(getNthObject(0),obj0); + assertEquals(getNthObject(0), obj0); } if (isFifo()) { - assertEquals(getNthObject(2),obj0); + assertEquals(getNthObject(2), obj0); } pool.close(); } @Test - public void testBaseClear() { + void testBaseClear() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException e) { @@ -196,7 +196,7 @@ public void testBaseClear() { } @Test - public void testBaseClosePool() { + void testBaseClosePool() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException e) { @@ -210,7 +210,7 @@ public void testBaseClosePool() { } @Test - public void testBaseInvalidateObject() { + void testBaseInvalidateObject() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException e) { @@ -232,7 +232,7 @@ public void testBaseInvalidateObject() { } @Test - public void testBaseNumActiveNumIdle() { + void testBaseNumActiveNumIdle() { try { pool = makeEmptyPool(3); } catch (final UnsupportedOperationException e) { @@ -256,7 +256,7 @@ public void testBaseNumActiveNumIdle() { } @Test - public void testClose() { + void testClose() { @SuppressWarnings("resource") final ObjectPool pool = new TestObjectPool(); @@ -265,14 +265,14 @@ public void testClose() { } @Test - public void testUnsupportedOperations() { + void testUnsupportedOperations() { if (!getClass().equals(TestBaseObjectPool.class)) { return; // skip redundant tests } - try (final ObjectPool pool = new TestObjectPool()) { + try (ObjectPool pool = new TestObjectPool()) { - assertTrue( pool.getNumIdle() < 0,"Negative expected."); - assertTrue( pool.getNumActive() < 0,"Negative expected."); + assertTrue(pool.getNumIdle() < 0, "Negative expected."); + assertTrue(pool.getNumActive() < 0, "Negative expected."); assertThrows(UnsupportedOperationException.class, pool::clear); assertThrows(UnsupportedOperationException.class, pool::addObject); diff --git a/src/test/java/org/apache/commons/pool2/TestBasePoolableObjectFactory.java b/src/test/java/org/apache/commons/pool3/TestBasePoolableObjectFactory.java similarity index 79% rename from src/test/java/org/apache/commons/pool2/TestBasePoolableObjectFactory.java rename to src/test/java/org/apache/commons/pool3/TestBasePoolableObjectFactory.java index ceff13cbe..7bbd6d009 100644 --- a/src/test/java/org/apache/commons/pool2/TestBasePoolableObjectFactory.java +++ b/src/test/java/org/apache/commons/pool3/TestBasePoolableObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,31 +14,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; import org.junit.jupiter.api.Test; /** */ -public class TestBasePoolableObjectFactory { +class TestBasePoolableObjectFactory { - private static class TestFactory extends BasePooledObjectFactory { + private static final class TestFactory extends BasePooledObjectFactory { @Override public AtomicInteger create() { - return new AtomicInteger(0); + return new AtomicInteger(); } + @Override - public void destroyObject(final PooledObject p, final DestroyMode destroyMode){ + public void destroyObject(final PooledObject p, final DestroyMode destroyMode) { if (destroyMode.equals(DestroyMode.ABANDONED)) { p.getObject().incrementAndGet(); } } + @Override public PooledObject wrap(final AtomicInteger value) { return new DefaultPooledObject<>(value); @@ -46,7 +48,7 @@ public PooledObject wrap(final AtomicInteger value) { } @Test - public void testDefaultMethods() { + void testDefaultMethods() { final PooledObjectFactory factory = new TestFactory(); factory.activateObject(null); // a no-op @@ -56,14 +58,13 @@ public void testDefaultMethods() { } /** - * Default destroy does nothing to underlying AtomicInt, ABANDONED mode - * increments the value. Verify that destroy with no mode does default, - * destroy with ABANDONED mode increments. + * Default destroy does nothing to underlying AtomicInt, ABANDONED mode increments the value. Verify that destroy with no mode does default, destroy with + * ABANDONED mode increments. * * @throws RuntimeException May occur in some failure modes */ @Test - public void testDestroyModes() { + void testDestroyModes() { final PooledObjectFactory factory = new TestFactory(); final PooledObject pooledObj = factory.makeObject(); final AtomicInteger obj = pooledObj.getObject(); diff --git a/src/test/java/org/apache/commons/pool2/TestException.java b/src/test/java/org/apache/commons/pool3/TestException.java similarity index 94% rename from src/test/java/org/apache/commons/pool2/TestException.java rename to src/test/java/org/apache/commons/pool3/TestException.java index a18e58e62..204c7c83d 100644 --- a/src/test/java/org/apache/commons/pool2/TestException.java +++ b/src/test/java/org/apache/commons/pool3/TestException.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * A custom exception for unit tests. @@ -28,16 +28,16 @@ public TestException() { // empty } - public TestException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); + public TestException(final String message) { + super(message); } public TestException(final String message, final Throwable cause) { super(message, cause); } - public TestException(final String message) { - super(message); + public TestException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); } public TestException(final Throwable cause) { diff --git a/src/test/java/org/apache/commons/pool2/TestPoolUtils.java b/src/test/java/org/apache/commons/pool3/TestPoolUtils.java similarity index 75% rename from src/test/java/org/apache/commons/pool2/TestPoolUtils.java rename to src/test/java/org/apache/commons/pool3/TestPoolUtils.java index d73abff76..8fdc8ca9d 100644 --- a/src/test/java/org/apache/commons/pool2/TestPoolUtils.java +++ b/src/test/java/org/apache/commons/pool3/TestPoolUtils.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,8 +15,9 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -29,16 +30,13 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.TimerTask; -import org.apache.commons.pool2.impl.DefaultPooledObject; -import org.apache.commons.pool2.impl.GenericKeyedObjectPool; -import org.apache.commons.pool2.impl.GenericObjectPool; -import org.apache.commons.pool2.impl.TestGenericKeyedObjectPool; +import org.apache.commons.pool3.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.GenericKeyedObjectPool; +import org.apache.commons.pool3.impl.GenericObjectPool; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; @@ -47,7 +45,7 @@ * * TODO Replace our own mocking with a mocking library like Mockito. */ -public class TestPoolUtils { +class TestPoolUtils { private static class MethodCallLogger implements InvocationHandler { private final List calledMethods; @@ -156,16 +154,16 @@ private static List invokeEveryMethod(final Poo } @Test - public void testCheckMinIdleKeyedObjectPool() throws InterruptedException { + void testCheckMinIdleKeyedObjectPool() throws InterruptedException { assertThrows(IllegalArgumentException.class, () -> PoolUtils.checkMinIdle(null, new Object(), 1, 1), "PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not allow null pool."); try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { + KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { assertThrows(IllegalArgumentException.class, () -> PoolUtils.checkMinIdle(pool, (Object) null, 1, 1), "PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept null keys."); } try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { + KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { assertThrows(IllegalArgumentException.class, () -> PoolUtils.checkMinIdle(pool, new Object(), -1, 1), "PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept negative min idle values."); } @@ -176,14 +174,14 @@ public void testCheckMinIdleKeyedObjectPool() throws InterruptedException { // Test that the minIdle check doesn't add too many idle objects @SuppressWarnings("unchecked") final KeyedPooledObjectFactory kpof = createProxy(KeyedPooledObjectFactory.class, calledMethods); - try (final KeyedObjectPool kop = new GenericKeyedObjectPool<>(kpof)) { + try (KeyedObjectPool kop = new GenericKeyedObjectPool<>(kpof)) { PoolUtils.checkMinIdle(kop, key, 2, 100); Thread.sleep(400); assertEquals(2, kop.getNumIdle(key)); assertEquals(2, kop.getNumIdle()); } int makeObjectCount = 0; - for (String methodName : calledMethods) { + for (final String methodName : calledMethods) { if ("makeObject".equals(methodName)) { makeObjectCount++; } @@ -198,7 +196,7 @@ public void testCheckMinIdleKeyedObjectPool() throws InterruptedException { try { calledMethods.clear(); try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods)) { + KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods)) { // checks minIdle immediately final TimerTask task = PoolUtils.checkMinIdle(pool, key, 1, CHECK_PERIOD); @@ -224,7 +222,7 @@ public void testCheckMinIdleKeyedObjectPool() throws InterruptedException { } @Test - public void testCheckMinIdleKeyedObjectPoolKeys() throws InterruptedException { + void testCheckMinIdleKeyedObjectPoolKeys() throws InterruptedException { // Because this isn't deterministic and you can get false failures, try more than once. AssertionFailedError afe = null; int triesLeft = 3; @@ -232,7 +230,7 @@ public void testCheckMinIdleKeyedObjectPoolKeys() throws InterruptedException { afe = null; final List calledMethods = new ArrayList<>(); try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods)) { + KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods)) { final Collection keys = new ArrayList<>(2); keys.add("one"); keys.add("two"); @@ -240,9 +238,7 @@ public void testCheckMinIdleKeyedObjectPoolKeys() throws InterruptedException { final Map tasks = PoolUtils.checkMinIdle(pool, keys, 1, CHECK_PERIOD); Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times. - for (final TimerTask task : tasks.values()) { - task.cancel(); - } + tasks.values().forEach(TimerTask::cancel); final List expectedMethods = new ArrayList<>(); for (int i = 0; i < CHECK_COUNT * keys.size(); i++) { @@ -260,15 +256,15 @@ public void testCheckMinIdleKeyedObjectPoolKeys() throws InterruptedException { } @Test - public void testCheckMinIdleKeyedObjectPoolKeysNulls() { + void testCheckMinIdleKeyedObjectPoolKeysNulls() { try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { + KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { assertThrows(IllegalArgumentException.class, () -> PoolUtils.checkMinIdle(pool, (Collection) null, 1, 1), "PoolUtils.checkMinIdle(KeyedObjectPool,Collection,int,long) must not accept null keys."); } try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { + KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { PoolUtils.checkMinIdle(pool, (Collection) Collections.emptyList(), 1, 1); } catch (final IllegalArgumentException iae) { fail("PoolUtils.checkMinIdle(KeyedObjectPool,Collection,int,long) must accept empty lists."); @@ -276,11 +272,11 @@ public void testCheckMinIdleKeyedObjectPoolKeysNulls() { } @Test - public void testCheckMinIdleObjectPool() throws InterruptedException { + void testCheckMinIdleObjectPool() throws InterruptedException { assertThrows(IllegalArgumentException.class, () -> PoolUtils.checkMinIdle(null, 1, 1), "PoolUtils.checkMinIdle(ObjectPool,,) must not allow null pool."); try (@SuppressWarnings("unchecked") - final ObjectPool pool = createProxy(ObjectPool.class, (List) null)) { + ObjectPool pool = createProxy(ObjectPool.class, (List) null)) { assertThrows(IllegalArgumentException.class, () -> PoolUtils.checkMinIdle(pool, -1, 1), "PoolUtils.checkMinIdle(ObjectPool,,) must not accept negative min idle values."); } @@ -290,13 +286,13 @@ public void testCheckMinIdleObjectPool() throws InterruptedException { // Test that the minIdle check doesn't add too many idle objects @SuppressWarnings("unchecked") final PooledObjectFactory pof = createProxy(PooledObjectFactory.class, calledMethods); - try (final ObjectPool op = new GenericObjectPool<>(pof)) { + try (ObjectPool op = new GenericObjectPool<>(pof)) { PoolUtils.checkMinIdle(op, 2, 100); Thread.sleep(1000); assertEquals(2, op.getNumIdle()); } int makeObjectCount = 0; - for (String methodName : calledMethods) { + for (final String methodName : calledMethods) { if ("makeObject".equals(methodName)) { makeObjectCount++; } @@ -311,7 +307,7 @@ public void testCheckMinIdleObjectPool() throws InterruptedException { try { calledMethods.clear(); try (@SuppressWarnings("unchecked") - final ObjectPool pool = createProxy(ObjectPool.class, calledMethods)) { + ObjectPool pool = createProxy(ObjectPool.class, calledMethods)) { final TimerTask task = PoolUtils.checkMinIdle(pool, 1, CHECK_PERIOD); // checks minIdle immediately Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times. @@ -336,35 +332,20 @@ public void testCheckMinIdleObjectPool() throws InterruptedException { } @Test - public void testCheckRethrow() { - try { - PoolUtils.checkRethrow(new Exception()); - } catch (final Throwable t) { - fail("PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError."); - } - try { - PoolUtils.checkRethrow(new ThreadDeath()); - fail("PoolUtils.checkRethrow(Throwable) must rethrow ThreadDeath."); - } catch (final ThreadDeath td) { - // expected - } catch (final Throwable t) { - fail("PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError."); - } - try { - PoolUtils.checkRethrow(new InternalError()); // InternalError extends VirtualMachineError - fail("PoolUtils.checkRethrow(Throwable) must rethrow VirtualMachineError."); - } catch (final VirtualMachineError td) { - // expected - } catch (final Throwable t) { - fail("PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError."); - } + void testCheckRethrow() { + assertDoesNotThrow(() -> PoolUtils.checkRethrow(new Exception()), + "PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError."); + assertThrows(ThreadDeath.class, () -> PoolUtils.checkRethrow(new ThreadDeath()), + "PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError."); + assertThrows(VirtualMachineError.class, () -> PoolUtils.checkRethrow(new InternalError()), + "PoolUtils.checkRethrow(Throwable) must rethrow only ThreadDeath and VirtualMachineError."); } @Test - public void testErodingObjectPoolDefaultFactor() { + void testErodingObjectPoolDefaultFactor() { try (@SuppressWarnings("unchecked") - final ObjectPool internalPool = createProxy(ObjectPool.class, (arg0, arg1, arg2) -> null); - final ObjectPool pool = PoolUtils.erodingPool(internalPool)) { + ObjectPool internalPool = createProxy(ObjectPool.class, (arg0, arg1, arg2) -> null); + ObjectPool pool = PoolUtils.erodingPool(internalPool)) { final String expectedToString = "ErodingObjectPool{factor=ErodingFactor{factor=1.0, idleHighWaterMark=1}, pool=" + internalPool + "}"; // The factor is not exposed, but will be printed in the toString() method @@ -374,7 +355,7 @@ public void testErodingObjectPoolDefaultFactor() { } @Test - public void testErodingPerKeyKeyedObjectPool() throws InterruptedException { + void testErodingPerKeyKeyedObjectPool() throws InterruptedException { assertThrows(IllegalArgumentException.class, () -> PoolUtils.erodingPool((KeyedObjectPool) null, 1f, true), "PoolUtils.erodingPool(KeyedObjectPool) must not allow a null pool."); @@ -400,7 +381,7 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg // If the logic behind PoolUtils.erodingPool changes then this will need to be tweaked. final float factor = 0.01f; // about ~9 seconds until first discard try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = PoolUtils.erodingPool(createProxy(KeyedObjectPool.class, handler), factor, true)) { + KeyedObjectPool pool = PoolUtils.erodingPool(createProxy(KeyedObjectPool.class, handler), factor, true)) { final List expectedMethods = new ArrayList<>(); assertEquals(expectedMethods, calledMethods); @@ -446,7 +427,7 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg } @Test - public void testErodingPoolKeyedObjectPool() throws InterruptedException { + void testErodingPoolKeyedObjectPool() throws InterruptedException { assertThrows(IllegalArgumentException.class, () -> PoolUtils.erodingPool((KeyedObjectPool) null), "PoolUtils.erodingPool(KeyedObjectPool) must not allow a null pool."); @@ -479,7 +460,7 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg final float factor = 0.01f; // about ~9 seconds until first discard final List expectedMethods = new ArrayList<>(); try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = PoolUtils.erodingPool(createProxy(KeyedObjectPool.class, handler), factor)) { + KeyedObjectPool pool = PoolUtils.erodingPool(createProxy(KeyedObjectPool.class, handler), factor)) { assertEquals(expectedMethods, calledMethods); @@ -533,13 +514,11 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg } @Test - public void testErodingPoolKeyedObjectPoolDefaultFactor() { + void testErodingPoolKeyedObjectPoolDefaultFactor() { try (@SuppressWarnings("unchecked") - final KeyedObjectPool internalPool = createProxy(KeyedObjectPool.class, - (arg0, arg1, arg2) -> null); - final KeyedObjectPool pool = PoolUtils.erodingPool(internalPool)) { - final String expectedToString = "ErodingKeyedObjectPool{factor=ErodingFactor{factor=1.0, idleHighWaterMark=1}, keyedPool=" + - internalPool + "}"; + KeyedObjectPool internalPool = createProxy(KeyedObjectPool.class, (arg0, arg1, arg2) -> null); + KeyedObjectPool pool = PoolUtils.erodingPool(internalPool)) { + final String expectedToString = "ErodingKeyedObjectPool{factor=ErodingFactor{factor=1.0, idleHighWaterMark=1}, keyedPool=" + internalPool + "}"; // The factor is not exposed, but will be printed in the toString() method // In this case since we didn't pass one, the default 1.0f will be printed assertEquals(expectedToString, pool.toString()); @@ -547,7 +526,7 @@ public void testErodingPoolKeyedObjectPoolDefaultFactor() { } @Test - public void testErodingPoolObjectPool() throws InterruptedException { + void testErodingPoolObjectPool() throws InterruptedException { assertThrows(IllegalArgumentException.class, () -> PoolUtils.erodingPool((ObjectPool) null), "PoolUtils.erodingPool(ObjectPool) must not allow a null pool."); @@ -574,7 +553,7 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg final float factor = 0.01f; // about ~9 seconds until first discard final List expectedMethods = new ArrayList<>(); try (@SuppressWarnings("unchecked") - final ObjectPool pool = PoolUtils.erodingPool(createProxy(ObjectPool.class, handler), factor)) { + ObjectPool pool = PoolUtils.erodingPool(createProxy(ObjectPool.class, handler), factor)) { assertEquals(expectedMethods, calledMethods); @@ -626,87 +605,12 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg } @Test - public void testJavaBeanInstantiation() { + void testJavaBeanInstantiation() { assertNotNull(new PoolUtils()); } - @SuppressWarnings("deprecation") - @Test - public void testPrefillKeyedObjectPool() throws Exception { - assertThrows(IllegalArgumentException.class, () -> PoolUtils.prefill(null, new Object(), 1), - "PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null pool."); - - try (final KeyedObjectPool pool = new GenericKeyedObjectPool<>(new TestGenericKeyedObjectPool.SimpleFactory<>())) { - assertThrows(IllegalArgumentException.class, () -> PoolUtils.prefill(pool, (Object) null, 1), - "PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null key."); - } - - final List calledMethods = new ArrayList<>(); - try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods)) { - - PoolUtils.prefill(pool, new Object(), 0); - final List expectedMethods = new ArrayList<>(); - expectedMethods.add("addObjects"); - assertEquals(expectedMethods, calledMethods); - - calledMethods.clear(); - PoolUtils.prefill(pool, new Object(), 3); - assertEquals(expectedMethods, calledMethods); - } - } - - @SuppressWarnings("deprecation") - @Test - public void testPrefillKeyedObjectPoolCollection() { - try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, (List) null)) { - assertThrows(IllegalArgumentException.class, () -> PoolUtils.prefill(pool, (Collection) null, 1), - "PoolUtils.prefill(KeyedObjectPool,Collection,int) must not accept null keys."); - } - - final List calledMethods = new ArrayList<>(); - try (@SuppressWarnings("unchecked") - final KeyedObjectPool pool = createProxy(KeyedObjectPool.class, calledMethods)) { - - final Set keys = new HashSet<>(); - PoolUtils.prefill(pool, keys, 0); - final List expectedMethods = new ArrayList<>(); - expectedMethods.add("addObjects"); - assertEquals(expectedMethods, calledMethods); - - calledMethods.clear(); - keys.add("one"); - keys.add("two"); - keys.add("three"); - final int count = 3; - PoolUtils.prefill(pool, keys, count); - assertEquals(expectedMethods, calledMethods); - } - } - - @SuppressWarnings("deprecation") - @Test - public void testPrefillObjectPool() { - assertThrows(IllegalArgumentException.class, () -> PoolUtils.prefill(null, 1), "PoolUtils.prefill(ObjectPool,int) must not allow null pool."); - - final List calledMethods = new ArrayList<>(); - try (@SuppressWarnings("unchecked") - final ObjectPool pool = createProxy(ObjectPool.class, calledMethods)) { - - PoolUtils.prefill(pool, 0); - final List expectedMethods = new ArrayList<>(); - expectedMethods.add("addObjects"); - assertEquals(expectedMethods, calledMethods); - - calledMethods.clear(); - PoolUtils.prefill(pool, 3); - assertEquals(expectedMethods, calledMethods); - } - } - @Test - public void testSynchronizedPoolableFactoryKeyedPooledObjectFactory() { + void testSynchronizedPoolableFactoryKeyedPooledObjectFactory() { assertThrows(IllegalArgumentException.class, () -> PoolUtils.synchronizedKeyedPooledFactory((KeyedPooledObjectFactory) null), "PoolUtils.synchronizedPoolableFactory(KeyedPooledObjectFactory) must not allow a null factory."); @@ -723,7 +627,7 @@ public void testSynchronizedPoolableFactoryKeyedPooledObjectFactory() { } @Test - public void testSynchronizedPoolableFactoryPoolableObjectFactory() throws Exception { + void testSynchronizedPoolableFactoryPoolableObjectFactory() throws Exception { assertThrows(IllegalArgumentException.class, () -> PoolUtils.synchronizedPooledFactory((PooledObjectFactory) null), "PoolUtils.synchronizedPoolableFactory(PoolableObjectFactory) must not allow a null factory."); @@ -739,14 +643,14 @@ public void testSynchronizedPoolableFactoryPoolableObjectFactory() throws Except } @Test - public void testSynchronizedPoolKeyedObjectPool() { + void testSynchronizedPoolKeyedObjectPool() { assertThrows(IllegalArgumentException.class, () -> PoolUtils.synchronizedPool((KeyedObjectPool) null), "PoolUtils.synchronizedPool(KeyedObjectPool) must not allow a null pool."); final List calledMethods = new ArrayList<>(); try (@SuppressWarnings("unchecked") - final KeyedObjectPool kop = createProxy(KeyedObjectPool.class, calledMethods); - final KeyedObjectPool skop = PoolUtils.synchronizedPool(kop)) { + KeyedObjectPool kop = createProxy(KeyedObjectPool.class, calledMethods); + KeyedObjectPool skop = PoolUtils.synchronizedPool(kop)) { final List expectedMethods = invokeEveryMethod(skop); assertEquals(expectedMethods, calledMethods); } @@ -755,13 +659,14 @@ public void testSynchronizedPoolKeyedObjectPool() { } @Test - public void testSynchronizedPoolObjectPool() { + void testSynchronizedPoolObjectPool() { assertThrows(IllegalArgumentException.class, () -> PoolUtils.synchronizedPool((ObjectPool) null), "PoolUtils.synchronizedPool(ObjectPool) must not allow a null pool."); final List calledMethods = new ArrayList<>(); try (@SuppressWarnings("unchecked") - final ObjectPool op = createProxy(ObjectPool.class, calledMethods); final ObjectPool sop = PoolUtils.synchronizedPool(op)) { + ObjectPool op = createProxy(ObjectPool.class, calledMethods); + ObjectPool sop = PoolUtils.synchronizedPool(op)) { final List expectedMethods = invokeEveryMethod(sop); assertEquals(expectedMethods, calledMethods); @@ -773,7 +678,7 @@ public void testSynchronizedPoolObjectPool() { * Tests the {@link PoolUtils} timer holder. */ @Test - public void testTimerHolder() { + void testTimerHolder() { final PoolUtils.TimerHolder h = new PoolUtils.TimerHolder(); assertNotNull(h); assertNotNull(PoolUtils.TimerHolder.MIN_IDLE_TIMER); diff --git a/src/test/java/org/apache/commons/pool2/TestTrackedUse.java b/src/test/java/org/apache/commons/pool3/TestTrackedUse.java similarity index 77% rename from src/test/java/org/apache/commons/pool2/TestTrackedUse.java rename to src/test/java/org/apache/commons/pool3/TestTrackedUse.java index 421ee702e..b97bfb571 100644 --- a/src/test/java/org/apache/commons/pool2/TestTrackedUse.java +++ b/src/test/java/org/apache/commons/pool3/TestTrackedUse.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -23,19 +23,19 @@ import org.junit.jupiter.api.Test; -public class TestTrackedUse { +class TestTrackedUse { - class DefaultTrackedUse implements TrackedUse { + final class DefaultTrackedUse implements TrackedUse { @Override - public long getLastUsed() { - return 1; + public Instant getLastUsedInstant() { + return Instant.ofEpochMilli(1); } } @Test - public void testDefaultGetLastUsedInstant() { + void testDefaultGetLastUsedInstant() { assertEquals(Instant.ofEpochMilli(1), new DefaultTrackedUse().getLastUsedInstant()); } } diff --git a/src/test/java/org/apache/commons/pool2/VisitTracker.java b/src/test/java/org/apache/commons/pool3/VisitTracker.java similarity index 96% rename from src/test/java/org/apache/commons/pool2/VisitTracker.java rename to src/test/java/org/apache/commons/pool3/VisitTracker.java index 2dbd4b796..235f2f9da 100644 --- a/src/test/java/org/apache/commons/pool2/VisitTracker.java +++ b/src/test/java/org/apache/commons/pool3/VisitTracker.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; /** * Test pooled object class. Keeps track of how many times it has been validated, activated, passivated. diff --git a/src/test/java/org/apache/commons/pool2/VisitTrackerFactory.java b/src/test/java/org/apache/commons/pool3/VisitTrackerFactory.java similarity index 94% rename from src/test/java/org/apache/commons/pool2/VisitTrackerFactory.java rename to src/test/java/org/apache/commons/pool3/VisitTrackerFactory.java index 78121ef1c..2cb1243fc 100644 --- a/src/test/java/org/apache/commons/pool2/VisitTrackerFactory.java +++ b/src/test/java/org/apache/commons/pool3/VisitTrackerFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,9 +15,9 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * Factory that creates VisitTracker instances. Used to test Evictor runs. diff --git a/src/test/java/org/apache/commons/pool2/Waiter.java b/src/test/java/org/apache/commons/pool3/Waiter.java similarity index 94% rename from src/test/java/org/apache/commons/pool2/Waiter.java rename to src/test/java/org/apache/commons/pool3/Waiter.java index 0a3166a42..cc7adbea2 100644 --- a/src/test/java/org/apache/commons/pool2/Waiter.java +++ b/src/test/java/org/apache/commons/pool3/Waiter.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,10 +15,13 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; +import java.time.Duration; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.commons.lang3.ThreadUtils; + /** *

    Object created by {@link WaiterFactory}. Maintains active / valid state, * last passivated and idle times. Waits with configurable latency when @@ -28,14 +31,11 @@ */ public class Waiter { private static final AtomicInteger instanceCount = new AtomicInteger(); - /** TODO Reuse Apache Commons Lang ThreadUtils */ + public static void sleepQuietly(final long millis) { - try { - Thread.sleep(millis); - } catch (final InterruptedException e) { - // be quiet - } + ThreadUtils.sleepQuietly(Duration.ofMillis(millis)); } + private boolean active; private boolean valid; private long latency; @@ -117,7 +117,7 @@ public int hashCode() { } /** - * Whether or not the instance is active. + * Tests whether or not the instance is active. * * @return true if the last lifecycle event for this instance was activation. */ diff --git a/src/test/java/org/apache/commons/pool2/WaiterFactory.java b/src/test/java/org/apache/commons/pool3/WaiterFactory.java similarity index 85% rename from src/test/java/org/apache/commons/pool2/WaiterFactory.java rename to src/test/java/org/apache/commons/pool3/WaiterFactory.java index 8d441f1a5..c6507cfee 100644 --- a/src/test/java/org/apache/commons/pool2/WaiterFactory.java +++ b/src/test/java/org/apache/commons/pool3/WaiterFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.commons.pool2; +package org.apache.commons.pool3; import java.util.HashMap; import java.util.Map; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * Object factory with configurable latencies for object lifecycle methods. @@ -64,7 +64,7 @@ public class WaiterFactory implements PooledObjectFactory activeCounts = new HashMap<>(); + private final Map activeCounts = new HashMap<>(); /** Maximum of (makes - destroys) - if exceeded IllegalStateException */ private final long maxActive; // GKOP 1.x calls this maxTotal @@ -72,24 +72,18 @@ public class WaiterFactory implements PooledObjectFactory makeObject(final K key) { if (v1.intValue() >= maxActivePerKey) { throw new IllegalStateException("Too many active " + "instances for key = " + key + ": " + v1.intValue() + - " in circulation " + "with maxActivePerKey = " + + " in circulation with maxActivePerKey = " + maxActivePerKey); } return Integer.valueOf(v1.intValue() + 1); @@ -194,9 +188,7 @@ public synchronized void reset() { if (activeCounts.isEmpty()) { return; } - for (K key : activeCounts.keySet()) { - activeCounts.put(key, ZERO); - } + activeCounts.keySet().forEach(key -> activeCounts.put(key, ZERO)); } @Override diff --git a/src/test/java/org/apache/commons/pool2/impl/AtomicIntegerFactory.java b/src/test/java/org/apache/commons/pool3/impl/AtomicIntegerFactory.java similarity index 92% rename from src/test/java/org/apache/commons/pool2/impl/AtomicIntegerFactory.java rename to src/test/java/org/apache/commons/pool3/impl/AtomicIntegerFactory.java index bf7b38c1f..d9dd5b789 100644 --- a/src/test/java/org/apache/commons/pool2/impl/AtomicIntegerFactory.java +++ b/src/test/java/org/apache/commons/pool3/impl/AtomicIntegerFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,13 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.Waiter; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.Waiter; /** * Factory that sources PooledObjects that wrap AtomicIntegers. @@ -46,7 +46,7 @@ public void activateObject(final PooledObject p) { @Override public AtomicInteger create() { Waiter.sleepQuietly(createLatency); - return new AtomicInteger(0); + return new AtomicInteger(); } @Override @@ -74,7 +74,6 @@ public void setCreateLatency(final long createLatency) { this.createLatency = createLatency; } - /** * @param destroyLatency the destroyLatency to set */ @@ -82,7 +81,6 @@ public void setDestroyLatency(final long destroyLatency) { this.destroyLatency = destroyLatency; } - /** * @param passivateLatency the passivateLatency to set */ @@ -90,7 +88,6 @@ public void setPassivateLatency(final long passivateLatency) { this.passivateLatency = passivateLatency; } - /** * @param validateLatency the validateLatency to set */ @@ -98,16 +95,14 @@ public void setValidateLatency(final long validateLatency) { this.validateLatency = validateLatency; } - @Override public boolean validateObject(final PooledObject instance) { Waiter.sleepQuietly(validateLatency); return instance.getObject().intValue() == 1; } - @Override public PooledObject wrap(final AtomicInteger integer) { return new DefaultPooledObject<>(integer); } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool2/impl/CallStackTest.java b/src/test/java/org/apache/commons/pool3/impl/CallStackTest.java similarity index 89% rename from src/test/java/org/apache/commons/pool2/impl/CallStackTest.java rename to src/test/java/org/apache/commons/pool3/impl/CallStackTest.java index 6c8c56af9..b28067edd 100644 --- a/src/test/java/org/apache/commons/pool2/impl/CallStackTest.java +++ b/src/test/java/org/apache/commons/pool3/impl/CallStackTest.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the license for the specific language governing permissions and * limitations under the license. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -27,7 +27,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -public class CallStackTest { +class CallStackTest { public static Stream data() { // @formatter:off @@ -44,7 +44,7 @@ public static Stream data() { @ParameterizedTest @MethodSource("data") - public void testPrintClearedStackTraceIsNoOp(final CallStack stack) { + void testPrintClearedStackTraceIsNoOp(final CallStack stack) { stack.fillInStackTrace(); stack.clear(); stack.printStackTrace(new PrintWriter(writer)); @@ -54,10 +54,10 @@ public void testPrintClearedStackTraceIsNoOp(final CallStack stack) { @ParameterizedTest @MethodSource("data") - public void testPrintFilledStackTrace(final CallStack stack) { + void testPrintFilledStackTrace(final CallStack stack) { stack.fillInStackTrace(); stack.printStackTrace(new PrintWriter(writer)); final String stackTrace = writer.toString(); assertTrue(stackTrace.contains(getClass().getName())); } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool2/impl/DisconnectingWaiterFactory.java b/src/test/java/org/apache/commons/pool3/impl/DisconnectingWaiterFactory.java similarity index 97% rename from src/test/java/org/apache/commons/pool2/impl/DisconnectingWaiterFactory.java rename to src/test/java/org/apache/commons/pool3/impl/DisconnectingWaiterFactory.java index 36c6cfad7..db9b3c813 100644 --- a/src/test/java/org/apache/commons/pool2/impl/DisconnectingWaiterFactory.java +++ b/src/test/java/org/apache/commons/pool3/impl/DisconnectingWaiterFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.time.Duration; import java.time.Instant; @@ -24,22 +24,11 @@ import java.util.function.Predicate; import java.util.function.Supplier; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.Waiter; -import org.apache.commons.pool2.WaiterFactory; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.Waiter; +import org.apache.commons.pool3.WaiterFactory; public class DisconnectingWaiterFactory extends WaiterFactory { - /** - * - * A WaiterFactory that simulates a resource required by factory methods going - * down (and coming back). - *

    - * When connected, this factory behaves like a normal WaiterFactory. - * When disconnected, factory methods are determined by functional parameters. - *

    - */ - private final AtomicBoolean connected = new AtomicBoolean(true); - private static final Duration DEFAULT_TIME_BETWEEN_CONNECTION_CHECKS = Duration.ofMillis(100); private static final Duration DEFAULT_MAX_WAIT = Duration.ofSeconds(10); @@ -68,6 +57,37 @@ public class DisconnectingWaiterFactory extends WaiterFactory { */ protected static final Predicate> DEFAULT_DISCONNECTED_VALIDATION_ACTION = w -> false; + /* + * Blocks until connected or maxWait is exceeded. + * + * @throws TimeoutException if maxWait is exceeded. + */ + private static void waitForConnection(final AtomicBoolean connected, + final Duration timeBetweenConnectionChecks, final Duration maxWait) { + final Instant start = Instant.now(); + while (!connected.get()) { + try { + Thread.sleep(timeBetweenConnectionChecks.toMillis()); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + if (Duration.between(start, Instant.now()).compareTo(maxWait) > 0) { + throw new IllegalStateException(new TimeoutException("Timed out waiting for connection")); + } + } + } + + /** + * + * A WaiterFactory that simulates a resource required by factory methods going + * down (and coming back). + *

    + * When connected, this factory behaves like a normal WaiterFactory. + * When disconnected, factory methods are determined by functional parameters. + *

    + */ + private final AtomicBoolean connected = new AtomicBoolean(true); + /** Time between reconnection checks */ final Duration timeBetweenConnectionChecks; @@ -89,6 +109,11 @@ public class DisconnectingWaiterFactory extends WaiterFactory { /** Function to perform for validate when invoked in disconnected mode */ final Predicate> disconnectedValidationAction; + public DisconnectingWaiterFactory() { + this(DEFAULT_DISCONNECTED_CREATE_ACTION, DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, + DEFAULT_DISCONNECTED_VALIDATION_ACTION); + } + public DisconnectingWaiterFactory(final long activateLatency, final long destroyLatency, final long makeLatency, final long passivateLatency, final long validateLatency, final long waiterLatency) { @@ -133,34 +158,57 @@ public DisconnectingWaiterFactory(final Supplier> disconnec this.disconnectedValidationAction = disconnectedValidationAction; } - public DisconnectingWaiterFactory() { - this(DEFAULT_DISCONNECTED_CREATE_ACTION, DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, - DEFAULT_DISCONNECTED_VALIDATION_ACTION); - } - - private boolean validate(final PooledObject obj) { + private void activate(final PooledObject obj) { if (connected.get()) { - return super.validateObject(obj); + super.activateObject(obj); + } else { + disconnectedLifcycleAction.accept(obj); } - return disconnectedValidationAction.test(obj); } @Override - public boolean validateObject(final K key, final PooledObject obj) { - return validate(obj); + public void activateObject(final K key, final PooledObject obj) { + activate(obj); } @Override - public boolean validateObject(final PooledObject obj) { - return validate(obj); + public void activateObject(final PooledObject obj) { + activate(obj); } - private void activate(final PooledObject obj) { + /** + * Reconnect the factory. + */ + public void connect() { + connected.set(true); + } + /* + * TODO: add builder to clean up constructors and make maxWait, + * timeBetweenConnectionChecks configurable. + */ + + /** + * Disconnect the factory. + */ + public void disconnect() { + connected.set(false); + } + + private PooledObject make() { if (connected.get()) { - super.activateObject(obj); - } else { - disconnectedLifcycleAction.accept(obj); + return super.makeObject(); } + return disconnectedCreateAction.get(); + } + + @Override + public PooledObject makeObject() { + return make(); + } + + @Override + public PooledObject makeObject(final K key) { + return make(); } private void passivate(final PooledObject obj) { @@ -181,69 +229,21 @@ public void passivateObject(final PooledObject obj) { passivate(obj); } - @Override - public void activateObject(final K key, final PooledObject obj) { - activate(obj); - } - - @Override - public void activateObject(final PooledObject obj) { - activate(obj); - } - - @Override - public PooledObject makeObject(final K key) { - return make(); - } - - @Override - public PooledObject makeObject() { - return make(); - } - - private PooledObject make() { + private boolean validate(final PooledObject obj) { if (connected.get()) { - return super.makeObject(); - } - return disconnectedCreateAction.get(); - } - - /** - * Blocks until connected or maxWait is exceeded. - * - * @throws TimeoutException if maxWait is exceeded. - */ - private static void waitForConnection(final AtomicBoolean connected, - final Duration timeBetweenConnectionChecks, final Duration maxWait) { - final Instant start = Instant.now(); - while (!connected.get()) { - try { - Thread.sleep(timeBetweenConnectionChecks.toMillis()); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - if (Duration.between(start, Instant.now()).compareTo(maxWait) > 0) { - throw new IllegalStateException(new TimeoutException("Timed out waiting for connection")); - } + return super.validateObject(obj); } + return disconnectedValidationAction.test(obj); } - /** - * Disconnect the factory. - */ - public void disconnect() { - connected.set(false); + @Override + public boolean validateObject(final K key, final PooledObject obj) { + return validate(obj); } - /** - * Reconnect the factory. - */ - public void connect() { - connected.set(true); + @Override + public boolean validateObject(final PooledObject obj) { + return validate(obj); } - /* - * TODO: add builder to clean up constructors and make maxWait, - * timeBetweenConnectionChecks configurable. - */ } diff --git a/src/test/java/org/apache/commons/pool2/impl/NoOpCallStackTest.java b/src/test/java/org/apache/commons/pool3/impl/NoOpCallStackTest.java similarity index 87% rename from src/test/java/org/apache/commons/pool2/impl/NoOpCallStackTest.java rename to src/test/java/org/apache/commons/pool3/impl/NoOpCallStackTest.java index 8f3d909fa..40f5ef0c5 100644 --- a/src/test/java/org/apache/commons/pool2/impl/NoOpCallStackTest.java +++ b/src/test/java/org/apache/commons/pool3/impl/NoOpCallStackTest.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -23,13 +23,13 @@ import org.junit.jupiter.api.Test; -public class NoOpCallStackTest { +class NoOpCallStackTest { @Test - public void printStackTraceIsNoOp() { + void testPrintStackTraceIsNoOp() { final CallStack stack = NoOpCallStack.INSTANCE; stack.fillInStackTrace(); final StringWriter writer = new StringWriter(); stack.printStackTrace(new PrintWriter(writer)); assertEquals("", writer.toString()); } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool2/impl/TestAbandonedKeyedObjectPool.java b/src/test/java/org/apache/commons/pool3/impl/TestAbandonedKeyedObjectPool.java similarity index 86% rename from src/test/java/org/apache/commons/pool2/impl/TestAbandonedKeyedObjectPool.java rename to src/test/java/org/apache/commons/pool3/impl/TestAbandonedKeyedObjectPool.java index 90ee04875..3d7c414c5 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestAbandonedKeyedObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestAbandonedKeyedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -33,10 +33,10 @@ import javax.management.MBeanServer; import javax.management.ObjectName; -import org.apache.commons.pool2.DestroyMode; -import org.apache.commons.pool2.KeyedPooledObjectFactory; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.Waiter; +import org.apache.commons.pool3.DestroyMode; +import org.apache.commons.pool3.KeyedPooledObjectFactory; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.Waiter; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -44,12 +44,12 @@ /** * Tests for {@link AbandonedConfig}. */ -public class TestAbandonedKeyedObjectPool { +class TestAbandonedKeyedObjectPool { - class ConcurrentBorrower extends Thread { + private final class ConcurrentBorrower extends Thread { private final ArrayList borrowed; - public ConcurrentBorrower(final ArrayList borrowed) { + private ConcurrentBorrower(final ArrayList borrowed) { this.borrowed = borrowed; } @@ -62,11 +62,14 @@ public void run() { } } } - class ConcurrentReturner extends Thread { + + private final class ConcurrentReturner extends Thread { private final PooledTestObject returned; - public ConcurrentReturner(final PooledTestObject obj) { + + private ConcurrentReturner(final PooledTestObject obj) { returned = obj; } + @Override public void run() { try { @@ -78,17 +81,17 @@ public void run() { } } - private static class SimpleFactory implements KeyedPooledObjectFactory { + private static final class SimpleFactory implements KeyedPooledObjectFactory { private final long destroyLatencyMillis; private final long validateLatencyMillis; - public SimpleFactory() { + private SimpleFactory() { destroyLatencyMillis = 0; validateLatencyMillis = 0; } - public SimpleFactory(final long destroyLatencyMillis, final long validateLatencyMillis) { + private SimpleFactory(final long destroyLatencyMillis, final long validateLatencyMillis) { this.destroyLatencyMillis = destroyLatencyMillis; this.validateLatencyMillis = validateLatencyMillis; } @@ -147,11 +150,6 @@ public void setUp() { // One second Duration. abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); assertEquals(TestConstants.ONE_SECOND_DURATION, abandonedConfig.getRemoveAbandonedTimeoutDuration()); - assertEquals(1, abandonedConfig.getRemoveAbandonedTimeout()); - // One second int (not millis). - abandonedConfig.setRemoveAbandonedTimeout(1); - assertEquals(TestConstants.ONE_SECOND_DURATION, abandonedConfig.getRemoveAbandonedTimeoutDuration()); - assertEquals(1, abandonedConfig.getRemoveAbandonedTimeout()); pool = new GenericKeyedObjectPool<>( new SimpleFactory(), @@ -168,8 +166,7 @@ public void tearDown() throws Exception { pool = null; final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - final Set result = mbs.queryNames(new ObjectName( - "org.apache.commoms.pool2:type=GenericKeyedObjectPool,*"), null); + final Set result = mbs.queryNames(new ObjectName("org.apache.commoms.pool3:type=GenericKeyedObjectPool,*"), null); // There should be no registered pools at this point final int registeredPoolCount = result.size(); final StringBuilder msg = new StringBuilder("Current pool is: "); @@ -183,7 +180,7 @@ public void tearDown() throws Exception { msg.append('\n'); mbs.unregisterMBean(name); } - assertEquals(0, registeredPoolCount,msg.toString()); + assertEquals(0, registeredPoolCount, msg.toString()); } /** @@ -193,7 +190,7 @@ public void tearDown() throws Exception { * @throws InterruptedException May occur in some failure modes */ @Test - public void testAbandonedInvalidate() throws InterruptedException { + void testAbandonedInvalidate() throws InterruptedException { abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnMaintenance(true); abandonedConfig.setRemoveAbandonedTimeout(Duration.ofMillis(2000)); @@ -205,7 +202,7 @@ public void testAbandonedInvalidate() throws InterruptedException { final int n = 10; pool.setMaxTotal(n); pool.setBlockWhenExhausted(false); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(250)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(250)); PooledTestObject pooledObj = null; final Integer key = 0; for (int i = 0; i < 5; i++) { @@ -232,7 +229,7 @@ public void testAbandonedInvalidate() throws InterruptedException { * @throws Exception May occur in some failure modes */ @Test - public void testAbandonedReturn() throws Exception { + void testAbandonedReturn() throws Exception { abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnBorrow(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); @@ -267,7 +264,7 @@ public void testAbandonedReturn() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testConcurrentInvalidation() throws Exception { + void testConcurrentInvalidation() throws Exception { final int POOL_SIZE = 30; pool.setMaxTotalPerKey(POOL_SIZE); pool.setMaxIdlePerKey(POOL_SIZE); @@ -308,7 +305,7 @@ public void testConcurrentInvalidation() throws Exception { assertEquals(0, pool.getNumActive(), "numActive should have been 0, was " + pool.getNumActive()); } - public void testDestroyModeAbandoned() throws Exception { + void testDestroyModeAbandoned() throws Exception { abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnMaintenance(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); @@ -317,14 +314,14 @@ public void testDestroyModeAbandoned() throws Exception { // validate takes 1 second new SimpleFactory(0, 0), new GenericKeyedObjectPoolConfig<>(), abandonedConfig); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(50)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(50)); // Borrow an object, wait long enough for it to be abandoned final PooledTestObject obj = pool.borrowObject(0); Thread.sleep(100); assertTrue(obj.isDetached()); } - public void testDestroyModeNormal() throws Exception { + void testDestroyModeNormal() throws Exception { abandonedConfig = new AbandonedConfig(); pool.close(); // Unregister pool created by setup pool = new GenericKeyedObjectPool<>(new SimpleFactory(0, 0)); @@ -342,7 +339,7 @@ public void testDestroyModeNormal() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testRemoveAbandonedWhileReturning() throws Exception { + void testRemoveAbandonedWhileReturning() throws Exception { abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnMaintenance(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); @@ -354,14 +351,14 @@ public void testRemoveAbandonedWhileReturning() throws Exception { final int n = 10; pool.setMaxTotal(n); pool.setBlockWhenExhausted(false); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); pool.setTestOnReturn(true); // Borrow an object, wait long enough for it to be abandoned // then arrange for evictor to run while it is being returned // validation takes a second, evictor runs every 500 ms final PooledTestObject obj = pool.borrowObject(0); Thread.sleep(50); // abandon obj - pool.returnObject(0,obj); // evictor will run during validation + pool.returnObject(0, obj); // evictor will run during validation final PooledTestObject obj2 = pool.borrowObject(0); assertEquals(obj, obj2); // should get original back assertFalse(obj2.isDestroyed()); // and not destroyed @@ -371,7 +368,7 @@ public void testRemoveAbandonedWhileReturning() throws Exception { * JIRA: POOL-300 */ @Test - public void testStackTrace() throws Exception { + void testStackTrace() throws Exception { abandonedConfig.setRemoveAbandonedOnMaintenance(true); abandonedConfig.setLogAbandoned(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); @@ -380,7 +377,7 @@ public void testStackTrace() throws Exception { final PrintWriter pw = new PrintWriter(bos); abandonedConfig.setLogWriter(pw); pool.setAbandonedConfig(abandonedConfig); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); final PooledTestObject o1 = pool.borrowObject(0); Thread.sleep(2000); assertTrue(o1.isDestroyed()); @@ -398,10 +395,10 @@ public void testStackTrace() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testWhenExhaustedBlock() throws Exception { + void testWhenExhaustedBlock() throws Exception { abandonedConfig.setRemoveAbandonedOnMaintenance(true); pool.setAbandonedConfig(abandonedConfig); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); pool.setMaxTotal(1); diff --git a/src/test/java/org/apache/commons/pool2/impl/TestAbandonedObjectPool.java b/src/test/java/org/apache/commons/pool3/impl/TestAbandonedObjectPool.java similarity index 85% rename from src/test/java/org/apache/commons/pool2/impl/TestAbandonedObjectPool.java rename to src/test/java/org/apache/commons/pool3/impl/TestAbandonedObjectPool.java index b403f9049..5b7be2ec7 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestAbandonedObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestAbandonedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -35,16 +35,16 @@ import javax.management.MBeanServer; import javax.management.ObjectName; -import org.apache.commons.pool2.DestroyMode; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectFactory; -import org.apache.commons.pool2.TrackedUse; -import org.apache.commons.pool2.Waiter; +import org.apache.commons.pool3.DestroyMode; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; +import org.apache.commons.pool3.TrackedUse; +import org.apache.commons.pool3.Waiter; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -class PooledTestObject implements TrackedUse { +final class PooledTestObject implements TrackedUse { private static final AtomicInteger ATOMIC_HASH = new AtomicInteger(); private static final Instant INSTANT_0 = Instant.ofEpochMilli(0); private static final Instant INSTANT_1 = Instant.ofEpochMilli(1); @@ -54,7 +54,7 @@ class PooledTestObject implements TrackedUse { private boolean abandoned; private boolean detached; // destroy-abandoned "detaches" - public PooledTestObject() { + PooledTestObject() { this.hash = ATOMIC_HASH.incrementAndGet(); } @@ -73,17 +73,6 @@ public boolean equals(final Object obj) { return obj.hashCode() == hashCode(); } - @Override - public long getLastUsed() { - if (abandoned) { - // Abandoned object sweep will occur no matter what the value of removeAbandonedTimeout, - // because this indicates that this object was last used decades ago - return 1; - } - // Abandoned object sweep won't clean up this object - return 0; - } - @Override public Instant getLastUsedInstant() { if (abandoned) { @@ -124,12 +113,12 @@ public synchronized void setActive(final boolean b) { /** * TestCase for AbandonedObjectPool */ -public class TestAbandonedObjectPool { +class TestAbandonedObjectPool { - class ConcurrentBorrower extends Thread { + private final class ConcurrentBorrower extends Thread { private final ArrayList borrowed; - public ConcurrentBorrower(final ArrayList borrowed) { + private ConcurrentBorrower(final ArrayList borrowed) { this.borrowed = borrowed; } @@ -142,11 +131,14 @@ public void run() { } } } - class ConcurrentReturner extends Thread { + + private final class ConcurrentReturner extends Thread { private final PooledTestObject returned; - public ConcurrentReturner(final PooledTestObject obj) { + + private ConcurrentReturner(final PooledTestObject obj) { returned = obj; } + @Override public void run() { try { @@ -158,17 +150,17 @@ public void run() { } } - private static class SimpleFactory implements PooledObjectFactory { + private static final class SimpleFactory implements PooledObjectFactory { private final long destroyLatency; private final long validateLatency; - public SimpleFactory() { + private SimpleFactory() { destroyLatency = 0; validateLatency = 0; } - public SimpleFactory(final long destroyLatency, final long validateLatency) { + private SimpleFactory(final long destroyLatency, final long validateLatency) { this.destroyLatency = destroyLatency; this.validateLatency = validateLatency; } @@ -228,11 +220,6 @@ public void setUp() { // One second Duration. abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); assertEquals(TestConstants.ONE_SECOND_DURATION, abandonedConfig.getRemoveAbandonedTimeoutDuration()); - assertEquals(1, abandonedConfig.getRemoveAbandonedTimeout()); // in seconds. - // One second int (not millis). - abandonedConfig.setRemoveAbandonedTimeout(1); - assertEquals(TestConstants.ONE_SECOND_DURATION, abandonedConfig.getRemoveAbandonedTimeoutDuration()); - assertEquals(1, abandonedConfig.getRemoveAbandonedTimeout()); // in seconds. pool = new GenericObjectPool<>( new SimpleFactory(), @@ -250,7 +237,7 @@ public void tearDown() throws Exception { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); final Set result = mbs.queryNames(new ObjectName( - "org.apache.commoms.pool2:type=GenericObjectPool,*"), null); + "org.apache.commoms.pool3:type=GenericObjectPool,*"), null); // There should be no registered pools at this point final int registeredPoolCount = result.size(); final StringBuilder msg = new StringBuilder("Current pool is: "); @@ -264,7 +251,7 @@ public void tearDown() throws Exception { msg.append('\n'); mbs.unregisterMBean(name); } - assertEquals( 0, registeredPoolCount,msg.toString()); + assertEquals(0, registeredPoolCount, msg.toString()); } /** @@ -274,7 +261,7 @@ public void tearDown() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testAbandonedInvalidate() throws Exception { + void testAbandonedInvalidate() throws Exception { abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnMaintenance(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); @@ -286,7 +273,7 @@ public void testAbandonedInvalidate() throws Exception { final int n = 10; pool.setMaxTotal(n); pool.setBlockWhenExhausted(false); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); PooledTestObject obj = null; for (int i = 0; i < 5; i++) { obj = pool.borrowObject(); @@ -306,7 +293,7 @@ public void testAbandonedInvalidate() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testAbandonedReturn() throws Exception { + void testAbandonedReturn() throws Exception { abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnBorrow(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); @@ -341,7 +328,7 @@ public void testAbandonedReturn() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testConcurrentInvalidation() throws Exception { + void testConcurrentInvalidation() throws Exception { final int POOL_SIZE = 30; pool.setMaxTotal(POOL_SIZE); pool.setMaxIdle(POOL_SIZE); @@ -382,7 +369,7 @@ public void testConcurrentInvalidation() throws Exception { assertEquals(0, pool.getNumActive(), "numActive should have been 0, was " + pool.getNumActive()); } - public void testDestroyModeAbandoned() throws Exception { + void testDestroyModeAbandoned() throws Exception { abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnMaintenance(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); @@ -391,14 +378,14 @@ public void testDestroyModeAbandoned() throws Exception { // validate takes 1 second new SimpleFactory(0, 0), new GenericObjectPoolConfig<>(), abandonedConfig); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(50)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(50)); // Borrow an object, wait long enough for it to be abandoned final PooledTestObject obj = pool.borrowObject(); Thread.sleep(100); assertTrue(obj.isDetached()); } - public void testDestroyModeNormal() throws Exception { + void testDestroyModeNormal() throws Exception { abandonedConfig = new AbandonedConfig(); pool.close(); // Unregister pool created by setup pool = new GenericObjectPool<>(new SimpleFactory(0, 0)); @@ -416,7 +403,7 @@ public void testDestroyModeNormal() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testRemoveAbandonedWhileReturning() throws Exception { + void testRemoveAbandonedWhileReturning() throws Exception { abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnMaintenance(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); @@ -428,7 +415,7 @@ public void testRemoveAbandonedWhileReturning() throws Exception { final int n = 10; pool.setMaxTotal(n); pool.setBlockWhenExhausted(false); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); pool.setTestOnReturn(true); // Borrow an object, wait long enough for it to be abandoned // then arrange for evictor to run while it is being returned @@ -445,21 +432,25 @@ public void testRemoveAbandonedWhileReturning() throws Exception { * JIRA: POOL-300 */ @Test - public void testStackTrace() throws Exception { + void testStackTrace() throws Exception { abandonedConfig.setRemoveAbandonedOnMaintenance(true); abandonedConfig.setLogAbandoned(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); + abandonedConfig.setUseUsageTracking(true); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final BufferedOutputStream bos = new BufferedOutputStream(baos); final PrintWriter pw = new PrintWriter(bos); abandonedConfig.setLogWriter(pw); pool.setAbandonedConfig(abandonedConfig); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); final PooledTestObject o1 = pool.borrowObject(); + pool.use(o1); Thread.sleep(2000); assertTrue(o1.isDestroyed()); bos.flush(); - assertTrue(baos.toString().indexOf("Pooled object") >= 0); + final String traceString = baos.toString(); + assertTrue(traceString.indexOf("Pooled object") >= 0); + assertTrue(traceString.indexOf("The last code to use this object was:") >= 0); } /** @@ -472,10 +463,10 @@ public void testStackTrace() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testWhenExhaustedBlock() throws Exception { + void testWhenExhaustedBlock() throws Exception { abandonedConfig.setRemoveAbandonedOnMaintenance(true); pool.setAbandonedConfig(abandonedConfig); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); pool.setMaxTotal(1); diff --git a/src/test/java/org/apache/commons/pool3/impl/TestBaseGenericObjectPool.java b/src/test/java/org/apache/commons/pool3/impl/TestBaseGenericObjectPool.java new file mode 100644 index 000000000..caeb2d851 --- /dev/null +++ b/src/test/java/org/apache/commons/pool3/impl/TestBaseGenericObjectPool.java @@ -0,0 +1,313 @@ +/* + * 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 + * + * https://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.pool3.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.management.ManagementFactory; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.commons.pool3.TestException; +import org.apache.commons.pool3.Waiter; +import org.apache.commons.pool3.WaiterFactory; +import org.apache.commons.pool3.impl.TestGenericObjectPool.SimpleFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +/** + */ +class TestBaseGenericObjectPool { + + BaseGenericObjectPool pool; + SimpleFactory factory; + + @BeforeEach + public void setUp() { + factory = new SimpleFactory(); + pool = new GenericObjectPool<>(factory); + } + + @AfterEach + public void tearDown() { + pool.close(); + pool = null; + factory = null; + } + + @Test + void testActiveTimeStatistics() { + for (int i = 0; i < 99; i++) { // must be < MEAN_TIMING_STATS_CACHE_SIZE + pool.updateStatsReturn(Duration.ofMillis(i)); + } + assertEquals(49, pool.getMeanActiveTimeMillis(), Double.MIN_VALUE); + } + + @Test + void testBorrowWaitStatistics() { + final DefaultPooledObject p = (DefaultPooledObject) factory.makeObject(); + pool.updateStatsBorrow(p, Duration.ofMillis(10)); + pool.updateStatsBorrow(p, Duration.ofMillis(20)); + pool.updateStatsBorrow(p, Duration.ofMillis(20)); + pool.updateStatsBorrow(p, Duration.ofMillis(30)); + assertEquals(20, pool.getMeanBorrowWaitTimeMillis(), Double.MIN_VALUE); + assertEquals(30, pool.getMaxBorrowWaitTimeMillis(), 0); + } + + void testBorrowWaitStatisticsMax() { + final DefaultPooledObject p = (DefaultPooledObject) factory.makeObject(); + assertEquals(0, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); + pool.updateStatsBorrow(p, Duration.ZERO); + assertEquals(0, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); + pool.updateStatsBorrow(p, Duration.ofMillis(20)); + assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); + pool.updateStatsBorrow(p, Duration.ofMillis(20)); + assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); + pool.updateStatsBorrow(p, Duration.ofMillis(10)); + assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE); + } + + @Test + void testEvictionTimerMultiplePools() throws InterruptedException { + final AtomicIntegerFactory factory = new AtomicIntegerFactory(); + factory.setValidateLatency(50); + try (GenericObjectPool evictingPool = new GenericObjectPool<>(factory)) { + evictingPool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); + evictingPool.setNumTestsPerEvictionRun(5); + evictingPool.setTestWhileIdle(true); + evictingPool.setMinEvictableIdleDuration(Duration.ofMillis(50)); + for (int i = 0; i < 10; i++) { + try { + evictingPool.addObject(); + } catch (final Exception e) { + e.printStackTrace(); + } + } + + for (int i = 0; i < 1000; i++) { + try (GenericObjectPool nonEvictingPool = new GenericObjectPool<>(factory)) { + // empty + } + } + + Thread.sleep(1000); + assertEquals(0, evictingPool.getNumIdle()); + } + } + + /** + * POOL-393 + * Tests JMX registration does not add too much latency to pool creation. + */ + @SuppressWarnings("resource") // pools closed in finally block + @Test + @Timeout(value = 10_000, unit = TimeUnit.MILLISECONDS) + void testJMXRegistrationLatency() { + final int numPools = 1000; + final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + final ArrayList> pools = new ArrayList<>(); + try { + // final long startTime = System.currentTimeMillis(); + for (int i = 0; i < numPools; i++) { + pools.add(new GenericObjectPool<>(new WaiterFactory<>(0, 0, 0, 0, 0, 0), new GenericObjectPoolConfig<>())); + } + // System.out.println("Duration: " + (System.currentTimeMillis() - startTime)); + final ObjectName oname = pools.get(numPools - 1).getJmxName(); + assertEquals(1, mbs.queryNames(oname, null).size()); + } finally { + pools.forEach(GenericObjectPool::close); + } + } + + @Test + void testCollectDetailedStatisticsDefault() { + // Test that collectDetailedStatistics defaults to true for backward compatibility + assertTrue(pool.getCollectDetailedStatistics()); + } + + @Test + void testCollectDetailedStatisticsConfiguration() { + // Test configuration through config object + final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); + config.setCollectDetailedStatistics(false); + try (GenericObjectPool testPool = new GenericObjectPool<>(factory, config)) { + assertFalse(testPool.getCollectDetailedStatistics()); + } + // Test runtime configuration + pool.setCollectDetailedStatistics(false); + assertFalse(pool.getCollectDetailedStatistics()); + pool.setCollectDetailedStatistics(true); + assertTrue(pool.getCollectDetailedStatistics()); + } + + @Test + void testCollectDetailedStatisticsDisabled() throws Exception { + // Configure pool to disable detailed statistics + pool.setCollectDetailedStatistics(false); + final DefaultPooledObject pooledObject = (DefaultPooledObject) factory.makeObject(); + // Record initial values + final long initialActiveTime = pool.getMeanActiveTimeMillis(); + final long initialIdleTime = pool.getMeanIdleDuration().toMillis(); + final long initialWaitTime = pool.getMeanBorrowWaitTimeMillis(); + final long initialMaxWaitTime = pool.getMaxBorrowWaitTimeMillis(); + // Update statistics - should be ignored for detailed stats + pool.updateStatsBorrow(pooledObject, Duration.ofMillis(100)); + pool.updateStatsReturn(Duration.ofMillis(200)); + // Basic counters should still work + assertEquals(1, pool.getBorrowedCount()); + assertEquals(1, pool.getReturnedCount()); + // Detailed statistics should remain unchanged + assertEquals(initialActiveTime, pool.getMeanActiveTimeMillis()); + assertEquals(initialIdleTime, pool.getMeanIdleDuration().toMillis()); + assertEquals(initialWaitTime, pool.getMeanBorrowWaitTimeMillis()); + assertEquals(initialMaxWaitTime, pool.getMaxBorrowWaitTimeMillis()); + } + + @Test + void testCollectDetailedStatisticsEnabled() throws Exception { + // Ensure detailed statistics are enabled (default) + pool.setCollectDetailedStatistics(true); + final DefaultPooledObject pooledObject = (DefaultPooledObject) factory.makeObject(); + // Update statistics + pool.updateStatsBorrow(pooledObject, Duration.ofMillis(100)); + pool.updateStatsReturn(Duration.ofMillis(200)); + // All counters should work + assertEquals(1, pool.getBorrowedCount()); + assertEquals(1, pool.getReturnedCount()); + // Detailed statistics should be updated + assertEquals(200, pool.getMeanActiveTimeMillis()); + assertEquals(100, pool.getMeanBorrowWaitTimeMillis()); + assertEquals(100, pool.getMaxBorrowWaitTimeMillis()); + } + + @Test + void testCollectDetailedStatisticsToggling() throws Exception { + final DefaultPooledObject pooledObject = (DefaultPooledObject) factory.makeObject(); + // Start with detailed stats enabled + pool.setCollectDetailedStatistics(true); + pool.updateStatsBorrow(pooledObject, Duration.ofMillis(50)); + pool.updateStatsReturn(Duration.ofMillis(100)); + assertEquals(50, pool.getMeanBorrowWaitTimeMillis()); + assertEquals(100, pool.getMeanActiveTimeMillis()); + // Disable detailed stats + pool.setCollectDetailedStatistics(false); + pool.updateStatsBorrow(pooledObject, Duration.ofMillis(200)); + pool.updateStatsReturn(Duration.ofMillis(300)); + // Detailed stats should remain at previous values + assertEquals(50, pool.getMeanBorrowWaitTimeMillis()); + assertEquals(100, pool.getMeanActiveTimeMillis()); + // Basic counters should continue to increment + assertEquals(2, pool.getBorrowedCount()); + assertEquals(2, pool.getReturnedCount()); + } + + @Test + void testStatsStoreConcurrentAccess() throws Exception { + // Test the lock-free StatsStore implementation under concurrent load + final int numThreads = 10; + final int operationsPerThread = 1000; + final ExecutorService executor = Executors.newFixedThreadPool(numThreads); + final CountDownLatch startLatch = new CountDownLatch(1); + final CountDownLatch completeLatch = new CountDownLatch(numThreads); + final List> futures = new ArrayList<>(); + // Create threads that will concurrently update statistics + for (int i = 0; i < numThreads; i++) { + final int threadId = i; + futures.add(executor.submit(() -> { + try { + final DefaultPooledObject pooledObject = (DefaultPooledObject) factory.makeObject(); + // Wait for all threads to be ready + startLatch.await(); + // Perform concurrent operations + for (int j = 0; j < operationsPerThread; j++) { + pool.updateStatsBorrow(pooledObject, Duration.ofMillis(threadId * 10 + j)); + pool.updateStatsReturn(Duration.ofMillis(threadId * 20 + j)); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + completeLatch.countDown(); + } + return null; + })); + } + // Start all threads simultaneously + startLatch.countDown(); + // Wait for completion + assertTrue(completeLatch.await(30, TimeUnit.SECONDS), "Concurrent test should complete within 30 seconds"); + // Verify no exceptions occurred + for (Future future : futures) { + future.get(); // Will throw if there was an exception + } + // Verify that statistics were collected (exact values may vary due to race conditions) + assertEquals(numThreads * operationsPerThread, pool.getBorrowedCount()); + assertEquals(numThreads * operationsPerThread, pool.getReturnedCount()); + // Mean values should be reasonable (not zero or wildly incorrect) + assertTrue(pool.getMeanActiveTimeMillis() >= 0); + assertTrue(pool.getMeanBorrowWaitTimeMillis() >= 0); + assertTrue(pool.getMaxBorrowWaitTimeMillis() >= 0); + executor.shutdown(); + assertTrue(executor.awaitTermination(5, TimeUnit.SECONDS)); + } + + @Test + void testStatsStoreCircularBuffer() throws Exception { + // Test that StatsStore properly handles circular buffer behavior + final DefaultPooledObject pooledObject = (DefaultPooledObject) factory.makeObject(); + // Fill beyond the cache size (100) to test circular behavior + final int cacheSize = 100; // BaseGenericObjectPool.MEAN_TIMING_STATS_CACHE_SIZE + for (int i = 0; i < cacheSize + 50; i++) { + pool.updateStatsBorrow(pooledObject, Duration.ofMillis(i)); + pool.updateStatsReturn(Duration.ofMillis(i * 2)); + } + // Statistics should still be meaningful after circular buffer wrapping + assertTrue(pool.getMeanActiveTimeMillis() > 0); + assertTrue(pool.getMeanBorrowWaitTimeMillis() > 0); + assertTrue(pool.getMaxBorrowWaitTimeMillis() > 0); + // The mean should reflect recent values, not all historical values + // (exact assertion depends on circular buffer implementation) + assertTrue(pool.getMeanBorrowWaitTimeMillis() >= 50); // Should be influenced by recent higher values + } + + @Test + void testDetailedStatisticsConfigIntegration() { + // Test that config property is properly applied during pool construction + final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); + config.setCollectDetailedStatistics(false); + try (GenericObjectPool testPool = new GenericObjectPool<>(factory, config)) { + assertFalse(testPool.getCollectDetailedStatistics(), "Pool should respect collectDetailedStatistics setting from config"); + // Test that toString includes the new property + final String configString = config.toString(); + assertTrue(configString.contains("collectDetailedStatistics"), "Config toString should include collectDetailedStatistics property"); + } + } +} diff --git a/src/test/java/org/apache/commons/pool3/impl/TestCallStackUtils.java b/src/test/java/org/apache/commons/pool3/impl/TestCallStackUtils.java new file mode 100644 index 000000000..d484ef04f --- /dev/null +++ b/src/test/java/org/apache/commons/pool3/impl/TestCallStackUtils.java @@ -0,0 +1,51 @@ +/* + * 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 + * + * https://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.pool3.impl; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.junit.jupiter.api.Test; + +/** + * Tests {@link CallStackUtils}. + */ +class TestCallStackUtils { + + private static final String MESSAGE_FORMAT = "'Timestamp:' yyyy-MM-dd HH:mm:ss Z"; + + private void assertNewCallStack(final CallStack callStack) { + callStack.fillInStackTrace(); + final StringWriter out = new StringWriter(); + callStack.printStackTrace(new PrintWriter(out)); + assertFalse(out.toString().isEmpty()); + callStack.clear(); + out.getBuffer().setLength(0); + callStack.printStackTrace(new PrintWriter(out)); + assertTrue(out.toString().isEmpty()); + } + + @Test + void testNewCallStack3() { + assertNewCallStack(CallStackUtils.newCallStack(MESSAGE_FORMAT, false, false)); + assertNewCallStack(CallStackUtils.newCallStack(MESSAGE_FORMAT, false, true)); + } +} diff --git a/src/test/java/org/apache/commons/pool2/impl/TestConstants.java b/src/test/java/org/apache/commons/pool3/impl/TestConstants.java similarity index 91% rename from src/test/java/org/apache/commons/pool2/impl/TestConstants.java rename to src/test/java/org/apache/commons/pool3/impl/TestConstants.java index 9d1a62545..04462da7e 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestConstants.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestConstants.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,14 +15,14 @@ * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import java.time.Duration; /** * Constants used in tests. */ -public class TestConstants { +class TestConstants { /** * A duration of one second. diff --git a/src/test/java/org/apache/commons/pool2/impl/TestDefaultPooledObject.java b/src/test/java/org/apache/commons/pool3/impl/TestDefaultPooledObject.java similarity index 66% rename from src/test/java/org/apache/commons/pool2/impl/TestDefaultPooledObject.java rename to src/test/java/org/apache/commons/pool3/impl/TestDefaultPooledObject.java index 10575165a..f4e9107c7 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestDefaultPooledObject.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestDefaultPooledObject.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,14 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.Matchers.lessThanOrEqualTo; 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.assertTrue; import java.time.Duration; import java.util.ArrayList; @@ -31,13 +29,13 @@ import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; import org.junit.jupiter.api.Test; /** * Tests {@link DefaultPooledObject}. */ -public class TestDefaultPooledObject { +class TestDefaultPooledObject { /** * JIRA: POOL-279 @@ -45,24 +43,24 @@ public class TestDefaultPooledObject { * @throws Exception May occur in some failure modes */ @Test - public void testGetIdleTimeMillis() throws Exception { + void testGetIdleTimeMillis() throws Exception { final DefaultPooledObject dpo = new DefaultPooledObject<>(new Object()); - final AtomicBoolean negativeIdleTimeReturned = new AtomicBoolean(false); + final AtomicBoolean negativeIdleTimeReturned = new AtomicBoolean(); final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 3); final Runnable allocateAndDeallocateTask = () -> { for (int i1 = 0; i1 < 10000; i1++) { - if (dpo.getIdleDuration().isNegative() || dpo.getIdleTime().isNegative()) { + if (dpo.getIdleDuration().isNegative()) { negativeIdleTimeReturned.set(true); break; } - if (dpo.getIdleDuration().isNegative() || dpo.getIdleTime().isNegative()) { + if (dpo.getIdleDuration().isNegative()) { negativeIdleTimeReturned.set(true); break; } } dpo.allocate(); for (int i2 = 0; i2 < 10000; i2++) { - if (dpo.getIdleDuration().isNegative() || dpo.getIdleTime().isNegative()) { + if (dpo.getIdleDuration().isNegative()) { negativeIdleTimeReturned.set(true); break; } @@ -71,7 +69,7 @@ public void testGetIdleTimeMillis() throws Exception { }; final Runnable getIdleTimeTask = () -> { for (int i = 0; i < 10000; i++) { - if (dpo.getIdleDuration().isNegative() || dpo.getIdleTime().isNegative()) { + if (dpo.getIdleDuration().isNegative()) { negativeIdleTimeReturned.set(true); break; } @@ -90,7 +88,7 @@ public void testGetIdleTimeMillis() throws Exception { } @Test - public void testInitialStateActiveDuration() throws InterruptedException { + void testInitialStateActiveDuration() throws InterruptedException { final PooledObject dpo = new DefaultPooledObject<>(new Object()); // Sleep MUST be "long enough" to test that we are not returning a negative time. // Need an API in Java 8 to get the clock granularity. @@ -101,18 +99,12 @@ public void testInitialStateActiveDuration() throws InterruptedException { assertFalse(dpo.getActiveDuration().isNegative()); assertFalse(dpo.getActiveDuration().isZero()); // We use greaterThanOrEqualTo instead of equal because "now" many be different when each argument is evaluated. - assertThat(1L, lessThanOrEqualTo(2L)); // sanity check - assertThat(Duration.ZERO, lessThanOrEqualTo(Duration.ZERO.plusNanos(1))); // sanity check - assertThat(dpo.getActiveDuration(), lessThanOrEqualTo(dpo.getIdleDuration())); - // Deprecated - assertThat(dpo.getActiveDuration().toMillis(), lessThanOrEqualTo(dpo.getActiveTimeMillis())); - assertThat(dpo.getActiveDuration(), lessThanOrEqualTo(dpo.getActiveTime())); - assertThat(dpo.getActiveDuration(), lessThanOrEqualTo(dpo.getIdleTime())); - assertThat(dpo.getActiveDuration().toMillis(), lessThanOrEqualTo(dpo.getIdleTimeMillis())); + assertTrue(Duration.ZERO.compareTo(Duration.ZERO.plusNanos(1)) <= 0); // sanity check + assertTrue(dpo.getActiveDuration().compareTo(dpo.getIdleDuration()) <= 0); } @Test - public void testInitialStateCreateInstant() { + void testInitialStateCreateInstant() { final PooledObject dpo = new DefaultPooledObject<>(new Object()); // In the initial state, all instants are the creation instant: last borrow, last use, last return. @@ -122,17 +114,12 @@ public void testInitialStateCreateInstant() { assertEquals(dpo.getCreateInstant(), dpo.getLastReturnInstant()); assertEquals(dpo.getCreateInstant(), dpo.getLastUsedInstant()); - // Instant vs. long (deprecated) - assertEquals(dpo.getCreateInstant().toEpochMilli(), dpo.getCreateTime()); + assertEquals(dpo.getCreateInstant(), dpo.getCreateInstant()); - // long vs. long (deprecated) - assertEquals(dpo.getCreateTime(), dpo.getLastBorrowTime()); - assertEquals(dpo.getCreateTime(), dpo.getLastReturnTime()); - assertEquals(dpo.getCreateTime(), dpo.getLastUsedTime()); } @Test - public void testInitialStateDuration() throws InterruptedException { + void testInitialStateDuration() throws InterruptedException { final PooledObject dpo = new DefaultPooledObject<>(new Object()); final Duration duration1 = dpo.getFullDuration(); assertNotNull(duration1); @@ -141,11 +128,12 @@ public void testInitialStateDuration() throws InterruptedException { final Duration duration2 = dpo.getFullDuration(); assertNotNull(duration2); assertFalse(duration2.isNegative()); - assertThat(duration1, lessThan(duration2)); + assertTrue(duration1.compareTo(duration2) < 0); + } @Test - public void testInitialStateIdleDuration() throws InterruptedException { + void testInitialStateIdleDuration() throws InterruptedException { final PooledObject dpo = new DefaultPooledObject<>(new Object()); // Sleep MUST be "long enough" to test that we are not returning a negative time. Thread.sleep(200); @@ -154,12 +142,7 @@ public void testInitialStateIdleDuration() throws InterruptedException { // In the initial state, the idle duration is the time between "now" and the last return, which is the creation time. assertFalse(dpo.getIdleDuration().isNegative()); assertFalse(dpo.getIdleDuration().isZero()); - // We use greaterThanOrEqualTo instead of equal because "now" many be different when each argument is evaluated. - assertThat(dpo.getIdleDuration(), lessThanOrEqualTo(dpo.getActiveDuration())); - // Deprecated - // assertThat(dpo.getIdleDuration().toMillis(), lessThanOrEqualTo(dpo.getIdleTimeMillis())); - // assertThat(dpo.getIdleDuration(), lessThanOrEqualTo(dpo.getIdleTime())); - assertThat(dpo.getIdleDuration(), lessThanOrEqualTo(dpo.getActiveTime())); - assertThat(dpo.getIdleDuration().toMillis(), lessThanOrEqualTo(dpo.getActiveTimeMillis())); + // We use <= instead of equal because "now" many be different when each argument is evaluated. + assertTrue(dpo.getIdleDuration().compareTo(dpo.getActiveDuration()) <= 0); } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool2/impl/TestDefaultPooledObjectInfo.java b/src/test/java/org/apache/commons/pool3/impl/TestDefaultPooledObjectInfo.java similarity index 81% rename from src/test/java/org/apache/commons/pool2/impl/TestDefaultPooledObjectInfo.java rename to src/test/java/org/apache/commons/pool3/impl/TestDefaultPooledObjectInfo.java index cba399c7e..69df7c3d3 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestDefaultPooledObjectInfo.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestDefaultPooledObjectInfo.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -22,20 +22,20 @@ import java.text.SimpleDateFormat; import java.util.Set; -import org.apache.commons.pool2.TestException; -import org.apache.commons.pool2.impl.TestGenericObjectPool.SimpleFactory; +import org.apache.commons.pool3.TestException; +import org.apache.commons.pool3.impl.TestGenericObjectPool.SimpleFactory; import org.junit.jupiter.api.Test; -public class TestDefaultPooledObjectInfo { +class TestDefaultPooledObjectInfo { @Test - public void testGetLastBorrowTrace() throws Exception { + void testGetLastBorrowTrace() throws Exception { final AbandonedConfig abandonedConfig = new AbandonedConfig(); abandonedConfig.setRemoveAbandonedOnBorrow(true); abandonedConfig.setRemoveAbandonedTimeout(TestConstants.ONE_SECOND_DURATION); abandonedConfig.setLogAbandoned(true); - try (final GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory(), + try (GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory(), new GenericObjectPoolConfig<>(), abandonedConfig)) { pool.borrowObject(); @@ -50,8 +50,8 @@ public void testGetLastBorrowTrace() throws Exception { } @Test - public void testGetPooledObjectToString() throws Exception { - try (final GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory())) { + void testGetPooledObjectToString() throws Exception { + try (GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory())) { final String s1 = pool.borrowObject(); @@ -66,8 +66,8 @@ public void testGetPooledObjectToString() throws Exception { } @Test - public void testGetPooledObjectType() throws Exception { - try (final GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory())) { + void testGetPooledObjectType() throws Exception { + try (GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory())) { pool.borrowObject(); @@ -82,8 +82,8 @@ public void testGetPooledObjectType() throws Exception { } @Test - public void testTiming() throws Exception { - try (final GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory())) { + void testTiming() throws Exception { + try (GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory())) { final long t1Millis = System.currentTimeMillis(); diff --git a/src/test/java/org/apache/commons/pool2/impl/TestEvictionConfig.java b/src/test/java/org/apache/commons/pool3/impl/TestEvictionConfig.java similarity index 51% rename from src/test/java/org/apache/commons/pool2/impl/TestEvictionConfig.java rename to src/test/java/org/apache/commons/pool3/impl/TestEvictionConfig.java index 95db65b9e..9cff06cc4 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestEvictionConfig.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestEvictionConfig.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,9 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import java.time.Duration; @@ -25,46 +26,26 @@ /** * Tests for {@link EvictionConfig}. */ -public class TestEvictionConfig { +class TestEvictionConfig { @Test - public void testConstructor1s() { + void testConstructor1s() { final EvictionConfig config = new EvictionConfig(Duration.ofMillis(1), Duration.ofMillis(1), 1); - assertEquals(1, config.getIdleEvictDuration().toMillis()); - assertEquals(1, config.getIdleEvictTime()); - assertEquals(1, config.getIdleEvictTimeDuration().toMillis()); assertEquals(1, config.getIdleSoftEvictDuration().toMillis()); - assertEquals(1, config.getIdleSoftEvictTime()); - assertEquals(1, config.getIdleSoftEvictTimeDuration().toMillis()); assertEquals(1, config.getMinIdle()); + // toString() should never throw + assertFalse(config.toString().isEmpty()); } @Test - public void testConstructorZerosDurations() { + void testConstructorZerosDurations() { final EvictionConfig config = new EvictionConfig(Duration.ZERO, Duration.ZERO, 0); - - assertEquals(Long.MAX_VALUE, config.getIdleEvictDuration().toMillis()); - assertEquals(Long.MAX_VALUE, config.getIdleEvictTime()); - assertEquals(Long.MAX_VALUE, config.getIdleEvictTimeDuration().toMillis()); - assertEquals(Long.MAX_VALUE, config.getIdleSoftEvictDuration().toMillis()); - assertEquals(Long.MAX_VALUE, config.getIdleSoftEvictTime()); - assertEquals(Long.MAX_VALUE, config.getIdleSoftEvictTimeDuration().toMillis()); - assertEquals(0, config.getMinIdle()); - } - - @Test - public void testConstructorZerosMillis() { - @SuppressWarnings("deprecation") - final EvictionConfig config = new EvictionConfig(0, 0, 0); - assertEquals(Long.MAX_VALUE, config.getIdleEvictDuration().toMillis()); - assertEquals(Long.MAX_VALUE, config.getIdleEvictTime()); - assertEquals(Long.MAX_VALUE, config.getIdleEvictTimeDuration().toMillis()); assertEquals(Long.MAX_VALUE, config.getIdleSoftEvictDuration().toMillis()); - assertEquals(Long.MAX_VALUE, config.getIdleSoftEvictTime()); - assertEquals(Long.MAX_VALUE, config.getIdleSoftEvictTimeDuration().toMillis()); assertEquals(0, config.getMinIdle()); + // toString() should never throw + assertFalse(config.toString().isEmpty()); } } diff --git a/src/test/java/org/apache/commons/pool2/impl/TestEvictionTimer.java b/src/test/java/org/apache/commons/pool3/impl/TestEvictionTimer.java similarity index 89% rename from src/test/java/org/apache/commons/pool2/impl/TestEvictionTimer.java rename to src/test/java/org/apache/commons/pool3/impl/TestEvictionTimer.java index f904ff59d..ae813c52b 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestEvictionTimer.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestEvictionTimer.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,8 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; - +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -26,19 +25,19 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadPoolExecutor; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; import org.junit.jupiter.api.Test; /** * Tests for {@link EvictionTimer}. */ -public class TestEvictionTimer { +class TestEvictionTimer { @Test - public void testStartStopEvictionTimer() throws Exception { + void testStartStopEvictionTimer() throws Exception { - try (final GenericObjectPool pool = new GenericObjectPool<>(new BasePooledObjectFactory() { + try (GenericObjectPool pool = new GenericObjectPool<>(new BasePooledObjectFactory() { @Override public String create() { @@ -85,7 +84,7 @@ public PooledObject wrap(final String obj) { EvictionTimer.cancel(evictor1, BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT, false); // Assert that eviction objects are correctly cleaned - // 1 - the evictor timer task is cancelled + // 1 - the evictor timer task is canceled sf = (ScheduledFuture) evictorTaskFutureField.get(evictor1); assertTrue(sf.isCancelled()); // 2- and, the eviction action is removed from executor thread pool @@ -97,7 +96,7 @@ public PooledObject wrap(final String obj) { EvictionTimer.cancel(evictor2, BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT, false); // Assert that eviction objects are correctly cleaned - // 1 - the evictor timer task is cancelled + // 1 - the evictor timer task is canceled sf = (ScheduledFuture) evictorTaskFutureField.get(evictor2); assertTrue(sf.isCancelled()); // 2- and, the eviction thread pool executor is freed @@ -105,4 +104,4 @@ public PooledObject wrap(final String obj) { assertEquals(0, EvictionTimer.getNumTasks()); } } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java b/src/test/java/org/apache/commons/pool3/impl/TestGenericKeyedObjectPool.java similarity index 76% rename from src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java rename to src/test/java/org/apache/commons/pool3/impl/TestGenericKeyedObjectPool.java index 3e60202ad..980fcc7c6 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestGenericKeyedObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestGenericKeyedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,8 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2.impl; - +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -54,17 +53,18 @@ import javax.management.ObjectName; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.apache.commons.pool2.BaseKeyedPooledObjectFactory; -import org.apache.commons.pool2.DestroyMode; -import org.apache.commons.pool2.KeyedObjectPool; -import org.apache.commons.pool2.KeyedPooledObjectFactory; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.TestException; -import org.apache.commons.pool2.AbstractTestKeyedObjectPool; -import org.apache.commons.pool2.VisitTracker; -import org.apache.commons.pool2.VisitTrackerFactory; -import org.apache.commons.pool2.Waiter; -import org.apache.commons.pool2.WaiterFactory; +import org.apache.commons.lang3.function.Suppliers; +import org.apache.commons.pool3.AbstractTestKeyedObjectPool; +import org.apache.commons.pool3.BaseKeyedPooledObjectFactory; +import org.apache.commons.pool3.DestroyMode; +import org.apache.commons.pool3.KeyedObjectPool; +import org.apache.commons.pool3.KeyedPooledObjectFactory; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.TestException; +import org.apache.commons.pool3.VisitTracker; +import org.apache.commons.pool3.VisitTrackerFactory; +import org.apache.commons.pool3.Waiter; +import org.apache.commons.pool3.WaiterFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -74,9 +74,9 @@ /** */ -public class TestGenericKeyedObjectPool extends AbstractTestKeyedObjectPool { +class TestGenericKeyedObjectPool extends AbstractTestKeyedObjectPool { - private static class DaemonThreadFactory implements ThreadFactory { + private static final class DaemonThreadFactory implements ThreadFactory { @Override public Thread newThread(final Runnable r) { final Thread t = new Thread(r); @@ -85,11 +85,12 @@ public Thread newThread(final Runnable r) { } } - private static class DummyFactory extends BaseKeyedPooledObjectFactory { + private static final class DummyFactory extends BaseKeyedPooledObjectFactory { @Override public Object create(final Object key) { return null; } + @Override public PooledObject wrap(final Object value) { return new DefaultPooledObject<>(value); @@ -97,16 +98,15 @@ public PooledObject wrap(final Object value) { } /** - * Factory that creates HashSets. Note that this means - * 0) All instances are initially equal (not discernible by equals) - * 1) Instances are mutable and mutation can cause change in identity / hash code. + * Factory that creates HashSets. Note that this means 0) All instances are initially equal (not discernible by equals) 1) Instances are mutable and + * mutation can cause change in identity / hash code. */ - private static final class HashSetFactory - extends BaseKeyedPooledObjectFactory, RuntimeException> { + private static final class HashSetFactory extends BaseKeyedPooledObjectFactory, RuntimeException> { @Override public HashSet create(final String key) { return new HashSet<>(); } + @Override public PooledObject> wrap(final HashSet value) { return new DefaultPooledObject<>(value); @@ -116,14 +116,14 @@ public PooledObject> wrap(final HashSet value) { /** * Attempts to invalidate an object, swallowing IllegalStateException. */ - static class InvalidateThread implements Runnable { + private static class InvalidateThread implements Runnable { private final String obj; private final KeyedObjectPool pool; private final String key; private boolean done; - public InvalidateThread(final KeyedObjectPool pool, final String key, final String obj) { + private InvalidateThread(final KeyedObjectPool pool, final String key, final String obj) { this.obj = obj; this.pool = pool; this.key = key; @@ -147,8 +147,7 @@ public void run() { } } - private static class ObjectFactory - extends BaseKeyedPooledObjectFactory { + private static final class ObjectFactory extends BaseKeyedPooledObjectFactory { @Override public Object create(final Integer key) { @@ -181,11 +180,11 @@ public static class SimpleFactory implements KeyedPooledObjectFactory obj) throws T @Override public void destroyObject(final K key, final PooledObject obj) throws TestException { doWait(destroyLatency); - synchronized(this) { + synchronized (this) { activeCount--; } if (exceptionOnDestroy) { @@ -218,11 +217,10 @@ public PooledObject makeObject(final K key) throws TestException { } doWait(makeLatency); String out = null; - synchronized(this) { + synchronized (this) { activeCount++; if (activeCount > maxTotalPerKey) { - throw new IllegalStateException( - "Too many active instances: " + activeCount); + throw new IllegalStateException("Too many active instances: " + activeCount); } out = String.valueOf(key) + String.valueOf(counter++); } @@ -294,12 +292,12 @@ public boolean validateObject(final K key, final PooledObject obj) { } } - private static class SimplePerKeyFactory extends BaseKeyedPooledObjectFactory { + private static final class SimplePerKeyFactory extends BaseKeyedPooledObjectFactory { final ConcurrentHashMap map = new ConcurrentHashMap<>(); @Override public Object create(final Object key) { - int counter = map.computeIfAbsent(key, k -> new AtomicInteger(-1)).incrementAndGet(); + final int counter = map.computeIfAbsent(key, k -> new AtomicInteger(-1)).incrementAndGet(); return String.valueOf(key) + String.valueOf(counter); } @@ -310,14 +308,16 @@ public PooledObject wrap(final Object value) { } /** - * Very simple test thread that just tries to borrow an object from - * the provided pool with the specified key and returns it + * Very simple test thread that just tries to borrow an object from the provided pool with the specified key and returns it. + * + * @param Type of element pooled in the pool. + * @param Type of exception thrown by the pool. */ - static class SimpleTestThread implements Runnable { + private static class SimpleTestThread implements Runnable { private final KeyedObjectPool pool; private final String key; - public SimpleTestThread(final KeyedObjectPool pool, final String key) { + private SimpleTestThread(final KeyedObjectPool pool, final String key) { this.pool = pool; this.key = key; } @@ -334,8 +334,10 @@ public void run() { /** * DefaultEvictionPolicy modified to add latency + * + * @param the type of objects in the pool. */ - private static class SlowEvictionPolicy extends DefaultEvictionPolicy { + private static final class SlowEvictionPolicy extends DefaultEvictionPolicy { private final long delay; /** @@ -343,54 +345,53 @@ private static class SlowEvictionPolicy extends DefaultEvictionPolicy { * * @param delay number of ms of latency to inject in evict */ - public SlowEvictionPolicy(final long delay) { + private SlowEvictionPolicy(final long delay) { this.delay = delay; } @Override - public boolean evict(final EvictionConfig config, final PooledObject underTest, - final int idleCount) { + public boolean evict(final EvictionConfig config, final PooledObject underTest, final int idleCount) { Waiter.sleepQuietly(delay); return super.evict(config, underTest, idleCount); } } - static class TestThread implements Runnable { - private final java.util.Random random = new java.util.Random(); + private static class TestThread implements Runnable { + private final Random random = new Random(); /** GKOP to hit */ private final KeyedObjectPool pool; - /** number of borrow/return iterations */ + /** Number of borrow/return iterations */ private final int iter; - /** delay before borrow */ + /** Delay before borrow */ private final int startDelay; - /** delay before return */ + /** Delay before return */ private final int holdTime; - /** whether or not delays are random (with max = configured values) */ + /** Whether or not delays are random (with max = configured values) */ private final boolean randomDelay; - /** expected object */ + /** Expected object */ private final T expectedObject; - /** key used in borrow / return sequence - null means random */ + /** Key used in borrow / return sequence - null means random */ private final String key; private volatile boolean complete; private volatile boolean failed; private volatile Exception exception; - public TestThread(final KeyedObjectPool pool) { + private TestThread(final KeyedObjectPool pool) { this(pool, 100, 50, 50, true, null, null); } - public TestThread(final KeyedObjectPool pool, final int iter) { + private TestThread(final KeyedObjectPool pool, final int iter) { this(pool, iter, 50, 50, true, null, null); } - public TestThread(final KeyedObjectPool pool, final int iter, final int delay) { + private TestThread(final KeyedObjectPool pool, final int iter, final int delay) { this(pool, iter, delay, delay, true, null, null); } - public TestThread(final KeyedObjectPool pool, final int iter, final int startDelay, - final int holdTime, final boolean randomDelay, final T expectedObject, final String key) { + private TestThread(final KeyedObjectPool pool, final int iter, final int startDelay, final int holdTime, final boolean randomDelay, + final T expectedObject, final String key) { this.pool = pool; this.iter = iter; this.startDelay = startDelay; @@ -446,8 +447,7 @@ public void run() { } /* - * Very simple test thread that just tries to borrow an object from - * the provided pool with the specified key and returns it after a wait + * Very simple test thread that just tries to borrow an object from the provided pool with the specified key and returns it after a wait */ static class WaitingTestThread extends Thread { private final KeyedObjectPool pool; @@ -456,12 +456,12 @@ static class WaitingTestThread extends Thread { private Throwable thrown; private long preBorrowMillis; // just before borrow - private long postBorrowMillis; // borrow returned + private long postBorrowMillis; // borrow returned private long postReturnMillis; // after object was returned private long endedMillis; private String objectId; - public WaitingTestThread(final KeyedObjectPool pool, final String key, final long pause) { + WaitingTestThread(final KeyedObjectPool pool, final String key, final long pause) { this.pool = pool; this.key = key; this.pause = pause; @@ -480,7 +480,7 @@ public void run() { postReturnMillis = System.currentTimeMillis(); } catch (final Exception e) { thrown = e; - } finally{ + } finally { endedMillis = System.currentTimeMillis(); } } @@ -492,23 +492,22 @@ public void run() { private static final Integer KEY_TWO = Integer.valueOf(2); - private static final boolean DISPLAY_THREAD_DETAILS= - Boolean.getBoolean("TestGenericKeyedObjectPool.display.thread.details"); + private static final boolean DISPLAY_THREAD_DETAILS = Boolean.getBoolean("TestGenericKeyedObjectPool.display.thread.details"); // To pass this to a Maven test, use: // mvn test -DargLine="-DTestGenericKeyedObjectPool.display.thread.details=true" // @see https://issues.apache.org/jira/browse/SUREFIRE-121 - /** setUp(): {@code new GenericKeyedObjectPool(factory)} */ + /** SetUp(): {@code new GenericKeyedObjectPool(factory)} */ private GenericKeyedObjectPool gkoPool; - /** setUp(): {@code new SimpleFactory()} */ + /** SetUp(): {@code new SimpleFactory()} */ private SimpleFactory simpleFactory; private void checkEvictionOrder(final boolean lifo) throws InterruptedException, TestException { final SimpleFactory intFactory = new SimpleFactory<>(); - try (final GenericKeyedObjectPool intPool = new GenericKeyedObjectPool<>(intFactory)) { + try (GenericKeyedObjectPool intPool = new GenericKeyedObjectPool<>(intFactory)) { intPool.setNumTestsPerEvictionRun(2); - intPool.setMinEvictableIdleTime(Duration.ofMillis(100)); + intPool.setMinEvictableIdleDuration(Duration.ofMillis(100)); intPool.setLifo(lifo); for (int i = 0; i < 3; i++) { @@ -524,8 +523,7 @@ private void checkEvictionOrder(final boolean lifo) throws InterruptedException, /* * Initial state (Key, Object) pairs in order of age: * - * (0,0), (0,1), (0,2), (0,3), (0,4) (1,5), (1,6), (1,7), (1,8), (1,9) (2,10), (2,11), (2,12), (2,13), - * (2,14) + * (0,0), (0,1), (0,2), (0,3), (0,4) (1,5), (1,6), (1,7), (1,8), (1,9) (2,10), (2,11), (2,12), (2,13), (2,14) */ intPool.evict(); // Kill (0,0),(0,1) @@ -568,7 +566,7 @@ private void checkEvictionOrder(final boolean lifo) throws InterruptedException, intPool.clear(); // Reload - intPool.setMinEvictableIdleTime(Duration.ofMillis(500)); + intPool.setMinEvictableIdleDuration(Duration.ofMillis(500)); intFactory.counter = 0; // Reset counter for (int i = 0; i < 3; i++) { final Integer key = Integer.valueOf(i); @@ -617,10 +615,9 @@ private void checkEvictionOrder(final boolean lifo) throws InterruptedException, private void checkEvictorVisiting(final boolean lifo) throws Exception { VisitTrackerFactory trackerFactory = new VisitTrackerFactory<>(); - try (GenericKeyedObjectPool, RuntimeException> intPool = new GenericKeyedObjectPool<>( - trackerFactory)) { + try (GenericKeyedObjectPool, RuntimeException> intPool = new GenericKeyedObjectPool<>(trackerFactory)) { intPool.setNumTestsPerEvictionRun(2); - intPool.setMinEvictableIdleTime(Duration.ofMillis(-1)); + intPool.setMinEvictableIdleDuration(Duration.ofMillis(-1)); intPool.setTestWhileIdle(true); intPool.setLifo(lifo); intPool.setTestOnReturn(false); @@ -644,10 +641,9 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { for (int i = 0; i < 8; i++) { final VisitTracker tracker = intPool.borrowObject(KEY_ZERO); if (tracker.getId() >= 4) { - assertEquals( 0, tracker.getValidateCount(),"Unexpected instance visited " + tracker.getId()); + assertEquals(0, tracker.getValidateCount(), "Unexpected instance visited " + tracker.getId()); } else { - assertEquals( 1, - tracker.getValidateCount(),"Instance " + tracker.getId() + " visited wrong number of times."); + assertEquals(1, tracker.getValidateCount(), "Instance " + tracker.getId() + " visited wrong number of times."); } } // 0's are all out @@ -682,11 +678,9 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { for (int i = 0; i < 8; i++) { final VisitTracker tracker = intPool.borrowObject(KEY_ONE); if (lifo && tracker.getId() > 1 || !lifo && tracker.getId() > 2) { - assertEquals( 1, - tracker.getValidateCount(),"Instance " + tracker.getId() + " visited wrong number of times."); + assertEquals(1, tracker.getValidateCount(), "Instance " + tracker.getId() + " visited wrong number of times."); } else { - assertEquals( 2, - tracker.getValidateCount(),"Instance " + tracker.getId() + " visited wrong number of times."); + assertEquals(2, tracker.getValidateCount(), "Instance " + tracker.getId() + " visited wrong number of times."); } } } @@ -697,16 +691,15 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { final Random random = new Random(); random.setSeed(System.currentTimeMillis()); for (int i = 0; i < smallPrimes.length; i++) { - for (int j = 0; j < 5; j++) {// Try the tests a few times + for (int j = 0; j < 5; j++) { // Try the tests a few times // Can't use clear as some objects are still active so create // a new pool trackerFactory = new VisitTrackerFactory<>(); - try (GenericKeyedObjectPool, RuntimeException> intPool = new GenericKeyedObjectPool<>( - trackerFactory)) { + try (GenericKeyedObjectPool, RuntimeException> intPool = new GenericKeyedObjectPool<>(trackerFactory)) { intPool.setMaxIdlePerKey(-1); intPool.setMaxTotalPerKey(-1); intPool.setNumTestsPerEvictionRun(smallPrimes[i]); - intPool.setMinEvictableIdleTime(Duration.ofMillis(-1)); + intPool.setMinEvictableIdleDuration(Duration.ofMillis(-1)); intPool.setTestWhileIdle(true); intPool.setLifo(lifo); intPool.setTestOnReturn(false); @@ -745,18 +738,16 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { tracker = intPool.borrowObject(KEY_ZERO); visitCount = tracker.getValidateCount(); if (visitCount < cycleCount || visitCount > cycleCount + 1) { - fail(formatSettings("ZERO", "runs", runs, "lifo", lifo, "i", i, "j", j, "k", k, - "visitCount", visitCount, "cycleCount", cycleCount, "totalInstances", - totalInstances, zeroLength, oneLength, twoLength)); + fail(formatSettings("ZERO", "runs", runs, "lifo", lifo, "i", i, "j", j, "k", k, "visitCount", visitCount, "cycleCount", cycleCount, + "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); } } for (int k = 0; k < oneLength; k++) { tracker = intPool.borrowObject(KEY_ONE); visitCount = tracker.getValidateCount(); if (visitCount < cycleCount || visitCount > cycleCount + 1) { - fail(formatSettings("ONE", "runs", runs, "lifo", lifo, "i", i, "j", j, "k", k, "visitCount", - visitCount, "cycleCount", cycleCount, "totalInstances", totalInstances, zeroLength, - oneLength, twoLength)); + fail(formatSettings("ONE", "runs", runs, "lifo", lifo, "i", i, "j", j, "k", k, "visitCount", visitCount, "cycleCount", cycleCount, + "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); } } final int[] visits = new int[twoLength]; @@ -769,9 +760,8 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { for (int l = 0; l <= k; l++) { sb.append(visits[l]).append(' '); } - fail(formatSettings("TWO " + sb.toString(), "runs", runs, "lifo", lifo, "i", i, "j", j, "k", - k, "visitCount", visitCount, "cycleCount", cycleCount, "totalInstances", - totalInstances, zeroLength, oneLength, twoLength)); + fail(formatSettings("TWO " + sb.toString(), "runs", runs, "lifo", lifo, "i", i, "j", j, "k", k, "visitCount", visitCount, + "cycleCount", cycleCount, "totalInstances", totalInstances, zeroLength, oneLength, twoLength)); } } } @@ -779,8 +769,9 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { } } - private String formatSettings(final String title, final String s, final int i, final String s0, final boolean b0, final String s1, final int i1, final String s2, final int i2, final String s3, final int i3, - final String s4, final int i4, final String s5, final int i5, final String s6, final int i6, final int zeroLength, final int oneLength, final int twoLength){ + private String formatSettings(final String title, final String s, final int i, final String s0, final boolean b0, final String s1, final int i1, + final String s2, final int i2, final String s3, final int i3, final String s4, final int i4, final String s5, final int i5, final String s6, + final int i6, final int zeroLength, final int oneLength, final int twoLength) { final StringBuilder sb = new StringBuilder(80); sb.append(title).append(' '); sb.append(s).append('=').append(i).append(' '); @@ -800,7 +791,6 @@ protected Object getNthObject(final Object key, final int n) { return String.valueOf(key) + String.valueOf(n); } - @Override protected boolean isFifo() { return false; @@ -832,15 +822,15 @@ protected Object makeKey(final int n) { } /** - * Kicks off {@code numThreads} test threads, each of which will go - * through {@code iterations} borrow-return cycles with random delay - * times <= delay in between. + * Kicks off {@code numThreads} test threads, each of which will go through {@code iterations} borrow-return cycles with random delay times <= delay in + * between. * - * @param Type of object in pool - * @param numThreads Number of test threads - * @param iterations Number of iterations for each thread - * @param delay Maximum delay between iterations - * @param gkopPool The keyed object pool to use + * @param Type of object in pool + * @param Type of exception thrown in the pool. + * @param numThreads Number of test threads + * @param iterations Number of iterations for each thread + * @param delay Maximum delay between iterations + * @param gkopPool The keyed object pool to use */ public void runTestThreads(final int numThreads, final int iterations, final int delay, final GenericKeyedObjectPool gkopPool) { @@ -878,9 +868,7 @@ public void tearDownJmx() throws Exception { simpleFactory = null; final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - final Set result = mbs.queryNames(new ObjectName( - "org.apache.commoms.pool2:type=GenericKeyedObjectPool,*"), - null); + final Set result = mbs.queryNames(new ObjectName("org.apache.commoms.pool3:type=GenericKeyedObjectPool,*"), null); // There should be no registered pools at this point final int registeredPoolCount = result.size(); final StringBuilder msg = new StringBuilder("Current pool is: "); @@ -894,14 +882,14 @@ public void tearDownJmx() throws Exception { msg.append('\n'); mbs.unregisterMBean(name); } - assertEquals( 0, registeredPoolCount, msg.toString()); + assertEquals(0, registeredPoolCount, msg.toString()); } @Test - public void testAppendStats() { + void testAppendStats() { assertFalse(gkoPool.getMessageStatistics()); assertEquals("foo", gkoPool.appendStats("foo")); - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(new SimpleFactory<>())) { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(new SimpleFactory<>())) { pool.setMessagesStatistics(true); assertNotEquals("foo", pool.appendStats("foo")); pool.setMessagesStatistics(false); @@ -911,9 +899,9 @@ public void testAppendStats() { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testBlockedKeyDoesNotBlockPool() throws Exception { + void testBlockedKeyDoesNotBlockPool() throws Exception { gkoPool.setBlockWhenExhausted(true); - gkoPool.setMaxWaitMillis(5000); + gkoPool.setMaxWait(Duration.ofMillis(5000)); gkoPool.setMaxTotalPerKey(1); gkoPool.setMaxTotal(-1); gkoPool.borrowObject("one"); @@ -931,20 +919,18 @@ public void testBlockedKeyDoesNotBlockPool() throws Exception { // If it passes it should be almost instant // Use 3000ms as the threshold - should avoid timing issues on most // (all? platforms) - assertTrue(endMillis - startMillis < 4000, - "Elapsed time: " + (endMillis - startMillis) + " should be less than 4000"); + assertTrue(endMillis - startMillis < 4000, "Elapsed time: " + (endMillis - startMillis) + " should be less than 4000"); } /* - * Note: This test relies on timing for correct execution. There *should* be - * enough margin for this to work correctly on most (all?) systems but be - * aware of this if you see a failure of this test. + * Note: This test relies on timing for correct execution. There *should* be enough margin for this to work correctly on most (all?) systems but be aware of + * this if you see a failure of this test. */ @SuppressWarnings("rawtypes") @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testBorrowObjectFairness() throws Exception { + void testBorrowObjectFairness() throws Exception { final int numThreads = 40; final int maxTotal = 40; @@ -970,11 +956,7 @@ public void testBorrowObjectFairness() throws Exception { final Thread t = new Thread(threads[i]); t.start(); // Short delay to ensure threads start in correct order - try { - Thread.sleep(10); - } catch (final InterruptedException e) { - fail(e.toString()); - } + Thread.sleep(10); } // Return objects, other threads should get served in order @@ -994,110 +976,13 @@ public void testBorrowObjectFairness() throws Exception { } /** - * Tests POOL-411, or least tries to reproduce the NPE, but does not. - * - * @throws TestException a test failure. - */ - @Test - public void testConcurrentBorrowAndClear() throws TestException { - final int threadCount = 64; - final int taskCount = 64; - final int addCount = 1; - final int borrowCycles = 1024; - final int clearCycles = 1024; - final boolean useYield = true; - - testConcurrentBorrowAndClear(threadCount, taskCount, addCount, borrowCycles, clearCycles, useYield); - } - - /** - * See https://issues.apache.org/jira/browse/POOL-411?focusedCommentId=17741156&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-17741156 - * - * @throws TestException a test failure. - */ - @Test - public void testConcurrentBorrowAndClear_JiraComment17741156() throws TestException { - final int threadCount = 2; - final int taskCount = 2; - final int addCount = 1; - final int borrowCycles = 5_000; - final int clearCycles = 5_000; - final boolean useYield = false; - - testConcurrentBorrowAndClear(threadCount, taskCount, addCount, borrowCycles, clearCycles, useYield); - } - - /** - * Tests POOL-411, or least tries to reproduce the NPE, but does not. - * - * @throws TestException a test failure. - */ - private void testConcurrentBorrowAndClear(final int threadCount, final int taskCount, final int addCount, final int borrowCycles, final int clearCycles, - final boolean useYield) throws TestException { - final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); - final int maxTotalPerKey = borrowCycles + 1; - config.setMaxTotalPerKey(threadCount); - config.setMaxIdlePerKey(threadCount); - config.setMaxTotal(maxTotalPerKey * threadCount); - config.setBlockWhenExhausted(false); // pool exhausted indicates a bug in the test - - gkoPool = new GenericKeyedObjectPool<>(simpleFactory, config); - final String key = "0"; - gkoPool.addObjects(Arrays.asList(key), threadCount); - // all objects in the pool are now idle. - - final ExecutorService threadPool = Executors.newFixedThreadPool(threadCount); - final List> futures = new ArrayList<>(); - try { - for (int t = 0; t < taskCount; t++) { - futures.add(threadPool.submit(() -> { - for (int i = 0; i < clearCycles; i++) { - if (useYield) { - Thread.yield(); - } - gkoPool.clear(key, true); - try { - gkoPool.addObjects(Arrays.asList(key), addCount); - } catch (IllegalArgumentException | TestException e) { - fail(e); - } - } - })); - futures.add(threadPool.submit(() -> { - try { - for (int i = 0; i < borrowCycles; i++) { - if (useYield) { - Thread.yield(); - } - final String pooled = gkoPool.borrowObject(key); - gkoPool.returnObject(key, pooled); - } - } catch (TestException e) { - fail(e); - } - })); - } - futures.forEach(f -> { - try { - f.get(); - } catch (InterruptedException | ExecutionException e) { - fail(e); - } - }); - } finally { - threadPool.shutdownNow(); - } - } - - /** - * POOL-192 - * Verify that clear(key) does not leak capacity. + * POOL-192 Verify that clear(key) does not leak capacity. * * @throws Exception May occur in some failure modes */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testClear() throws Exception { + void testClear() throws Exception { gkoPool.setMaxTotal(2); gkoPool.setMaxTotalPerKey(2); gkoPool.setBlockWhenExhausted(false); @@ -1126,10 +1011,10 @@ public void testClear() throws Exception { */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testClearOldest() throws Exception { + void testClearOldest() throws Exception { // Make destroy have some latency so clearOldest takes some time final WaiterFactory waiterFactory = new WaiterFactory<>(0, 20, 0, 0, 0, 0, 50, 5, 0); - try (final GenericKeyedObjectPool waiterPool = new GenericKeyedObjectPool<>(waiterFactory)) { + try (GenericKeyedObjectPool waiterPool = new GenericKeyedObjectPool<>(waiterFactory)) { waiterPool.setMaxTotalPerKey(5); waiterPool.setMaxTotal(50); waiterPool.setLifo(false); @@ -1155,67 +1040,65 @@ public void testClearOldest() throws Exception { } } - /** - * POOL-391 Verify that when clear(key) is called with reuseCapacity true, - * capacity freed is reused and allocated to most loaded pools. - * - * @throws Exception May occur in some failure modes - */ - @Test - public void testClearReuseCapacity() throws Exception { - gkoPool.setMaxTotalPerKey(6); - gkoPool.setMaxTotal(6); - gkoPool.setMaxWait(Duration.ofSeconds(5)); - // Create one thread to wait on "one", two on "two", three on "three" - final ArrayList testThreads = new ArrayList<>(); - testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "one"))); - testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "two"))); - testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "two"))); - testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "three"))); - testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "three"))); - testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "three"))); - // Borrow two each from "four", "five", "six" - using all capacity - final String four = gkoPool.borrowObject("four"); - final String four2 = gkoPool.borrowObject("four"); - final String five = gkoPool.borrowObject("five"); - final String five2 = gkoPool.borrowObject("five"); - final String six = gkoPool.borrowObject("six"); - final String six2 = gkoPool.borrowObject("six"); - Thread.sleep(100); - // Launch the waiters - all will be blocked waiting - for (final Thread t : testThreads) { - t.start(); - } - Thread.sleep(100); - // Return and clear the fours - at least one "three" should get served - // Other should be a two or a three (three was most loaded) - gkoPool.returnObject("four", four); - gkoPool.returnObject("four", four2); - gkoPool.clear("four"); - Thread.sleep(20); - assertTrue(!testThreads.get(3).isAlive() || !testThreads.get(4).isAlive() || !testThreads.get(5).isAlive()); - // Now clear the fives - gkoPool.returnObject("five", five); - gkoPool.returnObject("five", five2); - gkoPool.clear("five"); - Thread.sleep(20); - // Clear the sixes - gkoPool.returnObject("six", six); - gkoPool.returnObject("six", six2); - gkoPool.clear("six"); - Thread.sleep(20); - for (final Thread t : testThreads) { - assertFalse(t.isAlive()); - } - } + * POOL-391 Verify that when clear(key) is called with reuseCapacity true, capacity freed is reused and allocated to most loaded pools. + * + * @throws Exception May occur in some failure modes + */ + @Test + void testClearReuseCapacity() throws Exception { + gkoPool.setMaxTotalPerKey(6); + gkoPool.setMaxTotal(6); + gkoPool.setMaxWait(Duration.ofSeconds(5)); + // Create one thread to wait on "one", two on "two", three on "three" + final ArrayList testThreads = new ArrayList<>(); + testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "one"))); + testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "two"))); + testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "two"))); + testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "three"))); + testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "three"))); + testThreads.add(new Thread(new SimpleTestThread<>(gkoPool, "three"))); + // Borrow two each from "four", "five", "six" - using all capacity + final String four = gkoPool.borrowObject("four"); + final String four2 = gkoPool.borrowObject("four"); + final String five = gkoPool.borrowObject("five"); + final String five2 = gkoPool.borrowObject("five"); + final String six = gkoPool.borrowObject("six"); + final String six2 = gkoPool.borrowObject("six"); + Thread.sleep(100); + // Launch the waiters - all will be blocked waiting + for (final Thread t : testThreads) { + t.start(); + } + Thread.sleep(100); + // Return and clear the fours - at least one "three" should get served + // Other should be a two or a three (three was most loaded) + gkoPool.returnObject("four", four); + gkoPool.returnObject("four", four2); + gkoPool.clear("four"); + Thread.sleep(20); + assertTrue(!testThreads.get(3).isAlive() || !testThreads.get(4).isAlive() || !testThreads.get(5).isAlive()); + // Now clear the fives + gkoPool.returnObject("five", five); + gkoPool.returnObject("five", five2); + gkoPool.clear("five"); + Thread.sleep(20); + // Clear the sixes + gkoPool.returnObject("six", six); + gkoPool.returnObject("six", six2); + gkoPool.clear("six"); + Thread.sleep(20); + for (final Thread t : testThreads) { + assertFalse(t.isAlive()); + } + } /** * POOL-391 Adapted from code in the JIRA ticket. */ @Test @Timeout(value = 10000, unit = TimeUnit.MILLISECONDS) - public void testClearUnblocksWaiters() throws Exception { + void testClearUnblocksWaiters() throws Exception { final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotalPerKey(1); config.setMaxTotal(1); @@ -1228,8 +1111,7 @@ public void activateObject(final Integer key, final PooledObject p) { } @Override - public void destroyObject(final Integer key, final PooledObject p) - throws InterruptedException { + public void destroyObject(final Integer key, final PooledObject p) throws InterruptedException { Thread.sleep(10); } @@ -1281,12 +1163,11 @@ public boolean validateObject(final Integer key, final PooledObject p) // POOL-259 @Test - public void testClientWaitStats() throws TestException { + void testClientWaitStats() throws TestException { final SimpleFactory factory = new SimpleFactory<>(); // Give makeObject a little latency factory.setMakeLatency(200); - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory, - new GenericKeyedObjectPoolConfig<>())) { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory, new GenericKeyedObjectPoolConfig<>())) { final String s = pool.borrowObject("one"); // First borrow waits on create, so wait time should be at least 200 ms // Allow 100ms error in clock times @@ -1302,20 +1183,116 @@ public void testClientWaitStats() throws TestException { } /** - * POOL-231 - verify that concurrent invalidates of the same object do not - * corrupt pool destroyCount. + * Tests POOL-411, or least tries to reproduce the NPE, but does not. + * + * @throws TestException a test failure. + */ + @Test + void testConcurrentBorrowAndClear() throws TestException { + final int threadCount = 64; + final int taskCount = 64; + final int addCount = 1; + final int borrowCycles = 1024; + final int clearCycles = 1024; + final boolean useYield = true; + + testConcurrentBorrowAndClear(threadCount, taskCount, addCount, borrowCycles, clearCycles, useYield); + } + + /* + * Tests POOL-411, or least tries to reproduce the NPE, but does not. + * + * @throws TestException a test failure. + */ + private void testConcurrentBorrowAndClear(final int threadCount, final int taskCount, final int addCount, final int borrowCycles, final int clearCycles, + final boolean useYield) throws TestException { + final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); + final int maxTotalPerKey = borrowCycles + 1; + config.setMaxTotalPerKey(threadCount); + config.setMaxIdlePerKey(threadCount); + config.setMaxTotal(maxTotalPerKey * threadCount); + config.setBlockWhenExhausted(false); // pool exhausted indicates a bug in the test + + gkoPool = new GenericKeyedObjectPool<>(simpleFactory, config); + final String key = "0"; + gkoPool.addObjects(Arrays.asList(key), threadCount); + // all objects in the pool are now idle. + + final ExecutorService threadPool = Executors.newFixedThreadPool(threadCount); + final List> futures = new ArrayList<>(); + try { + for (int t = 0; t < taskCount; t++) { + futures.add(threadPool.submit(() -> { + for (int i = 0; i < clearCycles; i++) { + if (useYield) { + Thread.yield(); + } + gkoPool.clear(key, true); + try { + gkoPool.addObjects(Arrays.asList(key), addCount); + } catch (IllegalArgumentException | TestException e) { + fail(e); + } + } + })); + futures.add(threadPool.submit(() -> { + try { + for (int i = 0; i < borrowCycles; i++) { + if (useYield) { + Thread.yield(); + } + final String pooled = gkoPool.borrowObject(key); + gkoPool.returnObject(key, pooled); + } + } catch (final TestException e) { + fail(e); + } + })); + } + futures.forEach(f -> { + try { + f.get(); + } catch (InterruptedException | ExecutionException e) { + fail(e); + } + }); + } finally { + threadPool.shutdownNow(); + } + } + + /** + * See https://issues.apache.org/jira/browse/POOL-411? + * focusedCommentId=17741156&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-17741156 + * + * @throws TestException a test failure. + */ + @Test + void testConcurrentBorrowAndClear_JiraComment17741156() throws TestException { + final int threadCount = 2; + final int taskCount = 2; + final int addCount = 1; + final int borrowCycles = 5_000; + final int clearCycles = 5_000; + final boolean useYield = false; + + testConcurrentBorrowAndClear(threadCount, taskCount, addCount, borrowCycles, clearCycles, useYield); + } + + /** + * POOL-231 - verify that concurrent invalidates of the same object do not corrupt pool destroyCount. * * @throws Exception May occur in some failure modes */ @Test - public void testConcurrentInvalidate() throws Exception { + void testConcurrentInvalidate() throws Exception { // Get allObjects and idleObjects loaded with some instances final int nObjects = 1000; final String key = "one"; gkoPool.setMaxTotal(nObjects); gkoPool.setMaxTotalPerKey(nObjects); gkoPool.setMaxIdlePerKey(nObjects); - final String [] obj = new String[nObjects]; + final String[] obj = new String[nObjects]; for (int i = 0; i < nObjects; i++) { obj[i] = gkoPool.borrowObject(key); } @@ -1357,16 +1334,15 @@ public void testConcurrentInvalidate() throws Exception { } @Test - public void testConstructorNullFactory() { + void testConstructorNullFactory() { // add dummy assert (won't be invoked because of IAE) to avoid "unused" warning - assertThrows(IllegalArgumentException.class, - () -> new GenericKeyedObjectPool<>(null)); + assertThrows(IllegalArgumentException.class, () -> new GenericKeyedObjectPool<>(null)); } @SuppressWarnings("deprecation") @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testConstructors() { + void testConstructors() { // Make constructor arguments all different from defaults final int maxTotalPerKey = 1; @@ -1388,34 +1364,20 @@ public void testConstructors() { try (GenericKeyedObjectPool objPool = new GenericKeyedObjectPool<>(dummyFactory)) { assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY, objPool.getMaxTotalPerKey()); assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY, objPool.getMaxIdlePerKey()); - assertEquals(BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS, objPool.getMaxWaitMillis()); + assertEquals(BaseObjectPoolConfig.DEFAULT_MAX_WAIT, objPool.getMaxWaitDuration()); assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY, objPool.getMinIdlePerKey()); assertEquals(GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL, objPool.getMaxTotal()); // - assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, - objPool.getMinEvictableIdleTimeMillis()); - assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME, - objPool.getMinEvictableIdleTime()); - assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME, - objPool.getMinEvictableIdleDuration()); + assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION, objPool.getMinEvictableIdleDuration()); // assertEquals(BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, objPool.getNumTestsPerEvictionRun()); - assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW), - Boolean.valueOf(objPool.getTestOnBorrow())); - assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN), - Boolean.valueOf(objPool.getTestOnReturn())); - assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE), - Boolean.valueOf(objPool.getTestWhileIdle())); + assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW), Boolean.valueOf(objPool.getTestOnBorrow())); + assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN), Boolean.valueOf(objPool.getTestOnReturn())); + assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE), Boolean.valueOf(objPool.getTestWhileIdle())); // - assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS, - objPool.getDurationBetweenEvictionRuns()); - assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, - objPool.getTimeBetweenEvictionRunsMillis()); - assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS, - objPool.getTimeBetweenEvictionRuns()); + assertEquals(BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS, objPool.getDurationBetweenEvictionRuns()); // - assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED), - Boolean.valueOf(objPool.getBlockWhenExhausted())); + assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED), Boolean.valueOf(objPool.getBlockWhenExhausted())); assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_LIFO), Boolean.valueOf(objPool.getLifo())); } @@ -1426,46 +1388,40 @@ public void testConstructors() { config.setMinIdlePerKey(minIdle); config.setMaxTotal(maxTotal); config.setMaxWait(maxWaitDuration); - config.setMinEvictableIdleTime(Duration.ofMillis(minEvictableIdleTimeMillis)); + config.setMinEvictableIdleDuration(Duration.ofMillis(minEvictableIdleTimeMillis)); config.setNumTestsPerEvictionRun(numTestsPerEvictionRun); config.setTestOnBorrow(testOnBorrow); config.setTestOnReturn(testOnReturn); config.setTestWhileIdle(testWhileIdle); - config.setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis)); + config.setDurationBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis)); config.setBlockWhenExhausted(blockWhenExhausted); try (GenericKeyedObjectPool objPool = new GenericKeyedObjectPool<>(dummyFactory, config)) { assertEquals(maxTotalPerKey, objPool.getMaxTotalPerKey()); assertEquals(maxIdle, objPool.getMaxIdlePerKey()); assertEquals(maxWaitDuration, objPool.getMaxWaitDuration()); - assertEquals(maxWaitMillis, objPool.getMaxWaitMillis()); assertEquals(minIdle, objPool.getMinIdlePerKey()); assertEquals(maxTotal, objPool.getMaxTotal()); assertEquals(minEvictableIdleTimeMillis, objPool.getMinEvictableIdleDuration().toMillis()); - assertEquals(minEvictableIdleTimeMillis, objPool.getMinEvictableIdleTimeMillis()); - assertEquals(minEvictableIdleTimeMillis, objPool.getMinEvictableIdleTime().toMillis()); assertEquals(numTestsPerEvictionRun, objPool.getNumTestsPerEvictionRun()); assertEquals(Boolean.valueOf(testOnBorrow), Boolean.valueOf(objPool.getTestOnBorrow())); assertEquals(Boolean.valueOf(testOnReturn), Boolean.valueOf(objPool.getTestOnReturn())); assertEquals(Boolean.valueOf(testWhileIdle), Boolean.valueOf(objPool.getTestWhileIdle())); assertEquals(timeBetweenEvictionRunsMillis, objPool.getDurationBetweenEvictionRuns().toMillis()); - assertEquals(timeBetweenEvictionRunsMillis, objPool.getTimeBetweenEvictionRunsMillis()); - assertEquals(timeBetweenEvictionRunsMillis, objPool.getTimeBetweenEvictionRuns().toMillis()); assertEquals(Boolean.valueOf(blockWhenExhausted), Boolean.valueOf(objPool.getBlockWhenExhausted())); assertEquals(Boolean.valueOf(lifo), Boolean.valueOf(objPool.getLifo())); } } /** - * JIRA: POOL-270 - make sure constructor correctly sets run - * frequency of evictor timer. + * JIRA: POOL-270 - make sure constructor correctly sets run frequency of evictor timer. */ @Test - public void testContructorEvictionConfig() throws TestException { + void testContructorEvictionConfig() throws TestException { final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); - config.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); - config.setMinEvictableIdleTime(Duration.ofMillis(50)); + config.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); + config.setMinEvictableIdleDuration(Duration.ofMillis(50)); config.setNumTestsPerEvictionRun(5); - try (final GenericKeyedObjectPool p = new GenericKeyedObjectPool<>(simpleFactory, config)) { + try (GenericKeyedObjectPool p = new GenericKeyedObjectPool<>(simpleFactory, config)) { for (int i = 0; i < 5; i++) { p.addObject("one"); } @@ -1477,15 +1433,14 @@ public void testContructorEvictionConfig() throws TestException { } /** - * Verifies that when a factory's makeObject produces instances that are not - * discernible by equals, the pool can handle them. + * Verifies that when a factory's makeObject produces instances that are not discernible by equals, the pool can handle them. * * JIRA: POOL-283 */ @Test - public void testEqualsIndiscernible() throws Exception { + void testEqualsIndiscernible() throws Exception { final HashSetFactory factory = new HashSetFactory(); - try (final GenericKeyedObjectPool, RuntimeException> pool = new GenericKeyedObjectPool<>(factory, + try (GenericKeyedObjectPool, RuntimeException> pool = new GenericKeyedObjectPool<>(factory, new GenericKeyedObjectPoolConfig<>())) { final HashSet s1 = pool.borrowObject("a"); final HashSet s2 = pool.borrowObject("a"); @@ -1496,19 +1451,19 @@ public void testEqualsIndiscernible() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testEviction() throws Exception { + void testEviction() throws Exception { gkoPool.setMaxIdlePerKey(500); gkoPool.setMaxTotalPerKey(500); gkoPool.setNumTestsPerEvictionRun(100); - gkoPool.setMinEvictableIdleTime(Duration.ofMillis(250)); - gkoPool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + gkoPool.setMinEvictableIdleDuration(Duration.ofMillis(250)); + gkoPool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); final String[] active = new String[500]; - for(int i=0;i<500;i++) { + for (int i = 0; i < 500; i++) { active[i] = gkoPool.borrowObject(""); } - for(int i=0;i<500;i++) { - gkoPool.returnObject("",active[i]); + for (int i = 0; i < 500; i++) { + gkoPool.returnObject("", active[i]); } Waiter.sleepQuietly(1000L); @@ -1516,43 +1471,43 @@ public void testEviction() throws Exception { Waiter.sleepQuietly(600L); assertTrue(gkoPool.getNumIdle("") < 400, "Should be less than 400 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); - assertTrue(gkoPool.getNumIdle("") < 300,"Should be less than 300 idle, found " + gkoPool.getNumIdle("")); + assertTrue(gkoPool.getNumIdle("") < 300, "Should be less than 300 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); assertTrue(gkoPool.getNumIdle("") < 200, "Should be less than 200 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); - assertTrue(gkoPool.getNumIdle("") < 100 , "Should be less than 100 idle, found " + gkoPool.getNumIdle("")); + assertTrue(gkoPool.getNumIdle("") < 100, "Should be less than 100 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); - assertEquals(0,gkoPool.getNumIdle(""),"Should be zero idle, found " + gkoPool.getNumIdle("")); + assertEquals(0, gkoPool.getNumIdle(""), "Should be zero idle, found " + gkoPool.getNumIdle("")); - for(int i=0;i<500;i++) { + for (int i = 0; i < 500; i++) { active[i] = gkoPool.borrowObject(""); } - for(int i=0;i<500;i++) { - gkoPool.returnObject("",active[i]); + for (int i = 0; i < 500; i++) { + gkoPool.returnObject("", active[i]); } Waiter.sleepQuietly(1000L); - assertTrue(gkoPool.getNumIdle("") < 500,"Should be less than 500 idle, found " + gkoPool.getNumIdle("")); + assertTrue(gkoPool.getNumIdle("") < 500, "Should be less than 500 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); - assertTrue(gkoPool.getNumIdle("") < 400,"Should be less than 400 idle, found " + gkoPool.getNumIdle("")); + assertTrue(gkoPool.getNumIdle("") < 400, "Should be less than 400 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); - assertTrue(gkoPool.getNumIdle("") < 300,"Should be less than 300 idle, found " + gkoPool.getNumIdle("")); + assertTrue(gkoPool.getNumIdle("") < 300, "Should be less than 300 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); - assertTrue(gkoPool.getNumIdle("") < 200,"Should be less than 200 idle, found " + gkoPool.getNumIdle("")); + assertTrue(gkoPool.getNumIdle("") < 200, "Should be less than 200 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); - assertTrue(gkoPool.getNumIdle("") < 100,"Should be less than 100 idle, found " + gkoPool.getNumIdle("")); + assertTrue(gkoPool.getNumIdle("") < 100, "Should be less than 100 idle, found " + gkoPool.getNumIdle("")); Waiter.sleepQuietly(600L); - assertEquals(0,gkoPool.getNumIdle(""),"Should be zero idle, found " + gkoPool.getNumIdle("")); + assertEquals(0, gkoPool.getNumIdle(""), "Should be zero idle, found " + gkoPool.getNumIdle("")); } @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testEviction2() throws Exception { + void testEviction2() throws Exception { gkoPool.setMaxIdlePerKey(500); gkoPool.setMaxTotalPerKey(500); gkoPool.setNumTestsPerEvictionRun(100); - gkoPool.setMinEvictableIdleTime(Duration.ofMillis(500)); - gkoPool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + gkoPool.setMinEvictableIdleDuration(Duration.ofMillis(500)); + gkoPool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); final String[] active = new String[500]; final String[] active2 = new String[500]; @@ -1591,8 +1546,7 @@ public void testEviction2() throws Exception { } /** - * Test to make sure evictor visits least recently used objects first, - * regardless of FIFO/LIFO + * Test to make sure evictor visits least recently used objects first, regardless of FIFO/LIFO * * JIRA: POOL-86 * @@ -1600,15 +1554,15 @@ public void testEviction2() throws Exception { */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testEvictionOrder() throws Exception { + void testEvictionOrder() throws Exception { checkEvictionOrder(false); checkEvictionOrder(true); } // POOL-326 @Test - public void testEvictorClearOldestRace() throws Exception { - gkoPool.setMinEvictableIdleTime(Duration.ofMillis(100)); + void testEvictorClearOldestRace() throws Exception { + gkoPool.setMinEvictableIdleDuration(Duration.ofMillis(100)); gkoPool.setNumTestsPerEvictionRun(1); // Introduce latency between when evictor starts looking at an instance and when @@ -1625,7 +1579,7 @@ public void testEvictorClearOldestRace() throws Exception { Thread.sleep(1000); // Start evictor and race with clearOldest - gkoPool.setTimeBetweenEvictionRuns(Duration.ofMillis(10)); + gkoPool.setDurationBetweenEvictionRuns(Duration.ofMillis(10)); // Wait for evictor to start Thread.sleep(100); @@ -1639,23 +1593,22 @@ public void testEvictorClearOldestRace() throws Exception { } /** - * Verifies that the evictor visits objects in expected order - * and frequency. + * Verifies that the evictor visits objects in expected order and frequency. * * @throws Exception May occur in some failure modes */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testEvictorVisiting() throws Exception { + void testEvictorVisiting() throws Exception { checkEvictorVisiting(true); checkEvictorVisiting(false); } @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testExceptionInValidationDuringEviction() throws Exception { + void testExceptionInValidationDuringEviction() throws Exception { gkoPool.setMaxIdlePerKey(1); - gkoPool.setMinEvictableIdleTime(Duration.ZERO); + gkoPool.setMinEvictableIdleDuration(Duration.ZERO); gkoPool.setTestWhileIdle(true); final String obj = gkoPool.borrowObject("one"); @@ -1667,10 +1620,9 @@ public void testExceptionInValidationDuringEviction() throws Exception { assertEquals(0, gkoPool.getNumIdle()); } - @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testExceptionOnActivateDuringBorrow() throws Exception { + void testExceptionOnActivateDuringBorrow() throws Exception { final String obj1 = gkoPool.borrowObject("one"); final String obj2 = gkoPool.borrowObject("one"); gkoPool.returnObject("one", obj1); @@ -1698,7 +1650,7 @@ public void testExceptionOnActivateDuringBorrow() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testExceptionOnDestroyDuringBorrow() throws Exception { + void testExceptionOnDestroyDuringBorrow() throws Exception { simpleFactory.setThrowExceptionOnDestroy(true); simpleFactory.setValidationEnabled(true); gkoPool.setTestOnBorrow(true); @@ -1713,7 +1665,7 @@ public void testExceptionOnDestroyDuringBorrow() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testExceptionOnDestroyDuringReturn() throws Exception { + void testExceptionOnDestroyDuringReturn() throws Exception { simpleFactory.setThrowExceptionOnDestroy(true); simpleFactory.setValidationEnabled(true); gkoPool.setTestOnReturn(true); @@ -1729,35 +1681,35 @@ public void testExceptionOnDestroyDuringReturn() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testExceptionOnPassivateDuringReturn() throws Exception { + void testExceptionOnPassivateDuringReturn() throws Exception { final String obj = gkoPool.borrowObject("one"); simpleFactory.setThrowExceptionOnPassivate(true); gkoPool.returnObject("one", obj); - assertEquals(0,gkoPool.getNumIdle()); + assertEquals(0, gkoPool.getNumIdle()); gkoPool.close(); } @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testFIFO() throws Exception { + void testFIFO() throws Exception { gkoPool.setLifo(false); final String key = "key"; gkoPool.addObject(key); // "key0" gkoPool.addObject(key); // "key1" gkoPool.addObject(key); // "key2" - assertEquals( "key0", gkoPool.borrowObject(key),"Oldest"); - assertEquals( "key1", gkoPool.borrowObject(key),"Middle"); - assertEquals( "key2", gkoPool.borrowObject(key),"Youngest"); + assertEquals("key0", gkoPool.borrowObject(key), "Oldest"); + assertEquals("key1", gkoPool.borrowObject(key), "Middle"); + assertEquals("key2", gkoPool.borrowObject(key), "Youngest"); final String s = gkoPool.borrowObject(key); - assertEquals( "key3", s,"new-3"); + assertEquals("key3", s, "new-3"); gkoPool.returnObject(key, s); - assertEquals( s, gkoPool.borrowObject(key),"returned"); - assertEquals( "key4", gkoPool.borrowObject(key),"new-4"); + assertEquals(s, gkoPool.borrowObject(key), "returned"); + assertEquals("key4", gkoPool.borrowObject(key), "new-4"); } @Test @Timeout(value = 60, unit = TimeUnit.SECONDS) - public void testGetKeys() throws Exception { + void testGetKeys() throws Exception { gkoPool.addObject("one"); assertEquals(1, gkoPool.getKeys().size()); gkoPool.addObject("two"); @@ -1769,7 +1721,7 @@ public void testGetKeys() throws Exception { } @Test - public void testGetStatsString() { + void testGetStatsString() { assertNotNull(gkoPool.getStatsString()); } @@ -1782,11 +1734,11 @@ public void testGetStatsString() { * @throws Exception May occur in some failure modes */ @Test - public void testInvalidateFreesCapacity() throws TestException, InterruptedException { + void testInvalidateFreesCapacity() throws TestException, InterruptedException { final SimpleFactory factory = new SimpleFactory<>(); - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { pool.setMaxTotalPerKey(2); - pool.setMaxWaitMillis(500); + pool.setMaxWait(Duration.ofMillis(500)); // Borrow an instance and hold if for 5 seconds final WaitingTestThread thread1 = new WaitingTestThread<>(pool, "one", 5000); thread1.start(); @@ -1806,26 +1758,26 @@ public void testInvalidateFreesCapacity() throws TestException, InterruptedExcep } @Test - public void testInvalidateFreesCapacityForOtherKeys() throws Exception { + void testInvalidateFreesCapacityForOtherKeys() throws Exception { gkoPool.setMaxTotal(1); gkoPool.setMaxWait(Duration.ofMillis(500)); final Thread borrower = new Thread(new SimpleTestThread<>(gkoPool, "two")); final String obj = gkoPool.borrowObject("one"); - borrower.start(); // Will block - Thread.sleep(100); // Make sure borrower has started - gkoPool.invalidateObject("one", obj); // Should free capacity to serve the other key - Thread.sleep(20); // Should have been served by now + borrower.start(); // Will block + Thread.sleep(100); // Make sure borrower has started + gkoPool.invalidateObject("one", obj); // Should free capacity to serve the other key + Thread.sleep(20); // Should have been served by now assertFalse(borrower.isAlive()); } @Test - public void testInvalidateMissingKey() throws Exception { + void testInvalidateMissingKey() throws Exception { assertThrows(IllegalStateException.class, () -> gkoPool.invalidateObject("UnknownKey", "Ignored")); } @ParameterizedTest @EnumSource(DestroyMode.class) - public void testInvalidateMissingKeyForDestroyMode(final DestroyMode destroyMode) throws Exception { + void testInvalidateMissingKeyForDestroyMode(final DestroyMode destroyMode) throws Exception { assertThrows(IllegalStateException.class, () -> gkoPool.invalidateObject("UnknownKey", "Ignored", destroyMode)); } @@ -1838,9 +1790,7 @@ public void testInvalidateMissingKeyForDestroyMode(final DestroyMode destroyMode * @throws Exception May occur in some failure modes */ @Test - public void testInvalidateWaiting() - throws Exception { - + void testInvalidateWaiting() throws Exception { final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotal(2); config.setBlockWhenExhausted(true); @@ -1850,9 +1800,9 @@ public void testInvalidateWaiting() config.setTestOnBorrow(true); config.setTestOnReturn(false); config.setTestWhileIdle(true); - config.setTimeBetweenEvictionRuns(Duration.ofMillis(-1)); + config.setDurationBetweenEvictionRuns(Duration.ofMillis(-1)); - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(new ObjectFactory(), config)) { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(new ObjectFactory(), config)) { // Allocate both objects with this thread pool.borrowObject(Integer.valueOf(1)); // object1 @@ -1884,7 +1834,7 @@ public void testInvalidateWaiting() pool.invalidateObject(Integer.valueOf(1), object2); - assertTrue(signal.tryAcquire(2, TimeUnit.SECONDS),"Call to invalidateObject did not unblock pool waiters."); + assertTrue(signal.tryAcquire(2, TimeUnit.SECONDS), "Call to invalidateObject did not unblock pool waiters."); if (result.get() != null) { throw new AssertionError(result.get()); @@ -1897,7 +1847,7 @@ public void testInvalidateWaiting() */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testJmxRegistration() { + void testJmxRegistration() { final ObjectName oname = gkoPool.getJmxName(); final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); final Set result = mbs.queryNames(oname, null); @@ -1906,20 +1856,20 @@ public void testJmxRegistration() { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testLIFO() throws Exception { + void testLIFO() throws Exception { gkoPool.setLifo(true); final String key = "key"; gkoPool.addObject(key); // "key0" gkoPool.addObject(key); // "key1" gkoPool.addObject(key); // "key2" - assertEquals( "key2", gkoPool.borrowObject(key),"Youngest"); - assertEquals( "key1", gkoPool.borrowObject(key),"Middle"); - assertEquals( "key0", gkoPool.borrowObject(key),"Oldest"); + assertEquals("key2", gkoPool.borrowObject(key), "Youngest"); + assertEquals("key1", gkoPool.borrowObject(key), "Middle"); + assertEquals("key0", gkoPool.borrowObject(key), "Oldest"); final String s = gkoPool.borrowObject(key); - assertEquals( "key3", s,"new-3"); + assertEquals("key3", s, "new-3"); gkoPool.returnObject(key, s); - assertEquals( s, gkoPool.borrowObject(key),"returned"); - assertEquals( "key4", gkoPool.borrowObject(key),"new-4"); + assertEquals(s, gkoPool.borrowObject(key), "returned"); + assertEquals("key4", gkoPool.borrowObject(key), "new-4"); } /** @@ -1930,11 +1880,11 @@ public void testLIFO() throws Exception { */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testLivenessPerKey() throws Exception { + void testLivenessPerKey() throws Exception { gkoPool.setMaxIdlePerKey(3); gkoPool.setMaxTotal(3); gkoPool.setMaxTotalPerKey(3); - gkoPool.setMaxWaitMillis(3000); // Really a timeout for the test + gkoPool.setMaxWait(Duration.ofMillis(3000)); // Really a timeout for the test // Check out and briefly hold 3 "1"s final WaitingTestThread t1 = new WaitingTestThread<>(gkoPool, "1", 100); @@ -1957,9 +1907,9 @@ public void testLivenessPerKey() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testMakeObjectException() throws Exception { + void testMakeObjectException() throws Exception { final SimpleFactory factory = new SimpleFactory<>(); - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { pool.setMaxTotalPerKey(1); pool.setBlockWhenExhausted(false); factory.exceptionOnCreate = true; @@ -1974,46 +1924,46 @@ public void testMakeObjectException() throws Exception { */ @Test @Timeout(value = 200000, unit = TimeUnit.MILLISECONDS) - public void testMaxActivePerKeyExceeded() { + void testMaxActivePerKeyExceeded() { final WaiterFactory waiterFactory = new WaiterFactory<>(0, 20, 0, 0, 0, 0, 8, 5, 0); // TODO Fix this. Can't use local pool since runTestThreads uses the // protected pool field - try (final GenericKeyedObjectPool waiterPool = new GenericKeyedObjectPool<>(waiterFactory)) { + try (GenericKeyedObjectPool waiterPool = new GenericKeyedObjectPool<>(waiterFactory)) { waiterPool.setMaxTotalPerKey(5); waiterPool.setMaxTotal(8); waiterPool.setTestOnBorrow(true); waiterPool.setMaxIdlePerKey(5); - waiterPool.setMaxWaitMillis(-1); + waiterPool.setMaxWait(Duration.ofMillis(-1)); runTestThreads(20, 300, 250, waiterPool); } } @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMaxIdle() throws Exception { + void testMaxIdle() throws Exception { gkoPool.setMaxTotalPerKey(100); gkoPool.setMaxIdlePerKey(8); final String[] active = new String[100]; - for(int i=0;i<100;i++) { + for (int i = 0; i < 100; i++) { active[i] = gkoPool.borrowObject(""); } - assertEquals(100,gkoPool.getNumActive("")); - assertEquals(0,gkoPool.getNumIdle("")); - for(int i=0;i<100;i++) { - gkoPool.returnObject("",active[i]); - assertEquals(99 - i,gkoPool.getNumActive("")); - assertEquals(i < 8 ? i+1 : 8,gkoPool.getNumIdle("")); + assertEquals(100, gkoPool.getNumActive("")); + assertEquals(0, gkoPool.getNumIdle("")); + for (int i = 0; i < 100; i++) { + gkoPool.returnObject("", active[i]); + assertEquals(99 - i, gkoPool.getNumActive("")); + assertEquals(i < 8 ? i + 1 : 8, gkoPool.getNumIdle("")); } - for(int i=0;i<100;i++) { + for (int i = 0; i < 100; i++) { active[i] = gkoPool.borrowObject("a"); } - assertEquals(100,gkoPool.getNumActive("a")); - assertEquals(0,gkoPool.getNumIdle("a")); - for(int i=0;i<100;i++) { - gkoPool.returnObject("a",active[i]); - assertEquals(99 - i,gkoPool.getNumActive("a")); - assertEquals(i < 8 ? i+1 : 8,gkoPool.getNumIdle("a")); + assertEquals(100, gkoPool.getNumActive("a")); + assertEquals(0, gkoPool.getNumIdle("a")); + for (int i = 0; i < 100; i++) { + gkoPool.returnObject("a", active[i]); + assertEquals(99 - i, gkoPool.getNumActive("a")); + assertEquals(i < 8 ? i + 1 : 8, gkoPool.getNumIdle("a")); } // total number of idle instances is twice maxIdle @@ -2026,7 +1976,7 @@ public void testMaxIdle() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMaxTotal() throws Exception { + void testMaxTotal() throws Exception { gkoPool.setMaxTotalPerKey(2); gkoPool.setMaxTotal(3); gkoPool.setBlockWhenExhausted(false); @@ -2069,7 +2019,7 @@ public void testMaxTotal() throws Exception { */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMaxTotalInvariant() { + void testMaxTotalInvariant() { final int maxTotal = 15; simpleFactory.setEvenValid(false); // Every other validation fails simpleFactory.setDestroyLatency(100); // Destroy takes 100 ms @@ -2078,13 +2028,13 @@ public void testMaxTotalInvariant() { gkoPool.setMaxTotal(maxTotal); gkoPool.setMaxIdlePerKey(-1); gkoPool.setTestOnReturn(true); - gkoPool.setMaxWaitMillis(10000L); + gkoPool.setMaxWait(Duration.ofSeconds(10)); runTestThreads(5, 10, 50, gkoPool); } @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMaxTotalLRU() throws Exception { + void testMaxTotalLRU() throws Exception { gkoPool.setMaxTotalPerKey(2); gkoPool.setMaxTotal(3); @@ -2135,7 +2085,7 @@ public void testMaxTotalLRU() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMaxTotalPerKey() throws Exception { + void testMaxTotalPerKey() throws Exception { gkoPool.setMaxTotalPerKey(3); gkoPool.setBlockWhenExhausted(false); @@ -2145,17 +2095,15 @@ public void testMaxTotalPerKey() throws Exception { assertThrows(NoSuchElementException.class, () -> gkoPool.borrowObject("")); } - @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMaxTotalPerKeyZero() { + void testMaxTotalPerKeyZero() { gkoPool.setMaxTotalPerKey(0); gkoPool.setBlockWhenExhausted(false); assertThrows(NoSuchElementException.class, () -> gkoPool.borrowObject("a")); } - /** * Verifies that if a borrow of a new key is blocked because maxTotal has * been reached, that borrow continues once another object is returned. @@ -2163,7 +2111,7 @@ public void testMaxTotalPerKeyZero() { * JIRA: POOL-310 */ @Test - public void testMaxTotalWithThreads() throws Exception { + void testMaxTotalWithThreads() throws Exception { gkoPool.setMaxTotalPerKey(2); gkoPool.setMaxTotal(1); @@ -2199,7 +2147,7 @@ public void testMaxTotalWithThreads() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMaxTotalZero() { + void testMaxTotalZero() { gkoPool.setMaxTotal(0); gkoPool.setBlockWhenExhausted(false); @@ -2216,13 +2164,13 @@ public void testMaxTotalZero() { */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMaxWaitMultiThreaded() throws Exception { + void testMaxWaitMultiThreaded() throws Exception { final long maxWait = 500; // wait for connection final long holdTime = 4 * maxWait; // how long to hold connection final int keyCount = 4; // number of different keys final int threadsPerKey = 5; // number of threads to grab the key initially gkoPool.setBlockWhenExhausted(true); - gkoPool.setMaxWaitMillis(maxWait); + gkoPool.setMaxWait(Duration.ofMillis(maxWait)); gkoPool.setMaxTotalPerKey(threadsPerKey); // Create enough threads so half the threads will have to wait final WaitingTestThread[] wtt = new WaitingTestThread[keyCount * threadsPerKey * 2]; @@ -2236,11 +2184,11 @@ public void testMaxWaitMultiThreaded() throws Exception { int failed = 0; for (final WaitingTestThread element : wtt) { element.join(); - if (element.thrown != null){ + if (element.thrown != null) { failed++; } } - if (DISPLAY_THREAD_DETAILS || wtt.length/2 != failed){ + if (DISPLAY_THREAD_DETAILS || wtt.length / 2 != failed) { System.out.println( "MaxWait: " + maxWait + " HoldTime: " + holdTime + @@ -2261,18 +2209,18 @@ public void testMaxWaitMultiThreaded() throws Exception { ); } } - assertEquals(wtt.length/2,failed,"Expected half the threads to fail"); + assertEquals(wtt.length / 2, failed, "Expected half the threads to fail"); } @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMinIdle() throws Exception { + void testMinIdle() throws Exception { gkoPool.setMaxIdlePerKey(500); gkoPool.setMinIdlePerKey(5); gkoPool.setMaxTotalPerKey(10); gkoPool.setNumTestsPerEvictionRun(0); - gkoPool.setMinEvictableIdleTime(Duration.ofMillis(50)); - gkoPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + gkoPool.setMinEvictableIdleDuration(Duration.ofMillis(50)); + gkoPool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); gkoPool.setTestWhileIdle(true); // Generate a random key @@ -2306,20 +2254,19 @@ public void testMinIdle() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMinIdleMaxTotalPerKey() throws Exception { + void testMinIdleMaxTotalPerKey() throws Exception { gkoPool.setMaxIdlePerKey(500); gkoPool.setMinIdlePerKey(5); gkoPool.setMaxTotalPerKey(10); gkoPool.setNumTestsPerEvictionRun(0); - gkoPool.setMinEvictableIdleTime(Duration.ofMillis(50)); - gkoPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + gkoPool.setMinEvictableIdleDuration(Duration.ofMillis(50)); + gkoPool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); gkoPool.setTestWhileIdle(true); final String key = "A"; gkoPool.preparePool(key); - assertEquals(5, gkoPool.getNumIdle(), "Should be 5 idle, found " + - gkoPool.getNumIdle()); + assertEquals(5, gkoPool.getNumIdle(), "Should be 5 idle, found " + gkoPool.getNumIdle()); Waiter.sleepQuietly(150L); assertEquals(5, gkoPool.getNumIdle(), "Should be 5 idle, found " + gkoPool.getNumIdle()); @@ -2329,28 +2276,28 @@ public void testMinIdleMaxTotalPerKey() throws Exception { Waiter.sleepQuietly(150L); assertEquals(5, gkoPool.getNumIdle(), "Should be 5 idle, found " + gkoPool.getNumIdle()); - for(int i=0 ; i<5 ; i++) { + for (int i = 0; i < 5; i++) { active[i] = gkoPool.borrowObject(key); } Waiter.sleepQuietly(150L); assertEquals(5, gkoPool.getNumIdle(), "Should be 5 idle, found " + gkoPool.getNumIdle()); - for(int i=0 ; i<5 ; i++) { + for (int i = 0; i < 5; i++) { gkoPool.returnObject(key, active[i]); } Waiter.sleepQuietly(150L); assertEquals(10, gkoPool.getNumIdle(), "Should be 10 idle, found " + gkoPool.getNumIdle()); - for(int i=0 ; i<10 ; i++) { + for (int i = 0; i < 10; i++) { active[i] = gkoPool.borrowObject(key); } Waiter.sleepQuietly(150L); assertEquals(0, gkoPool.getNumIdle(), "Should be 0 idle, found " + gkoPool.getNumIdle()); - for(int i=0 ; i<10 ; i++) { + for (int i = 0; i < 10; i++) { gkoPool.returnObject(key, active[i]); } @@ -2360,16 +2307,15 @@ public void testMinIdleMaxTotalPerKey() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testMinIdleNoPreparePool() throws Exception { + void testMinIdleNoPreparePool() throws Exception { gkoPool.setMaxIdlePerKey(500); gkoPool.setMinIdlePerKey(5); gkoPool.setMaxTotalPerKey(10); gkoPool.setNumTestsPerEvictionRun(0); - gkoPool.setMinEvictableIdleTime(Duration.ofMillis(50)); - gkoPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + gkoPool.setMinEvictableIdleDuration(Duration.ofMillis(50)); + gkoPool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); gkoPool.setTestWhileIdle(true); - //Generate a random key final String key = "A"; @@ -2390,9 +2336,9 @@ public void testMinIdleNoPreparePool() throws Exception { * JIRA: POOL-285 */ @Test - public void testMultipleReturn() throws Exception { + void testMultipleReturn() throws Exception { final WaiterFactory factory = new WaiterFactory<>(0, 0, 0, 0, 0, 0); - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { pool.setTestOnReturn(true); final Waiter waiter = pool.borrowObject("a"); pool.returnObject("a", waiter); @@ -2416,9 +2362,9 @@ public void testMultipleReturn() throws Exception { * JIRA: POOL-284 */ @Test - public void testMutable() throws Exception { + void testMutable() throws Exception { final HashSetFactory factory = new HashSetFactory(); - try (final GenericKeyedObjectPool, RuntimeException> pool = new GenericKeyedObjectPool<>(factory, + try (GenericKeyedObjectPool, RuntimeException> pool = new GenericKeyedObjectPool<>(factory, new GenericKeyedObjectPoolConfig<>())) { final HashSet s1 = pool.borrowObject("a"); final HashSet s2 = pool.borrowObject("a"); @@ -2431,12 +2377,12 @@ public void testMutable() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testNegativeMaxTotalPerKey() throws Exception { + void testNegativeMaxTotalPerKey() throws Exception { gkoPool.setMaxTotalPerKey(-1); gkoPool.setBlockWhenExhausted(false); final String obj = gkoPool.borrowObject(""); - assertEquals("0",obj); - gkoPool.returnObject("",obj); + assertEquals("0", obj); + gkoPool.returnObject("", obj); } /** @@ -2444,15 +2390,15 @@ public void testNegativeMaxTotalPerKey() throws Exception { */ @Test @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) - public void testNPEOnFactoryNull() { + void testNPEOnFactoryNull() { // @formatter:off final DisconnectingWaiterFactory factory = new DisconnectingWaiterFactory<>( - () -> null, // Override default to always return null from makeObject + Suppliers.nul(), // Override default to always return null from makeObject DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_VALIDATION_ACTION ); // @formatter:on - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { final String key = "one"; pool.setTestOnBorrow(true); pool.setMaxTotal(-1); @@ -2467,66 +2413,65 @@ public void testNPEOnFactoryNull() { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testNumActiveNumIdle2() throws Exception { - assertEquals(0,gkoPool.getNumActive()); - assertEquals(0,gkoPool.getNumIdle()); - assertEquals(0,gkoPool.getNumActive("A")); - assertEquals(0,gkoPool.getNumIdle("A")); - assertEquals(0,gkoPool.getNumActive("B")); - assertEquals(0,gkoPool.getNumIdle("B")); + void testNumActiveNumIdle2() throws Exception { + assertEquals(0, gkoPool.getNumActive()); + assertEquals(0, gkoPool.getNumIdle()); + assertEquals(0, gkoPool.getNumActive("A")); + assertEquals(0, gkoPool.getNumIdle("A")); + assertEquals(0, gkoPool.getNumActive("B")); + assertEquals(0, gkoPool.getNumIdle("B")); final String objA0 = gkoPool.borrowObject("A"); final String objB0 = gkoPool.borrowObject("B"); - assertEquals(2,gkoPool.getNumActive()); - assertEquals(0,gkoPool.getNumIdle()); - assertEquals(1,gkoPool.getNumActive("A")); - assertEquals(0,gkoPool.getNumIdle("A")); - assertEquals(1,gkoPool.getNumActive("B")); - assertEquals(0,gkoPool.getNumIdle("B")); + assertEquals(2, gkoPool.getNumActive()); + assertEquals(0, gkoPool.getNumIdle()); + assertEquals(1, gkoPool.getNumActive("A")); + assertEquals(0, gkoPool.getNumIdle("A")); + assertEquals(1, gkoPool.getNumActive("B")); + assertEquals(0, gkoPool.getNumIdle("B")); final String objA1 = gkoPool.borrowObject("A"); final String objB1 = gkoPool.borrowObject("B"); - assertEquals(4,gkoPool.getNumActive()); - assertEquals(0,gkoPool.getNumIdle()); - assertEquals(2,gkoPool.getNumActive("A")); - assertEquals(0,gkoPool.getNumIdle("A")); - assertEquals(2,gkoPool.getNumActive("B")); - assertEquals(0,gkoPool.getNumIdle("B")); + assertEquals(4, gkoPool.getNumActive()); + assertEquals(0, gkoPool.getNumIdle()); + assertEquals(2, gkoPool.getNumActive("A")); + assertEquals(0, gkoPool.getNumIdle("A")); + assertEquals(2, gkoPool.getNumActive("B")); + assertEquals(0, gkoPool.getNumIdle("B")); - gkoPool.returnObject("A",objA0); - gkoPool.returnObject("B",objB0); + gkoPool.returnObject("A", objA0); + gkoPool.returnObject("B", objB0); - assertEquals(2,gkoPool.getNumActive()); - assertEquals(2,gkoPool.getNumIdle()); - assertEquals(1,gkoPool.getNumActive("A")); - assertEquals(1,gkoPool.getNumIdle("A")); - assertEquals(1,gkoPool.getNumActive("B")); - assertEquals(1,gkoPool.getNumIdle("B")); + assertEquals(2, gkoPool.getNumActive()); + assertEquals(2, gkoPool.getNumIdle()); + assertEquals(1, gkoPool.getNumActive("A")); + assertEquals(1, gkoPool.getNumIdle("A")); + assertEquals(1, gkoPool.getNumActive("B")); + assertEquals(1, gkoPool.getNumIdle("B")); - gkoPool.returnObject("A",objA1); - gkoPool.returnObject("B",objB1); + gkoPool.returnObject("A", objA1); + gkoPool.returnObject("B", objB1); - assertEquals(0,gkoPool.getNumActive()); - assertEquals(4,gkoPool.getNumIdle()); - assertEquals(0,gkoPool.getNumActive("A")); - assertEquals(2,gkoPool.getNumIdle("A")); - assertEquals(0,gkoPool.getNumActive("B")); - assertEquals(2,gkoPool.getNumIdle("B")); + assertEquals(0, gkoPool.getNumActive()); + assertEquals(4, gkoPool.getNumIdle()); + assertEquals(0, gkoPool.getNumActive("A")); + assertEquals(2, gkoPool.getNumIdle("A")); + assertEquals(0, gkoPool.getNumActive("B")); + assertEquals(2, gkoPool.getNumIdle("B")); } @Test - public void testReturnObjectThrowsIllegalStateException() { - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(new SimpleFactory<>())) { + void testReturnObjectThrowsIllegalStateException() { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(new SimpleFactory<>())) { assertThrows(IllegalStateException.class, () -> pool.returnObject("Foo", "Bar")); } } - @Test - public void testReturnObjectWithBlockWhenExhausted() throws Exception { + void testReturnObjectWithBlockWhenExhausted() throws Exception { gkoPool.setBlockWhenExhausted(true); gkoPool.setMaxTotal(1); @@ -2546,7 +2491,7 @@ public void testReturnObjectWithBlockWhenExhausted() throws Exception { } @Test - public void testReturnObjectWithoutBlockWhenExhausted() throws Exception { + void testReturnObjectWithoutBlockWhenExhausted() throws Exception { gkoPool.setBlockWhenExhausted(false); // Test return object with no take waiters @@ -2563,16 +2508,16 @@ public void testReturnObjectWithoutBlockWhenExhausted() throws Exception { * Test creates the scenario described in POOL-287. */ @Test - public void testReturnToHead() throws Exception { + void testReturnToHead() throws Exception { final SimpleFactory factory = new SimpleFactory<>(); factory.setValidateLatency(100); factory.setValid(true); // Validation always succeeds - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { - pool.setMaxWaitMillis(1000); + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { + pool.setMaxWait(Duration.ofMillis(1000)); pool.setTestWhileIdle(true); pool.setMaxTotalPerKey(2); pool.setNumTestsPerEvictionRun(1); - pool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + pool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); // Load pool with two objects pool.addObject("one"); // call this o1 @@ -2594,7 +2539,7 @@ public void testReturnToHead() throws Exception { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testSettersAndGetters() { + void testSettersAndGetters() { { gkoPool.setMaxTotalPerKey(123); assertEquals(123, gkoPool.getMaxTotalPerKey()); @@ -2604,19 +2549,11 @@ public void testSettersAndGetters() { assertEquals(12, gkoPool.getMaxIdlePerKey()); } { - gkoPool.setMaxWaitMillis(1234L); - assertEquals(1234L, gkoPool.getMaxWaitMillis()); + gkoPool.setMaxWait(Duration.ofMillis(1234)); + assertEquals(1234L, gkoPool.getMaxWaitDuration().toMillis()); } { - gkoPool.setMinEvictableIdleTimeMillis(12345L); - assertEquals(12345L, gkoPool.getMinEvictableIdleTimeMillis()); - } - { - gkoPool.setMinEvictableIdleTime(Duration.ofMillis(12345L)); - assertEquals(12345L, gkoPool.getMinEvictableIdleTime().toMillis()); - } - { - gkoPool.setMinEvictableIdleTime(Duration.ofMillis(12345L)); + gkoPool.setMinEvictableIdleDuration(Duration.ofMillis(12345)); assertEquals(12345L, gkoPool.getMinEvictableIdleDuration().toMillis()); } { @@ -2642,16 +2579,8 @@ public void testSettersAndGetters() { assertFalse(gkoPool.getTestWhileIdle()); } { - gkoPool.setTimeBetweenEvictionRunsMillis(11235L); + gkoPool.setDurationBetweenEvictionRuns(Duration.ofMillis(11235)); assertEquals(11235L, gkoPool.getDurationBetweenEvictionRuns().toMillis()); - assertEquals(11235L, gkoPool.getTimeBetweenEvictionRuns().toMillis()); - assertEquals(11235L, gkoPool.getTimeBetweenEvictionRunsMillis()); - } - { - gkoPool.setTimeBetweenEvictionRuns(Duration.ofMillis(11235L)); - assertEquals(11235L, gkoPool.getDurationBetweenEvictionRuns().toMillis()); - assertEquals(11235L, gkoPool.getTimeBetweenEvictionRuns().toMillis()); - assertEquals(11235L, gkoPool.getTimeBetweenEvictionRunsMillis()); } { gkoPool.setBlockWhenExhausted(true); @@ -2663,42 +2592,42 @@ public void testSettersAndGetters() { @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testThreaded1() { + void testThreaded1() { gkoPool.setMaxTotalPerKey(15); gkoPool.setMaxIdlePerKey(15); - gkoPool.setMaxWaitMillis(1000L); + gkoPool.setMaxWait(Duration.ofMillis(1000)); runTestThreads(20, 100, 50, gkoPool); } // Pool-361 @Test - public void testValidateOnCreate() throws Exception { + void testValidateOnCreate() throws Exception { gkoPool.setTestOnCreate(true); simpleFactory.setValidationEnabled(true); gkoPool.addObject("one"); assertEquals(1, simpleFactory.validateCounter); } - @Test -public void testValidateOnCreateFailure() throws Exception { - gkoPool.setTestOnCreate(true); - gkoPool.setTestOnBorrow(false); - gkoPool.setMaxTotal(2); - simpleFactory.setValidationEnabled(true); - simpleFactory.setValid(false); - // Make sure failed validations do not leak capacity - gkoPool.addObject("one"); - gkoPool.addObject("one"); - assertEquals(0, gkoPool.getNumIdle()); - assertEquals(0, gkoPool.getNumActive()); - simpleFactory.setValid(true); - final String obj = gkoPool.borrowObject("one"); - assertNotNull(obj); - gkoPool.addObject("one"); - // Should have one idle, one out now - assertEquals(1, gkoPool.getNumIdle()); - assertEquals(1, gkoPool.getNumActive()); -} + @Test + void testValidateOnCreateFailure() throws Exception { + gkoPool.setTestOnCreate(true); + gkoPool.setTestOnBorrow(false); + gkoPool.setMaxTotal(2); + simpleFactory.setValidationEnabled(true); + simpleFactory.setValid(false); + // Make sure failed validations do not leak capacity + gkoPool.addObject("one"); + gkoPool.addObject("one"); + assertEquals(0, gkoPool.getNumIdle()); + assertEquals(0, gkoPool.getNumActive()); + simpleFactory.setValid(true); + final String obj = gkoPool.borrowObject("one"); + assertNotNull(obj); + gkoPool.addObject("one"); + // Should have one idle, one out now + assertEquals(1, gkoPool.getNumIdle()); + assertEquals(1, gkoPool.getNumActive()); + } /** * Verify that threads waiting on a depleted pool get served when a returning object fails @@ -2709,14 +2638,14 @@ public void testValidateOnCreateFailure() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testValidationFailureOnReturnFreesCapacity() + void testValidationFailureOnReturnFreesCapacity() throws Exception { final SimpleFactory factory = new SimpleFactory<>(); factory.setValid(false); // Validate will always fail factory.setValidationEnabled(true); - try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { + try (GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { pool.setMaxTotalPerKey(2); - pool.setMaxWaitMillis(1500); + pool.setMaxWait(Duration.ofMillis(1500)); pool.setTestOnReturn(true); pool.setTestOnBorrow(false); // Borrow an instance and hold if for 5 seconds @@ -2734,7 +2663,7 @@ public void testValidationFailureOnReturnFreesCapacity() // POOL-276 @Test - public void testValidationOnCreateOnly() throws Exception { + void testValidationOnCreateOnly() throws Exception { simpleFactory.enableValidation = true; gkoPool.setMaxTotal(1); @@ -2767,10 +2696,10 @@ public void run() { */ @Test @Timeout(value = 60_000, unit = TimeUnit.MILLISECONDS) - public void testWhenExhaustedBlockClosePool() throws Exception { + void testWhenExhaustedBlockClosePool() throws Exception { gkoPool.setMaxTotalPerKey(1); gkoPool.setBlockWhenExhausted(true); - gkoPool.setMaxWaitMillis(-1); + gkoPool.setMaxWait(Duration.ofMillis(-1)); final String obj1 = gkoPool.borrowObject("a"); // Make sure an object was obtained @@ -2794,4 +2723,3 @@ public void testWhenExhaustedBlockClosePool() throws Exception { } - diff --git a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java b/src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPool.java similarity index 72% rename from src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java rename to src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPool.java index e0cc113d9..e4bc90df1 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,13 +15,11 @@ * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.lessThanOrEqualTo; 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.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -29,12 +27,14 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.io.Serializable; import java.lang.management.ManagementFactory; import java.lang.ref.WeakReference; import java.nio.charset.UnsupportedCharsetException; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; @@ -51,33 +51,35 @@ import javax.management.MBeanServer; import javax.management.ObjectName; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.ObjectPool; -import org.apache.commons.pool2.PoolUtils; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectFactory; -import org.apache.commons.pool2.SwallowedExceptionListener; -import org.apache.commons.pool2.TestBaseObjectPool; -import org.apache.commons.pool2.TestException; -import org.apache.commons.pool2.VisitTracker; -import org.apache.commons.pool2.VisitTrackerFactory; -import org.apache.commons.pool2.Waiter; -import org.apache.commons.pool2.WaiterFactory; +import org.apache.commons.lang3.ThreadUtils; +import org.apache.commons.lang3.function.Suppliers; +import org.apache.commons.lang3.time.DurationUtils; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.ObjectPool; +import org.apache.commons.pool3.PoolUtils; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; +import org.apache.commons.pool3.SwallowedExceptionListener; +import org.apache.commons.pool3.TestBaseObjectPool; +import org.apache.commons.pool3.TestException; +import org.apache.commons.pool3.VisitTracker; +import org.apache.commons.pool3.VisitTrackerFactory; +import org.apache.commons.pool3.Waiter; +import org.apache.commons.pool3.WaiterFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; /** */ -public class TestGenericObjectPool extends TestBaseObjectPool { +class TestGenericObjectPool extends TestBaseObjectPool { - private class ConcurrentBorrowAndEvictThread extends Thread { + private final class ConcurrentBorrowAndEvictThread extends Thread { private final boolean borrow; - public String obj; + private String obj; - public ConcurrentBorrowAndEvictThread(final boolean borrow) { + private ConcurrentBorrowAndEvictThread(final boolean borrow) { this.borrow = borrow; } @@ -95,7 +97,7 @@ public void run() { } } - private static class CreateErrorFactory extends BasePooledObjectFactory { + private static final class CreateErrorFactory extends BasePooledObjectFactory { private final Semaphore semaphore = new Semaphore(0); @@ -119,7 +121,7 @@ public PooledObject wrap(final String obj) { } } - private static class CreateFailFactory extends BasePooledObjectFactory { + private static final class CreateFailFactory extends BasePooledObjectFactory { private final Semaphore semaphore = new Semaphore(0); @@ -149,17 +151,18 @@ private static final class DummyFactory public Object create() { return null; } + @Override public PooledObject wrap(final Object value) { return new DefaultPooledObject<>(value); } } - private static class EvictionThread extends Thread { + private static final class EvictionThread extends Thread { private final GenericObjectPool pool; - public EvictionThread(final GenericObjectPool pool) { + private EvictionThread(final GenericObjectPool pool) { this.pool = pool; } @@ -174,9 +177,10 @@ public void run() { } /** - * Factory that creates HashSets. Note that this means - * 0) All instances are initially equal (not discernible by equals) - * 1) Instances are mutable and mutation can cause change in identity / hash code. + * Factory that creates HashSets. Note that this means + * 0) All instances are initially equal (not discernible by equals) + * 1) Instances are mutable and mutation can cause change in identity / hash + * code. */ private static final class HashSetFactory extends BasePooledObjectFactory, RuntimeException> { @@ -184,6 +188,7 @@ private static final class HashSetFactory public HashSet create() { return new HashSet<>(); } + @Override public PooledObject> wrap(final HashSet value) { return new DefaultPooledObject<>(value); @@ -197,13 +202,16 @@ static class InvalidateThread implements Runnable { private final String obj; private final ObjectPool pool; private boolean done; - public InvalidateThread(final ObjectPool pool, final String obj) { + + InvalidateThread(final ObjectPool pool, final String obj) { this.obj = obj; this.pool = pool; } + public boolean complete() { return done; } + @Override public void run() { try { @@ -218,13 +226,14 @@ public void run() { } } - private static class InvalidFactory + private static final class InvalidFactory extends BasePooledObjectFactory { @Override public Object create() { return new Object(); } + @Override public boolean validateObject(final PooledObject obj) { Waiter.sleepQuietly(1000); @@ -268,15 +277,15 @@ public static class SimpleFactory implements PooledObjectFactory obj) throws TestException oddTest = oddValid; counter = activationCounter++; } - if (hurl && !(counter%2 == 0 ? evenTest : oddTest)) { + if (hurl && !(counter % 2 == 0 ? evenTest : oddTest)) { throw new TestException(); } } @@ -340,7 +349,7 @@ public PooledObject makeObject() { activeCount++; if (activeCount > maxTotal) { throw new IllegalStateException( - "Too many active instances: " + activeCount); + "Too many active instances: " + activeCount); } waitLatency = makeLatency; } @@ -437,7 +446,7 @@ public boolean validateObject(final PooledObject obj) { throw new RuntimeException("validation failed"); } if (validate) { - return counter%2 == 0 ? evenTest : oddTest; + return counter % 2 == 0 ? evenTest : oddTest; } return true; } @@ -445,7 +454,7 @@ public boolean validateObject(final PooledObject obj) { public static class TestEvictionPolicy implements EvictionPolicy { - private final AtomicInteger callCount = new AtomicInteger(0); + private final AtomicInteger callCount = new AtomicInteger(); @Override public boolean evict(final EvictionConfig config, final PooledObject underTest, @@ -456,63 +465,63 @@ public boolean evict(final EvictionConfig config, final PooledObject underTes static class TestThread implements Runnable { - /** source of random delay times */ - private final java.util.Random random; + /** Source of random delay times */ + private final Random random; - /** pool to borrow from */ + /** Pool to borrow from */ private final ObjectPool pool; - /** number of borrow attempts */ + /** Number of borrow attempts */ private final int iter; - /** delay before each borrow attempt */ + /** Delay before each borrow attempt */ private final int startDelay; - /** time to hold each borrowed object before returning it */ + /** Time to hold each borrowed object before returning it */ private final int holdTime; - /** whether or not start and hold time are randomly generated */ + /** Whether or not start and hold time are randomly generated */ private final boolean randomDelay; - /** object expected to be borrowed (fail otherwise) */ + /** Object expected to be borrowed (fail otherwise) */ private final Object expectedObject; private volatile boolean complete; private volatile boolean failed; private volatile Throwable error; - public TestThread(final ObjectPool pool) { + private TestThread(final ObjectPool pool) { this(pool, 100, 50, true, null); } - public TestThread(final ObjectPool pool, final int iter) { + private TestThread(final ObjectPool pool, final int iter) { this(pool, iter, 50, true, null); } - public TestThread(final ObjectPool pool, final int iter, final int delay) { + private TestThread(final ObjectPool pool, final int iter, final int delay) { this(pool, iter, delay, true, null); } - public TestThread(final ObjectPool pool, final int iter, final int delay, + private TestThread(final ObjectPool pool, final int iter, final int delay, final boolean randomDelay) { this(pool, iter, delay, randomDelay, null); } - public TestThread(final ObjectPool pool, final int iter, final int delay, + private TestThread(final ObjectPool pool, final int iter, final int delay, final boolean randomDelay, final Object obj) { this(pool, iter, delay, delay, randomDelay, obj); } - public TestThread(final ObjectPool pool, final int iter, final int startDelay, - final int holdTime, final boolean randomDelay, final Object obj) { - this.pool = pool; - this.iter = iter; - this.startDelay = startDelay; - this.holdTime = holdTime; - this.randomDelay = randomDelay; - this.random = this.randomDelay ? new Random() : null; - this.expectedObject = obj; - } + private TestThread(final ObjectPool pool, final int iter, final int startDelay, + final int holdTime, final boolean randomDelay, final Object obj) { + this.pool = pool; + this.iter = iter; + this.startDelay = startDelay; + this.holdTime = holdTime; + this.randomDelay = randomDelay; + this.random = this.randomDelay ? new Random() : null; + this.expectedObject = obj; + } public boolean complete() { return complete; @@ -569,12 +578,12 @@ static class WaitingTestThread extends Thread { private Throwable thrown; private long preBorrowMillis; // just before borrow - private long postBorrowMillis; // borrow returned + private long postBorrowMillis; // borrow returned private long postReturnMillis; // after object was returned private long endedMillis; private String objectId; - public WaitingTestThread(final GenericObjectPool pool, final long pause) { + WaitingTestThread(final GenericObjectPool pool, final long pause) { this.pool = pool; this.pause = pause; this.thrown = null; @@ -592,23 +601,21 @@ public void run() { postReturnMillis = System.currentTimeMillis(); } catch (final Throwable e) { thrown = e; - } finally{ + } finally { endedMillis = System.currentTimeMillis(); } } } - private static final boolean DISPLAY_THREAD_DETAILS= - Boolean.getBoolean("TestGenericObjectPool.display.thread.details"); + private static final boolean DISPLAY_THREAD_DETAILS = Boolean.getBoolean("TestGenericObjectPool.display.thread.details"); + // To pass this to a Maven test, use: // mvn test -DargLine="-DTestGenericObjectPool.display.thread.details=true" // @see https://issues.apache.org/jira/browse/SUREFIRE-121 - - protected GenericObjectPool genericObjectPool; + private GenericObjectPool genericObjectPool; private SimpleFactory simpleFactory; - @SuppressWarnings("deprecation") private void assertConfiguration(final GenericObjectPoolConfig expected, final GenericObjectPool actual) { assertEquals(Boolean.valueOf(expected.getTestOnCreate()), Boolean.valueOf(actual.getTestOnCreate()), "testOnCreate"); @@ -622,34 +629,18 @@ private void assertConfiguration(final GenericObjectPoolConfig expected, fina "whenExhaustedAction"); assertEquals(expected.getMaxTotal(), actual.getMaxTotal(), "maxTotal"); assertEquals(expected.getMaxIdle(), actual.getMaxIdle(), "maxIdle"); - assertEquals(expected.getMaxWaitMillis(), actual.getMaxWaitMillis(), "maxWaitDuration"); assertEquals(expected.getMaxWaitDuration(), actual.getMaxWaitDuration(), "maxWaitDuration"); - assertEquals(expected.getMinEvictableIdleTimeMillis(), actual.getMinEvictableIdleTimeMillis(), - "minEvictableIdleTimeMillis"); - assertEquals(expected.getMinEvictableIdleTime(), actual.getMinEvictableIdleTime(), - "minEvictableIdleTime"); assertEquals(expected.getMinEvictableIdleDuration(), actual.getMinEvictableIdleDuration(), "minEvictableIdleDuration"); assertEquals(expected.getNumTestsPerEvictionRun(), actual.getNumTestsPerEvictionRun(), "numTestsPerEvictionRun"); assertEquals(expected.getEvictorShutdownTimeoutDuration(), actual.getEvictorShutdownTimeoutDuration(), "evictorShutdownTimeoutDuration"); - assertEquals(expected.getEvictorShutdownTimeoutMillis(), actual.getEvictorShutdownTimeoutMillis(), - "evictorShutdownTimeoutMillis"); - assertEquals(expected.getEvictorShutdownTimeout(), actual.getEvictorShutdownTimeout(), - "evictorShutdownTimeout"); - assertEquals(expected.getTimeBetweenEvictionRunsMillis(), actual.getTimeBetweenEvictionRunsMillis(), - "timeBetweenEvictionRunsMillis"); - assertEquals(expected.getDurationBetweenEvictionRuns(), actual.getTimeBetweenEvictionRuns(), - "timeBetweenEvictionRuns"); - assertEquals(expected.getTimeBetweenEvictionRuns(), actual.getTimeBetweenEvictionRuns(), - "timeBetweenEvictionRuns"); } private void checkEvict(final boolean lifo) throws Exception { // yea this is hairy but it tests all the code paths in GOP.evict() - genericObjectPool.setSoftMinEvictableIdle(Duration.ofMillis(10)); - genericObjectPool.setSoftMinEvictableIdleTime(Duration.ofMillis(10)); + genericObjectPool.setSoftMinEvictableIdleDuration(Duration.ofMillis(10)); genericObjectPool.setMinIdle(2); genericObjectPool.setTestWhileIdle(true); genericObjectPool.setLifo(lifo); @@ -680,7 +671,7 @@ private void checkEvictionOrder(final boolean lifo) throws Exception { private void checkEvictionOrderPart1(final boolean lifo) throws Exception { genericObjectPool.setNumTestsPerEvictionRun(2); - genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(100)); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(100)); genericObjectPool.setLifo(lifo); for (int i = 0; i < 5; i++) { genericObjectPool.addObject(); @@ -692,13 +683,13 @@ private void checkEvictionOrderPart1(final boolean lifo) throws Exception { assertNotEquals("0", obj, "oldest not evicted"); assertNotEquals("1", obj, "second oldest not evicted"); // 2 should be next out for FIFO, 4 for LIFO - assertEquals(lifo ? "4" : "2" , obj,"Wrong instance returned"); + assertEquals(lifo ? "4" : "2", obj, "Wrong instance returned"); } private void checkEvictionOrderPart2(final boolean lifo) throws Exception { // Two eviction runs in sequence genericObjectPool.setNumTestsPerEvictionRun(2); - genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(100)); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(100)); genericObjectPool.setLifo(lifo); for (int i = 0; i < 5; i++) { genericObjectPool.addObject(); @@ -707,15 +698,16 @@ private void checkEvictionOrderPart2(final boolean lifo) throws Exception { genericObjectPool.evict(); // Should evict "0" and "1" genericObjectPool.evict(); // Should evict "2" and "3" final Object obj = genericObjectPool.borrowObject(); - assertEquals("4", obj,"Wrong instance remaining in pool"); + assertEquals("4", obj, "Wrong instance remaining in pool"); } private void checkEvictorVisiting(final boolean lifo) throws Exception { VisitTracker obj; VisitTrackerFactory trackerFactory = new VisitTrackerFactory<>(); - try (GenericObjectPool,RuntimeException> trackerPool = new GenericObjectPool<>(trackerFactory)) { + try (GenericObjectPool, RuntimeException> trackerPool = new GenericObjectPool<>( + trackerFactory)) { trackerPool.setNumTestsPerEvictionRun(2); - trackerPool.setMinEvictableIdleTime(Duration.ofMillis(-1)); + trackerPool.setMinEvictableIdleDuration(Duration.ofMillis(-1)); trackerPool.setTestWhileIdle(true); trackerPool.setLifo(lifo); trackerPool.setTestOnReturn(false); @@ -735,18 +727,19 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { for (int i = 0; i < 8; i++) { final VisitTracker tracker = trackerPool.borrowObject(); if (tracker.getId() >= 4) { - assertEquals( 0, tracker.getValidateCount(),"Unexpected instance visited " + tracker.getId()); + assertEquals(0, tracker.getValidateCount(), "Unexpected instance visited " + tracker.getId()); } else { - assertEquals( 1, tracker.getValidateCount(), + assertEquals(1, tracker.getValidateCount(), "Instance " + tracker.getId() + " visited wrong number of times."); } } } trackerFactory = new VisitTrackerFactory<>(); - try (GenericObjectPool, RuntimeException> trackerPool = new GenericObjectPool<>(trackerFactory)) { + try (GenericObjectPool, RuntimeException> trackerPool = new GenericObjectPool<>( + trackerFactory)) { trackerPool.setNumTestsPerEvictionRun(3); - trackerPool.setMinEvictableIdleTime(Duration.ofMillis(-1)); + trackerPool.setMinEvictableIdleDuration(Duration.ofMillis(-1)); trackerPool.setTestWhileIdle(true); trackerPool.setLifo(lifo); trackerPool.setTestOnReturn(false); @@ -771,10 +764,10 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { for (int i = 0; i < 8; i++) { final VisitTracker tracker = trackerPool.borrowObject(); if (tracker.getId() != 0) { - assertEquals( 1, tracker.getValidateCount(), + assertEquals(1, tracker.getValidateCount(), "Instance " + tracker.getId() + " visited wrong number of times."); } else { - assertEquals( 2, tracker.getValidateCount(), + assertEquals(2, tracker.getValidateCount(), "Instance " + tracker.getId() + " visited wrong number of times."); } } @@ -787,9 +780,10 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { random.setSeed(System.currentTimeMillis()); for (int i = 0; i < 4; i++) { for (int j = 0; j < 5; j++) { - try (GenericObjectPool, RuntimeException> trackerPool = new GenericObjectPool<>(trackerFactory)) { + try (GenericObjectPool, RuntimeException> trackerPool = new GenericObjectPool<>( + trackerFactory)) { trackerPool.setNumTestsPerEvictionRun(smallPrimes[i]); - trackerPool.setMinEvictableIdleTime(Duration.ofMillis(-1)); + trackerPool.setMinEvictableIdleDuration(Duration.ofMillis(-1)); trackerPool.setTestWhileIdle(true); trackerPool.setLifo(lifo); trackerPool.setTestOnReturn(false); @@ -826,7 +820,7 @@ private void checkEvictorVisiting(final boolean lifo) throws Exception { } private BasePooledObjectFactory createDefaultPooledObjectFactory() { - return new BasePooledObjectFactory() { + return new BasePooledObjectFactory<>() { @Override public String create() { // fake @@ -842,7 +836,7 @@ public PooledObject wrap(final String obj) { } private BasePooledObjectFactory createNullPooledObjectFactory() { - return new BasePooledObjectFactory() { + return new BasePooledObjectFactory<>() { @Override public String create() { // fake @@ -857,11 +851,11 @@ public PooledObject wrap(final String obj) { }; } - private BasePooledObjectFactory createSlowObjectFactory(final long elapsedTimeMillis) { - return new BasePooledObjectFactory() { + private BasePooledObjectFactory createSlowObjectFactory(final Duration sleepDuration) { + return new BasePooledObjectFactory<>() { @Override public String create() throws InterruptedException { - Thread.sleep(elapsedTimeMillis); + ThreadUtils.sleep(sleepDuration); return "created"; } @@ -892,8 +886,8 @@ protected boolean isLifo() { protected ObjectPool makeEmptyPool(final int minCap) { final GenericObjectPool mtPool = new GenericObjectPool<>(new SimpleFactory()); mtPool.setMaxTotal(minCap); - mtPool.setMaxIdle(minCap); - return mtPool; + mtPool.setMaxIdle(minCap); + return mtPool; } @Override @@ -901,10 +895,8 @@ protected ObjectPool makeEmptyPool(final Pooled return new GenericObjectPool<>(fac); } - /** - * Kicks off test threads, each of which will go through - * borrow-return cycles with random delay times <= delay - * in between. + /* + * Kicks off numThreads test threads, each of which will go through iterations borrow-return cycles with random delay times <= delay in between. */ private void runTestThreads(final int numThreads, final int iterations, final int delay, final GenericObjectPool testPool) { final TestThread[] threads = new TestThread[numThreads]; @@ -940,7 +932,8 @@ public void tearDown() throws Exception { simpleFactory = null; final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - final Set result = mbs.queryNames(new ObjectName("org.apache.commoms.pool2:type=GenericObjectPool,*"), null); + final Set result = mbs + .queryNames(new ObjectName("org.apache.commoms.pool3:type=GenericObjectPool,*"), null); // There should be no registered pools at this point final int registeredPoolCount = result.size(); final StringBuilder msg = new StringBuilder("Current pool is: "); @@ -965,52 +958,65 @@ public void tearDown() throws Exception { } /** - * Check that a pool that starts an evictor, but is never closed does not leave EvictionTimer executor running. Confirmation check is in + * Check that a pool that starts an evictor, but is never closed does not leave + * EvictionTimer executor running. Confirmation check is in * {@link #tearDown()}. * - * @throws TestException Custom exception - * @throws InterruptedException if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this - * exception is thrown. + * @throws TestException Custom exception + * @throws InterruptedException if any thread has interrupted the current + * thread. The interrupted status of the + * current thread is cleared when this + * exception is thrown. */ @SuppressWarnings("deprecation") @Test - public void testAbandonedPool() throws TestException, InterruptedException { + void testAbandonedPool() throws TestException, InterruptedException { final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); config.setJmxEnabled(false); - GenericObjectPool abandoned = new GenericObjectPool<>(simpleFactory, config); - abandoned.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); // Starts evictor - assertEquals(abandoned.getRemoveAbandonedTimeout(), abandoned.getRemoveAbandonedTimeoutDuration().getSeconds()); - - // This is ugly, but forces GC to hit the pool - final WeakReference> ref = new WeakReference<>(abandoned); - abandoned = null; - while (ref.get() != null) { + + // Need to create at least 2 pools to test EvictorTimer Reaper for ConcurrentModificationException + // Note: If the test fails, the ConcurrentModificationException isn't visible without modifications to the + // Reaper class. + GenericObjectPool abandoned1 = new GenericObjectPool<>(simpleFactory, config); + abandoned1.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); // Starts evictor + GenericObjectPool abandoned2 = new GenericObjectPool<>(simpleFactory, config); + abandoned2.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); // Starts evictor + + // This is ugly, but forces GC to hit the pools + final WeakReference> ref1 = new WeakReference<>(abandoned1); + abandoned1 = null; + while (ref1.get() != null) { + System.gc(); + Thread.sleep(100); + } + final WeakReference> ref2 = new WeakReference<>(abandoned2); + abandoned2 = null; + while (ref2.get() != null) { System.gc(); Thread.sleep(100); } } - @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testAddObject() throws Exception { - assertEquals( 0, genericObjectPool.getNumIdle(),"should be zero idle"); + void testAddObject() throws Exception { + assertEquals(0, genericObjectPool.getNumIdle(), "should be zero idle"); genericObjectPool.addObject(); - assertEquals( 1, genericObjectPool.getNumIdle(),"should be one idle"); - assertEquals( 0, genericObjectPool.getNumActive(),"should be zero active"); + assertEquals(1, genericObjectPool.getNumIdle(), "should be one idle"); + assertEquals(0, genericObjectPool.getNumActive(), "should be zero active"); final String obj = genericObjectPool.borrowObject(); - assertEquals( 0, genericObjectPool.getNumIdle(),"should be zero idle"); - assertEquals( 1, genericObjectPool.getNumActive(),"should be one active"); + assertEquals(0, genericObjectPool.getNumIdle(), "should be zero idle"); + assertEquals(1, genericObjectPool.getNumActive(), "should be one active"); genericObjectPool.returnObject(obj); - assertEquals( 1, genericObjectPool.getNumIdle(),"should be one idle"); - assertEquals( 0, genericObjectPool.getNumActive(),"should be zero active"); + assertEquals(1, genericObjectPool.getNumIdle(), "should be one idle"); + assertEquals(0, genericObjectPool.getNumActive(), "should be zero active"); } @Test - public void testAppendStats() { + void testAppendStats() { assertFalse(genericObjectPool.getMessageStatistics()); assertEquals("foo", genericObjectPool.appendStats("foo")); - try (final GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory())) { + try (GenericObjectPool pool = new GenericObjectPool<>(new SimpleFactory())) { pool.setMessagesStatistics(true); assertNotEquals("foo", pool.appendStats("foo")); pool.setMessagesStatistics(false); @@ -1024,11 +1030,11 @@ public void testAppendStats() { * aware of this if you see a failure of this test. */ @SuppressWarnings({ - "rawtypes", "unchecked" + "rawtypes", "unchecked" }) @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testBorrowObjectFairness() throws Exception { + void testBorrowObjectFairness() throws Exception { final int numThreads = 40; final int maxTotal = 40; @@ -1049,16 +1055,12 @@ public void testBorrowObjectFairness() throws Exception { // Start and park threads waiting to borrow objects final TestThread[] threads = new TestThread[numThreads]; - for(int i=0;i pool = new GenericObjectPool<>(createSlowObjectFactory(Duration.ofSeconds(60)))) { + pool.setMaxTotal(1); + pool.setMaxWait(Duration.ofMillis(1_000)); // large + pool.setBlockWhenExhausted(false); + // thread1 tries creating a slow object to make pool full. + final WaitingTestThread thread1 = new WaitingTestThread<>(pool, 0); + thread1.start(); + // Wait for thread1's reaching to create(). + Thread.sleep(100); + // The test needs to make sure a wait happens in create(). + final Duration d = DurationUtils.of(() -> assertThrows(NoSuchElementException.class, () -> pool.borrowObject(Duration.ofMillis(1)), + "borrowObject must fail quickly due to timeout parameter")); + final long millis = d.toMillis(); + final long nanos = d.toNanos(); + assertTrue(nanos >= 0, () -> "borrowObject(Duration) argument not respected: " + nanos); + assertTrue(millis >= 0, () -> "borrowObject(Duration) argument not respected: " + millis); // not > 0 to account for spurious waits + assertTrue(millis < 50, () -> "borrowObject(Duration) argument not respected: " + millis); + } + } + + @Test/* maxWaitMillis x2 + padding */ + @Timeout(value = 1200, unit = TimeUnit.MILLISECONDS) + void testBorrowObjectOverrideMaxWaitSmall() throws Exception { + try (GenericObjectPool pool = new GenericObjectPool<>(createSlowObjectFactory(Duration.ofSeconds(60)))) { + pool.setMaxTotal(1); + pool.setMaxWait(Duration.ofMillis(1)); // small + pool.setBlockWhenExhausted(false); + // thread1 tries creating a slow object to make pool full. + final WaitingTestThread thread1 = new WaitingTestThread<>(pool, 0); + thread1.start(); + // Wait for thread1's reaching to create(). + Thread.sleep(100); + // The test needs to make sure a wait happens in create(). + final Duration d = DurationUtils.of(() -> assertThrows(NoSuchElementException.class, () -> pool.borrowObject(Duration.ofMillis(500)), + "borrowObject must fail slowly due to timeout parameter")); + final long millis = d.toMillis(); + final long nanos = d.toNanos(); + assertTrue(nanos >= 0, () -> "borrowObject(Duration) argument not respected: " + nanos); + assertTrue(millis >= 0, () -> "borrowObject(Duration) argument not respected: " + millis); // not > 0 to account for spurious waits + assertTrue(millis < 600, () -> "borrowObject(Duration) argument not respected: " + millis); + assertTrue(millis > 490, () -> "borrowObject(Duration) argument not respected: " + millis); + } + } @Test - public void testBorrowTimings() throws Exception { + void testBorrowTimings() throws Exception { // Borrow final String object = genericObjectPool.borrowObject(); final PooledObject po = genericObjectPool.getPooledObject(object); - // In the initial state, all instants are the creation instant: last borrow, last use, last return. - // In the initial state, the active duration is the time between "now" and the creation time. - // In the initial state, the idle duration is the time between "now" and the last return, which is the creation time. + // In the initial state, all instants are the creation instant: last borrow, + // last use, last return. + // In the initial state, the active duration is the time between "now" and the + // creation time. + // In the initial state, the idle duration is the time between "now" and the + // last return, which is the creation time. // But... this PO might have already been used in other tests in this class. final Instant lastBorrowInstant1 = po.getLastBorrowInstant(); final Instant lastReturnInstant1 = po.getLastReturnInstant(); final Instant lastUsedInstant1 = po.getLastUsedInstant(); - assertThat(po.getCreateInstant(), lessThanOrEqualTo(lastBorrowInstant1)); - assertThat(po.getCreateInstant(), lessThanOrEqualTo(lastReturnInstant1)); - assertThat(po.getCreateInstant(), lessThanOrEqualTo(lastUsedInstant1)); - assertThat(po.getCreateTime(), lessThanOrEqualTo(lastBorrowInstant1.toEpochMilli())); - assertThat(po.getCreateTime(), lessThanOrEqualTo(lastReturnInstant1.toEpochMilli())); - assertThat(po.getCreateTime(), lessThanOrEqualTo(lastUsedInstant1.toEpochMilli())); + assertTrue(po.getCreateInstant().compareTo(lastBorrowInstant1) <= 0); + assertTrue(po.getCreateInstant().compareTo(lastReturnInstant1) <= 0); + assertTrue(po.getCreateInstant().compareTo(lastUsedInstant1) <= 0); - // Sleep MUST be "long enough" to detect that more than 0 milliseconds have elapsed. + // Sleep MUST be "long enough" to detect that more than 0 milliseconds have + // elapsed. // Need an API in Java 8 to get the clock granularity. Thread.sleep(200); assertFalse(po.getActiveDuration().isNegative()); assertFalse(po.getActiveDuration().isZero()); - // We use greaterThanOrEqualTo instead of equal because "now" many be different when each argument is evaluated. - assertThat(1L, lessThanOrEqualTo(2L)); // sanity check - assertThat(Duration.ZERO, lessThanOrEqualTo(Duration.ZERO.plusNanos(1))); // sanity check - assertThat(po.getActiveDuration(), lessThanOrEqualTo(po.getIdleDuration())); - // Deprecated - assertThat(po.getActiveDuration().toMillis(), lessThanOrEqualTo(po.getActiveTimeMillis())); - assertThat(po.getActiveDuration(), lessThanOrEqualTo(po.getActiveTime())); + // We use greaterThanOrEqualTo instead of equal because "now" many be different + // when each argument is evaluated. + assertTrue(Duration.ZERO.compareTo(Duration.ZERO.plusNanos(1)) <= 0); // sanity check + assertTrue(po.getActiveDuration().compareTo(po.getIdleDuration()) <= 0); + assertTrue(po.getActiveDuration().compareTo(po.getActiveDuration()) <= 0); // // TODO How to compare ID with AD since other tests may have touched the PO? - assertThat(po.getActiveDuration(), lessThanOrEqualTo(po.getIdleTime())); - assertThat(po.getActiveDuration().toMillis(), lessThanOrEqualTo(po.getIdleTimeMillis())); + assertTrue(po.getActiveDuration().compareTo(po.getIdleDuration()) <= 0); // - assertThat(po.getCreateInstant(), lessThanOrEqualTo(po.getLastBorrowInstant())); - assertThat(po.getCreateInstant(), lessThanOrEqualTo(po.getLastReturnInstant())); - assertThat(po.getCreateInstant(), lessThanOrEqualTo(po.getLastUsedInstant())); + assertTrue(po.getCreateInstant().compareTo(po.getLastBorrowInstant()) <= 0); + assertTrue(po.getCreateInstant().compareTo(po.getLastReturnInstant()) <= 0); + assertTrue(po.getCreateInstant().compareTo(po.getLastUsedInstant()) <= 0); - assertThat(lastBorrowInstant1, lessThanOrEqualTo(po.getLastBorrowInstant())); - assertThat(lastReturnInstant1, lessThanOrEqualTo(po.getLastReturnInstant())); - assertThat(lastUsedInstant1, lessThanOrEqualTo(po.getLastUsedInstant())); + assertTrue(lastBorrowInstant1.compareTo(po.getLastBorrowInstant()) <= 0); + assertTrue(lastReturnInstant1.compareTo(po.getLastReturnInstant()) <= 0); + assertTrue(lastUsedInstant1.compareTo(po.getLastUsedInstant()) <= 0); genericObjectPool.returnObject(object); assertFalse(po.getActiveDuration().isNegative()); assertFalse(po.getActiveDuration().isZero()); - assertThat(po.getActiveDuration().toMillis(), lessThanOrEqualTo(po.getActiveTimeMillis())); - assertThat(po.getActiveDuration(), lessThanOrEqualTo(po.getActiveTime())); + assertTrue(po.getActiveDuration().compareTo(po.getActiveDuration()) <= 0); - assertThat(lastBorrowInstant1, lessThanOrEqualTo(po.getLastBorrowInstant())); - assertThat(lastReturnInstant1, lessThanOrEqualTo(po.getLastReturnInstant())); - assertThat(lastUsedInstant1, lessThanOrEqualTo(po.getLastUsedInstant())); + assertTrue(lastBorrowInstant1.compareTo(po.getLastBorrowInstant()) <= 0); + assertTrue(lastReturnInstant1.compareTo(po.getLastReturnInstant()) <= 0); + assertTrue(lastUsedInstant1.compareTo(po.getLastUsedInstant()) <= 0); } /** * On first borrow, first object fails validation, second object is OK. * Subsequent borrows are OK. This was POOL-152. + * * @throws Exception */ @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testBrokenFactoryShouldNotBlockPool() throws Exception { + void testBrokenFactoryShouldNotBlockPool() throws Exception { final int maxTotal = 1; simpleFactory.setMaxTotal(maxTotal); @@ -1163,7 +1209,7 @@ public void testBrokenFactoryShouldNotBlockPool() throws Exception { } // Failure expected assertNotNull(ex); - assertTrue(ex instanceof NoSuchElementException); + assertInstanceOf(NoSuchElementException.class, ex); assertNull(obj); // Configure factory to create valid objects so subsequent borrows work @@ -1177,11 +1223,12 @@ public void testBrokenFactoryShouldNotBlockPool() throws Exception { // POOL-259 @Test - public void testClientWaitStats() throws TestException { + void testClientWaitStats() throws TestException { final SimpleFactory factory = new SimpleFactory(); // Give makeObject a little latency factory.setMakeLatency(200); - try (final GenericObjectPool pool = new GenericObjectPool<>(factory, new GenericObjectPoolConfig<>())) { + try (GenericObjectPool pool = new GenericObjectPool<>(factory, + new GenericObjectPoolConfig<>())) { final String s = pool.borrowObject(); // First borrow waits on create, so wait time should be at least 200 ms // Allow 100ms error in clock times @@ -1198,25 +1245,28 @@ public void testClientWaitStats() throws TestException { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testCloseMultiplePools1() { - try (final GenericObjectPool genericObjectPool2 = new GenericObjectPool<>(simpleFactory)) { - genericObjectPool.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION); - genericObjectPool2.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION); + void testCloseMultiplePools1() { + try (GenericObjectPool genericObjectPool2 = new GenericObjectPool<>( + simpleFactory)) { + genericObjectPool.setDurationBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION); + genericObjectPool2.setDurationBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION); } genericObjectPool.close(); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testCloseMultiplePools2() throws Exception { - try (final GenericObjectPool genericObjectPool2 = new GenericObjectPool<>(simpleFactory)) { - // Ensure eviction takes a long time, during which time EvictionTimer.executor's queue is empty + void testCloseMultiplePools2() throws Exception { + try (GenericObjectPool genericObjectPool2 = new GenericObjectPool<>( + simpleFactory)) { + // Ensure eviction takes a long time, during which time EvictionTimer.executor's + // queue is empty simpleFactory.setDestroyLatency(1000L); // Ensure there is an object to evict, so that above latency takes effect - genericObjectPool.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION); - genericObjectPool2.setTimeBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION); - genericObjectPool.setMinEvictableIdleTime(TestConstants.ONE_MILLISECOND_DURATION); - genericObjectPool2.setMinEvictableIdleTime(TestConstants.ONE_MILLISECOND_DURATION); + genericObjectPool.setDurationBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION); + genericObjectPool2.setDurationBetweenEvictionRuns(TestConstants.ONE_MILLISECOND_DURATION); + genericObjectPool.setMinEvictableIdleDuration(TestConstants.ONE_MILLISECOND_DURATION); + genericObjectPool2.setMinEvictableIdleDuration(TestConstants.ONE_MILLISECOND_DURATION); genericObjectPool.addObject(); genericObjectPool2.addObject(); // Close both pools @@ -1224,19 +1274,16 @@ public void testCloseMultiplePools2() throws Exception { genericObjectPool.close(); } - @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testConcurrentBorrowAndEvict() throws Exception { + void testConcurrentBorrowAndEvict() throws Exception { genericObjectPool.setMaxTotal(1); genericObjectPool.addObject(); for (int i = 0; i < 5000; i++) { - final ConcurrentBorrowAndEvictThread one = - new ConcurrentBorrowAndEvictThread(true); - final ConcurrentBorrowAndEvictThread two = - new ConcurrentBorrowAndEvictThread(false); + final ConcurrentBorrowAndEvictThread one = new ConcurrentBorrowAndEvictThread(true); + final ConcurrentBorrowAndEvictThread two = new ConcurrentBorrowAndEvictThread(false); one.start(); two.start(); @@ -1245,11 +1292,12 @@ public void testConcurrentBorrowAndEvict() throws Exception { genericObjectPool.returnObject(one.obj); - /* Uncomment this for a progress indication - if (i % 10 == 0) { - System.out.println(i/10); - } - */ + /* + * Uncomment this for a progress indication + * if (i % 10 == 0) { + * System.out.println(i/10); + * } + */ } } @@ -1260,7 +1308,7 @@ public void testConcurrentBorrowAndEvict() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testConcurrentInvalidate() throws Exception { + void testConcurrentInvalidate() throws Exception { // Get allObjects and idleObjects loaded with some instances final int nObjects = 1000; genericObjectPool.setMaxTotal(nObjects); @@ -1307,7 +1355,7 @@ public void testConcurrentInvalidate() throws Exception { } @Test - public void testConstructorNullFactory() { + void testConstructorNullFactory() { // add dummy assert (won't be invoked because of IAE) to avoid "unused" warning assertThrows(IllegalArgumentException.class, () -> new GenericObjectPool<>(null)); @@ -1315,12 +1363,11 @@ public void testConstructorNullFactory() { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testConstructors() { + void testConstructors() { // Make constructor arguments all different from defaults final int minIdle = 2; final Duration maxWaitDuration = Duration.ofMillis(3); - final long maxWaitMillis = maxWaitDuration.toMillis(); final int maxIdle = 4; final int maxTotal = 5; final Duration minEvictableIdleDuration = Duration.ofMillis(6); @@ -1330,19 +1377,16 @@ public void testConstructors() { final boolean testOnReturn = true; final boolean testWhileIdle = true; final long timeBetweenEvictionRunsMillis = 8; + final Duration durationBetweenEvictionRuns = Duration.ofMillis(timeBetweenEvictionRunsMillis); final boolean blockWhenExhausted = false; final boolean lifo = false; final PooledObjectFactory dummyFactory = new DummyFactory(); try (GenericObjectPool dummyPool = new GenericObjectPool<>(dummyFactory)) { assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_IDLE, dummyPool.getMaxIdle()); - assertEquals(BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS, dummyPool.getMaxWaitMillis()); + assertEquals(BaseObjectPoolConfig.DEFAULT_MAX_WAIT, dummyPool.getMaxWaitDuration()); assertEquals(GenericObjectPoolConfig.DEFAULT_MIN_IDLE, dummyPool.getMinIdle()); assertEquals(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL, dummyPool.getMaxTotal()); - assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS, - dummyPool.getMinEvictableIdleTimeMillis()); - assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME, - dummyPool.getMinEvictableIdleTime()); - assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME, + assertEquals(BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION, dummyPool.getMinEvictableIdleDuration()); assertEquals(BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN, dummyPool.getNumTestsPerEvictionRun()); @@ -1352,12 +1396,8 @@ public void testConstructors() { Boolean.valueOf(dummyPool.getTestOnReturn())); assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE), Boolean.valueOf(dummyPool.getTestWhileIdle())); - assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS, + assertEquals(BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS, dummyPool.getDurationBetweenEvictionRuns()); - assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS, - dummyPool.getTimeBetweenEvictionRunsMillis()); - assertEquals(BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS, - dummyPool.getTimeBetweenEvictionRuns()); assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED), Boolean.valueOf(dummyPool.getBlockWhenExhausted())); assertEquals(Boolean.valueOf(BaseObjectPoolConfig.DEFAULT_LIFO), Boolean.valueOf(dummyPool.getLifo())); @@ -1369,27 +1409,26 @@ public void testConstructors() { config.setMinIdle(minIdle); config.setMaxTotal(maxTotal); config.setMaxWait(maxWaitDuration); - config.setMinEvictableIdleTimeMillis(minEvictableIdleMillis); - assertEquals(minEvictableIdleMillis, config.getMinEvictableIdleTime().toMillis()); + config.setMinEvictableIdleDuration(minEvictableIdleDuration); + assertEquals(minEvictableIdleMillis, config.getMinEvictableIdleDuration().toMillis()); config.setNumTestsPerEvictionRun(numTestsPerEvictionRun); config.setTestOnBorrow(testOnBorrow); config.setTestOnReturn(testOnReturn); config.setTestWhileIdle(testWhileIdle); - config.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); - assertEquals(timeBetweenEvictionRunsMillis, config.getTimeBetweenEvictionRuns().toMillis()); + config.setDurationBetweenEvictionRuns(durationBetweenEvictionRuns); + assertEquals(timeBetweenEvictionRunsMillis, config.getDurationBetweenEvictionRuns().toMillis()); config.setBlockWhenExhausted(blockWhenExhausted); try (GenericObjectPool dummyPool = new GenericObjectPool<>(dummyFactory, config)) { assertEquals(maxIdle, dummyPool.getMaxIdle()); assertEquals(maxWaitDuration, dummyPool.getMaxWaitDuration()); - assertEquals(maxWaitMillis, dummyPool.getMaxWaitMillis()); assertEquals(minIdle, dummyPool.getMinIdle()); assertEquals(maxTotal, dummyPool.getMaxTotal()); - assertEquals(minEvictableIdleMillis, dummyPool.getMinEvictableIdleTimeMillis()); + assertEquals(minEvictableIdleDuration, dummyPool.getMinEvictableIdleDuration()); assertEquals(numTestsPerEvictionRun, dummyPool.getNumTestsPerEvictionRun()); assertEquals(Boolean.valueOf(testOnBorrow), Boolean.valueOf(dummyPool.getTestOnBorrow())); assertEquals(Boolean.valueOf(testOnReturn), Boolean.valueOf(dummyPool.getTestOnReturn())); assertEquals(Boolean.valueOf(testWhileIdle), Boolean.valueOf(dummyPool.getTestWhileIdle())); - assertEquals(timeBetweenEvictionRunsMillis, dummyPool.getTimeBetweenEvictionRunsMillis()); + assertEquals(durationBetweenEvictionRuns, dummyPool.getDurationBetweenEvictionRuns()); assertEquals(Boolean.valueOf(blockWhenExhausted), Boolean.valueOf(dummyPool.getBlockWhenExhausted())); assertEquals(Boolean.valueOf(lifo), Boolean.valueOf(dummyPool.getLifo())); } @@ -1397,8 +1436,8 @@ public void testConstructors() { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testDefaultConfiguration() { - assertConfiguration(new GenericObjectPoolConfig<>(),genericObjectPool); + void testDefaultConfiguration() { + assertConfiguration(new GenericObjectPoolConfig<>(), genericObjectPool); } /** @@ -1408,9 +1447,9 @@ public void testDefaultConfiguration() { * JIRA: POOL-283 */ @Test - public void testEqualsIndiscernible() throws Exception { + void testEqualsIndiscernible() throws Exception { final HashSetFactory factory = new HashSetFactory(); - try (final GenericObjectPool, RuntimeException> pool = new GenericObjectPool<>(factory, + try (GenericObjectPool, RuntimeException> pool = new GenericObjectPool<>(factory, new GenericObjectPoolConfig<>())) { final HashSet s1 = pool.borrowObject(); final HashSet s2 = pool.borrowObject(); @@ -1420,10 +1459,11 @@ public void testEqualsIndiscernible() throws Exception { } @Test - public void testErrorFactoryDoesNotBlockThreads() throws Exception { + void testErrorFactoryDoesNotBlockThreads() throws Exception { final CreateErrorFactory factory = new CreateErrorFactory(); - try (final GenericObjectPool createFailFactoryPool = new GenericObjectPool<>(factory)) { + try (GenericObjectPool createFailFactoryPool = new GenericObjectPool<>( + factory)) { createFailFactoryPool.setMaxTotal(1); @@ -1476,7 +1516,7 @@ public void testErrorFactoryDoesNotBlockThreads() throws Exception { */ @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictAddObjects() throws Exception { + void testEvictAddObjects() throws Exception { simpleFactory.setMakeLatency(300); simpleFactory.setMaxTotal(2); genericObjectPool.setMaxTotal(2); @@ -1487,26 +1527,26 @@ public void testEvictAddObjects() throws Exception { final TestThread borrower = new TestThread<>(genericObjectPool, 1, 150, false); final Thread borrowerThread = new Thread(borrower); // Set evictor to run in 100 ms - will create idle instance - genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); - borrowerThread.start(); // Off to the races + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); + borrowerThread.start(); // Off to the races borrowerThread.join(); assertFalse(borrower.failed()); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictFIFO() throws Exception { + void testEvictFIFO() throws Exception { checkEvict(false); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEviction() throws Exception { + void testEviction() throws Exception { genericObjectPool.setMaxIdle(500); genericObjectPool.setMaxTotal(500); genericObjectPool.setNumTestsPerEvictionRun(100); - genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(250)); - genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(250)); + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); genericObjectPool.setTestWhileIdle(true); final String[] active = new String[500]; @@ -1518,17 +1558,22 @@ public void testEviction() throws Exception { } Waiter.sleepQuietly(1000L); - assertTrue(genericObjectPool.getNumIdle() < 500,"Should be less than 500 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 500, + "Should be less than 500 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertTrue(genericObjectPool.getNumIdle() < 400,"Should be less than 400 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 400, + "Should be less than 400 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertTrue(genericObjectPool.getNumIdle() < 300,"Should be less than 300 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 300, + "Should be less than 300 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertTrue(genericObjectPool.getNumIdle() < 200,"Should be less than 200 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 200, + "Should be less than 200 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertTrue(genericObjectPool.getNumIdle() < 100,"Should be less than 100 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 100, + "Should be less than 100 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertEquals(0,genericObjectPool.getNumIdle(),"Should be zero idle, found " + genericObjectPool.getNumIdle()); + assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle()); for (int i = 0; i < 500; i++) { active[i] = genericObjectPool.borrowObject(); @@ -1538,31 +1583,37 @@ public void testEviction() throws Exception { } Waiter.sleepQuietly(1000L); - assertTrue(genericObjectPool.getNumIdle() < 500,"Should be less than 500 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 500, + "Should be less than 500 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertTrue(genericObjectPool.getNumIdle() < 400,"Should be less than 400 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 400, + "Should be less than 400 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertTrue(genericObjectPool.getNumIdle() < 300,"Should be less than 300 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 300, + "Should be less than 300 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertTrue(genericObjectPool.getNumIdle() < 200,"Should be less than 200 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 200, + "Should be less than 200 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertTrue(genericObjectPool.getNumIdle() < 100,"Should be less than 100 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() < 100, + "Should be less than 100 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(600L); - assertEquals(0,genericObjectPool.getNumIdle(),"Should be zero idle, found " + genericObjectPool.getNumIdle()); + assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle()); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictionInvalid() throws Exception { + void testEvictionInvalid() throws Exception { - try (final GenericObjectPool invalidFactoryPool = new GenericObjectPool<>(new InvalidFactory())) { + try (GenericObjectPool invalidFactoryPool = new GenericObjectPool<>( + new InvalidFactory())) { invalidFactoryPool.setMaxIdle(1); invalidFactoryPool.setMaxTotal(1); invalidFactoryPool.setTestOnBorrow(false); invalidFactoryPool.setTestOnReturn(false); invalidFactoryPool.setTestWhileIdle(true); - invalidFactoryPool.setMinEvictableIdleTime(Duration.ofSeconds(100)); + invalidFactoryPool.setMinEvictableIdleDuration(Duration.ofSeconds(100)); invalidFactoryPool.setNumTestsPerEvictionRun(1); final Object p = invalidFactoryPool.borrowObject(); @@ -1585,8 +1636,8 @@ public void testEvictionInvalid() throws Exception { Thread.sleep(1000); // Should have an empty pool - assertEquals( 0, invalidFactoryPool.getNumIdle(),"Idle count different than expected."); - assertEquals( 0, invalidFactoryPool.getNumActive(),"Total count different than expected."); + assertEquals(0, invalidFactoryPool.getNumIdle(), "Idle count different than expected."); + assertEquals(0, invalidFactoryPool.getNumActive(), "Total count different than expected."); } } @@ -1600,7 +1651,7 @@ public void testEvictionInvalid() throws Exception { */ @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictionOrder() throws Exception { + void testEvictionOrder() throws Exception { checkEvictionOrder(false); tearDown(); setUp(); @@ -1609,27 +1660,31 @@ public void testEvictionOrder() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictionPolicy() throws Exception { + void testEvictionPolicy() throws Exception { genericObjectPool.setMaxIdle(500); genericObjectPool.setMaxTotal(500); genericObjectPool.setNumTestsPerEvictionRun(500); - genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(250)); - genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(500)); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(250)); + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(500)); genericObjectPool.setTestWhileIdle(true); // ClassNotFoundException - assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(Long.toString(System.currentTimeMillis())), + assertThrows(IllegalArgumentException.class, + () -> genericObjectPool.setEvictionPolicyClassName(Long.toString(System.currentTimeMillis())), "setEvictionPolicyClassName must throw an error if the class name is invalid."); // InstantiationException - assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.io.Serializable.class.getName()), + assertThrows(IllegalArgumentException.class, + () -> genericObjectPool.setEvictionPolicyClassName(Serializable.class.getName()), "setEvictionPolicyClassName must throw an error if the class name is invalid."); // IllegalAccessException - assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.util.Collections.class.getName()), + assertThrows(IllegalArgumentException.class, + () -> genericObjectPool.setEvictionPolicyClassName(Collections.class.getName()), "setEvictionPolicyClassName must throw an error if the class name is invalid."); - assertThrows(IllegalArgumentException.class, () -> genericObjectPool.setEvictionPolicyClassName(java.lang.String.class.getName()), + assertThrows(IllegalArgumentException.class, + () -> genericObjectPool.setEvictionPolicyClassName(String.class.getName()), () -> "setEvictionPolicyClassName must throw an error if a class that does not implement EvictionPolicy is specified."); genericObjectPool.setEvictionPolicy(new TestEvictionPolicy<>()); @@ -1659,11 +1714,11 @@ public void testEvictionPolicy() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictionSoftMinIdle() throws Exception { - class TimeTest extends BasePooledObjectFactory { + void testEvictionSoftMinIdle() throws Exception { + final class TimeTest extends BasePooledObjectFactory { private final long createTimeMillis; - public TimeTest() { + TimeTest() { createTimeMillis = System.currentTimeMillis(); } @@ -1682,14 +1737,13 @@ public PooledObject wrap(final TimeTest value) { } } - try (final GenericObjectPool timePool = new GenericObjectPool<>(new TimeTest())) { + try (GenericObjectPool timePool = new GenericObjectPool<>(new TimeTest())) { timePool.setMaxIdle(5); timePool.setMaxTotal(5); timePool.setNumTestsPerEvictionRun(5); - timePool.setMinEvictableIdle(Duration.ofSeconds(3)); - timePool.setMinEvictableIdleTime(Duration.ofSeconds(3)); - timePool.setSoftMinEvictableIdleTime(TestConstants.ONE_SECOND_DURATION); + timePool.setMinEvictableIdleDuration(Duration.ofSeconds(3)); + timePool.setSoftMinEvictableIdleDuration(TestConstants.ONE_SECOND_DURATION); timePool.setMinIdle(2); final TimeTest[] active = new TimeTest[5]; @@ -1706,24 +1760,25 @@ public PooledObject wrap(final TimeTest value) { // Soft evict all but minIdle(2) Thread.sleep(1500L); timePool.evict(); - assertEquals( 2, timePool.getNumIdle(),"Idle count different than expected."); + assertEquals(2, timePool.getNumIdle(), "Idle count different than expected."); // Hard evict the rest. Thread.sleep(2000L); timePool.evict(); - assertEquals( 0, timePool.getNumIdle(),"Idle count different than expected."); + assertEquals(0, timePool.getNumIdle(), "Idle count different than expected."); } } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictionWithNegativeNumTests() throws Exception { - // when numTestsPerEvictionRun is negative, it represents a fraction of the idle objects to test + void testEvictionWithNegativeNumTests() throws Exception { + // when numTestsPerEvictionRun is negative, it represents a fraction of the idle + // objects to test genericObjectPool.setMaxIdle(6); genericObjectPool.setMaxTotal(6); genericObjectPool.setNumTestsPerEvictionRun(-2); - genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50)); - genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(50)); + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); final String[] active = new String[6]; for (int i = 0; i < 6; i++) { @@ -1734,18 +1789,21 @@ public void testEvictionWithNegativeNumTests() throws Exception { } Waiter.sleepQuietly(100L); - assertTrue(genericObjectPool.getNumIdle() <= 6,"Should at most 6 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() <= 6, + "Should at most 6 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(100L); - assertTrue(genericObjectPool.getNumIdle() <= 3,"Should at most 3 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() <= 3, + "Should at most 3 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(100L); - assertTrue(genericObjectPool.getNumIdle() <= 2,"Should be at most 2 idle, found " + genericObjectPool.getNumIdle()); + assertTrue(genericObjectPool.getNumIdle() <= 2, + "Should be at most 2 idle, found " + genericObjectPool.getNumIdle()); Waiter.sleepQuietly(100L); - assertEquals(0,genericObjectPool.getNumIdle(),"Should be zero idle, found " + genericObjectPool.getNumIdle()); + assertEquals(0, genericObjectPool.getNumIdle(), "Should be zero idle, found " + genericObjectPool.getNumIdle()); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictLIFO() throws Exception { + void testEvictLIFO() throws Exception { checkEvict(true); } @@ -1756,14 +1814,14 @@ public void testEvictLIFO() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testEvictorVisiting() throws Exception { + void testEvictorVisiting() throws Exception { checkEvictorVisiting(true); checkEvictorVisiting(false); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testEvictWhileEmpty() throws Exception { + void testEvictWhileEmpty() throws Exception { genericObjectPool.evict(); genericObjectPool.evict(); genericObjectPool.close(); @@ -1771,9 +1829,9 @@ public void testEvictWhileEmpty() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testExceptionInValidationDuringEviction() throws Exception { + void testExceptionInValidationDuringEviction() throws Exception { genericObjectPool.setMaxIdle(1); - genericObjectPool.setMinEvictableIdleTime(Duration.ZERO); + genericObjectPool.setMinEvictableIdleDuration(Duration.ZERO); genericObjectPool.setTestWhileIdle(true); final String active = genericObjectPool.borrowObject(); @@ -1788,7 +1846,7 @@ public void testExceptionInValidationDuringEviction() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testExceptionOnActivateDuringBorrow() throws Exception { + void testExceptionOnActivateDuringBorrow() throws Exception { final String obj1 = genericObjectPool.borrowObject(); final String obj2 = genericObjectPool.borrowObject(); genericObjectPool.returnObject(obj1); @@ -1812,7 +1870,7 @@ public void testExceptionOnActivateDuringBorrow() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testExceptionOnDestroyDuringBorrow() throws Exception { + void testExceptionOnDestroyDuringBorrow() throws Exception { simpleFactory.setThrowExceptionOnDestroy(true); genericObjectPool.setTestOnBorrow(true); genericObjectPool.borrowObject(); @@ -1824,7 +1882,7 @@ public void testExceptionOnDestroyDuringBorrow() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testExceptionOnDestroyDuringReturn() throws Exception { + void testExceptionOnDestroyDuringReturn() throws Exception { simpleFactory.setThrowExceptionOnDestroy(true); genericObjectPool.setTestOnReturn(true); final String obj1 = genericObjectPool.borrowObject(); @@ -1837,18 +1895,19 @@ public void testExceptionOnDestroyDuringReturn() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testExceptionOnPassivateDuringReturn() throws Exception { + void testExceptionOnPassivateDuringReturn() throws Exception { final String obj = genericObjectPool.borrowObject(); simpleFactory.setThrowExceptionOnPassivate(true); genericObjectPool.returnObject(obj); - assertEquals(0,genericObjectPool.getNumIdle()); + assertEquals(0, genericObjectPool.getNumIdle()); } @Test - public void testFailingFactoryDoesNotBlockThreads() throws Exception { + void testFailingFactoryDoesNotBlockThreads() throws Exception { final CreateFailFactory factory = new CreateFailFactory(); - try (final GenericObjectPool createFailFactoryPool = new GenericObjectPool<>(factory)) { + try (GenericObjectPool createFailFactoryPool = new GenericObjectPool<>( + factory)) { createFailFactoryPool.setMaxTotal(1); @@ -1888,84 +1947,87 @@ public void testFailingFactoryDoesNotBlockThreads() throws Exception { assertFalse(thread1.isAlive()); assertFalse(thread2.isAlive()); - assertTrue(thread1.thrown instanceof UnsupportedCharsetException); - assertTrue(thread2.thrown instanceof UnsupportedCharsetException); + assertTrue(thread1.thrown instanceof UnsupportedCharsetException, () -> Objects.toString(thread1.thrown)); + assertTrue(thread2.thrown instanceof UnsupportedCharsetException, () -> Objects.toString(thread2.thrown)); } } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testFIFO() throws Exception { + void testFIFO() throws Exception { genericObjectPool.setLifo(false); genericObjectPool.addObject(); // "0" genericObjectPool.addObject(); // "1" genericObjectPool.addObject(); // "2" - assertEquals( "0", genericObjectPool.borrowObject(),"Oldest"); - assertEquals( "1", genericObjectPool.borrowObject(),"Middle"); - assertEquals( "2", genericObjectPool.borrowObject(),"Youngest"); + assertEquals("0", genericObjectPool.borrowObject(), "Oldest"); + assertEquals("1", genericObjectPool.borrowObject(), "Middle"); + assertEquals("2", genericObjectPool.borrowObject(), "Youngest"); final String o = genericObjectPool.borrowObject(); - assertEquals( "3", o,"new-3"); + assertEquals("3", o, "new-3"); genericObjectPool.returnObject(o); - assertEquals( o, genericObjectPool.borrowObject(),"returned-3"); - assertEquals( "4", genericObjectPool.borrowObject(),"new-4"); + assertEquals(o, genericObjectPool.borrowObject(), "returned-3"); + assertEquals("4", genericObjectPool.borrowObject(), "new-4"); } @Test - public void testGetFactoryType_DefaultPooledObjectFactory() { - try (final GenericObjectPool pool = new GenericObjectPool<>(createDefaultPooledObjectFactory())) { + void testGetFactoryType_DefaultPooledObjectFactory() { + try (GenericObjectPool pool = new GenericObjectPool<>( + createDefaultPooledObjectFactory())) { assertNotNull(pool.getFactoryType()); } } @Test - public void testGetFactoryType_NullPooledObjectFactory() { - try (final GenericObjectPool pool = new GenericObjectPool<>(createNullPooledObjectFactory())) { + void testGetFactoryType_NullPooledObjectFactory() { + try (GenericObjectPool pool = new GenericObjectPool<>( + createNullPooledObjectFactory())) { assertNotNull(pool.getFactoryType()); } } @Test - public void testGetFactoryType_PoolUtilsSynchronizedDefaultPooledFactory() { - try (final GenericObjectPool pool = new GenericObjectPool<>( + void testGetFactoryType_PoolUtilsSynchronizedDefaultPooledFactory() { + try (GenericObjectPool pool = new GenericObjectPool<>( PoolUtils.synchronizedPooledFactory(createDefaultPooledObjectFactory()))) { assertNotNull(pool.getFactoryType()); } } @Test - public void testGetFactoryType_PoolUtilsSynchronizedNullPooledFactory() { - try (final GenericObjectPool pool = new GenericObjectPool<>( + void testGetFactoryType_PoolUtilsSynchronizedNullPooledFactory() { + try (GenericObjectPool pool = new GenericObjectPool<>( PoolUtils.synchronizedPooledFactory(createNullPooledObjectFactory()))) { assertNotNull(pool.getFactoryType()); } } @Test - public void testGetFactoryType_SynchronizedDefaultPooledObjectFactory() { - try (final GenericObjectPool pool = new GenericObjectPool<>( + void testGetFactoryType_SynchronizedDefaultPooledObjectFactory() { + try (GenericObjectPool pool = new GenericObjectPool<>( new TestSynchronizedPooledObjectFactory<>(createDefaultPooledObjectFactory()))) { assertNotNull(pool.getFactoryType()); } } @Test - public void testGetFactoryType_SynchronizedNullPooledObjectFactory() { - try (final GenericObjectPool pool = new GenericObjectPool<>( + void testGetFactoryType_SynchronizedNullPooledObjectFactory() { + try (GenericObjectPool pool = new GenericObjectPool<>( new TestSynchronizedPooledObjectFactory<>(createNullPooledObjectFactory()))) { assertNotNull(pool.getFactoryType()); } } @Test - public void testGetStatsString() { - try (final GenericObjectPool pool = new GenericObjectPool<>( + void testGetStatsString() { + try (GenericObjectPool pool = new GenericObjectPool<>( new TestSynchronizedPooledObjectFactory<>(createNullPooledObjectFactory()))) { assertNotNull(pool.getStatsString()); } } /** - * Verify that threads waiting on a depleted pool get served when a checked out object is + * Verify that threads waiting on a depleted pool get served when a checked out + * object is * invalidated. * * JIRA: POOL-240 @@ -1973,11 +2035,11 @@ public void testGetStatsString() { * @throws Exception May occur in some failure modes */ @Test - public void testInvalidateFreesCapacity() throws Exception { + void testInvalidateFreesCapacity() throws Exception { final SimpleFactory factory = new SimpleFactory(); - try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { + try (GenericObjectPool pool = new GenericObjectPool<>(factory)) { pool.setMaxTotal(2); - pool.setMaxWaitMillis(500); + pool.setMaxWait(Duration.ofMillis(500)); // Borrow an instance and hold if for 5 seconds final WaitingTestThread thread1 = new WaitingTestThread<>(pool, 5000); thread1.start(); @@ -1986,7 +2048,8 @@ public void testInvalidateFreesCapacity() throws Exception { // Launch another thread - will block, but fail in 500 ms final WaitingTestThread thread2 = new WaitingTestThread<>(pool, 100); thread2.start(); - // Invalidate the object borrowed by this thread - should allow thread2 to create + // Invalidate the object borrowed by this thread - should allow thread2 to + // create Thread.sleep(20); pool.invalidateObject(obj); Thread.sleep(600); // Wait for thread2 to timeout @@ -2001,7 +2064,7 @@ public void testInvalidateFreesCapacity() throws Exception { */ @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testJmxRegistration() { + void testJmxRegistration() { final ObjectName oname = genericObjectPool.getJmxName(); final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); final Set result = mbs.queryNames(oname, null); @@ -2010,93 +2073,100 @@ public void testJmxRegistration() { final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); config.setJmxEnabled(false); - try (final GenericObjectPool poolWithoutJmx = new GenericObjectPool<>(simpleFactory, config)) { + try (GenericObjectPool poolWithoutJmx = new GenericObjectPool<>(simpleFactory, + config)) { assertNull(poolWithoutJmx.getJmxName()); config.setJmxEnabled(true); poolWithoutJmx.jmxUnregister(); } config.setJmxNameBase(null); - try (final GenericObjectPool poolWithDefaultJmxNameBase = new GenericObjectPool<>(simpleFactory, config)) { + try (GenericObjectPool poolWithDefaultJmxNameBase = new GenericObjectPool<>( + simpleFactory, config)) { assertNotNull(poolWithDefaultJmxNameBase.getJmxName()); } } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testLIFO() throws Exception { + void testLIFO() throws Exception { final String o; genericObjectPool.setLifo(true); genericObjectPool.addObject(); // "0" genericObjectPool.addObject(); // "1" genericObjectPool.addObject(); // "2" - assertEquals( "2", genericObjectPool.borrowObject(),"Youngest"); - assertEquals( "1", genericObjectPool.borrowObject(),"Middle"); - assertEquals( "0", genericObjectPool.borrowObject(),"Oldest"); + assertEquals("2", genericObjectPool.borrowObject(), "Youngest"); + assertEquals("1", genericObjectPool.borrowObject(), "Middle"); + assertEquals("0", genericObjectPool.borrowObject(), "Oldest"); o = genericObjectPool.borrowObject(); - assertEquals( "3", o,"new-3"); + assertEquals("3", o, "new-3"); genericObjectPool.returnObject(o); - assertEquals( o, genericObjectPool.borrowObject(),"returned-3"); - assertEquals( "4", genericObjectPool.borrowObject(),"new-4"); + assertEquals(o, genericObjectPool.borrowObject(), "returned-3"); + assertEquals("4", genericObjectPool.borrowObject(), "new-4"); } /** * Simplest example of recovery from factory outage. - * A thread gets into parked wait on the deque when there is capacity to create, but - * creates are failing due to factory outage. Verify that the borrower is served + * A thread gets into parked wait on the deque when there is capacity to create, + * but + * creates are failing due to factory outage. Verify that the borrower is served * once the factory is back online. */ @Test - @Disabled @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) - public void testLivenessOnTransientFactoryFailure() throws InterruptedException { + void testLivenessOnTransientFactoryFailure() throws InterruptedException { final DisconnectingWaiterFactory factory = new DisconnectingWaiterFactory<>( - DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_CREATE_ACTION, - DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, - (obj) -> false // all instances fail validation + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_CREATE_ACTION, + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, + obj -> false // all instances fail validation ); - final GenericObjectPool pool = new GenericObjectPool<>(factory); - pool.setMaxWait(Duration.ofMillis(100)); - pool.setTestOnReturn(true); - pool.setMaxTotal(1); - final Waiter w = pool.borrowObject(); - final AtomicBoolean failed = new AtomicBoolean(false); - final Thread t = new Thread(() -> { - try { - pool.borrowObject(); - } catch (final NoSuchElementException e) { - failed.set(true); - } - }); - Thread.sleep(10); - t.start(); - // t is blocked waiting on the deque - Thread.sleep(10); - factory.disconnect(); - pool.returnObject(w); // validation fails, so no return - Thread.sleep(10); - factory.connect(); - // Borrower should be able to be served now - t.join(); - pool.close(); + final AtomicBoolean failed = new AtomicBoolean(); + final ResilientPooledObjectFactory resilientFactory = new ResilientPooledObjectFactory<>( + factory, 10, Duration.ofMillis(20), Duration.ofMinutes(10), Duration.ofMillis(20)); + try (GenericObjectPool pool = new GenericObjectPool<>(resilientFactory)) { + resilientFactory.setPool(pool); + resilientFactory.startMonitor(); + pool.setMaxWait(Duration.ofMillis(100)); + pool.setTestOnReturn(true); + pool.setMaxTotal(1); + final Waiter w = pool.borrowObject(); + final Thread t = new Thread(() -> { + try { + pool.borrowObject(); + } catch (final NoSuchElementException e) { + failed.set(true); + } + }); + Thread.sleep(10); + t.start(); + // t is blocked waiting on the deque + Thread.sleep(10); + factory.disconnect(); + pool.returnObject(w); // validation fails, so no return + Thread.sleep(10); + factory.connect(); + // Borrower should be able to be served now + t.join(); + } if (failed.get()) { fail("Borrower timed out waiting for an instance"); } } - /** * Test the following scenario: - * Thread 1 borrows an instance - * Thread 2 starts to borrow another instance before thread 1 returns its instance - * Thread 1 returns its instance while thread 2 is validating its newly created instance + * Thread 1 borrows an instance + * Thread 2 starts to borrow another instance before thread 1 returns its + * instance + * Thread 1 returns its instance while thread 2 is validating its newly created + * instance * The test verifies that the instance created by Thread 2 is not leaked. * * @throws Exception May occur in some failure modes */ @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testMakeConcurrentWithReturn() throws Exception { + void testMakeConcurrentWithReturn() throws Exception { genericObjectPool.setTestOnBorrow(true); simpleFactory.setValid(true); // Borrow and return an instance, with a short wait @@ -2114,36 +2184,36 @@ public void testMakeConcurrentWithReturn() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testMaxIdle() throws Exception { + void testMaxIdle() throws Exception { genericObjectPool.setMaxTotal(100); genericObjectPool.setMaxIdle(8); final String[] active = new String[100]; - for(int i=0;i<100;i++) { + for (int i = 0; i < 100; i++) { active[i] = genericObjectPool.borrowObject(); } - assertEquals(100,genericObjectPool.getNumActive()); - assertEquals(0,genericObjectPool.getNumIdle()); - for(int i=0;i<100;i++) { + assertEquals(100, genericObjectPool.getNumActive()); + assertEquals(0, genericObjectPool.getNumIdle()); + for (int i = 0; i < 100; i++) { genericObjectPool.returnObject(active[i]); - assertEquals(99 - i,genericObjectPool.getNumActive()); - assertEquals(i < 8 ? i+1 : 8,genericObjectPool.getNumIdle()); + assertEquals(99 - i, genericObjectPool.getNumActive()); + assertEquals(i < 8 ? i + 1 : 8, genericObjectPool.getNumIdle()); } } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testMaxIdleZero() throws Exception { + void testMaxIdleZero() throws Exception { genericObjectPool.setMaxTotal(100); genericObjectPool.setMaxIdle(0); final String[] active = new String[100]; - for(int i=0;i<100;i++) { + for (int i = 0; i < 100; i++) { active[i] = genericObjectPool.borrowObject(); } - assertEquals(100,genericObjectPool.getNumActive()); - assertEquals(0,genericObjectPool.getNumIdle()); - for(int i=0;i<100;i++) { + assertEquals(100, genericObjectPool.getNumActive()); + assertEquals(0, genericObjectPool.getNumIdle()); + for (int i = 0; i < 100; i++) { genericObjectPool.returnObject(active[i]); - assertEquals(99 - i,genericObjectPool.getNumActive()); + assertEquals(99 - i, genericObjectPool.getNumActive()); assertEquals(0, genericObjectPool.getNumIdle()); } } @@ -2154,7 +2224,7 @@ public void testMaxIdleZero() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) @SuppressWarnings("rawtypes") - public void testMaxIdleZeroUnderLoad() { + void testMaxIdleZeroUnderLoad() { // Config final int numThreads = 199; // And main thread makes a round 200. final int numIter = 20; @@ -2164,14 +2234,14 @@ public void testMaxIdleZeroUnderLoad() { simpleFactory.setMaxTotal(maxTotal); genericObjectPool.setMaxTotal(maxTotal); genericObjectPool.setBlockWhenExhausted(true); - genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(-1)); + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(-1)); // this is important to trigger POOL-356 genericObjectPool.setMaxIdle(0); // Start threads to borrow objects final TestThread[] threads = new TestThread[numThreads]; - for(int i=0;i genericObjectPool.borrowObject()); @@ -2325,18 +2395,19 @@ public void testMaxTotalZero() throws Exception { * Test multi-threaded pool access. * Multiple threads, but maxTotal only allows half the threads to succeed. * - * This test was prompted by Continuum build failures in the Commons DBCP test case: + * This test was prompted by Continuum build failures in the Commons DBCP test + * case: * TestPerUserPoolDataSource.testMultipleThreads2() * Let's see if the this fails on Continuum too! */ @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testMaxWaitMultiThreaded() throws Exception { + void testMaxWaitMultiThreaded() throws Exception { final long maxWait = 500; // wait for connection final long holdTime = 2 * maxWait; // how long to hold connection final int threads = 10; // number of threads to grab the object initially genericObjectPool.setBlockWhenExhausted(true); - genericObjectPool.setMaxWaitMillis(maxWait); + genericObjectPool.setMaxWait(Duration.ofMillis(maxWait)); genericObjectPool.setMaxTotal(threads); // Create enough threads so half the threads will have to wait final WaitingTestThread[] wtt = new WaitingTestThread[threads * 2]; @@ -2350,41 +2421,40 @@ public void testMaxWaitMultiThreaded() throws Exception { int failed = 0; for (final WaitingTestThread element : wtt) { element.join(); - if (element.thrown != null){ + if (element.thrown != null) { failed++; } } - if (DISPLAY_THREAD_DETAILS || wtt.length/2 != failed){ + if (DISPLAY_THREAD_DETAILS || wtt.length / 2 != failed) { System.out.println( "MaxWait: " + maxWait + - " HoldTime: " + holdTime + - " MaxTotal: " + threads + - " Threads: " + wtt.length + - " Failed: " + failed - ); + " HoldTime: " + holdTime + + " MaxTotal: " + threads + + " Threads: " + wtt.length + + " Failed: " + failed); for (final WaitingTestThread wt : wtt) { System.out.println( "PreBorrow: " + (wt.preBorrowMillis - originMillis) + - " PostBorrow: " + (wt.postBorrowMillis != 0 ? wt.postBorrowMillis - originMillis : -1) + - " BorrowTime: " + (wt.postBorrowMillis != 0 ? wt.postBorrowMillis - wt.preBorrowMillis : -1) + - " PostReturn: " + (wt.postReturnMillis != 0 ? wt.postReturnMillis - originMillis : -1) + - " Ended: " + (wt.endedMillis - originMillis) + - " ObjId: " + wt.objectId - ); + " PostBorrow: " + (wt.postBorrowMillis != 0 ? wt.postBorrowMillis - originMillis : -1) + + " BorrowTime: " + + (wt.postBorrowMillis != 0 ? wt.postBorrowMillis - wt.preBorrowMillis : -1) + + " PostReturn: " + (wt.postReturnMillis != 0 ? wt.postReturnMillis - originMillis : -1) + + " Ended: " + (wt.endedMillis - originMillis) + + " ObjId: " + wt.objectId); } } - assertEquals(wtt.length / 2, failed,"Expected half the threads to fail"); + assertEquals(wtt.length / 2, failed, "Expected half the threads to fail"); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testMinIdle() throws Exception { + void testMinIdle() throws Exception { genericObjectPool.setMaxIdle(500); genericObjectPool.setMinIdle(5); genericObjectPool.setMaxTotal(10); genericObjectPool.setNumTestsPerEvictionRun(0); - genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50)); - genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(50)); + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); genericObjectPool.setTestWhileIdle(true); Waiter.sleepQuietly(150L); @@ -2413,13 +2483,13 @@ public void testMinIdle() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testMinIdleMaxTotal() throws Exception { + void testMinIdleMaxTotal() throws Exception { genericObjectPool.setMaxIdle(500); genericObjectPool.setMinIdle(5); genericObjectPool.setMaxTotal(10); genericObjectPool.setNumTestsPerEvictionRun(0); - genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(50)); - genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(50)); + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); genericObjectPool.setTestWhileIdle(true); Waiter.sleepQuietly(150L); @@ -2437,7 +2507,7 @@ public void testMinIdleMaxTotal() throws Exception { Waiter.sleepQuietly(150L); assertEquals(5, genericObjectPool.getNumIdle(), "Should be 5 idle, found " + genericObjectPool.getNumIdle()); - for(int i = 0 ; i < 5 ; i++) { + for (int i = 0; i < 5; i++) { genericObjectPool.returnObject(active[i]); } @@ -2460,15 +2530,16 @@ public void testMinIdleMaxTotal() throws Exception { } /** - * Verifies that returning an object twice (without borrow in between) causes ISE + * Verifies that returning an object twice (without borrow in between) causes + * ISE * but does not re-validate or re-passivate the instance. * * JIRA: POOL-285 */ @Test - public void testMultipleReturn() throws Exception { + void testMultipleReturn() throws Exception { final WaiterFactory factory = new WaiterFactory<>(0, 0, 0, 0, 0, 0); - try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { + try (GenericObjectPool pool = new GenericObjectPool<>(factory)) { pool.setTestOnReturn(true); final Waiter waiter = pool.borrowObject(); pool.returnObject(waiter); @@ -2487,8 +2558,9 @@ public void testMultipleReturn() throws Exception { // POOL-248 @Test - public void testMultipleReturnOfSameObject() throws Exception { - try (final GenericObjectPool pool = new GenericObjectPool<>(simpleFactory, new GenericObjectPoolConfig<>())) { + void testMultipleReturnOfSameObject() throws Exception { + try (GenericObjectPool pool = new GenericObjectPool<>(simpleFactory, + new GenericObjectPoolConfig<>())) { assertEquals(0, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); @@ -2518,9 +2590,9 @@ public void testMultipleReturnOfSameObject() throws Exception { * JIRA: POOL-284 */ @Test - public void testMutable() throws Exception { + void testMutable() throws Exception { final HashSetFactory factory = new HashSetFactory(); - try (final GenericObjectPool, RuntimeException> pool = new GenericObjectPool<>(factory, + try (GenericObjectPool, RuntimeException> pool = new GenericObjectPool<>(factory, new GenericObjectPoolConfig<>())) { final HashSet s1 = pool.borrowObject(); final HashSet s2 = pool.borrowObject(); @@ -2533,11 +2605,11 @@ public void testMutable() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testNegativeMaxTotal() throws Exception { + void testNegativeMaxTotal() throws Exception { genericObjectPool.setMaxTotal(-1); genericObjectPool.setBlockWhenExhausted(false); final String obj = genericObjectPool.borrowObject(); - assertEquals(getNthObject(0),obj); + assertEquals(getNthObject(0), obj); genericObjectPool.returnObject(obj); } @@ -2545,18 +2617,18 @@ public void testNegativeMaxTotal() throws Exception { * Verifies that concurrent threads never "share" instances */ @Test - public void testNoInstanceOverlap() { + void testNoInstanceOverlap() { final int maxTotal = 5; final int numThreads = 100; final int delay = 1; final int iterations = 1000; final AtomicIntegerFactory factory = new AtomicIntegerFactory(); - try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { + try (GenericObjectPool pool = new GenericObjectPool<>(factory)) { pool.setMaxTotal(maxTotal); pool.setMaxIdle(maxTotal); pool.setTestOnBorrow(true); pool.setBlockWhenExhausted(true); - pool.setMaxWaitMillis(-1); + pool.setMaxWait(Duration.ofMillis(-1)); runTestThreads(numThreads, iterations, delay, pool); assertEquals(0, pool.getDestroyedByBorrowValidationCount()); } @@ -2567,10 +2639,10 @@ public void testNoInstanceOverlap() { */ @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testNoInvalidateNPE() throws Exception { + void testNoInvalidateNPE() throws Exception { genericObjectPool.setMaxTotal(1); genericObjectPool.setTestOnCreate(true); - genericObjectPool.setMaxWaitMillis(-1); + genericObjectPool.setMaxWait(Duration.ofMillis(-1)); final String obj = genericObjectPool.borrowObject(); // Make validation fail - this will cause create() to return null simpleFactory.setValid(false); @@ -2586,45 +2658,30 @@ public void testNoInvalidateNPE() throws Exception { /** * Verify that when a factory returns a null object, pool methods throw NPE. + * * @throws InterruptedException */ @Test @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) - public void testNPEOnFactoryNull() throws InterruptedException { + void testNPEOnFactoryNull() throws InterruptedException { final DisconnectingWaiterFactory factory = new DisconnectingWaiterFactory<>( - () -> null, // Override default to always return null from makeObject - DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, - DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_VALIDATION_ACTION - ); - final GenericObjectPool pool = new GenericObjectPool<>(factory); - pool.setTestOnBorrow(true); - pool.setMaxTotal(-1); - pool.setMinIdle(1); - // Disconnect the factory - will always return null in this state - factory.disconnect(); - try { - pool.borrowObject(); - fail("Expecting NullPointerException"); - } catch (final NullPointerException ex) { - // expected - } - try { - pool.addObject(); - fail("Expecting NullPointerException"); - } catch (final NullPointerException ex2) { - // expected - } - try { - pool.ensureMinIdle(); - fail("Expecting NullPointerException"); - } catch (final NullPointerException ex3) { - // expected + Suppliers.nul(), // Override default to always return null from makeObject + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_LIFECYCLE_ACTION, + DisconnectingWaiterFactory.DEFAULT_DISCONNECTED_VALIDATION_ACTION); + try (GenericObjectPool pool = new GenericObjectPool<>(factory)) { + pool.setTestOnBorrow(true); + pool.setMaxTotal(-1); + pool.setMinIdle(1); + // Disconnect the factory - will always return null in this state + factory.disconnect(); + assertThrows(NullPointerException.class, pool::borrowObject); + assertThrows(NullPointerException.class, pool::addObject); + assertThrows(NullPointerException.class, pool::ensureMinIdle); } - pool.close(); } @Test - public void testPreparePool() throws Exception { + void testPreparePool() throws Exception { genericObjectPool.setMinIdle(1); genericObjectPool.setMaxTotal(1); genericObjectPool.preparePool(); @@ -2638,27 +2695,42 @@ public void testPreparePool() throws Exception { assertEquals(1, genericObjectPool.getNumIdle()); } - @Test/* maxWaitMillis x2 + padding */ + @Test /* maxWaitMillis x2 + padding */ @Timeout(value = 1200, unit = TimeUnit.MILLISECONDS) - public void testReturnBorrowObjectWithingMaxWaitMillis() throws Exception { - final long maxWaitMillis = 500; - - try (final GenericObjectPool createSlowObjectFactoryPool = new GenericObjectPool<>( - createSlowObjectFactory(60000))) { + void testReturnBorrowObjectWithingMaxWaitDuration() throws Exception { + final Duration maxWaitDuration = Duration.ofMillis(500); + try (GenericObjectPool createSlowObjectFactoryPool = new GenericObjectPool<>( + createSlowObjectFactory(Duration.ofSeconds(60)))) { createSlowObjectFactoryPool.setMaxTotal(1); - createSlowObjectFactoryPool.setMaxWaitMillis(maxWaitMillis); - + createSlowObjectFactoryPool.setMaxWait(maxWaitDuration); // thread1 tries creating a slow object to make pool full. final WaitingTestThread thread1 = new WaitingTestThread<>(createSlowObjectFactoryPool, 0); thread1.start(); - // Wait for thread1's reaching to create(). Thread.sleep(100); + // another one tries borrowObject. It should return within maxWaitMillis. + assertThrows(NoSuchElementException.class, () -> createSlowObjectFactoryPool.borrowObject(maxWaitDuration), + "borrowObject must fail due to timeout by maxWaitMillis"); + assertTrue(thread1.isAlive()); + } + } + @Test /* maxWaitMillis x2 + padding */ + @Timeout(value = 1200, unit = TimeUnit.MILLISECONDS) + void testReturnBorrowObjectWithingMaxWaitMillis() throws Exception { + final long maxWaitMillis = 500; + try (GenericObjectPool createSlowObjectFactoryPool = new GenericObjectPool<>( + createSlowObjectFactory(Duration.ofSeconds(60)))) { + createSlowObjectFactoryPool.setMaxTotal(1); + createSlowObjectFactoryPool.setMaxWait(Duration.ofMillis(maxWaitMillis)); + // thread1 tries creating a slow object to make pool full. + final WaitingTestThread thread1 = new WaitingTestThread<>(createSlowObjectFactoryPool, 0); + thread1.start(); + // Wait for thread1's reaching to create(). + Thread.sleep(100); // another one tries borrowObject. It should return within maxWaitMillis. assertThrows(NoSuchElementException.class, () -> createSlowObjectFactoryPool.borrowObject(maxWaitMillis), "borrowObject must fail due to timeout by maxWaitMillis"); - assertTrue(thread1.isAlive()); } } @@ -2671,9 +2743,9 @@ public void testReturnBorrowObjectWithingMaxWaitMillis() throws Exception { * inserted just before the final call to isLifo() in the returnObject() * method. */ - //@Test + // @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testReturnObject() throws Exception { + void testReturnObject() throws Exception { genericObjectPool.setMaxTotal(1); genericObjectPool.setMaxIdle(-1); @@ -2697,27 +2769,27 @@ public void testReturnObject() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testSetConfig() throws Exception { + void testSetConfig() throws Exception { final GenericObjectPoolConfig expected = new GenericObjectPoolConfig<>(); - assertConfiguration(expected,genericObjectPool); + assertConfiguration(expected, genericObjectPool); expected.setMaxTotal(2); expected.setMaxIdle(3); expected.setMaxWait(Duration.ofMillis(5)); - expected.setMinEvictableIdleTime(Duration.ofMillis(7L)); + expected.setMinEvictableIdleDuration(Duration.ofMillis(7L)); expected.setNumTestsPerEvictionRun(9); expected.setTestOnCreate(true); expected.setTestOnBorrow(true); expected.setTestOnReturn(true); expected.setTestWhileIdle(true); - expected.setTimeBetweenEvictionRuns(Duration.ofMillis(11L)); + expected.setDurationBetweenEvictionRuns(Duration.ofMillis(11L)); expected.setBlockWhenExhausted(false); genericObjectPool.setConfig(expected); - assertConfiguration(expected,genericObjectPool); + assertConfiguration(expected, genericObjectPool); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testSettersAndGetters() throws Exception { + void testSettersAndGetters() throws Exception { { // The object receives an Exception during its creation to prevent // memory leaks. See BaseGenericObjectPool constructor for more details. @@ -2758,25 +2830,23 @@ public void testSettersAndGetters() throws Exception { } { genericObjectPool.setMaxTotal(123); - assertEquals(123,genericObjectPool.getMaxTotal()); + assertEquals(123, genericObjectPool.getMaxTotal()); } { genericObjectPool.setMaxIdle(12); - assertEquals(12,genericObjectPool.getMaxIdle()); + assertEquals(12, genericObjectPool.getMaxIdle()); } { - genericObjectPool.setMaxWaitMillis(1234L); - assertEquals(1234L,genericObjectPool.getMaxWaitMillis()); + genericObjectPool.setMaxWait(Duration.ofMillis(1234)); + assertEquals(1234L, genericObjectPool.getMaxWaitDuration().toMillis()); } { - genericObjectPool.setMinEvictableIdleTimeMillis(12345L); - assertEquals(12345L,genericObjectPool.getMinEvictableIdleDuration().toMillis()); - assertEquals(12345L,genericObjectPool.getMinEvictableIdleTimeMillis()); - assertEquals(12345L,genericObjectPool.getMinEvictableIdleTime().toMillis()); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(12345)); + assertEquals(12345L, genericObjectPool.getMinEvictableIdleDuration().toMillis()); } { genericObjectPool.setNumTestsPerEvictionRun(11); - assertEquals(11,genericObjectPool.getNumTestsPerEvictionRun()); + assertEquals(11, genericObjectPool.getNumTestsPerEvictionRun()); } { genericObjectPool.setTestOnBorrow(true); @@ -2797,16 +2867,12 @@ public void testSettersAndGetters() throws Exception { assertFalse(genericObjectPool.getTestWhileIdle()); } { - genericObjectPool.setTimeBetweenEvictionRunsMillis(11235L); - assertEquals(11235L,genericObjectPool.getDurationBetweenEvictionRuns().toMillis()); - assertEquals(11235L,genericObjectPool.getTimeBetweenEvictionRunsMillis()); - assertEquals(11235L,genericObjectPool.getTimeBetweenEvictionRuns().toMillis()); + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(11235)); + assertEquals(11235L, genericObjectPool.getDurationBetweenEvictionRuns().toMillis()); } { - genericObjectPool.setSoftMinEvictableIdleTimeMillis(12135L); - assertEquals(12135L,genericObjectPool.getSoftMinEvictableIdleDuration().toMillis()); - assertEquals(12135L,genericObjectPool.getSoftMinEvictableIdleTimeMillis()); - assertEquals(12135L,genericObjectPool.getSoftMinEvictableIdleTime().toMillis()); + genericObjectPool.setSoftMinEvictableIdleDuration(Duration.ofMillis(12135)); + assertEquals(12135L, genericObjectPool.getSoftMinEvictableIdleDuration().toMillis()); } { genericObjectPool.setBlockWhenExhausted(true); @@ -2818,12 +2884,12 @@ public void testSettersAndGetters() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testStartAndStopEvictor() throws Exception { + void testStartAndStopEvictor() throws Exception { // set up pool without evictor genericObjectPool.setMaxIdle(6); genericObjectPool.setMaxTotal(6); genericObjectPool.setNumTestsPerEvictionRun(6); - genericObjectPool.setMinEvictableIdleTime(Duration.ofMillis(100)); + genericObjectPool.setMinEvictableIdleDuration(Duration.ofMillis(100)); for (int j = 0; j < 2; j++) { // populate the pool @@ -2838,16 +2904,16 @@ public void testStartAndStopEvictor() throws Exception { } // note that it stays populated - assertEquals(6,genericObjectPool.getNumIdle(),"Should have 6 idle"); + assertEquals(6, genericObjectPool.getNumIdle(), "Should have 6 idle"); // start the evictor - genericObjectPool.setTimeBetweenEvictionRuns(Duration.ofMillis(50)); + genericObjectPool.setDurationBetweenEvictionRuns(Duration.ofMillis(50)); // wait a second (well, .2 seconds) Waiter.sleepQuietly(200L); // assert that the evictor has cleared out the pool - assertEquals(0,genericObjectPool.getNumIdle(),"Should have 0 idle"); + assertEquals(0, genericObjectPool.getNumIdle(), "Should have 0 idle"); // stop the evictor genericObjectPool.startEvictor(Duration.ZERO); @@ -2855,7 +2921,7 @@ public void testStartAndStopEvictor() throws Exception { } @Test - public void testSwallowedExceptionListener() { + void testSwallowedExceptionListener() { genericObjectPool.setSwallowedExceptionListener(null); // must simply return final List swallowedExceptions = new ArrayList<>(); /* @@ -2882,18 +2948,18 @@ public void testSwallowedExceptionListener() { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testThreaded1() throws Exception { + void testThreaded1() throws Exception { genericObjectPool.setMaxTotal(15); genericObjectPool.setMaxIdle(15); - genericObjectPool.setMaxWaitMillis(1000L); + genericObjectPool.setMaxWait(Duration.ofMillis(1000)); runTestThreads(20, 100, 50, genericObjectPool); } @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testTimeoutNoLeak() throws Exception { + void testTimeoutNoLeak() throws Exception { genericObjectPool.setMaxTotal(2); - genericObjectPool.setMaxWaitMillis(10); + genericObjectPool.setMaxWait(Duration.ofMillis(10)); genericObjectPool.setBlockWhenExhausted(true); final String obj = genericObjectPool.borrowObject(); final String obj2 = genericObjectPool.borrowObject(); @@ -2909,7 +2975,7 @@ public void testTimeoutNoLeak() throws Exception { * Tests POOL-361 */ @Test - public void testValidateOnCreate() throws Exception { + void testValidateOnCreate() throws Exception { genericObjectPool.setTestOnCreate(true); genericObjectPool.addObject(); assertEquals(1, simpleFactory.validateCounter); @@ -2919,7 +2985,7 @@ public void testValidateOnCreate() throws Exception { * Tests POOL-361 */ @Test - public void testValidateOnCreateFailure() throws Exception { + void testValidateOnCreateFailure() throws Exception { genericObjectPool.setTestOnCreate(true); genericObjectPool.setTestOnBorrow(false); genericObjectPool.setMaxTotal(2); @@ -2936,10 +3002,11 @@ public void testValidateOnCreateFailure() throws Exception { // Should have one idle, one out now assertEquals(1, genericObjectPool.getNumIdle()); assertEquals(1, genericObjectPool.getNumActive()); - } + } /** - * Verify that threads waiting on a depleted pool get served when a returning object fails + * Verify that threads waiting on a depleted pool get served when a returning + * object fails * validation. * * JIRA: POOL-240 @@ -2947,13 +3014,13 @@ public void testValidateOnCreateFailure() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testValidationFailureOnReturnFreesCapacity() throws Exception { + void testValidationFailureOnReturnFreesCapacity() throws Exception { final SimpleFactory factory = new SimpleFactory(); factory.setValid(false); // Validate will always fail factory.setValidationEnabled(true); - try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { + try (GenericObjectPool pool = new GenericObjectPool<>(factory)) { pool.setMaxTotal(2); - pool.setMaxWaitMillis(1500); + pool.setMaxWait(Duration.ofMillis(1500)); pool.setTestOnReturn(true); pool.setTestOnBorrow(false); // Borrow an instance and hold if for 5 seconds @@ -2971,7 +3038,7 @@ public void testValidationFailureOnReturnFreesCapacity() throws Exception { // POOL-276 @Test - public void testValidationOnCreateOnly() throws Exception { + void testValidationOnCreateOnly() throws Exception { genericObjectPool.setMaxTotal(1); genericObjectPool.setTestOnCreate(true); genericObjectPool.setTestOnBorrow(false); @@ -2997,10 +3064,10 @@ public void run() { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testWhenExhaustedBlock() throws Exception { + void testWhenExhaustedBlock() throws Exception { genericObjectPool.setMaxTotal(1); genericObjectPool.setBlockWhenExhausted(true); - genericObjectPool.setMaxWaitMillis(10L); + genericObjectPool.setMaxWait(Duration.ofMillis(10)); final String obj1 = genericObjectPool.borrowObject(); assertNotNull(obj1); assertThrows(NoSuchElementException.class, () -> genericObjectPool.borrowObject()); @@ -3015,10 +3082,10 @@ public void testWhenExhaustedBlock() throws Exception { */ @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testWhenExhaustedBlockClosePool() throws Exception { + void testWhenExhaustedBlockClosePool() throws Exception { genericObjectPool.setMaxTotal(1); genericObjectPool.setBlockWhenExhausted(true); - genericObjectPool.setMaxWaitMillis(-1); + genericObjectPool.setMaxWait(Duration.ofMillis(-1)); final Object obj1 = genericObjectPool.borrowObject(); // Make sure an object was obtained @@ -3042,10 +3109,10 @@ public void testWhenExhaustedBlockClosePool() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testWhenExhaustedBlockInterrupt() throws Exception { + void testWhenExhaustedBlockInterrupt() throws Exception { genericObjectPool.setMaxTotal(1); genericObjectPool.setBlockWhenExhausted(true); - genericObjectPool.setMaxWaitMillis(-1); + genericObjectPool.setMaxWait(Duration.ofMillis(-1)); final String obj1 = genericObjectPool.borrowObject(); // Make sure on object was obtained @@ -3068,7 +3135,7 @@ public void testWhenExhaustedBlockInterrupt() throws Exception { genericObjectPool.returnObject(obj1); // Bug POOL-162 - check there is now an object in the pool - genericObjectPool.setMaxWaitMillis(10L); + genericObjectPool.setMaxWait(Duration.ofMillis(10)); String obj2 = null; try { obj2 = genericObjectPool.borrowObject(); @@ -3084,7 +3151,7 @@ public void testWhenExhaustedBlockInterrupt() throws Exception { @Test @Timeout(value = 60000, unit = TimeUnit.MILLISECONDS) - public void testWhenExhaustedFail() throws Exception { + void testWhenExhaustedFail() throws Exception { genericObjectPool.setMaxTotal(1); genericObjectPool.setBlockWhenExhausted(false); final String obj1 = genericObjectPool.borrowObject(); diff --git a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolClassLoaders.java b/src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPoolClassLoaders.java similarity index 77% rename from src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolClassLoaders.java rename to src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPoolClassLoaders.java index 8298255a5..da219a3a4 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolClassLoaders.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPoolClassLoaders.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -22,13 +22,13 @@ import java.net.URLClassLoader; import java.time.Duration; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; import org.junit.jupiter.api.Test; -public class TestGenericObjectPoolClassLoaders { +class TestGenericObjectPoolClassLoaders { - private static class CustomClassLoader extends URLClassLoader { + private static final class CustomClassLoader extends URLClassLoader { private final int n; CustomClassLoader(final int n) { @@ -46,7 +46,7 @@ public URL findResource(final String name) { } } - private static class CustomClassLoaderObjectFactory extends + private static final class CustomClassLoaderObjectFactory extends BasePooledObjectFactory { private final int n; @@ -71,19 +71,19 @@ public PooledObject wrap(final URL value) { } private static final URL BASE_URL = TestGenericObjectPoolClassLoaders.class - .getResource("/org/apache/commons/pool2/impl/"); + .getResource("/org/apache/commons/pool3/impl/"); @Test - public void testContextClassLoader() throws Exception { + void testContextClassLoader() throws Exception { final ClassLoader savedClassloader = Thread.currentThread().getContextClassLoader(); - try (final CustomClassLoader cl1 = new CustomClassLoader(1)) { + try (CustomClassLoader cl1 = new CustomClassLoader(1)) { Thread.currentThread().setContextClassLoader(cl1); final CustomClassLoaderObjectFactory factory1 = new CustomClassLoaderObjectFactory(1); - try (final GenericObjectPool pool1 = new GenericObjectPool<>(factory1)) { + try (GenericObjectPool pool1 = new GenericObjectPool<>(factory1)) { pool1.setMinIdle(1); - pool1.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + pool1.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); int counter = 0; while (counter < 50 && pool1.getNumIdle() != 1) { Thread.sleep(100); @@ -91,17 +91,17 @@ public void testContextClassLoader() throws Exception { } assertEquals(1, pool1.getNumIdle(), "Wrong number of idle objects in pool1"); - try (final CustomClassLoader cl2 = new CustomClassLoader(2)) { + try (CustomClassLoader cl2 = new CustomClassLoader(2)) { Thread.currentThread().setContextClassLoader(cl2); final CustomClassLoaderObjectFactory factory2 = new CustomClassLoaderObjectFactory(2); - try (final GenericObjectPool pool2 = new GenericObjectPool<>(factory2)) { + try (GenericObjectPool pool2 = new GenericObjectPool<>(factory2)) { pool2.setMinIdle(1); pool2.addObject(); assertEquals(1, pool2.getNumIdle(), "Wrong number of idle objects in pool2"); pool2.clear(); - pool2.setTimeBetweenEvictionRuns(Duration.ofMillis(100)); + pool2.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); counter = 0; while (counter < 50 && pool2.getNumIdle() != 1) { diff --git a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolFactoryCreateFailure.java b/src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPoolFactoryCreateFailure.java similarity index 86% rename from src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolFactoryCreateFailure.java rename to src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPoolFactoryCreateFailure.java index e0e4c94c5..0aaf9a9d8 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPoolFactoryCreateFailure.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestGenericObjectPoolFactoryCreateFailure.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -24,18 +24,18 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.Waiter; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.Waiter; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; /** * Tests POOL-340. */ -public class TestGenericObjectPoolFactoryCreateFailure { +class TestGenericObjectPoolFactoryCreateFailure { - private static class SingleObjectFactory extends BasePooledObjectFactory { + private static final class SingleObjectFactory extends BasePooledObjectFactory { private final AtomicBoolean created = new AtomicBoolean(); @Override @@ -57,7 +57,7 @@ public PooledObject wrap(final Object obj) { } } - private static class WinnerRunnable implements Runnable { + private static final class WinnerRunnable implements Runnable { private final CountDownLatch barrier; private final AtomicBoolean failed; private final GenericObjectPool pool; @@ -98,7 +98,7 @@ private static void println(final String msg) { @Test @Timeout(value = 10_000, unit = TimeUnit.MILLISECONDS) - public void testBorrowObjectStuck() { + void testBorrowObjectStuck() { final SingleObjectFactory factory = new SingleObjectFactory(); final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); config.setMaxIdle(1); @@ -108,9 +108,9 @@ public void testBorrowObjectStuck() { config.setTestOnBorrow(true); config.setTestOnReturn(true); config.setTestWhileIdle(false); - config.setTimeBetweenEvictionRuns(NEG_ONE_DURATION); - config.setMinEvictableIdleTime(NEG_ONE_DURATION); - config.setSoftMinEvictableIdleTime(NEG_ONE_DURATION); + config.setDurationBetweenEvictionRuns(NEG_ONE_DURATION); + config.setMinEvictableIdleDuration(NEG_ONE_DURATION); + config.setSoftMinEvictableIdleDuration(NEG_ONE_DURATION); config.setMaxWait(NEG_ONE_DURATION); try (GenericObjectPool pool = new GenericObjectPool<>(factory, config)) { @@ -140,4 +140,4 @@ public void testBorrowObjectStuck() { } } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool2/impl/TestLinkedBlockingDeque.java b/src/test/java/org/apache/commons/pool3/impl/TestLinkedBlockingDeque.java similarity index 86% rename from src/test/java/org/apache/commons/pool2/impl/TestLinkedBlockingDeque.java rename to src/test/java/org/apache/commons/pool3/impl/TestLinkedBlockingDeque.java index c8ea68fc7..c2bef8de6 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestLinkedBlockingDeque.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestLinkedBlockingDeque.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -37,7 +37,7 @@ /** * Tests for {@link LinkedBlockingDeque}. */ -public class TestLinkedBlockingDeque { +class TestLinkedBlockingDeque { private static final Duration TIMEOUT_50_MILLIS = Duration.ofMillis(50); private static final Integer ONE = Integer.valueOf(1); @@ -52,7 +52,7 @@ public void setUp() { } @Test - public void testAdd() { + void testAdd() { assertTrue(deque.add(ONE)); assertTrue(deque.add(TWO)); assertThrows(IllegalStateException.class, () -> deque.add(THREE)); @@ -60,7 +60,7 @@ public void testAdd() { } @Test - public void testAddFirst() { + void testAddFirst() { deque.addFirst(ONE); deque.addFirst(TWO); assertEquals(2, deque.size()); @@ -69,7 +69,7 @@ public void testAddFirst() { } @Test - public void testAddLast() { + void testAddLast() { deque.addLast(ONE); deque.addLast(TWO); assertEquals(2, deque.size()); @@ -78,7 +78,7 @@ public void testAddLast() { } @Test - public void testClear() { + void testClear() { deque.add(ONE); deque.add(TWO); deque.clear(); @@ -87,7 +87,7 @@ public void testClear() { } @Test - public void testConstructors() { + void testConstructors() { LinkedBlockingDeque deque = new LinkedBlockingDeque<>(); assertEquals(Integer.MAX_VALUE, deque.remainingCapacity()); @@ -101,7 +101,7 @@ public void testConstructors() { } @Test - public void testContains() { + void testContains() { deque.add(ONE); assertTrue(deque.contains(ONE)); assertFalse(deque.contains(TWO)); @@ -112,7 +112,7 @@ public void testContains() { } @Test - public void testDescendingIterator() { + void testDescendingIterator() { assertThrows(NoSuchElementException.class, () -> deque.descendingIterator().next()); deque.add(ONE); deque.add(TWO); @@ -123,7 +123,7 @@ public void testDescendingIterator() { } @Test - public void testDrainTo() { + void testDrainTo() { Collection c = new ArrayList<>(); deque.add(ONE); deque.add(TWO); @@ -140,7 +140,7 @@ public void testDrainTo() { } @Test - public void testElement() { + void testElement() { assertThrows(NoSuchElementException.class, () -> deque.element()); deque.add(ONE); deque.add(TWO); @@ -148,7 +148,7 @@ public void testElement() { } @Test - public void testGetFirst() { + void testGetFirst() { assertThrows(NoSuchElementException.class, () -> deque.getFirst()); deque.add(ONE); deque.add(TWO); @@ -156,7 +156,7 @@ public void testGetFirst() { } @Test - public void testGetLast() { + void testGetLast() { assertThrows(NoSuchElementException.class, () -> deque.getLast()); deque.add(ONE); deque.add(TWO); @@ -164,7 +164,7 @@ public void testGetLast() { } @Test - public void testIterator() { + void testIterator() { assertThrows(NoSuchElementException.class, () -> deque.iterator().next()); deque.add(ONE); deque.add(TWO); @@ -175,7 +175,7 @@ public void testIterator() { } @Test - public void testOffer() { + void testOffer() { assertTrue(deque.offer(ONE)); assertTrue(deque.offer(TWO)); assertFalse(deque.offer(THREE)); @@ -183,7 +183,7 @@ public void testOffer() { } @Test - public void testOfferFirst() { + void testOfferFirst() { deque.offerFirst(ONE); deque.offerFirst(TWO); assertEquals(2, deque.size()); @@ -192,7 +192,7 @@ public void testOfferFirst() { } @Test - public void testOfferFirstWithTimeout() throws InterruptedException { + void testOfferFirstWithTimeout() throws InterruptedException { assertThrows(NullPointerException.class, () -> deque.offerFirst(null, TIMEOUT_50_MILLIS)); assertTrue(deque.offerFirst(ONE, TIMEOUT_50_MILLIS)); assertTrue(deque.offerFirst(TWO, TIMEOUT_50_MILLIS)); @@ -200,7 +200,7 @@ public void testOfferFirstWithTimeout() throws InterruptedException { } @Test - public void testOfferLast() { + void testOfferLast() { deque.offerLast(ONE); deque.offerLast(TWO); assertEquals(2, deque.size()); @@ -209,7 +209,7 @@ public void testOfferLast() { } @Test - public void testOfferLastWithTimeout() throws InterruptedException { + void testOfferLastWithTimeout() throws InterruptedException { assertThrows(NullPointerException.class, () -> deque.offerLast(null, TIMEOUT_50_MILLIS)); assertTrue(deque.offerLast(ONE, TIMEOUT_50_MILLIS)); assertTrue(deque.offerLast(TWO, TIMEOUT_50_MILLIS)); @@ -217,7 +217,7 @@ public void testOfferLastWithTimeout() throws InterruptedException { } @Test - public void testOfferWithTimeout() throws InterruptedException { + void testOfferWithTimeout() throws InterruptedException { assertTrue(deque.offer(ONE, TIMEOUT_50_MILLIS)); assertTrue(deque.offer(TWO, TIMEOUT_50_MILLIS)); assertFalse(deque.offer(THREE, TIMEOUT_50_MILLIS)); @@ -225,7 +225,7 @@ public void testOfferWithTimeout() throws InterruptedException { } @Test - public void testPeek() { + void testPeek() { assertNull(deque.peek()); deque.add(ONE); deque.add(TWO); @@ -233,7 +233,7 @@ public void testPeek() { } @Test - public void testPeekFirst() { + void testPeekFirst() { assertNull(deque.peekFirst()); deque.add(ONE); deque.add(TWO); @@ -241,7 +241,7 @@ public void testPeekFirst() { } @Test - public void testPeekLast() { + void testPeekLast() { assertNull(deque.peekLast()); deque.add(ONE); deque.add(TWO); @@ -249,7 +249,7 @@ public void testPeekLast() { } @Test - public void testPollFirst() { + void testPollFirst() { assertNull(deque.pollFirst()); assertTrue(deque.offerFirst(ONE)); assertTrue(deque.offerFirst(TWO)); @@ -257,13 +257,13 @@ public void testPollFirst() { } @Test - public void testPollFirstWithTimeout() throws InterruptedException { + void testPollFirstWithTimeout() throws InterruptedException { assertNull(deque.pollFirst()); assertNull(deque.pollFirst(TIMEOUT_50_MILLIS)); } @Test - public void testPollLast() { + void testPollLast() { assertNull(deque.pollLast()); assertTrue(deque.offerFirst(ONE)); assertTrue(deque.offerFirst(TWO)); @@ -271,19 +271,19 @@ public void testPollLast() { } @Test - public void testPollLastWithTimeout() throws InterruptedException { + void testPollLastWithTimeout() throws InterruptedException { assertNull(deque.pollLast()); assertNull(deque.pollLast(TIMEOUT_50_MILLIS)); } @Test - public void testPollWithTimeout() throws InterruptedException { + void testPollWithTimeout() throws InterruptedException { assertNull(deque.poll(TIMEOUT_50_MILLIS)); assertNull(deque.poll(TIMEOUT_50_MILLIS)); } @Test - public void testPop() { + void testPop() { assertThrows(NoSuchElementException.class, () -> deque.pop()); deque.add(ONE); deque.add(TWO); @@ -301,7 +301,7 @@ public void testPop() { */ @Test @Timeout(value = 10000, unit = TimeUnit.MILLISECONDS) - public void testPossibleBug() { + void testPossibleBug() { deque = new LinkedBlockingDeque<>(); for (int i = 0; i < 3; i++) { @@ -322,7 +322,7 @@ public void testPossibleBug() { } @Test - public void testPush() { + void testPush() { deque.push(ONE); deque.push(TWO); assertEquals(2, deque.size()); @@ -331,14 +331,14 @@ public void testPush() { } @Test - public void testPut() throws InterruptedException { + void testPut() throws InterruptedException { assertThrows(NullPointerException.class, () -> deque.put(null)); deque.put(ONE); deque.put(TWO); } @Test - public void testPutFirst() throws InterruptedException { + void testPutFirst() throws InterruptedException { assertThrows(NullPointerException.class, () -> deque.putFirst(null)); deque.putFirst(ONE); deque.putFirst(TWO); @@ -347,7 +347,7 @@ public void testPutFirst() throws InterruptedException { } @Test - public void testPutLast() throws InterruptedException { + void testPutLast() throws InterruptedException { assertThrows(NullPointerException.class, () -> deque.putLast(null)); deque.putLast(ONE); deque.putLast(TWO); @@ -356,7 +356,7 @@ public void testPutLast() throws InterruptedException { } @Test - public void testRemove() { + void testRemove() { assertThrows(NoSuchElementException.class, deque::remove); deque.add(ONE); deque.add(TWO); @@ -364,7 +364,7 @@ public void testRemove() { } @Test - public void testRemoveFirst() { + void testRemoveFirst() { assertThrows(NoSuchElementException.class, deque::removeFirst); deque.add(ONE); deque.add(TWO); @@ -376,7 +376,7 @@ public void testRemoveFirst() { } @Test - public void testRemoveLast() { + void testRemoveLast() { assertThrows(NoSuchElementException.class, deque::removeLast); deque.add(ONE); deque.add(TWO); @@ -388,7 +388,7 @@ public void testRemoveLast() { } @Test - public void testRemoveLastOccurrence() { + void testRemoveLastOccurrence() { assertFalse(deque.removeLastOccurrence(null)); assertFalse(deque.removeLastOccurrence(ONE)); deque.add(ONE); @@ -398,28 +398,28 @@ public void testRemoveLastOccurrence() { } @Test - public void testTake() throws InterruptedException { + void testTake() throws InterruptedException { assertTrue(deque.offerFirst(ONE)); assertTrue(deque.offerFirst(TWO)); assertEquals(Integer.valueOf(2), deque.take()); } @Test - public void testTakeFirst() throws InterruptedException { + void testTakeFirst() throws InterruptedException { assertTrue(deque.offerFirst(ONE)); assertTrue(deque.offerFirst(TWO)); assertEquals(Integer.valueOf(2), deque.takeFirst()); } @Test - public void testTakeLast() throws InterruptedException { + void testTakeLast() throws InterruptedException { assertTrue(deque.offerFirst(ONE)); assertTrue(deque.offerFirst(TWO)); assertEquals(Integer.valueOf(1), deque.takeLast()); } @Test - public void testToArray() { + void testToArray() { deque.add(ONE); deque.add(TWO); Object[] arr = deque.toArray(); diff --git a/src/test/java/org/apache/commons/pool2/impl/TestPoolImplUtils.java b/src/test/java/org/apache/commons/pool3/impl/TestPoolImplUtils.java similarity index 86% rename from src/test/java/org/apache/commons/pool2/impl/TestPoolImplUtils.java rename to src/test/java/org/apache/commons/pool3/impl/TestPoolImplUtils.java index 03ea82402..91b246084 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestPoolImplUtils.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestPoolImplUtils.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -23,11 +23,11 @@ import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; import org.junit.jupiter.api.Test; -public class TestPoolImplUtils { +class TestPoolImplUtils { @SuppressWarnings("unused") private abstract static class FactoryAB extends BasePooledObjectFactory { @@ -51,7 +51,7 @@ private abstract static class FactoryF extends FactoryDE { // empty by design } - private static class NotSimpleFactory extends FactoryF { + private static final class NotSimpleFactory extends FactoryF { @Override public Long create() { return null; @@ -63,7 +63,7 @@ public PooledObject wrap(final Long obj) { } } - private static class SimpleFactory extends BasePooledObjectFactory { + private static final class SimpleFactory extends BasePooledObjectFactory { @Override public String create() { return null; @@ -80,19 +80,19 @@ public PooledObject wrap(final String obj) { private static final Instant INSTANT_0 = Instant.ofEpochMilli(0); @Test - public void testFactoryTypeNotSimple() { + void testFactoryTypeNotSimple() { final Class result = PoolImplUtils.getFactoryType(NotSimpleFactory.class); assertEquals(Long.class, result); } @Test - public void testFactoryTypeSimple() { + void testFactoryTypeSimple() { final Class result = PoolImplUtils.getFactoryType(SimpleFactory.class); assertEquals(String.class, result); } @Test - public void testMaxInstants() { + void testMaxInstants() { assertEquals(INSTANT_1, PoolImplUtils.max(INSTANT_0, INSTANT_1)); assertEquals(INSTANT_1, PoolImplUtils.max(INSTANT_1, INSTANT_0)); assertEquals(INSTANT_1, PoolImplUtils.max(INSTANT_1, INSTANT_1)); @@ -100,7 +100,7 @@ public void testMaxInstants() { } @Test - public void testMinInstants() { + void testMinInstants() { assertEquals(INSTANT_0, PoolImplUtils.min(INSTANT_0, INSTANT_1)); assertEquals(INSTANT_0, PoolImplUtils.min(INSTANT_1, INSTANT_0)); assertEquals(INSTANT_1, PoolImplUtils.min(INSTANT_1, INSTANT_1)); @@ -108,7 +108,7 @@ public void testMinInstants() { } @Test - public void testToChronoUnit() { + void testToChronoUnit() { assertEquals(ChronoUnit.NANOS, PoolImplUtils.toChronoUnit(TimeUnit.NANOSECONDS)); assertEquals(ChronoUnit.MICROS, PoolImplUtils.toChronoUnit(TimeUnit.MICROSECONDS)); assertEquals(ChronoUnit.MILLIS, PoolImplUtils.toChronoUnit(TimeUnit.MILLISECONDS)); @@ -119,7 +119,7 @@ public void testToChronoUnit() { } @Test - public void testToDuration() { + void testToDuration() { assertEquals(Duration.ZERO, PoolImplUtils.toDuration(0, TimeUnit.MILLISECONDS)); assertEquals(Duration.ofMillis(1), PoolImplUtils.toDuration(1, TimeUnit.MILLISECONDS)); for (final TimeUnit tu : TimeUnit.values()) { diff --git a/src/test/java/org/apache/commons/pool2/impl/TestPooledSoftReference.java b/src/test/java/org/apache/commons/pool3/impl/TestPooledSoftReference.java similarity index 90% rename from src/test/java/org/apache/commons/pool2/impl/TestPooledSoftReference.java rename to src/test/java/org/apache/commons/pool3/impl/TestPooledSoftReference.java index 2e3fff8d7..1e26e1455 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestPooledSoftReference.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestPooledSoftReference.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,8 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; - +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -24,11 +23,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - /** * Tests for PooledSoftReference. */ -public class TestPooledSoftReference { +class TestPooledSoftReference { private static final String REFERENT = "test"; private static final String REFERENT2 = "test2"; @@ -41,7 +39,7 @@ public void setUp() { } @Test - public void testPooledSoftReference() { + void testPooledSoftReference() { assertEquals(REFERENT, ref.getObject()); SoftReference softRef = ref.getReference(); @@ -59,7 +57,7 @@ public void testPooledSoftReference() { } @Test - public void testToString() { + void testToString() { final String expected = "Referenced Object: test, State: IDLE"; assertEquals(expected, ref.toString()); } diff --git a/src/test/java/org/apache/commons/pool3/impl/TestResilientPooledObjectFactory.java b/src/test/java/org/apache/commons/pool3/impl/TestResilientPooledObjectFactory.java new file mode 100644 index 000000000..8d1ac26eb --- /dev/null +++ b/src/test/java/org/apache/commons/pool3/impl/TestResilientPooledObjectFactory.java @@ -0,0 +1,377 @@ +/* + * 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 + * + * https://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.pool3.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Duration; +import java.util.UUID; + +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; +import org.junit.jupiter.api.Test; + +class TestResilientPooledObjectFactory { + /** + * Factory that suffers outages and fails in configurable ways when it is down. + */ + class FailingFactory implements PooledObjectFactory { + + /** Whether or not the factory is up */ + private boolean up = true; + + /** Whether or not to fail silently */ + private boolean silentFail = true; + + /** Whether or not to hang */ + private boolean hang; + + @Override + public void activateObject(final PooledObject p) throws Exception { + } + + public void crash() { + this.up = false; + } + + @Override + public void destroyObject(final PooledObject p) throws Exception { + } + + @Override + public PooledObject makeObject() throws Exception { + if (up) { + return new DefaultPooledObject<>(UUID.randomUUID().toString()); + } + if (!silentFail) { + throw new Exception("makeObject failed"); + } + if (hang) { + while (!up) { + try { + Thread.sleep(1000); + } catch (final InterruptedException e) { + } + } + } + return null; + } + + @Override + public void passivateObject(final PooledObject p) throws Exception { + } + + public void recover() { + this.up = true; + } + + public void setHang(final boolean hang) { + this.hang = hang; + } + + public void setSilentFail(final boolean silentFail) { + this.silentFail = silentFail; + } + + @Override + public boolean validateObject(final PooledObject p) { + return up; + } + } + + @Test + void testAdderStartStop() throws Exception { + final FailingFactory ff = new FailingFactory(); + // Make the factory fail with exception immediately on make + ff.setSilentFail(true); + final ResilientPooledObjectFactory rf = new ResilientPooledObjectFactory<>(ff, + 5, Duration.ofMillis(200), Duration.ofMinutes(10), Duration.ofMillis(20)); + // Create a pool with a max size of 2, using the resilient factory + final GenericObjectPool pool = new GenericObjectPool<>(rf); + pool.setMaxTotal(2); + pool.setBlockWhenExhausted(true); + pool.setTestOnReturn(true); + rf.setPool(pool); + rf.startMonitor(); + // Exhasut the pool + final String s1 = pool.borrowObject(); + final String s2 = pool.borrowObject(); + // Start a borrower that will block waiting + new Thread() { + @Override + public void run() { + try { + final String s = pool.borrowObject(); + } catch (final Exception e) { + } + } + }.start(); + // Wait for the borrower to get in the queue + try { + Thread.sleep(50); + } catch (final InterruptedException e) { + } + // Crash the base factory + ff.crash(); + // Return object will create capacity in the pool + try { + pool.returnObject(s1); + } catch (final Exception e) { + } + // Wait for the adder to run + try { + Thread.sleep(100); + } catch (final InterruptedException e) { + } + // Adder should be running + assertTrue(rf.isAdderRunning()); + // Restart the factory + ff.recover(); + // Wait for the adder to succeed + try { + Thread.sleep(200); + } catch (final InterruptedException e) { + } + // Pool should have no waiters + assertEquals(0, pool.getNumWaiters()); + // Adder should still be running because there is a failure in the log + assertTrue(rf.isAdderRunning()); + // Expand the pool - don't try this at home + pool.setMaxTotal(10); + // Run enough adds to homogenize the log + for (int i = 0; i < 6; i++) { + pool.addObject(); + } + // Wait for the monitor to run + try { + Thread.sleep(200); + } catch (final InterruptedException e) { + } + assertTrue(rf.isUp()); + // Adder should be stopped + assertFalse(rf.isAdderRunning()); + } + + @Test + void testConstructorWithDefaults() { + final FailingFactory ff = new FailingFactory(); + final ResilientPooledObjectFactory rf = new ResilientPooledObjectFactory<>(ff); + assertFalse(rf.isMonitorRunning()); + assertFalse(rf.isAdderRunning()); + assertEquals(ResilientPooledObjectFactory.getDefaultLogSize(), rf.getLogSize()); + assertEquals(ResilientPooledObjectFactory.getDefaultTimeBetweenChecks(), rf.getTimeBetweenChecks()); + assertEquals(ResilientPooledObjectFactory.getDefaultDelay(), rf.getDelay()); + assertEquals(ResilientPooledObjectFactory.getDefaultLookBack(), rf.getLookBack()); + assertEquals(0, rf.getMakeObjectLog().size()); + rf.setLogSize(5); + assertEquals(5, rf.getLogSize()); + rf.setTimeBetweenChecks(Duration.ofMillis(200)); + } + + @Test + void testIsMonitorRunning() throws Exception { + final FailingFactory ff = new FailingFactory(); + // Make the factory fail with exception immediately on make + ff.setSilentFail(true); + final ResilientPooledObjectFactory rf = new ResilientPooledObjectFactory<>(ff, + 5, Duration.ofMillis(200), Duration.ofMinutes(10), Duration.ofMillis(20)); + final GenericObjectPool pool = new GenericObjectPool<>(rf); + rf.setPool(pool); + rf.startMonitor(); + assertTrue(rf.isMonitorRunning()); + rf.stopMonitor(); + assertFalse(rf.isMonitorRunning()); + rf.startMonitor(); + pool.close(); + // Wait for monitor to run so it can kill itself + try { + Thread.sleep(200); + } catch (final InterruptedException e) { + } + assertFalse(rf.isMonitorRunning()); + } + + @Test + void testNulls() throws Exception { + final FailingFactory ff = new FailingFactory(); + // Make the factory fail with exception immediately on make + ff.setSilentFail(true); + final ResilientPooledObjectFactory rf = new ResilientPooledObjectFactory<>(ff, + 5, Duration.ofMillis(50), Duration.ofMinutes(10), Duration.ofMillis(50)); + // Create a pool with a max size of 2, using the resilient factory + final GenericObjectPool pool = new GenericObjectPool<>(rf); + pool.setMaxTotal(2); + pool.setBlockWhenExhausted(true); + pool.setTestOnReturn(true); + // Tell the factory what pool it is attached to (a little awkward) + rf.setPool(pool); + rf.startMonitor(Duration.ofMillis(20)); // 20ms monitor interval + + // Exhaust the pool + final String s1 = pool.borrowObject(); + final String s2 = pool.borrowObject(); + ff.crash(); + // Start two borrowers that will block waiting + new Thread() { + @Override + public void run() { + try { + final String s = pool.borrowObject(); + pool.returnObject(s); + } catch (final Exception e) { + } + } + }.start(); + new Thread() { + @Override + public void run() { + try { + final String s = pool.borrowObject(); + pool.returnObject(s); + } catch (final Exception e) { + } + } + }.start(); + // Return borrowed objects - validation will fail + // Wait for the borrowers to get in the queue + try { + Thread.sleep(50); + } catch (final InterruptedException e) { + } + pool.returnObject(s1); + pool.returnObject(s2); + assertEquals(0, pool.getNumIdle()); + assertTrue(pool.getNumWaiters() > 0); + // Wait for the monitor to pick up the failed create which should happen on + // validation destroy + try { + Thread.sleep(200); + } catch (final InterruptedException e) { + } + assertFalse(rf.isUp()); + // Restart the factory + ff.recover(); + // Wait for the adder to succeed + try { + Thread.sleep(200); + } catch (final InterruptedException e) { + } + // Pool should have no waiters + assertEquals(0, pool.getNumWaiters()); + pool.close(); + // Wait for monitor to run + try { + Thread.sleep(200); + } catch (final InterruptedException e) { + } + // Monitor and adder should be stopped by pool close + assertFalse(rf.isAdderRunning()); + assertFalse(rf.isMonitorRunning()); + } + + @Test + void testTransientFailure() throws Exception { + final FailingFactory ff = new FailingFactory(); + // Make the factory fail with exception immediately on make + ff.setHang(false); + ff.setSilentFail(false); + final ResilientPooledObjectFactory rf = new ResilientPooledObjectFactory<>(ff, + 5, Duration.ofMillis(100), Duration.ofMinutes(10), Duration.ofMillis(100)); + // Create a pool with a max size of 2, using the resilient factory + final GenericObjectPool pool = new GenericObjectPool<>(rf); + pool.setMaxTotal(2); + pool.setBlockWhenExhausted(true); + pool.setTestOnReturn(true); + // Tell the factory what pool it is attached to (a little awkward) + rf.setPool(pool); + rf.startMonitor(Duration.ofMillis(20)); // 20ms monitor interval + // Base factory is up + assertTrue(rf.isUp()); + // Check out a couple of objects + final String s1 = pool.borrowObject(); + final String s2 = pool.borrowObject(); + // Start a borrower that will wait + new Thread() { + @Override + public void run() { + try { + pool.borrowObject(); + } catch (final Exception e) { + } + } + }.start(); + // Wait for the borrower to join wait queue + try { + Thread.sleep(200); + } catch (final InterruptedException e) { + } + + // Crash the base factory + ff.crash(); + // Resilient factory does not know the base factory is down until a make is + // attempted + assertTrue(rf.isUp()); + assertEquals(1, pool.getNumWaiters()); + pool.returnObject(s1); + pool.returnObject(s2); + assertEquals(0, pool.getNumIdle()); + assertEquals(1, pool.getNumWaiters()); + // Wait for the monitor to pick up the failed create which should happen on + // validation destroy + try { + Thread.sleep(100); + } catch (final InterruptedException e) { + } + assertFalse(rf.isUp()); + // Adder should be running, but failing + assertTrue(rf.isAdderRunning()); + + // Pool should have one take waiter + assertEquals(1, pool.getNumWaiters()); + + // Restart the factory + ff.recover(); + // Wait for the adder to succeed + try { + Thread.sleep(100); + } catch (final InterruptedException e) { + } + // Pool should have no waiters + assertTrue(pool.getNumWaiters() == 0); + // Add 5 objects to clear the rf log + // First have to expand the pool + pool.setMaxTotal(10); + for (int i = 0; i < 5; i++) { + pool.addObject(); + } + // Wait for monitor to run + try { + Thread.sleep(200); + } catch (final InterruptedException e) { + } + // rf should be up now + assertTrue(rf.isUp()); + + // Adder should be stopped + assertFalse(rf.isAdderRunning()); + + pool.close(); + rf.stopMonitor(); + } +} diff --git a/src/test/java/org/apache/commons/pool2/impl/TestSoftRefOutOfMemory.java b/src/test/java/org/apache/commons/pool3/impl/TestSoftRefOutOfMemory.java similarity index 82% rename from src/test/java/org/apache/commons/pool2/impl/TestSoftRefOutOfMemory.java rename to src/test/java/org/apache/commons/pool3/impl/TestSoftRefOutOfMemory.java index 55044f3b6..a0818813c 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestSoftRefOutOfMemory.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestSoftRefOutOfMemory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,30 +15,31 @@ * limitations under the License. */ -package org.apache.commons.pool2.impl; - +package org.apache.commons.pool3.impl; import static org.junit.jupiter.api.Assertions.assertEquals; +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.util.Arrays; import java.util.LinkedList; import java.util.List; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; /** */ -public class TestSoftRefOutOfMemory { +class TestSoftRefOutOfMemory { + public static class LargePoolableObjectFactory extends BasePooledObjectFactory { + private final String buffer; private int counter; - public LargePoolableObjectFactory(final int size) { + LargePoolableObjectFactory(final int size) { final char[] data = new char[size]; Arrays.fill(data, '.'); buffer = new String(data); @@ -56,11 +57,11 @@ public PooledObject wrap(final String value) { } } - private static class OomeFactory extends BasePooledObjectFactory { + private static final class OomeFactory extends BasePooledObjectFactory { private final OomeTrigger trigger; - public OomeFactory(final OomeTrigger trigger) { + OomeFactory(final OomeTrigger trigger) { this.trigger = trigger; } @@ -136,7 +137,7 @@ public void tearDown() { } @Test - public void testOutOfMemory() throws Exception { + void testOutOfMemory() throws Exception { pool = new SoftReferenceObjectPool<>(new SmallPoolableObjectFactory()); String obj = pool.borrowObject(); @@ -172,7 +173,7 @@ public void testOutOfMemory() throws Exception { } @Test - public void testOutOfMemory1000() throws Exception { + void testOutOfMemory1000() throws Exception { pool = new SoftReferenceObjectPool<>(new SmallPoolableObjectFactory()); for (int i = 0 ; i < 1000 ; i++) { @@ -217,46 +218,22 @@ public void testOutOfMemory1000() throws Exception { * @throws Exception May occur in some failure modes */ @Test - public void testOutOfMemoryError() throws Exception { - pool = new SoftReferenceObjectPool<>( - new OomeFactory(OomeTrigger.CREATE)); - - try { - pool.borrowObject(); - fail("Expected out of memory."); - } - catch (final OutOfMemoryError ex) { - // expected - } + void testOutOfMemoryError() throws Exception { + pool = new SoftReferenceObjectPool<>(new OomeFactory(OomeTrigger.CREATE)); + assertThrows(OutOfMemoryError.class, pool::borrowObject); pool.close(); - pool = new SoftReferenceObjectPool<>( - new OomeFactory(OomeTrigger.VALIDATE)); - - try { - pool.borrowObject(); - fail("Expected out of memory."); - } - catch (final OutOfMemoryError ex) { - // expected - } + pool = new SoftReferenceObjectPool<>(new OomeFactory(OomeTrigger.VALIDATE)); + assertThrows(OutOfMemoryError.class, pool::borrowObject); pool.close(); - pool = new SoftReferenceObjectPool<>( - new OomeFactory(OomeTrigger.DESTROY)); - - try { - pool.borrowObject(); - fail("Expected out of memory."); - } - catch (final OutOfMemoryError ex) { - // expected - } + pool = new SoftReferenceObjectPool<>(new OomeFactory(OomeTrigger.DESTROY)); + assertThrows(OutOfMemoryError.class, pool::borrowObject); pool.close(); } @Test - public void testOutOfMemoryLarge() throws Exception { + void testOutOfMemoryLarge() throws Exception { pool = new SoftReferenceObjectPool<>(new LargePoolableObjectFactory(1000000)); String obj = pool.borrowObject(); @@ -290,4 +267,4 @@ public void testOutOfMemoryLarge() throws Exception { assertEquals(1, pool.getNumIdle()); } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/pool2/impl/TestSoftReferenceObjectPool.java b/src/test/java/org/apache/commons/pool3/impl/TestSoftReferenceObjectPool.java similarity index 76% rename from src/test/java/org/apache/commons/pool2/impl/TestSoftReferenceObjectPool.java rename to src/test/java/org/apache/commons/pool3/impl/TestSoftReferenceObjectPool.java index 43d9fbd83..1c31590db 100644 --- a/src/test/java/org/apache/commons/pool2/impl/TestSoftReferenceObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/impl/TestSoftReferenceObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,19 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.impl; +package org.apache.commons.pool3.impl; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.ObjectPool; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectFactory; -import org.apache.commons.pool2.TestBaseObjectPool; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.ObjectPool; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; +import org.apache.commons.pool3.TestBaseObjectPool; /** */ -public class TestSoftReferenceObjectPool extends TestBaseObjectPool { +class TestSoftReferenceObjectPool extends TestBaseObjectPool { - private static class SimpleFactory extends BasePooledObjectFactory { + private static final class SimpleFactory extends BasePooledObjectFactory { int counter; @@ -61,7 +61,6 @@ protected ObjectPool makeEmptyPool(final int ca return (ObjectPool) new SoftReferenceObjectPool<>(new SimpleFactory()); } - @Override protected ObjectPool makeEmptyPool(final PooledObjectFactory factory) { return new SoftReferenceObjectPool<>(factory); diff --git a/src/test/java/org/apache/commons/pool3/impl/TestSynchronizedPooledObjectFactory.java b/src/test/java/org/apache/commons/pool3/impl/TestSynchronizedPooledObjectFactory.java new file mode 100644 index 000000000..57e19de33 --- /dev/null +++ b/src/test/java/org/apache/commons/pool3/impl/TestSynchronizedPooledObjectFactory.java @@ -0,0 +1,135 @@ +/* + * 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 + * + * https://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.pool3.impl; + +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; + +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; + +/** + * Copies PoolUtil's private static final class SynchronizedPooledObjectFactory. + * + * A fully synchronized PooledObjectFactory that wraps a PooledObjectFactory and synchronizes access to the wrapped factory methods. + *

    + * Note: This should not be used on pool implementations that already provide proper synchronization such as the pools provided in the Commons + * Pool library. + *

    + * + * @param Type of element managed in this factory. + * @param Type of exception thrown in this factory. + */ +final class TestSynchronizedPooledObjectFactory implements PooledObjectFactory { + + /** Synchronization lock */ + private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock(); + + /** Wrapped factory */ + private final PooledObjectFactory factory; + + /** + * Constructs a SynchronizedPoolableObjectFactory wrapping the given factory. + * + * @param factory underlying factory to wrap + * @throws IllegalArgumentException if the factory is null + */ + TestSynchronizedPooledObjectFactory(final PooledObjectFactory factory) throws IllegalArgumentException { + if (factory == null) { + throw new IllegalArgumentException("factory must not be null."); + } + this.factory = factory; + } + + /** + * {@inheritDoc} + */ + @Override + public void activateObject(final PooledObject p) throws E { + writeLock.lock(); + try { + factory.activateObject(p); + } finally { + writeLock.unlock(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void destroyObject(final PooledObject p) throws E { + writeLock.lock(); + try { + factory.destroyObject(p); + } finally { + writeLock.unlock(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public PooledObject makeObject() throws E { + writeLock.lock(); + try { + return factory.makeObject(); + } finally { + writeLock.unlock(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void passivateObject(final PooledObject p) throws E { + writeLock.lock(); + try { + factory.passivateObject(p); + } finally { + writeLock.unlock(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("SynchronizedPoolableObjectFactory"); + sb.append("{factory=").append(factory); + sb.append('}'); + return sb.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean validateObject(final PooledObject p) { + writeLock.lock(); + try { + return factory.validateObject(p); + } finally { + writeLock.unlock(); + } + } +} diff --git a/src/test/java/org/apache/commons/pool2/performance/PerformanceTest.java b/src/test/java/org/apache/commons/pool3/performance/PerformanceTest.java similarity index 90% rename from src/test/java/org/apache/commons/pool2/performance/PerformanceTest.java rename to src/test/java/org/apache/commons/pool3/performance/PerformanceTest.java index ea29789e9..55c92d8b4 100644 --- a/src/test/java/org/apache/commons/pool2/performance/PerformanceTest.java +++ b/src/test/java/org/apache/commons/pool3/performance/PerformanceTest.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2.performance; +package org.apache.commons.pool3.performance; import java.time.Duration; import java.util.ArrayList; @@ -26,14 +26,14 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; -import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool3.impl.GenericObjectPool; /** * Multi-thread performance test */ -public class PerformanceTest { +class PerformanceTest { - class PerfTask implements Callable { + final class PerfTask implements Callable { final TaskStats taskStats = new TaskStats(); long borrowTimeNanos; long returnTimeNanos; @@ -91,12 +91,13 @@ public void runOnce() { } } } - private static class TaskStats { - public int waiting; - public int complete; - public long totalBorrowNanos; - public long totalReturnNanos; - public int nrSamples; + + private static final class TaskStats { + private int waiting; + private int complete; + private long totalBorrowNanos; + private long totalReturnNanos; + private int nrSamples; } public static void main(final String[] args) { @@ -133,7 +134,9 @@ private void run(final int iterations, final int nrThreads, final int maxTotal, this.nrIterations = iterations; final SleepingObjectFactory factory = new SleepingObjectFactory(); - if (logLevel >= 4) { factory.setDebug(true); } + if (logLevel >= 4) { + factory.setDebug(true); + } pool = new GenericObjectPool<>(factory); pool.setMaxTotal(maxTotal); pool.setMaxIdle(maxIdle); @@ -158,13 +161,19 @@ private void run(final int iterations, final int nrThreads, final int maxTotal, e.printStackTrace(); } - if (logLevel >= 1) { System.out.println("started"); } + if (logLevel >= 1) { + System.out.println("started"); + } Thread.yield(); - if (logLevel >= 1) { System.out.println("go"); } + if (logLevel >= 1) { + System.out.println("go"); + } Thread.yield(); - if (logLevel >= 1) { System.out.println("finish"); } + if (logLevel >= 1) { + System.out.println("finish"); + } final TaskStats aggregate = new TaskStats(); if (futures != null) { diff --git a/src/test/java/org/apache/commons/pool2/performance/SleepingObjectFactory.java b/src/test/java/org/apache/commons/pool3/performance/SleepingObjectFactory.java similarity index 88% rename from src/test/java/org/apache/commons/pool2/performance/SleepingObjectFactory.java rename to src/test/java/org/apache/commons/pool3/performance/SleepingObjectFactory.java index a12b664ec..f0e8eb6b7 100644 --- a/src/test/java/org/apache/commons/pool2/performance/SleepingObjectFactory.java +++ b/src/test/java/org/apache/commons/pool3/performance/SleepingObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.commons.pool2.performance; +package org.apache.commons.pool3.performance; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectFactory; -import org.apache.commons.pool2.Waiter; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; +import org.apache.commons.pool3.Waiter; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * Sleepy ObjectFactory (everything takes a while longer) diff --git a/src/test/java/org/apache/commons/pool2/pool407/AbstractKeyedPool407Factory.java b/src/test/java/org/apache/commons/pool3/pool407/AbstractKeyedPool407Factory.java similarity index 83% rename from src/test/java/org/apache/commons/pool2/pool407/AbstractKeyedPool407Factory.java rename to src/test/java/org/apache/commons/pool3/pool407/AbstractKeyedPool407Factory.java index 064862d12..766d4ca21 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/AbstractKeyedPool407Factory.java +++ b/src/test/java/org/apache/commons/pool3/pool407/AbstractKeyedPool407Factory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; -import org.apache.commons.pool2.BaseKeyedPooledObjectFactory; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.BaseKeyedPooledObjectFactory; +import org.apache.commons.pool3.PooledObject; /** * Tests POOL-407. @@ -30,7 +30,7 @@ public abstract class AbstractKeyedPool407Factory extends BaseKeyedPooledObjectF @Override public boolean validateObject(final String key, final PooledObject p) { // TODO Should this be enough even if wrap() does throw and returns a DefaultPooledObject wrapping a null? - return !PooledObject.isNull(p); + return PooledObject.nonNull(p); } } diff --git a/src/test/java/org/apache/commons/pool2/pool407/AbstractPool407Factory.java b/src/test/java/org/apache/commons/pool3/pool407/AbstractPool407Factory.java similarity index 82% rename from src/test/java/org/apache/commons/pool2/pool407/AbstractPool407Factory.java rename to src/test/java/org/apache/commons/pool3/pool407/AbstractPool407Factory.java index 5638f2bdf..60d83fe7e 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/AbstractPool407Factory.java +++ b/src/test/java/org/apache/commons/pool3/pool407/AbstractPool407Factory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.PooledObject; /** * Tests POOL-407. @@ -28,6 +28,8 @@ public abstract class AbstractPool407Factory extends BasePooledObjectFactory p) { // TODO Should this be enough even if wrap() does throw and returns a DefaultPooledObject wrapping a null? - return !PooledObject.isNull(p); + return PooledObject.isNull(p); } } diff --git a/src/test/java/org/apache/commons/pool2/pool407/AbstractPool407Test.java b/src/test/java/org/apache/commons/pool3/pool407/AbstractPool407Test.java similarity index 92% rename from src/test/java/org/apache/commons/pool2/pool407/AbstractPool407Test.java rename to src/test/java/org/apache/commons/pool3/pool407/AbstractPool407Test.java index 60a252ef3..4935e89f2 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/AbstractPool407Test.java +++ b/src/test/java/org/apache/commons/pool3/pool407/AbstractPool407Test.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,19 +15,19 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.Duration; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; /** * Tests POOL-407. */ -public class AbstractPool407Test { +class AbstractPool407Test { protected void assertShutdown(final boolean termination, final Duration poolConfigMaxWait, final T obj, final PooledObject pooledObject) { if (pooledObject != null) { diff --git a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407.java b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407.java similarity index 80% rename from src/test/java/org/apache/commons/pool2/pool407/KeyedPool407.java rename to src/test/java/org/apache/commons/pool3/pool407/KeyedPool407.java index c7e221117..846665507 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407.java +++ b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,13 +15,13 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; import java.time.Duration; -import org.apache.commons.pool2.BaseKeyedPooledObjectFactory; -import org.apache.commons.pool2.impl.BaseObjectPoolConfig; -import org.apache.commons.pool2.impl.GenericKeyedObjectPool; +import org.apache.commons.pool3.BaseKeyedPooledObjectFactory; +import org.apache.commons.pool3.impl.BaseObjectPoolConfig; +import org.apache.commons.pool3.impl.GenericKeyedObjectPool; public final class KeyedPool407 extends GenericKeyedObjectPool { diff --git a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Config.java b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Config.java similarity index 87% rename from src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Config.java rename to src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Config.java index 6feff5ffa..a4dad268c 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Config.java +++ b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Config.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; import java.time.Duration; -import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; +import org.apache.commons.pool3.impl.GenericKeyedObjectPoolConfig; public final class KeyedPool407Config extends GenericKeyedObjectPoolConfig { diff --git a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Fixture.java b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Fixture.java similarity index 89% rename from src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Fixture.java rename to src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Fixture.java index 48f3e613a..5fcbda8fb 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Fixture.java +++ b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Fixture.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; public final class KeyedPool407Fixture { // empty diff --git a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NormalFactory.java b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NormalFactory.java similarity index 81% rename from src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NormalFactory.java rename to src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NormalFactory.java index 8ff88bd88..79e381aad 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NormalFactory.java +++ b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NormalFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * Tests POOL-407. @@ -34,7 +34,8 @@ public final class KeyedPool407NormalFactory extends AbstractKeyedPool407Factory @Override public KeyedPool407Fixture create(final String key) { // This is key to the test, creation failed and returns null for instance see - // https://github.com/openhab/openhab-core/blob/main/bundles/org.openhab.core.io.transport.modbus/src/main/java/org/openhab/core/io/transport/modbus/internal/pooling/ModbusSlaveConnectionFactoryImpl.java#L163 + // https://github.com/openhab/openhab-core/blob/main/bundles/org.openhab.core.io.transport.modbus/ + // src/main/java/org/openhab/core/io/transport/modbus/internal/pooling/ModbusSlaveConnectionFactoryImpl.java#L163 // the test passes when this returns new Pool407Fixture(); return fixture; } diff --git a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NullObjectFactory.java b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NullObjectFactory.java similarity index 87% rename from src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NullObjectFactory.java rename to src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NullObjectFactory.java index e3b9c2066..a0c54ac97 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NullObjectFactory.java +++ b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NullObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * Tests POOL-407. diff --git a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NullPoolableObjectFactory.java b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NullPoolableObjectFactory.java similarity index 90% rename from src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NullPoolableObjectFactory.java rename to src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NullPoolableObjectFactory.java index c319fdcd1..0b3a6002b 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407NullPoolableObjectFactory.java +++ b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407NullPoolableObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,9 +15,9 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; /** * Tests POOL-407. diff --git a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Test.java b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Test.java similarity index 80% rename from src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Test.java rename to src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Test.java index deb2f0016..a43258a53 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/KeyedPool407Test.java +++ b/src/test/java/org/apache/commons/pool3/pool407/KeyedPool407Test.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,29 +15,29 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; import java.time.Duration; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Tests POOL-407. */ -public class KeyedPool407Test extends AbstractPool407Test { +class KeyedPool407Test extends AbstractPool407Test { /** * Borrows from a pool and then immediately returns to that a pool. */ - private static class KeyedPool407RoundtripRunnable implements Runnable { + private static final class KeyedPool407RoundtripRunnable implements Runnable { private final KeyedPool407 pool; - public KeyedPool407RoundtripRunnable(final KeyedPool407 pool) { + KeyedPool407RoundtripRunnable(final KeyedPool407 pool) { this.pool = pool; } @@ -56,7 +56,8 @@ public void run() { private static final String KEY = "key"; - protected void assertShutdown(final ExecutorService executor, final Duration poolConfigMaxWait, final AbstractKeyedPool407Factory factory) throws InterruptedException { + protected void assertShutdown(final ExecutorService executor, final Duration poolConfigMaxWait, final AbstractKeyedPool407Factory factory) + throws InterruptedException { // Old note: This never finishes when the factory makes nulls because two threads are stuck forever // If a factory always returns a null object or a null poolable object, then we will wait forever. // This would also be true is object validation always fails. @@ -70,10 +71,9 @@ protected void assertShutdown(final ExecutorService executor, final Duration poo assertShutdown(termination, poolConfigMaxWait, obj, pooledObject); } - private void test(final AbstractKeyedPool407Factory factory, final int poolSize, final Duration poolConfigMaxWait) throws InterruptedException { final ExecutorService executor = Executors.newFixedThreadPool(poolSize); - try (final KeyedPool407 pool = new KeyedPool407(factory, poolConfigMaxWait)) { + try (KeyedPool407 pool = new KeyedPool407(factory, poolConfigMaxWait)) { // Start 'poolSize' threads that try to borrow a Pool407Fixture with the same key for (int i = 0; i < poolSize; i++) { executor.execute(new KeyedPool407RoundtripRunnable(pool)); @@ -83,37 +83,37 @@ private void test(final AbstractKeyedPool407Factory factory, final int poolSize, } @Test - public void testNormalFactoryNonNullFixtureWaitMax() throws InterruptedException { + void testNormalFactoryNonNullFixtureWaitMax() throws InterruptedException { test(new KeyedPool407NormalFactory(new KeyedPool407Fixture()), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Disabled @Test - public void testNormalFactoryNullFixtureWaitMax() throws InterruptedException { + void testNormalFactoryNullFixtureWaitMax() throws InterruptedException { test(new KeyedPool407NormalFactory(null), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Disabled @Test - public void testNullObjectFactoryWaitMax() throws InterruptedException { + void testNullObjectFactoryWaitMax() throws InterruptedException { test(new KeyedPool407NullObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Disabled @Test - public void testNullObjectFactoryWaitShort() throws InterruptedException { + void testNullObjectFactoryWaitShort() throws InterruptedException { test(new KeyedPool407NullObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_SHORT); } @Disabled @Test - public void testNullPoolableFactoryWaitMax() throws InterruptedException { + void testNullPoolableFactoryWaitMax() throws InterruptedException { test(new KeyedPool407NullPoolableObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Disabled @Test - public void testNullPoolableFactoryWaitShort() throws InterruptedException { + void testNullPoolableFactoryWaitShort() throws InterruptedException { test(new KeyedPool407NullPoolableObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_SHORT); } } diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407.java b/src/test/java/org/apache/commons/pool3/pool407/Pool407.java similarity index 84% rename from src/test/java/org/apache/commons/pool2/pool407/Pool407.java rename to src/test/java/org/apache/commons/pool3/pool407/Pool407.java index 6880ec8ba..9237e3aff 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407.java +++ b/src/test/java/org/apache/commons/pool3/pool407/Pool407.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; import java.time.Duration; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.impl.GenericObjectPool; /** * Tests POOL-407. diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407Config.java b/src/test/java/org/apache/commons/pool3/pool407/Pool407Config.java similarity index 87% rename from src/test/java/org/apache/commons/pool2/pool407/Pool407Config.java rename to src/test/java/org/apache/commons/pool3/pool407/Pool407Config.java index ee75d183e..8b2ee2134 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407Config.java +++ b/src/test/java/org/apache/commons/pool3/pool407/Pool407Config.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; import java.time.Duration; -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.apache.commons.pool3.impl.GenericObjectPoolConfig; /** * Tests POOL-407. diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407Constants.java b/src/test/java/org/apache/commons/pool3/pool407/Pool407Constants.java similarity index 86% rename from src/test/java/org/apache/commons/pool2/pool407/Pool407Constants.java rename to src/test/java/org/apache/commons/pool3/pool407/Pool407Constants.java index 9e35124c2..ecd04dec7 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407Constants.java +++ b/src/test/java/org/apache/commons/pool3/pool407/Pool407Constants.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,16 +15,16 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; import java.time.Duration; -import org.apache.commons.pool2.impl.BaseObjectPoolConfig; +import org.apache.commons.pool3.impl.BaseObjectPoolConfig; /** * Tests POOL-407. */ -class Pool407Constants { +final class Pool407Constants { static final int AWAIT_TERMINATION_SECONDS = 10; static final boolean BLOCK_WHEN_EXHAUSTED = true; diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407Fixture.java b/src/test/java/org/apache/commons/pool3/pool407/Pool407Fixture.java similarity index 89% rename from src/test/java/org/apache/commons/pool2/pool407/Pool407Fixture.java rename to src/test/java/org/apache/commons/pool3/pool407/Pool407Fixture.java index 0488bb221..5ec6f425e 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407Fixture.java +++ b/src/test/java/org/apache/commons/pool3/pool407/Pool407Fixture.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; public final class Pool407Fixture { // empty diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407NormalFactory.java b/src/test/java/org/apache/commons/pool3/pool407/Pool407NormalFactory.java similarity index 83% rename from src/test/java/org/apache/commons/pool2/pool407/Pool407NormalFactory.java rename to src/test/java/org/apache/commons/pool3/pool407/Pool407NormalFactory.java index 03ade541d..40eb779b9 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407NormalFactory.java +++ b/src/test/java/org/apache/commons/pool3/pool407/Pool407NormalFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * Tests POOL-407. @@ -37,7 +37,8 @@ public Pool407Fixture create() { // // Old note: // This is key to the test, creation failed and returns null for instance see - // https://github.com/openhab/openhab-core/blob/main/bundles/org.openhab.core.io.transport.modbus/src/main/java/org/openhab/core/io/transport/modbus/internal/pooling/ModbusSlaveConnectionFactoryImpl.java#L163 + // https://github.com/openhab/openhab-core/blob/main/bundles/org.openhab.core.io.transport.modbus/ + // src/main/java/org/openhab/core/io/transport/modbus/internal/pooling/ModbusSlaveConnectionFactoryImpl.java#L163 // the test passes when this returns new Pool407Fixture(); return fixture; } diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407NullObjectFactory.java b/src/test/java/org/apache/commons/pool3/pool407/Pool407NullObjectFactory.java similarity index 88% rename from src/test/java/org/apache/commons/pool2/pool407/Pool407NullObjectFactory.java rename to src/test/java/org/apache/commons/pool3/pool407/Pool407NullObjectFactory.java index eecf8d263..bece79cde 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407NullObjectFactory.java +++ b/src/test/java/org/apache/commons/pool3/pool407/Pool407NullObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.impl.DefaultPooledObject; /** * Tests POOL-407. diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407NullPoolableObjectFactory.java b/src/test/java/org/apache/commons/pool3/pool407/Pool407NullPoolableObjectFactory.java similarity index 90% rename from src/test/java/org/apache/commons/pool2/pool407/Pool407NullPoolableObjectFactory.java rename to src/test/java/org/apache/commons/pool3/pool407/Pool407NullPoolableObjectFactory.java index 3e54b965c..a76611b8f 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407NullPoolableObjectFactory.java +++ b/src/test/java/org/apache/commons/pool3/pool407/Pool407NullPoolableObjectFactory.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,9 +15,9 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; /** * Tests POOL-407. diff --git a/src/test/java/org/apache/commons/pool2/pool407/Pool407Test.java b/src/test/java/org/apache/commons/pool3/pool407/Pool407Test.java similarity index 81% rename from src/test/java/org/apache/commons/pool2/pool407/Pool407Test.java rename to src/test/java/org/apache/commons/pool3/pool407/Pool407Test.java index 9e79b92d9..ccba1a9f4 100644 --- a/src/test/java/org/apache/commons/pool2/pool407/Pool407Test.java +++ b/src/test/java/org/apache/commons/pool3/pool407/Pool407Test.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -15,29 +15,29 @@ * limitations under the License. */ -package org.apache.commons.pool2.pool407; +package org.apache.commons.pool3.pool407; import java.time.Duration; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool3.PooledObject; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Tests POOL-407. */ -public class Pool407Test extends AbstractPool407Test { +class Pool407Test extends AbstractPool407Test { /** * Borrows from a pool and then immediately returns to that a pool. */ - private static class Pool407RoundtripRunnable implements Runnable { + private static final class Pool407RoundtripRunnable implements Runnable { private final Pool407 pool; - public Pool407RoundtripRunnable(final Pool407 pool) { + Pool407RoundtripRunnable(final Pool407 pool) { this.pool = pool; } @@ -54,7 +54,8 @@ public void run() { } } - protected void assertShutdown(final ExecutorService executor, final Duration poolConfigMaxWait, final AbstractPool407Factory factory) throws InterruptedException { + protected void assertShutdown(final ExecutorService executor, final Duration poolConfigMaxWait, final AbstractPool407Factory factory) + throws InterruptedException { // Old note: This never finishes when the factory makes nulls because two threads are stuck forever // If a factory always returns a null object or a null poolable object, then we will wait forever. // This would also be true is object validation always fails. @@ -70,7 +71,7 @@ protected void assertShutdown(final ExecutorService executor, final Duration poo private void test(final AbstractPool407Factory factory, final int poolSize, final Duration poolConfigMaxWait) throws InterruptedException { final ExecutorService executor = Executors.newFixedThreadPool(poolSize); - try (final Pool407 pool = new Pool407(factory, poolConfigMaxWait)) { + try (Pool407 pool = new Pool407(factory, poolConfigMaxWait)) { // Start 'poolSize' threads that try to borrow a Pool407Fixture with the same key for (int i = 0; i < poolSize; i++) { executor.execute(new Pool407RoundtripRunnable(pool)); @@ -80,37 +81,37 @@ private void test(final AbstractPool407Factory factory, final int poolSize, fina } @Test - public void testNormalFactoryNonNullFixtureWaitMax() throws InterruptedException { + void testNormalFactoryNonNullFixtureWaitMax() throws InterruptedException { test(new Pool407NormalFactory(new Pool407Fixture()), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Test @Disabled - public void testNormalFactoryNullFixtureWaitMax() throws InterruptedException { + void testNormalFactoryNullFixtureWaitMax() throws InterruptedException { test(new Pool407NormalFactory(null), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Disabled @Test - public void testNullObjectFactoryWaitMax() throws InterruptedException { + void testNullObjectFactoryWaitMax() throws InterruptedException { test(new Pool407NullObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Test @Disabled - public void testNullObjectFactoryWaitShort() throws InterruptedException { + void testNullObjectFactoryWaitShort() throws InterruptedException { test(new Pool407NullObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_SHORT); } @Test @Disabled - public void testNullPoolableFactoryWaitMax() throws InterruptedException { + void testNullPoolableFactoryWaitMax() throws InterruptedException { test(new Pool407NullPoolableObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_FOREVER); } @Test @Disabled - public void testNullPoolableFactoryWaitShort() throws InterruptedException { + void testNullPoolableFactoryWaitShort() throws InterruptedException { test(new Pool407NullPoolableObjectFactory(), Pool407Constants.POOL_SIZE, Pool407Constants.WAIT_SHORT); } } diff --git a/src/test/java/org/apache/commons/pool2/proxy/AbstractTestProxiedKeyedObjectPool.java b/src/test/java/org/apache/commons/pool3/proxy/AbstractTestProxiedKeyedObjectPool.java similarity index 81% rename from src/test/java/org/apache/commons/pool2/proxy/AbstractTestProxiedKeyedObjectPool.java rename to src/test/java/org/apache/commons/pool3/proxy/AbstractTestProxiedKeyedObjectPool.java index 52bd1f394..54d440ac4 100644 --- a/src/test/java/org/apache/commons/pool2/proxy/AbstractTestProxiedKeyedObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/proxy/AbstractTestProxiedKeyedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -25,22 +25,20 @@ import java.io.StringWriter; import java.time.Duration; -import org.apache.commons.pool2.BaseKeyedPooledObjectFactory; -import org.apache.commons.pool2.KeyedObjectPool; -import org.apache.commons.pool2.KeyedPooledObjectFactory; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.impl.AbandonedConfig; -import org.apache.commons.pool2.impl.DefaultPooledObject; -import org.apache.commons.pool2.impl.GenericKeyedObjectPool; -import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; +import org.apache.commons.pool3.BaseKeyedPooledObjectFactory; +import org.apache.commons.pool3.KeyedObjectPool; +import org.apache.commons.pool3.KeyedPooledObjectFactory; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.impl.AbandonedConfig; +import org.apache.commons.pool3.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.GenericKeyedObjectPool; +import org.apache.commons.pool3.impl.GenericKeyedObjectPoolConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - - public abstract class AbstractTestProxiedKeyedObjectPool { - private static class TestKeyedObjectFactory extends BaseKeyedPooledObjectFactory { + private static final class TestKeyedObjectFactory extends BaseKeyedPooledObjectFactory { @Override public TestObject create(final String key) { @@ -58,7 +56,7 @@ protected interface TestObject { void setData(String data); } - private static class TestObjectImpl implements TestObject { + private static final class TestObjectImpl implements TestObject { private String data; @@ -75,7 +73,6 @@ public void setData(final String data) { private static final String KEY1 = "key1"; - private static final String DATA1 = "data1"; private static final Duration ABANDONED_TIMEOUT_SECS = Duration.ofSeconds(3); @@ -84,9 +81,7 @@ public void setData(final String data) { private StringWriter log; - - protected abstract ProxySource getproxySource(); - + protected abstract ProxySource getProxySource(); @BeforeEach public void setUp() { @@ -108,12 +103,11 @@ public void setUp() { @SuppressWarnings("resource") final KeyedObjectPool innerPool = new GenericKeyedObjectPool<>(factory, config, abandonedConfig); - pool = new ProxiedKeyedObjectPool<>(innerPool, getproxySource()); + pool = new ProxiedKeyedObjectPool<>(innerPool, getProxySource()); } - @Test - public void testAccessAfterInvalidate() { + void testAccessAfterInvalidate() { final TestObject obj = pool.borrowObject(KEY1); assertNotNull(obj); @@ -130,9 +124,8 @@ public void testAccessAfterInvalidate() { } - @Test - public void testAccessAfterReturn() { + void testAccessAfterReturn() { final TestObject obj = pool.borrowObject(KEY1); assertNotNull(obj); @@ -148,7 +141,7 @@ public void testAccessAfterReturn() { } @Test - public void testBorrowObject() { + void testBorrowObject() { final TestObject obj = pool.borrowObject(KEY1); assertNotNull(obj); @@ -159,9 +152,8 @@ public void testBorrowObject() { pool.returnObject(KEY1, obj); } - @Test - public void testPassThroughMethods01() { + void testPassThroughMethods01() { assertEquals(0, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); @@ -176,16 +168,15 @@ public void testPassThroughMethods01() { assertEquals(0, pool.getNumIdle()); } - @Test - public void testPassThroughMethods02() { + void testPassThroughMethods02() { pool.close(); assertThrows(IllegalStateException.class, () -> pool.addObject(KEY1)); } @Test - public void testUsageTracking() throws InterruptedException { + void testUsageTracking() throws InterruptedException { final TestObject obj = pool.borrowObject(KEY1); assertNotNull(obj); diff --git a/src/test/java/org/apache/commons/pool2/proxy/AbstractTestProxiedObjectPool.java b/src/test/java/org/apache/commons/pool3/proxy/AbstractTestProxiedObjectPool.java similarity index 60% rename from src/test/java/org/apache/commons/pool2/proxy/AbstractTestProxiedObjectPool.java rename to src/test/java/org/apache/commons/pool3/proxy/AbstractTestProxiedObjectPool.java index 55682d1dc..37cc25dfd 100644 --- a/src/test/java/org/apache/commons/pool2/proxy/AbstractTestProxiedObjectPool.java +++ b/src/test/java/org/apache/commons/pool3/proxy/AbstractTestProxiedObjectPool.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -25,30 +25,38 @@ import java.io.StringWriter; import java.time.Duration; -import org.apache.commons.pool2.BasePooledObjectFactory; -import org.apache.commons.pool2.ObjectPool; -import org.apache.commons.pool2.PooledObject; -import org.apache.commons.pool2.PooledObjectFactory; -import org.apache.commons.pool2.impl.AbandonedConfig; -import org.apache.commons.pool2.impl.DefaultPooledObject; -import org.apache.commons.pool2.impl.GenericObjectPool; -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.apache.commons.pool3.BasePooledObjectFactory; +import org.apache.commons.pool3.ObjectPool; +import org.apache.commons.pool3.PooledObject; +import org.apache.commons.pool3.PooledObjectFactory; +import org.apache.commons.pool3.impl.AbandonedConfig; +import org.apache.commons.pool3.impl.DefaultPooledObject; +import org.apache.commons.pool3.impl.GenericObjectPool; +import org.apache.commons.pool3.impl.GenericObjectPoolConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - public abstract class AbstractTestProxiedObjectPool { + private static class MyException extends RuntimeException { } + protected interface TestObject { String getData(); void setData(String data); } - private static class TestObjectFactory extends + + private static final class TestObjectFactory extends BasePooledObjectFactory { + private final RuntimeException exceptionToThrow; + + private TestObjectFactory(RuntimeException exceptionToThrow) { + this.exceptionToThrow = exceptionToThrow; + } + @Override public TestObject create() { - return new TestObjectImpl(); + return new TestObjectImpl(exceptionToThrow); } @Override public PooledObject wrap(final TestObject value) { @@ -56,37 +64,44 @@ public PooledObject wrap(final TestObject value) { } } - private static class TestObjectImpl implements TestObject { + private static final class TestObjectImpl implements TestObject { + private final RuntimeException exceptionToThrow; private String data; + private TestObjectImpl(RuntimeException exceptionToThrow) { + this.exceptionToThrow = exceptionToThrow; + } + @Override public String getData() { + if (exceptionToThrow != null) { + throw exceptionToThrow; + } return data; } @Override public void setData(final String data) { + if (exceptionToThrow != null) { + throw exceptionToThrow; + } this.data = data; } } + private static final String DATA1 = "data1"; private static final Duration ABANDONED_TIMEOUT_SECS = Duration.ofSeconds(3); - - private ObjectPool pool; - private StringWriter log; + private ProxiedObjectPool createProxiedObjectPool() { + return createProxiedObjectPool(false, null); + } - protected abstract ProxySource getproxySource(); - - - @BeforeEach - public void setUp() { - log = new StringWriter(); - + private ProxiedObjectPool createProxiedObjectPool( + boolean unwrapInvocationTargetException, RuntimeException exceptionToThrow) { final PrintWriter pw = new PrintWriter(log); final AbandonedConfig abandonedConfig = new AbandonedConfig(); abandonedConfig.setLogAbandoned(true); @@ -98,17 +113,27 @@ public void setUp() { final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); config.setMaxTotal(3); - final PooledObjectFactory factory = new TestObjectFactory(); + final PooledObjectFactory factory = new TestObjectFactory(exceptionToThrow); - @SuppressWarnings("resource") final ObjectPool innerPool = new GenericObjectPool<>(factory, config, abandonedConfig); - pool = new ProxiedObjectPool<>(innerPool, getproxySource()); + return new ProxiedObjectPool<>(innerPool, getProxySource(unwrapInvocationTargetException)); } + protected abstract Class getInvocationTargetExceptionType(); + + protected abstract ProxySource getProxySource(boolean unwrapInvocationTargetException); + + @BeforeEach + public void setUp() { + log = new StringWriter(); + } @Test public void testAccessAfterInvalidate() { + @SuppressWarnings("resource") + final ObjectPool pool = createProxiedObjectPool(); + final TestObject obj = pool.borrowObject(); assertNotNull(obj); @@ -125,9 +150,11 @@ public void testAccessAfterInvalidate() { } - @Test public void testAccessAfterReturn() { + @SuppressWarnings("resource") + final ObjectPool pool = createProxiedObjectPool(); + final TestObject obj = pool.borrowObject(); assertNotNull(obj); @@ -143,9 +170,11 @@ public void testAccessAfterReturn() { obj::getData); } - @Test public void testBorrowObject() { + @SuppressWarnings("resource") + final ObjectPool pool = createProxiedObjectPool(); + final TestObject obj = pool.borrowObject(); assertNotNull(obj); @@ -158,6 +187,9 @@ public void testBorrowObject() { @Test public void testPassThroughMethods01() { + @SuppressWarnings("resource") + final ObjectPool pool = createProxiedObjectPool(); + assertEquals(0, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); @@ -172,18 +204,39 @@ public void testPassThroughMethods01() { assertEquals(0, pool.getNumIdle()); } - @Test public void testPassThroughMethods02() { + final ObjectPool pool = createProxiedObjectPool(); + pool.close(); assertThrows(IllegalStateException.class, () -> pool.addObject()); } + @Test + public void testUnwrapInvocationTargetExceptionFalse() { + @SuppressWarnings("resource") + final ObjectPool pool = createProxiedObjectPool(false, new MyException()); + + final TestObject object = pool.borrowObject(); + assertThrows(getInvocationTargetExceptionType(), object::getData); + } + + @Test + public void testUnwrapInvocationTargetExceptionTrue() { + @SuppressWarnings("resource") + final ObjectPool pool = createProxiedObjectPool(true, new MyException()); + + final TestObject object = pool.borrowObject(); + assertThrows(MyException.class, object::getData); + } @Test public void testUsageTracking() throws InterruptedException { + @SuppressWarnings("resource") + final ObjectPool pool = createProxiedObjectPool(); + final TestObject obj = pool.borrowObject(); assertNotNull(obj); @@ -201,5 +254,4 @@ public void testUsageTracking() throws InterruptedException { assertTrue(logOutput.contains("Pooled object created")); assertTrue(logOutput.contains("The last code to use this object was")); } - } diff --git a/src/test/java/org/apache/commons/pool2/proxy/TestProxiedKeyedObjectPoolWithCglibProxy.java b/src/test/java/org/apache/commons/pool3/proxy/TestProxiedKeyedObjectPoolWithCglibProxy.java similarity index 80% rename from src/test/java/org/apache/commons/pool2/proxy/TestProxiedKeyedObjectPoolWithCglibProxy.java rename to src/test/java/org/apache/commons/pool3/proxy/TestProxiedKeyedObjectPoolWithCglibProxy.java index 2f6e599ff..d7b3ca557 100644 --- a/src/test/java/org/apache/commons/pool2/proxy/TestProxiedKeyedObjectPoolWithCglibProxy.java +++ b/src/test/java/org/apache/commons/pool3/proxy/TestProxiedKeyedObjectPoolWithCglibProxy.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,13 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; -public class TestProxiedKeyedObjectPoolWithCglibProxy extends +class TestProxiedKeyedObjectPoolWithCglibProxy extends AbstractTestProxiedKeyedObjectPool { @Override - protected ProxySource getproxySource() { + protected ProxySource getProxySource() { return new CglibProxySource<>(TestObject.class); } } diff --git a/src/test/java/org/apache/commons/pool2/proxy/TestProxiedKeyedObjectPoolWithJdkProxy.java b/src/test/java/org/apache/commons/pool3/proxy/TestProxiedKeyedObjectPoolWithJdkProxy.java similarity index 82% rename from src/test/java/org/apache/commons/pool2/proxy/TestProxiedKeyedObjectPoolWithJdkProxy.java rename to src/test/java/org/apache/commons/pool3/proxy/TestProxiedKeyedObjectPoolWithJdkProxy.java index d5c4d82f5..a0804d7f6 100644 --- a/src/test/java/org/apache/commons/pool2/proxy/TestProxiedKeyedObjectPoolWithJdkProxy.java +++ b/src/test/java/org/apache/commons/pool3/proxy/TestProxiedKeyedObjectPoolWithJdkProxy.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,13 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; +package org.apache.commons.pool3.proxy; -public class TestProxiedKeyedObjectPoolWithJdkProxy +class TestProxiedKeyedObjectPoolWithJdkProxy extends AbstractTestProxiedKeyedObjectPool { @Override - protected ProxySource getproxySource() { + protected ProxySource getProxySource() { return new JdkProxySource<>(this.getClass().getClassLoader(), new Class[] { TestObject.class }); } diff --git a/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java b/src/test/java/org/apache/commons/pool3/proxy/TestProxiedObjectPoolWithCglibProxy.java similarity index 51% rename from src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java rename to src/test/java/org/apache/commons/pool3/proxy/TestProxiedObjectPoolWithCglibProxy.java index 2df83d0ad..63407d3b7 100644 --- a/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java +++ b/src/test/java/org/apache/commons/pool3/proxy/TestProxiedObjectPoolWithCglibProxy.java @@ -6,7 +6,7 @@ * (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 + * https://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, @@ -14,13 +14,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.pool2.proxy; -public class TestProxiedObjectPoolWithCglibProxy extends - AbstractTestProxiedObjectPool { +package org.apache.commons.pool3.proxy; + +import java.lang.reflect.InvocationTargetException; + +class TestProxiedObjectPoolWithCglibProxy extends AbstractTestProxiedObjectPool { + + @Override + protected Class getInvocationTargetExceptionType() { + return InvocationTargetException.class; + } @Override - protected ProxySource getproxySource() { - return new CglibProxySource<>(TestObject.class); + protected ProxySource getProxySource(boolean unwrapInvocationTargetException) { + // @formatter:off + return CglibProxySource.builder() + .setSuperclass(TestObject.class) + .setUnwrapInvocationTargetException(unwrapInvocationTargetException) + .get(); + // @formatter:on } } diff --git a/src/test/java/org/apache/commons/pool3/proxy/TestProxiedObjectPoolWithJdkProxy.java b/src/test/java/org/apache/commons/pool3/proxy/TestProxiedObjectPoolWithJdkProxy.java new file mode 100644 index 000000000..35662673d --- /dev/null +++ b/src/test/java/org/apache/commons/pool3/proxy/TestProxiedObjectPoolWithJdkProxy.java @@ -0,0 +1,39 @@ +/* + * 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 + * + * https://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.pool3.proxy; + +import java.lang.reflect.UndeclaredThrowableException; + +class TestProxiedObjectPoolWithJdkProxy extends AbstractTestProxiedObjectPool { + + @Override + protected Class getInvocationTargetExceptionType() { + return UndeclaredThrowableException.class; + } + + @Override + protected ProxySource getProxySource(boolean unwrapInvocationTargetException) { + // @formatter:off + return JdkProxySource.builder() + .setClassLoader(getClass().getClassLoader()) + .setInterfaces(TestObject.class) + .setUnwrapInvocationTargetException(unwrapInvocationTargetException) + .get(); + // @formatter:on + } +}