pax_global_header00006660000000000000000000000064147204534570014525gustar00rootroot0000000000000052 comment=3cccba8e127cf55a4a30c5056e0bb9ec09446fd7 commons-dbcp-rel-commons-dbcp-2.13.0/000077500000000000000000000000001472045345700173305ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/.asf.yaml000066400000000000000000000025301472045345700210430ustar00rootroot00000000000000# 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. github: description: "Apache Commons DBCP" homepage: https://commons.apache.org/dbcp/ notifications: commits: commits@commons.apache.org issues: issues@commons.apache.org 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 issues_bot_codecov-commenter: notifications@commons.apache.org pullrequests_bot_codecov-commenter: notifications@commons.apache.org commons-dbcp-rel-commons-dbcp-2.13.0/.github/000077500000000000000000000000001472045345700206705ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/.github/GH-ROBOTS.txt000066400000000000000000000016331472045345700227400ustar00rootroot00000000000000# 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. # Keeps on creating FUD PRs in test code # Does not follow Apache disclosure policies User-agent: JLLeitschuh/security-research Disallow: * commons-dbcp-rel-commons-dbcp-2.13.0/.github/dependabot.yml000066400000000000000000000020061472045345700235160ustar00rootroot00000000000000# 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. version: 2 updates: - package-ecosystem: "maven" directory: "/" schedule: interval: "weekly" day: "friday" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" day: "friday" commons-dbcp-rel-commons-dbcp-2.13.0/.github/workflows/000077500000000000000000000000001472045345700227255ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/.github/workflows/codeql-analysis.yml000066400000000000000000000062751472045345700265520ustar00rootroot00000000000000# 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: "CodeQL" on: push: branches: [ master ] pull_request: # The branches below must be a subset of the branches above branches: [ master ] schedule: - cron: '33 9 * * 4' permissions: contents: read jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'java' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://git.io/codeql-language-support steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # 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@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5 commons-dbcp-rel-commons-dbcp-2.13.0/.github/workflows/dependency-review.yml000066400000000000000000000022341472045345700270660ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. name: 'Dependency Review' on: [pull_request] permissions: contents: read jobs: dependency-review: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: 'Dependency Review PR' uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 commons-dbcp-rel-commons-dbcp-2.13.0/.github/workflows/maven.yml000066400000000000000000000035071472045345700245630ustar00rootroot00000000000000# 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: Java CI on: [push, pull_request] permissions: contents: read jobs: build: runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental }} strategy: matrix: java: [ 8, 11, 17, 21, 23 ] experimental: [false] include: - java: 24-ea experimental: true steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} - name: Build with Maven run: mvn --errors --show-version --batch-mode --no-transfer-progress commons-dbcp-rel-commons-dbcp-2.13.0/.github/workflows/scorecards-analysis.yml000066400000000000000000000047451472045345700274330ustar00rootroot00000000000000# 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: "Scorecards supply-chain security" on: branch_protection_rule: schedule: - cron: "30 1 * * 6" # Weekly on Saturdays push: branches: [ "master" ] permissions: read-all jobs: analysis: name: "Scorecards analysis" runs-on: ubuntu-latest permissions: # Needed to upload the results to the code-scanning dashboard. security-events: write actions: read id-token: write # This is required for requesting the JWT contents: read # This is required for actions/checkout steps: - name: "Checkout code" uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Run analysis" uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # 2.4.0 with: results_file: results.sarif results_format: sarif # A read-only PAT token, which is sufficient for the action to function. # The relevant discussion: https://github.com/ossf/scorecard-action/issues/188 repo_token: ${{ secrets.GITHUB_TOKEN }} # Publish the results for public repositories to enable scorecard badges. # For more details: https://github.com/ossf/scorecard-action#publishing-results publish_results: true - name: "Upload artifact" uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # 4.4.3 with: name: SARIF file path: results.sarif retention-days: 5 - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5 with: sarif_file: results.sarif commons-dbcp-rel-commons-dbcp-2.13.0/.gitignore000066400000000000000000000004071472045345700213210ustar00rootroot00000000000000target/ pom.xml.tag pom.xml.releaseBackup pom.xml.versionsBackup pom.xml.next release.properties site-content /.checkstyle /.classpath /.pmd /.project /.settings /ObjectStore/ /bin/ # no IDE stuff in our SCM .classpath .settings .idea .vscode *.iml .nbproject commons-dbcp-rel-commons-dbcp-2.13.0/CODE_OF_CONDUCT.md000066400000000000000000000016411472045345700221310ustar00rootroot00000000000000 The Apache code of conduct page is [https://www.apache.org/foundation/policies/conduct.html](https://www.apache.org/foundation/policies/conduct.html). commons-dbcp-rel-commons-dbcp-2.13.0/CONTRIBUTING.md000066400000000000000000000146621472045345700215720ustar00rootroot00000000000000 Contributing to Apache Commons DBCP ====================== Have you found a bug or have an idea for a cool new feature? Contributing code is a great way to give something back to the open-source community. Before you dig right into the code, we need contributors to follow a few guidelines to have a chance of keeping on top of things. Getting Started --------------- + Make sure you have a [JIRA account](https://issues.apache.org/jira/). + Make sure you have a [GitHub account](https://github.com/signup/free). This is not essential, but makes providing patches much easier. + If you're planning to implement a new feature it makes sense to discuss your changes on the [dev list](https://commons.apache.org/mail-lists.html) first. This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Commons DBCP's scope. + Submit a [Jira Ticket][jira] for your issue, assuming one does not already exist. + Clearly describe the issue including steps to reproduce when it is a bug. + Make sure you fill in the earliest version that you know has the issue. + Find the corresponding [repository on GitHub](https://github.com/apache/?query=commons-), [fork](https://help.github.com/articles/fork-a-repo/) and check out your forked repository. If you don't have a GitHub account, you can still clone the Commons repository. Making Changes -------------- + Create a _topic branch_ for your isolated work. * Usually you should base your branch on the `master` branch. * A good topic branch name can be the JIRA bug ID plus a keyword, e.g. `DBCP-123-InputStream`. * 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. `DBCP-123: Close input stream earlier` + Respect the original code style: + Only use spaces for indentation. + 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 ensure nothing else was accidentally broken. 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. Submitting Changes ------------------ + Sign and submit the Apache [Contributor License Agreement][cla] if you haven't already. * Note that small patches & typical bug fixes do not require a CLA as clause 5 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0.html#contributions) covers them. + Push your changes to a topic branch in your fork of the repository. + Submit a _Pull Request_ to the corresponding repository in the `apache` organization. * Verify _Files Changed_ shows only your intended changes and does not include additional files like `target/*.class` + Update your JIRA ticket and include a link to the pull request in the ticket. If you prefer to not use GitHub, then you can instead use `git format-patch` (or `svn diff`) and attach the patch file to the JIRA issue. Additional Resources -------------------- + [Contributing patches](https://commons.apache.org/patches.html) + [Apache Commons DBCP JIRA project page][jira] + [Contributor License Agreement][cla] + [General GitHub documentation](https://help.github.com/) + [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/) + [Apache Commons Twitter Account](https://twitter.com/ApacheCommons) [cla]:https://www.apache.org/licenses/#clas [jira]:https://issues.apache.org/jira/browse/DBCP commons-dbcp-rel-commons-dbcp-2.13.0/LICENSE.txt000066400000000000000000000261361472045345700211630ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. commons-dbcp-rel-commons-dbcp-2.13.0/NOTICE.txt000066400000000000000000000002561472045345700210550ustar00rootroot00000000000000Apache Commons DBCP Copyright 2001-2024 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). commons-dbcp-rel-commons-dbcp-2.13.0/README.md000066400000000000000000000146101472045345700206110ustar00rootroot00000000000000 Apache Commons DBCP =================== [![Java CI](https://github.com/apache/commons-dbcp/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/commons-dbcp/actions/workflows/maven.yml) [![Maven Central](https://img.shields.io/maven-central/v/org.apache.commons/commons-dbcp2?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.commons/commons-dbcp2) [![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-dbcp2/2.13.0.svg)](https://javadoc.io/doc/org.apache.commons/commons-dbcp2/2.13.0) [![CodeQL](https://github.com/apache/commons-dbcp/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/commons-dbcp/actions/workflows/codeql-analysis.yml) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/commons-dbcp/badge)](https://api.securityscorecards.dev/projects/github.com/apache/commons-dbcp) Apache Commons DBCP software implements Database Connection Pooling Documentation ------------- More information can be found on the [Apache Commons DBCP homepage](https://commons.apache.org/proper/commons-dbcp). The [Javadoc](https://commons.apache.org/proper/commons-dbcp/apidocs) can be browsed. Questions related to the usage of Apache Commons DBCP should be posted to the [user mailing list](https://commons.apache.org/mail-lists.html). Getting the latest release -------------------------- You can download source and binaries from our [download page](https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi). Alternatively, you can pull it from the central Maven repositories: ```xml org.apache.commons commons-dbcp2 2.13.0 ``` Building -------- Building requires a Java JDK and [Apache Maven](https://maven.apache.org/). The required Java version is found in the `pom.xml` as the `maven.compiler.source` property. From a command shell, run `mvn` without arguments to invoke the default Maven goal to run all tests and checks. Contributing ------------ We accept Pull Requests via GitHub. The [developer mailing list](https://commons.apache.org/mail-lists.html) is the main channel of communication for contributors. There are some guidelines which will make applying PRs easier for us: + No tabs! Please use spaces for indentation. + Respect the existing code style for each file. + 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`. + 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 licensed under the [Apache License v2](https://www.apache.org/licenses/LICENSE-2.0). See the `NOTICE.txt` file for required notices and attributions. Donating -------- You like Apache Commons DBCP? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support development. Additional Resources -------------------- + [Apache Commons Homepage](https://commons.apache.org/) + [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/DBCP) + [Apache Commons Slack Channel](https://the-asf.slack.com/archives/C60NVB8AD) + [Apache Commons Twitter Account](https://twitter.com/ApacheCommons) Apache Commons Components ------------------------- Please see the [list of components](https://commons.apache.org/components.html) commons-dbcp-rel-commons-dbcp-2.13.0/RELEASE-NOTES.txt000066400000000000000000001162161472045345700220460ustar00rootroot00000000000000Apache Commons DBCP Version 2.13.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.13.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes ------- New features: * Add support for ignoring non-fatal SQL state codes #421. Thanks to Johno Crawford, Gary Gregory. * Add @FunctionalInterface to SwallowedExceptionListener. Thanks to Johno Crawford, Gary Gregory. * Add missing Javadoc comments and descriptions. Thanks to Gary Gregory. * Add tests, raise the bar for JaCoCo checks. Thanks to Gary Gregory. Fixed Bugs ---------- * Avoid object creation when invoking isDisconnectionSqlException #422. Thanks to Johno Crawford. * DBCP-599: PoolableConnectionFactory.destroyObject() method behaves incorrectly on ABANDONED connection, issue with unhandled AbstractMethodError. DelegatingConnection.abort(Executor) should delegate to Jdbc41Bridge Thanks to denixx baykin, Phil Steitz, Gary Gregory. * DelegatingConnection.setSchema(String) should delegate to Jdbc41Bridge. Thanks to Gary Gregory. * Fix possible NullPointerException in PoolingConnection.close(). Thanks to Gary Gregory. * PerUserPoolDataSource.registerPool() incorrectly replacing a CPDSConnectionFactory into managers map before throwing an IllegalStateException. Thanks to Gary Gregory. * Fix PMD UnnecessaryFullyQualifiedName in AbandonedTrace. Thanks to Gary Gregory. * Fix PMD UnnecessaryFullyQualifiedName in PoolableCallableStatement. Thanks to Gary Gregory. * Fix PMD UnnecessaryFullyQualifiedName in PoolablePreparedStatement. Thanks to Gary Gregory. * Fix PMD UnnecessaryFullyQualifiedName in Utils. Thanks to Gary Gregory. * Fix PMD UnnecessaryFullyQualifiedName in LocalXAConnectionFactory. Thanks to Gary Gregory. * Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in PerUserPoolDataSource. Thanks to Gary Gregory. * Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in SharedPoolDataSource. Thanks to Gary Gregory. Changes ------- * Bump org.apache.commons:commons-parent from 66 to 78 #360, #371, #395, #420, #426, #436, #441, #449. Thanks to Gary Gregory. * Bump commons-logging:commons-logging from 1.3.0 to 1.3.4 #368, #399, #423. Thanks to Gary Gregory, Dependabot. * Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #404, #412, #427. Thanks to Gary Gregory, Dependabot. * Bump org.hamcrest:hamcrest from 2.2 to 3.0 #410. Thanks to Gary Gregory, Dependabot. * Bump org.slf4j:slf4j-simple from 2.0.13 to 2.0.16 #413, #418. Thanks to Gary Gregory, Dependabot. The list of changes is here: https://commons.apache.org/proper/commons-dbcp/changes-report.html For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/proper/commons-dbcp/ Download page: https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.12.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.12.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. New features ------------ * Add property project.build.outputTimestamp for build reproducibility. Thanks to Gary Gregory. * Add null guards in DelegatingDatabaseMetaData constructor #352. Thanks to Heewon Lee. * DBCP-473: Data source bean creation failed due to mismatched return type of setter and getter for connectionInitSqls in BasicDataSource: Add BasicDataSource.setConnectionInitSqls(List). Thanks to Steve Cohen, Gary Gregory. Fixed Bugs ---------- * DBCP-590: BasicDataSource#setAbandonedUsageTracking has no effect. Thanks to Réda Housni Alaoui. * DBCP-596: PoolingConnection.toString() causes StackOverflowError. Thanks to Aapo Haapanen, Gary Gregory. * PooledConnectionImpl.destroyObject(PStmtKey, PooledObject) can throw NullPointerException #312. Thanks to Gary Gregory, Rémy Maucherat. * PoolingConnection.destroyObject(PStmtKey, PooledObject) can throw NullPointerException #312. Thanks to Gary Gregory, Rémy Maucherat. * DBCP-477: Fix examples in src/main/java/org/apache/commons/dbcp2/package-info.java. Thanks to Mubasher Usman, Gary Gregory. Changes ------- * Use ReentrantLock in PoolableConnection.close, #591 Thanks to cortlepp-intershop. * Bump commons-lang3 from 3.13.0 to 3.14.0. Thanks to Gary Gregory. * Bump commons-parent from 64 to 66. Thanks to Gary Gregory. * Bump org.slf4j:slf4j-simple from 2.0.9 to 2.0.12 #349. Thanks to Dependabot. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/proper/commons-dbcp/ Download page: https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.11.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.11.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes in this version include: Changes ------- o Update call sites of deprecated APIs from Apache Commons Pool. Thanks to Gary Gregory. o Add DataSourceMXBean.getUserName() and deprecate getUsername(). Thanks to Gary Gregory, Dependabot. o Bump h2 from 2.2.220 to 2.2.224, #308. Thanks to Gary Gregory, Dependabot. o Bump commons-parent from 60 to 64. Thanks to Gary Gregory. o Bump org.slf4j:slf4j-simple from 2.0.7 to 2.0.9 #301. Thanks to Dependabot. o Bump org.apache.commons:commons-pool2 from 2.11.1 to 2.12.0. Thanks to Gary Gregory. o Bump jakarta.transaction:jakarta.transaction-api from 1.3.1 to 1.3.3. Thanks to Gary Gregory. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.10.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.10.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes in this version include: New features ------------ o Add and use AbandonedTrace#setLastUsed(Instant). Thanks to Gary Gregory. o - Add and use Duration versions of now deprecated APIs that use ints and longs. - Internally track durations with Duration objects instead of ints and longs. - See the JApiCmp report for the complete list. Thanks to Gary Gregory. o Add PMD check to default Maven goal. Thanks to Gary Gregory. o Add Utils.getDisconnectionSqlCodes() and Utils.DISCONNECTION_SQL_CODES. Thanks to Gary Gregory. o Make BasicDataSource.getConnectionPool() public. Thanks to Gary Gregory. o Add github/codeql-action. Thanks to Gary Gregory. Fixed Bugs ---------- o Fix StackOverflowError in PoolableConnection.isDisconnectionSqlException #123. Thanks to newnewcoder, Gary Gregory. o PerUserPoolDataSourceFactory.getNewInstance(Reference) parsed defaultMaxWaitMillis as an int instead of a long. Thanks to Gary Gregory. o Reimplement time tracking in AbandonedTrace with an Instant instead of a long. Thanks to Gary Gregory. o Migrate away from deprecated APIs in Apache Commons Pool. Thanks to Gary Gregory. o Fix possible NullPointerException in BasicDataSourceFactory.validatePropertyNames(). Thanks to Gary Gregory. o Fix possible NullPointerException in BasicDataSourceFactory.getObjectInstance(). Thanks to Gary Gregory. o DBCP-585: Connection level JMX queries result in concurrent access to connection objects, causing errors #179. Thanks to Kurtcebe Eroglu, Gary Gregory, Phil Steitz. o UserPassKey should be Serializable. Thanks to Gary Gregory. o LifetimeExceededException should extend SQLException. Thanks to Gary Gregory. o Replace Exception with SQLException in some method signatures (preserves binary compatibility, not source). Thanks to Gary Gregory. o Don't leak Connections when PoolableConnectionFactory.makeObject() fails to create a JMX ObjectName. Thanks to Gary Gregory. o Performance: No need for map lookups if we traverse map entries instead of keys. Thanks to SpotBugs, Gary Gregory. o Performance: Refactor to use a static inner class in DataSourceXAConnectionFactory. Thanks to SpotBugs, Gary Gregory. o Reuse pattern of throwing XAException instead of NullPointerException in LocalXAConnectionFactory.LocalXAResource. Thanks to SpotBugs, Gary Gregory. o SpotBugs: An overridable method is called from constructors in PoolableCallableStatement. Thanks to SpotBugs, Gary Gregory. o SpotBugs: An overridable method is called from constructors in PoolablePreparedStatement. Thanks to SpotBugs, Gary Gregory. o Wrong property name logged in ConnectionFactoryFactory.createConnectionFactory(BasicDataSource, Driver). Thanks to Gary Gregory. o Throw SQLException instead of NullPointerException when the connection is already closed. Thanks to Gary Gregory. o CPDSConnectionFactory.makeObject() does not need to wrap and rethrow SQLException. Thanks to Gary Gregory. o PoolingDataSource.close() now always throws SQLException. Thanks to Gary Gregory. o [StepSecurity] ci: Harden GitHub Actions #282. Thanks to step-security-bot, Gary Gregory. o Fixes typos, missing or misplaced characters, and grammar issues #299. Thanks to Martin Wiesner. Changes ------- o Bump actions/cache from 2.1.6 to 3.0.8 #147, #176. Thanks to Dependabot, Gary Gregory. o Bump actions/checkout from 2.3.4 to 3.0.2 #139, #143, #173. Thanks to Dependabot, Gary Gregory. o Bump actions/setup-java from 2 to 3.6.0 #229. Thanks to Gary Gregory, Dependabot. o Bump actions/upload-artifact from 3.1.0 to 3.1.1 #231. Thanks to Dependabot. o Bump checkstyle from 8.44 to 9.3 #121, #130, #149, #158, #190. Thanks to Dependabot. o Bump maven-checkstyle-plugin from 3.1.2 to 3.2.0 #210. Thanks to Dependabot. o Bump commons-pool2 2.10.0 to 2.11.1. Thanks to Gary Gregory, Dependabot. o Bump junit-jupiter from 5.8.0-M1 to 5.9.1 #125, #136, #157, #203, #218. Thanks to Dependabot. o Bump spotbugs-maven-plugin from 4.3.0 to 4.7.3.0 #140, #154, #161, #178, #192, #200, #204, #213, #234. Thanks to Dependabot. o Bump spotbugs from 4.3.0 to 4.7.3 #124, #133, #151, #164, #177, #189, #214, #230. Thanks to Dependabot, Gary Gregory. o Bump org.mockito:mockito-core from 3.11.2 to 4.11.0, #128, #138, #152, #175, #188. #193, #208, #215, #232, #235, #246, #252. Thanks to Gary Gregory, Dependabot. o Bump maven-javadoc-plugin from 3.3.0 to 3.4.1 #131, #184. Thanks to Dependabot. o Bump maven-pmd-plugin from 3.14.0 to 3.19.0 #132, #172, #195. Thanks to Dependabot, Gary Gregory. o Bump pmd from 6.44.0 to 6.52.0. Thanks to Dependabot, Gary Gregory. o Bump narayana-jta from 5.12.0.Final to 5.12.7.Final #134, #156, #163, #185, #197. Thanks to Dependabot. o Bump japicmp-maven-plugin from 0.15.3 to 0.17.1 #137, #166, #174, #211, #238. Thanks to Dependabot. o Bump h2 from 1.4.200 to 2.2.220 #153, #183, #196, #287. Update SQL for migration from H2 1.4.200 to 2.0.204 where "KEY" and "VALUE" are now reserved keywords. Thanks to Gary Gregory, Dependabot. o Bump jboss-logging from 3.4.2.Final to 3.4.3.Final #162. Thanks to Dependabot. o Bump slf4j-simple from 1.7.30 to 1.7.36 #169. Thanks to Dependabot. o Bump commons-parent from 52 to 60 #180, #219, #254, #278. Thanks to Dependabot, Gary Gregory. o Bump JaCoCo from 0.8.7 to 0.8.8. Thanks to Gary Gregory. o Bump maven-surefire-plugin 2.22.2 to 3.0.0-M7. Thanks to Gary Gregory. o Bump apache-rat-plugin 0.13 to 0.14. Thanks to Gary Gregory. o Bump commons-lang3 from 3.12 to 3.13.0. Thanks to Gary Gregory. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.9.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.9.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes in this version include: New features ------------ o Add and reuse Constants.KEY_USER and Constants.KEY_PASSWORD. Thanks to Gary Gregory. o Add and reuse DataSourceMXBean. Thanks to Frank Gasdorf, Gary Gregory. o Add and reuse DriverAdapterCPDS.{get|set}DurationBetweenEvictionRuns(), deprecate {get|set}TimeBetweenEvictionRunsMillis(long). Thanks to Gary Gregory. o Add and reuse DriverAdapterCPDS.{get|set}MinEvictableIdleDuration(), deprecate {get|set}MinEvictableIdleTimeMillis(int). Thanks to Gary Gregory. o Add and reuse CPDSConnectionFactory.setMaxConnLifetime(Duration), deprecate setMaxConnLifetimeMillis(long). Thanks to Gary Gregory. o Add and reuse KeyedCPDSConnectionFactory.setMaxConnLifetime(Duration), deprecate setMaxConnLifetimeMillis(long). Thanks to Gary Gregory. o Add and reuse KeyedCPDSConnectionFactory.setMaxConnLifetime(Duration), deprecate setMaxConnLifetimeMillis(long). Thanks to Gary Gregory. o Add and reuse InstanceKeyDataSource.{get|set}DefaultMaxWait(Duration), deprecate {get|set}DefaultMaxWaitMillis(long). Thanks to Gary Gregory. Fixed Bugs ---------- o DBCP-569: Fix test random failure on TestSynchronizationOrder.testInterposedSynchronization, #84. Thanks to Florent Guillaume. o DBCP-568: ManagedConnection must clear its cached state after transaction completes, #75. Thanks to Florent Guillaume. o Minor Improvements #78. Thanks to Arturo Bernal. o DBCP-567: Use abort rather than close to clean up abandoned connections. Thanks to Phil Steitz, Gary Gregory, Phil Steitz, Romain Manni-Bucau. o Performance Enhancement: Call toArray with Zero Array Size #20. Thanks to Gary Gregory, DaGeRe. o DBCP-562: Avoid exposing password via JMX #38. Thanks to Frank Gasdorf, Gary Gregory. o DBCP-575: Remove redundant initializers #98. Thanks to Arturo Bernal. o DBCP-577: Simplify test assertions #100, #113. Thanks to Arturo Bernal. o DBCP-573: DataSource implementations do not implement Wrapper interface correctly #93. Thanks to Réda Housni Alaoui, Gary Gregory. o Replace FindBugs with SpotBugs. o DataSourceConnectionFactory.getUserPassword() may expose internal representation by returning DataSourceConnectionFactory.userPassword. o DataSourceXAConnectionFactory.getUserPassword() may expose internal representation by returning DataSourceXAConnectionFactory.userPassword. o DriverAdapterCPDS.getPasswordCharArray() may expose internal representation by returning DriverAdapterCPDS.userPassword. o new org.apache.commons.dbcp2.managed.DataSourceXAConnectionFactory(TransactionManager, XADataSource, String, char[], TransactionSynchronizationRegistry) may expose internal representation by storing an externally mutable object into DataSourceXAConnectionFactory.userPassword. o org.apache.commons.dbcp2.managed.DataSourceXAConnectionFactory.setPassword(char[]) may expose internal representation by storing an externally mutable object into DataSourceXAConnectionFactory.userPassword. o org.apache.commons.dbcp2.PStmtKey.getColumnIndexes() may expose internal representation by returning PStmtKey.columnIndexes. o org.apache.commons.dbcp2.PStmtKey.getColumnNames() may expose internal representation by returning PStmtKey.columnNames. o DBCP-578: Use Collections.synchronizedList() Instead Of Vector #101. Thanks to Arturo Bernal. o DBCP-576: Simplify and inline variables #99. Thanks to Arturo Bernal. o Update PoolKey#toString() to avoid revealing a user name is here. Thanks to Gary Gregory. o Internal package private UserPassKey class stores its user name as a char[] as it already does the password. Thanks to Gary Gregory. o DBCP-579: Performance of DelegatingConnection.prepareStatement(String) regressed enormously in 2.8.0 compared to 1.4. DelegatingConnection should also cache connection schema string to avoid calling the Connection#getSchema() for each key creation. DelegatingConnection should also cache connection catalog string to avoid calling the Connection#getCatalog() for each key creation. Thanks to Shaktisinh Jhala, Gary Gregory. o BasicDataSource should test for the presence of a security manager dynamically, not once on initialization. Thanks to Gary Gregory. Changes ------- o Bump mockito-core from 3.5.11 to 3.11.2 #66, #72, #77, #85, #91, #105, #110, #116. Thanks to Dependabot. o Bump actions/checkout from v2.3.2 to v2.3.4 #65, #74. Thanks to Dependabot. o Bump actions/cache from v2 to v2.1.6 #90, #108. Thanks to Dependabot. o Bump commons-pool2 from 2.8.1 to 2.9.0. Thanks to Gary Gregory. o Bump actions/setup-java from v1.4.2 to v2 #69. Thanks to Dependabot, Gary Gregory. o Bump japicmp-maven-plugin from 0.14.3 to 0.15.2 #71, #82. Thanks to Dependabot, Gary Gregory. o Bump maven-pmd-plugin from 3.13.0 to 3.14.0 #76. Thanks to Dependabot. o Bump japicmp-maven-plugin from 0.14.4 to 0.15.3, #83. Thanks to Dependabot, Gary Gregory. o Bump Hamcrest 1.3 -> 2.2 #70. Thanks to John Patrick. o Bump maven-checkstyle-plugin from 3.1.1 to 3.1.2 #88. Thanks to Gary Gregory. o Bump junit-jupiter from 5.7.0 to 5.8.0-M1, #89, #106. Thanks to Gary Gregory. o Bump narayana-jta from 5.10.6.Final to 5.12.0.Final #103, #111. Thanks to Dependabot. o Bump maven-javadoc-plugin from 3.2.0 to 3.3.0 #107. Thanks to Dependabot. o Bump commons.jacoco.version 0.8.6 -> 0.8.7. Thanks to Gary Gregory. o Bump jboss-logging from 3.4.1.Final to 3.4.2.Final #109. Thanks to Dependabot. o Bump org.jboss:jboss-transaction-spi from 7.6.0.Final to 7.6.1.Final. Thanks to Gary Gregory. o Bump commons-pool2 from 2.9.0 to 2.10.0. Thanks to Gary Gregory. o Bump checkstyle to 8.44. Thanks to Gary Gregory. o Bump spotbugs from 4.2.3 to 4.3.0 #117. Thanks to Dependabot. o Bump spotbugs-maven-plugin from 4.2.3 to 4.3.0 #118. Thanks to Dependabot. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.8.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.8.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes in this version include: New features ------------ o DBCP-564: Fix BasicManagedDataSource leak of connections opened after transaction is rollback-only #39. Thanks to Florent Guillaume. o DBCP-566: Add clearStatementPoolOnReturn #42. Thanks to Robert Paschek, Gary Gregory, Phil Steitz. o DBCP-559: Add start, restart methods to BasicDataSource. #50. Thanks to Phil Steitz. Fixed Bugs ---------- o DBCP-555: NPE when creating a SQLExceptionList with a null list. Thanks to Gary Gregory. o DBCP-558: Fix DelegatingConnection readOnly and autoCommit caching mechanism #35. Thanks to louislatreille. o Fix regression introduced by unreleased code clean-up #63. Thanks to Sebastian Haas. Changes ------- o Update to PR#36 - PrepareStatement and prepareCall methods are extracted #37. Thanks to DoiMasayuki, Alexander Norz, Gary Gregory. o Mask out user name and password from DriverAdapterCPDS.toString(). Thanks to Gary Gregory. o DBCP-650: Update Apache Commons Pool from 2.7.0 to 2.8.1, #48. Thanks to Gary Gregory, Dependabot. o Update tests from H2 1.4.199 to 1.4.200. Thanks to Gary Gregory. o Update tests from Mockito 3.0.0 to 3.5.11 #47, #60, #64. Thanks to Gary Gregory, Dependabot. o Update tests from jboss-logging 3.4.0.Final to 3.4.1.Final. Thanks to Gary Gregory. o Update tests from narayana-jta 5.9.5.Final to 5.10.6.Final, #61. Thanks to Gary Gregory. o Update tests from junit-jupiter 5.5.1 to 5.7.0 #62. Thanks to Gary Gregory. o Update tests from org.slf4j:slf4j-simple 1.7.26 to 1.7.30. Thanks to Gary Gregory. o Update build from com.github.siom79.japicmp:japicmp-maven-plugin 0.13.1 to 0.14.3. Thanks to Gary Gregory. o Update build from maven-javadoc-plugin 3.1.1 to 3.2.0. Thanks to Gary Gregory. o Update build from maven-pmd-plugin 3.12.0 to 3.13.0. Thanks to Gary Gregory. o Update org.apache.commons:commons-parent from 48 to 51. Thanks to Gary Gregory. o Update jacoco-maven-plugin from 0.8.4 to 0.8.6. Thanks to Gary Gregory. o Update maven-checkstyle-plugin from 3.0.0 to 3.1.1. Thanks to Gary Gregory. o Update actions/checkout from v1 to v2.3.2, #44, #51. Thanks to Dependabot. o Update actions/setup-java from v1.4.0 to v1.4.2 #58. Thanks to Dependabot. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.7.0 RELEASE NOTES 7 July 2019 The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.7.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes in this version include: New features ------------ o DBCP-539: ManagedDataSource#close() should declare used exceptions. Thanks to Jacques Le Roux. o DBCP-547: Add a ConnectionFactory class name setting for BasicDataSource.createConnectionFactory() #33. Thanks to leechoongyon, Gary Gregory. o Add missing Javadocs. Thanks to Gary Gregory. Fixed Bugs ---------- o DBCP-538: Wrong JMX base name derived in BasicDataSource#updateJmxName. Thanks to Ragnar Haugan, Gary Gregory. o DBCP-546: Avoid NPE when calling DriverAdapterCPDS.toString(). Thanks to Sergey Chupov. o DBCP-550: java.util.IllegalFormatException while building a message for a SQLFeatureNotSupportedException in Jdbc41Bridge.getObject(ResultSet,String,Class). Thanks to Gary Gregory. o Fix Javadoc link in README.md #21. Thanks to LichKing-lee. Changes ------- o DBCP-540: Close ObjectOutputStream before calling toByteArray() on underlying ByteArrayOutputStream #28. Thanks to emopers. o DBCP-541: Upgrade to JUnit Jupiter #19. Thanks to Allon Murienik. o DBCP-542: Fix tests on Java 11. Thanks to Zheng Feng, Gary Gregory. o DBCP-543: Update Apache Commons Pool from 2.6.1 to 2.6.2. Thanks to Gary Gregory. o DBCP-529: Add 'jmxName' property to web configuration parameters listing. Thanks to Yuri. o DBCP-548: Update Apache Commons Pool from 2.6.2 to 2.7.0. Thanks to Gary Gregory. o DBCP-549: Make org.apache.commons.dbcp2.AbandonedTrace.removeTrace(AbandonedTrace) null-safe. Thanks to Gary Gregory. o DBCP-551: org.apache.commons.dbcp2.DelegatingStatement.close() should try to close ALL of its result sets even when an exception occurs. Thanks to Gary Gregory. o DBCP-552: org.apache.commons.dbcp2.DelegatingConnection.passivate() should close ALL of its resources even when an exception occurs. Thanks to Gary Gregory. o DBCP-553: org.apache.commons.dbcp2.PoolablePreparedStatement.passivate() should close ALL of its resources even when an exception occurs. Thanks to Gary Gregory. o DBCP-554: org.apache.commons.dbcp2.PoolableCallableStatement.passivate() should close ALL of its resources even when an exception occurs. Thanks to Gary Gregory. o Update tests from org.mockito:mockito-core 2.28.2 to 3.0.0. Thanks to Gary Gregory. o Update tests from H2 1.4.198 to 1.4.199. Thanks to Gary Gregory. o Update tests from com.h2database:h2 1.4.197 to 1.4.199. Thanks to Gary Gregory. o Update tests from org.jboss.narayana.jta:narayana-jta 5.9.2.Final to 5.9.5.Final. Thanks to Gary Gregory. o Update tests from org.jboss.logging:jboss-logging 3.3.2.Final to 3.4.0.Final. Thanks to Gary Gregory. o Update tests from org.mockito:mockito-core 2.24.0 to 2.28.2. Thanks to Gary Gregory. o Update tests from org.mockito:mockito-core 2.28.2 to 3.0.0. Thanks to Gary Gregory. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.6.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.6.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes in this version include: New features ------------ o DBCP-534: Allow for manual connection eviction. Thanks to Peter Wicks. o DBCP-514: Allow DBCP to register with a TransactionSynchronizationRegistry for XA cases. Thanks to Tom Jenkinson, Gary Gregory. o DBCP-519: Add some toString() methods for debugging (never printing passwords.) Thanks to Gary Gregory. o DBCP-527: Add getters to some classes. Thanks to Gary Gregory. o DBCP-528: org.apache.commons.dbcp2.DriverManagerConnectionFactory should use a char[] instead of a String to store passwords. Thanks to Gary Gregory. Fixed Bugs ---------- o DBCP-518: Allow DBCP to work with old Java 6/JDBC drivers without throwing AbstractMethodError. Thanks to Gary Gregory. Changes ------- o DBCP-517: Make defensive copies of char[] passwords. Thanks to Gary Gregory. o DBCP-515: Do not try to register synchronization when the transaction is no longer active. Thanks to Tom Jenkinson, Gary Gregory. o DBCP-516: Do not double returnObject back to the pool if there is a transaction context with a shared connection. Thanks to Tom Jenkinson, Gary Gregory. o DBCP-520: BasicManagedDataSource needs to pass the TSR with creating DataSourceXAConnectionFactory. Thanks to Zheng Feng. o DBCP-537: Update Apache Commons Pool from 2.6.0 to 2.6.1. Thanks to Gary Gregory. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.5.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.5.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements and requires Java 8 or above to support JDBC 4.2. Changes in this version include: New features ------------ o DBCP-506: Support JDBC 4.2. Thanks to Gary Gregory. o DBCP-479: Support default schema in configuration. Thanks to Guillaume Husta, Gary Gregory. Fixed Bugs ---------- o DBCP-508: Prepared statement keys should take a Connection's schema into account. Thanks to Gary Gregory. o DBCP-512: Avoid exceptions when closing a connection in mutli-threaded use case. Thanks to Gary Gregory. Changes ------- o DBCP-505: Update Java requirement from version 7 to 8. Thanks to Gary Gregory. o DBCP-427: Examines 'SQLException's thrown by underlying connections or statements for fatal (disconnection) errors. Thanks to Vladimir Konkov, Phil Steitz, Gary Gregory. o DBCP-507: Change default for fail-fast connections from false to true. Thanks to Vladimir Konkov, Phil Steitz, Gary Gregory. o DBCP-504: Increase test coverage. Thanks to Bruno P. Kinoshita. o DBCP-510: Update Apache Commons Pool from 2.5.0 to 2.6.0. Thanks to Gary Gregory. Note that Clirr incorrectly reports one binary incompatible change because it is not aware of Java 8 and default methods: [ERROR] 7012: org.apache.commons.dbcp2.BasicDataSourceMXBean: Method 'public java.lang.String getDefaultSchema()' has been added to an interface For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Download page: https://commons.apache.org/dbcp/download_dbcp.cgi Apache Commons DBCP Version 2.4.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.4.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements, which you can download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi Changes in this version include: Fixed Bugs ---------- o DBCP-484: Connection leak during XATransaction in high load. Thanks to Emanuel Freitas. o DBCP-496: Add support for pooling CallableStatements to the org.apache.commons.dbcp2.cpdsadapter package. Thanks to Gary Gregory. Changes ------- o DBCP-492: Drop Ant build. Thanks to Gary Gregory. o DBCP-491: Ensure DBCP ConnectionListener can deal with transaction managers which invoke rollback in a separate thread. Thanks to Zheng Feng, Gary Gregory. o DBCP-494: org.apache.commons.dbcp2.PStmtKey should make copies of given arrays in constructors. Thanks to Gary Gregory. o DBCP-495: Remove duplicate code in org.apache.commons.dbcp2.cpdsadapter.PStmtKeyCPDS. Thanks to Gary Gregory. o DBCP-497: Deprecate use of PStmtKeyCPDS in favor of PStmtKey. Thanks to Gary Gregory. o DBCP-498: org.apache.commons.dbcp2.DataSourceConnectionFactory should use a char[] instead of a String to store passwords. Thanks to Gary Gregory. o DBCP-499: org.apache.commons.dbcp2.managed.DataSourceXAConnectionFactory should use a char[] instead of a String to store passwords. Thanks to Gary Gregory. o DBCP-500: org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS should use a char[] instead of a String to store passwords. Thanks to Gary Gregory. o DBCP-501: org.apache.commons.dbcp2.datasources.CPDSConnectionFactory should use a char[] instead of a String to store passwords. Thanks to Gary Gregory. o DBCP-502: org.apache.commons.dbcp2.datasources internals should use a char[] instead of a String to store passwords. Thanks to Gary Gregory. o DBCP-503: org.apache.commons.dbcp2.datasources.InstanceKeyDataSourceFactory.closeAll() does not close all. Thanks to Gary Gregory. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.3.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.3.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes in this version include: Fixed Bugs ---------- o DBCP-476: AbandonedTrace.getTrace() contains race condition Thanks to Gary Evesson, Richard Cordova. o DBCP-482: Avoid javax.management.InstanceNotFoundException on shutdown when a bean is not registered. Thanks to Dennis Lloyd, Gary Gregory. Changes ------- o DBCP-483: Make constant public: org.apache.commons.dbcp2.PoolingDriver.URL_PREFIX. Thanks to Gary Gregory. o DBCP-486: DriverAdapterCPDS.setUser(), setPassword(), and getPooledConnection() with null arguments throw NullPointerExceptions when connection properties are set. Thanks to Gary Gregory. o DBCP-487: Add API org.apache.commons.dbcp2.datasources.PerUserPoolDataSource.clear(). Thanks to Gary Gregory. o DBCP-488: NPE for org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS.setConnectionProperties(null). Thanks to Gary Gregory. o DBCP-490: The method org.apache.commons.dbcp2.PoolingDriver.getConnectionPool(String) does not tell you which pool name is not registered when it throws an exception. Thanks to Gary Gregory. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.2.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.2.0. Apache Commons DBCP software implements Database Connection Pooling. This is a minor release, including bug fixes and enhancements. Changes in this version include: New features ------------ o DBCP-451: Add constructor DriverManagerConnectionFactory(String). o DBCP-462: Refactoring to prepare for a future patch to enable pooling of all prepared and callable statements in PoolingConnection. Thanks to Keiichi Fujino. o DBCP-458: Make it simpler to extend BasicDataSource to allow sub-classes to provide custom GenericObjectPool implementations. Thanks to Adrian Tarau. o DBCP-474: Enable pooling of all prepared and callable statements inPoolingConnection. Thanks to Keiichi Fujino. Fixed Bugs ---------- o DBCP-481: Update Apache Commons Pool from 2.4.2 to 2.5.0. Thanks to Gary Gregory. o DBCP-454: OSGi declarations contain multiple import headers for javax.transaction. Thanks to Philipp Marx, Matt Sicker. o DBCP-478: Wrong parameter name in site documentation for BasicDataSource Configuration Parameters. Thanks to nicola mele. o DBCP-452: Add jmxName to properties set by BasicDataSourceFactory. This enables container-managed pools created from JNDI Resource definitions to enable JMX by supplying a valid root JMX name. o DBCP-446: NullPointerException thrown when calling ManagedConnection.isClosed(). Thanks to Gary Gregory, feng yang, Euclides M, Phil Steitz. o DBCP-444: InvalidateConnection can result in closed connection returned by getConnection. o DBCP-449: Complete the fix for DBCP-418, enabling PoolableConnection class to load in environments (such as GAE) where the JMX ManagementFactory is not available. Thanks to Grzegorz D.. o DBCP-455: Ensure that the cacheState setting is used when statement pooling is disabled. Thanks to Kyohei Nakamura. o DBCP-453: Ensure that setSoftMinEvictableIdleTimeMillis is used when working with BasicDataSource. Thanks to Philipp Marx. o DBCP-456: Correct the name of the configuration attribute softMinEvictableIdleTimeMillis. Thanks to Kyohei Nakamura. o DBCP-472: Avoid potential infinite loops when checking if an SQLException is fatal for a connection or not. o DBCP-468: Expand the fail-fast for fatal connection errors feature to include managed connections. o DBCP-463: Correct a typo in the method name PoolableConnectionFactory#setMaxOpenPreparedStatements. The old method remains but is deprecated so not to break clients currently using the incorrect name. o DBCP-459: Ensure that a thread's interrupt status is visible to the caller if the thread is interrupted during a call to PoolingDataSource.getConnection(). o DBCP-457: When using a BasicDataSource, pass changes related to the handling of abandoned connections to the underlying pool so that the pool configuration may be updated dynamically. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Commons DBCP Version 2.1.1 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.1.1. Apache Commons DBCP software implements Database Connection Pooling. This is a patch release, including bug fixes only. Changes in this version include: Fixed Bugs ---------- o DBCP-441: Added BasicDataSource abandonedUsageTracking property missing from BasicDataSourceFactory. o DBCP-442: SharedPoolDataSource getConnection fails when testOnBorrow is set with a null validation query. o DBCP-438: Nested connections in a transaction (local) throws null pointer. Thanks to Raihan Kibria. o DBCP-437: BasicDataSource does not set disconnectionSql properties on its PoolableConnectionFactory. Changes ------- o Updated pool version to 2.4.2. The fix for POOL-300 may cause DBCP users to see more reports of abandoned connections (if removal and logging are configured). Prior to the fix for POOL-300, the PrintWriter used to log abandoned connection stack traces was not being flushed on each log event. For complete information on Apache Commons DBCP, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi commons-dbcp-rel-commons-dbcp-2.13.0/SECURITY.md000066400000000000000000000016041472045345700211220ustar00rootroot00000000000000 The Apache Commons security page is [https://commons.apache.org/security.html](https://commons.apache.org/security.html). commons-dbcp-rel-commons-dbcp-2.13.0/dbcp-RC.sh000077500000000000000000000044621472045345700211070ustar00rootroot00000000000000#!/bin/sh # # 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. # ----------------------------------------------------------------------------- # Generates a dbcp RC and publishes (a superset of) maven artifacts to Nexus. # Should be run from top-level directory of a fresh checkout of the RC tag. # # Preconditions: # 0) dbcp-pre-RC has been run to update the download page and release notes # and these have been checked in and included in the RC tag. # 1) Release artifacts from previous runs have been svn deleted from local # svn pub/sub dev checkout. # 2) Nexus repo from previous RC has been dropped. # # ----------------------------------------------------------------------------- # Set script variables version=2.4.0 repo_path=~/.m2/repository/org/apache/commons/commons-dbcp2/${version} release_path=~/dbcp-rc #checkout of https://dist.apache.org/repos/dist/dev/commons/dbcp # # Delete any locally installed artifacts from previous runs rm -rf ${repo_path} echo "Cleaned maven repo." # # Generate site and release artifacts, deploy locally and upload to Nexus mvn clean site mvn deploy -Prelease # # Copy the zips/tarballs and release notes to the local svn pub path cp ${repo_path}/*bin.zip* ${release_path}/binaries cp ${repo_path}/*bin.tar.gz* ${release_path}/binaries cp ${repo_path}/*src.zip* ${release_path}/source cp ${repo_path}/*src.tar.gz* ${release_path}/source cp RELEASE-NOTES.txt ${release_path} echo "Release candidate complete." echo "svn add the generated artifacts and commit after inspection." echo "log in to repository.apache.org, manually (sic) drop the cruft and close the repo." commons-dbcp-rel-commons-dbcp-2.13.0/dbcp-pre-RC.sh000077500000000000000000000026201472045345700216650ustar00rootroot00000000000000#!/bin/sh # # 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. # ----------------------------------------------------------------------------- # # Shell script to update download page and release notes prior # to preparing a commons dbcp release candidate. # # Note: RELEASE-NOTES.txt may need a little reformatting prior # to checkin. Both RELEASE-NOTES.txt and the generated download # page need to be checked in after review. # # ---------------------------------------------------------------------------- version=2.4.0 mvn changes:announcement-generate -Prelease-notes -Dchanges.version=${version} mvn commons:download-page -Dcommons.componentid=dbcp -Dcommons.release.version=${version} commons-dbcp-rel-commons-dbcp-2.13.0/dbcp-release.sh000077500000000000000000000050721472045345700222210ustar00rootroot00000000000000#!/bin/sh # # 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. # ----------------------------------------------------------------------------- # Performs the local svn steps necessary to publish a dbcp release. # # Preconditions: # 0) Successful release VOTE has completed, based on artifacts in rc_path # (checkout of https://dist.apache.org/repos/dist/dev/commons/dbcp) # 1) release_path points to a local checkout of # https://dist.apache.org/repos/dist/release/commons/dbcp # 2) RELEASE-NOTES.txt for the new release is in top level of rc_path # # NOTE: This script does not do any of the following: # 0) Commit the local changes to actually publish the artifacts # 1) Cleanup old versions in dist # # ----------------------------------------------------------------------------- # Set script variables version=2.4.0 # version being released last_version=2.3.0 # previous version, will be replaced in README.html rc_path=~/dbcp-rc # checkout of https://dist.apache.org/repos/dist/dev/commons/dbcp release_path=~/dbcp-release #https://dist.apache.org/repos/dist/release/commons/dbcp # # Move release notes cp $rc_path/RELEASE-NOTES.txt $release_path svn rm $rc_path/RELEASE-NOTES.txt # # Update README.html sed -i "" "s/$last_version/$version/g" $release_path/README.html # OSX ^^ required suffix # # DBCP uses symlinks, so below not needed unless this changes. #cp $release_path/README.html $release_path/source #cp $release_path/README.html $release_path/binaries # ^^^^^^^^^^ Maybe we can toss these? ^^^^^^^ # # Move release artifacts svn mv $rc_path/source/* $release_path/source svn mv $rc_path/binaries/* $release_path/binaries # echo "Local svn changes complete." echo "Inspect the files in $release_path and commit to publish the release." echo "Also remember to commit $rc_path to drop RC artifacts and svn rm" echo "obsolete artifacts from $release_path." commons-dbcp-rel-commons-dbcp-2.13.0/doc/000077500000000000000000000000001472045345700200755ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/doc/BasicDataSourceExample.java000066400000000000000000000106621472045345700252550ustar00rootroot00000000000000/* * 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. */ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.sql.DataSource; // // Here are the dbcp-specific classes. // Note that they are only used in the setupDataSource // method. In normal use, your classes interact // only with the standard JDBC API // import org.apache.commons.dbcp2.BasicDataSource; // // Here's a simple example of how to use the BasicDataSource. // // // Note that this example is very similar to the PoolingDriver // example. // // To compile this example, you'll want: // * commons-pool-2.3.jar // * commons-dbcp-2.1.jar // in your classpath. // // To run this example, you'll want: // * commons-pool-2.3.jar // * commons-dbcp-2.1.jar // * commons-logging-1.2.jar // in your classpath. // // // Invoke the class using two arguments: // * the connect string for your underlying JDBC driver // * the query you'd like to execute // You'll also want to ensure your underlying JDBC driver // is registered. You can use the "jdbc.drivers" // property to do this. // // For example: // java -Djdbc.drivers=org.h2.Driver \ // -classpath commons-pool2-2.3.jar:commons-dbcp2-2.1.jar:commons-logging-1.2.jar:h2-1.3.152.jar:. \ // BasicDataSourceExample \ // "jdbc:h2:~/test" \ // "SELECT 1" // public class BasicDataSourceExample { public static void main(String[] args) { // First we set up the BasicDataSource. // Normally this would be handled auto-magically by // an external configuration, but in this example we'll // do it manually. // System.out.println("Setting up data source."); DataSource dataSource = setupDataSource(args[0]); System.out.println("Done."); // // Now, we can use JDBC DataSource as we normally would. // Connection conn = null; Statement stmt = null; ResultSet rset = null; try { System.out.println("Creating connection."); conn = dataSource.getConnection(); System.out.println("Creating statement."); stmt = conn.createStatement(); System.out.println("Executing statement."); rset = stmt.executeQuery(args[1]); System.out.println("Results:"); int numcols = rset.getMetaData().getColumnCount(); while(rset.next()) { for(int i=1;i<=numcols;i++) { System.out.print("\t" + rset.getString(i)); } System.out.println(""); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rset != null) rset.close(); } catch (Exception e) { } try { if (stmt != null) stmt.close(); } catch (Exception e) { } try { if (conn != null) conn.close(); } catch (Exception e) { } } } public static DataSource setupDataSource(String connectURI) { BasicDataSource ds = new BasicDataSource(); ds.setDriverClassName("org.h2.Driver"); ds.setUrl(connectURI); return ds; } public static void printDataSourceStats(DataSource ds) { BasicDataSource bds = (BasicDataSource) ds; System.out.println("NumActive: " + bds.getNumActive()); System.out.println("NumIdle: " + bds.getNumIdle()); } public static void shutdownDataSource(DataSource ds) throws SQLException { BasicDataSource bds = (BasicDataSource) ds; bds.close(); } } commons-dbcp-rel-commons-dbcp-2.13.0/doc/PoolingDataSourceExample.java000066400000000000000000000143701472045345700256430ustar00rootroot00000000000000/* * 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. */ import javax.sql.DataSource; import java.sql.Connection; import java.sql.Statement; import java.sql.ResultSet; import java.sql.SQLException; // // Here are the dbcp-specific classes. // Note that they are only used in the setupDataSource // method. In normal use, your classes interact // only with the standard JDBC API // import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.dbcp2.ConnectionFactory; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolingDataSource; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.DriverManagerConnectionFactory; // // Here's a simple example of how to use the PoolingDataSource. // // // Note that this example is very similar to the PoolingDriver // example. In fact, you could use the same pool in both a // PoolingDriver and a PoolingDataSource // // // To compile this example, you'll want: // * commons-pool2-2.3.jar // * commons-dbcp2-2.1.jar // in your classpath. // // To run this example, you'll want: // * commons-pool2-2.3.jar // * commons-dbcp2-2.1.jar // * commons-logging-1.2.jar // * the classes for your (underlying) JDBC driver // in your classpath. // // Invoke the class using two arguments: // * the connect string for your underlying JDBC driver // * the query you'd like to execute // You'll also want to ensure your underlying JDBC driver // is registered. You can use the "jdbc.drivers" // property to do this. // // For example: // java -Djdbc.drivers=org.h2.Driver \ // -classpath commons-pool2-2.3.jar:commons-dbcp2-2.1.jar:commons-logging-1.2.jar:h2-1.3.152.jar:. \ // PoolingDataSourceExample \ // "jdbc:h2:~/test" \ // "SELECT 1" // public class PoolingDataSourceExample { public static void main(String[] args) { // // First we load the underlying JDBC driver. // You need this if you don't use the jdbc.drivers // system property. // System.out.println("Loading underlying JDBC driver."); try { Class.forName("org.h2.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println("Done."); // // Then, we set up the PoolingDataSource. // Normally this would be handled auto-magically by // an external configuration, but in this example we'll // do it manually. // System.out.println("Setting up data source."); DataSource dataSource = setupDataSource(args[0]); System.out.println("Done."); // // Now, we can use JDBC DataSource as we normally would. // Connection conn = null; Statement stmt = null; ResultSet rset = null; try { System.out.println("Creating connection."); conn = dataSource.getConnection(); System.out.println("Creating statement."); stmt = conn.createStatement(); System.out.println("Executing statement."); rset = stmt.executeQuery(args[1]); System.out.println("Results:"); int numcols = rset.getMetaData().getColumnCount(); while(rset.next()) { for(int i=1;i<=numcols;i++) { System.out.print("\t" + rset.getString(i)); } System.out.println(""); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rset != null) rset.close(); } catch (Exception e) { } try { if (stmt != null) stmt.close(); } catch (Exception e) { } try { if (conn != null) conn.close(); } catch (Exception e) { } } } public static DataSource setupDataSource(String connectURI) { // // First, we'll create a ConnectionFactory that the // pool will use to create Connections. // We'll use the DriverManagerConnectionFactory, // using the connect string passed in the command line // arguments. // ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectURI, null); // // Next we'll create the PoolableConnectionFactory, which wraps // the "real" Connections created by the ConnectionFactory with // the classes that implement the pooling functionality. // PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null); // // Now we'll need a ObjectPool that serves as the // actual pool of connections. // // We'll use a GenericObjectPool instance, although // any ObjectPool implementation will suffice. // ObjectPool connectionPool = new GenericObjectPool<>(poolableConnectionFactory); // Set the factory's pool property to the owning pool poolableConnectionFactory.setPool(connectionPool); // // Finally, we create the PoolingDriver itself, // passing in the object pool we created. // PoolingDataSource dataSource = new PoolingDataSource<>(connectionPool); return dataSource; } } commons-dbcp-rel-commons-dbcp-2.13.0/doc/PoolingDriverExample.java000066400000000000000000000166451472045345700250530ustar00rootroot00000000000000/* * 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. */ import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.apache.commons.dbcp2.ConnectionFactory; import org.apache.commons.dbcp2.DriverManagerConnectionFactory; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.PoolingDriver; // // Here are the dbcp-specific classes. // Note that they are only used in the setupDriver // method. In normal use, your classes interact // only with the standard JDBC API // import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool; // // Here's a simple example of how to use the PoolingDriver. // // To compile this example, you'll want: // * commons-pool-2.3.jar // * commons-dbcp-2.1.jar // in your classpath. // // To run this example, you'll want: // * commons-pool-2.3.jar // * commons-dbcp-2.1.jar // * commons-logging-1.2.jar // in your classpath. // // Invoke the class using two arguments: // * the connect string for your underlying JDBC driver // * the query you'd like to execute // You'll also want to ensure your underlying JDBC driver // is registered. You can use the "jdbc.drivers" // property to do this. // // For example: // java -Djdbc.drivers=org.h2.Driver \ // -classpath commons-pool2-2.3.jar:commons-dbcp2-2.1.jar:commons-logging-1.2.jar:h2-1.3.152.jar:. \ // PoolingDriverExample \ // "jdbc:h2:~/test" \ // "SELECT 1" // public class PoolingDriverExample { public static void main(String[] args) { // // First we load the underlying JDBC driver. // You need this if you don't use the jdbc.drivers // system property. // System.out.println("Loading underlying JDBC driver."); try { Class.forName("org.h2.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println("Done."); // // Then we set up and register the PoolingDriver. // Normally this would be handled auto-magically by // an external configuration, but in this example we'll // do it manually. // System.out.println("Setting up driver."); try { setupDriver(args[0]); } catch (Exception e) { e.printStackTrace(); } System.out.println("Done."); // // Now, we can use JDBC as we normally would. // Using the connect string // jdbc:apache:commons:dbcp:example // The general form being: // jdbc:apache:commons:dbcp: // Connection conn = null; Statement stmt = null; ResultSet rset = null; try { System.out.println("Creating connection."); conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:example"); System.out.println("Creating statement."); stmt = conn.createStatement(); System.out.println("Executing statement."); rset = stmt.executeQuery(args[1]); System.out.println("Results:"); int numcols = rset.getMetaData().getColumnCount(); while(rset.next()) { for(int i=1;i<=numcols;i++) { System.out.print("\t" + rset.getString(i)); } System.out.println(""); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rset != null) rset.close(); } catch (Exception e) { } try { if (stmt != null) stmt.close(); } catch (Exception e) { } try { if (conn != null) conn.close(); } catch (Exception e) { } } // Display some pool statistics try { printDriverStats(); } catch (Exception e) { e.printStackTrace(); } // closes the pool try { shutdownDriver(); } catch (Exception e) { e.printStackTrace(); } } public static void setupDriver(String connectURI) throws Exception { // // First, we'll create a ConnectionFactory that the // pool will use to create Connections. // We'll use the DriverManagerConnectionFactory, // using the connect string passed in the command line // arguments. // ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectURI, null); // // Next, we'll create the PoolableConnectionFactory, which wraps // the "real" Connections created by the ConnectionFactory with // the classes that implement the pooling functionality. // PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null); // // Now we'll need a ObjectPool that serves as the // actual pool of connections. // // We'll use a GenericObjectPool instance, although // any ObjectPool implementation will suffice. // ObjectPool connectionPool = new GenericObjectPool<>(poolableConnectionFactory); // Set the factory's pool property to the owning pool poolableConnectionFactory.setPool(connectionPool); // // Finally, we create the PoolingDriver itself... // Class.forName("org.apache.commons.dbcp2.PoolingDriver"); PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:"); // // ...and register our pool with it. // driver.registerPool("example", connectionPool); // // Now we can just use the connect string "jdbc:apache:commons:dbcp:example" // to access our pool of Connections. // } public static void printDriverStats() throws Exception { PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:"); ObjectPool connectionPool = driver.getConnectionPool("example"); System.out.println("NumActive: " + connectionPool.getNumActive()); System.out.println("NumIdle: " + connectionPool.getNumIdle()); } public static void shutdownDriver() throws Exception { PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:"); driver.closePool("example"); } } commons-dbcp-rel-commons-dbcp-2.13.0/doc/README.txt000066400000000000000000000027071472045345700216010ustar00rootroot00000000000000=================================================================================== Before running these examples make sure you have registered the database driver you want to use. If you don't you will get the following error: "org.apache.commons.dbcp2.DbcpException: java.sql.SQLException: No suitable driver" The DriverManager class will attempt to load the driver classes referenced in the "jdbc.drivers" system property. For example you might specify -Djdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver as command line argument to the java VM. A program can also explicitly load JDBC drivers at any time. For example, the my.sql.Driver is loaded with the following statement: Class.forName("my.sql.Driver"); =================================================================================== PoolingDriverExample.java Provides a simple example of how to use the DBCP package with a PoolingDriver. Look at the comments with that file for instructions on how to build and run it. PoolingDataSource.java Provides a simple example of how to use the DBCP package with a PoolingDataSource. Look at the comments with that file for instructions on how to build and run it. See also the Javadoc documentation (use "ant doc" to generate it), especially the package documentation for org.apache.commons.dbcp for an overview of how it all works. The test cases (the source files whose names start with "Test") provide some additional examples. commons-dbcp-rel-commons-dbcp-2.13.0/doc/abandon.jsp000066400000000000000000000111201472045345700222100ustar00rootroot00000000000000 Couldn't build an initial context : " + e); return null; } try { Object value = ctx.lookup("java:/comp/env/jdbc/abandoned"); out.println("
DataSource lookup"); out.println("
jdbc value : " + value); out.println("
jdbc class : " + value.getClass().getName()); out.println("
"); if (value instanceof DataSource) { return (DataSource) value; } else { return null; } } catch (NamingException e) { out.println("
JNDI lookup failed : " + e); return null; } } private void getConnection1(DataSource ds, JspWriter out) throws Exception { System.err.println("BEGIN getConnection1()"); out.println("
BEGIN getConnection1()"); Connection conn = ds.getConnection(); System.err.println("conn: " + conn); out.println("
conn: " + conn); System.err.println("END getConnection1()"); out.println("
END getConnection1()"); } private void getConnection2(DataSource ds, JspWriter out) throws Exception { System.err.println("BEGIN getConnection2()"); out.println("
BEGIN getConnection2()"); Connection conn = ds.getConnection(); System.err.println("conn: " + conn); out.println("
conn: " + conn); System.err.println("END getConnection2()"); out.println("
END getConnection2()"); } private void getConnection3(DataSource ds, JspWriter out) throws Exception { System.err.println("BEGIN getConnection3()"); out.println("
BEGIN getConnection3()"); Connection conn = ds.getConnection(); System.err.println("conn: " + conn); out.println("
conn: " + conn); System.err.println("END getConnection3()"); out.println("
END getConnection3()"); } ]]>
DBCP Abandoned Connection Test

DBCP Abandoned Connection Test


DataSource ds = getDataSource(out); if (ds != null) { getConnection1(ds, out); getConnection2(ds, out); getConnection3(ds, out); }

OK
commons-dbcp-rel-commons-dbcp-2.13.0/doc/static_structure_dia.gif000066400000000000000000000236431472045345700250200ustar00rootroot00000000000000GIF89a#@ ` @ @@@`@@@@@` `@``````` @` @` @` @`@ @@@`@@@@@ @ @@ @` @ @ @ @ @@@ @@@@@`@@@@@@@@@@`@ `@@`@``@`@`@`@`@@ @@@`@@@@@@ @@@`@@@@@@ @@@`@@@@@@ @@@`@@@@@ @` @ ` @ @@@`@@@@@` `@``````` @` @`ࠀ @` @` @` @ ` @ @@@`@@@@@` `@``````` @` @` @`𠠤!,#@ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗ƌ)pA q>YR˟@obQGw:0EFA JիXj:5b׏>6@Vֳ ͪT%۶pʝKҦ2Y^5m7< &};K1Ę{w0əg82d~IW|y2{VxymmÜ N8Ȯo+4УKN^νO^{ӫ_v;#ßO}돺B_"U&J.x`F(AH^vx~(vω(,0(4h!hނ&@)7O=9d=(%QJeVfPZ|Mّy^_bd=Wg\rfSz ']Y$砄jf2$衐F*韋VjxkM馜R*m}V5du*p 묨¨ӘEꮼ꒩ =Z. N(l6;#vmJU7Pf-ƵlLƪ뜲'nfFfN^{rY Ӥ‹n+k +op}ڋ_t0*1wLt{,$2I',#H/,4i\ϼL(M+FJ'mt_M=8{lնןɖZl1Q\{Vm`a - ^m3| U7x9vm{U,؆YFAq^ڠw= h6v梡沅:䗫6۩O8j;?{A̧uzG/ɷ =g}xwqƖI}6 ֟.y?, ;)Mj׺xzWF5%3XIUd4Ah'9..)xP8 E%@NH"8=<DP"(*Z{T|Ph+zAY΀57i&&p+ڈF;QPmJc %}.HH!F:r9N$IJ̤&mXNJx(Y4Mz@MhVɍ[G(+]FPpe (WqkڻL"ҔV(7PNτ6mz '8INe]L:Aڱ_[ .z:IgJSS"IP1: P,$Jъ.AF7zo^$F$κq,3KF'ǡkߜ.4qLyS`6Y{PtS4WLj,F<6#Z)S!"*W(g]Ymz԰5sjiP Ցb^j䔨ezVnl*R:y},E#+3JSbF0` 8N3FLy$gh4--be+:֦SHZt]*/pK ՑFK>SgAR.% .[t׆)#[P|7h%z3Y|ߋ̾(~ 0`_>! "4KɔQJe<rЖzmdN A_.pNs 2Eܩ ¢DNڸq c y-B0&.vі\eg(GN'\"g\梗#VWas)DQ 3&>l4Ҍz*`٪H l7p]qL)&tלfNd&tQӝ>-RԦNiZ\Oj*U[կ7O .'>bCo塡L)A*bu]jTmZְiVnO[;ݧ TdOw_u<؎[Fwgo bzuYUHZ Ox[ӑ7iǰhx(N}Wײ].sK~Dlny(tfJOv͓Ys{;D% lb9@ M/zl`Q/= 򵟯n_ʵYk۽ӽ9R}]Agl`|b'w5>ɜջ2OvSyBgړQ._` Yi2~! ڧ,iŗG~;OR5w~Elxw\=?c?7sYN.vt8}Kw@ hKPa3.w~}w81S"j5&4o\EZR[߶VQFXY1UV[w{'^9\*hm>ER%!yPS866,(pXZ4heUVpm@ՂQxEjX2Gx;a98Tns9SnsmA~d2(CWpS;8pss8Up;?8F޴]e䅉‰Ȇ5[ms[YU(WHYo&Kh48T]8o1/3%FbW9ÌU[nu6xx&7USVoȸ8c[_TnSp8qk%"0U%Lju8㘌<;qm);IY Y;׌w:cVhE[ֈVf8f=en؋:[s,y3؎Ȓuu;oX2ZՓ)p< 趂1iwLQb!e]Q QTWI`֕^ca9"Xwe~햖%l k E&H{vyxDG|i\Pf9p=(!duDVZ3u)o6کP:Ҫ: v貎Kˠ;KiC[c)&׹Z_񤭀 *F5C-ڡ}_rBr#Z'kt麴WZ?Gy t};wx$O yԷy7+t1ܷr$ xˢ&~v6rlFO4Z[Cͅ . k>\Q{0Z&Y~˸$LOX(|,lR0|1LHdzg]ۜTŁ^gĩdjƱ{nBqzl|ǢYMzg |,~ۺOʷ+ɝ+BZ}NKg' \Z|y*GKc˜e,{Oܘ+(D8Rʰ ,T {mTq ΅j\ZR蜖sܗI++2Xl$<0pttOv4ilrt =W'۽,gsKgLdэ:P]D=z+-r 1=7]6B^D]ڕGc VL%)ptx69kŊFI=4y/Ի]#cHَ]ȏpdρ Vcuw^6՘C鳯:^K# x}I^[]MɕqocX ֏}٘HGqkmHYPTX8U&AP*ZԸعؼi5ѭas݌+M\!E\ܽ`-nճbGY5},F6S:iX6ߍXd{ލ\qWᾼ 2.F#9F RbYlֽ\%('T*ɍHnߪUHַNǘ iz*7_abM޳F|-kۮQڤj5p퓊.x_ 5NJl# nk11 \k)km.8 ;낏/#9IdGi}գa3V)+y?؈ tƝt͏=9Z۸֥oESv퓮.`2eX83I2$@2x\NHJXWRIT_2\Q^gb#ZeojKOlnprq_&x/|~O}/džU/9?*q{D?fX`XO2}c\>Q)!ߦϙ/Yk&ȟJZcLef[,힠ڨ_ڽhvJa$Ҍf}oYkulTʛ Y 0`A*40!‡ "pE5nؑ`?$YdH)U)K1eΤYM9ueODF+"ԩELJ'PYnҪa lS!'j"[b5Ux_1n9װAuhZl2VK1Ùq5\V4i\kرegm tjaol]q޿*sׯw#^zRٵs~䰙o'_goyC_]}J 4@#0/tPiKpB +B 3)B{C8JD K4DST'Y[IkFs a챣1 }kP9qI&txŧ k"*{G:2NJJ24L4}*<ȴ 2((rP0C3M>%C$"S4D%:<sO@+RL ԦG?GTtӖ25TTST>U͐dUUkVLiUX{KWpvXb% XxuP3YhٗeZeI[iEZl}K<Uw]\vEr13yOw_ܵ^~}z%ā xl`$3;87:eW˓=+>M]$v/˒"NdD([{Sg޲-.Y~$EĎ!6rˠ1l1Dz3wSh+rl$˪t;)g6ZydQˇԶZ-ў3NZ!dD ɶnLC|[1%.ҙSE}qlLW?u.0IBw6vNuWЎ>}y7C^ꗇa{Ad}|3Dq^|Qw_Px@&P2@Ft`-x&`=AM#$a %BP+,CBP+rfxCA5 }C A$b&Kdb;D;IDH?(J_Th,nEQ xF脱7q{ZFȂ2 (]j>WF݋5PǭRcn %Dv)pQIY*w% -.Y"9Ar`z~G1$ؽ> *)]Mѕ,e-GA9:Eqm YfwaZQelIW.ml%+IW攱UhiiRlf.Kq✣:v\;+ F¢VP*LWkڜK0rl8W=ܮx n^޳[b+bGrmqZwCk%UJ].[[^)piF 5]Բ 5*zĿS2Zl8YR2`NI0| a`5 ]M|#Ά-%>qiXݒX34Icݡ}c!8@&rGYKyd(Gy4M|eQXrC7b/kx\Zfb@2לN5V͂\lᐙqXihH٢mQTqJlמW x)x >:Cg^;Mod^w)LYzƱ}%d^)})'~{g_|'W~E_G?̗~H}g}' _~g? ~ڄ.W>3 ;GC41t4ES@Vİ۴Y\ }I@]7^3˒ A7@ 9yAO3{[vg8[97b9k[6}ct@Gqts8ABxS8B$̠ ؍$B\)C$ C1,3T04YC6lC%:tA?C@ DADB,DC<@1CElyÿDG ?IICLDaDNwDP-#J$;EBEVQlEX4UXxE[/CD^E_E` 9yFcmҪʊTY5A*mU.TuVpT&/z/q jU:*VaEauTJWUJBUX꒩dVWD2)|-؜2Ve=ׅWQ:f YR,l-WY'ZEZjUY-%YوEUZَ]ZD-ESURڙZZa Z:VyPE֣SUx-(UbWe`ݯME׸su?0%S\M8z!Tm\B&J1Ow=+L/Uی%L\eEXeʍY]ۻS%REX`=]^{% wL^\C6\mJX֢^L۪uW}Z ڦ^=]Z X-߳տmO[,Oۺ*>%]f_eAܜ!~` ? ;commons-dbcp-rel-commons-dbcp-2.13.0/pom.xml000066400000000000000000000431121472045345700206460ustar00rootroot00000000000000 org.apache.commons commons-parent 78 4.0.0 commons-dbcp2 2.13.0 Apache Commons DBCP 2001 Apache Commons DBCP software implements Database Connection Pooling https://commons.apache.org/proper/commons-dbcp/ apache.website Apache Commons Site scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-dbcp/ jira https://issues.apache.org/jira/browse/DBCP scm:git:http://gitbox.apache.org/repos/asf/commons-dbcp.git scm:git:https://gitbox.apache.org/repos/asf/commons-dbcp.git https://gitbox.apache.org/repos/asf?p=commons-dbcp.git org.apache.commons commons-pool2 ${commons.pool.version} commons-logging commons-logging 1.3.4 org.junit.jupiter junit-jupiter test org.mockito mockito-core 4.11.0 test org.apache.commons commons-lang3 3.17.0 test jakarta.transaction jakarta.transaction-api 1.3.3 tomcat naming-common 5.0.28 test tomcat naming-java 5.0.28 test org.apache.geronimo.modules geronimo-transaction 2.2.1 test org.junit.jupiter junit-jupiter commons-logging commons-logging org.slf4j slf4j-simple 2.0.16 test com.h2database h2 2.2.224 test org.jboss.narayana.jta narayana-jta 5.12.7.Final test org.jboss jboss-transaction-spi 8.0.0.Final org.jboss.logging jboss-logging-spi test org.jboss.logging jboss-logging 3.4.3.Final test UTF-8 UTF-8 2024-11-23T22:28:37Z 1.8 1.8 dbcp RC1 org.apache.commons.dbcp2 2.13.0 2.13.1 for JDBC 4.2 on Java 8 sha512 2.4.0 for JDBC 4.1 on Java 7 sha256 dbcp https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-dbcp site-content DBCP 12310469 2.12.0 javax.transaction;version="1.1.0",javax.transaction.xa;version="1.1.0";partial=true;mandatory:=partial,* true 2.12.0 true false false true 0.5.5 true 0.98 0.74 0.89 0.66 0.62 0.78 clean verify apache-rat:check japicmp:cmp checkstyle:check spotbugs:check pmd:check pmd:cpd-check javadoc:javadoc org.apache.maven.plugins maven-scm-publish-plugin ${commons.scm-publish.version} javadocs org.apache.maven.plugins maven-checkstyle-plugin ${commons.checkstyle-plugin.version} ${basedir}/src/conf/checkstyle.xml false com.github.spotbugs spotbugs-maven-plugin ${basedir}/src/conf/spotbugs-exclude-filter.xml org.apache.maven.plugins maven-javadoc-plugin ${commons.javadoc.version} https://commons.apache.org/proper/commons-pool/apidocs ${commons.javadoc.javaee.link} org.apache.maven.plugins maven-surefire-plugin ${argLine} ${surefire.argline} **/Tester*.java **/Test*$*.java maven-assembly-plugin src/main/assembly/bin.xml src/main/assembly/src-tar-gz.xml src/main/assembly/src-zip.xml gnu org.apache.maven.plugins maven-scm-publish-plugin api-* org.apache.maven.plugins maven-javadoc-plugin com.github.siom79.japicmp japicmp-maven-plugin cmp-report true ${commons.japicmp.breakBuildOnBinaryIncompatibleModifications} true true true ${commons.japicmp.ignoreMissingClasses} ${commons.bc.version} jakarta.transaction jakarta.transaction-api 1.3.1 com.github.spotbugs spotbugs-maven-plugin org.apache.maven.plugins maven-javadoc-plugin org.apache.maven.plugins maven-changes-plugin ${commons.changes.version} src/changes 12313721,12326766,12328750 org.apache.maven.plugins maven-checkstyle-plugin ${basedir}/src/conf/checkstyle.xml false maven-pmd-plugin ${maven.compiler.target} pmd cpd jdk9-plus [1.9,) --add-exports=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED Morgan Delagrange morgand Geir Magnusson geirm Craig McClanahan craigmcc John McNally jmcnally Martin Poeschl mpoeschl mpoeschl@marmot.at tucana.at Rodney Waldhoff rwaldhoff David Weinrich dweinr1 Dirk Verbeeck dirkv Yoav Shapira yoavs yoavs@apache.org The Apache Software Foundation Jörg Schaible joehni joerg.schaible@gmx.de +1 Mark Thomas markt markt@apache.org 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 https://people.apache.org/~ggregory/img/garydgregory80.png Ignacio J. Ortega nacho Sean C. Sullivan sullis Todd Carmichael toddc@concur.com Wayne Woodfield Dain Sundstrom dain@apache.org Philippe Mouawad Glenn L. Nielsen James House James Ring Peter Wicks pwicks@apache.org commons-dbcp-rel-commons-dbcp-2.13.0/src/000077500000000000000000000000001472045345700201175ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/changes/000077500000000000000000000000001472045345700215275ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/changes/changes.xml000066400000000000000000002574121472045345700236740ustar00rootroot00000000000000 Apache Commons DBCP Release Notes Avoid object creation when invoking isDisconnectionSqlException #422. PoolableConnectionFactory.destroyObject() method behaves incorrectly on ABANDONED connection, issue with unhandled AbstractMethodError. DelegatingConnection.abort(Executor) should delegate to Jdbc41Bridge DelegatingConnection.setSchema(String) should delegate to Jdbc41Bridge. Fix possible NullPointerException in PoolingConnection.close(). PerUserPoolDataSource.registerPool() incorrectly replacing a CPDSConnectionFactory into managers map before throwing an IllegalStateException. Fix PMD UnnecessaryFullyQualifiedName in AbandonedTrace. Fix PMD UnnecessaryFullyQualifiedName in PoolableCallableStatement. Fix PMD UnnecessaryFullyQualifiedName in PoolablePreparedStatement. Fix PMD UnnecessaryFullyQualifiedName in Utils. Fix PMD UnnecessaryFullyQualifiedName in LocalXAConnectionFactory. Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in PerUserPoolDataSource. Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in SharedPoolDataSource. Add support for ignoring non-fatal SQL state codes #421. Add @FunctionalInterface to SwallowedExceptionListener. Add missing Javadoc comments and descriptions. Add tests, raise the bar for JaCoCo checks. Bump org.apache.commons:commons-parent from 66 to 78 #360, #371, #395, #420, #426, #436, #441, #449. Bump commons-logging:commons-logging from 1.3.0 to 1.3.4 #368, #399, #423. Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #404, #412, #427. Bump org.hamcrest:hamcrest from 2.2 to 3.0 #410. Bump org.slf4j:slf4j-simple from 2.0.13 to 2.0.16 #413, #418. BasicDataSource#setAbandonedUsageTracking has no effect. PoolingConnection.toString() causes StackOverflowError. PooledConnectionImpl.destroyObject(PStmtKey, PooledObject) can throw NullPointerException #312. PoolingConnection.destroyObject(PStmtKey, PooledObject) can throw NullPointerException #312. Fix examples in src/main/java/org/apache/commons/dbcp2/package-info.java. Add property project.build.outputTimestamp for build reproducibility. Add null guards in DelegatingDatabaseMetaData constructor #352. Data source bean creation failed due to mismatched return type of setter and getter for connectionInitSqls in BasicDataSource: Add BasicDataSource.setConnectionInitSqls(List). Use ReentrantLock in PoolableConnection.close, #591 Bump commons-lang3 from 3.13.0 to 3.14.0. Bump commons-parent from 64 to 66. Bump org.slf4j:slf4j-simple from 2.0.9 to 2.0.12 #349. Update call sites of deprecated APIs from Apache Commons Pool. Add DataSourceMXBean.getUserName() and deprecate getUsername(). Bump h2 from 2.2.220 to 2.2.224, #308. Bump commons-parent from 60 to 64. Bump org.slf4j:slf4j-simple from 2.0.7 to 2.0.9 #301. Bump org.apache.commons:commons-pool2 from 2.11.1 to 2.12.0. Bump jakarta.transaction:jakarta.transaction-api from 1.3.1 to 1.3.3. Bump commons-logging:commons-logging from 1.2 to 1.3.0. Fix StackOverflowError in PoolableConnection.isDisconnectionSqlException #123. PerUserPoolDataSourceFactory.getNewInstance(Reference) parsed defaultMaxWaitMillis as an int instead of a long. Reimplement time tracking in AbandonedTrace with an Instant instead of a long. Migrate away from deprecated APIs in Apache Commons Pool. Fix possible NullPointerException in BasicDataSourceFactory.validatePropertyNames(). Fix possible NullPointerException in BasicDataSourceFactory.getObjectInstance(). Connection level JMX queries result in concurrent access to connection objects, causing errors #179. UserPassKey should be Serializable. LifetimeExceededException should extend SQLException. Replace Exception with SQLException in some method signatures (preserves binary compatibility, not source). Don't leak Connections when PoolableConnectionFactory.makeObject() fails to create a JMX ObjectName. Performance: No need for map lookups if we traverse map entries instead of keys. Performance: Refactor to use a static inner class in DataSourceXAConnectionFactory. Reuse pattern of throwing XAException instead of NullPointerException in LocalXAConnectionFactory.LocalXAResource. SpotBugs: An overridable method is called from constructors in PoolableCallableStatement. SpotBugs: An overridable method is called from constructors in PoolablePreparedStatement. Wrong property name logged in ConnectionFactoryFactory.createConnectionFactory(BasicDataSource, Driver). Throw SQLException instead of NullPointerException when the connection is already closed. CPDSConnectionFactory.makeObject() does not need to wrap and rethrow SQLException. PoolingDataSource.close() now always throws SQLException. [StepSecurity] ci: Harden GitHub Actions #282. Fixes typos, missing or misplaced characters, and grammar issues #299. Add and use AbandonedTrace#setLastUsed(Instant). Add and use Duration versions of now deprecated APIs that use ints and longs. Internally track durations with Duration objects instead of ints and longs. See the JApiCmp report for the complete list. Add PMD check to default Maven goal. Add Utils.getDisconnectionSqlCodes() and Utils.DISCONNECTION_SQL_CODES. Make BasicDataSource.getConnectionPool() public. Add github/codeql-action. Bump actions/cache from 2.1.6 to 3.0.8 #147, #176. Bump actions/checkout from 2.3.4 to 3.0.2 #139, #143, #173. Bump actions/setup-java from 2 to 3.6.0 #229. Bump actions/upload-artifact from 3.1.0 to 3.1.1 #231. Bump checkstyle from 8.44 to 9.3 #121, #130, #149, #158, #190. Bump maven-checkstyle-plugin from 3.1.2 to 3.2.0 #210. Bump commons-pool2 2.10.0 to 2.11.1. Bump junit-jupiter from 5.8.0-M1 to 5.9.1 #125, #136, #157, #203, #218. Bump spotbugs-maven-plugin from 4.3.0 to 4.7.3.0 #140, #154, #161, #178, #192, #200, #204, #213, #234. Bump spotbugs from 4.3.0 to 4.7.3 #124, #133, #151, #164, #177, #189, #214, #230. Bump org.mockito:mockito-core from 3.11.2 to 4.11.0, #128, #138, #152, #175, #188. #193, #208, #215, #232, #235, #246, #252. Bump maven-javadoc-plugin from 3.3.0 to 3.4.1 #131, #184. Bump maven-pmd-plugin from 3.14.0 to 3.19.0 #132, #172, #195. Bump pmd from 6.44.0 to 6.52.0. Bump narayana-jta from 5.12.0.Final to 5.12.7.Final #134, #156, #163, #185, #197. Bump japicmp-maven-plugin from 0.15.3 to 0.17.1 #137, #166, #174, #211, #238. Bump h2 from 1.4.200 to 2.2.220 #153, #183, #196, #287. Update SQL for migration from H2 1.4.200 to 2.0.204 where "KEY" and "VALUE" are now reserved keywords. Bump jboss-logging from 3.4.2.Final to 3.4.3.Final #162. Bump slf4j-simple from 1.7.30 to 1.7.36 #169. Bump commons-parent from 52 to 60 #180, #219, #254, #278. Bump JaCoCo from 0.8.7 to 0.8.8. Bump maven-surefire-plugin 2.22.2 to 3.0.0-M7. Bump apache-rat-plugin 0.13 to 0.14. Bump commons-lang3 from 3.12 to 3.13.0. Add and reuse Constants.KEY_USER and Constants.KEY_PASSWORD. Add and reuse DataSourceMXBean. Add and reuse DriverAdapterCPDS.{get|set}DurationBetweenEvictionRuns(), deprecate {get|set}TimeBetweenEvictionRunsMillis(long). Add and reuse DriverAdapterCPDS.{get|set}MinEvictableIdleDuration(), deprecate {get|set}MinEvictableIdleTimeMillis(int). Add and reuse CPDSConnectionFactory.setMaxConnLifetime(Duration), deprecate setMaxConnLifetimeMillis(long). Add and reuse KeyedCPDSConnectionFactory.setMaxConnLifetime(Duration), deprecate setMaxConnLifetimeMillis(long). Add and reuse KeyedCPDSConnectionFactory.setMaxConnLifetime(Duration), deprecate setMaxConnLifetimeMillis(long). Add and reuse InstanceKeyDataSource.{get|set}DefaultMaxWait(Duration), deprecate {get|set}DefaultMaxWaitMillis(long). Fix test random failure on TestSynchronizationOrder.testInterposedSynchronization, #84. ManagedConnection must clear its cached state after transaction completes, #75. Minor Improvements #78. Use abort rather than close to clean up abandoned connections. Performance Enhancement: Call toArray with Zero Array Size #20. Avoid exposing password via JMX #38. Remove redundant initializers #98. Simplify test assertions #100, #113. DataSource implementations do not implement Wrapper interface correctly #93. Replace FindBugs with SpotBugs. DataSourceConnectionFactory.getUserPassword() may expose internal representation by returning DataSourceConnectionFactory.userPassword. DataSourceXAConnectionFactory.getUserPassword() may expose internal representation by returning DataSourceXAConnectionFactory.userPassword. DriverAdapterCPDS.getPasswordCharArray() may expose internal representation by returning DriverAdapterCPDS.userPassword. new org.apache.commons.dbcp2.managed.DataSourceXAConnectionFactory(TransactionManager, XADataSource, String, char[], TransactionSynchronizationRegistry) may expose internal representation by storing an externally mutable object into DataSourceXAConnectionFactory.userPassword. org.apache.commons.dbcp2.managed.DataSourceXAConnectionFactory.setPassword(char[]) may expose internal representation by storing an externally mutable object into DataSourceXAConnectionFactory.userPassword. org.apache.commons.dbcp2.PStmtKey.getColumnIndexes() may expose internal representation by returning PStmtKey.columnIndexes. org.apache.commons.dbcp2.PStmtKey.getColumnNames() may expose internal representation by returning PStmtKey.columnNames. Use Collections.synchronizedList() Instead Of Vector #101. Simplify and inline variables #99. Update PoolKey#toString() to avoid revealing a user name is here. Internal package private UserPassKey class stores its user name as a char[] as it already does the password. Performance of DelegatingConnection.prepareStatement(String) regressed enormously in 2.8.0 compared to 1.4. DelegatingConnection should also cache connection schema string to avoid calling the Connection#getSchema() for each key creation. DelegatingConnection should also cache connection catalog string to avoid calling the Connection#getCatalog() for each key creation. BasicDataSource should test for the presence of a security manager dynamically, not once on initialization. Bump mockito-core from 3.5.11 to 3.11.2 #66, #72, #77, #85, #91, #105, #110, #116. Bump actions/checkout from v2.3.2 to v2.3.4 #65, #74. Bump actions/cache from v2 to v2.1.6 #90, #108. Bump commons-pool2 from 2.8.1 to 2.9.0. Bump actions/setup-java from v1.4.2 to v2 #69. Bump japicmp-maven-plugin from 0.14.3 to 0.15.2 #71, #82. Bump maven-pmd-plugin from 3.13.0 to 3.14.0 #76. Bump japicmp-maven-plugin from 0.14.4 to 0.15.3, #83. Bump Hamcrest 1.3 -> 2.2 #70. Bump maven-checkstyle-plugin from 3.1.1 to 3.1.2 #88. Bump junit-jupiter from 5.7.0 to 5.8.0-M1, #89, #106. Bump narayana-jta from 5.10.6.Final to 5.12.0.Final #103, #111. Bump maven-javadoc-plugin from 3.2.0 to 3.3.0 #107. Bump commons.jacoco.version 0.8.6 -> 0.8.7. Bump jboss-logging from 3.4.1.Final to 3.4.2.Final #109. Bump org.jboss:jboss-transaction-spi from 7.6.0.Final to 7.6.1.Final. Bump commons-pool2 from 2.9.0 to 2.10.0. Bump checkstyle to 8.44. Bump spotbugs from 4.2.3 to 4.3.0 #117. Bump spotbugs-maven-plugin from 4.2.3 to 4.3.0 #118. Fix BasicManagedDataSource leak of connections opened after transaction is rollback-only #39. Add clearStatementPoolOnReturn #42. Add start, restart methods to BasicDataSource. #50. NPE when creating a SQLExceptionList with a null list. Fix DelegatingConnection readOnly and autoCommit caching mechanism #35. Fix regression introduced by unreleased code clean-up #63. Update to PR#36 - PrepareStatement and prepareCall methods are extracted #37. Do not display credentials in DriverAdapterCPDS.toString(). Do not display credentials in DelegatingConnection.toString(). Do not display credentials in DriverConnectionFactory.toString(). Do not display credentials in PoolKey.toString(). Do not display credentials in UserPassKey.toString(). Update Apache Commons Pool from 2.7.0 to 2.8.1, #48. Update tests from H2 1.4.199 to 1.4.200. Update tests from Mockito 3.0.0 to 3.5.11 #47, #60, #64. Update tests from jboss-logging 3.4.0.Final to 3.4.1.Final. Update tests from narayana-jta 5.9.5.Final to 5.10.6.Final, #61. Update tests from junit-jupiter 5.5.1 to 5.7.0 #62. Update tests from org.slf4j:slf4j-simple 1.7.26 to 1.7.30. Update build from com.github.siom79.japicmp:japicmp-maven-plugin 0.13.1 to 0.14.3. Update build from maven-javadoc-plugin 3.1.1 to 3.2.0. Update build from maven-pmd-plugin 3.12.0 to 3.13.0. Update org.apache.commons:commons-parent from 48 to 51. Update jacoco-maven-plugin from 0.8.4 to 0.8.6. Update maven-checkstyle-plugin from 3.0.0 to 3.1.1. Update actions/checkout from v1 to v2.3.2, #44, #51. Update actions/setup-java from v1.4.0 to v1.4.2 #58. ManagedDataSource#close() should declare used exceptions. Add a ConnectionFactory class name setting for BasicDataSource.createConnectionFactory() #33. Add missing Javadocs. Wrong JMX base name derived in BasicDataSource#updateJmxName. Avoid NPE when calling DriverAdapterCPDS.toString(). java.util.IllegalFormatException while building a message for a SQLFeatureNotSupportedException in Jdbc41Bridge.getObject(ResultSet,String,Class). Fix Javadoc link in README.md #21. Close ObjectOutputStream before calling toByteArray() on underlying ByteArrayOutputStream #28. Upgrade to JUnit Jupiter #19. Fix tests on Java 11. Update Apache Commons Pool from 2.6.1 to 2.6.2. Add 'jmxName' property to web configuration parameters listing. Update Apache Commons Pool from 2.6.2 to 2.7.0. Make org.apache.commons.dbcp2.AbandonedTrace.removeTrace(AbandonedTrace) null-safe. org.apache.commons.dbcp2.DelegatingStatement.close() should try to close ALL of its result sets even when an exception occurs. org.apache.commons.dbcp2.DelegatingConnection.passivate() should close ALL of its resources even when an exception occurs. org.apache.commons.dbcp2.PoolablePreparedStatement.passivate() should close ALL of its resources even when an exception occurs. org.apache.commons.dbcp2.PoolableCallableStatement.passivate() should close ALL of its resources even when an exception occurs. Update tests from org.mockito:mockito-core 2.28.2 to 3.0.0. Update tests from H2 1.4.198 to 1.4.199. Update tests from com.h2database:h2 1.4.197 to 1.4.199. Update tests from org.jboss.narayana.jta:narayana-jta 5.9.2.Final to 5.9.5.Final. Update tests from org.jboss.logging:jboss-logging 3.3.2.Final to 3.4.0.Final. Update tests from org.mockito:mockito-core 2.24.0 to 2.28.2. Update tests from org.mockito:mockito-core 2.28.2 to 3.0.0. Allow for manual connection eviction. Allow DBCP to register with a TransactionSynchronizationRegistry for XA cases. Make defensive copies of char[] passwords. Do not try to register synchronization when the transaction is no longer active. Do not double returnObject back to the pool if there is a transaction context with a shared connection. Allow DBCP to work with old Java 6/JDBC drivers without throwing AbstractMethodError. Add some toString() methods for debugging (never printing passwords.) BasicManagedDataSource needs to pass the TSR with creating DataSourceXAConnectionFactory. Add getters to some classes. org.apache.commons.dbcp2.DriverManagerConnectionFactory should use a char[] instead of a String to store passwords. Update Apache Commons Pool from 2.6.0 to 2.6.1. Update Java requirement from version 7 to 8. Support JDBC 4.2. Support default schema in configuration. Examines 'SQLException's thrown by underlying connections or statements for fatal (disconnection) errors. Change default for fail-fast connections from false to true. Prepared statement keys should take a Connection's schema into account. Increase test coverage. Update Apache Commons Pool from 2.5.0 to 2.6.0. Avoid exceptions when closing a connection in mutli-threaded use case. Connection leak during XATransaction in high load. Drop Ant build. Ensure DBCP ConnectionListener can deal with transaction managers which invoke rollback in a separate thread. org.apache.commons.dbcp2.PStmtKey should make copies of given arrays in constructors. Remove duplicate code in org.apache.commons.dbcp2.cpdsadapter.PStmtKeyCPDS. Add support for pooling CallableStatements to the org.apache.commons.dbcp2.cpdsadapter package. Deprecate use of PStmtKeyCPDS in favor of PStmtKey. org.apache.commons.dbcp2.DataSourceConnectionFactory should use a char[] instead of a String to store passwords. org.apache.commons.dbcp2.managed.DataSourceXAConnectionFactory should use a char[] instead of a String to store passwords. org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS should use a char[] instead of a String to store passwords. org.apache.commons.dbcp2.datasources.CPDSConnectionFactory should use a char[] instead of a String to store passwords. org.apache.commons.dbcp2.datasources internals should use a char[] instead of a String to store passwords. org.apache.commons.dbcp2.datasources.InstanceKeyDataSourceFactory.closeAll() does not close all. AbandonedTrace.getTrace() contains race condition. Avoid javax.management.InstanceNotFoundException on shutdown when a bean is not registered. Closes #9. Make constant public: org.apache.commons.dbcp2.PoolingDriver.URL_PREFIX. DriverAdapterCPDS.setUser(), setPassword(), and getPooledConnection() with null arguments throw NullPointerExceptions when connection properties are set. Add API org.apache.commons.dbcp2.datasources.PerUserPoolDataSource.clear(). NPE for org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS.setConnectionProperties(null). The method org.apache.commons.dbcp2.PoolingDriver.getConnectionPool(String) does not tell you which pool name is not registered when it throws an exception. Update Apache Commons Pool from 2.4.2 to 2.5.0. OSGi declarations contain multiple import headers for javax.transaction. Wrong parameter name in site documentation for BasicDataSource Configuration Parameters. Add jmxName to properties set by BasicDataSourceFactory. This enables container-managed pools created from JNDI Resource definitions to enable JMX by supplying a valid root JMX name. NullPointerException thrown when calling ManagedConnection.isClosed(). InvalidateConnection can result in closed connection returned by getConnection. Complete the fix for DBCP-418, enabling PoolableConnection class to load in environments (such as GAE) where the JMX ManagementFactory is not available. Add constructor DriverManagerConnectionFactory(String). Ensure that the cacheState setting is used when statement pooling is disabled. Ensure that setSoftMinEvictableIdleTimeMillis is used when working with BasicDataSource. Correct the name of the configuration attribute softMinEvictableIdleTimeMillis. Avoid potential infinite loops when checking if an SQLException is fatal for a connection or not. Expand the fail-fast for fatal connection errors feature to include managed connections. Correct a typo in the method name PoolableConnectionFactory#setMaxOpenPreparedStatements. The old method remains but is deprecated so not to break clients currently using the incorrect name. Refactoring to prepare for a future patch to enable pooling of all prepared and callable statements in PoolingConnection. Ensure that a thread's interrupt status is visible to the caller if the thread is interrupted during a call to PoolingDataSource.getConnection(). Make it simpler to extend BasicDataSource to allow sub-classes to provide custom GenericObjectPool implementations. When using a BasicDataSource, pass changes related to the handling of abandoned connections to the underlying pool so that the pool configuration may be updated dynamically. Enable pooling of all prepared and callable statements inPoolingConnection. Updated pool version to 2.4.2. The fix for POOL-300 may cause DBCP users to see more reports of abandoned connections (if removal and logging are configured). Prior to the fix for POOL-300, the PrintWriter used to log abandoned connection stack traces was not being flushed on each log event. Added BasicDataSource abandonedUsageTracking property missing from BasicDataSourceFactory. SharedPoolDataSource getConnection fails when testOnBorrow is set with a null validation query. Nested connections in a transaction (local) throws null pointer. BasicDataSource does not set disconnectionSql properties on its PoolableConnectionFactory. InstanceKeyDataSource discards native SQLException when given password does not match password used to create the connection. Update Apache Commons Logging to 1.2 from 1.1.3. Correct some Javadoc references to Apache Commons Pool 2 classes that have changed names since Pool 1.x. Do not ignore the configured custom eviction policy when creating a BasicDataSource. Added invalidateConnection method to BasicDataSource. Unsuccessful Connection enlistment in XA Transaction ignored by TransactionContext. Made expired connection logging configurable in BasicDataSource. Setting logExpiredConnections to false suppresses expired connection log messages. Made Datasources implement AutoCloseable. Added fastFailValidation property to PoolableConnection, configurable in BasicDataSource. When set to true, connections that have previously thrown fatal disconnection errors will fail validation immediately (no driver calls). Changed BasicDataSource createDataSource method to ensure that initialization completes before clients get reference to newly created instances. Fixed connection leak when SQLException is thrown while enlisting an XA transaction. Setting jmxName to null should suppress JMX registration of connection and statement pools. Eliminated synchronization in BasicDataSource getNumActive, getNumIdle methods. Added property name verification to BasicDataSourceFactory. References including obsolete or unrecognized properties now generate log messages. Small performance improvements when returning connections to the pool. Fixed DelegatingStatement close to ensure closed statements do not retain references to pooled prepared statements. Due to finalization code added in 2.0, this was causing pooled prepared statements to be closed by GC while in use by clients. Added check in PoolingDataSource constructor to ensure that the connection factory and pool are properly linked. Fixed connection leak when managed connections are closed during transactions. Enable PoolableConnection class to load without JMX. BasicManagedDataSource - unregister from JMX on close(). Log validation failures of poolable connections. DelegatingStatement.close() fails with NPE if statement is null CPDSConnectionFactory.validateObject(Object) ignores Throwable. Provide a new option (cacheState) to cache current values of autoCommit and readOnly so database queries are not required for every call to the associated getters. This option is enabled by default. Removed unnecessary synchronisation in BasicDataSource#createDataSource. The Java package name has been changed from org.apache.commons.dbcp to org.apache.commons.dbcp2. Update to Commons Pool 2 (based on java.util.concurrent) to provide pooling functionality. Updated source code for Java 1.6 (added @Override & @Deprecated annotations). Removed JOCL support. Remove deprecated SQLNestedException. Fix threading issues with accessToUnderlyingConnectionAllowed attribute of PoolingDriver which is used to support unit testing. BasicDataSource instances are now exposed via JMX. All the configuration properties are available as is the connection pool and the statement pools (if statement pooling is enabled). Fix thread safety issues in the SharedPoolDataSource and the PerUserPoolDataSource. Allow accessToUnderlyingConnectionAllowed to be configured when configuration takes place via JNDI in a JavaEE container. Fix threading issue when using multiple instances of the SharedPoolDataSource concurrently. Ensure that the close state of a pooled connection and the underlying connection is consistent when the underlying connection is closed as a result of an error condition. Make all mutable fields private. Return BasicDataSource rather than DataSource from BasicDataSourceFactory so a cast is not required to use BasicDataSource specific methods. The equals() implementations of the DelegatingXxx classes are now symmetric. There are some important API changes underlying this fix. Firstly, two DelegatingXxx instances are no longer considered equal if they have the same innermost delegate. Secondly, a DelegatingXxx instance is not considered equal to its innermost delegate. The getInnermostDelegateInternal() method has been made public (but remains part of the internal API) to allow classes extending this implementation to access the innermost delegate when required. Expose the new Pool 2 property evictionPolicyClassName to enable more sophisticated eviction strategies to be used. Add support for pooling PreparedStatements that use auto-generated keys. Enable JDBC resources that are no longer referenced by client code to be eligible for garbage collection. Enable DBCP to work with a SecurityManager such that only DBCP needs to be granted the necessary permissions to communicate with the database. Correct path to Javadoc overview in build.xml. The default values for readOnly, autoCommit and transactionIsolation are now taken from the JDBC driver. No calls to setReadOnly(), setAutoCommit() or setTransactionIsolation() will be made for a newly borrowed connection unless a default is explicitly configured and the connection is currently using a different setting. Register pooled connections with JMX so that they may be forcibly closed via JMX if required. Modify SharedPoolDataSource and PerUserPoolDataSource to expose all of the configuration properties of the underlying connection pool(s). This represents a significant refactoring of these classes and a number of property names have changed as a result. Provide an option to control if autoCommit is always set to true when a connection is returned to the connection pool. Provide an option to control if rollback is called when a connection is returned to the poll with autoCommit disabled. Provide an option to set the default query timeout. Connection.isValid() should not throw an SQLException if the connection is closed. Use Connection.isValid() to validate connections unless a validation query is explicitly configured. Note that this means it is no longer necessary for a validation query to be specified in order for validation to take place. When testing with Oracle, this resulted in database validation being approximately 7 times faster. Add support for validation testing database connections on creation. Correct the documentation for the maxOpenPreparedStatements parameter and review the use of the phrase non-positive throughout the documentation and javadoc, replacing it with negative where that is the correct definition to use. Avoid multiple calls to Connection.getAutoCommit() in PoolableConnectionFactory.passivateObject() as it could be an expensive call. Use one line per statement for methods with multiple statements rather than using a single line. Expose all of the AbandonedConfig properties through a BasicDataSource. Correct implementation of DelegatingConnection.isWrapperFor() so it works correctly with older JDBC drivers. Correct implementation of DelegatingStatement.isWrapperFor(). Also fix DelegatingDatabaseMetaData.isWrapperFor() and DelegatingResultSet.isWrapperFor() that had the same problem. LocalXAConnectionFactory does not properly check if Xid is equal to currentXid when resuming which may result in an XAException. Ensure that the XAConnection is closed when the associated Connection is closed. Clarify Jaavdoc for isClosed() method of PoolableConnection. Avoid NullPointerException and throw an XAException if an attempt is made to commit the current transaction for a connection when no transaction has been started. Using batchUpdate() should not invalidate the PreparedStatement when it is returned to the pool. Improve documentation for JNDI example using BasicDataSource. Exposed GenericObjectPool's softMinEvictableIdleTimeMillis property for configuration and use by BasicDataSource. Made equals reflexive in DelegatingStatement (and subclasses), DelegatingMetaData, DelegatingResultSet and PoolingDriver#PoolGuardConnectionWrapper. Modified createDataSource method in BasicDataSource to ensure that GenericObjectPool Evictor tasks are not started and orphaned when BasicDataSource encounters errors on initialization. Prior to this fix, when minIdle and timeBetweenEvictionRunsMillis are both positive, Evictors orphaned by failed initialization can continue to generate database connection requests. This issue is duplicated by DBCP-339 and DBCP-93. Changed DelegatingDatabaseMetaData to no longer add itself to the AbandonedTrace of its parent connection. This was causing excessive memory consumption and was not necessary, as resultsets created by DelegatingDatabaseMetaData instances are attached to the parent connection's trace on creation. Also fixes DBCP-352. Modified execute methods of Statement objects to ensure that whenever a statement is used, the lastUsed property of its parent connection is updated. Correctly implemented the option to configure the class loader used to load the JDBC driver. LIFO configuration option has been added to BasicDataSource. When set to true (the default), the pool acts as a LIFO queue; setting to false causes connections to enter and exit to pool in FIFO order. Test transitive dependencies brought in by geronimo-transaction created version conflicts (commons logging and junit). These have been explicitly excluded in the POM. BasicDataSourceFactory incorrectly used "initConnectSqls" in versions 1.3 and 1.4 of DBCP as the property name for connectionInitSqls. Online docs for 1.3/1/4 have been updated to reflect this inconsistency. The BasicDataSourceFactory property name has been changed to "connectInitSqls" to match the online docs and the BasicDataSource property name. Eliminated poolKeys cache from PerUserPoolDataSource. Eliminated userKeys LRUMap cache from SharedPoolDataSource. Made private fields final where possible. PerUserPoolDataSource.getPooledConnectionAndInfo multi-threading bug. Remove throws clause from method that does not throw an exception. Remove code that catches and ignores Exceptions when calling PooledConnection.removeConnectionEventListener(ConnectionEventListener) as the method does not throw any Exceptions. Remove impossible null check. Renamed variables with duplicate names in different scopes. Clarified javadoc for BasicDataSource close() method. Made PoolingConnection pool CallableStatements. When BasicDataSource's poolPreparedStatements property is true, CallableStatements are now pooled along with PreparedStatements. The maxOpenPreparedStatements property limits the combined number of Callable and Prepared statements that can be in use at a given time. Use an API specific exception for logging abandoned objects to make scanning the logs for these exceptions simpler and to provide a better message that includes the creation time of the abandoned object. Ensure Statement.getGeneratedKeys() works correctly with the CPDS adapter. Removed incorrectly advertised ClassNotFoundException from JOCLContentHandler.ConstructorDetails.createObject(). Make the class loader used to load the JDBC driver configurable for the BasicDatasource. Handle user password changes for InstanceKeyDataSources. Made XADataSource configurable in BasicManagedDataSource. Added PoolableManagedConnection and PoolableManagedConnectionFactory so that pooled managed connections can unregister themselves from transaction registries, avoiding resource leaks. Added connectionProperties property to DriverAdapterCPDS. Added a validationQueryTimeout configuration parameter to BasicDataSource allowing the user to specify a timeout value (in seconds) for connection validation queries. Added a connectionInitSqls configuration parameter to BasicDataSource allowing the user to specify a collection of SQL statements to execute one time when a physical database connection is first opened. PoolableConnectionFactory.makeObject() is no longer synchronized. This provides improved response times when load spikes at the cost of a faster rise in database server load. This change was made as a partial fix for DBCP-212. The synchronization changes in Commons Pool 1.5 complete the fix for this issue. Reverted DelegatingConnection close to 1.2.2 version to ensure open statements are closed before the underlying connection is closed. Refactor DelegatingConnection and ManagedConnection enable overridden equals() and hashcode() to work correctly. Add a DelegatingDatabaseMetaData to track ResultSets returned from DatabaseMetaData objects. Modified BasicDataSourceFactory to complete initialization of the pool by creating initialSize connections rather than leaving this to lazy initialization when the pool is used. Eliminated masked _stmt field in descendents of DelegatingStatement. Modified DBCP sources to support compilation under JDK 1.4-1.6 using Ant flags to do conditional compilation. Added a static initializer to BasicDatasource that calls DriverManager.getDrivers() to force initialization before we ever do anything that might use Class.forName() to load (and register) a JDBC driver. Eliminated direct System.out calls in AbandonedTrace. Modified DelegatingStatement close to clear open batches. Eliminated unused private "parent" field in AbandonedTrace. Fixed errors handling boolean-valued Reference properties in InstanceKeyObjectFactory, DriverAdapterCPDS that were causing testOnBorrow and poolPreparedStatements properties to be incorrectly set when creating objects from javax.naming.Reference instances. Made private instance fields of AbandonedTrace volatile (parent, createdBy, lastUsed, createdTime) or final (trace). Narrowed synchronization in AbandonedTrace to resolve an Evictor deadlock. Corrected Javadoc to state that getLoginTimeout and setLoginTimeout are NOT supported by BasicDataSource. Added Maven 2 pom.xml. Removed a block of code from TestJOCLed that set the Xerces parser manually. This was to support early JDKs. The 1.3 version of DBCP requires JDK 1.4+. Added support for pooling managed connections. Added BasicManagedDataSource, extending BasicDataSource. Also improved extensibility of BasicDataSource by encapsulating methods to create object pool, connection factory and datasource instance previously embedded in createDataSource. Changed behavior to allow Connection, Statement, PreparedStatement, CallableStatement and ResultSet to be closed multiple times. The first time close is called the resource is closed and any subsequent calls have no effect. This behavior is required as per the Javadocs for these classes. Also added tests for closing all types multiple times and updated any tests that incorrectly assert that a resource can not be closed more then once. Fixes DBCP-3, DBCP-5, DBCP-23 and DBCP-134. Modified PoolingDataSource, PoolingDriver and DelegatingStatement to assure that all returned Statements, PreparedStatements, CallableStatements and ResultSets are wrapped with a delegating object, which already properly handle the back pointers for Connection and Statement. Also added tests to assure that the *same* object used to create the statement or result set is returned from either getConnection() or getStatement(). SQLNestedException has been deprecated and will be replaced in DBCP 2.0 with SQLException and standard Java exception chaining. BasicDataSource.close() now permanently marks the data source as closed, and no new connections can be obtained from the data source. At close all idle connections are destroyed and the method returns. As the remaining active connections are closed, they are destroyed. Eliminated potential sources of NullPointerExceptions in PoolingConnection. Improved error recovery and listener cleanup in KeyedCPDSConnectionFactory. Substituted calls to destroyObject with _pool.invalidateObject on error to ensure pool active count is decremented on error events. Ensured that events from closed or invalid connections are ignored and listeners are cleaned up. Fixed error in SharedPoolDataSource causing incorrect passwords to be stored under certain conditions. Added exception handler to ensure that PooledConnections are not orphaned when an exception occurs in setUpDefaults or clearWarnings in InstanceKeyDataSource.getConnection. Made getPool synchronized in PoolableConnectionFactory. Fixes inconsistent synchronization accessing _pool. Fixed inconsistent synchronization on _rollbackAfterValidation, _validationQuery and _pool in CPDSConnectionFactory and KeyedCPDSConnectionFactory by making the first two volatile and making both getter and setter for _pool synchronized. See <a href="changes-report.html#a1.4">DBCP 1.4 Changes </a> for details. Version 1.3 is identical to 1.4, other than JDBC 4 methods being filtered out of the DBCP 1.3 sources. Changes Since 1.2.2 are the same for 1.3 and 1.4. Add a <i>JNDI How To</i> to the User Guide. DriverManagerConnectionFactory: blank user name and password handling. Broken behaviour for BasicDataSource.setMaxActive(0). BasicDataSource does not work with getConnection(String, String). Enhancements to prepared statement in DriverAdapterCPDS. Better messages and docs for LoginTimeout UnsupportedOperationException. Error in JOCL snippet in org.apache.commons.dbcp package javadoc. Added toString() methods to DelegatingPreparedStatement and DelegatingStatement Changes to make DBCP compile on JDK 1.5 by adding source="1.4" to compiler arguments (there are compiler errors in JDK 5.0 without this source switch that cannot be fixed without JDK 5.0-specific syntax). Per-user pooling with Oracle driver and default isolation settings. Error in JOCL document in javadoc. Added toString() method to DelegatingConnection. Add DriverManager.invalidateConnection(). Improved Exception nesting in ConnectionPool. Fix broken website links for examples. Modified PoolableConnection close method to invalidate instance when invoked on an already closed connection. Inserted null checks to avoid NPE in close operations. Changed getReference method in InstanceKeyDataSource to return a concrete factory and added implementations of getReference in concrete subclasses. Inserted null check in close method of SharedPoolDataSource to avoid NPE when invoked on non-initialized pool. Document fact that true values for testOnBorrow, testOnReturn, testWhileIdle only have effect when validationQuery is set to a non-null string. Modified activateObject in PoolableConnection to test connection properties before resetting to defaults. Corrected maxActive documentation in configuration.html. Upgraded dependency to Pool 1.3. Added connection info to SQLException messages when closed connections (resp stmts) are accessed in DelegatingConnection, DelegatingStatement. Fixed errors in pool parameter documentation and made 0 value for _maxPreparedStatements in DriverAdapterCPDS behave like a negative value, to be consistent with documentation and pool behavior. Made userKeys an instance variable (i.e., not static) in SharedPoolDataSource. Changed implementation of equals in PoolingDataSource.PoolGuardConnectionWrapper to ensure it is reflexive, even when wrapped connections are not DelegatingConnections. Added rollbackAfterValidation property and code to issue a rollback on a connection after validation when this property is set to true to eliminate Oracle driver exceptions. Default property value is false. Removed dependency on Commons Collections by adding collections 2.1 sources for LRUMap and SequencedHashMap with package scope to datasources package. Removed synchronization from prepareStatement methods in PoolingConnection. Synchronization in these methods was causing deadlocks. No resources other than the prepared statement pool are accessed by these methods, and the pool methods are synchronized. Also fixes DBCP-202. See <a href="release-notes-1.2.1.html">DBCP 1.2.1 Release Notes</a> for details. See <a href="release-notes-1.2.html">DBCP 1.2 Release Notes</a> for details. See <a href="release-notes-1.1.html">DBCP 1.1 Release Notes</a> for details. Initial Release commons-dbcp-rel-commons-dbcp-2.13.0/src/changes/release-notes.vm000066400000000000000000000070251472045345700246450ustar00rootroot00000000000000## 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. ${project.name} Version ${version} RELEASE NOTES The ${developmentTeam} is pleased to announce the release of ${project.name} ${version}. $introduction.replaceAll("(? commons-dbcp-rel-commons-dbcp-2.13.0/src/conf/eclipse/000077500000000000000000000000001472045345700224705ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/conf/eclipse/formatter.xml000066400000000000000000001123441472045345700252220ustar00rootroot00000000000000 commons-dbcp-rel-commons-dbcp-2.13.0/src/conf/spotbugs-exclude-filter.xml000066400000000000000000000066761472045345700263650ustar00rootroot00000000000000 commons-dbcp-rel-commons-dbcp-2.13.0/src/main/000077500000000000000000000000001472045345700210435ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/assembly/000077500000000000000000000000001472045345700226625ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/assembly/bin.xml000066400000000000000000000034671472045345700241660ustar00rootroot00000000000000 bin tar.gz zip false LICENSE.txt NOTICE.txt README.txt RELEASE-NOTES.txt target *.jar target/site/apidocs apidocs commons-dbcp-rel-commons-dbcp-2.13.0/src/main/assembly/src-tar-gz.xml000066400000000000000000000055511472045345700254030ustar00rootroot00000000000000 src tar.gz ${project.artifactId}-${project.version}-src build.properties.sample build.xml LICENSE.txt NOTICE.txt pom.xml README.md RELEASE-NOTES.txt lf doc static_structure_dia.gif lf src/site/resources src/conf src/site/xdoc lf src/site site.xml lf src/media src/changes lf src/main lf src/test lf commons-dbcp-rel-commons-dbcp-2.13.0/src/main/assembly/src-zip.xml000066400000000000000000000055571472045345700250070ustar00rootroot00000000000000 src zip ${project.artifactId}-${project.version}-src CODE_OF_CONDUCT.md LICENSE.txt NOTICE.txt pom.xml README.md RELEASE-NOTES.txt SECURITY.md crlf doc static_structure_dia.gif crlf src/conf src/site/resources src/site/xdoc crlf src/site site.xml crlf src/media src/changes crlf src/main crlf src/test crlf commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/000077500000000000000000000000001472045345700217645ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/000077500000000000000000000000001472045345700225535ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/000077500000000000000000000000001472045345700237745ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/000077500000000000000000000000001472045345700254475ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/000077500000000000000000000000001472045345700264415ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/AbandonedTrace.java000066400000000000000000000153661472045345700321510ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.lang.ref.WeakReference; import java.sql.SQLException; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.function.Consumer; import org.apache.commons.pool2.TrackedUse; /** * Tracks connection usage for recovering and reporting abandoned connections. *

* The JDBC Connection, Statement, and ResultSet classes extend this class. *

* * @since 2.0 */ public class AbandonedTrace implements TrackedUse, AutoCloseable { static void add(final AbandonedTrace receiver, final AbandonedTrace trace) { if (receiver != null) { receiver.addTrace(trace); } } /** A list of objects created by children of this object. */ private final List> traceList = new ArrayList<>(); /** Last time this connection was used. */ private volatile Instant lastUsedInstant = Instant.EPOCH; /** * Creates a new AbandonedTrace without config and without doing abandoned tracing. */ public AbandonedTrace() { init(null); } /** * Constructs a new AbandonedTrace with a parent object. * * @param parent * AbandonedTrace parent object. */ public AbandonedTrace(final AbandonedTrace parent) { init(parent); } /** * Adds an object to the list of objects being traced. * * @param trace * AbandonedTrace object to add. */ protected void addTrace(final AbandonedTrace trace) { synchronized (this.traceList) { this.traceList.add(new WeakReference<>(trace)); } setLastUsed(); } /** * Clears the list of objects being traced by this object. */ protected void clearTrace() { synchronized (this.traceList) { this.traceList.clear(); } } /** * Subclasses can implement this nop. * * @throws SQLException Ignored here, for subclasses. * @since 2.10.0 */ @Override public void close() throws SQLException { // nop } /** * Closes this resource and if an exception is caught, then calls {@code exceptionHandler}. * * @param exceptionHandler Consumes exception thrown closing this resource. * @since 2.10.0 */ protected void close(final Consumer exceptionHandler) { Utils.close(this, exceptionHandler); } /** * Gets the last time this object was used in milliseconds. * * @return long time in milliseconds. */ @Override @Deprecated public long getLastUsed() { return lastUsedInstant.toEpochMilli(); } @Override public Instant getLastUsedInstant() { return lastUsedInstant; } /** * Gets a list of objects being traced by this object. * * @return List of objects. */ protected List getTrace() { final int size = traceList.size(); if (size == 0) { return Collections.emptyList(); } final ArrayList result = new ArrayList<>(size); synchronized (this.traceList) { final Iterator> iter = traceList.iterator(); while (iter.hasNext()) { final AbandonedTrace trace = iter.next().get(); if (trace == null) { // Clean-up since we are here anyway iter.remove(); } else { result.add(trace); } } } return result; } /** * Initializes abandoned tracing for this object. * * @param parent * AbandonedTrace parent object. */ private void init(final AbandonedTrace parent) { add(parent, this); } /** * Removes this object the source object is tracing. * * @param source The object tracing * @since 2.7.0 */ protected void removeThisTrace(final Object source) { if (source instanceof AbandonedTrace) { AbandonedTrace.class.cast(source).removeTrace(this); } } /** * Removes a child object this object is tracing. * * @param trace * AbandonedTrace object to remove. */ protected void removeTrace(final AbandonedTrace trace) { synchronized (this.traceList) { final Iterator> iter = traceList.iterator(); while (iter.hasNext()) { final AbandonedTrace traceInList = iter.next().get(); if (trace != null && trace.equals(traceInList)) { iter.remove(); break; } if (traceInList == null) { // Clean-up since we are here anyway iter.remove(); } } } } /** * Sets the time this object was last used to the current time in milliseconds. */ protected void setLastUsed() { lastUsedInstant = Instant.now(); } /** * Sets the instant this object was last used. * * @param lastUsedInstant * instant. * @since 2.10.0 */ protected void setLastUsed(final Instant lastUsedInstant) { this.lastUsedInstant = lastUsedInstant; } /** * Sets the time in milliseconds this object was last used. * * @param lastUsedMillis * time in milliseconds. * @deprecated Use {@link #setLastUsed(Instant)} */ @Deprecated protected void setLastUsed(final long lastUsedMillis) { this.lastUsedInstant = Instant.ofEpochMilli(lastUsedMillis); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java000066400000000000000000003320111472045345700323000ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.time.Duration; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.function.BiConsumer; import java.util.logging.Logger; import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.StandardMBean; import javax.sql.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.AbandonedConfig; import org.apache.commons.pool2.impl.BaseObjectPoolConfig; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; /** * Basic implementation of {@code javax.sql.DataSource} that is configured via JavaBeans properties. *

* This is not the only way to combine the commons-dbcp2 and commons-pool2 packages, but provides a * one-stop solution for basic requirements. *

* * @since 2.0 */ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable { private static final Log log = LogFactory.getLog(BasicDataSource.class); static { // Attempt to prevent deadlocks - see DBCP - 272 DriverManager.getDrivers(); try { // Load classes now to prevent AccessControlExceptions later // A number of classes are loaded when getConnection() is called // but the following classes are not loaded and therefore require // explicit loading. if (Utils.isSecurityEnabled()) { final ClassLoader loader = BasicDataSource.class.getClassLoader(); final String dbcpPackageName = BasicDataSource.class.getPackage().getName(); loader.loadClass(dbcpPackageName + ".DelegatingCallableStatement"); loader.loadClass(dbcpPackageName + ".DelegatingDatabaseMetaData"); loader.loadClass(dbcpPackageName + ".DelegatingPreparedStatement"); loader.loadClass(dbcpPackageName + ".DelegatingResultSet"); loader.loadClass(dbcpPackageName + ".PoolableCallableStatement"); loader.loadClass(dbcpPackageName + ".PoolablePreparedStatement"); loader.loadClass(dbcpPackageName + ".PoolingConnection$StatementType"); loader.loadClass(dbcpPackageName + ".PStmtKey"); final String poolPackageName = PooledObject.class.getPackage().getName(); loader.loadClass(poolPackageName + ".impl.LinkedBlockingDeque$Node"); loader.loadClass(poolPackageName + ".impl.GenericKeyedObjectPool$ObjectDeque"); } } catch (final ClassNotFoundException cnfe) { throw new IllegalStateException("Unable to pre-load classes", cnfe); } } /** * Validates the given factory. * * @param connectionFactory the factory * @throws SQLException Thrown by one of the factory methods while managing a temporary pooled object. */ @SuppressWarnings("resource") protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory) throws SQLException { PoolableConnection conn = null; PooledObject p = null; try { p = connectionFactory.makeObject(); conn = p.getObject(); connectionFactory.activateObject(p); connectionFactory.validateConnection(conn); connectionFactory.passivateObject(p); } finally { if (p != null) { connectionFactory.destroyObject(p); } } } /** * The default auto-commit state of connections created by this pool. */ private volatile Boolean defaultAutoCommit; /** * The default read-only state of connections created by this pool. */ private transient Boolean defaultReadOnly; /** * The default TransactionIsolation state of connections created by this pool. */ private volatile int defaultTransactionIsolation = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; private Duration defaultQueryTimeoutDuration; /** * The default "catalog" of connections created by this pool. */ private volatile String defaultCatalog; /** * The default "schema" of connections created by this pool. */ private volatile String defaultSchema; /** * The property that controls if the pooled connections cache some state rather than query the database for current * state to improve performance. */ private boolean cacheState = true; /** * The instance of the JDBC Driver to use. */ private Driver driver; /** * The fully qualified Java class name of the JDBC driver to be used. */ private String driverClassName; /** * The class loader instance to use to load the JDBC driver. If not specified, {@link Class#forName(String)} is used * to load the JDBC driver. If specified, {@link Class#forName(String, boolean, ClassLoader)} is used. */ private ClassLoader driverClassLoader; /** * True means that borrowObject returns the most recently used ("last in") connection in the pool (if there are idle * connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle * instance pool in the order that they are returned to the pool. */ private boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO; /** * The maximum number of active connections that can be allocated from this pool at the same time, or negative for * no limit. */ private int maxTotal = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL; /** * The maximum number of connections that can remain idle in the pool, without extra ones being destroyed, or * negative for no limit. If maxIdle is set too low on heavily loaded systems it is possible you will see * connections being closed and almost immediately new connections being opened. This is a result of the active * threads momentarily closing connections faster than they are opening them, causing the number of idle connections * to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good * starting point. */ private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE; /** * The minimum number of active connections that can remain idle in the pool, without extra ones being created when * the evictor runs, or 0 to create none. The pool attempts to ensure that minIdle connections are available when * the idle object evictor runs. The value of this property has no effect unless * {@link #durationBetweenEvictionRuns} has a positive value. */ private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE; /** * The initial number of connections that are created when the pool is started. */ private int initialSize; /** * The maximum Duration that the pool will wait (when there are no available connections) for a * connection to be returned before throwing an exception, or <= 0 to wait indefinitely. */ private Duration maxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT; /** * Prepared statement pooling for this pool. When this property is set to {@code true} both PreparedStatements * and CallableStatements are pooled. */ private boolean poolPreparedStatements; private boolean clearStatementPoolOnReturn; /** *

* The maximum number of open statements that can be allocated from the statement pool at the same time, or negative * for no limit. Since a connection usually only uses one or two statements at a time, this is mostly used to help * detect resource leaks. *

*

* Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall}) are pooled along * with PreparedStatements (produced by {@link Connection#prepareStatement}) and * {@code maxOpenPreparedStatements} limits the total number of prepared or callable statements that may be in * use at a given time. *

*/ private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; /** * The indication of whether objects will be validated as soon as they have been created by the pool. If the object * fails to validate, the borrow operation that triggered the creation will fail. */ private boolean testOnCreate; /** * The indication of whether objects will be validated before being borrowed from the pool. If the object fails to * validate, it will be dropped from the pool, and we will attempt to borrow another. */ private boolean testOnBorrow = true; /** * The indication of whether objects will be validated before being returned to the pool. */ private boolean testOnReturn; /** * 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. */ private Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS; /** * The number of objects to examine during each run of the idle object evictor thread (if any). */ private int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; /** * 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). */ private Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION; /** * The minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the idle * object evictor, with the extra condition that at least "minIdle" connections remain in the pool. Note that * {@code minEvictableIdleTimeMillis} takes precedence over this parameter. See * {@link #getSoftMinEvictableIdleDuration()}. */ private Duration softMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION; private String evictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME; /** * The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to * validate, it will be dropped from the pool. */ private boolean testWhileIdle; /** * The connection password to be passed to our JDBC driver to establish a connection. */ private volatile String password; /** * The connection string to be passed to our JDBC driver to establish a connection. */ private String connectionString; /** * The connection user name to be passed to our JDBC driver to establish a connection. */ private String userName; /** * The SQL query that will be used to validate connections from this pool before returning them to the caller. If * specified, this query MUST be an SQL SELECT statement that returns at least one row. If not * specified, {@link Connection#isValid(int)} will be used to validate connections. */ private volatile String validationQuery; /** * Timeout in seconds before connection validation queries fail. */ private volatile Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1); /** * The fully qualified Java class name of a {@link ConnectionFactory} implementation. */ private String connectionFactoryClassName; /** * These SQL statements run once after a Connection is created. *

* This property can be used for example to run ALTER SESSION SET NLS_SORT=XCYECH in an Oracle Database only once * after connection creation. *

*/ private volatile List connectionInitSqls; /** * Controls access to the underlying connection. */ private boolean accessToUnderlyingConnectionAllowed; private Duration maxConnDuration = Duration.ofMillis(-1); private boolean logExpiredConnections = true; private String jmxName; private boolean registerConnectionMBean = true; private boolean autoCommitOnReturn = true; private boolean rollbackOnReturn = true; private volatile Set disconnectionSqlCodes; /** * A collection of SQL State codes that are not considered fatal disconnection codes. * * @since 2.13.0 */ private volatile Set disconnectionIgnoreSqlCodes; private boolean fastFailValidation; /** * The object pool that internally manages our connections. */ private volatile GenericObjectPool connectionPool; /** * The connection properties that will be sent to our JDBC driver when establishing new connections. * NOTE - The "user" and "password" properties will be passed explicitly, so they do not need to be * included here. */ private Properties connectionProperties = new Properties(); /** * The data source we will use to manage connections. This object should be acquired ONLY by calls * to the {@code createDataSource()} method. */ private volatile DataSource dataSource; /** * The PrintWriter to which log messages should be directed. */ private volatile PrintWriter logWriter = new PrintWriter( new OutputStreamWriter(System.out, StandardCharsets.UTF_8)); private AbandonedConfig abandonedConfig; private boolean closed; /** * Actual name under which this component has been registered. */ private ObjectNameWrapper registeredJmxObjectName; /** * Adds a custom connection property to the set that will be passed to our JDBC driver. This MUST * be called before the first connection is retrieved (along with all the other configuration property setters). * Calls to this method after the connection pool has been initialized have no effect. * * @param name Name of the custom connection property * @param value Value of the custom connection property */ public void addConnectionProperty(final String name, final String value) { connectionProperties.put(name, value); } /** * Closes and releases all idle connections that are currently stored in the connection pool associated with this * data source. *

* Connections that are checked out to clients when this method is invoked are not affected. When client * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the * underlying JDBC connections are closed. *

*

* Attempts to acquire connections using {@link #getConnection()} after this method has been invoked result in * SQLExceptions. To reopen a datasource that has been closed using this method, use {@link #start()}. *

*

* This method is idempotent - i.e., closing an already closed BasicDataSource has no effect and does not generate * exceptions. *

* * @throws SQLException if an error occurs closing idle connections */ @Override public synchronized void close() throws SQLException { if (registeredJmxObjectName != null) { registeredJmxObjectName.unregisterMBean(); registeredJmxObjectName = null; } closed = true; final GenericObjectPool oldPool = connectionPool; connectionPool = null; dataSource = null; try { if (oldPool != null) { oldPool.close(); } } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException(Utils.getMessage("pool.close.fail"), e); } } /** * Closes the connection pool, silently swallowing any exception that occurs. */ private void closeConnectionPool() { final GenericObjectPool oldPool = connectionPool; connectionPool = null; Utils.closeQuietly(oldPool); } /** * Creates a JDBC connection factory for this data source. The JDBC driver is loaded using the following algorithm: *
    *
  1. If a Driver instance has been specified via {@link #setDriver(Driver)} use it
  2. *
  3. If no Driver instance was specified and {code driverClassName} is specified that class is loaded using the * {@link ClassLoader} of this class or, if {code driverClassLoader} is set, {code driverClassName} is loaded * with the specified {@link ClassLoader}.
  4. *
  5. If {code driverClassName} is specified and the previous attempt fails, the class is loaded using the * context class loader of the current thread.
  6. *
  7. If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {code connectionString}. *
*

* This method exists so subclasses can replace the implementation class. *

* * @return A new connection factory. * * @throws SQLException If the connection factory cannot be created */ protected ConnectionFactory createConnectionFactory() throws SQLException { // Load the JDBC driver class return ConnectionFactoryFactory.createConnectionFactory(this, DriverFactory.createDriver(this)); } /** * Creates a connection pool for this datasource. This method only exists so subclasses can replace the * implementation class. *

* This implementation configures all pool properties other than timeBetweenEvictionRunsMillis. Setting that * property is deferred to {@link #startPoolMaintenance()}, since setting timeBetweenEvictionRunsMillis to a * positive value causes {@link GenericObjectPool}'s eviction timer to be started. *

* * @param factory The factory to use to create new connections for this pool. */ protected void createConnectionPool(final PoolableConnectionFactory factory) { // Create an object pool to contain our active connections final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); updateJmxName(config); // Disable JMX on the underlying pool if the DS is not registered: config.setJmxEnabled(registeredJmxObjectName != null); // Set up usage tracking if enabled if (getAbandonedUsageTracking() && abandonedConfig != null) { abandonedConfig.setUseUsageTracking(true); } final GenericObjectPool gop = createObjectPool(factory, config, abandonedConfig); gop.setMaxTotal(maxTotal); gop.setMaxIdle(maxIdle); gop.setMinIdle(minIdle); gop.setMaxWait(maxWaitDuration); gop.setTestOnCreate(testOnCreate); gop.setTestOnBorrow(testOnBorrow); gop.setTestOnReturn(testOnReturn); gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun); gop.setMinEvictableIdleDuration(minEvictableIdleDuration); gop.setSoftMinEvictableIdleDuration(softMinEvictableIdleDuration); gop.setTestWhileIdle(testWhileIdle); gop.setLifo(lifo); gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections)); gop.setEvictionPolicyClassName(evictionPolicyClassName); factory.setPool(gop); connectionPool = gop; } /** * Creates (if necessary) and return the internal data source we are using to manage our connections. * * @return The current internal DataSource or a newly created instance if it has not yet been created. * @throws SQLException if the object pool cannot be created. */ protected synchronized DataSource createDataSource() throws SQLException { if (closed) { throw new SQLException("Data source is closed"); } // Return the pool if we have already created it // This is double-checked locking. This is safe since dataSource is // volatile and the code is targeted at Java 5 onwards. if (dataSource != null) { return dataSource; } synchronized (this) { if (dataSource != null) { return dataSource; } jmxRegister(); // create factory which returns raw physical connections final ConnectionFactory driverConnectionFactory = createConnectionFactory(); // Set up the poolable connection factory final PoolableConnectionFactory poolableConnectionFactory; try { poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory); poolableConnectionFactory.setPoolStatements(poolPreparedStatements); poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); // create a pool for our connections createConnectionPool(poolableConnectionFactory); final DataSource newDataSource = createDataSourceInstance(); newDataSource.setLogWriter(logWriter); connectionPool.addObjects(initialSize); // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor // task startPoolMaintenance(); dataSource = newDataSource; } catch (final SQLException | RuntimeException se) { closeConnectionPool(); throw se; } catch (final Exception ex) { closeConnectionPool(); throw new SQLException("Error creating connection factory", ex); } return dataSource; } } /** * Creates the actual data source instance. This method only exists so that subclasses can replace the * implementation class. * * @throws SQLException if unable to create a datasource instance * * @return A new DataSource instance */ protected DataSource createDataSourceInstance() throws SQLException { final PoolingDataSource pds = new PoolingDataSource<>(connectionPool); pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); return pds; } /** * Creates an object pool used to provide pooling support for {@link Connection JDBC connections}. * * @param factory the object factory * @param poolConfig the object pool configuration * @param abandonedConfig the abandoned objects configuration * @return a non-null instance */ protected GenericObjectPool createObjectPool(final PoolableConnectionFactory factory, final GenericObjectPoolConfig poolConfig, final AbandonedConfig abandonedConfig) { final GenericObjectPool gop; if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow() || abandonedConfig.getRemoveAbandonedOnMaintenance())) { gop = new GenericObjectPool<>(factory, poolConfig, abandonedConfig); } else { gop = new GenericObjectPool<>(factory, poolConfig); } return gop; } /** * Creates the PoolableConnectionFactory and attaches it to the connection pool. This method only exists so * subclasses can replace the default implementation. * * @param driverConnectionFactory JDBC connection factory * @throws SQLException if an error occurs creating the PoolableConnectionFactory * * @return A new PoolableConnectionFactory configured with the current configuration of this BasicDataSource */ protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory) throws SQLException { PoolableConnectionFactory connectionFactory = null; try { if (registerConnectionMBean) { connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, ObjectNameWrapper.unwrap(registeredJmxObjectName)); } else { connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, null); } connectionFactory.setValidationQuery(validationQuery); connectionFactory.setValidationQueryTimeout(validationQueryTimeoutDuration); connectionFactory.setConnectionInitSql(connectionInitSqls); connectionFactory.setDefaultReadOnly(defaultReadOnly); connectionFactory.setDefaultAutoCommit(defaultAutoCommit); connectionFactory.setDefaultTransactionIsolation(defaultTransactionIsolation); connectionFactory.setDefaultCatalog(defaultCatalog); connectionFactory.setDefaultSchema(defaultSchema); connectionFactory.setCacheState(cacheState); connectionFactory.setPoolStatements(poolPreparedStatements); connectionFactory.setClearStatementPoolOnReturn(clearStatementPoolOnReturn); connectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); connectionFactory.setMaxConn(maxConnDuration); connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn()); connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration()); connectionFactory.setFastFailValidation(fastFailValidation); connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes); connectionFactory.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); validateConnectionFactory(connectionFactory); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e); } return connectionFactory; } /** * Manually evicts idle connections * * @throws Exception when there is a problem evicting idle objects. */ public void evict() throws Exception { if (connectionPool != null) { connectionPool.evict(); } } /** * Gets the print writer used by this configuration to log information on abandoned objects. * * @return The print writer used by this configuration to log information on abandoned objects. */ public PrintWriter getAbandonedLogWriter() { return abandonedConfig == null ? null : abandonedConfig.getLogWriter(); } /** * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, should the * connection pool record a stack trace every time a method is called on a pooled connection and retain the most * recent stack trace to aid debugging of abandoned connections? * * @return {@code true} if usage tracking is enabled */ @Override public boolean getAbandonedUsageTracking() { return abandonedConfig != null && abandonedConfig.getUseUsageTracking(); } /** * Gets the value of the flag that controls whether or not connections being returned to the pool will be checked * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit * setting is {@code false} when the connection is returned. It is {@code true} by default. * * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit. */ public boolean getAutoCommitOnReturn() { return autoCommitOnReturn; } /** * Gets the state caching flag. * * @return the state caching flag */ @Override public boolean getCacheState() { return cacheState; } /** * Creates (if necessary) and return a connection to the database. * * @throws SQLException if a database access error occurs * @return a database connection */ @Override public Connection getConnection() throws SQLException { if (Utils.isSecurityEnabled()) { final PrivilegedExceptionAction action = () -> createDataSource().getConnection(); try { return AccessController.doPrivileged(action); } catch (final PrivilegedActionException e) { final Throwable cause = e.getCause(); if (cause instanceof SQLException) { throw (SQLException) cause; } throw new SQLException(e); } } return createDataSource().getConnection(); } /** * BasicDataSource does NOT support this method. * * @param user Database user on whose behalf the Connection is being made * @param pass The database user's password * * @throws UnsupportedOperationException always thrown. * @throws SQLException if a database access error occurs * @return nothing - always throws UnsupportedOperationException */ @Override public Connection getConnection(final String user, final String pass) throws SQLException { // This method isn't supported by the PoolingDataSource returned by the // createDataSource throw new UnsupportedOperationException("Not supported by BasicDataSource"); } /** * Gets the ConnectionFactoryClassName that has been configured for use by this pool. *

* Note: This getter only returns the last value set by a call to {@link #setConnectionFactoryClassName(String)}. *

* * @return the ConnectionFactoryClassName that has been configured for use by this pool. * @since 2.7.0 */ public String getConnectionFactoryClassName() { return this.connectionFactoryClassName; } /** * Gets the list of SQL statements executed when a physical connection is first created. Returns an empty list if * there are no initialization statements configured. * * @return initialization SQL statements */ public List getConnectionInitSqls() { final List result = connectionInitSqls; return result == null ? Collections.emptyList() : result; } /** * Provides the same data as {@link #getConnectionInitSqls()} but in an array so it is accessible via JMX. */ @Override public String[] getConnectionInitSqlsAsArray() { return getConnectionInitSqls().toArray(Utils.EMPTY_STRING_ARRAY); } /** * Gets the underlying connection pool. * * @return the underlying connection pool. * @since 2.10.0 */ public GenericObjectPool getConnectionPool() { return connectionPool; } Properties getConnectionProperties() { return connectionProperties; } /** * Gets the default auto-commit property. * * @return true if default auto-commit is enabled */ @Override public Boolean getDefaultAutoCommit() { return defaultAutoCommit; } /** * Gets the default catalog. * * @return the default catalog */ @Override public String getDefaultCatalog() { return this.defaultCatalog; } /** * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this * connection. {@code null} means that the driver default will be used. * * @return The default query timeout in seconds. * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. */ @Deprecated public Integer getDefaultQueryTimeout() { return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds(); } /** * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this * connection. {@code null} means that the driver default will be used. * * @return The default query timeout Duration. * @since 2.10.0 */ public Duration getDefaultQueryTimeoutDuration() { return defaultQueryTimeoutDuration; } /** * Gets the default readOnly property. * * @return true if connections are readOnly by default */ @Override public Boolean getDefaultReadOnly() { return defaultReadOnly; } /** * Gets the default schema. * * @return the default schema. * @since 2.5.0 */ @Override public String getDefaultSchema() { return this.defaultSchema; } /** * Gets the default transaction isolation state of returned connections. * * @return the default value for transaction isolation state * @see Connection#getTransactionIsolation */ @Override public int getDefaultTransactionIsolation() { return this.defaultTransactionIsolation; } /** * Gets the set of SQL State codes that are not considered fatal disconnection codes. *

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

* * @return a set of SQL State codes that should be ignored for disconnection checks, or an empty set if none have been specified. * @since 2.13.0 */ public Set getDisconnectionIgnoreSqlCodes() { final Set result = disconnectionIgnoreSqlCodes; return result == null ? Collections.emptySet() : result; } /** * Provides the same data as {@link #getDisconnectionIgnoreSqlCodes()} but in an array, so it is accessible via JMX. * * @since 2.13.0 */ @Override public String[] getDisconnectionIgnoreSqlCodesAsArray() { return getDisconnectionIgnoreSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY); } /** * Gets the set of SQL State codes considered to signal fatal conditions. * * @return fatal disconnection state codes * @see #setDisconnectionSqlCodes(Collection) * @since 2.1 */ public Set getDisconnectionSqlCodes() { final Set result = disconnectionSqlCodes; return result == null ? Collections.emptySet() : result; } /** * Provides the same data as {@link #getDisconnectionSqlCodes} but in an array so it is accessible via JMX. * * @since 2.1 */ @Override public String[] getDisconnectionSqlCodesAsArray() { return getDisconnectionSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY); } /** * Gets the JDBC Driver that has been configured for use by this pool. *

* Note: This getter only returns the last value set by a call to {@link #setDriver(Driver)}. It does not return any * driver instance that may have been created from the value set via {@link #setDriverClassName(String)}. *

* * @return the JDBC Driver that has been configured for use by this pool */ public synchronized Driver getDriver() { return driver; } /** * Gets the class loader specified for loading the JDBC driver. Returns {@code null} if no class loader has * been explicitly specified. *

* Note: This getter only returns the last value set by a call to {@link #setDriverClassLoader(ClassLoader)}. It * does not return the class loader of any driver that may have been set via {@link #setDriver(Driver)}. *

* * @return The class loader specified for loading the JDBC driver. */ public synchronized ClassLoader getDriverClassLoader() { return this.driverClassLoader; } /** * Gets the JDBC driver class name. *

* Note: This getter only returns the last value set by a call to {@link #setDriverClassName(String)}. It does not * return the class name of any driver that may have been set via {@link #setDriver(Driver)}. *

* * @return the JDBC driver class name */ @Override public synchronized String getDriverClassName() { return this.driverClassName; } /** * Gets the value of the {code durationBetweenEvictionRuns} property. * * @return the time (in milliseconds) between evictor runs * @see #setDurationBetweenEvictionRuns(Duration) * @since 2.10.0 */ public synchronized Duration getDurationBetweenEvictionRuns() { return this.durationBetweenEvictionRuns; } /** * Gets the value of the flag that controls whether or not connections being returned to the pool will be checked * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit * setting is {@code false} when the connection is returned. It is {@code true} by default. * * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit. * @deprecated Use {@link #getAutoCommitOnReturn()}. */ @Deprecated public boolean getEnableAutoCommitOnReturn() { return autoCommitOnReturn; } /** * Gets the EvictionPolicy implementation in use with this connection pool. * * @return The EvictionPolicy implementation in use with this connection pool. */ public synchronized String getEvictionPolicyClassName() { return evictionPolicyClassName; } /** * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with * SQL State indicating fatal disconnection errors. * * @return true if connections created by this datasource will fast fail validation. * @see #setDisconnectionSqlCodes(Collection) * @see #setDisconnectionIgnoreSqlCodes(Collection) * @since 2.1 */ @Override public boolean getFastFailValidation() { return fastFailValidation; } /** * Gets the initial size of the connection pool. * * @return the number of connections created when the pool is initialized */ @Override public synchronized int getInitialSize() { return this.initialSize; } /** * Gets the JMX name that has been requested for this DataSource. If the requested name is not valid, an * alternative may be chosen. * * @return The JMX name that has been requested for this DataSource. */ public String getJmxName() { return jmxName; } /** * Gets the LIFO property. * * @return true if connection pool behaves as a LIFO queue. */ @Override public synchronized boolean getLifo() { return this.lifo; } /** * Flag to log stack traces for application code which abandoned a Statement or Connection. *

* Defaults to false. *

*

* Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because * a stack trace has to be generated. *

*/ @Override public boolean getLogAbandoned() { return abandonedConfig != null && abandonedConfig.getLogAbandoned(); } /** * When {@link #getMaxConnDuration()} is set to limit connection lifetime, this property determines whether or * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. * * @since 2.1 */ @Override public boolean getLogExpiredConnections() { return logExpiredConnections; } /** * BasicDataSource does NOT support this method. * *

* Gets the login timeout (in seconds) for connecting to the database. *

*

* Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. *

* * @throws SQLException if a database access error occurs * @throws UnsupportedOperationException If the DataSource implementation does not support the login timeout * feature. * @return login timeout in seconds */ @Override public int getLoginTimeout() throws SQLException { // This method isn't supported by the PoolingDataSource returned by the createDataSource throw new UnsupportedOperationException("Not supported by BasicDataSource"); } /** * Gets the log writer being used by this data source. *

* Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. *

* * @throws SQLException if a database access error occurs * @return log writer in use */ @Override public PrintWriter getLogWriter() throws SQLException { return createDataSource().getLogWriter(); } /** * Gets the maximum permitted duration of a connection. A value of zero or less indicates an * infinite lifetime. * @return the maximum permitted duration of a connection. * @since 2.10.0 */ public Duration getMaxConnDuration() { return maxConnDuration; } /** * Gets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an * infinite lifetime. * @deprecated Use {@link #getMaxConnDuration()}. */ @Override @Deprecated public long getMaxConnLifetimeMillis() { return maxConnDuration.toMillis(); } /** * Gets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed * on return to the pool. *

* A negative value indicates that there is no limit *

* * @return the maximum number of idle connections */ @Override public synchronized int getMaxIdle() { return this.maxIdle; } /** * Gets the value of the {@code maxOpenPreparedStatements} property. * * @return the maximum number of open statements */ @Override public synchronized int getMaxOpenPreparedStatements() { return this.maxOpenPreparedStatements; } /** * Gets the maximum number of active connections that can be allocated at the same time. *

* A negative number means that there is no limit. *

* * @return the maximum number of active connections */ @Override public synchronized int getMaxTotal() { return this.maxTotal; } /** * Gets the maximum Duration that the pool will wait for a connection to be returned before throwing an exception. A * value less than or equal to zero means the pool is set to wait indefinitely. * * @return the maxWaitDuration property value. * @since 2.10.0 */ public synchronized Duration getMaxWaitDuration() { return this.maxWaitDuration; } /** * Gets the maximum number of milliseconds that the pool will wait for a connection to be returned before * throwing an exception. A value less than or equal to zero means the pool is set to wait indefinitely. * * @return the maxWaitMillis property value. * @deprecated Use {@link #getMaxWaitDuration()}. */ @Deprecated @Override public synchronized long getMaxWaitMillis() { return this.maxWaitDuration.toMillis(); } /** * Gets the {code minEvictableIdleDuration} property. * * @return the value of the {code minEvictableIdleDuration} property * @see #setMinEvictableIdle(Duration) * @since 2.10.0 */ public synchronized Duration getMinEvictableIdleDuration() { return this.minEvictableIdleDuration; } /** * Gets the {code minEvictableIdleDuration} property. * * @return the value of the {code minEvictableIdleDuration} property * @see #setMinEvictableIdle(Duration) * @deprecated Use {@link #getMinEvictableIdleDuration()}. */ @Deprecated @Override public synchronized long getMinEvictableIdleTimeMillis() { return this.minEvictableIdleDuration.toMillis(); } /** * Gets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections * are available when the idle object evictor runs. The value of this property has no effect unless * {code durationBetweenEvictionRuns} has a positive value. * * @return the minimum number of idle connections * @see GenericObjectPool#getMinIdle() */ @Override public synchronized int getMinIdle() { return this.minIdle; } /** * [Read Only] The current number of active connections that have been allocated from this data source. * * @return the current number of active connections */ @Override public int getNumActive() { // Copy reference to avoid NPE if close happens after null check final GenericObjectPool pool = connectionPool; return pool == null ? 0 : pool.getNumActive(); } /** * [Read Only] The current number of idle connections that are waiting to be allocated from this data source. * * @return the current number of idle connections */ @Override public int getNumIdle() { // Copy reference to avoid NPE if close happens after null check final GenericObjectPool pool = connectionPool; return pool == null ? 0 : pool.getNumIdle(); } /** * Gets the value of the {code numTestsPerEvictionRun} property. * * @return the number of objects to examine during idle object evictor runs * @see #setNumTestsPerEvictionRun(int) */ @Override public synchronized int getNumTestsPerEvictionRun() { return this.numTestsPerEvictionRun; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } /** * Gets the password passed to the JDBC driver to establish connections. * * @return the connection password * @deprecated Exposing passwords via JMX is an Information Exposure issue. */ @Deprecated @Override public String getPassword() { return this.password; } /** * Gets the registered JMX ObjectName. * * @return the registered JMX ObjectName. */ protected ObjectName getRegisteredJmxName() { return ObjectNameWrapper.unwrap(registeredJmxObjectName); } /** * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout when borrowObject is invoked. *

* The default value is false. *

*

* If set to true a connection is considered abandoned and eligible for removal if it has not been used for more * than {@link #getRemoveAbandonedTimeoutDuration() removeAbandonedTimeout} seconds. *

*

* Abandoned connections are identified and removed when {@link #getConnection()} is invoked and all of the * following conditions hold: *

*
    *
  • {@link #getRemoveAbandonedOnBorrow()}
  • *
  • {@link #getNumActive()} > {@link #getMaxTotal()} - 3
  • *
  • {@link #getNumIdle()} < 2
  • *
* * @see #getRemoveAbandonedTimeoutDuration() */ @Override public boolean getRemoveAbandonedOnBorrow() { return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnBorrow(); } /** * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout during pool maintenance. *

* The default value is false. *

*

* If set to true a connection is considered abandoned and eligible for removal if it has not been used for more * than {@link #getRemoveAbandonedTimeoutDuration() removeAbandonedTimeout} seconds. *

* * @see #getRemoveAbandonedTimeoutDuration() */ @Override public boolean getRemoveAbandonedOnMaintenance() { return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnMaintenance(); } /** * Gets the timeout in seconds before an abandoned connection can be removed. *

* Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one * of the execute methods) resets the lastUsed property of the parent connection. *

*

* Abandoned connection cleanup happens when: *

*
    *
  • {@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true
  • *
  • {@link #getNumIdle() numIdle} < 2
  • *
  • {@link #getNumActive() numActive} > {@link #getMaxTotal() maxTotal} - 3
  • *
*

* The default value is 300 seconds. *

* @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}. */ @Deprecated @Override public int getRemoveAbandonedTimeout() { return (int) getRemoveAbandonedTimeoutDuration().getSeconds(); } /** * Gets the timeout before an abandoned connection can be removed. *

* Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one * of the execute methods) resets the lastUsed property of the parent connection. *

*

* Abandoned connection cleanup happens when: *

*
    *
  • {@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true
  • *
  • {@link #getNumIdle() numIdle} < 2
  • *
  • {@link #getNumActive() numActive} > {@link #getMaxTotal() maxTotal} - 3
  • *
*

* The default value is 300 seconds. *

* @return Timeout before an abandoned connection can be removed. * @since 2.10.0 */ public Duration getRemoveAbandonedTimeoutDuration() { return abandonedConfig == null ? Duration.ofSeconds(300) : abandonedConfig.getRemoveAbandonedTimeoutDuration(); } /** * Gets the current value of the flag that controls whether a connection will be rolled back when it is returned to * the pool if auto commit is not enabled and the connection is not read only. * * @return whether a connection will be rolled back when it is returned to the pool. */ public boolean getRollbackOnReturn() { return rollbackOnReturn; } /** * Gets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool. *

* When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value, * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis}, * including the {@code minIdle}, constraint. *

* * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming * there are minIdle idle connections in the pool * @since 2.10.0 */ public synchronized Duration getSoftMinEvictableIdleDuration() { return softMinEvictableIdleDuration; } /** * Gets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool. *

* When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value, * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis}, * including the {@code minIdle}, constraint. *

* * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming * there are minIdle idle connections in the pool * @deprecated Use {@link #getSoftMinEvictableIdleDuration()}. */ @Deprecated @Override public synchronized long getSoftMinEvictableIdleTimeMillis() { return softMinEvictableIdleDuration.toMillis(); } /** * Gets the {code testOnBorrow} property. * * @return true if objects are validated before being borrowed from the pool * * @see #setTestOnBorrow(boolean) */ @Override public synchronized boolean getTestOnBorrow() { return this.testOnBorrow; } /** * Gets the {code testOnCreate} property. * * @return true if objects are validated immediately after they are created by the pool * @see #setTestOnCreate(boolean) */ @Override public synchronized boolean getTestOnCreate() { return this.testOnCreate; } /** * Gets the value of the {code testOnReturn} property. * * @return true if objects are validated before being returned to the pool * @see #setTestOnReturn(boolean) */ public synchronized boolean getTestOnReturn() { return this.testOnReturn; } /** * Gets the value of the {code testWhileIdle} property. * * @return true if objects examined by the idle object evictor are validated * @see #setTestWhileIdle(boolean) */ @Override public synchronized boolean getTestWhileIdle() { return this.testWhileIdle; } /** * Gets the value of the {code durationBetweenEvictionRuns} property. * * @return the time (in milliseconds) between evictor runs * @see #setDurationBetweenEvictionRuns(Duration) * @deprecated Use {@link #getDurationBetweenEvictionRuns()}. */ @Deprecated @Override public synchronized long getTimeBetweenEvictionRunsMillis() { return this.durationBetweenEvictionRuns.toMillis(); } /** * Gets the JDBC connection {code connectionString} property. * * @return the {code connectionString} passed to the JDBC driver to establish connections */ @Override public synchronized String getUrl() { return this.connectionString; } /** * Gets the JDBC connection {code userName} property. * * @return the {code userName} passed to the JDBC driver to establish connections * @deprecated Use {@link #getUserName()}. */ @Deprecated @Override public String getUsername() { return this.userName; } /** * Gets the validation query used to validate connections before returning them. * * @return the SQL validation query * @see #setValidationQuery(String) */ @Override public String getValidationQuery() { return this.validationQuery; } /** * Gets the validation query timeout. * * @return the timeout in seconds before connection validation queries fail. * @deprecated Use {@link #getValidationQueryTimeoutDuration()}. */ @Deprecated @Override public int getValidationQueryTimeout() { return (int) validationQueryTimeoutDuration.getSeconds(); } /** * Gets the validation query timeout. * * @return the timeout in seconds before connection validation queries fail. */ public Duration getValidationQueryTimeoutDuration() { return validationQueryTimeoutDuration; } /** * Manually invalidates a connection, effectively requesting the pool to try to close it, remove it from the pool * and reclaim pool capacity. * * @param connection The Connection to invalidate. * * @throws IllegalStateException if invalidating the connection failed. * @since 2.1 */ @SuppressWarnings("resource") public void invalidateConnection(final Connection connection) throws IllegalStateException { if (connection == null) { return; } if (connectionPool == null) { throw new IllegalStateException("Cannot invalidate connection: ConnectionPool is null."); } final PoolableConnection poolableConnection; try { poolableConnection = connection.unwrap(PoolableConnection.class); if (poolableConnection == null) { throw new IllegalStateException( "Cannot invalidate connection: Connection is not a poolable connection."); } } catch (final SQLException e) { throw new IllegalStateException("Cannot invalidate connection: Unwrapping poolable connection failed.", e); } try { connectionPool.invalidateObject(poolableConnection); } catch (final Exception e) { throw new IllegalStateException("Invalidating connection threw unexpected exception", e); } } /** * Gets the value of the accessToUnderlyingConnectionAllowed property. * * @return true if access to the underlying connection is allowed, false otherwise. */ @Override public synchronized boolean isAccessToUnderlyingConnectionAllowed() { return this.accessToUnderlyingConnectionAllowed; } /** * Returns true if the statement pool is cleared when the connection is returned to its pool. * * @return true if the statement pool is cleared at connection return * @since 2.8.0 */ @Override public boolean isClearStatementPoolOnReturn() { return clearStatementPoolOnReturn; } /** * If true, this data source is closed and no more connections can be retrieved from this data source. * * @return true, if the data source is closed; false otherwise */ @Override public synchronized boolean isClosed() { return closed; } /** * Delegates in a null-safe manner to {@link String#isEmpty()}. * * @param value the string to test, may be null. * @return boolean false if value is null, otherwise {@link String#isEmpty()}. */ private boolean isEmpty(final String value) { return value == null || value.trim().isEmpty(); } /** * Returns true if we are pooling statements. * * @return true if prepared and callable statements are pooled */ @Override public synchronized boolean isPoolPreparedStatements() { return this.poolPreparedStatements; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return iface != null && iface.isInstance(this); } private void jmxRegister() { // Return immediately if this DataSource has already been registered if (registeredJmxObjectName != null) { return; } // Return immediately if no JMX name has been specified final String requestedName = getJmxName(); if (requestedName == null) { return; } registeredJmxObjectName = registerJmxObjectName(requestedName, null); try { final StandardMBean standardMBean = new StandardMBean(this, DataSourceMXBean.class); registeredJmxObjectName.registerMBean(standardMBean); } catch (final NotCompliantMBeanException e) { log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored."); } } /** * Logs the given message. * * @param message the message to log. */ protected void log(final String message) { if (logWriter != null) { logWriter.println(message); } } /** * Logs the given message and throwable. * * @param message value to be log. * @param throwable the throwable. * @since 2.7.0 */ protected void log(final String message, final Throwable throwable) { if (logWriter != null) { logWriter.println(message); throwable.printStackTrace(logWriter); } } @Override public void postDeregister() { // NO-OP } @Override public void postRegister(final Boolean registrationDone) { // NO-OP } @Override public void preDeregister() throws Exception { // NO-OP } @Override public ObjectName preRegister(final MBeanServer server, final ObjectName objectName) { registeredJmxObjectName = registerJmxObjectName(getJmxName(), objectName); return ObjectNameWrapper.unwrap(registeredJmxObjectName); } private ObjectNameWrapper registerJmxObjectName(final String requestedName, final ObjectName objectName) { ObjectNameWrapper objectNameWrapper = null; if (requestedName != null) { try { objectNameWrapper = ObjectNameWrapper.wrap(requestedName); } catch (final MalformedObjectNameException e) { log.warn("The requested JMX name '" + requestedName + "' was not valid and will be ignored."); } } if (objectNameWrapper == null) { objectNameWrapper = ObjectNameWrapper.wrap(objectName); } return objectNameWrapper; } /** * Removes a custom connection property. * * @param name Name of the custom connection property to remove * @see #addConnectionProperty(String, String) */ public void removeConnectionProperty(final String name) { connectionProperties.remove(name); } /** * Restarts the datasource. *

* This method calls {@link #close()} and {@link #start()} in sequence within synchronized scope so any * connection requests that come in while the datasource is shutting down will be served by the new pool. *

* Idle connections that are stored in the connection pool when this method is invoked are closed, but * connections that are checked out to clients when this method is invoked are not affected. When client * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the * underlying JDBC connections are closed. These connections do not count in {@link #getMaxTotal()} or * {@link #getNumActive()} after invoking this method. For example, if there are 3 connections checked out by * clients when {@link #restart()} is invoked, after this method is called, {@link #getNumActive()} will * return 0 and up to {@link #getMaxTotal()} + 3 connections may be open until the connections sourced from * the original pool are returned. *

* The new connection pool created by this method is initialized with currently set configuration properties. * * @throws SQLException if an error occurs initializing the datasource */ @Override public synchronized void restart() throws SQLException { close(); start(); } private void setAbandoned(final BiConsumer consumer, final T object) { if (abandonedConfig == null) { abandonedConfig = new AbandonedConfig(); } consumer.accept(abandonedConfig, object); final GenericObjectPool gop = this.connectionPool; if (gop != null) { gop.setAbandonedConfig(abandonedConfig); } } /** * Sets the print writer to be used by this configuration to log information on abandoned objects. * * @param logWriter The new log writer */ public void setAbandonedLogWriter(final PrintWriter logWriter) { setAbandoned(AbandonedConfig::setLogWriter, logWriter); } /** * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, configure whether * the connection pool should record a stack trace every time a method is called on a pooled connection and retain * the most recent stack trace to aid debugging of abandoned connections. * * @param usageTracking A value of {@code true} will enable the recording of a stack trace on every use of a * pooled connection */ public void setAbandonedUsageTracking(final boolean usageTracking) { setAbandoned(AbandonedConfig::setUseUsageTracking, usageTracking); } /** * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to * the underlying connection. (Default: false) *

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

* * @param allow Access to the underlying connection is granted when true. */ public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) { this.accessToUnderlyingConnectionAllowed = allow; } /** * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit * setting is {@code false} when the connection is returned. It is {@code true} by default. * * @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured * with auto-commit. * @since 2.6.0 */ public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { this.autoCommitOnReturn = autoCommitOnReturn; } /** * Sets the state caching flag. * * @param cacheState The new value for the state caching flag */ public void setCacheState(final boolean cacheState) { this.cacheState = cacheState; } /** * Sets whether the pool of statements (which was enabled with {@link #setPoolPreparedStatements(boolean)}) should * be cleared when the connection is returned to its pool. Default is false. * * @param clearStatementPoolOnReturn clear or not * @since 2.8.0 */ public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) { this.clearStatementPoolOnReturn = clearStatementPoolOnReturn; } /** * Sets the ConnectionFactory class name. * * @param connectionFactoryClassName A class name. * @since 2.7.0 */ public void setConnectionFactoryClassName(final String connectionFactoryClassName) { this.connectionFactoryClassName = isEmpty(connectionFactoryClassName) ? null : connectionFactoryClassName; } /** * Sets the collection of SQL statements to be executed when a physical connection is first created. *

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

* * @param connectionInitSqls Collection of SQL statements to execute on connection creation */ public void setConnectionInitSqls(final Collection connectionInitSqls) { final List collect = Utils.isEmpty(connectionInitSqls) ? null : connectionInitSqls.stream().filter(s -> !isEmpty(s)).collect(Collectors.toList()); this.connectionInitSqls = Utils.isEmpty(collect) ? null : collect; } /** * Sets the list of SQL statements to be executed when a physical connection is first created. *

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

* * @param connectionInitSqls List of SQL statements to execute on connection creation * @since 2.12.0 */ public void setConnectionInitSqls(final List connectionInitSqls) { setConnectionInitSqls((Collection) connectionInitSqls); } private void setConnectionPool(final BiConsumer, T> consumer, final T object) { if (connectionPool != null) { consumer.accept(connectionPool, object); } } /** * Sets the connection properties passed to driver.connect(...). *

* Format of the string must be [propertyName=property;]* *

*

* NOTE - The "user" and "password" properties will be added explicitly, so they do not need to be included here. *

* * @param connectionProperties the connection properties used to create new connections */ public void setConnectionProperties(final String connectionProperties) { Objects.requireNonNull(connectionProperties, "connectionProperties"); final String[] entries = connectionProperties.split(";"); final Properties properties = new Properties(); Stream.of(entries).filter(e -> !e.isEmpty()).forEach(entry -> { final int index = entry.indexOf('='); if (index > 0) { final String name = entry.substring(0, index); final String value = entry.substring(index + 1); properties.setProperty(name, value); } else { // no value is empty string which is how // java.util.Properties works properties.setProperty(entry, ""); } }); this.connectionProperties = properties; } /** * Sets default auto-commit state of connections returned by this datasource. *

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

* * @param defaultAutoCommit default auto-commit value */ public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { this.defaultAutoCommit = defaultAutoCommit; } /** * Sets the default catalog. *

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

* * @param defaultCatalog the default catalog */ public void setDefaultCatalog(final String defaultCatalog) { this.defaultCatalog = isEmpty(defaultCatalog) ? null : defaultCatalog; } /** * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this * connection. {@code null} means that the driver default will be used. * * @param defaultQueryTimeoutDuration The default query timeout Duration. * @since 2.10.0 */ public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) { this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration; } /** * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this * connection. {@code null} means that the driver default will be used. * * @param defaultQueryTimeoutSeconds The default query timeout in seconds. * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}. */ @Deprecated public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds); } /** * Sets defaultReadonly property. *

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

* * @param defaultReadOnly default read-only value */ public void setDefaultReadOnly(final Boolean defaultReadOnly) { this.defaultReadOnly = defaultReadOnly; } /** * Sets the default schema. *

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

* * @param defaultSchema the default catalog * @since 2.5.0 */ public void setDefaultSchema(final String defaultSchema) { this.defaultSchema = isEmpty(defaultSchema) ? null : defaultSchema; } /** * Sets the default transaction isolation state for returned connections. *

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

* * @param defaultTransactionIsolation the default transaction isolation state * @see Connection#getTransactionIsolation */ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { this.defaultTransactionIsolation = defaultTransactionIsolation; } /** * Sets the SQL State codes that should be ignored when determining fatal disconnection conditions. *

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

*

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

*

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

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

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

*

* If {@link #getFastFailValidation()} is {@code false} setting this property has no effect. *

*

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

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

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

* * @param driver The JDBC Driver instance to use for this pool. */ public synchronized void setDriver(final Driver driver) { this.driver = driver; } /** * Sets the class loader to be used to load the JDBC driver. *

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

* * @param driverClassLoader the class loader with which to load the JDBC driver */ public synchronized void setDriverClassLoader(final ClassLoader driverClassLoader) { this.driverClassLoader = driverClassLoader; } /** * Sets the JDBC driver class name. *

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

* * @param driverClassName the class name of the JDBC driver */ public synchronized void setDriverClassName(final String driverClassName) { this.driverClassName = isEmpty(driverClassName) ? null : driverClassName; } /** * Sets the {code durationBetweenEvictionRuns} property. * * @param timeBetweenEvictionRunsMillis the new time between evictor runs * @see #setDurationBetweenEvictionRuns(Duration) * @since 2.10.0 */ public synchronized void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRunsMillis) { this.durationBetweenEvictionRuns = timeBetweenEvictionRunsMillis; setConnectionPool(GenericObjectPool::setDurationBetweenEvictionRuns, timeBetweenEvictionRunsMillis); } /** * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit * setting is {@code false} when the connection is returned. It is {@code true} by default. * * @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured * with auto-commit. * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}. */ @Deprecated public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) { this.autoCommitOnReturn = autoCommitOnReturn; } /** * Sets the EvictionPolicy implementation to use with this connection pool. * * @param evictionPolicyClassName The fully qualified class name of the EvictionPolicy implementation */ public synchronized void setEvictionPolicyClassName(final String evictionPolicyClassName) { setConnectionPool(GenericObjectPool::setEvictionPolicyClassName, evictionPolicyClassName); this.evictionPolicyClassName = evictionPolicyClassName; } /** * @see #getFastFailValidation() * @param fastFailValidation true means connections created by this factory will fast fail validation * @since 2.1 */ public void setFastFailValidation(final boolean fastFailValidation) { this.fastFailValidation = fastFailValidation; } /** * Sets the initial size of the connection pool. *

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

* * @param initialSize the number of connections created when the pool is initialized */ public synchronized void setInitialSize(final int initialSize) { this.initialSize = initialSize; } /** * Sets the JMX name that has been requested for this DataSource. If the requested name is not valid, an alternative * may be chosen. This DataSource will attempt to register itself using this name. If another component registers * this DataSource with JMX and this name is valid this name will be used in preference to any specified by the * other component. * * @param jmxName The JMX name that has been requested for this DataSource */ public void setJmxName(final String jmxName) { this.jmxName = jmxName; } /** * Sets the LIFO property. True means the pool behaves as a LIFO queue; false means FIFO. * * @param lifo the new value for the LIFO property */ public synchronized void setLifo(final boolean lifo) { this.lifo = lifo; setConnectionPool(GenericObjectPool::setLifo, lifo); } /** * @param logAbandoned new logAbandoned property value */ public void setLogAbandoned(final boolean logAbandoned) { setAbandoned(AbandonedConfig::setLogAbandoned, logAbandoned); } /** * When {@link #getMaxConnDuration()} is set to limit connection lifetime, this property determines whether or * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. Set this * property to false to suppress log messages when connections expire. * * @param logExpiredConnections Whether or not log messages are generated when the pool closes connections due to * maximum lifetime exceeded. */ public void setLogExpiredConnections(final boolean logExpiredConnections) { this.logExpiredConnections = logExpiredConnections; } /** * BasicDataSource does NOT support this method. * *

* Sets the login timeout (in seconds) for connecting to the database. *

*

* Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. *

* * @param loginTimeout The new login timeout, or zero for no timeout * @throws UnsupportedOperationException If the DataSource implementation does not support the login timeout * feature. * @throws SQLException if a database access error occurs */ @Override public void setLoginTimeout(final int loginTimeout) throws SQLException { // This method isn't supported by the PoolingDataSource returned by the // createDataSource throw new UnsupportedOperationException("Not supported by BasicDataSource"); } /** * Sets the log writer being used by this data source. *

* Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. *

* * @param logWriter The new log writer * @throws SQLException if a database access error occurs */ @Override public void setLogWriter(final PrintWriter logWriter) throws SQLException { createDataSource().setLogWriter(logWriter); this.logWriter = logWriter; } /** * Sets the maximum permitted lifetime of a connection. A value of zero or less indicates an * infinite lifetime. *

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

* * @param maxConnDuration The maximum permitted lifetime of a connection. * @since 2.10.0 */ public void setMaxConn(final Duration maxConnDuration) { this.maxConnDuration = maxConnDuration; } /** * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an * infinite lifetime. *

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

* * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds. * @deprecated Use {@link #setMaxConn(Duration)}. */ @Deprecated public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis); } /** * Sets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed on * return to the pool. * * @see #getMaxIdle() * @param maxIdle the new value for maxIdle */ public synchronized void setMaxIdle(final int maxIdle) { this.maxIdle = maxIdle; setConnectionPool(GenericObjectPool::setMaxIdle, maxIdle); } /** * Sets the value of the {@code maxOpenPreparedStatements} property. *

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

* * @param maxOpenStatements the new maximum number of prepared statements */ public synchronized void setMaxOpenPreparedStatements(final int maxOpenStatements) { this.maxOpenPreparedStatements = maxOpenStatements; } /** * Sets the maximum total number of idle and borrows connections that can be active at the same time. Use a negative * value for no limit. * * @param maxTotal the new value for maxTotal * @see #getMaxTotal() */ public synchronized void setMaxTotal(final int maxTotal) { this.maxTotal = maxTotal; setConnectionPool(GenericObjectPool::setMaxTotal, maxTotal); } /** * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely. * * @param maxWaitDuration the new value for MaxWaitMillis * @see #getMaxWaitDuration() * @since 2.10.0 */ public synchronized void setMaxWait(final Duration maxWaitDuration) { this.maxWaitDuration = maxWaitDuration; setConnectionPool(GenericObjectPool::setMaxWait, maxWaitDuration); } /** * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely. * * @param maxWaitMillis the new value for MaxWaitMillis * @see #getMaxWaitDuration() * @deprecated {@link #setMaxWait(Duration)}. */ @Deprecated public synchronized void setMaxWaitMillis(final long maxWaitMillis) { setMaxWait(Duration.ofMillis(maxWaitMillis)); } /** * Sets the {code minEvictableIdleDuration} property. * * @param minEvictableIdleDuration the minimum amount of time an object may sit idle in the pool * @see #setMinEvictableIdle(Duration) * @since 2.10.0 */ public synchronized void setMinEvictableIdle(final Duration minEvictableIdleDuration) { this.minEvictableIdleDuration = minEvictableIdleDuration; setConnectionPool(GenericObjectPool::setMinEvictableIdleDuration, minEvictableIdleDuration); } /** * Sets the {code minEvictableIdleDuration} property. * * @param minEvictableIdleTimeMillis the minimum amount of time an object may sit idle in the pool * @see #setMinEvictableIdle(Duration) * @deprecated Use {@link #setMinEvictableIdle(Duration)}. */ @Deprecated public synchronized void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { setMinEvictableIdle(Duration.ofMillis(minEvictableIdleTimeMillis)); } /** * Sets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections are * available when the idle object evictor runs. The value of this property has no effect unless * {code durationBetweenEvictionRuns} has a positive value. * * @param minIdle the new value for minIdle * @see GenericObjectPool#setMinIdle(int) */ public synchronized void setMinIdle(final int minIdle) { this.minIdle = minIdle; setConnectionPool(GenericObjectPool::setMinIdle, minIdle); } /** * Sets the value of the {code numTestsPerEvictionRun} property. * * @param numTestsPerEvictionRun the new {code numTestsPerEvictionRun} value * @see #setNumTestsPerEvictionRun(int) */ public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { this.numTestsPerEvictionRun = numTestsPerEvictionRun; setConnectionPool(GenericObjectPool::setNumTestsPerEvictionRun, numTestsPerEvictionRun); } /** * Sets the {code password}. *

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

* * @param password new value for the password */ public void setPassword(final String password) { this.password = password; } /** * Sets whether to pool statements or not. *

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

* * @param poolingStatements pooling on or off */ public synchronized void setPoolPreparedStatements(final boolean poolingStatements) { this.poolPreparedStatements = poolingStatements; } /** * Sets if connection level JMX tracking is requested for this DataSource. If true, each connection will be * registered for tracking with JMX. * * @param registerConnectionMBean connection tracking requested for this DataSource. */ public void setRegisterConnectionMBean(final boolean registerConnectionMBean) { this.registerConnectionMBean = registerConnectionMBean; } /** * @param removeAbandonedOnBorrow true means abandoned connections may be removed when connections are borrowed from * the pool. * @see #getRemoveAbandonedOnBorrow() */ public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) { setAbandoned(AbandonedConfig::setRemoveAbandonedOnBorrow, removeAbandonedOnBorrow); } /** * @param removeAbandonedOnMaintenance true means abandoned connections may be removed on pool maintenance. * @see #getRemoveAbandonedOnMaintenance() */ public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) { setAbandoned(AbandonedConfig::setRemoveAbandonedOnMaintenance, removeAbandonedOnMaintenance); } /** * Sets the timeout before an abandoned connection can be removed. *

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

* * @param removeAbandonedTimeout new abandoned timeout * @see #getRemoveAbandonedTimeoutDuration() * @see #getRemoveAbandonedOnBorrow() * @see #getRemoveAbandonedOnMaintenance() * @since 2.10.0 */ public void setRemoveAbandonedTimeout(final Duration removeAbandonedTimeout) { setAbandoned(AbandonedConfig::setRemoveAbandonedTimeout, removeAbandonedTimeout); } /** * Sets the timeout in seconds before an abandoned connection can be removed. *

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

* * @param removeAbandonedTimeout new abandoned timeout in seconds * @see #getRemoveAbandonedTimeoutDuration() * @see #getRemoveAbandonedOnBorrow() * @see #getRemoveAbandonedOnMaintenance() * @deprecated Use {@link #setRemoveAbandonedTimeout(Duration)}. */ @Deprecated public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) { setAbandoned(AbandonedConfig::setRemoveAbandonedTimeout, Duration.ofSeconds(removeAbandonedTimeout)); } /** * Sets the flag that controls if a connection will be rolled back when it is returned to the pool if auto commit is * not enabled and the connection is not read only. * * @param rollbackOnReturn whether a connection will be rolled back when it is returned to the pool. */ public void setRollbackOnReturn(final boolean rollbackOnReturn) { this.rollbackOnReturn = rollbackOnReturn; } /** * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool. * * @param softMinEvictableIdleTimeMillis minimum amount of time a connection may sit idle in the pool before it is * eligible for eviction, assuming there are minIdle idle connections in the * pool. * @see #getSoftMinEvictableIdleTimeMillis * @since 2.10.0 */ public synchronized void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTimeMillis) { this.softMinEvictableIdleDuration = softMinEvictableIdleTimeMillis; setConnectionPool(GenericObjectPool::setSoftMinEvictableIdleDuration, softMinEvictableIdleTimeMillis); } /** * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool. * * @param softMinEvictableIdleTimeMillis minimum amount of time a connection may sit idle in the pool before it is * eligible for eviction, assuming there are minIdle idle connections in the * pool. * @see #getSoftMinEvictableIdleTimeMillis * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}. */ @Deprecated public synchronized void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { setSoftMinEvictableIdle(Duration.ofMillis(softMinEvictableIdleTimeMillis)); } /** * Sets the {code testOnBorrow} property. This property determines whether or not the pool will validate objects * before they are borrowed from the pool. * * @param testOnBorrow new value for testOnBorrow property */ public synchronized void setTestOnBorrow(final boolean testOnBorrow) { this.testOnBorrow = testOnBorrow; setConnectionPool(GenericObjectPool::setTestOnBorrow, testOnBorrow); } /** * Sets the {code testOnCreate} property. This property determines whether or not the pool will validate objects * immediately after they are created by the pool * * @param testOnCreate new value for testOnCreate property */ public synchronized void setTestOnCreate(final boolean testOnCreate) { this.testOnCreate = testOnCreate; setConnectionPool(GenericObjectPool::setTestOnCreate, testOnCreate); } /** * Sets the {@code testOnReturn} property. This property determines whether or not the pool will validate * objects before they are returned to the pool. * * @param testOnReturn new value for testOnReturn property */ public synchronized void setTestOnReturn(final boolean testOnReturn) { this.testOnReturn = testOnReturn; setConnectionPool(GenericObjectPool::setTestOnReturn, testOnReturn); } /** * Sets the {@code testWhileIdle} property. This property determines whether or not the idle object evictor * will validate connections. * * @param testWhileIdle new value for testWhileIdle property */ public synchronized void setTestWhileIdle(final boolean testWhileIdle) { this.testWhileIdle = testWhileIdle; setConnectionPool(GenericObjectPool::setTestWhileIdle, testWhileIdle); } /** * Sets the {code durationBetweenEvictionRuns} property. * * @param timeBetweenEvictionRunsMillis the new time between evictor runs * @see #setDurationBetweenEvictionRuns(Duration) * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}. */ @Deprecated public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { setDurationBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis)); } /** * Sets the {code connection string}. *

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

* * @param connectionString the new value for the JDBC connection connectionString */ public synchronized void setUrl(final String connectionString) { this.connectionString = connectionString; } /** * Sets the {code userName}. *

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

* * @param userName the new value for the JDBC connection user name */ public void setUsername(final String userName) { this.userName = userName; } /** * Sets the {code validationQuery}. *

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

* * @param validationQuery the new value for the validation query */ public void setValidationQuery(final String validationQuery) { this.validationQuery = isEmpty(validationQuery) ? null : validationQuery; } /** * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. *

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

* * @param validationQueryTimeoutDuration new validation query timeout value in seconds * @since 2.10.0 */ public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) { this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; } /** * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. *

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

* * @param validationQueryTimeoutSeconds new validation query timeout value in seconds * @deprecated Use {@link #setValidationQueryTimeout(Duration)}. */ @Deprecated public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); } /** * Starts the datasource. *

* It is not necessary to call this method before using a newly created BasicDataSource instance, but * calling it in that context causes the datasource to be immediately initialized (instead of waiting for * the first {@link #getConnection()} request). Its primary use is to restart and reinitialize a * datasource that has been closed. *

* When this method is called after {@link #close()}, connections checked out by clients * before the datasource was stopped do not count in {@link #getMaxTotal()} or {@link #getNumActive()}. * For example, if there are 3 connections checked out by clients when {@link #close()} is invoked and they are * not returned before {@link #start()} is invoked, after this method is called, {@link #getNumActive()} will * return 0. These connections will be physically closed when they are returned, but they will not count against * the maximum allowed in the newly started datasource. * * @throws SQLException if an error occurs initializing the datasource */ @Override public synchronized void start() throws SQLException { closed = false; createDataSource(); } /** * Starts the connection pool maintenance task, if configured. */ protected void startPoolMaintenance() { if (connectionPool != null && durationBetweenEvictionRuns.compareTo(Duration.ZERO) > 0) { connectionPool.setDurationBetweenEvictionRuns(durationBetweenEvictionRuns); } } private Collector> toLinkedHashSet() { return Collectors.toCollection(LinkedHashSet::new); } @Override public T unwrap(final Class iface) throws SQLException { if (isWrapperFor(iface)) { return iface.cast(this); } throw new SQLException(this + " is not a wrapper for " + iface); } private void updateJmxName(final GenericObjectPoolConfig config) { if (registeredJmxObjectName == null) { return; } final StringBuilder base = new StringBuilder(registeredJmxObjectName.toString()); base.append(Constants.JMX_CONNECTION_POOL_BASE_EXT); config.setJmxNameBase(base.toString()); config.setJmxNamePrefix(Constants.JMX_CONNECTION_POOL_PREFIX); } } BasicDataSourceFactory.java000066400000000000000000000634211472045345700335570ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Properties; import java.util.StringTokenizer; import java.util.function.Consumer; import java.util.function.Function; import javax.naming.Context; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.pool2.impl.BaseObjectPoolConfig; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; /** * JNDI object factory that creates an instance of {@code BasicDataSource} that has been configured based on the * {@code RefAddr} values of the specified {@code Reference}, which must match the names and data types of the * {@code BasicDataSource} bean properties with the following exceptions: *

    *
  • {@code connectionInitSqls} must be passed to this factory as a single String using semicolon to delimit the * statements whereas {@code BasicDataSource} requires a collection of Strings.
  • *
* * @since 2.0 */ public class BasicDataSourceFactory implements ObjectFactory { private static final Log log = LogFactory.getLog(BasicDataSourceFactory.class); private static final String PROP_DEFAULT_AUTO_COMMIT = "defaultAutoCommit"; private static final String PROP_DEFAULT_READ_ONLY = "defaultReadOnly"; private static final String PROP_DEFAULT_TRANSACTION_ISOLATION = "defaultTransactionIsolation"; private static final String PROP_DEFAULT_CATALOG = "defaultCatalog"; private static final String PROP_DEFAULT_SCHEMA = "defaultSchema"; private static final String PROP_CACHE_STATE = "cacheState"; private static final String PROP_DRIVER_CLASS_NAME = "driverClassName"; private static final String PROP_LIFO = "lifo"; private static final String PROP_MAX_TOTAL = "maxTotal"; private static final String PROP_MAX_IDLE = "maxIdle"; private static final String PROP_MIN_IDLE = "minIdle"; private static final String PROP_INITIAL_SIZE = "initialSize"; private static final String PROP_MAX_WAIT_MILLIS = "maxWaitMillis"; private static final String PROP_TEST_ON_CREATE = "testOnCreate"; private static final String PROP_TEST_ON_BORROW = "testOnBorrow"; private static final String PROP_TEST_ON_RETURN = "testOnReturn"; private static final String PROP_TIME_BETWEEN_EVICTION_RUNS_MILLIS = "timeBetweenEvictionRunsMillis"; private static final String PROP_NUM_TESTS_PER_EVICTION_RUN = "numTestsPerEvictionRun"; private static final String PROP_MIN_EVICTABLE_IDLE_TIME_MILLIS = "minEvictableIdleTimeMillis"; private static final String PROP_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = "softMinEvictableIdleTimeMillis"; private static final String PROP_EVICTION_POLICY_CLASS_NAME = "evictionPolicyClassName"; private static final String PROP_TEST_WHILE_IDLE = "testWhileIdle"; private static final String PROP_PASSWORD = Constants.KEY_PASSWORD; private static final String PROP_URL = "url"; private static final String PROP_USER_NAME = "username"; private static final String PROP_VALIDATION_QUERY = "validationQuery"; private static final String PROP_VALIDATION_QUERY_TIMEOUT = "validationQueryTimeout"; private static final String PROP_JMX_NAME = "jmxName"; private static final String PROP_REGISTER_CONNECTION_MBEAN = "registerConnectionMBean"; private static final String PROP_CONNECTION_FACTORY_CLASS_NAME = "connectionFactoryClassName"; /** * The property name for connectionInitSqls. The associated value String must be of the form [query;]* */ private static final String PROP_CONNECTION_INIT_SQLS = "connectionInitSqls"; private static final String PROP_ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED = "accessToUnderlyingConnectionAllowed"; private static final String PROP_REMOVE_ABANDONED_ON_BORROW = "removeAbandonedOnBorrow"; private static final String PROP_REMOVE_ABANDONED_ON_MAINTENANCE = "removeAbandonedOnMaintenance"; private static final String PROP_REMOVE_ABANDONED_TIMEOUT = "removeAbandonedTimeout"; private static final String PROP_LOG_ABANDONED = "logAbandoned"; private static final String PROP_ABANDONED_USAGE_TRACKING = "abandonedUsageTracking"; private static final String PROP_POOL_PREPARED_STATEMENTS = "poolPreparedStatements"; private static final String PROP_CLEAR_STATEMENT_POOL_ON_RETURN = "clearStatementPoolOnReturn"; private static final String PROP_MAX_OPEN_PREPARED_STATEMENTS = "maxOpenPreparedStatements"; private static final String PROP_CONNECTION_PROPERTIES = "connectionProperties"; private static final String PROP_MAX_CONN_LIFETIME_MILLIS = "maxConnLifetimeMillis"; private static final String PROP_LOG_EXPIRED_CONNECTIONS = "logExpiredConnections"; private static final String PROP_ROLLBACK_ON_RETURN = "rollbackOnReturn"; private static final String PROP_ENABLE_AUTO_COMMIT_ON_RETURN = "enableAutoCommitOnReturn"; private static final String PROP_DEFAULT_QUERY_TIMEOUT = "defaultQueryTimeout"; private static final String PROP_FAST_FAIL_VALIDATION = "fastFailValidation"; /** * Value string must be of the form [STATE_CODE,]* */ private static final String PROP_DISCONNECTION_SQL_CODES = "disconnectionSqlCodes"; /** * Property key for specifying the SQL State codes that should be ignored during disconnection checks. *

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

* @since 2.13.0 */ private static final String PROP_DISCONNECTION_IGNORE_SQL_CODES = "disconnectionIgnoreSqlCodes"; /* * Block with obsolete properties from DBCP 1.x. Warn users that these are ignored and they should use the 2.x * properties. */ private static final String NUPROP_MAX_ACTIVE = "maxActive"; private static final String NUPROP_REMOVE_ABANDONED = "removeAbandoned"; private static final String NUPROP_MAXWAIT = "maxWait"; /* * Block with properties expected in a DataSource This props will not be listed as ignored - we know that they may * appear in Resource, and not listing them as ignored. */ private static final String SILENT_PROP_FACTORY = "factory"; private static final String SILENT_PROP_SCOPE = "scope"; private static final String SILENT_PROP_SINGLETON = "singleton"; private static final String SILENT_PROP_AUTH = "auth"; private static final List ALL_PROPERTY_NAMES = Arrays.asList(PROP_DEFAULT_AUTO_COMMIT, PROP_DEFAULT_READ_ONLY, PROP_DEFAULT_TRANSACTION_ISOLATION, PROP_DEFAULT_CATALOG, PROP_DEFAULT_SCHEMA, PROP_CACHE_STATE, PROP_DRIVER_CLASS_NAME, PROP_LIFO, PROP_MAX_TOTAL, PROP_MAX_IDLE, PROP_MIN_IDLE, PROP_INITIAL_SIZE, PROP_MAX_WAIT_MILLIS, PROP_TEST_ON_CREATE, PROP_TEST_ON_BORROW, PROP_TEST_ON_RETURN, PROP_TIME_BETWEEN_EVICTION_RUNS_MILLIS, PROP_NUM_TESTS_PER_EVICTION_RUN, PROP_MIN_EVICTABLE_IDLE_TIME_MILLIS, PROP_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS, PROP_EVICTION_POLICY_CLASS_NAME, PROP_TEST_WHILE_IDLE, PROP_PASSWORD, PROP_URL, PROP_USER_NAME, PROP_VALIDATION_QUERY, PROP_VALIDATION_QUERY_TIMEOUT, PROP_CONNECTION_INIT_SQLS, PROP_ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED, PROP_REMOVE_ABANDONED_ON_BORROW, PROP_REMOVE_ABANDONED_ON_MAINTENANCE, PROP_REMOVE_ABANDONED_TIMEOUT, PROP_LOG_ABANDONED, PROP_ABANDONED_USAGE_TRACKING, PROP_POOL_PREPARED_STATEMENTS, PROP_CLEAR_STATEMENT_POOL_ON_RETURN, PROP_MAX_OPEN_PREPARED_STATEMENTS, PROP_CONNECTION_PROPERTIES, PROP_MAX_CONN_LIFETIME_MILLIS, PROP_LOG_EXPIRED_CONNECTIONS, PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTO_COMMIT_ON_RETURN, PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_DISCONNECTION_IGNORE_SQL_CODES, PROP_JMX_NAME, PROP_REGISTER_CONNECTION_MBEAN, PROP_CONNECTION_FACTORY_CLASS_NAME); /** * Obsolete properties from DBCP 1.x. with warning strings suggesting new properties. LinkedHashMap will guarantee * that properties will be listed to output in order of insertion into map. */ private static final Map NUPROP_WARNTEXT = new LinkedHashMap<>(); static { NUPROP_WARNTEXT.put(NUPROP_MAX_ACTIVE, "Property " + NUPROP_MAX_ACTIVE + " is not used in DBCP2, use " + PROP_MAX_TOTAL + " instead. " + PROP_MAX_TOTAL + " default value is " + GenericObjectPoolConfig.DEFAULT_MAX_TOTAL + "."); NUPROP_WARNTEXT.put(NUPROP_REMOVE_ABANDONED, "Property " + NUPROP_REMOVE_ABANDONED + " is not used in DBCP2," + " use one or both of " + PROP_REMOVE_ABANDONED_ON_BORROW + " or " + PROP_REMOVE_ABANDONED_ON_MAINTENANCE + " instead. " + "Both have default value set to false."); NUPROP_WARNTEXT.put(NUPROP_MAXWAIT, "Property " + NUPROP_MAXWAIT + " is not used in DBCP2" + " , use " + PROP_MAX_WAIT_MILLIS + " instead. " + PROP_MAX_WAIT_MILLIS + " default value is " + BaseObjectPoolConfig.DEFAULT_MAX_WAIT + "."); } /** * Silent Properties. These properties will not be listed as ignored - we know that they may appear in JDBC Resource * references, and we will not list them as ignored. */ private static final List SILENT_PROPERTIES = new ArrayList<>(); static { SILENT_PROPERTIES.add(SILENT_PROP_FACTORY); SILENT_PROPERTIES.add(SILENT_PROP_SCOPE); SILENT_PROPERTIES.add(SILENT_PROP_SINGLETON); SILENT_PROPERTIES.add(SILENT_PROP_AUTH); } private static void accept(final Properties properties, final String name, final Function parser, final Consumer consumer) { getOptional(properties, name).ifPresent(v -> consumer.accept(parser.apply(v))); } private static void acceptBoolean(final Properties properties, final String name, final Consumer consumer) { accept(properties, name, Boolean::parseBoolean, consumer); } private static void acceptDurationOfMillis(final Properties properties, final String name, final Consumer consumer) { accept(properties, name, s -> Duration.ofMillis(Long.parseLong(s)), consumer); } private static void acceptDurationOfSeconds(final Properties properties, final String name, final Consumer consumer) { accept(properties, name, s -> Duration.ofSeconds(Long.parseLong(s)), consumer); } private static void acceptInt(final Properties properties, final String name, final Consumer consumer) { accept(properties, name, Integer::parseInt, consumer); } private static void acceptString(final Properties properties, final String name, final Consumer consumer) { accept(properties, name, Function.identity(), consumer); } /** * Creates and configures a {@link BasicDataSource} instance based on the given properties. * * @param properties * The data source configuration properties. * @return A new a {@link BasicDataSource} instance based on the given properties. * @throws SQLException * Thrown when an error occurs creating the data source. */ public static BasicDataSource createDataSource(final Properties properties) throws SQLException { final BasicDataSource dataSource = new BasicDataSource(); acceptBoolean(properties, PROP_DEFAULT_AUTO_COMMIT, dataSource::setDefaultAutoCommit); acceptBoolean(properties, PROP_DEFAULT_READ_ONLY, dataSource::setDefaultReadOnly); getOptional(properties, PROP_DEFAULT_TRANSACTION_ISOLATION).ifPresent(value -> { value = value.toUpperCase(Locale.ROOT); int level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; switch (value) { case "NONE": level = Connection.TRANSACTION_NONE; break; case "READ_COMMITTED": level = Connection.TRANSACTION_READ_COMMITTED; break; case "READ_UNCOMMITTED": level = Connection.TRANSACTION_READ_UNCOMMITTED; break; case "REPEATABLE_READ": level = Connection.TRANSACTION_REPEATABLE_READ; break; case "SERIALIZABLE": level = Connection.TRANSACTION_SERIALIZABLE; break; default: try { level = Integer.parseInt(value); } catch (final NumberFormatException e) { System.err.println("Could not parse defaultTransactionIsolation: " + value); System.err.println("WARNING: defaultTransactionIsolation not set"); System.err.println("using default value of database driver"); level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; } break; } dataSource.setDefaultTransactionIsolation(level); }); acceptString(properties, PROP_DEFAULT_SCHEMA, dataSource::setDefaultSchema); acceptString(properties, PROP_DEFAULT_CATALOG, dataSource::setDefaultCatalog); acceptBoolean(properties, PROP_CACHE_STATE, dataSource::setCacheState); acceptString(properties, PROP_DRIVER_CLASS_NAME, dataSource::setDriverClassName); acceptBoolean(properties, PROP_LIFO, dataSource::setLifo); acceptInt(properties, PROP_MAX_TOTAL, dataSource::setMaxTotal); acceptInt(properties, PROP_MAX_IDLE, dataSource::setMaxIdle); acceptInt(properties, PROP_MIN_IDLE, dataSource::setMinIdle); acceptInt(properties, PROP_INITIAL_SIZE, dataSource::setInitialSize); acceptDurationOfMillis(properties, PROP_MAX_WAIT_MILLIS, dataSource::setMaxWait); acceptBoolean(properties, PROP_TEST_ON_CREATE, dataSource::setTestOnCreate); acceptBoolean(properties, PROP_TEST_ON_BORROW, dataSource::setTestOnBorrow); acceptBoolean(properties, PROP_TEST_ON_RETURN, dataSource::setTestOnReturn); acceptDurationOfMillis(properties, PROP_TIME_BETWEEN_EVICTION_RUNS_MILLIS, dataSource::setDurationBetweenEvictionRuns); acceptInt(properties, PROP_NUM_TESTS_PER_EVICTION_RUN, dataSource::setNumTestsPerEvictionRun); acceptDurationOfMillis(properties, PROP_MIN_EVICTABLE_IDLE_TIME_MILLIS, dataSource::setMinEvictableIdle); acceptDurationOfMillis(properties, PROP_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS, dataSource::setSoftMinEvictableIdle); acceptString(properties, PROP_EVICTION_POLICY_CLASS_NAME, dataSource::setEvictionPolicyClassName); acceptBoolean(properties, PROP_TEST_WHILE_IDLE, dataSource::setTestWhileIdle); acceptString(properties, PROP_PASSWORD, dataSource::setPassword); acceptString(properties, PROP_URL, dataSource::setUrl); acceptString(properties, PROP_USER_NAME, dataSource::setUsername); acceptString(properties, PROP_VALIDATION_QUERY, dataSource::setValidationQuery); acceptDurationOfSeconds(properties, PROP_VALIDATION_QUERY_TIMEOUT, dataSource::setValidationQueryTimeout); acceptBoolean(properties, PROP_ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED, dataSource::setAccessToUnderlyingConnectionAllowed); acceptBoolean(properties, PROP_REMOVE_ABANDONED_ON_BORROW, dataSource::setRemoveAbandonedOnBorrow); acceptBoolean(properties, PROP_REMOVE_ABANDONED_ON_MAINTENANCE, dataSource::setRemoveAbandonedOnMaintenance); acceptDurationOfSeconds(properties, PROP_REMOVE_ABANDONED_TIMEOUT, dataSource::setRemoveAbandonedTimeout); acceptBoolean(properties, PROP_LOG_ABANDONED, dataSource::setLogAbandoned); acceptBoolean(properties, PROP_ABANDONED_USAGE_TRACKING, dataSource::setAbandonedUsageTracking); acceptBoolean(properties, PROP_POOL_PREPARED_STATEMENTS, dataSource::setPoolPreparedStatements); acceptBoolean(properties, PROP_CLEAR_STATEMENT_POOL_ON_RETURN, dataSource::setClearStatementPoolOnReturn); acceptInt(properties, PROP_MAX_OPEN_PREPARED_STATEMENTS, dataSource::setMaxOpenPreparedStatements); getOptional(properties, PROP_CONNECTION_INIT_SQLS).ifPresent(v -> dataSource.setConnectionInitSqls(parseList(v, ';'))); final String value = properties.getProperty(PROP_CONNECTION_PROPERTIES); if (value != null) { for (final Object key : getProperties(value).keySet()) { final String propertyName = Objects.toString(key, null); dataSource.addConnectionProperty(propertyName, getProperties(value).getProperty(propertyName)); } } acceptDurationOfMillis(properties, PROP_MAX_CONN_LIFETIME_MILLIS, dataSource::setMaxConn); acceptBoolean(properties, PROP_LOG_EXPIRED_CONNECTIONS, dataSource::setLogExpiredConnections); acceptString(properties, PROP_JMX_NAME, dataSource::setJmxName); acceptBoolean(properties, PROP_REGISTER_CONNECTION_MBEAN, dataSource::setRegisterConnectionMBean); acceptBoolean(properties, PROP_ENABLE_AUTO_COMMIT_ON_RETURN, dataSource::setAutoCommitOnReturn); acceptBoolean(properties, PROP_ROLLBACK_ON_RETURN, dataSource::setRollbackOnReturn); acceptDurationOfSeconds(properties, PROP_DEFAULT_QUERY_TIMEOUT, dataSource::setDefaultQueryTimeout); acceptBoolean(properties, PROP_FAST_FAIL_VALIDATION, dataSource::setFastFailValidation); getOptional(properties, PROP_DISCONNECTION_SQL_CODES).ifPresent(v -> dataSource.setDisconnectionSqlCodes(parseList(v, ','))); getOptional(properties, PROP_DISCONNECTION_IGNORE_SQL_CODES).ifPresent(v -> dataSource.setDisconnectionIgnoreSqlCodes(parseList(v, ','))); acceptString(properties, PROP_CONNECTION_FACTORY_CLASS_NAME, dataSource::setConnectionFactoryClassName); // DBCP-215 // Trick to make sure that initialSize connections are created if (dataSource.getInitialSize() > 0) { dataSource.getLogWriter(); } // Return the configured DataSource instance return dataSource; } private static Optional getOptional(final Properties properties, final String name) { return Optional.ofNullable(properties.getProperty(name)); } /** * Parse properties from the string. Format of the string must be [propertyName=property;]* * * @param propText The source text * @return Properties A new Properties instance * @throws SQLException When a paring exception occurs */ private static Properties getProperties(final String propText) throws SQLException { final Properties p = new Properties(); if (propText != null) { try { p.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes(StandardCharsets.ISO_8859_1))); } catch (final IOException e) { throw new SQLException(propText, e); } } return p; } /** * Parses list of property values from a delimited string * * @param value * delimited list of values * @param delimiter * character used to separate values in the list * @return String Collection of values */ private static List parseList(final String value, final char delimiter) { final StringTokenizer tokenizer = new StringTokenizer(value, Character.toString(delimiter)); final List tokens = new ArrayList<>(tokenizer.countTokens()); while (tokenizer.hasMoreTokens()) { tokens.add(tokenizer.nextToken()); } return tokens; } /** * Creates and return a new {@code BasicDataSource} instance. If no instance can be created, return * {@code null} instead. * * @param obj * The possibly null object containing location or reference information that can be used in creating an * object * @param name * The name of this object relative to {@code nameCtx} * @param nameCtx * The context relative to which the {@code name} parameter is specified, or {@code null} if * {@code name} is relative to the default initial context * @param environment * The possibly null environment that is used in creating this object * * @throws SQLException * if an exception occurs creating the instance */ @Override public Object getObjectInstance(final Object obj, final Name name, final Context nameCtx, final Hashtable environment) throws SQLException { // We only know how to deal with {@code javax.naming.Reference}s // that specify a class name of "javax.sql.DataSource" if (obj == null || !(obj instanceof Reference)) { return null; } final Reference ref = (Reference) obj; if (!"javax.sql.DataSource".equals(ref.getClassName())) { return null; } // Check property names and log warnings about obsolete and / or unknown properties final List warnMessages = new ArrayList<>(); final List infoMessages = new ArrayList<>(); validatePropertyNames(ref, name, warnMessages, infoMessages); warnMessages.forEach(log::warn); infoMessages.forEach(log::info); final Properties properties = new Properties(); ALL_PROPERTY_NAMES.forEach(propertyName -> { final RefAddr ra = ref.get(propertyName); if (ra != null) { properties.setProperty(propertyName, Objects.toString(ra.getContent(), null)); } }); return createDataSource(properties); } /** * Collects warnings and info messages. Warnings are generated when an obsolete property is set. Unknown properties * generate info messages. * * @param ref * Reference to check properties of * @param name * Name provided to getObject * @param warnMessages * container for warning messages * @param infoMessages * container for info messages */ private void validatePropertyNames(final Reference ref, final Name name, final List warnMessages, final List infoMessages) { final String nameString = name != null ? "Name = " + name.toString() + " " : ""; NUPROP_WARNTEXT.forEach((propertyName, value) -> { final RefAddr ra = ref.get(propertyName); if (ra != null && !ALL_PROPERTY_NAMES.contains(ra.getType())) { final StringBuilder stringBuilder = new StringBuilder(nameString); final String propertyValue = Objects.toString(ra.getContent(), null); stringBuilder.append(value).append(" You have set value of \"").append(propertyValue).append("\" for \"").append(propertyName) .append("\" property, which is being ignored."); warnMessages.add(stringBuilder.toString()); } }); final Enumeration allRefAddrs = ref.getAll(); while (allRefAddrs.hasMoreElements()) { final RefAddr ra = allRefAddrs.nextElement(); final String propertyName = ra.getType(); // If property name is not in the properties list, we haven't warned on it // and it is not in the "silent" list, tell user we are ignoring it. if (!(ALL_PROPERTY_NAMES.contains(propertyName) || NUPROP_WARNTEXT.containsKey(propertyName) || SILENT_PROPERTIES.contains(propertyName))) { final String propertyValue = Objects.toString(ra.getContent(), null); final StringBuilder stringBuilder = new StringBuilder(nameString); stringBuilder.append("Ignoring unknown property: ").append("value of \"").append(propertyValue).append("\" for \"").append(propertyName) .append("\" property"); infoMessages.add(stringBuilder.toString()); } } } } BasicDataSourceMXBean.java000066400000000000000000000026441472045345700332620ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; /** * Interface to keep API compatibility. Methods listed here are not made available to * JMX. *

* As of 2.9.0, this interface extends {@link DataSourceMXBean}. *

* * @since 2.0 */ public interface BasicDataSourceMXBean extends DataSourceMXBean { /** * See {@link BasicDataSource#getPassword()} * * @return {@link BasicDataSource#getPassword()} * @deprecated Exposing passwords via JMX is an Information Exposure issue. */ @Deprecated String getPassword(); } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/ConnectionFactory.java000066400000000000000000000025021472045345700327320ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.SQLException; /** * Abstract factory interface for creating {@link java.sql.Connection}s. * * @since 2.0 */ public interface ConnectionFactory { /** * Create a new {@link java.sql.Connection} in an implementation specific fashion. * * @return a new {@link java.sql.Connection} * @throws SQLException * if a database error occurs creating the connection */ Connection createConnection() throws SQLException; } ConnectionFactoryFactory.java000066400000000000000000000065771472045345700342230ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Driver; import java.sql.SQLException; import java.util.Properties; /* * Creates {@link ConnectionFactory} instances. * * @since 2.7.0 */ final class ConnectionFactoryFactory { /** * Creates a new {@link DriverConnectionFactory} allowing for an override through * {@link BasicDataSource#getDriverClassName()}. * * @param basicDataSource Configures creation. * @param driver The JDBC driver. * @return a new {@link DriverConnectionFactory} allowing for a {@link BasicDataSource#getDriverClassName()} * override. * @throws SQLException Thrown when instantiation fails. */ static ConnectionFactory createConnectionFactory(final BasicDataSource basicDataSource, final Driver driver) throws SQLException { final Properties connectionProperties = basicDataSource.getConnectionProperties(); final String url = basicDataSource.getUrl(); // Set up the driver connection factory we will use final String user = basicDataSource.getUserName(); if (user != null) { connectionProperties.put(Constants.KEY_USER, user); } else { basicDataSource.log(String.format("DBCP DataSource configured without a '%s'", Constants.KEY_USER)); } final String pwd = basicDataSource.getPassword(); if (pwd != null) { connectionProperties.put(Constants.KEY_PASSWORD, pwd); } else { basicDataSource.log(String.format("DBCP DataSource configured without a '%s'", Constants.KEY_PASSWORD)); } final String connectionFactoryClassName = basicDataSource.getConnectionFactoryClassName(); if (connectionFactoryClassName != null) { try { final Class connectionFactoryFromCCL = Class.forName(connectionFactoryClassName); return (ConnectionFactory) connectionFactoryFromCCL .getConstructor(Driver.class, String.class, Properties.class) .newInstance(driver, url, connectionProperties); } catch (final Exception t) { final String message = "Cannot load ConnectionFactory implementation '" + connectionFactoryClassName + "'"; basicDataSource.log(message, t); throw new SQLException(message, t); } } // Defaults to DriverConnectionFactory return new DriverConnectionFactory(driver, url, connectionProperties); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/Constants.java000066400000000000000000000036501472045345700312640ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; /** * Constants. * * @since 2.0 */ public class Constants { /** * Constant used to build JMX strings. */ public static final String JMX_CONNECTION_POOL_BASE_EXT = ",connectionpool="; /** * Constant used to build JMX strings. */ public static final String JMX_CONNECTION_POOL_PREFIX = "connections"; /** * Constant used to build JMX strings. */ public static final String JMX_CONNECTION_BASE_EXT = JMX_CONNECTION_POOL_BASE_EXT + JMX_CONNECTION_POOL_PREFIX + ",connection="; /** * Constant used to build JMX strings. */ public static final String JMX_STATEMENT_POOL_BASE_EXT = JMX_CONNECTION_BASE_EXT; /** * Constant used to build JMX strings. */ public static final String JMX_STATEMENT_POOL_PREFIX = ",statementpool=statements"; /** * JDBC properties and URL key for passwords. * * @since 2.9.0 */ public static final String KEY_PASSWORD = "password"; /** * JDBC properties and URL key for users. * * @since 2.9.0 */ public static final String KEY_USER = "user"; } DataSourceConnectionFactory.java000066400000000000000000000064761472045345700346440ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; /** * A {@link DataSource}-based implementation of {@link ConnectionFactory}. * * @since 2.0 */ public class DataSourceConnectionFactory implements ConnectionFactory { private final DataSource dataSource; private final String userName; private final char[] userPassword; /** * Constructs an instance for the given DataSource. * * @param dataSource * The DataSource for this factory. */ public DataSourceConnectionFactory(final DataSource dataSource) { this(dataSource, null, (char[]) null); } /** * Constructs an instance for the given DataSource. * * @param dataSource * The DataSource for this factory. * @param userName * The user name. * @param userPassword * The user password. * @since 2.4.0 */ public DataSourceConnectionFactory(final DataSource dataSource, final String userName, final char[] userPassword) { this.dataSource = dataSource; this.userName = userName; this.userPassword = Utils.clone(userPassword); } /** * Constructs an instance for the given DataSource. * * @param dataSource * The DataSource for this factory. * @param userName * The user name. * @param password * The user password. */ public DataSourceConnectionFactory(final DataSource dataSource, final String userName, final String password) { this.dataSource = dataSource; this.userName = userName; this.userPassword = Utils.toCharArray(password); } @Override public Connection createConnection() throws SQLException { if (null == userName && null == userPassword) { return dataSource.getConnection(); } return dataSource.getConnection(userName, Utils.toString(userPassword)); } /** * @return The data source. * @since 2.6.0 */ public DataSource getDataSource() { return dataSource; } /** * @return The user name. * @since 2.6.0 */ public String getUserName() { return userName; } /** * @return The user password. * @since 2.6.0 */ public char[] getUserPassword() { return Utils.clone(userPassword); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java000066400000000000000000000230411472045345700323710ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.SQLException; /** * Defines the methods that will be made available via * JMX. * * @since 2.9.0 */ public interface DataSourceMXBean { /** * See {@link BasicDataSource#getAbandonedUsageTracking()}. * * @return {@link BasicDataSource#getAbandonedUsageTracking()} */ boolean getAbandonedUsageTracking(); /** * See {@link BasicDataSource#getCacheState()}. * * @return {@link BasicDataSource#getCacheState()}. */ boolean getCacheState(); /** * See {@link BasicDataSource#getConnectionInitSqlsAsArray()}. * * @return {@link BasicDataSource#getConnectionInitSqlsAsArray()}. */ String[] getConnectionInitSqlsAsArray(); /** * See {@link BasicDataSource#getDefaultAutoCommit()}. * * @return {@link BasicDataSource#getDefaultAutoCommit()}. */ Boolean getDefaultAutoCommit(); /** * See {@link BasicDataSource#getDefaultCatalog()}. * * @return {@link BasicDataSource#getDefaultCatalog()}. */ String getDefaultCatalog(); /** * See {@link BasicDataSource#getDefaultReadOnly()}. * * @return {@link BasicDataSource#getDefaultReadOnly()}. */ Boolean getDefaultReadOnly(); /** * See {@link BasicDataSource#getDefaultSchema()}. * * @return {@link BasicDataSource#getDefaultSchema()}. * @since 2.5.0 */ default String getDefaultSchema() { return null; } /** * See {@link BasicDataSource#getDefaultTransactionIsolation()}. * * @return {@link BasicDataSource#getDefaultTransactionIsolation()}. */ int getDefaultTransactionIsolation(); /** * See {@link BasicDataSource#getDisconnectionIgnoreSqlCodesAsArray()}. * * @return {@link BasicDataSource#getDisconnectionIgnoreSqlCodesAsArray()}. * @since 2.13.0 */ default String[] getDisconnectionIgnoreSqlCodesAsArray() { return Utils.EMPTY_STRING_ARRAY; } /** * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}. * * @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}. * @since 2.1 */ String[] getDisconnectionSqlCodesAsArray(); /** * See {@link BasicDataSource#getDriverClassName()}. * * @return {@link BasicDataSource#getDriverClassName()}. */ String getDriverClassName(); /** * See {@link BasicDataSource#getFastFailValidation()}. * * @return {@link BasicDataSource#getFastFailValidation()}. * @since 2.1 */ boolean getFastFailValidation(); /** * See {@link BasicDataSource#getInitialSize()}. * * @return {@link BasicDataSource#getInitialSize()}. */ int getInitialSize(); /** * See {@link BasicDataSource#getLifo()}. * * @return {@link BasicDataSource#getLifo()}. */ boolean getLifo(); /** * See {@link BasicDataSource#getLogAbandoned()}. * * @return {@link BasicDataSource#getLogAbandoned()}. */ boolean getLogAbandoned(); /** * See {@link BasicDataSource#getLogExpiredConnections()}. * * @return {@link BasicDataSource#getLogExpiredConnections()}. * @since 2.1 */ boolean getLogExpiredConnections(); /** * See {@link BasicDataSource#getMaxConnLifetimeMillis()}. * * @return {@link BasicDataSource#getMaxConnLifetimeMillis()}. */ long getMaxConnLifetimeMillis(); /** * See {@link BasicDataSource#getMaxIdle()}. * * @return {@link BasicDataSource#getMaxIdle()}. */ int getMaxIdle(); /** * See {@link BasicDataSource#getMaxOpenPreparedStatements()}. * * @return {@link BasicDataSource#getMaxOpenPreparedStatements()}. */ int getMaxOpenPreparedStatements(); /** * See {@link BasicDataSource#getMaxTotal()}. * * @return {@link BasicDataSource#getMaxTotal()}. */ int getMaxTotal(); /** * See {@link BasicDataSource#getMaxWaitMillis()}. * * @return {@link BasicDataSource#getMaxWaitMillis()}. */ long getMaxWaitMillis(); /** * See {@link BasicDataSource#getMinEvictableIdleTimeMillis()}. * * @return {@link BasicDataSource#getMinEvictableIdleTimeMillis()}. */ long getMinEvictableIdleTimeMillis(); /** * See {@link BasicDataSource#getMinIdle()}. * * @return {@link BasicDataSource#getMinIdle()}. */ int getMinIdle(); /** * See {@link BasicDataSource#getNumActive()}. * * @return {@link BasicDataSource#getNumActive()}. */ int getNumActive(); /** * See {@link BasicDataSource#getNumIdle()}. * * @return {@link BasicDataSource#getNumIdle()}. */ int getNumIdle(); /** * See {@link BasicDataSource#getNumTestsPerEvictionRun()}. * * @return {@link BasicDataSource#getNumTestsPerEvictionRun()}. */ int getNumTestsPerEvictionRun(); /** * See {@link BasicDataSource#getRemoveAbandonedOnBorrow()}. * * @return {@link BasicDataSource#getRemoveAbandonedOnBorrow()}. */ boolean getRemoveAbandonedOnBorrow(); /** * See {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}. * * @return {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}. */ boolean getRemoveAbandonedOnMaintenance(); /** * See {@link BasicDataSource#getRemoveAbandonedTimeout()}. * * @return {@link BasicDataSource#getRemoveAbandonedTimeout()}. */ int getRemoveAbandonedTimeout(); /** * See {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}. * * @return {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}. */ long getSoftMinEvictableIdleTimeMillis(); /** * See {@link BasicDataSource#getTestOnBorrow()}. * * @return {@link BasicDataSource#getTestOnBorrow()}. */ boolean getTestOnBorrow(); /** * See {@link BasicDataSource#getTestOnCreate()}. * * @return {@link BasicDataSource#getTestOnCreate()}. */ boolean getTestOnCreate(); /** * See {@link BasicDataSource#getTestWhileIdle()}. * * @return {@link BasicDataSource#getTestWhileIdle()}. */ boolean getTestWhileIdle(); /** * See {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}. * * @return {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}. */ long getTimeBetweenEvictionRunsMillis(); /** * See {@link BasicDataSource#getUrl()}. * * @return {@link BasicDataSource#getUrl()}. */ String getUrl(); /** * See {@link BasicDataSource#getUsername()}. * * @return {@link BasicDataSource#getUsername()}. * @deprecated Use {@link #getUserName()}. */ @Deprecated String getUsername(); /** * See {@link BasicDataSource#getUsername()}. * * @return {@link BasicDataSource#getUsername()}. * @since 2.11.0 */ default String getUserName() { return getUsername(); } /** * See {@link BasicDataSource#getValidationQuery()}. * * @return {@link BasicDataSource#getValidationQuery()}. */ String getValidationQuery(); /** * See {@link BasicDataSource#getValidationQueryTimeout()}. * * @return {@link BasicDataSource#getValidationQueryTimeout()}. */ int getValidationQueryTimeout(); /** * See {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}. * * @return {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}. */ boolean isAccessToUnderlyingConnectionAllowed(); /** * See {@link BasicDataSource#isClearStatementPoolOnReturn()}. * * @return {@link BasicDataSource#isClearStatementPoolOnReturn()}. * @since 2.8.0 */ default boolean isClearStatementPoolOnReturn() { return false; } /** * See {@link BasicDataSource#isClosed()}. * * @return {@link BasicDataSource#isClosed()}. */ boolean isClosed(); /** * See {@link BasicDataSource#isPoolPreparedStatements()}. * * @return {@link BasicDataSource#isPoolPreparedStatements()}. */ boolean isPoolPreparedStatements(); /** * See {@link BasicDataSource#restart()} * * @throws SQLException if an error occurs initializing the data source. * * @since 2.8.0 */ default void restart() throws SQLException { // do nothing by default? } /** * See {@link BasicDataSource#start()} * * @throws SQLException if an error occurs initializing the data source. * * @since 2.8.0 */ default void start() throws SQLException { // do nothing } } DelegatingCallableStatement.java000066400000000000000000001226431472045345700346050ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Date; import java.sql.NClob; import java.sql.Ref; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLType; import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Map; /** * A base delegating implementation of {@link CallableStatement}. *

* All of the methods from the {@link CallableStatement} interface simply call the corresponding method on the * "delegate" provided in my constructor. *

*

* Extends AbandonedTrace to implement Statement tracking and logging of code which created the Statement. Tracking the * Statement ensures that the Connection which created it can close any open Statement's on Connection close. *

* * @since 2.0 */ public class DelegatingCallableStatement extends DelegatingPreparedStatement implements CallableStatement { /** * Creates a wrapper for the Statement which traces this Statement to the Connection which created it and the code * which created it. * * @param connection * the {@link DelegatingConnection} that created this statement * @param statement * the {@link CallableStatement} to delegate all calls to */ public DelegatingCallableStatement(final DelegatingConnection connection, final CallableStatement statement) { super(connection, statement); } @Override public Array getArray(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getArray(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Array getArray(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getArray(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public BigDecimal getBigDecimal(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBigDecimal(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } /** @deprecated Use {@link #getBigDecimal(int)} or {@link #getBigDecimal(String)} */ @Override @Deprecated public BigDecimal getBigDecimal(final int parameterIndex, final int scale) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBigDecimal(parameterIndex, scale); } catch (final SQLException e) { handleException(e); return null; } } @Override public BigDecimal getBigDecimal(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBigDecimal(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Blob getBlob(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBlob(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Blob getBlob(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBlob(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public boolean getBoolean(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBoolean(parameterIndex); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean getBoolean(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBoolean(parameterName); } catch (final SQLException e) { handleException(e); return false; } } @Override public byte getByte(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getByte(parameterIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public byte getByte(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getByte(parameterName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public byte[] getBytes(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBytes(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public byte[] getBytes(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getBytes(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Reader getCharacterStream(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getCharacterStream(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Reader getCharacterStream(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getCharacterStream(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Clob getClob(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getClob(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Clob getClob(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getClob(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Date getDate(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getDate(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Date getDate(final int parameterIndex, final Calendar cal) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getDate(parameterIndex, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public Date getDate(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getDate(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Date getDate(final String parameterName, final Calendar cal) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getDate(parameterName, cal); } catch (final SQLException e) { handleException(e); return null; } } private CallableStatement getDelegateCallableStatement() { return (CallableStatement) getDelegate(); } @Override public double getDouble(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getDouble(parameterIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public double getDouble(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getDouble(parameterName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public float getFloat(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getFloat(parameterIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public float getFloat(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getFloat(parameterName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getInt(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getInt(parameterIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getInt(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getInt(parameterName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public long getLong(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getLong(parameterIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public long getLong(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getLong(parameterName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public Reader getNCharacterStream(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getNCharacterStream(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Reader getNCharacterStream(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getNCharacterStream(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public NClob getNClob(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getNClob(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public NClob getNClob(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getNClob(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public String getNString(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getNString(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public String getNString(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getNString(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Object getObject(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getObject(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public T getObject(final int parameterIndex, final Class type) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getObject(parameterIndex, type); } catch (final SQLException e) { handleException(e); return null; } } @Override public Object getObject(final int i, final Map> map) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getObject(i, map); } catch (final SQLException e) { handleException(e); return null; } } @Override public Object getObject(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getObject(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public T getObject(final String parameterName, final Class type) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getObject(parameterName, type); } catch (final SQLException e) { handleException(e); return null; } } @Override public Object getObject(final String parameterName, final Map> map) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getObject(parameterName, map); } catch (final SQLException e) { handleException(e); return null; } } @Override public Ref getRef(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getRef(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Ref getRef(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getRef(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public RowId getRowId(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getRowId(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public RowId getRowId(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getRowId(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public short getShort(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getShort(parameterIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public short getShort(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getShort(parameterName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public SQLXML getSQLXML(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getSQLXML(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public SQLXML getSQLXML(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getSQLXML(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public String getString(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getString(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public String getString(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getString(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Time getTime(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getTime(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Time getTime(final int parameterIndex, final Calendar cal) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getTime(parameterIndex, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public Time getTime(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getTime(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Time getTime(final String parameterName, final Calendar cal) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getTime(parameterName, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public Timestamp getTimestamp(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getTimestamp(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Timestamp getTimestamp(final int parameterIndex, final Calendar cal) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getTimestamp(parameterIndex, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public Timestamp getTimestamp(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getTimestamp(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Timestamp getTimestamp(final String parameterName, final Calendar cal) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getTimestamp(parameterName, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public URL getURL(final int parameterIndex) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getURL(parameterIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public URL getURL(final String parameterName) throws SQLException { checkOpen(); try { return getDelegateCallableStatement().getURL(parameterName); } catch (final SQLException e) { handleException(e); return null; } } @Override public void registerOutParameter(final int parameterIndex, final int sqlType) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterIndex, sqlType); } catch (final SQLException e) { handleException(e); } } @Override public void registerOutParameter(final int parameterIndex, final int sqlType, final int scale) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterIndex, sqlType, scale); } catch (final SQLException e) { handleException(e); } } @Override public void registerOutParameter(final int paramIndex, final int sqlType, final String typeName) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(paramIndex, sqlType, typeName); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void registerOutParameter(final int parameterIndex, final SQLType sqlType) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterIndex, sqlType); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void registerOutParameter(final int parameterIndex, final SQLType sqlType, final int scale) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterIndex, sqlType, scale); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void registerOutParameter(final int parameterIndex, final SQLType sqlType, final String typeName) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterIndex, sqlType, typeName); } catch (final SQLException e) { handleException(e); } } @Override public void registerOutParameter(final String parameterName, final int sqlType) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterName, sqlType); } catch (final SQLException e) { handleException(e); } } @Override public void registerOutParameter(final String parameterName, final int sqlType, final int scale) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterName, sqlType, scale); } catch (final SQLException e) { handleException(e); } } @Override public void registerOutParameter(final String parameterName, final int sqlType, final String typeName) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterName, sqlType, typeName); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void registerOutParameter(final String parameterName, final SQLType sqlType) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterName, sqlType); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void registerOutParameter(final String parameterName, final SQLType sqlType, final int scale) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterName, sqlType, scale); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void registerOutParameter(final String parameterName, final SQLType sqlType, final String typeName) throws SQLException { checkOpen(); try { getDelegateCallableStatement().registerOutParameter(parameterName, sqlType, typeName); } catch (final SQLException e) { handleException(e); } } @Override public void setAsciiStream(final String parameterName, final InputStream inputStream) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setAsciiStream(parameterName, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void setAsciiStream(final String parameterName, final InputStream x, final int length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setAsciiStream(parameterName, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void setAsciiStream(final String parameterName, final InputStream inputStream, final long length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setAsciiStream(parameterName, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void setBigDecimal(final String parameterName, final BigDecimal x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBigDecimal(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setBinaryStream(final String parameterName, final InputStream inputStream) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBinaryStream(parameterName, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void setBinaryStream(final String parameterName, final InputStream x, final int length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBinaryStream(parameterName, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void setBinaryStream(final String parameterName, final InputStream inputStream, final long length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBinaryStream(parameterName, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void setBlob(final String parameterName, final Blob blob) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBlob(parameterName, blob); } catch (final SQLException e) { handleException(e); } } @Override public void setBlob(final String parameterName, final InputStream inputStream) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBlob(parameterName, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void setBlob(final String parameterName, final InputStream inputStream, final long length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBlob(parameterName, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void setBoolean(final String parameterName, final boolean x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBoolean(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setByte(final String parameterName, final byte x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setByte(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setBytes(final String parameterName, final byte[] x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setBytes(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setCharacterStream(final String parameterName, final Reader reader) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setCharacterStream(parameterName, reader); } catch (final SQLException e) { handleException(e); } } @Override public void setCharacterStream(final String parameterName, final Reader reader, final int length) throws SQLException { checkOpen(); getDelegateCallableStatement().setCharacterStream(parameterName, reader, length); } @Override public void setCharacterStream(final String parameterName, final Reader reader, final long length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setCharacterStream(parameterName, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void setClob(final String parameterName, final Clob clob) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setClob(parameterName, clob); } catch (final SQLException e) { handleException(e); } } @Override public void setClob(final String parameterName, final Reader reader) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setClob(parameterName, reader); } catch (final SQLException e) { handleException(e); } } @Override public void setClob(final String parameterName, final Reader reader, final long length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setClob(parameterName, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void setDate(final String parameterName, final Date x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setDate(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setDate(final String parameterName, final Date x, final Calendar cal) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setDate(parameterName, x, cal); } catch (final SQLException e) { handleException(e); } } @Override public void setDouble(final String parameterName, final double x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setDouble(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setFloat(final String parameterName, final float x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setFloat(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setInt(final String parameterName, final int x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setInt(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setLong(final String parameterName, final long x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setLong(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setNCharacterStream(final String parameterName, final Reader reader) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setNCharacterStream(parameterName, reader); } catch (final SQLException e) { handleException(e); } } @Override public void setNCharacterStream(final String parameterName, final Reader reader, final long length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setNCharacterStream(parameterName, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void setNClob(final String parameterName, final NClob value) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setNClob(parameterName, value); } catch (final SQLException e) { handleException(e); } } @Override public void setNClob(final String parameterName, final Reader reader) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setNClob(parameterName, reader); } catch (final SQLException e) { handleException(e); } } @Override public void setNClob(final String parameterName, final Reader reader, final long length) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setNClob(parameterName, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void setNString(final String parameterName, final String value) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setNString(parameterName, value); } catch (final SQLException e) { handleException(e); } } @Override public void setNull(final String parameterName, final int sqlType) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setNull(parameterName, sqlType); } catch (final SQLException e) { handleException(e); } } @Override public void setNull(final String parameterName, final int sqlType, final String typeName) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setNull(parameterName, sqlType, typeName); } catch (final SQLException e) { handleException(e); } } @Override public void setObject(final String parameterName, final Object x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setObject(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setObject(final String parameterName, final Object x, final int targetSqlType) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setObject(parameterName, x, targetSqlType); } catch (final SQLException e) { handleException(e); } } @Override public void setObject(final String parameterName, final Object x, final int targetSqlType, final int scale) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setObject(parameterName, x, targetSqlType, scale); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void setObject(final String parameterName, final Object x, final SQLType targetSqlType) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setObject(parameterName, x, targetSqlType); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void setObject(final String parameterName, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setObject(parameterName, x, targetSqlType, scaleOrLength); } catch (final SQLException e) { handleException(e); } } @Override public void setRowId(final String parameterName, final RowId value) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setRowId(parameterName, value); } catch (final SQLException e) { handleException(e); } } @Override public void setShort(final String parameterName, final short x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setShort(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setSQLXML(final String parameterName, final SQLXML value) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setSQLXML(parameterName, value); } catch (final SQLException e) { handleException(e); } } @Override public void setString(final String parameterName, final String x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setString(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setTime(final String parameterName, final Time x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setTime(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setTime(final String parameterName, final Time x, final Calendar cal) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setTime(parameterName, x, cal); } catch (final SQLException e) { handleException(e); } } @Override public void setTimestamp(final String parameterName, final Timestamp x) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setTimestamp(parameterName, x); } catch (final SQLException e) { handleException(e); } } @Override public void setTimestamp(final String parameterName, final Timestamp x, final Calendar cal) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setTimestamp(parameterName, x, cal); } catch (final SQLException e) { handleException(e); } } @Override public void setURL(final String parameterName, final URL val) throws SQLException { checkOpen(); try { getDelegateCallableStatement().setURL(parameterName, val); } catch (final SQLException e) { handleException(e); } } @Override public boolean wasNull() throws SQLException { checkOpen(); try { return getDelegateCallableStatement().wasNull(); } catch (final SQLException e) { handleException(e); return false; } } } DelegatingConnection.java000066400000000000000000001052351472045345700333160ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.ClientInfoStatus; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.SQLClientInfoException; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Savepoint; import java.sql.Statement; import java.sql.Struct; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; import org.apache.commons.dbcp2.managed.ManagedConnection; /** * A base delegating implementation of {@link Connection}. *

* All of the methods from the {@link Connection} interface simply check to see that the {@link Connection} is active, * and call the corresponding method on the "delegate" provided in my constructor. *

*

* Extends AbandonedTrace to implement Connection tracking and logging of code which created the Connection. Tracking * the Connection ensures that the AbandonedObjectPool can close this connection and recycle it if its pool of * connections is nearing exhaustion and this connection's last usage is older than the removeAbandonedTimeout. *

* * @param * the Connection type * * @since 2.0 */ public class DelegatingConnection extends AbandonedTrace implements Connection { private static final Map EMPTY_FAILED_PROPERTIES = Collections .emptyMap(); /** My delegate {@link Connection}. */ private volatile C connection; private volatile boolean closed; private boolean cacheState = true; private Boolean cachedAutoCommit; private Boolean cachedReadOnly; private String cachedCatalog; private String cachedSchema; private Duration defaultQueryTimeoutDuration; /** * Creates a wrapper for the Connection which traces this Connection in the AbandonedObjectPool. * * @param connection the {@link Connection} to delegate all calls to, may be null (see {@link ManagedConnection}). */ public DelegatingConnection(final C connection) { this.connection = connection; } @Override public void abort(final Executor executor) throws SQLException { try { Jdbc41Bridge.abort(connection, executor); } catch (final SQLException e) { handleException(e); } } /** * Marks this instance as used and delegates to a wrapped {@link DelegatingConnection#activate()}. */ protected void activate() { closed = false; setLastUsed(); if (connection instanceof DelegatingConnection) { ((DelegatingConnection) connection).activate(); } } /** * Throws a SQLException if this connection is not open. * * @throws SQLException Thrown if this connection is not open. */ protected void checkOpen() throws SQLException { if (closed) { if (null != connection) { String label; try { label = connection.toString(); } catch (final Exception e) { // leave label empty label = ""; } throw new SQLException("Connection " + label + " is closed."); } throw new SQLException("Connection is null."); } } /** * Clears the cached state. Call when you know that the underlying connection may have been accessed * directly. */ public void clearCachedState() { cachedAutoCommit = null; cachedReadOnly = null; cachedSchema = null; cachedCatalog = null; if (connection instanceof DelegatingConnection) { ((DelegatingConnection) connection).clearCachedState(); } } @Override public void clearWarnings() throws SQLException { checkOpen(); try { connection.clearWarnings(); } catch (final SQLException e) { handleException(e); } } /** * Closes the underlying connection, and close any Statements that were not explicitly closed. Sub-classes that * override this method must: *
    *
  1. Call {@link #passivate()}
  2. *
  3. Call close (or the equivalent appropriate action) on the wrapped connection
  4. *
  5. Set {@code closed} to {@code false}
  6. *
*/ @Override public void close() throws SQLException { if (!closed) { closeInternal(); } } protected final void closeInternal() throws SQLException { try { passivate(); } finally { if (connection != null) { boolean connectionIsClosed; try { connectionIsClosed = connection.isClosed(); } catch (final SQLException e) { // not sure what the state is, so assume the connection is open. connectionIsClosed = false; } try { // DBCP-512: Avoid exceptions when closing a connection in multi-threaded use case. // Avoid closing again, which should be a no-op, but some drivers like H2 throw an exception when // closing from multiple threads. if (!connectionIsClosed) { connection.close(); } } finally { closed = true; } } else { closed = true; } } } @Override public void commit() throws SQLException { checkOpen(); try { connection.commit(); } catch (final SQLException e) { handleException(e); } } @Override public Array createArrayOf(final String typeName, final Object[] elements) throws SQLException { checkOpen(); try { return connection.createArrayOf(typeName, elements); } catch (final SQLException e) { handleException(e); return null; } } @Override public Blob createBlob() throws SQLException { checkOpen(); try { return connection.createBlob(); } catch (final SQLException e) { handleException(e); return null; } } @Override public Clob createClob() throws SQLException { checkOpen(); try { return connection.createClob(); } catch (final SQLException e) { handleException(e); return null; } } @Override public NClob createNClob() throws SQLException { checkOpen(); try { return connection.createNClob(); } catch (final SQLException e) { handleException(e); return null; } } @Override public SQLXML createSQLXML() throws SQLException { checkOpen(); try { return connection.createSQLXML(); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public Statement createStatement() throws SQLException { checkOpen(); try { return init(new DelegatingStatement(this, connection.createStatement())); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); try { return init(new DelegatingStatement(this, connection.createStatement(resultSetType, resultSetConcurrency))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); try { return init(new DelegatingStatement(this, connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability))); } catch (final SQLException e) { handleException(e); return null; } } @Override public Struct createStruct(final String typeName, final Object[] attributes) throws SQLException { checkOpen(); try { return connection.createStruct(typeName, attributes); } catch (final SQLException e) { handleException(e); return null; } } @Override public boolean getAutoCommit() throws SQLException { checkOpen(); if (cacheState && cachedAutoCommit != null) { return cachedAutoCommit; } try { cachedAutoCommit = connection.getAutoCommit(); return cachedAutoCommit; } catch (final SQLException e) { handleException(e); return false; } } /** * Gets whether to cache properties. The cached properties are: *
    *
  • auto-commit
  • *
  • catalog
  • *
  • schema
  • *
  • read-only
  • *
* * @return the state caching flag */ public boolean getCacheState() { return cacheState; } @Override public String getCatalog() throws SQLException { checkOpen(); if (cacheState && cachedCatalog != null) { return cachedCatalog; } try { cachedCatalog = connection.getCatalog(); return cachedCatalog; } catch (final SQLException e) { handleException(e); return null; } } @Override public Properties getClientInfo() throws SQLException { checkOpen(); try { return connection.getClientInfo(); } catch (final SQLException e) { handleException(e); return null; } } @Override public String getClientInfo(final String name) throws SQLException { checkOpen(); try { return connection.getClientInfo(name); } catch (final SQLException e) { handleException(e); return null; } } /** * Gets the default query timeout that will be used for {@link Statement}s created from this connection. * {@code null} means that the driver default will be used. * * @return query timeout limit in seconds; zero means there is no limit. * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. */ @Deprecated public Integer getDefaultQueryTimeout() { return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds(); } /** * Gets the default query timeout that will be used for {@link Statement}s created from this connection. * {@code null} means that the driver default will be used. * * @return query timeout limit; zero means there is no limit. * @since 2.10.0 */ public Duration getDefaultQueryTimeoutDuration() { return defaultQueryTimeoutDuration; } /** * Returns my underlying {@link Connection}. * * @return my underlying {@link Connection}. */ public C getDelegate() { return getDelegateInternal(); } /** * Gets the delegate connection. * * @return the delegate connection. */ protected final C getDelegateInternal() { return connection; } @Override public int getHoldability() throws SQLException { checkOpen(); try { return connection.getHoldability(); } catch (final SQLException e) { handleException(e); return 0; } } /** * If my underlying {@link Connection} is not a {@code DelegatingConnection}, returns it, otherwise recursively * invokes this method on my delegate. *

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

*

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

* * @return innermost delegate. */ public Connection getInnermostDelegate() { return getInnermostDelegateInternal(); } /** * Although this method is public, it is part of the internal API and should not be used by clients. The signature * of this method may change at any time including in ways that break backwards compatibility. * * @return innermost delegate. */ @SuppressWarnings("resource") public final Connection getInnermostDelegateInternal() { Connection conn = connection; while (conn instanceof DelegatingConnection) { conn = ((DelegatingConnection) conn).getDelegateInternal(); if (this == conn) { return null; } } return conn; } @Override public DatabaseMetaData getMetaData() throws SQLException { checkOpen(); try { return new DelegatingDatabaseMetaData(this, connection.getMetaData()); } catch (final SQLException e) { handleException(e); return null; } } @Override public int getNetworkTimeout() throws SQLException { checkOpen(); try { return Jdbc41Bridge.getNetworkTimeout(connection); } catch (final SQLException e) { handleException(e); return 0; } } @Override public String getSchema() throws SQLException { checkOpen(); if (cacheState && cachedSchema != null) { return cachedSchema; } try { cachedSchema = Jdbc41Bridge.getSchema(connection); return cachedSchema; } catch (final SQLException e) { handleException(e); return null; } } @Override public int getTransactionIsolation() throws SQLException { checkOpen(); try { return connection.getTransactionIsolation(); } catch (final SQLException e) { handleException(e); return -1; } } @Override public Map> getTypeMap() throws SQLException { checkOpen(); try { return connection.getTypeMap(); } catch (final SQLException e) { handleException(e); return null; } } @Override public SQLWarning getWarnings() throws SQLException { checkOpen(); try { return connection.getWarnings(); } catch (final SQLException e) { handleException(e); return null; } } /** * Handles the given exception by throwing it. * * @param e the exception to throw. * @throws SQLException the exception to throw. */ protected void handleException(final SQLException e) throws SQLException { throw e; } /** * Handles the given {@code SQLException}. * * @param The throwable type. * @param e The SQLException * @return the given {@code SQLException} * @since 2.7.0 */ protected T handleExceptionNoThrow(final T e) { return e; } /** * Initializes the given statement with this connection's settings. * * @param The DelegatingStatement type. * @param delegatingStatement The DelegatingStatement to initialize. * @return The given DelegatingStatement. * @throws SQLException if a database access error occurs, this method is called on a closed Statement. */ private T init(final T delegatingStatement) throws SQLException { if (defaultQueryTimeoutDuration != null && defaultQueryTimeoutDuration.getSeconds() != delegatingStatement.getQueryTimeout()) { delegatingStatement.setQueryTimeout((int) defaultQueryTimeoutDuration.getSeconds()); } return delegatingStatement; } /** * Compares innermost delegate to the given connection. * * @param c * connection to compare innermost delegate with * @return true if innermost delegate equals {@code c} */ @SuppressWarnings("resource") public boolean innermostDelegateEquals(final Connection c) { final Connection innerCon = getInnermostDelegateInternal(); if (innerCon == null) { return c == null; } return innerCon.equals(c); } @Override public boolean isClosed() throws SQLException { return closed || connection == null || connection.isClosed(); } /** * Tests the raw internal closed state. * * @return the raw internal closed state. */ protected boolean isClosedInternal() { return closed; } @Override public boolean isReadOnly() throws SQLException { checkOpen(); if (cacheState && cachedReadOnly != null) { return cachedReadOnly; } try { cachedReadOnly = connection.isReadOnly(); return cachedReadOnly; } catch (final SQLException e) { handleException(e); return false; } } /** * Tests if the connection has not been closed and is still valid. * * @param timeout The duration to wait for the database operation used to validate the connection to complete. * @return See {@link Connection#isValid(int)}. * @throws SQLException See {@link Connection#isValid(int)}. * @see Connection#isValid(int) * @since 2.10.0 */ public boolean isValid(final Duration timeout) throws SQLException { if (isClosed()) { return false; } try { return connection.isValid((int) timeout.getSeconds()); } catch (final SQLException e) { handleException(e); return false; } } /** * @deprecated Use {@link #isValid(Duration)}. */ @Override @Deprecated public boolean isValid(final int timeoutSeconds) throws SQLException { return isValid(Duration.ofSeconds(timeoutSeconds)); } @Override public boolean isWrapperFor(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return true; } if (iface.isAssignableFrom(connection.getClass())) { return true; } return connection.isWrapperFor(iface); } @Override public String nativeSQL(final String sql) throws SQLException { checkOpen(); try { return connection.nativeSQL(sql); } catch (final SQLException e) { handleException(e); return null; } } /** * Clears the list of objects being traced by this object. * * @throws SQLException Thrown if not all traced objects were closed. */ protected void passivate() throws SQLException { // The JDBC specification requires that a Connection close any open // Statements when it is closed. // DBCP-288. Not all the traced objects will be statements final List traceList = getTrace(); if (!Utils.isEmpty(traceList)) { final List thrownList = new ArrayList<>(); traceList.forEach(trace -> trace.close(thrownList::add)); clearTrace(); if (!thrownList.isEmpty()) { throw new SQLExceptionList(thrownList); } } setLastUsed(Instant.EPOCH); } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public CallableStatement prepareCall(final String sql) throws SQLException { checkOpen(); try { return init(new DelegatingCallableStatement(this, connection.prepareCall(sql))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); try { return init(new DelegatingCallableStatement(this, connection.prepareCall(sql, resultSetType, resultSetConcurrency))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); try { return init(new DelegatingCallableStatement(this, connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { checkOpen(); try { return init(new DelegatingPreparedStatement(this, connection.prepareStatement(sql))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); try { return init(new DelegatingPreparedStatement(this, connection.prepareStatement(sql, autoGeneratedKeys))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); try { return init(new DelegatingPreparedStatement(this, connection.prepareStatement(sql, resultSetType, resultSetConcurrency))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); try { return init(new DelegatingPreparedStatement(this, connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { checkOpen(); try { return init(new DelegatingPreparedStatement(this, connection.prepareStatement(sql, columnIndexes))); } catch (final SQLException e) { handleException(e); return null; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { checkOpen(); try { return init(new DelegatingPreparedStatement(this, connection.prepareStatement(sql, columnNames))); } catch (final SQLException e) { handleException(e); return null; } } @Override public void releaseSavepoint(final Savepoint savepoint) throws SQLException { checkOpen(); try { connection.releaseSavepoint(savepoint); } catch (final SQLException e) { handleException(e); } } @Override public void rollback() throws SQLException { checkOpen(); try { connection.rollback(); } catch (final SQLException e) { handleException(e); } } @Override public void rollback(final Savepoint savepoint) throws SQLException { checkOpen(); try { connection.rollback(savepoint); } catch (final SQLException e) { handleException(e); } } @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { checkOpen(); try { connection.setAutoCommit(autoCommit); if (cacheState) { cachedAutoCommit = connection.getAutoCommit(); } } catch (final SQLException e) { cachedAutoCommit = null; handleException(e); } } /** * Sets whether to cache properties. The cached properties are: *
    *
  • auto-commit
  • *
  • catalog
  • *
  • schema
  • *
  • read-only
  • *
* * @param cacheState The new value for the state caching flag */ public void setCacheState(final boolean cacheState) { this.cacheState = cacheState; } @Override public void setCatalog(final String catalog) throws SQLException { checkOpen(); try { connection.setCatalog(catalog); if (cacheState) { cachedCatalog = connection.getCatalog(); } } catch (final SQLException e) { cachedCatalog = null; handleException(e); } } @Override public void setClientInfo(final Properties properties) throws SQLClientInfoException { try { checkOpen(); connection.setClientInfo(properties); } catch (final SQLClientInfoException e) { throw e; } catch (final SQLException e) { throw new SQLClientInfoException("Connection is closed.", EMPTY_FAILED_PROPERTIES, e); } } @Override public void setClientInfo(final String name, final String value) throws SQLClientInfoException { try { checkOpen(); connection.setClientInfo(name, value); } catch (final SQLClientInfoException e) { throw e; } catch (final SQLException e) { throw new SQLClientInfoException("Connection is closed.", EMPTY_FAILED_PROPERTIES, e); } } /** * Sets the raw internal closed state. * * @param closed the raw internal closed state. */ protected void setClosedInternal(final boolean closed) { this.closed = closed; } /** * Sets the default query timeout that will be used for {@link Statement}s created from this connection. * {@code null} means that the driver default will be used. * * @param defaultQueryTimeoutDuration * the new query timeout limit Duration; zero means there is no limit. * @since 2.10.0 */ public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) { this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration; } /** * Sets the default query timeout that will be used for {@link Statement}s created from this connection. * {@code null} means that the driver default will be used. * * @param defaultQueryTimeoutSeconds * the new query timeout limit in seconds; zero means there is no limit. * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}. */ @Deprecated public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds); } /** * Sets my delegate. * * @param connection * my delegate, may be null. */ public void setDelegate(final C connection) { this.connection = connection; } @Override public void setHoldability(final int holdability) throws SQLException { checkOpen(); try { connection.setHoldability(holdability); } catch (final SQLException e) { handleException(e); } } @Override public void setNetworkTimeout(final Executor executor, final int milliseconds) throws SQLException { checkOpen(); try { Jdbc41Bridge.setNetworkTimeout(connection, executor, milliseconds); } catch (final SQLException e) { handleException(e); } } @Override public void setReadOnly(final boolean readOnly) throws SQLException { checkOpen(); try { connection.setReadOnly(readOnly); if (cacheState) { cachedReadOnly = connection.isReadOnly(); } } catch (final SQLException e) { cachedReadOnly = null; handleException(e); } } @Override public Savepoint setSavepoint() throws SQLException { checkOpen(); try { return connection.setSavepoint(); } catch (final SQLException e) { handleException(e); return null; } } @Override public Savepoint setSavepoint(final String name) throws SQLException { checkOpen(); try { return connection.setSavepoint(name); } catch (final SQLException e) { handleException(e); return null; } } @Override public void setSchema(final String schema) throws SQLException { checkOpen(); try { Jdbc41Bridge.setSchema(connection, schema); if (cacheState) { cachedSchema = Jdbc41Bridge.getSchema(connection); } } catch (final SQLException e) { cachedSchema = null; handleException(e); } } @Override public void setTransactionIsolation(final int level) throws SQLException { checkOpen(); try { connection.setTransactionIsolation(level); } catch (final SQLException e) { handleException(e); } } @Override public void setTypeMap(final Map> map) throws SQLException { checkOpen(); try { connection.setTypeMap(map); } catch (final SQLException e) { handleException(e); } } /** * Returns a string representation of the metadata associated with the innermost delegate connection. */ @SuppressWarnings("resource") @Override public synchronized String toString() { String str = null; final Connection conn = this.getInnermostDelegateInternal(); if (conn != null) { try { if (conn.isClosed()) { str = "connection is closed"; } else { final StringBuilder sb = new StringBuilder(); sb.append(hashCode()); final DatabaseMetaData meta = conn.getMetaData(); if (meta != null) { sb.append(", URL="); sb.append(meta.getURL()); sb.append(", "); sb.append(meta.getDriverName()); str = sb.toString(); } } } catch (final SQLException ignored) { // Ignore } } return str != null ? str : super.toString(); } @Override public T unwrap(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return iface.cast(this); } if (iface.isAssignableFrom(connection.getClass())) { return iface.cast(connection); } return connection.unwrap(iface); } } DelegatingDatabaseMetaData.java000066400000000000000000001052351472045345700343240ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.RowIdLifetime; import java.sql.SQLException; import java.util.Objects; import java.util.concurrent.Callable; /** *

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

*

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

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

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

*

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

* * @return the innermost database meta data. */ public DatabaseMetaData getInnermostDelegate() { DatabaseMetaData m = databaseMetaData; while (m instanceof DelegatingDatabaseMetaData) { m = ((DelegatingDatabaseMetaData) m).getDelegate(); if (this == m) { return null; } } return m; } @Override public int getJDBCMajorVersion() throws SQLException { return getI(databaseMetaData::getJDBCMajorVersion); } @Override public int getJDBCMinorVersion() throws SQLException { return getI(databaseMetaData::getJDBCMinorVersion); } private long getL(final Callable s) throws SQLException { return get(s, 0L); } @Override public int getMaxBinaryLiteralLength() throws SQLException { return getI(databaseMetaData::getMaxBinaryLiteralLength); } @Override public int getMaxCatalogNameLength() throws SQLException { return getI(databaseMetaData::getMaxCatalogNameLength); } @Override public int getMaxCharLiteralLength() throws SQLException { return getI(databaseMetaData::getMaxCharLiteralLength); } @Override public int getMaxColumnNameLength() throws SQLException { return getI(databaseMetaData::getMaxColumnNameLength); } @Override public int getMaxColumnsInGroupBy() throws SQLException { return getI(databaseMetaData::getMaxColumnsInGroupBy); } @Override public int getMaxColumnsInIndex() throws SQLException { return getI(databaseMetaData::getMaxColumnsInIndex); } @Override public int getMaxColumnsInOrderBy() throws SQLException { return getI(databaseMetaData::getMaxColumnsInOrderBy); } @Override public int getMaxColumnsInSelect() throws SQLException { return getI(databaseMetaData::getMaxColumnsInSelect); } @Override public int getMaxColumnsInTable() throws SQLException { return getI(databaseMetaData::getMaxColumnsInTable); } @Override public int getMaxConnections() throws SQLException { return getI(databaseMetaData::getMaxConnections); } @Override public int getMaxCursorNameLength() throws SQLException { return getI(databaseMetaData::getMaxCursorNameLength); } @Override public int getMaxIndexLength() throws SQLException { return getI(databaseMetaData::getMaxIndexLength); } /** * @since 2.5.0 */ @Override public long getMaxLogicalLobSize() throws SQLException { return getL(databaseMetaData::getMaxLogicalLobSize); } @Override public int getMaxProcedureNameLength() throws SQLException { return getI(databaseMetaData::getMaxProcedureNameLength); } @Override public int getMaxRowSize() throws SQLException { return getI(databaseMetaData::getMaxRowSize); } @Override public int getMaxSchemaNameLength() throws SQLException { return getI(databaseMetaData::getMaxSchemaNameLength); } @Override public int getMaxStatementLength() throws SQLException { return getI(databaseMetaData::getMaxStatementLength); } @Override public int getMaxStatements() throws SQLException { return getI(databaseMetaData::getMaxStatements); } @Override public int getMaxTableNameLength() throws SQLException { return getI(databaseMetaData::getMaxTableNameLength); } @Override public int getMaxTablesInSelect() throws SQLException { return getI(databaseMetaData::getMaxTablesInSelect); } @Override public int getMaxUserNameLength() throws SQLException { return getI(databaseMetaData::getMaxUserNameLength); } @Override public String getNumericFunctions() throws SQLException { return get(databaseMetaData::getNumericFunctions); } @Override public ResultSet getPrimaryKeys(final String catalog, final String schema, final String table) throws SQLException { return getRS(() -> databaseMetaData.getPrimaryKeys(catalog, schema, table)); } @Override public ResultSet getProcedureColumns(final String catalog, final String schemaPattern, final String procedureNamePattern, final String columnNamePattern) throws SQLException { return getRS(() -> databaseMetaData.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern)); } @Override public ResultSet getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) throws SQLException { return getRS(() -> databaseMetaData.getProcedures(catalog, schemaPattern, procedureNamePattern)); } @Override public String getProcedureTerm() throws SQLException { return get(databaseMetaData::getProcedureTerm); } @Override public ResultSet getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { return getRS(() -> Jdbc41Bridge.getPseudoColumns(databaseMetaData, catalog, schemaPattern, tableNamePattern, columnNamePattern)); } @Override public int getResultSetHoldability() throws SQLException { return getI(databaseMetaData::getResultSetHoldability); } @Override public RowIdLifetime getRowIdLifetime() throws SQLException { return get(databaseMetaData::getRowIdLifetime); } @SuppressWarnings("resource") private ResultSet getRS(final Callable s) throws SQLException { connection.checkOpen(); return DelegatingResultSet.wrapResultSet(connection, get(s)); } @Override public ResultSet getSchemas() throws SQLException { return getRS(databaseMetaData::getSchemas); } @Override public ResultSet getSchemas(final String catalog, final String schemaPattern) throws SQLException { return getRS(() -> databaseMetaData.getSchemas(catalog, schemaPattern)); } @Override public String getSchemaTerm() throws SQLException { return get(databaseMetaData::getSchemaTerm); } @Override public String getSearchStringEscape() throws SQLException { return get(databaseMetaData::getSearchStringEscape); } @Override public String getSQLKeywords() throws SQLException { return get(databaseMetaData::getSQLKeywords); } @Override public int getSQLStateType() throws SQLException { return getI(databaseMetaData::getSQLStateType); } @Override public String getStringFunctions() throws SQLException { return get(databaseMetaData::getStringFunctions); } @Override public ResultSet getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { return getRS(() -> databaseMetaData.getSuperTables(catalog, schemaPattern, tableNamePattern)); } @Override public ResultSet getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern) throws SQLException { return getRS(() -> databaseMetaData.getSuperTypes(catalog, schemaPattern, typeNamePattern)); } @Override public String getSystemFunctions() throws SQLException { return get(databaseMetaData::getSystemFunctions); } @Override public ResultSet getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { return getRS(() -> databaseMetaData.getTablePrivileges(catalog, schemaPattern, tableNamePattern)); } @Override public ResultSet getTables(final String catalog, final String schemaPattern, final String tableNamePattern, final String[] types) throws SQLException { return getRS(() -> databaseMetaData.getTables(catalog, schemaPattern, tableNamePattern, types)); } @Override public ResultSet getTableTypes() throws SQLException { return getRS(databaseMetaData::getTableTypes); } @Override public String getTimeDateFunctions() throws SQLException { return get(databaseMetaData::getTimeDateFunctions); } @Override public ResultSet getTypeInfo() throws SQLException { return getRS(databaseMetaData::getTypeInfo); } @Override public ResultSet getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, final int[] types) throws SQLException { return getRS(() -> databaseMetaData.getUDTs(catalog, schemaPattern, typeNamePattern, types)); } @Override public String getURL() throws SQLException { return get(databaseMetaData::getURL); } @Override public String getUserName() throws SQLException { return get(databaseMetaData::getUserName); } @Override public ResultSet getVersionColumns(final String catalog, final String schema, final String table) throws SQLException { return getRS(() -> databaseMetaData.getVersionColumns(catalog, schema, table)); } /** * Delegates to the connection's {@link DelegatingConnection#handleException(SQLException)}. * * @param e the exception to throw or delegate. * @throws SQLException the exception to throw. */ protected void handleException(final SQLException e) throws SQLException { if (connection == null) { throw e; } connection.handleException(e); } @Override public boolean insertsAreDetected(final int type) throws SQLException { return getB(() -> databaseMetaData.insertsAreDetected(type)); } @Override public boolean isCatalogAtStart() throws SQLException { return getB(databaseMetaData::isCatalogAtStart); } @Override public boolean isReadOnly() throws SQLException { return getB(databaseMetaData::isReadOnly); } @Override public boolean isWrapperFor(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return true; } if (iface.isAssignableFrom(databaseMetaData.getClass())) { return true; } return databaseMetaData.isWrapperFor(iface); } @Override public boolean locatorsUpdateCopy() throws SQLException { return getB(databaseMetaData::locatorsUpdateCopy); } @Override public boolean nullPlusNonNullIsNull() throws SQLException { return getB(databaseMetaData::nullPlusNonNullIsNull); } @Override public boolean nullsAreSortedAtEnd() throws SQLException { return getB(databaseMetaData::nullsAreSortedAtEnd); } @Override public boolean nullsAreSortedAtStart() throws SQLException { return getB(databaseMetaData::nullsAreSortedAtStart); } @Override public boolean nullsAreSortedHigh() throws SQLException { return getB(databaseMetaData::nullsAreSortedHigh); } @Override public boolean nullsAreSortedLow() throws SQLException { return getB(databaseMetaData::nullsAreSortedLow); } @Override public boolean othersDeletesAreVisible(final int type) throws SQLException { return getB(() -> databaseMetaData.othersDeletesAreVisible(type)); } @Override public boolean othersInsertsAreVisible(final int type) throws SQLException { return getB(() -> databaseMetaData.othersInsertsAreVisible(type)); } @Override public boolean othersUpdatesAreVisible(final int type) throws SQLException { return getB(() -> databaseMetaData.othersUpdatesAreVisible(type)); } @Override public boolean ownDeletesAreVisible(final int type) throws SQLException { return getB(() -> databaseMetaData.ownDeletesAreVisible(type)); } @Override public boolean ownInsertsAreVisible(final int type) throws SQLException { return getB(() -> databaseMetaData.ownInsertsAreVisible(type)); } @Override public boolean ownUpdatesAreVisible(final int type) throws SQLException { return getB(() -> databaseMetaData.ownUpdatesAreVisible(type)); } @Override public boolean storesLowerCaseIdentifiers() throws SQLException { return getB(databaseMetaData::storesLowerCaseIdentifiers); } @Override public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { return getB(databaseMetaData::storesLowerCaseQuotedIdentifiers); } @Override public boolean storesMixedCaseIdentifiers() throws SQLException { return getB(databaseMetaData::storesMixedCaseIdentifiers); } @Override public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { return getB(databaseMetaData::storesMixedCaseQuotedIdentifiers); } @Override public boolean storesUpperCaseIdentifiers() throws SQLException { return getB(databaseMetaData::storesUpperCaseIdentifiers); } @Override public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { return getB(databaseMetaData::storesUpperCaseQuotedIdentifiers); } @Override public boolean supportsAlterTableWithAddColumn() throws SQLException { return getB(databaseMetaData::supportsAlterTableWithAddColumn); } @Override public boolean supportsAlterTableWithDropColumn() throws SQLException { return getB(databaseMetaData::supportsAlterTableWithDropColumn); } @Override public boolean supportsANSI92EntryLevelSQL() throws SQLException { return getB(databaseMetaData::supportsANSI92EntryLevelSQL); } @Override public boolean supportsANSI92FullSQL() throws SQLException { return getB(databaseMetaData::supportsANSI92FullSQL); } @Override public boolean supportsANSI92IntermediateSQL() throws SQLException { return getB(databaseMetaData::supportsANSI92IntermediateSQL); } @Override public boolean supportsBatchUpdates() throws SQLException { return getB(databaseMetaData::supportsBatchUpdates); } @Override public boolean supportsCatalogsInDataManipulation() throws SQLException { return getB(databaseMetaData::supportsCatalogsInDataManipulation); } @Override public boolean supportsCatalogsInIndexDefinitions() throws SQLException { return getB(databaseMetaData::supportsCatalogsInIndexDefinitions); } @Override public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { return getB(databaseMetaData::supportsCatalogsInPrivilegeDefinitions); } @Override public boolean supportsCatalogsInProcedureCalls() throws SQLException { return getB(databaseMetaData::supportsCatalogsInProcedureCalls); } @Override public boolean supportsCatalogsInTableDefinitions() throws SQLException { return getB(databaseMetaData::supportsCatalogsInTableDefinitions); } @Override public boolean supportsColumnAliasing() throws SQLException { return getB(databaseMetaData::supportsColumnAliasing); } @Override public boolean supportsConvert() throws SQLException { return getB(databaseMetaData::supportsConvert); } @Override public boolean supportsConvert(final int fromType, final int toType) throws SQLException { return getB(() -> databaseMetaData.supportsConvert(fromType, toType)); } @Override public boolean supportsCoreSQLGrammar() throws SQLException { return getB(databaseMetaData::supportsCoreSQLGrammar); } @Override public boolean supportsCorrelatedSubqueries() throws SQLException { return getB(databaseMetaData::supportsCorrelatedSubqueries); } @Override public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { return getB(databaseMetaData::supportsDataDefinitionAndDataManipulationTransactions); } @Override public boolean supportsDataManipulationTransactionsOnly() throws SQLException { return getB(databaseMetaData::supportsDataManipulationTransactionsOnly); } @Override public boolean supportsDifferentTableCorrelationNames() throws SQLException { return getB(databaseMetaData::supportsDifferentTableCorrelationNames); } @Override public boolean supportsExpressionsInOrderBy() throws SQLException { return getB(databaseMetaData::supportsExpressionsInOrderBy); } @Override public boolean supportsExtendedSQLGrammar() throws SQLException { return getB(databaseMetaData::supportsExtendedSQLGrammar); } @Override public boolean supportsFullOuterJoins() throws SQLException { return getB(databaseMetaData::supportsFullOuterJoins); } @Override public boolean supportsGetGeneratedKeys() throws SQLException { return getB(databaseMetaData::supportsGetGeneratedKeys); } @Override public boolean supportsGroupBy() throws SQLException { return getB(databaseMetaData::supportsGroupBy); } @Override public boolean supportsGroupByBeyondSelect() throws SQLException { return getB(databaseMetaData::supportsGroupByBeyondSelect); } @Override public boolean supportsGroupByUnrelated() throws SQLException { return getB(databaseMetaData::supportsGroupByUnrelated); } @Override public boolean supportsIntegrityEnhancementFacility() throws SQLException { return getB(databaseMetaData::supportsIntegrityEnhancementFacility); } @Override public boolean supportsLikeEscapeClause() throws SQLException { return getB(databaseMetaData::supportsLikeEscapeClause); } @Override public boolean supportsLimitedOuterJoins() throws SQLException { return getB(databaseMetaData::supportsLimitedOuterJoins); } @Override public boolean supportsMinimumSQLGrammar() throws SQLException { return getB(databaseMetaData::supportsMinimumSQLGrammar); } @Override public boolean supportsMixedCaseIdentifiers() throws SQLException { return getB(databaseMetaData::supportsMixedCaseIdentifiers); } @Override public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { return getB(databaseMetaData::supportsMixedCaseQuotedIdentifiers); } @Override public boolean supportsMultipleOpenResults() throws SQLException { return getB(databaseMetaData::supportsMultipleOpenResults); } @Override public boolean supportsMultipleResultSets() throws SQLException { return getB(databaseMetaData::supportsMultipleResultSets); } @Override public boolean supportsMultipleTransactions() throws SQLException { return getB(databaseMetaData::supportsMultipleTransactions); } @Override public boolean supportsNamedParameters() throws SQLException { return getB(databaseMetaData::supportsNamedParameters); } @Override public boolean supportsNonNullableColumns() throws SQLException { return getB(databaseMetaData::supportsNonNullableColumns); } @Override public boolean supportsOpenCursorsAcrossCommit() throws SQLException { return getB(databaseMetaData::supportsOpenCursorsAcrossCommit); } @Override public boolean supportsOpenCursorsAcrossRollback() throws SQLException { return getB(databaseMetaData::supportsOpenCursorsAcrossRollback); } @Override public boolean supportsOpenStatementsAcrossCommit() throws SQLException { return getB(databaseMetaData::supportsOpenStatementsAcrossCommit); } @Override public boolean supportsOpenStatementsAcrossRollback() throws SQLException { return getB(databaseMetaData::supportsOpenStatementsAcrossRollback); } @Override public boolean supportsOrderByUnrelated() throws SQLException { return getB(databaseMetaData::supportsOrderByUnrelated); } @Override public boolean supportsOuterJoins() throws SQLException { return getB(databaseMetaData::supportsOuterJoins); } @Override public boolean supportsPositionedDelete() throws SQLException { return getB(databaseMetaData::supportsPositionedDelete); } @Override public boolean supportsPositionedUpdate() throws SQLException { return getB(databaseMetaData::supportsPositionedUpdate); } /** * @since 2.5.0 */ @Override public boolean supportsRefCursors() throws SQLException { return getB(databaseMetaData::supportsRefCursors); } @Override public boolean supportsResultSetConcurrency(final int type, final int concurrency) throws SQLException { return getB(() -> databaseMetaData.supportsResultSetConcurrency(type, concurrency)); } @Override public boolean supportsResultSetHoldability(final int holdability) throws SQLException { return getB(() -> databaseMetaData.supportsResultSetHoldability(holdability)); } @Override public boolean supportsResultSetType(final int type) throws SQLException { return getB(() -> databaseMetaData.supportsResultSetType(type)); } @Override public boolean supportsSavepoints() throws SQLException { return getB(databaseMetaData::supportsSavepoints); } @Override public boolean supportsSchemasInDataManipulation() throws SQLException { return getB(databaseMetaData::supportsSchemasInDataManipulation); } @Override public boolean supportsSchemasInIndexDefinitions() throws SQLException { return getB(databaseMetaData::supportsSchemasInIndexDefinitions); } @Override public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { return getB(databaseMetaData::supportsSchemasInPrivilegeDefinitions); } @Override public boolean supportsSchemasInProcedureCalls() throws SQLException { return getB(databaseMetaData::supportsSchemasInProcedureCalls); } @Override public boolean supportsSchemasInTableDefinitions() throws SQLException { return getB(databaseMetaData::supportsSchemasInTableDefinitions); } @Override public boolean supportsSelectForUpdate() throws SQLException { return getB(databaseMetaData::supportsSelectForUpdate); } @Override public boolean supportsStatementPooling() throws SQLException { return getB(databaseMetaData::supportsStatementPooling); } @Override public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { return getB(databaseMetaData::supportsStoredFunctionsUsingCallSyntax); } @Override public boolean supportsStoredProcedures() throws SQLException { return getB(databaseMetaData::supportsStoredProcedures); } @Override public boolean supportsSubqueriesInComparisons() throws SQLException { return getB(databaseMetaData::supportsSubqueriesInComparisons); } @Override public boolean supportsSubqueriesInExists() throws SQLException { return getB(databaseMetaData::supportsSubqueriesInExists); } @Override public boolean supportsSubqueriesInIns() throws SQLException { return getB(databaseMetaData::supportsSubqueriesInIns); } @Override public boolean supportsSubqueriesInQuantifieds() throws SQLException { return getB(databaseMetaData::supportsSubqueriesInQuantifieds); } @Override public boolean supportsTableCorrelationNames() throws SQLException { return getB(databaseMetaData::supportsTableCorrelationNames); } @Override public boolean supportsTransactionIsolationLevel(final int level) throws SQLException { return getB(() -> databaseMetaData.supportsTransactionIsolationLevel(level)); } @Override public boolean supportsTransactions() throws SQLException { return getB(databaseMetaData::supportsTransactions); } @Override public boolean supportsUnion() throws SQLException { return getB(databaseMetaData::supportsUnion); } @Override public boolean supportsUnionAll() throws SQLException { return getB(databaseMetaData::supportsUnionAll); } @Override public T unwrap(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return iface.cast(this); } if (iface.isAssignableFrom(databaseMetaData.getClass())) { return iface.cast(databaseMetaData); } return databaseMetaData.unwrap(iface); } @Override public boolean updatesAreDetected(final int type) throws SQLException { return getB(() -> databaseMetaData.updatesAreDetected(type)); } @Override public boolean usesLocalFilePerTable() throws SQLException { return getB(databaseMetaData::usesLocalFilePerTable); } @Override public boolean usesLocalFiles() throws SQLException { return getB(databaseMetaData::usesLocalFiles); } } DelegatingPreparedStatement.java000066400000000000000000000556751472045345700346620ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Date; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLType; import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Objects; /** * A base delegating implementation of {@link PreparedStatement}. *

* All of the methods from the {@link PreparedStatement} interface simply check to see that the * {@link PreparedStatement} is active, and call the corresponding method on the "delegate" provided in my constructor. *

* Extends AbandonedTrace to implement Statement tracking and logging of code which created the Statement. Tracking the * Statement ensures that the Connection which created it can close any open Statement's on Connection close. * * @since 2.0 */ public class DelegatingPreparedStatement extends DelegatingStatement implements PreparedStatement { /** * Create a wrapper for the Statement which traces this Statement to the Connection which created it and the code * which created it. * * @param statement * the {@link PreparedStatement} to delegate all calls to. * @param connection * the {@link DelegatingConnection} that created this statement. */ public DelegatingPreparedStatement(final DelegatingConnection connection, final PreparedStatement statement) { super(connection, statement); } @Override public void addBatch() throws SQLException { checkOpen(); try { getDelegatePreparedStatement().addBatch(); } catch (final SQLException e) { handleException(e); } } @Override public void clearParameters() throws SQLException { checkOpen(); try { getDelegatePreparedStatement().clearParameters(); } catch (final SQLException e) { handleException(e); } } @Override public boolean execute() throws SQLException { checkOpen(); if (getConnectionInternal() != null) { getConnectionInternal().setLastUsed(); } try { return getDelegatePreparedStatement().execute(); } catch (final SQLException e) { handleException(e); return false; } } /** * @since 2.5.0 */ @Override public long executeLargeUpdate() throws SQLException { checkOpen(); try { return getDelegatePreparedStatement().executeLargeUpdate(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public ResultSet executeQuery() throws SQLException { checkOpen(); if (getConnectionInternal() != null) { getConnectionInternal().setLastUsed(); } try { return DelegatingResultSet.wrapResultSet(this, getDelegatePreparedStatement().executeQuery()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public int executeUpdate() throws SQLException { checkOpen(); if (getConnectionInternal() != null) { getConnectionInternal().setLastUsed(); } try { return getDelegatePreparedStatement().executeUpdate(); } catch (final SQLException e) { handleException(e); return 0; } } private PreparedStatement getDelegatePreparedStatement() { return (PreparedStatement) getDelegate(); } @Override public ResultSetMetaData getMetaData() throws SQLException { checkOpen(); try { return getDelegatePreparedStatement().getMetaData(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public java.sql.ParameterMetaData getParameterMetaData() throws SQLException { checkOpen(); try { return getDelegatePreparedStatement().getParameterMetaData(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } protected void prepareToReturn() throws SQLException { setClosedInternal(true); removeThisTrace(getConnectionInternal()); // The JDBC spec requires that a statement close any open // ResultSet's when it is closed. // FIXME The PreparedStatement we're wrapping should handle this for us. // See DBCP-10 for what could happen when ResultSets are closed twice. final List traceList = getTrace(); if (traceList != null) { final List thrownList = new ArrayList<>(); traceList.forEach(trace -> trace.close(thrownList::add)); clearTrace(); if (!thrownList.isEmpty()) { throw new SQLExceptionList(thrownList); } } super.passivate(); } @Override public void setArray(final int i, final Array x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setArray(i, x); } catch (final SQLException e) { handleException(e); } } @Override public void setAsciiStream(final int parameterIndex, final InputStream inputStream) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setAsciiStream(parameterIndex, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void setAsciiStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setAsciiStream(parameterIndex, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void setAsciiStream(final int parameterIndex, final InputStream inputStream, final long length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setAsciiStream(parameterIndex, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void setBigDecimal(final int parameterIndex, final BigDecimal x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBigDecimal(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setBinaryStream(final int parameterIndex, final InputStream inputStream) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBinaryStream(parameterIndex, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void setBinaryStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBinaryStream(parameterIndex, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void setBinaryStream(final int parameterIndex, final InputStream inputStream, final long length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBinaryStream(parameterIndex, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void setBlob(final int i, final Blob x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBlob(i, x); } catch (final SQLException e) { handleException(e); } } @Override public void setBlob(final int parameterIndex, final InputStream inputStream) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBlob(parameterIndex, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void setBlob(final int parameterIndex, final InputStream inputStream, final long length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBlob(parameterIndex, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void setBoolean(final int parameterIndex, final boolean x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBoolean(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setByte(final int parameterIndex, final byte x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setByte(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setBytes(final int parameterIndex, final byte[] x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setBytes(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setCharacterStream(final int parameterIndex, final Reader reader) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader); } catch (final SQLException e) { handleException(e); } } @Override public void setCharacterStream(final int parameterIndex, final Reader reader, final int length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void setCharacterStream(final int parameterIndex, final Reader reader, final long length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void setClob(final int i, final Clob x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setClob(i, x); } catch (final SQLException e) { handleException(e); } } @Override public void setClob(final int parameterIndex, final Reader reader) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setClob(parameterIndex, reader); } catch (final SQLException e) { handleException(e); } } @Override public void setClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setClob(parameterIndex, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void setDate(final int parameterIndex, final Date x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setDate(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setDate(final int parameterIndex, final Date x, final Calendar cal) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setDate(parameterIndex, x, cal); } catch (final SQLException e) { handleException(e); } } @Override public void setDouble(final int parameterIndex, final double x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setDouble(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setFloat(final int parameterIndex, final float x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setFloat(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setInt(final int parameterIndex, final int x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setInt(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setLong(final int parameterIndex, final long x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setLong(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setNCharacterStream(final int parameterIndex, final Reader reader) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setNCharacterStream(parameterIndex, reader); } catch (final SQLException e) { handleException(e); } } @Override public void setNCharacterStream(final int parameterIndex, final Reader value, final long length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setNCharacterStream(parameterIndex, value, length); } catch (final SQLException e) { handleException(e); } } @Override public void setNClob(final int parameterIndex, final NClob value) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setNClob(parameterIndex, value); } catch (final SQLException e) { handleException(e); } } @Override public void setNClob(final int parameterIndex, final Reader reader) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setNClob(parameterIndex, reader); } catch (final SQLException e) { handleException(e); } } @Override public void setNClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setNClob(parameterIndex, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void setNString(final int parameterIndex, final String value) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setNString(parameterIndex, value); } catch (final SQLException e) { handleException(e); } } @Override public void setNull(final int parameterIndex, final int sqlType) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setNull(parameterIndex, sqlType); } catch (final SQLException e) { handleException(e); } } @Override public void setNull(final int paramIndex, final int sqlType, final String typeName) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setNull(paramIndex, sqlType, typeName); } catch (final SQLException e) { handleException(e); } } @Override public void setObject(final int parameterIndex, final Object x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setObject(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setObject(final int parameterIndex, final Object x, final int targetSqlType) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType); } catch (final SQLException e) { handleException(e); } } @Override public void setObject(final int parameterIndex, final Object x, final int targetSqlType, final int scale) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType, scale); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType, scaleOrLength); } catch (final SQLException e) { handleException(e); } } @Override public void setRef(final int i, final Ref x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setRef(i, x); } catch (final SQLException e) { handleException(e); } } @Override public void setRowId(final int parameterIndex, final RowId value) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setRowId(parameterIndex, value); } catch (final SQLException e) { handleException(e); } } @Override public void setShort(final int parameterIndex, final short x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setShort(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setSQLXML(final int parameterIndex, final SQLXML value) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setSQLXML(parameterIndex, value); } catch (final SQLException e) { handleException(e); } } @Override public void setString(final int parameterIndex, final String x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setString(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setTime(final int parameterIndex, final Time x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setTime(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setTime(final int parameterIndex, final Time x, final Calendar cal) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setTime(parameterIndex, x, cal); } catch (final SQLException e) { handleException(e); } } @Override public void setTimestamp(final int parameterIndex, final Timestamp x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setTimestamp(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void setTimestamp(final int parameterIndex, final Timestamp x, final Calendar cal) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setTimestamp(parameterIndex, x, cal); } catch (final SQLException e) { handleException(e); } } /** @deprecated Use setAsciiStream(), setCharacterStream() or setNCharacterStream() */ @Deprecated @Override public void setUnicodeStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setUnicodeStream(parameterIndex, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void setURL(final int parameterIndex, final java.net.URL x) throws SQLException { checkOpen(); try { getDelegatePreparedStatement().setURL(parameterIndex, x); } catch (final SQLException e) { handleException(e); } } /** * Returns a String representation of this object. * * @return String */ @SuppressWarnings("resource") @Override public synchronized String toString() { return Objects.toString(getDelegate(), "NULL"); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/DelegatingResultSet.java000066400000000000000000001636651472045345700332430ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; import java.sql.Date; import java.sql.NClob; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLType; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Map; /** * A base delegating implementation of {@link ResultSet}. *

* All of the methods from the {@link ResultSet} interface simply call the corresponding method on the "delegate" * provided in my constructor. *

*

* Extends AbandonedTrace to implement result set tracking and logging of code which created the ResultSet. Tracking the * ResultSet ensures that the Statement which created it can close any open ResultSet's on Statement close. *

* * @since 2.0 */ public final class DelegatingResultSet extends AbandonedTrace implements ResultSet { /** * Wraps the given result set in a delegate. * * @param connection * The Connection which created the ResultSet. * @param resultSet * The ResultSet to wrap. * @return a new delegate. */ public static ResultSet wrapResultSet(final Connection connection, final ResultSet resultSet) { if (null == resultSet) { return null; } return new DelegatingResultSet(connection, resultSet); } /** * Wraps the given result set in a delegate. * * @param statement * The Statement which created the ResultSet. * @param resultSet * The ResultSet to wrap. * @return a new delegate. */ public static ResultSet wrapResultSet(final Statement statement, final ResultSet resultSet) { if (null == resultSet) { return null; } return new DelegatingResultSet(statement, resultSet); } /** My delegate. **/ private final ResultSet resultSet; /** The Statement that created me, if any. **/ private Statement statement; /** The Connection that created me, if any. **/ private Connection connection; /** * Creates a wrapper for the ResultSet which traces this ResultSet to the Connection which created it (via, for * example DatabaseMetadata), and the code which created it. *

* Private to ensure all construction is {@link #wrapResultSet(Connection, ResultSet)} *

* * @param connection * Connection which created this ResultSet * @param resultSet * ResultSet to wrap */ private DelegatingResultSet(final Connection connection, final ResultSet resultSet) { super((AbandonedTrace) connection); this.connection = connection; this.resultSet = resultSet; } /** * Creates a wrapper for the ResultSet which traces this ResultSet to the Statement which created it and the code * which created it. *

* Private to ensure all construction is {@link #wrapResultSet(Statement, ResultSet)} *

* * @param statement * The Statement which created the ResultSet. * @param resultSet * The ResultSet to wrap. */ private DelegatingResultSet(final Statement statement, final ResultSet resultSet) { super((AbandonedTrace) statement); this.statement = statement; this.resultSet = resultSet; } @Override public boolean absolute(final int row) throws SQLException { try { return resultSet.absolute(row); } catch (final SQLException e) { handleException(e); return false; } } @Override public void afterLast() throws SQLException { try { resultSet.afterLast(); } catch (final SQLException e) { handleException(e); } } @Override public void beforeFirst() throws SQLException { try { resultSet.beforeFirst(); } catch (final SQLException e) { handleException(e); } } @Override public void cancelRowUpdates() throws SQLException { try { resultSet.cancelRowUpdates(); } catch (final SQLException e) { handleException(e); } } @Override public void clearWarnings() throws SQLException { try { resultSet.clearWarnings(); } catch (final SQLException e) { handleException(e); } } /** * Wrapper for close of ResultSet which removes this result set from being traced then calls close on the original * ResultSet. */ @Override public void close() throws SQLException { try { if (statement != null) { removeThisTrace(statement); statement = null; } if (connection != null) { removeThisTrace(connection); connection = null; } resultSet.close(); } catch (final SQLException e) { handleException(e); } } @Override public void deleteRow() throws SQLException { try { resultSet.deleteRow(); } catch (final SQLException e) { handleException(e); } } @Override public int findColumn(final String columnName) throws SQLException { try { return resultSet.findColumn(columnName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public boolean first() throws SQLException { try { return resultSet.first(); } catch (final SQLException e) { handleException(e); return false; } } @Override public Array getArray(final int i) throws SQLException { try { return resultSet.getArray(i); } catch (final SQLException e) { handleException(e); return null; } } @Override public Array getArray(final String colName) throws SQLException { try { return resultSet.getArray(colName); } catch (final SQLException e) { handleException(e); return null; } } @Override public InputStream getAsciiStream(final int columnIndex) throws SQLException { try { return resultSet.getAsciiStream(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public InputStream getAsciiStream(final String columnName) throws SQLException { try { return resultSet.getAsciiStream(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public BigDecimal getBigDecimal(final int columnIndex) throws SQLException { try { return resultSet.getBigDecimal(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } /** @deprecated Use {@link #getBigDecimal(int)} */ @Deprecated @Override public BigDecimal getBigDecimal(final int columnIndex, final int scale) throws SQLException { try { return resultSet.getBigDecimal(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public BigDecimal getBigDecimal(final String columnName) throws SQLException { try { return resultSet.getBigDecimal(columnName); } catch (final SQLException e) { handleException(e); return null; } } /** @deprecated Use {@link #getBigDecimal(String)} */ @Deprecated @Override public BigDecimal getBigDecimal(final String columnName, final int scale) throws SQLException { try { return resultSet.getBigDecimal(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public InputStream getBinaryStream(final int columnIndex) throws SQLException { try { return resultSet.getBinaryStream(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public InputStream getBinaryStream(final String columnName) throws SQLException { try { return resultSet.getBinaryStream(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Blob getBlob(final int i) throws SQLException { try { return resultSet.getBlob(i); } catch (final SQLException e) { handleException(e); return null; } } @Override public Blob getBlob(final String colName) throws SQLException { try { return resultSet.getBlob(colName); } catch (final SQLException e) { handleException(e); return null; } } @Override public boolean getBoolean(final int columnIndex) throws SQLException { try { return resultSet.getBoolean(columnIndex); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean getBoolean(final String columnName) throws SQLException { try { return resultSet.getBoolean(columnName); } catch (final SQLException e) { handleException(e); return false; } } @Override public byte getByte(final int columnIndex) throws SQLException { try { return resultSet.getByte(columnIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public byte getByte(final String columnName) throws SQLException { try { return resultSet.getByte(columnName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public byte[] getBytes(final int columnIndex) throws SQLException { try { return resultSet.getBytes(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public byte[] getBytes(final String columnName) throws SQLException { try { return resultSet.getBytes(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Reader getCharacterStream(final int columnIndex) throws SQLException { try { return resultSet.getCharacterStream(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Reader getCharacterStream(final String columnName) throws SQLException { try { return resultSet.getCharacterStream(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Clob getClob(final int i) throws SQLException { try { return resultSet.getClob(i); } catch (final SQLException e) { handleException(e); return null; } } @Override public Clob getClob(final String colName) throws SQLException { try { return resultSet.getClob(colName); } catch (final SQLException e) { handleException(e); return null; } } @Override public int getConcurrency() throws SQLException { try { return resultSet.getConcurrency(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public String getCursorName() throws SQLException { try { return resultSet.getCursorName(); } catch (final SQLException e) { handleException(e); return null; } } @Override public Date getDate(final int columnIndex) throws SQLException { try { return resultSet.getDate(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Date getDate(final int columnIndex, final Calendar cal) throws SQLException { try { return resultSet.getDate(columnIndex, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public Date getDate(final String columnName) throws SQLException { try { return resultSet.getDate(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Date getDate(final String columnName, final Calendar cal) throws SQLException { try { return resultSet.getDate(columnName, cal); } catch (final SQLException e) { handleException(e); return null; } } /** * Gets my delegate. * * @return my delegate. */ public ResultSet getDelegate() { return resultSet; } @Override public double getDouble(final int columnIndex) throws SQLException { try { return resultSet.getDouble(columnIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public double getDouble(final String columnName) throws SQLException { try { return resultSet.getDouble(columnName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getFetchDirection() throws SQLException { try { return resultSet.getFetchDirection(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getFetchSize() throws SQLException { try { return resultSet.getFetchSize(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public float getFloat(final int columnIndex) throws SQLException { try { return resultSet.getFloat(columnIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public float getFloat(final String columnName) throws SQLException { try { return resultSet.getFloat(columnName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getHoldability() throws SQLException { try { return resultSet.getHoldability(); } catch (final SQLException e) { handleException(e); return 0; } } /** * If my underlying {@link ResultSet} is not a {@code DelegatingResultSet}, returns it, otherwise recursively * invokes this method on my delegate. *

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

*

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

* * @return the innermost delegate. */ @SuppressWarnings("resource") public ResultSet getInnermostDelegate() { ResultSet r = resultSet; while (r instanceof DelegatingResultSet) { r = ((DelegatingResultSet) r).getDelegate(); if (this == r) { return null; } } return r; } @Override public int getInt(final int columnIndex) throws SQLException { try { return resultSet.getInt(columnIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getInt(final String columnName) throws SQLException { try { return resultSet.getInt(columnName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public long getLong(final int columnIndex) throws SQLException { try { return resultSet.getLong(columnIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public long getLong(final String columnName) throws SQLException { try { return resultSet.getLong(columnName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public ResultSetMetaData getMetaData() throws SQLException { try { return resultSet.getMetaData(); } catch (final SQLException e) { handleException(e); return null; } } @Override public Reader getNCharacterStream(final int columnIndex) throws SQLException { try { return resultSet.getNCharacterStream(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Reader getNCharacterStream(final String columnLabel) throws SQLException { try { return resultSet.getNCharacterStream(columnLabel); } catch (final SQLException e) { handleException(e); return null; } } @Override public NClob getNClob(final int columnIndex) throws SQLException { try { return resultSet.getNClob(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public NClob getNClob(final String columnLabel) throws SQLException { try { return resultSet.getNClob(columnLabel); } catch (final SQLException e) { handleException(e); return null; } } @Override public String getNString(final int columnIndex) throws SQLException { try { return resultSet.getNString(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public String getNString(final String columnLabel) throws SQLException { try { return resultSet.getNString(columnLabel); } catch (final SQLException e) { handleException(e); return null; } } @Override public Object getObject(final int columnIndex) throws SQLException { try { return resultSet.getObject(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public T getObject(final int columnIndex, final Class type) throws SQLException { try { return Jdbc41Bridge.getObject(resultSet, columnIndex, type); } catch (final SQLException e) { handleException(e); return null; } } @Override public Object getObject(final int i, final Map> map) throws SQLException { try { return resultSet.getObject(i, map); } catch (final SQLException e) { handleException(e); return null; } } @Override public Object getObject(final String columnName) throws SQLException { try { return resultSet.getObject(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public T getObject(final String columnLabel, final Class type) throws SQLException { try { return Jdbc41Bridge.getObject(resultSet, columnLabel, type); } catch (final SQLException e) { handleException(e); return null; } } @Override public Object getObject(final String colName, final Map> map) throws SQLException { try { return resultSet.getObject(colName, map); } catch (final SQLException e) { handleException(e); return null; } } @Override public Ref getRef(final int i) throws SQLException { try { return resultSet.getRef(i); } catch (final SQLException e) { handleException(e); return null; } } @Override public Ref getRef(final String colName) throws SQLException { try { return resultSet.getRef(colName); } catch (final SQLException e) { handleException(e); return null; } } @Override public int getRow() throws SQLException { try { return resultSet.getRow(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public RowId getRowId(final int columnIndex) throws SQLException { try { return resultSet.getRowId(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public RowId getRowId(final String columnLabel) throws SQLException { try { return resultSet.getRowId(columnLabel); } catch (final SQLException e) { handleException(e); return null; } } @Override public short getShort(final int columnIndex) throws SQLException { try { return resultSet.getShort(columnIndex); } catch (final SQLException e) { handleException(e); return 0; } } @Override public short getShort(final String columnName) throws SQLException { try { return resultSet.getShort(columnName); } catch (final SQLException e) { handleException(e); return 0; } } @Override public SQLXML getSQLXML(final int columnIndex) throws SQLException { try { return resultSet.getSQLXML(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public SQLXML getSQLXML(final String columnLabel) throws SQLException { try { return resultSet.getSQLXML(columnLabel); } catch (final SQLException e) { handleException(e); return null; } } @Override public Statement getStatement() throws SQLException { return statement; } @Override public String getString(final int columnIndex) throws SQLException { try { return resultSet.getString(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public String getString(final String columnName) throws SQLException { try { return resultSet.getString(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Time getTime(final int columnIndex) throws SQLException { try { return resultSet.getTime(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Time getTime(final int columnIndex, final Calendar cal) throws SQLException { try { return resultSet.getTime(columnIndex, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public Time getTime(final String columnName) throws SQLException { try { return resultSet.getTime(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Time getTime(final String columnName, final Calendar cal) throws SQLException { try { return resultSet.getTime(columnName, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public Timestamp getTimestamp(final int columnIndex) throws SQLException { try { return resultSet.getTimestamp(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public Timestamp getTimestamp(final int columnIndex, final Calendar cal) throws SQLException { try { return resultSet.getTimestamp(columnIndex, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public Timestamp getTimestamp(final String columnName) throws SQLException { try { return resultSet.getTimestamp(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public Timestamp getTimestamp(final String columnName, final Calendar cal) throws SQLException { try { return resultSet.getTimestamp(columnName, cal); } catch (final SQLException e) { handleException(e); return null; } } @Override public int getType() throws SQLException { try { return resultSet.getType(); } catch (final SQLException e) { handleException(e); return 0; } } /** @deprecated Use {@link #getCharacterStream(int)} */ @Deprecated @Override public InputStream getUnicodeStream(final int columnIndex) throws SQLException { try { return resultSet.getUnicodeStream(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } /** @deprecated Use {@link #getCharacterStream(String)} */ @Deprecated @Override public InputStream getUnicodeStream(final String columnName) throws SQLException { try { return resultSet.getUnicodeStream(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public java.net.URL getURL(final int columnIndex) throws SQLException { try { return resultSet.getURL(columnIndex); } catch (final SQLException e) { handleException(e); return null; } } @Override public java.net.URL getURL(final String columnName) throws SQLException { try { return resultSet.getURL(columnName); } catch (final SQLException e) { handleException(e); return null; } } @Override public SQLWarning getWarnings() throws SQLException { try { return resultSet.getWarnings(); } catch (final SQLException e) { handleException(e); return null; } } protected void handleException(final SQLException e) throws SQLException { if (statement instanceof DelegatingStatement) { ((DelegatingStatement) statement).handleException(e); } else if (connection instanceof DelegatingConnection) { ((DelegatingConnection) connection).handleException(e); } else { throw e; } } @Override public void insertRow() throws SQLException { try { resultSet.insertRow(); } catch (final SQLException e) { handleException(e); } } @Override public boolean isAfterLast() throws SQLException { try { return resultSet.isAfterLast(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isBeforeFirst() throws SQLException { try { return resultSet.isBeforeFirst(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isClosed() throws SQLException { try { return resultSet.isClosed(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isFirst() throws SQLException { try { return resultSet.isFirst(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isLast() throws SQLException { try { return resultSet.isLast(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isWrapperFor(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return true; } if (iface.isAssignableFrom(resultSet.getClass())) { return true; } return resultSet.isWrapperFor(iface); } @Override public boolean last() throws SQLException { try { return resultSet.last(); } catch (final SQLException e) { handleException(e); return false; } } @Override public void moveToCurrentRow() throws SQLException { try { resultSet.moveToCurrentRow(); } catch (final SQLException e) { handleException(e); } } @Override public void moveToInsertRow() throws SQLException { try { resultSet.moveToInsertRow(); } catch (final SQLException e) { handleException(e); } } @Override public boolean next() throws SQLException { try { return resultSet.next(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean previous() throws SQLException { try { return resultSet.previous(); } catch (final SQLException e) { handleException(e); return false; } } @Override public void refreshRow() throws SQLException { try { resultSet.refreshRow(); } catch (final SQLException e) { handleException(e); } } @Override public boolean relative(final int rows) throws SQLException { try { return resultSet.relative(rows); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean rowDeleted() throws SQLException { try { return resultSet.rowDeleted(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean rowInserted() throws SQLException { try { return resultSet.rowInserted(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean rowUpdated() throws SQLException { try { return resultSet.rowUpdated(); } catch (final SQLException e) { handleException(e); return false; } } @Override public void setFetchDirection(final int direction) throws SQLException { try { resultSet.setFetchDirection(direction); } catch (final SQLException e) { handleException(e); } } @Override public void setFetchSize(final int rows) throws SQLException { try { resultSet.setFetchSize(rows); } catch (final SQLException e) { handleException(e); } } @Override public synchronized String toString() { return super.toString() + "[resultSet=" + resultSet + ", statement=" + statement + ", connection=" + connection + "]"; } @Override public T unwrap(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return iface.cast(this); } if (iface.isAssignableFrom(resultSet.getClass())) { return iface.cast(resultSet); } return resultSet.unwrap(iface); } @Override public void updateArray(final int columnIndex, final Array x) throws SQLException { try { resultSet.updateArray(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateArray(final String columnName, final Array x) throws SQLException { try { resultSet.updateArray(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateAsciiStream(final int columnIndex, final InputStream inputStream) throws SQLException { try { resultSet.updateAsciiStream(columnIndex, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void updateAsciiStream(final int columnIndex, final InputStream x, final int length) throws SQLException { try { resultSet.updateAsciiStream(columnIndex, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateAsciiStream(final int columnIndex, final InputStream inputStream, final long length) throws SQLException { try { resultSet.updateAsciiStream(columnIndex, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateAsciiStream(final String columnLabel, final InputStream inputStream) throws SQLException { try { resultSet.updateAsciiStream(columnLabel, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void updateAsciiStream(final String columnName, final InputStream x, final int length) throws SQLException { try { resultSet.updateAsciiStream(columnName, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateAsciiStream(final String columnLabel, final InputStream inputStream, final long length) throws SQLException { try { resultSet.updateAsciiStream(columnLabel, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateBigDecimal(final int columnIndex, final BigDecimal x) throws SQLException { try { resultSet.updateBigDecimal(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateBigDecimal(final String columnName, final BigDecimal x) throws SQLException { try { resultSet.updateBigDecimal(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateBinaryStream(final int columnIndex, final InputStream inputStream) throws SQLException { try { resultSet.updateBinaryStream(columnIndex, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void updateBinaryStream(final int columnIndex, final InputStream x, final int length) throws SQLException { try { resultSet.updateBinaryStream(columnIndex, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateBinaryStream(final int columnIndex, final InputStream inputStream, final long length) throws SQLException { try { resultSet.updateBinaryStream(columnIndex, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateBinaryStream(final String columnLabel, final InputStream inputStream) throws SQLException { try { resultSet.updateBinaryStream(columnLabel, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void updateBinaryStream(final String columnName, final InputStream x, final int length) throws SQLException { try { resultSet.updateBinaryStream(columnName, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateBinaryStream(final String columnLabel, final InputStream inputStream, final long length) throws SQLException { try { resultSet.updateBinaryStream(columnLabel, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateBlob(final int columnIndex, final Blob x) throws SQLException { try { resultSet.updateBlob(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateBlob(final int columnIndex, final InputStream inputStream) throws SQLException { try { resultSet.updateBlob(columnIndex, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void updateBlob(final int columnIndex, final InputStream inputStream, final long length) throws SQLException { try { resultSet.updateBlob(columnIndex, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateBlob(final String columnName, final Blob x) throws SQLException { try { resultSet.updateBlob(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateBlob(final String columnLabel, final InputStream inputStream) throws SQLException { try { resultSet.updateBlob(columnLabel, inputStream); } catch (final SQLException e) { handleException(e); } } @Override public void updateBlob(final String columnLabel, final InputStream inputStream, final long length) throws SQLException { try { resultSet.updateBlob(columnLabel, inputStream, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateBoolean(final int columnIndex, final boolean x) throws SQLException { try { resultSet.updateBoolean(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateBoolean(final String columnName, final boolean x) throws SQLException { try { resultSet.updateBoolean(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateByte(final int columnIndex, final byte x) throws SQLException { try { resultSet.updateByte(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateByte(final String columnName, final byte x) throws SQLException { try { resultSet.updateByte(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateBytes(final int columnIndex, final byte[] x) throws SQLException { try { resultSet.updateBytes(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateBytes(final String columnName, final byte[] x) throws SQLException { try { resultSet.updateBytes(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateCharacterStream(final int columnIndex, final Reader reader) throws SQLException { try { resultSet.updateCharacterStream(columnIndex, reader); } catch (final SQLException e) { handleException(e); } } @Override public void updateCharacterStream(final int columnIndex, final Reader x, final int length) throws SQLException { try { resultSet.updateCharacterStream(columnIndex, x, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateCharacterStream(final int columnIndex, final Reader reader, final long length) throws SQLException { try { resultSet.updateCharacterStream(columnIndex, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateCharacterStream(final String columnLabel, final Reader reader) throws SQLException { try { resultSet.updateCharacterStream(columnLabel, reader); } catch (final SQLException e) { handleException(e); } } @Override public void updateCharacterStream(final String columnName, final Reader reader, final int length) throws SQLException { try { resultSet.updateCharacterStream(columnName, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException { try { resultSet.updateCharacterStream(columnLabel, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateClob(final int columnIndex, final Clob x) throws SQLException { try { resultSet.updateClob(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateClob(final int columnIndex, final Reader reader) throws SQLException { try { resultSet.updateClob(columnIndex, reader); } catch (final SQLException e) { handleException(e); } } @Override public void updateClob(final int columnIndex, final Reader reader, final long length) throws SQLException { try { resultSet.updateClob(columnIndex, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateClob(final String columnName, final Clob x) throws SQLException { try { resultSet.updateClob(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateClob(final String columnLabel, final Reader reader) throws SQLException { try { resultSet.updateClob(columnLabel, reader); } catch (final SQLException e) { handleException(e); } } @Override public void updateClob(final String columnLabel, final Reader reader, final long length) throws SQLException { try { resultSet.updateClob(columnLabel, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateDate(final int columnIndex, final Date x) throws SQLException { try { resultSet.updateDate(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateDate(final String columnName, final Date x) throws SQLException { try { resultSet.updateDate(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateDouble(final int columnIndex, final double x) throws SQLException { try { resultSet.updateDouble(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateDouble(final String columnName, final double x) throws SQLException { try { resultSet.updateDouble(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateFloat(final int columnIndex, final float x) throws SQLException { try { resultSet.updateFloat(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateFloat(final String columnName, final float x) throws SQLException { try { resultSet.updateFloat(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateInt(final int columnIndex, final int x) throws SQLException { try { resultSet.updateInt(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateInt(final String columnName, final int x) throws SQLException { try { resultSet.updateInt(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateLong(final int columnIndex, final long x) throws SQLException { try { resultSet.updateLong(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateLong(final String columnName, final long x) throws SQLException { try { resultSet.updateLong(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateNCharacterStream(final int columnIndex, final Reader reader) throws SQLException { try { resultSet.updateNCharacterStream(columnIndex, reader); } catch (final SQLException e) { handleException(e); } } @Override public void updateNCharacterStream(final int columnIndex, final Reader reader, final long length) throws SQLException { try { resultSet.updateNCharacterStream(columnIndex, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateNCharacterStream(final String columnLabel, final Reader reader) throws SQLException { try { resultSet.updateNCharacterStream(columnLabel, reader); } catch (final SQLException e) { handleException(e); } } @Override public void updateNCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException { try { resultSet.updateNCharacterStream(columnLabel, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateNClob(final int columnIndex, final NClob value) throws SQLException { try { resultSet.updateNClob(columnIndex, value); } catch (final SQLException e) { handleException(e); } } @Override public void updateNClob(final int columnIndex, final Reader reader) throws SQLException { try { resultSet.updateNClob(columnIndex, reader); } catch (final SQLException e) { handleException(e); } } @Override public void updateNClob(final int columnIndex, final Reader reader, final long length) throws SQLException { try { resultSet.updateNClob(columnIndex, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateNClob(final String columnLabel, final NClob value) throws SQLException { try { resultSet.updateNClob(columnLabel, value); } catch (final SQLException e) { handleException(e); } } @Override public void updateNClob(final String columnLabel, final Reader reader) throws SQLException { try { resultSet.updateNClob(columnLabel, reader); } catch (final SQLException e) { handleException(e); } } @Override public void updateNClob(final String columnLabel, final Reader reader, final long length) throws SQLException { try { resultSet.updateNClob(columnLabel, reader, length); } catch (final SQLException e) { handleException(e); } } @Override public void updateNString(final int columnIndex, final String value) throws SQLException { try { resultSet.updateNString(columnIndex, value); } catch (final SQLException e) { handleException(e); } } @Override public void updateNString(final String columnLabel, final String value) throws SQLException { try { resultSet.updateNString(columnLabel, value); } catch (final SQLException e) { handleException(e); } } @Override public void updateNull(final int columnIndex) throws SQLException { try { resultSet.updateNull(columnIndex); } catch (final SQLException e) { handleException(e); } } @Override public void updateNull(final String columnName) throws SQLException { try { resultSet.updateNull(columnName); } catch (final SQLException e) { handleException(e); } } @Override public void updateObject(final int columnIndex, final Object x) throws SQLException { try { resultSet.updateObject(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateObject(final int columnIndex, final Object x, final int scale) throws SQLException { try { resultSet.updateObject(columnIndex, x); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType) throws SQLException { try { resultSet.updateObject(columnIndex, x, targetSqlType); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { try { resultSet.updateObject(columnIndex, x, targetSqlType, scaleOrLength); } catch (final SQLException e) { handleException(e); } } @Override public void updateObject(final String columnName, final Object x) throws SQLException { try { resultSet.updateObject(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateObject(final String columnName, final Object x, final int scale) throws SQLException { try { resultSet.updateObject(columnName, x); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType) throws SQLException { try { resultSet.updateObject(columnLabel, x, targetSqlType); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { try { resultSet.updateObject(columnLabel, x, targetSqlType, scaleOrLength); } catch (final SQLException e) { handleException(e); } } @Override public void updateRef(final int columnIndex, final Ref x) throws SQLException { try { resultSet.updateRef(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateRef(final String columnName, final Ref x) throws SQLException { try { resultSet.updateRef(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateRow() throws SQLException { try { resultSet.updateRow(); } catch (final SQLException e) { handleException(e); } } @Override public void updateRowId(final int columnIndex, final RowId value) throws SQLException { try { resultSet.updateRowId(columnIndex, value); } catch (final SQLException e) { handleException(e); } } @Override public void updateRowId(final String columnLabel, final RowId value) throws SQLException { try { resultSet.updateRowId(columnLabel, value); } catch (final SQLException e) { handleException(e); } } @Override public void updateShort(final int columnIndex, final short x) throws SQLException { try { resultSet.updateShort(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateShort(final String columnName, final short x) throws SQLException { try { resultSet.updateShort(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateSQLXML(final int columnIndex, final SQLXML value) throws SQLException { try { resultSet.updateSQLXML(columnIndex, value); } catch (final SQLException e) { handleException(e); } } @Override public void updateSQLXML(final String columnLabel, final SQLXML value) throws SQLException { try { resultSet.updateSQLXML(columnLabel, value); } catch (final SQLException e) { handleException(e); } } @Override public void updateString(final int columnIndex, final String x) throws SQLException { try { resultSet.updateString(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateString(final String columnName, final String x) throws SQLException { try { resultSet.updateString(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateTime(final int columnIndex, final Time x) throws SQLException { try { resultSet.updateTime(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateTime(final String columnName, final Time x) throws SQLException { try { resultSet.updateTime(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateTimestamp(final int columnIndex, final Timestamp x) throws SQLException { try { resultSet.updateTimestamp(columnIndex, x); } catch (final SQLException e) { handleException(e); } } @Override public void updateTimestamp(final String columnName, final Timestamp x) throws SQLException { try { resultSet.updateTimestamp(columnName, x); } catch (final SQLException e) { handleException(e); } } @Override public boolean wasNull() throws SQLException { try { return resultSet.wasNull(); } catch (final SQLException e) { handleException(e); return false; } } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java000066400000000000000000000564421472045345700332470ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import java.util.Objects; /** * A base delegating implementation of {@link Statement}. *

* All of the methods from the {@link Statement} interface simply check to see that the {@link Statement} is active, and * call the corresponding method on the "delegate" provided in my constructor. *

* Extends AbandonedTrace to implement Statement tracking and logging of code which created the Statement. Tracking the * Statement ensures that the Connection which created it can close any open Statement's on Connection close. * * @since 2.0 */ public class DelegatingStatement extends AbandonedTrace implements Statement { /** My delegate. */ private Statement statement; /** The connection that created me. **/ private DelegatingConnection connection; private boolean closed; /** * Create a wrapper for the Statement which traces this Statement to the Connection which created it and the code * which created it. * * @param statement * the {@link Statement} to delegate all calls to. * @param connection * the {@link DelegatingConnection} that created this statement. */ public DelegatingStatement(final DelegatingConnection connection, final Statement statement) { super(connection); this.statement = statement; this.connection = connection; } /** * * @throws SQLException * thrown by the delegating statement. * @since 2.4.0 made public, was protected in 2.3.0. */ public void activate() throws SQLException { if (statement instanceof DelegatingStatement) { ((DelegatingStatement) statement).activate(); } } @Override public void addBatch(final String sql) throws SQLException { checkOpen(); try { statement.addBatch(sql); } catch (final SQLException e) { handleException(e); } } @Override public void cancel() throws SQLException { checkOpen(); try { statement.cancel(); } catch (final SQLException e) { handleException(e); } } protected void checkOpen() throws SQLException { if (isClosed()) { throw new SQLException(this.getClass().getName() + " with address: \"" + toString() + "\" is closed."); } } @Override public void clearBatch() throws SQLException { checkOpen(); try { statement.clearBatch(); } catch (final SQLException e) { handleException(e); } } @Override public void clearWarnings() throws SQLException { checkOpen(); try { statement.clearWarnings(); } catch (final SQLException e) { handleException(e); } } /** * Close this DelegatingStatement, and close any ResultSets that were not explicitly closed. */ @Override public void close() throws SQLException { if (isClosed()) { return; } final List thrownList = new ArrayList<>(); try { if (connection != null) { connection.removeTrace(this); connection = null; } // The JDBC spec requires that a statement close any open // ResultSet's when it is closed. // FIXME The PreparedStatement we're wrapping should handle this for us. // See bug 17301 for what could happen when ResultSets are closed twice. final List traceList = getTrace(); if (traceList != null) { traceList.forEach(trace -> trace.close(e -> { if (connection != null) { // Does not rethrow e. connection.handleExceptionNoThrow(e); } thrownList.add(e); })); clearTrace(); } Utils.close(statement, e -> { if (connection != null) { // Does not rethrow e. connection.handleExceptionNoThrow(e); } thrownList.add(e); }); } finally { closed = true; statement = null; if (!thrownList.isEmpty()) { throw new SQLExceptionList(thrownList); } } } @Override public void closeOnCompletion() throws SQLException { checkOpen(); try { Jdbc41Bridge.closeOnCompletion(statement); } catch (final SQLException e) { handleException(e); } } @Override public boolean execute(final String sql) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.execute(sql); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.execute(sql, autoGeneratedKeys); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean execute(final String sql, final int[] columnIndexes) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.execute(sql, columnIndexes); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean execute(final String sql, final String[] columnNames) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.execute(sql, columnNames); } catch (final SQLException e) { handleException(e); return false; } } @Override public int[] executeBatch() throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeBatch(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } /** * @since 2.5.0 */ @Override public long[] executeLargeBatch() throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeLargeBatch(); } catch (final SQLException e) { handleException(e); return null; } } /** * @since 2.5.0 */ @Override public long executeLargeUpdate(final String sql) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeLargeUpdate(sql); } catch (final SQLException e) { handleException(e); return 0; } } /** * @since 2.5.0 */ @Override public long executeLargeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeLargeUpdate(sql, autoGeneratedKeys); } catch (final SQLException e) { handleException(e); return 0; } } /** * @since 2.5.0 */ @Override public long executeLargeUpdate(final String sql, final int[] columnIndexes) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeLargeUpdate(sql, columnIndexes); } catch (final SQLException e) { handleException(e); return 0; } } /** * @since 2.5.0 */ @Override public long executeLargeUpdate(final String sql, final String[] columnNames) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeLargeUpdate(sql, columnNames); } catch (final SQLException e) { handleException(e); return 0; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public ResultSet executeQuery(final String sql) throws SQLException { checkOpen(); setLastUsedInParent(); try { return DelegatingResultSet.wrapResultSet(this, statement.executeQuery(sql)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public int executeUpdate(final String sql) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeUpdate(sql); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeUpdate(sql, autoGeneratedKeys); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeUpdate(sql, columnIndexes); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int executeUpdate(final String sql, final String[] columnNames) throws SQLException { checkOpen(); setLastUsedInParent(); try { return statement.executeUpdate(sql, columnNames); } catch (final SQLException e) { handleException(e); return 0; } } @Override protected void finalize() throws Throwable { // This is required because of statement pooling. The poolable // statements will always be strongly held by the statement pool. If the // delegating statements that wrap the poolable statement are not // strongly held they will be garbage collected but at that point the // poolable statements need to be returned to the pool else there will // be a leak of statements from the pool. Closing this statement will // close all the wrapped statements and return any poolable statements // to the pool. close(); super.finalize(); } @Override public Connection getConnection() throws SQLException { checkOpen(); return getConnectionInternal(); // return the delegating connection that created this } protected DelegatingConnection getConnectionInternal() { return connection; } /** * Returns my underlying {@link Statement}. * * @return my underlying {@link Statement}. * @see #getInnermostDelegate */ public Statement getDelegate() { return statement; } @Override public int getFetchDirection() throws SQLException { checkOpen(); try { return statement.getFetchDirection(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getFetchSize() throws SQLException { checkOpen(); try { return statement.getFetchSize(); } catch (final SQLException e) { handleException(e); return 0; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public ResultSet getGeneratedKeys() throws SQLException { checkOpen(); try { return DelegatingResultSet.wrapResultSet(this, statement.getGeneratedKeys()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } /** * If my underlying {@link Statement} is not a {@code DelegatingStatement}, returns it, otherwise recursively * invokes this method on my delegate. *

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

*

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

* * @return The innermost delegate, may return null. * @see #getDelegate */ @SuppressWarnings("resource") public Statement getInnermostDelegate() { Statement stmt = statement; while (stmt instanceof DelegatingStatement) { stmt = ((DelegatingStatement) stmt).getDelegate(); if (this == stmt) { return null; } } return stmt; } /** * @since 2.5.0 */ @Override public long getLargeMaxRows() throws SQLException { checkOpen(); try { return statement.getLargeMaxRows(); } catch (final SQLException e) { handleException(e); return 0; } } /** * @since 2.5.0 */ @Override public long getLargeUpdateCount() throws SQLException { checkOpen(); try { return statement.getLargeUpdateCount(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxFieldSize() throws SQLException { checkOpen(); try { return statement.getMaxFieldSize(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxRows() throws SQLException { checkOpen(); try { return statement.getMaxRows(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public boolean getMoreResults() throws SQLException { checkOpen(); try { return statement.getMoreResults(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean getMoreResults(final int current) throws SQLException { checkOpen(); try { return statement.getMoreResults(current); } catch (final SQLException e) { handleException(e); return false; } } @Override public int getQueryTimeout() throws SQLException { checkOpen(); try { return statement.getQueryTimeout(); } catch (final SQLException e) { handleException(e); return 0; } } @SuppressWarnings("resource") // Caller is responsible for closing the resource. @Override public ResultSet getResultSet() throws SQLException { checkOpen(); try { return DelegatingResultSet.wrapResultSet(this, statement.getResultSet()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public int getResultSetConcurrency() throws SQLException { checkOpen(); try { return statement.getResultSetConcurrency(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getResultSetHoldability() throws SQLException { checkOpen(); try { return statement.getResultSetHoldability(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getResultSetType() throws SQLException { checkOpen(); try { return statement.getResultSetType(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getUpdateCount() throws SQLException { checkOpen(); try { return statement.getUpdateCount(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public SQLWarning getWarnings() throws SQLException { checkOpen(); try { return statement.getWarnings(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } protected void handleException(final SQLException e) throws SQLException { if (connection == null) { throw e; } connection.handleException(e); } /* * Note: This method was protected prior to JDBC 4. */ @Override public boolean isClosed() throws SQLException { return closed; } protected boolean isClosedInternal() { return closed; } @Override public boolean isCloseOnCompletion() throws SQLException { checkOpen(); try { return Jdbc41Bridge.isCloseOnCompletion(statement); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isPoolable() throws SQLException { checkOpen(); try { return statement.isPoolable(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isWrapperFor(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return true; } if (iface.isAssignableFrom(statement.getClass())) { return true; } return statement.isWrapperFor(iface); } /** * * @throws SQLException * thrown by the delegating statement. * @since 2.4.0 made public, was protected in 2.3.0. */ public void passivate() throws SQLException { if (statement instanceof DelegatingStatement) { ((DelegatingStatement) statement).passivate(); } } protected void setClosedInternal(final boolean closed) { this.closed = closed; } @Override public void setCursorName(final String name) throws SQLException { checkOpen(); try { statement.setCursorName(name); } catch (final SQLException e) { handleException(e); } } /** * Sets my delegate. * * @param statement * my delegate. */ public void setDelegate(final Statement statement) { this.statement = statement; } @Override public void setEscapeProcessing(final boolean enable) throws SQLException { checkOpen(); try { statement.setEscapeProcessing(enable); } catch (final SQLException e) { handleException(e); } } @Override public void setFetchDirection(final int direction) throws SQLException { checkOpen(); try { statement.setFetchDirection(direction); } catch (final SQLException e) { handleException(e); } } @Override public void setFetchSize(final int rows) throws SQLException { checkOpen(); try { statement.setFetchSize(rows); } catch (final SQLException e) { handleException(e); } } /** * @since 2.5.0 */ @Override public void setLargeMaxRows(final long max) throws SQLException { checkOpen(); try { statement.setLargeMaxRows(max); } catch (final SQLException e) { handleException(e); } } private void setLastUsedInParent() { if (connection != null) { connection.setLastUsed(); } } @Override public void setMaxFieldSize(final int max) throws SQLException { checkOpen(); try { statement.setMaxFieldSize(max); } catch (final SQLException e) { handleException(e); } } @Override public void setMaxRows(final int max) throws SQLException { checkOpen(); try { statement.setMaxRows(max); } catch (final SQLException e) { handleException(e); } } @Override public void setPoolable(final boolean poolable) throws SQLException { checkOpen(); try { statement.setPoolable(poolable); } catch (final SQLException e) { handleException(e); } } @Override public void setQueryTimeout(final int seconds) throws SQLException { checkOpen(); try { statement.setQueryTimeout(seconds); } catch (final SQLException e) { handleException(e); } } /** * Returns a String representation of this object. * * @return String */ @Override public synchronized String toString() { return Objects.toString(statement, "NULL"); } @Override public T unwrap(final Class iface) throws SQLException { if (iface.isAssignableFrom(getClass())) { return iface.cast(this); } if (iface.isAssignableFrom(statement.getClass())) { return iface.cast(statement); } return statement.unwrap(iface); } } DriverConnectionFactory.java000066400000000000000000000050231472045345700340300ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; import java.util.Properties; /** * A {@link Driver}-based implementation of {@link ConnectionFactory}. * * @since 2.0 */ public class DriverConnectionFactory implements ConnectionFactory { private final String connectionString; private final Driver driver; private final Properties properties; /** * Constructs a connection factory for a given Driver. * * @param driver The Driver. * @param connectString The connection string. * @param properties The connection properties. */ public DriverConnectionFactory(final Driver driver, final String connectString, final Properties properties) { this.driver = driver; this.connectionString = connectString; this.properties = properties; } @Override public Connection createConnection() throws SQLException { return driver.connect(connectionString, properties); } /** * Gets the connection String. * * @return The connection String. * @since 2.6.0 */ public String getConnectionString() { return connectionString; } /** * Gets the JDBC Driver. * * @return The JDBC Driver. * @since 2.6.0 */ public Driver getDriver() { return driver; } /** * Gets the properties. * * @return The properties. * @since 2.6.0 */ public Properties getProperties() { return properties; } @Override public String toString() { return this.getClass().getName() + " [" + driver + ";" + connectionString + ";" + Utils.cloneWithoutCredentials(properties) + "]"; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/DriverFactory.java000066400000000000000000000066671472045345700321060ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; /* * Creates {@link Driver} instances. * * @since 2.7.0 */ final class DriverFactory { static Driver createDriver(final BasicDataSource basicDataSource) throws SQLException { // Load the JDBC driver class Driver driverToUse = basicDataSource.getDriver(); final String driverClassName = basicDataSource.getDriverClassName(); final ClassLoader driverClassLoader = basicDataSource.getDriverClassLoader(); final String url = basicDataSource.getUrl(); if (driverToUse == null) { Class driverFromCCL = null; if (driverClassName != null) { try { try { if (driverClassLoader == null) { driverFromCCL = Class.forName(driverClassName); } else { driverFromCCL = Class.forName(driverClassName, true, driverClassLoader); } } catch (final ClassNotFoundException cnfe) { driverFromCCL = Thread.currentThread().getContextClassLoader().loadClass(driverClassName); } } catch (final Exception t) { final String message = "Cannot load JDBC driver class '" + driverClassName + "'"; basicDataSource.log(message, t); throw new SQLException(message, t); } } try { if (driverFromCCL == null) { driverToUse = DriverManager.getDriver(url); } else { // Usage of DriverManager is not possible, as it does not // respect the ContextClassLoader // N.B. This cast may cause ClassCastException which is // handled below driverToUse = (Driver) driverFromCCL.getConstructor().newInstance(); if (!driverToUse.acceptsURL(url)) { throw new SQLException("No suitable driver", "08001"); } } } catch (final Exception t) { final String message = "Cannot create JDBC driver of class '" + (driverClassName != null ? driverClassName : "") + "' for connect URL '" + url + "'"; basicDataSource.log(message, t); throw new SQLException(message, t); } } return driverToUse; } } DriverManagerConnectionFactory.java000066400000000000000000000117451472045345700353330ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * A {@link DriverManager}-based implementation of {@link ConnectionFactory}. * * @since 2.0 */ public class DriverManagerConnectionFactory implements ConnectionFactory { static { // Related to DBCP-212 // Driver manager does not sync loading of drivers that use the service // provider interface. This will cause issues is multi-threaded // environments. This hack makes sure the drivers are loaded before // DBCP tries to use them. DriverManager.getDrivers(); } private final String connectionUri; private final String userName; private final char[] userPassword; private final Properties properties; /** * Constructor for DriverManagerConnectionFactory. * * @param connectionUri * a database connection string of the form {@code jdbc:subprotocol:subname} * @since 2.2 */ public DriverManagerConnectionFactory(final String connectionUri) { this.connectionUri = connectionUri; this.properties = new Properties(); this.userName = null; this.userPassword = null; } /** * Constructor for DriverManagerConnectionFactory. * * @param connectionUri * a database connection string of the form {@code jdbc:subprotocol:subname} * @param properties * a list of arbitrary string tag/value pairs as connection arguments; normally at least a "user" and * "password" property should be included. */ public DriverManagerConnectionFactory(final String connectionUri, final Properties properties) { this.connectionUri = connectionUri; this.properties = properties; this.userName = null; this.userPassword = null; } /** * Constructor for DriverManagerConnectionFactory. * * @param connectionUri * a database connection string of the form {@code jdbc:subprotocol:subname} * @param userName * the database user * @param userPassword * the user's password */ public DriverManagerConnectionFactory(final String connectionUri, final String userName, final char[] userPassword) { this.connectionUri = connectionUri; this.userName = userName; this.userPassword = Utils.clone(userPassword); this.properties = null; } /** * Constructor for DriverManagerConnectionFactory. * * @param connectionUri * a database connection string of the form {@code jdbc:subprotocol:subname} * @param userName * the database user * @param userPassword * the user's password */ public DriverManagerConnectionFactory(final String connectionUri, final String userName, final String userPassword) { this.connectionUri = connectionUri; this.userName = userName; this.userPassword = Utils.toCharArray(userPassword); this.properties = null; } @Override public Connection createConnection() throws SQLException { if (null == properties) { if (userName == null && userPassword == null) { return DriverManager.getConnection(connectionUri); } return DriverManager.getConnection(connectionUri, userName, Utils.toString(userPassword)); } return DriverManager.getConnection(connectionUri, properties); } /** * @return The connection URI. * @since 2.6.0 */ public String getConnectionUri() { return connectionUri; } /** * @return The Properties. * @since 2.6.0 */ public Properties getProperties() { return properties; } /** * @return The user name. * @since 2.6.0 */ public String getUserName() { return userName; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/Jdbc41Bridge.java000066400000000000000000000462421472045345700314400ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.Date; import java.sql.Ref; import java.sql.ResultSet; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLXML; import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.util.concurrent.Executor; import java.util.logging.Logger; import javax.sql.CommonDataSource; /** * Defines bridge methods to JDBC 4.1 (Java 7 or above) methods to allow call sites to operate safely (without * {@link AbstractMethodError}) when using a JDBC driver written for JDBC 4.0 (Java 6 or above). *

* There should be no need to this kind of code for JDBC 4.2 in Java 8 due to JDBC's use of default methods. *

*

* This should probably be moved or at least copied in some form to Apache Commons DbUtils. *

* * @since 2.6.0 */ public class Jdbc41Bridge { /** * Delegates to {@link Connection#abort(Executor)} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Connection#abort(Executor)}, then call {@link Connection#close()}. *

* * @param connection * the receiver * @param executor * See {@link Connection#abort(Executor)}. * @throws SQLException * See {@link Connection#abort(Executor)}. * @see Connection#abort(Executor) */ public static void abort(final Connection connection, final Executor executor) throws SQLException { try { connection.abort(executor); } catch (final AbstractMethodError e) { connection.close(); } } /** * Delegates to {@link Statement#closeOnCompletion()} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Statement#closeOnCompletion()}, then just check that the connection * is closed to then throw an SQLException. *

* * @param statement * See {@link Statement#closeOnCompletion()} * @throws SQLException * See {@link Statement#closeOnCompletion()} * @see Statement#closeOnCompletion() */ public static void closeOnCompletion(final Statement statement) throws SQLException { try { statement.closeOnCompletion(); } catch (final AbstractMethodError e) { if (statement.isClosed()) { throw new SQLException("Statement closed"); } } } /** * Delegates to {@link DatabaseMetaData#generatedKeyAlwaysReturned()} without throwing a * {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link DatabaseMetaData#generatedKeyAlwaysReturned()}, then return false. *

* * @param databaseMetaData * See {@link DatabaseMetaData#generatedKeyAlwaysReturned()} * @return See {@link DatabaseMetaData#generatedKeyAlwaysReturned()} * @throws SQLException * See {@link DatabaseMetaData#generatedKeyAlwaysReturned()} * @see DatabaseMetaData#generatedKeyAlwaysReturned() */ public static boolean generatedKeyAlwaysReturned(final DatabaseMetaData databaseMetaData) throws SQLException { try { return databaseMetaData.generatedKeyAlwaysReturned(); } catch (final AbstractMethodError e) { // do nothing return false; } } /** * Delegates to {@link Connection#getNetworkTimeout()} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Connection#getNetworkTimeout()}, then return 0. *

* * @param connection * the receiver * @return See {@link Connection#getNetworkTimeout()} * @throws SQLException * See {@link Connection#getNetworkTimeout()} * @see Connection#getNetworkTimeout() */ public static int getNetworkTimeout(final Connection connection) throws SQLException { try { return connection.getNetworkTimeout(); } catch (final AbstractMethodError e) { return 0; } } /** * Delegates to {@link ResultSet#getObject(int, Class)} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link ResultSet#getObject(int, Class)}, then return 0. *

* * @param * See {@link ResultSet#getObject(int, Class)} * @param resultSet * See {@link ResultSet#getObject(int, Class)} * @param columnIndex * See {@link ResultSet#getObject(int, Class)} * @param type * See {@link ResultSet#getObject(int, Class)} * @return See {@link ResultSet#getObject(int, Class)} * @throws SQLException * See {@link ResultSet#getObject(int, Class)} * @see ResultSet#getObject(int, Class) */ @SuppressWarnings("unchecked") public static T getObject(final ResultSet resultSet, final int columnIndex, final Class type) throws SQLException { try { return resultSet.getObject(columnIndex, type); } catch (final AbstractMethodError e) { if (type == String.class) { return (T) resultSet.getString(columnIndex); } // Numbers if (type == Integer.class) { return (T) Integer.valueOf(resultSet.getInt(columnIndex)); } if (type == Long.class) { return (T) Long.valueOf(resultSet.getLong(columnIndex)); } if (type == Double.class) { return (T) Double.valueOf(resultSet.getDouble(columnIndex)); } if (type == Float.class) { return (T) Float.valueOf(resultSet.getFloat(columnIndex)); } if (type == Short.class) { return (T) Short.valueOf(resultSet.getShort(columnIndex)); } if (type == BigDecimal.class) { return (T) resultSet.getBigDecimal(columnIndex); } if (type == Byte.class) { return (T) Byte.valueOf(resultSet.getByte(columnIndex)); } // Dates if (type == Date.class) { return (T) resultSet.getDate(columnIndex); } if (type == Time.class) { return (T) resultSet.getTime(columnIndex); } if (type == Timestamp.class) { return (T) resultSet.getTimestamp(columnIndex); } // Streams if (type == InputStream.class) { return (T) resultSet.getBinaryStream(columnIndex); } if (type == Reader.class) { return (T) resultSet.getCharacterStream(columnIndex); } // Other if (type == Object.class) { return (T) resultSet.getObject(columnIndex); } if (type == Boolean.class) { return (T) Boolean.valueOf(resultSet.getBoolean(columnIndex)); } if (type == Array.class) { return (T) resultSet.getArray(columnIndex); } if (type == Blob.class) { return (T) resultSet.getBlob(columnIndex); } if (type == Clob.class) { return (T) resultSet.getClob(columnIndex); } if (type == Ref.class) { return (T) resultSet.getRef(columnIndex); } if (type == RowId.class) { return (T) resultSet.getRowId(columnIndex); } if (type == SQLXML.class) { return (T) resultSet.getSQLXML(columnIndex); } if (type == URL.class) { return (T) resultSet.getURL(columnIndex); } throw new SQLFeatureNotSupportedException( String.format("resultSet=%s, columnIndex=%,d, type=%s", resultSet, columnIndex, type)); } } /** * Delegates to {@link ResultSet#getObject(String, Class)} without throwing an {@link AbstractMethodError}. * * @param * See {@link ResultSet#getObject(String, Class)} * @param resultSet * See {@link ResultSet#getObject(String, Class)} * @param columnLabel * See {@link ResultSet#getObject(String, Class)} * @param type * See {@link ResultSet#getObject(String, Class)} * @return See {@link ResultSet#getObject(String, Class)} * @throws SQLException * See {@link ResultSet#getObject(String, Class)} * @see ResultSet#getObject(int, Class) */ @SuppressWarnings("unchecked") public static T getObject(final ResultSet resultSet, final String columnLabel, final Class type) throws SQLException { try { return resultSet.getObject(columnLabel, type); } catch (final AbstractMethodError e) { // Numbers if (type == Integer.class) { return (T) Integer.valueOf(resultSet.getInt(columnLabel)); } if (type == Long.class) { return (T) Long.valueOf(resultSet.getLong(columnLabel)); } if (type == Double.class) { return (T) Double.valueOf(resultSet.getDouble(columnLabel)); } if (type == Float.class) { return (T) Float.valueOf(resultSet.getFloat(columnLabel)); } if (type == Short.class) { return (T) Short.valueOf(resultSet.getShort(columnLabel)); } if (type == BigDecimal.class) { return (T) resultSet.getBigDecimal(columnLabel); } if (type == Byte.class) { return (T) Byte.valueOf(resultSet.getByte(columnLabel)); } // Dates if (type == Date.class) { return (T) resultSet.getDate(columnLabel); } if (type == Time.class) { return (T) resultSet.getTime(columnLabel); } if (type == Timestamp.class) { return (T) resultSet.getTimestamp(columnLabel); } // Streams if (type == InputStream.class) { return (T) resultSet.getBinaryStream(columnLabel); } if (type == Reader.class) { return (T) resultSet.getCharacterStream(columnLabel); } // Other if (type == Object.class) { return (T) resultSet.getObject(columnLabel); } if (type == Boolean.class) { return (T) Boolean.valueOf(resultSet.getBoolean(columnLabel)); } if (type == Array.class) { return (T) resultSet.getArray(columnLabel); } if (type == Blob.class) { return (T) resultSet.getBlob(columnLabel); } if (type == Clob.class) { return (T) resultSet.getClob(columnLabel); } if (type == Ref.class) { return (T) resultSet.getRef(columnLabel); } if (type == RowId.class) { return (T) resultSet.getRowId(columnLabel); } if (type == SQLXML.class) { return (T) resultSet.getSQLXML(columnLabel); } if (type == URL.class) { return (T) resultSet.getURL(columnLabel); } throw new SQLFeatureNotSupportedException( String.format("resultSet=%s, columnLabel=%s, type=%s", resultSet, columnLabel, type)); } } /** * Delegates to {@link CommonDataSource#getParentLogger()} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link CommonDataSource#getParentLogger()}, then return null. *

* * @param commonDataSource * See {@link CommonDataSource#getParentLogger()} * @return See {@link CommonDataSource#getParentLogger()} * @throws SQLFeatureNotSupportedException * See {@link CommonDataSource#getParentLogger()} */ public static Logger getParentLogger(final CommonDataSource commonDataSource) throws SQLFeatureNotSupportedException { try { return commonDataSource.getParentLogger(); } catch (final AbstractMethodError e) { throw new SQLFeatureNotSupportedException("javax.sql.CommonDataSource#getParentLogger()"); } } /** * Delegates to {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} without throwing a * {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}, * then return null. *

* * @param databaseMetaData * the receiver * @param catalog * See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} * @param schemaPattern * See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} * @param tableNamePattern * See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} * @param columnNamePattern * See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} * @return See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} * @throws SQLException * See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} * @see DatabaseMetaData#getPseudoColumns(String, String, String, String) */ public static ResultSet getPseudoColumns(final DatabaseMetaData databaseMetaData, final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { try { return databaseMetaData.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); } catch (final AbstractMethodError e) { // do nothing return null; } } /** * Delegates to {@link Connection#getSchema()} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Connection#getSchema()}, then return null. *

* * @param connection * the receiver * @return null for a JDBC 4 driver or a value per {@link Connection#getSchema()}. * @throws SQLException * See {@link Connection#getSchema()}. * @see Connection#getSchema() */ public static String getSchema(final Connection connection) throws SQLException { try { return connection.getSchema(); } catch (final AbstractMethodError e) { // do nothing return null; } } /** * Delegates to {@link Statement#isCloseOnCompletion()} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Statement#isCloseOnCompletion()}, then just check that the * connection is closed to then throw an SQLException. *

* * @param statement * See {@link Statement#isCloseOnCompletion()} * @return See {@link Statement#isCloseOnCompletion()} * @throws SQLException * See {@link Statement#isCloseOnCompletion()} * @see Statement#closeOnCompletion() */ public static boolean isCloseOnCompletion(final Statement statement) throws SQLException { try { return statement.isCloseOnCompletion(); } catch (final AbstractMethodError e) { if (statement.isClosed()) { throw new SQLException("Statement closed"); } return false; } } /** * Delegates to {@link Connection#setNetworkTimeout(Executor, int)} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Connection#setNetworkTimeout(Executor, int)}, then do nothing. *

* * @param connection * the receiver * @param executor * See {@link Connection#setNetworkTimeout(Executor, int)} * @param milliseconds * {@link Connection#setNetworkTimeout(Executor, int)} * @throws SQLException * {@link Connection#setNetworkTimeout(Executor, int)} * @see Connection#setNetworkTimeout(Executor, int) */ public static void setNetworkTimeout(final Connection connection, final Executor executor, final int milliseconds) throws SQLException { try { connection.setNetworkTimeout(executor, milliseconds); } catch (final AbstractMethodError ignored) { // do nothing } } /** * Delegates to {@link Connection#setSchema(String)} without throwing an {@link AbstractMethodError}. *

* If the JDBC driver does not implement {@link Connection#setSchema(String)}, then do nothing. *

* * @param connection * the receiver * @param schema * See {@link Connection#setSchema(String)}. * @throws SQLException * See {@link Connection#setSchema(String)}. * @see Connection#setSchema(String) */ public static void setSchema(final Connection connection, final String schema) throws SQLException { try { connection.setSchema(schema); } catch (final AbstractMethodError ignored) { // do nothing } } } LifetimeExceededException.java000066400000000000000000000026761472045345700343040ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.SQLException; /** * Exception thrown when a connection's maximum lifetime has been exceeded. * * @since 2.1 */ final class LifetimeExceededException extends SQLException { private static final long serialVersionUID = -3783783104516492659L; /** * Constructs a new instance. */ public LifetimeExceededException() { } /** * Constructs a new instance with the given message. * * @param reason a description of the exception */ public LifetimeExceededException(final String reason) { super(reason); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/ListException.java000066400000000000000000000035071472045345700321030ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.util.List; /** * An exception wrapping a list of exceptions. * * @since 2.4.0 */ public class ListException extends Exception { private static final long serialVersionUID = 1L; private final List exceptionList; /** * Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently * be initialized by a call to {@link #initCause}. * * @param message * the detail message. The detail message is saved for later retrieval by the {@link #getMessage()} * method. * @param exceptionList * a list of exceptions. */ public ListException(final String message, final List exceptionList) { super(message); this.exceptionList = exceptionList; } /** * Gets the list of exceptions. * * @return the list of exceptions. */ public List getExceptionList() { return exceptionList; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/ObjectNameWrapper.java000066400000000000000000000065351472045345700326650ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.lang.management.ManagementFactory; import java.util.Objects; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Internal wrapper class that allows JMX to be a noop if absent or disabled. * * @since 2.2.1 */ final class ObjectNameWrapper { private static final Log log = LogFactory.getLog(ObjectNameWrapper.class); private static final MBeanServer MBEAN_SERVER = getPlatformMBeanServer(); private static MBeanServer getPlatformMBeanServer() { try { return ManagementFactory.getPlatformMBeanServer(); } catch (final LinkageError | Exception e) { // ignore - JMX not available log.debug("Failed to get platform MBeanServer", e); return null; } } public static ObjectName unwrap(final ObjectNameWrapper wrapper) { return wrapper == null ? null : wrapper.unwrap(); } public static ObjectNameWrapper wrap(final ObjectName objectName) { return new ObjectNameWrapper(objectName); } public static ObjectNameWrapper wrap(final String name) throws MalformedObjectNameException { return wrap(new ObjectName(name)); } private final ObjectName objectName; public ObjectNameWrapper(final ObjectName objectName) { this.objectName = objectName; } public void registerMBean(final Object object) { if (MBEAN_SERVER == null || objectName == null) { return; } try { MBEAN_SERVER.registerMBean(object, objectName); } catch (final LinkageError | Exception e) { log.warn("Failed to complete JMX registration for " + objectName, e); } } /** * @since 2.7.0 */ @Override public String toString() { return Objects.toString(objectName); } public void unregisterMBean() { if (MBEAN_SERVER == null || objectName == null) { return; } if (MBEAN_SERVER.isRegistered(objectName)) { try { MBEAN_SERVER.unregisterMBean(objectName); } catch (final LinkageError | Exception e) { log.warn("Failed to complete JMX unregistration for " + objectName, e); } } } public ObjectName unwrap() { return objectName; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/PStmtKey.java000066400000000000000000000704071472045345700310340ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.Objects; import java.util.function.Function; import org.apache.commons.dbcp2.PoolingConnection.StatementType; /** * A key uniquely identifying {@link java.sql.PreparedStatement PreparedStatement}s. * * @since 2.0 */ public class PStmtKey { /** * Interface for Prepared or Callable Statement. */ @FunctionalInterface private interface StatementBuilder { Statement createStatement(Connection connection, PStmtKey key) throws SQLException; } private static final StatementBuilder CallConcurrency = (c, k) -> c.prepareCall(k.sql, k.resultSetType, k.resultSetConcurrency); private static final StatementBuilder CallHoldability = (c, k) -> c.prepareCall(k.sql, k.resultSetType, k.resultSetConcurrency, k.resultSetHoldability); private static final StatementBuilder CallSQL = (c, k) -> c.prepareCall(k.sql); private static final StatementBuilder StatementAutoGeneratedKeys = (c, k) -> c.prepareStatement(k.sql, k.autoGeneratedKeys); private static final StatementBuilder StatementColumnIndexes = (c, k) -> c.prepareStatement(k.sql, k.columnIndexes); private static final StatementBuilder StatementColumnNames = (c, k) -> c.prepareStatement(k.sql, k.columnNames); private static final StatementBuilder StatementConcurrency = (c, k) -> c.prepareStatement(k.sql, k.resultSetType, k.resultSetConcurrency); private static final StatementBuilder StatementHoldability = (c, k) -> c.prepareStatement(k.sql, k.resultSetType, k.resultSetConcurrency, k.resultSetHoldability); private static final StatementBuilder StatementSQL = (c, k) -> c.prepareStatement(k.sql); private static StatementBuilder match(final StatementType statementType, final StatementBuilder prep, final StatementBuilder call) { switch (Objects.requireNonNull(statementType, "statementType")) { case PREPARED_STATEMENT: return prep; case CALLABLE_STATEMENT: return call; default: throw new IllegalArgumentException(statementType.toString()); } } /** * SQL defining Prepared or Callable Statement */ private final String sql; /** * Result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or * {@code ResultSet.TYPE_SCROLL_SENSITIVE}. */ private final Integer resultSetType; /** * Result set concurrency. A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. */ private final Integer resultSetConcurrency; /** * Result set holdability. One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. */ private final Integer resultSetHoldability; /** * Database catalog. */ private final String catalog; /** * Database schema. */ private final String schema; /** * A flag indicating whether auto-generated keys should be returned; one of {@code Statement.RETURN_GENERATED_KEYS} or * {@code Statement.NO_GENERATED_KEYS}. */ private final Integer autoGeneratedKeys; /** * An array of column indexes indicating the columns that should be returned from the inserted row or rows. */ private final int[] columnIndexes; /** * An array of column names indicating the columns that should be returned from the inserted row or rows. */ private final String[] columnNames; /** * Statement builder. */ private final transient StatementBuilder statementBuilder; /** * Statement type, prepared or callable. */ private final StatementType statementType; /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @deprecated Use {@link #PStmtKey(String, String, String)}. */ @Deprecated public PStmtKey(final String sql) { this(sql, null, StatementType.PREPARED_STATEMENT); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @deprecated Use {@link #PStmtKey(String, String, String, int, int)}. */ @Deprecated public PStmtKey(final String sql, final int resultSetType, final int resultSetConcurrency) { this(sql, null, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @deprecated Use {@link #PStmtKey(String, String, String)}. */ @Deprecated public PStmtKey(final String sql, final String catalog) { this(sql, catalog, StatementType.PREPARED_STATEMENT); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. * @deprecated Use {@link #PStmtKey(String, String, String, int)}. */ @Deprecated public PStmtKey(final String sql, final String catalog, final int autoGeneratedKeys) { this(sql, catalog, StatementType.PREPARED_STATEMENT, autoGeneratedKeys); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @deprecated Use {@link #PStmtKey(String, String, String, int, int)}. */ @Deprecated public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency) { this(sql, catalog, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE} * @param resultSetHoldability One of the following {@code ResultSet} constants: * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int)}. */ @Deprecated public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { this(sql, catalog, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE} * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @param resultSetHoldability One of the following {@code ResultSet} constants: * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * @param statementType The SQL statement type, prepared or callable. * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int, PoolingConnection.StatementType)} */ @Deprecated public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final StatementType statementType) { this(sql, catalog, null, resultSetType, resultSetConcurrency, resultSetHoldability, null, null, null, statementType, k -> match(statementType, StatementHoldability, CallHoldability)); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @param statementType The SQL statement type, prepared or callable. * @deprecated Use {@link #PStmtKey(String, String, String, int, int, PoolingConnection.StatementType)}. */ @Deprecated public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, final StatementType statementType) { this(sql, catalog, null, resultSetType, resultSetConcurrency, null, null, null, null, statementType, k -> match(statementType, StatementConcurrency, CallConcurrency)); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param columnIndexes An array of column indexes indicating the columns that should be returned from the inserted row * or rows. * @deprecated Use {@link #PStmtKey(String, String, String, int[])}. */ @Deprecated public PStmtKey(final String sql, final String catalog, final int[] columnIndexes) { this(sql, catalog, null, null, null, null, null, columnIndexes, null, StatementType.PREPARED_STATEMENT, StatementColumnIndexes); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param statementType The SQL statement type, prepared or callable. * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType)}. */ @Deprecated public PStmtKey(final String sql, final String catalog, final StatementType statementType) { this(sql, catalog, null, null, null, null, null, null, null, statementType, k -> match(statementType, StatementSQL, CallSQL)); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param statementType The SQL statement type, prepared or callable. * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType, Integer)} */ @Deprecated public PStmtKey(final String sql, final String catalog, final StatementType statementType, final Integer autoGeneratedKeys) { this(sql, catalog, null, null, null, null, autoGeneratedKeys, null, null, statementType, k -> match(statementType, StatementAutoGeneratedKeys, CallSQL)); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema) { this(sql, catalog, schema, StatementType.PREPARED_STATEMENT); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final int autoGeneratedKeys) { this(sql, catalog, schema, StatementType.PREPARED_STATEMENT, autoGeneratedKeys); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. */ public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency) { this(sql, catalog, schema, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE} * @param resultSetHoldability One of the following {@code ResultSet} constants: * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { this(sql, catalog, schema, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema. * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE} * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @param resultSetHoldability One of the following {@code ResultSet} constants: * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * @param statementType The SQL statement type, prepared or callable. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final StatementType statementType) { this(sql, catalog, schema, resultSetType, resultSetConcurrency, resultSetHoldability, null, null, null, statementType, k -> match(statementType, StatementHoldability, CallHoldability)); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema. * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @param statementType The SQL statement type, prepared or callable. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, final StatementType statementType) { this(sql, catalog, schema, resultSetType, resultSetConcurrency, null, null, null, null, statementType, k -> match(statementType, StatementConcurrency, CallConcurrency)); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema. * @param columnIndexes An array of column indexes indicating the columns that should be returned from the inserted row * or rows. */ public PStmtKey(final String sql, final String catalog, final String schema, final int[] columnIndexes) { this(sql, catalog, schema, null, null, null, null, columnIndexes, null, StatementType.PREPARED_STATEMENT, StatementColumnIndexes); } private PStmtKey(final String sql, final String catalog, final String schema, final Integer resultSetType, final Integer resultSetConcurrency, final Integer resultSetHoldability, final Integer autoGeneratedKeys, final int[] columnIndexes, final String[] columnNames, final StatementType statementType, final Function statementBuilder) { this.sql = Objects.requireNonNull(sql, "sql").trim(); this.catalog = catalog; this.schema = schema; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; this.resultSetHoldability = resultSetHoldability; this.autoGeneratedKeys = autoGeneratedKeys; this.columnIndexes = clone(columnIndexes); this.columnNames = clone(columnNames); this.statementBuilder = Objects.requireNonNull(Objects.requireNonNull(statementBuilder, "statementBuilder").apply(this), "statementBuilder"); this.statementType = statementType; } // Root constructor. private PStmtKey(final String sql, final String catalog, final String schema, final Integer resultSetType, final Integer resultSetConcurrency, final Integer resultSetHoldability, final Integer autoGeneratedKeys, final int[] columnIndexes, final String[] columnNames, final StatementType statementType, final StatementBuilder statementBuilder) { this.sql = sql; this.catalog = catalog; this.schema = schema; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; this.resultSetHoldability = resultSetHoldability; this.autoGeneratedKeys = autoGeneratedKeys; this.columnIndexes = clone(columnIndexes); this.columnNames = clone(columnNames); this.statementBuilder = Objects.requireNonNull(statementBuilder, "statementBuilder"); this.statementType = statementType; } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema. * @param statementType The SQL statement type, prepared or callable. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType) { this(sql, catalog, schema, null, null, null, null, null, null, statementType, k -> match(statementType, StatementSQL, CallSQL)); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema. * @param statementType The SQL statement type, prepared or callable. * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType, final Integer autoGeneratedKeys) { this(sql, catalog, schema, null, null, null, autoGeneratedKeys, null, null, statementType, k -> match(statementType, StatementAutoGeneratedKeys, CallSQL)); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema. * @param columnNames An array of column names indicating the columns that should be returned from the inserted row or * rows. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final String[] columnNames) { this(sql, catalog, schema, null, null, null, null, null, columnNames, StatementType.PREPARED_STATEMENT, StatementColumnNames); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. * @param catalog The catalog. * @param columnNames An array of column names indicating the columns that should be returned from the inserted row or * rows. * @deprecated Use {@link #PStmtKey(String, String, String, String[])}. */ @Deprecated public PStmtKey(final String sql, final String catalog, final String[] columnNames) { this(sql, catalog, null, null, null, null, null, null, columnNames, StatementType.PREPARED_STATEMENT, StatementColumnNames); } private int[] clone(final int[] array) { return array == null ? null : array.clone(); } private String[] clone(final String[] array) { return array == null ? null : array.clone(); } /** * Creates a new Statement from the given Connection. * * @param connection The Connection to use to create the statement. * @return The statement. * @throws SQLException Thrown when there is a problem creating the statement. */ public Statement createStatement(final Connection connection) throws SQLException { return statementBuilder.createStatement(connection, this); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final PStmtKey other = (PStmtKey) obj; if (!Objects.equals(autoGeneratedKeys, other.autoGeneratedKeys)) { return false; } if (!Objects.equals(catalog, other.catalog)) { return false; } if (!Arrays.equals(columnIndexes, other.columnIndexes)) { return false; } if (!Arrays.equals(columnNames, other.columnNames)) { return false; } if (!Objects.equals(resultSetConcurrency, other.resultSetConcurrency)) { return false; } if (!Objects.equals(resultSetHoldability, other.resultSetHoldability)) { return false; } if (!Objects.equals(resultSetType, other.resultSetType)) { return false; } if (!Objects.equals(schema, other.schema)) { return false; } if (!Objects.equals(sql, other.sql)) { return false; } return statementType == other.statementType; } /** * Gets a flag indicating whether auto-generated keys should be returned; one of {@code Statement.RETURN_GENERATED_KEYS} * or {@code Statement.NO_GENERATED_KEYS}. * * @return a flag indicating whether auto-generated keys should be returned. */ public Integer getAutoGeneratedKeys() { return autoGeneratedKeys; } /** * Gets the catalog. * * @return The catalog. */ public String getCatalog() { return catalog; } /** * Gets an array of column indexes indicating the columns that should be returned from the inserted row or rows. * * @return An array of column indexes. */ public int[] getColumnIndexes() { return clone(columnIndexes); } /** * Gets an array of column names indicating the columns that should be returned from the inserted row or rows. * * @return An array of column names. */ public String[] getColumnNames() { return clone(columnNames); } /** * Gets the result set concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * * @return The result set concurrency type. */ public Integer getResultSetConcurrency() { return resultSetConcurrency; } /** * Gets the result set holdability, one of the following {@code ResultSet} constants: * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * * @return The result set holdability. */ public Integer getResultSetHoldability() { return resultSetHoldability; } /** * Gets the result set type, one of {@code ResultSet.TYPE_FORWARD_ONLY}, {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or * {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * * @return the result set type. */ public Integer getResultSetType() { return resultSetType; } /** * Gets the schema. * * @return The catalog. */ public String getSchema() { return schema; } /** * Gets the SQL statement. * * @return the SQL statement. */ public String getSql() { return sql; } /** * Gets the SQL statement type. * * @return The SQL statement type. */ public StatementType getStmtType() { return statementType; } @Override public int hashCode() { return Objects.hash(autoGeneratedKeys, catalog, Arrays.hashCode(columnIndexes), Arrays.hashCode(columnNames), resultSetConcurrency, resultSetHoldability, resultSetType, schema, sql, statementType); } @Override public String toString() { final StringBuilder buf = new StringBuilder(); buf.append("PStmtKey: sql="); buf.append(sql); buf.append(", catalog="); buf.append(catalog); buf.append(", schema="); buf.append(schema); buf.append(", resultSetType="); buf.append(resultSetType); buf.append(", resultSetConcurrency="); buf.append(resultSetConcurrency); buf.append(", resultSetHoldability="); buf.append(resultSetHoldability); buf.append(", autoGeneratedKeys="); buf.append(autoGeneratedKeys); buf.append(", columnIndexes="); buf.append(Arrays.toString(columnIndexes)); buf.append(", columnNames="); buf.append(Arrays.toString(columnNames)); buf.append(", statementType="); buf.append(statementType); return buf.toString(); } } PoolableCallableStatement.java000066400000000000000000000075661472045345700343050ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.SQLException; import org.apache.commons.pool2.KeyedObjectPool; /** * A {@link DelegatingCallableStatement} that cooperates with {@link PoolingConnection} to implement a pool of * {@link CallableStatement}s. *

* The {@link #close} method returns this statement to its containing pool. (See {@link PoolingConnection}.) * * @see PoolingConnection * @since 2.0 */ public class PoolableCallableStatement extends DelegatingCallableStatement { /** * The {@link KeyedObjectPool} from which this CallableStatement was obtained. */ private final KeyedObjectPool pool; /** * Key for this statement in the containing {@link KeyedObjectPool}. */ private final PStmtKey key; /** * Constructs a new instance. * * @param callableStatement * the underlying {@link CallableStatement} * @param key * the key for this statement in the {@link KeyedObjectPool} * @param pool * the {@link KeyedObjectPool} from which this CallableStatement was obtained * @param connection * the {@link DelegatingConnection} that created this CallableStatement */ public PoolableCallableStatement(final CallableStatement callableStatement, final PStmtKey key, final KeyedObjectPool pool, final DelegatingConnection connection) { super(connection, callableStatement); this.pool = pool; this.key = key; // Remove from trace now because this statement will be // added by the activate method. removeThisTrace(connection); } /** * Activates after retrieval from the pool. Adds a trace for this CallableStatement to the Connection that created * it. * * @since 2.4.0 made public, was protected in 2.3.0. */ @Override public void activate() throws SQLException { setClosedInternal(false); add(getConnectionInternal(), this); super.activate(); } /** * Returns the CallableStatement to the pool. If {{@link #isClosed()}, this is a No-op. */ @Override public void close() throws SQLException { // calling close twice should have no effect if (!isClosed()) { try { pool.returnObject(key, this); } catch (final SQLException | RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot close CallableStatement (return to pool failed)", e); } } } /** * Passivates to prepare for return to the pool. Removes the trace associated with this CallableStatement from the * Connection that created it. Also closes any associated ResultSets. * * @since 2.4.0 made public, was protected in 2.3.0. */ @Override public void passivate() throws SQLException { prepareToReturn(); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java000066400000000000000000000443161472045345700330710ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.lang.management.ManagementFactory; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.time.Duration; import java.util.Collection; import java.util.concurrent.Executor; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.management.InstanceAlreadyExistsException; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool; /** * A delegating connection that, rather than closing the underlying connection, returns itself to an {@link ObjectPool} * when closed. * * @since 2.0 */ public class PoolableConnection extends DelegatingConnection implements PoolableConnectionMXBean { private static MBeanServer MBEAN_SERVER; static { try { MBEAN_SERVER = ManagementFactory.getPlatformMBeanServer(); } catch (final NoClassDefFoundError | Exception ignored) { // ignore - JMX not available } } /** The pool to which I should return. */ private final ObjectPool pool; private final ObjectNameWrapper jmxObjectName; // Use a prepared statement for validation, retaining the last used SQL to // check if the validation query has changed. private PreparedStatement validationPreparedStatement; private String lastValidationSql; /** * Indicate that unrecoverable SQLException was thrown when using this connection. Such a connection should be * considered broken and not pass validation in the future. */ private boolean fatalSqlExceptionThrown; /** * SQL State codes considered to signal fatal conditions. Overrides the defaults in * {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). */ private final Collection disconnectionSqlCodes; /** * A collection of SQL State codes that are not considered fatal disconnection codes. * * @since 2.13.0 */ private final Collection disconnectionIgnoreSqlCodes; /** Whether or not to fast fail validation after fatal connection errors */ private final boolean fastFailValidation; private final Lock lock = new ReentrantLock(); /** * * @param conn * my underlying connection * @param pool * the pool to which I should return when closed * @param jmxName * JMX name */ public PoolableConnection(final Connection conn, final ObjectPool pool, final ObjectName jmxName) { this(conn, pool, jmxName, null, true); } /** * * @param conn * my underlying connection * @param pool * the pool to which I should return when closed * @param jmxObjectName * JMX name * @param disconnectSqlCodes * SQL State codes considered fatal disconnection errors * @param fastFailValidation * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to * run query or isValid) */ public PoolableConnection(final Connection conn, final ObjectPool pool, final ObjectName jmxObjectName, final Collection disconnectSqlCodes, final boolean fastFailValidation) { this(conn, pool, jmxObjectName, disconnectSqlCodes, null, fastFailValidation); } /** * Creates a new {@link PoolableConnection} instance. * * @param conn * my underlying connection * @param pool * the pool to which I should return when closed * @param jmxObjectName * JMX name * @param disconnectSqlCodes * SQL State codes considered fatal disconnection errors * @param disconnectionIgnoreSqlCodes * SQL State codes that should be ignored when determining fatal disconnection errors * @param fastFailValidation * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to * run query or isValid) * @since 2.13.0 */ public PoolableConnection(final Connection conn, final ObjectPool pool, final ObjectName jmxObjectName, final Collection disconnectSqlCodes, final Collection disconnectionIgnoreSqlCodes, final boolean fastFailValidation) { super(conn); this.pool = pool; this.jmxObjectName = ObjectNameWrapper.wrap(jmxObjectName); this.disconnectionSqlCodes = disconnectSqlCodes; this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes; this.fastFailValidation = fastFailValidation; if (jmxObjectName != null) { try { MBEAN_SERVER.registerMBean(this, jmxObjectName); } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException ignored) { // For now, simply skip registration } } } /** * Abort my underlying {@link Connection}. * * @since 2.9.0 */ @Override public void abort(final Executor executor) throws SQLException { if (jmxObjectName != null) { jmxObjectName.unregisterMBean(); } super.abort(executor); } /** * Returns this instance to my containing pool. */ @Override public void close() throws SQLException { lock.lock(); try { if (isClosedInternal()) { // already closed return; } boolean isUnderlyingConnectionClosed; try { isUnderlyingConnectionClosed = getDelegateInternal().isClosed(); } catch (final SQLException e) { try { pool.invalidateObject(this); } catch (final IllegalStateException ise) { // pool is closed, so close the connection passivate(); getInnermostDelegate().close(); } catch (final Exception ignored) { // DO NOTHING the original exception will be rethrown } throw new SQLException("Cannot close connection (isClosed check failed)", e); } /* * Can't set close before this code block since the connection needs to be open when validation runs. Can't set * close after this code block since by then the connection will have been returned to the pool and may have * been borrowed by another thread. Therefore, the close flag is set in passivate(). */ if (isUnderlyingConnectionClosed) { // Abnormal close: underlying connection closed unexpectedly, so we // must destroy this proxy try { pool.invalidateObject(this); } catch (final IllegalStateException e) { // pool is closed, so close the connection passivate(); getInnermostDelegate().close(); } catch (final Exception e) { throw new SQLException("Cannot close connection (invalidating pooled object failed)", e); } } else { // Normal close: underlying connection is still open, so we // simply need to return this proxy to the pool try { pool.returnObject(this); } catch (final IllegalStateException e) { // pool is closed, so close the connection passivate(); getInnermostDelegate().close(); } catch (final SQLException | RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot close connection (return to pool failed)", e); } } } finally { lock.unlock(); } } /** * @return The disconnection SQL codes. * @since 2.6.0 */ public Collection getDisconnectionSqlCodes() { return disconnectionSqlCodes; } /** * Gets the value of the {@link #toString()} method via a bean getter, so it can be read as a property via JMX. */ @Override public String getToString() { return toString(); } @Override protected void handleException(final SQLException e) throws SQLException { fatalSqlExceptionThrown |= isFatalException(e); super.handleException(e); } /** * {@inheritDoc} *

* This method should not be used by a client to determine whether or not a connection should be return to the * connection pool (by calling {@link #close()}). Clients should always attempt to return a connection to the pool * once it is no longer required. */ @Override public boolean isClosed() throws SQLException { if (isClosedInternal()) { return true; } if (getDelegateInternal().isClosed()) { // Something has gone wrong. The underlying connection has been // closed without the connection being returned to the pool. Return // it now. close(); return true; } return false; } /** * Checks the SQLState of the input exception. *

* If {@link #disconnectionSqlCodes} has been set, sql states are compared to those in the configured list of fatal * exception codes. If this property is not set, codes are compared against the default codes in * {@link Utils#getDisconnectionSqlCodes()} and in this case anything starting with #{link * Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection. Additionally, any SQL state * listed in {@link #disconnectionIgnoreSqlCodes} will be ignored and not treated as fatal. *

* * @param e SQLException to be examined * @return true if the exception signals a disconnection */ boolean isDisconnectionSqlException(final SQLException e) { boolean fatalException = false; final String sqlState = e.getSQLState(); if (sqlState != null) { if (disconnectionIgnoreSqlCodes != null && disconnectionIgnoreSqlCodes.contains(sqlState)) { return false; } fatalException = disconnectionSqlCodes == null ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.isDisconnectionSqlCode(sqlState) : disconnectionSqlCodes.contains(sqlState); } return fatalException; } /** * @return Whether to fail-fast. * @since 2.6.0 */ public boolean isFastFailValidation() { return fastFailValidation; } /** * Checks the SQLState of the input exception and any nested SQLExceptions it wraps. *

* If {@link #disconnectionSqlCodes} has been set, sql states are compared to those in the * configured list of fatal exception codes. If this property is not set, codes are compared against the default * codes in {@link Utils#getDisconnectionSqlCodes()} and in this case anything starting with #{link * Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection. *

* * @param e * SQLException to be examined * @return true if the exception signals a disconnection */ boolean isFatalException(final SQLException e) { boolean fatalException = isDisconnectionSqlException(e); if (!fatalException) { SQLException parentException = e; SQLException nextException = e.getNextException(); while (nextException != null && nextException != parentException && !fatalException) { fatalException = isDisconnectionSqlException(nextException); parentException = nextException; nextException = parentException.getNextException(); } } return fatalException; } @Override protected void passivate() throws SQLException { super.passivate(); setClosedInternal(true); if (getDelegateInternal() instanceof PoolingConnection) { ((PoolingConnection) getDelegateInternal()).connectionReturnedToPool(); } } /** * Closes the underlying {@link Connection}. */ @Override public void reallyClose() throws SQLException { if (jmxObjectName != null) { jmxObjectName.unregisterMBean(); } if (validationPreparedStatement != null) { Utils.closeQuietly((AutoCloseable) validationPreparedStatement); } super.closeInternal(); } @Override public void setLastUsed() { super.setLastUsed(); if (pool instanceof GenericObjectPool) { final GenericObjectPool gop = (GenericObjectPool) pool; if (gop.isAbandonedConfig()) { gop.use(this); } } } /** * Validates the connection, using the following algorithm: *
    *
  1. If {@code fastFailValidation} (constructor argument) is {@code true} and this connection has previously * thrown a fatal disconnection exception, a {@code SQLException} is thrown.
  2. *
  3. If {@code sql} is null, the driver's #{@link Connection#isValid(int) isValid(timeout)} is called. If it * returns {@code false}, {@code SQLException} is thrown; otherwise, this method returns successfully.
  4. *
  5. If {@code sql} is not null, it is executed as a query and if the resulting {@code ResultSet} contains at * least one row, this method returns successfully. If not, {@code SQLException} is thrown.
  6. *
* * @param sql * The validation SQL query. * @param timeoutDuration * The validation timeout in seconds. * @throws SQLException * Thrown when validation fails or an SQLException occurs during validation * @since 2.10.0 */ public void validate(final String sql, Duration timeoutDuration) throws SQLException { if (fastFailValidation && fatalSqlExceptionThrown) { throw new SQLException(Utils.getMessage("poolableConnection.validate.fastFail")); } if (sql == null || sql.isEmpty()) { if (timeoutDuration.isNegative()) { timeoutDuration = Duration.ZERO; } if (!isValid(timeoutDuration)) { throw new SQLException("isValid() returned false"); } return; } if (!sql.equals(lastValidationSql)) { lastValidationSql = sql; // Has to be the innermost delegate else the prepared statement will // be closed when the pooled connection is passivated. validationPreparedStatement = getInnermostDelegateInternal().prepareStatement(sql); } if (timeoutDuration.compareTo(Duration.ZERO) > 0) { validationPreparedStatement.setQueryTimeout((int) timeoutDuration.getSeconds()); } try (ResultSet rs = validationPreparedStatement.executeQuery()) { if (!rs.next()) { throw new SQLException("validationQuery didn't return a row"); } } catch (final SQLException sqle) { throw sqle; } } /** * Validates the connection, using the following algorithm: *
    *
  1. If {@code fastFailValidation} (constructor argument) is {@code true} and this connection has previously * thrown a fatal disconnection exception, a {@code SQLException} is thrown.
  2. *
  3. If {@code sql} is null, the driver's #{@link Connection#isValid(int) isValid(timeout)} is called. If it * returns {@code false}, {@code SQLException} is thrown; otherwise, this method returns successfully.
  4. *
  5. If {@code sql} is not null, it is executed as a query and if the resulting {@code ResultSet} contains at * least one row, this method returns successfully. If not, {@code SQLException} is thrown.
  6. *
* * @param sql * The validation SQL query. * @param timeoutSeconds * The validation timeout in seconds. * @throws SQLException * Thrown when validation fails or an SQLException occurs during validation * @deprecated Use {@link #validate(String, Duration)}. */ @Deprecated public void validate(final String sql, final int timeoutSeconds) throws SQLException { validate(sql, Duration.ofSeconds(timeoutSeconds)); } } PoolableConnectionFactory.java000066400000000000000000000735601472045345700343450ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; import java.util.Collection; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.pool2.DestroyMode; import org.apache.commons.pool2.KeyedObjectPool; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; /** * A {@link PooledObjectFactory} that creates {@link PoolableConnection}s. * * @since 2.0 */ public class PoolableConnectionFactory implements PooledObjectFactory { private static final Log log = LogFactory.getLog(PoolableConnectionFactory.class); /** * Internal constant to indicate the level is not set. */ static final int UNKNOWN_TRANSACTION_ISOLATION = -1; private final ConnectionFactory connectionFactory; private final ObjectName dataSourceJmxObjectName; private volatile String validationQuery; private volatile Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1); private Collection connectionInitSqls; private Collection disconnectionSqlCodes; private Collection disconnectionIgnoreSqlCodes; private boolean fastFailValidation = true; private volatile ObjectPool pool; private Boolean defaultReadOnly; private Boolean defaultAutoCommit; private boolean autoCommitOnReturn = true; private boolean rollbackOnReturn = true; private int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION; private String defaultCatalog; private String defaultSchema; private boolean cacheState; private boolean poolStatements; private boolean clearStatementPoolOnReturn; private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; private Duration maxConnDuration = Duration.ofMillis(-1); private final AtomicLong connectionIndex = new AtomicLong(); private Duration defaultQueryTimeoutDuration; /** * Creates a new {@code PoolableConnectionFactory}. * * @param connFactory * the {@link ConnectionFactory} from which to obtain base {@link Connection}s * @param dataSourceJmxObjectName * The JMX object name, may be null. */ public PoolableConnectionFactory(final ConnectionFactory connFactory, final ObjectName dataSourceJmxObjectName) { this.connectionFactory = connFactory; this.dataSourceJmxObjectName = dataSourceJmxObjectName; } @Override public void activateObject(final PooledObject p) throws SQLException { validateLifetime(p); final PoolableConnection pConnection = p.getObject(); pConnection.activate(); if (defaultAutoCommit != null && pConnection.getAutoCommit() != defaultAutoCommit) { pConnection.setAutoCommit(defaultAutoCommit); } if (defaultTransactionIsolation != UNKNOWN_TRANSACTION_ISOLATION && pConnection.getTransactionIsolation() != defaultTransactionIsolation) { pConnection.setTransactionIsolation(defaultTransactionIsolation); } if (defaultReadOnly != null && pConnection.isReadOnly() != defaultReadOnly) { pConnection.setReadOnly(defaultReadOnly); } if (defaultCatalog != null && !defaultCatalog.equals(pConnection.getCatalog())) { pConnection.setCatalog(defaultCatalog); } if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(pConnection))) { Jdbc41Bridge.setSchema(pConnection, defaultSchema); } pConnection.setDefaultQueryTimeout(defaultQueryTimeoutDuration); } @Override public void destroyObject(final PooledObject p) throws SQLException { p.getObject().reallyClose(); } /** * @since 2.9.0 */ @Override public void destroyObject(final PooledObject p, final DestroyMode mode) throws SQLException { if (mode == DestroyMode.ABANDONED) { Jdbc41Bridge.abort(p.getObject().getInnermostDelegate(), Runnable::run); } else { p.getObject().reallyClose(); } } /** * Gets the cache state to propagate in {@link #makeObject()}. * * @return The cache state. * @since 2.6.0. */ public boolean getCacheState() { return cacheState; } /** * Gets the connection factory. * * @return The connection factory. * @since 2.6.0. */ public ConnectionFactory getConnectionFactory() { return connectionFactory; } /** * Gets how many connections were created in {@link #makeObject()}. * * @return the connection count. */ protected AtomicLong getConnectionIndex() { return connectionIndex; } /** * Gets the collection of initialization SQL statements. * * @return The collection of initialization SQL statements. * @since 2.6.0 */ public Collection getConnectionInitSqls() { return connectionInitSqls; } /** * Gets data source JMX ObjectName. * * @return The data source JMX ObjectName. * @since 2.6.0. */ public ObjectName getDataSourceJmxName() { return dataSourceJmxObjectName; } /** * Gets the data source JMX ObjectName. * * @return The data source JMX ObjectName. * @since 2.6.0 */ public ObjectName getDataSourceJmxObjectName() { return dataSourceJmxObjectName; } /** * Gets the Default auto-commit value. * * @return The default auto-commit value. * @since 2.6.0 */ public Boolean getDefaultAutoCommit() { return defaultAutoCommit; } /** * Gets the default catalog. * * @return The default catalog. * @since 2.6.0 */ public String getDefaultCatalog() { return defaultCatalog; } /** * Gets the default query timeout in seconds. * * @return The default query timeout in seconds. * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. */ @Deprecated public Integer getDefaultQueryTimeout() { return getDefaultQueryTimeoutSeconds(); } /** * Gets the default query timeout Duration. * * @return The default query timeout Duration. * @since 2.10.0 */ public Duration getDefaultQueryTimeoutDuration() { return defaultQueryTimeoutDuration; } /** * Gets the default query timeout in seconds. * * @return The default query timeout in seconds. * @since 2.6.0 * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}. */ @Deprecated public Integer getDefaultQueryTimeoutSeconds() { return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds(); } /** * Gets the default read-only-value. * * @return The default read-only-value. * @since 2.6.0 */ public Boolean getDefaultReadOnly() { return defaultReadOnly; } /** * Gets the default schema. * * @return The default schema. * @since 2.6.0 */ public String getDefaultSchema() { return defaultSchema; } /** * Gets the default transaction isolation. * * @return The default transaction isolation. * @since 2.6.0 */ public int getDefaultTransactionIsolation() { return defaultTransactionIsolation; } /** * Gets the collection of SQL State codes that are not considered fatal disconnection codes. *

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

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

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

*

* If {@link #isFastFailValidation()} is {@code false} setting this property has no effect. *

* * @return SQL State codes overriding defaults * @since 2.1 */ public Collection getDisconnectionSqlCodes() { return disconnectionSqlCodes; } /** * Gets the Maximum connection duration. * * @return Maximum connection duration. * @since 2.10.0 */ public Duration getMaxConnDuration() { return maxConnDuration; } /** * Gets the Maximum connection lifetime in milliseconds. * * @return Maximum connection lifetime in milliseconds. * @since 2.6.0 */ public long getMaxConnLifetimeMillis() { return maxConnDuration.toMillis(); } /** * Gets the maximum number of open prepared statements. * * @return The maximum number of open prepared statements. */ protected int getMaxOpenPreparedStatements() { return maxOpenPreparedStatements; } /** * Returns the {@link ObjectPool} in which {@link Connection}s are pooled. * * @return the connection pool */ public synchronized ObjectPool getPool() { return pool; } /** * Tests whether to pool statements. * * @return Whether to pool statements. * @since 2.6.0. */ public boolean getPoolStatements() { return poolStatements; } /** * Gets the validation query. * * @return Validation query. * @since 2.6.0 */ public String getValidationQuery() { return validationQuery; } /** * Gets the query timeout in seconds. * * @return Validation query timeout in seconds. * @since 2.10.0 */ public Duration getValidationQueryTimeoutDuration() { return validationQueryTimeoutDuration; } /** * Gets the query timeout in seconds. * * @return Validation query timeout in seconds. * @since 2.6.0 * @deprecated Use {@link #getValidationQueryTimeoutDuration()}. */ @Deprecated public int getValidationQueryTimeoutSeconds() { return (int) validationQueryTimeoutDuration.getSeconds(); } /** * Initializes the given connection with the collection of SQL statements set in {@link #setConnectionInitSql(Collection)}. * * @param conn the connection to initialize. * @throws SQLException if a database access error occurs or this method is called on a closed connection. * @see #setConnectionInitSql(Collection) */ protected void initializeConnection(final Connection conn) throws SQLException { final Collection sqls = connectionInitSqls; if (conn.isClosed()) { throw new SQLException("initializeConnection: connection closed"); } if (!Utils.isEmpty(sqls)) { try (Statement statement = conn.createStatement()) { for (final String sql : sqls) { statement.execute(Objects.requireNonNull(sql, "null connectionInitSqls element")); } } } } /** * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}. * * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}. * @since 2.6.0 */ public boolean isAutoCommitOnReturn() { return autoCommitOnReturn; } /** * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}. * * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}. * @deprecated Use {@link #isAutoCommitOnReturn()}. */ @Deprecated public boolean isEnableAutoCommitOnReturn() { return autoCommitOnReturn; } /** * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with * SQL State indicating fatal disconnection errors. * * @return true if connections created by this factory will fast fail validation. * @see #setDisconnectionSqlCodes(Collection) * @since 2.1 * @since 2.5.0 Defaults to true, previous versions defaulted to false. */ public boolean isFastFailValidation() { return fastFailValidation; } /** * Tests whether to rollback on return. * * @return Whether to rollback on return. */ public boolean isRollbackOnReturn() { return rollbackOnReturn; } @Override public PooledObject makeObject() throws SQLException { Connection conn = connectionFactory.createConnection(); if (conn == null) { throw new IllegalStateException("Connection factory returned null from createConnection"); } try { initializeConnection(conn); } catch (final SQLException e) { // Make sure the connection is closed Utils.closeQuietly((AutoCloseable) conn); // Rethrow original exception so it is visible to caller throw e; } final long connIndex = connectionIndex.getAndIncrement(); if (poolStatements) { conn = new PoolingConnection(conn); final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotalPerKey(-1); config.setBlockWhenExhausted(false); config.setMaxWait(Duration.ZERO); config.setMaxIdlePerKey(1); config.setMaxTotal(maxOpenPreparedStatements); if (dataSourceJmxObjectName != null) { final StringBuilder base = new StringBuilder(dataSourceJmxObjectName.toString()); base.append(Constants.JMX_CONNECTION_BASE_EXT); base.append(connIndex); config.setJmxNameBase(base.toString()); config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX); } else { config.setJmxEnabled(false); } final PoolingConnection poolingConn = (PoolingConnection) conn; final KeyedObjectPool stmtPool = new GenericKeyedObjectPool<>(poolingConn, config); poolingConn.setStatementPool(stmtPool); poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn); poolingConn.setCacheState(cacheState); } // Register this connection with JMX final ObjectName connJmxName; if (dataSourceJmxObjectName == null) { connJmxName = null; } else { final String name = dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex; try { connJmxName = new ObjectName(name); } catch (final MalformedObjectNameException e) { Utils.closeQuietly((AutoCloseable) conn); throw new SQLException(name, e); } } final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, disconnectionIgnoreSqlCodes, fastFailValidation); pc.setCacheState(cacheState); return new DefaultPooledObject<>(pc); } @Override public void passivateObject(final PooledObject p) throws SQLException { validateLifetime(p); final PoolableConnection conn = p.getObject(); Boolean connAutoCommit = null; if (rollbackOnReturn) { connAutoCommit = conn.getAutoCommit(); if (!connAutoCommit && !conn.isReadOnly()) { conn.rollback(); } } conn.clearWarnings(); // DBCP-97 / DBCP-399 / DBCP-351 Idle connections in the pool should // have autoCommit enabled if (autoCommitOnReturn) { if (connAutoCommit == null) { connAutoCommit = conn.getAutoCommit(); } if (!connAutoCommit) { conn.setAutoCommit(true); } } conn.passivate(); } /** * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}. * * @param autoCommitOnReturn whether to set auto-commit. */ public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { this.autoCommitOnReturn = autoCommitOnReturn; } /** * Sets the cache state to propagate in {@link #makeObject()}. * * @param cacheState the cache state to propagate. */ public void setCacheState(final boolean cacheState) { this.cacheState = cacheState; } /** * Sets whether the pool of statements (which was enabled with {@link #setPoolStatements(boolean)}) should * be cleared when the connection is returned to its pool. Default is false. * * @param clearStatementPoolOnReturn clear or not * @since 2.8.0 */ public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) { this.clearStatementPoolOnReturn = clearStatementPoolOnReturn; } /** * Sets the SQL statements I use to initialize newly created {@link Connection}s. Using {@code null} turns off * connection initialization. * * @param connectionInitSqls * SQL statement to initialize {@link Connection}s. */ public void setConnectionInitSql(final Collection connectionInitSqls) { this.connectionInitSqls = connectionInitSqls; } /** * Sets the default "auto commit" setting for borrowed {@link Connection}s * * @param defaultAutoCommit * the default "auto commit" setting for borrowed {@link Connection}s */ public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { this.defaultAutoCommit = defaultAutoCommit; } /** * Sets the default "catalog" setting for borrowed {@link Connection}s * * @param defaultCatalog * the default "catalog" setting for borrowed {@link Connection}s */ public void setDefaultCatalog(final String defaultCatalog) { this.defaultCatalog = defaultCatalog; } /** * Sets the query timeout Duration. * * @param defaultQueryTimeoutDuration the query timeout Duration. * @since 2.10.0 */ public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) { this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration; } /** * Sets the query timeout in seconds. * * @param defaultQueryTimeoutSeconds the query timeout in seconds. * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}. */ @Deprecated public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds); } /** * Sets the default "read only" setting for borrowed {@link Connection}s * * @param defaultReadOnly * the default "read only" setting for borrowed {@link Connection}s */ public void setDefaultReadOnly(final Boolean defaultReadOnly) { this.defaultReadOnly = defaultReadOnly; } /** * Sets the default "schema" setting for borrowed {@link Connection}s * * @param defaultSchema * the default "schema" setting for borrowed {@link Connection}s * @since 2.5.0 */ public void setDefaultSchema(final String defaultSchema) { this.defaultSchema = defaultSchema; } /** * Sets the default "Transaction Isolation" setting for borrowed {@link Connection}s * * @param defaultTransactionIsolation * the default "Transaction Isolation" setting for returned {@link Connection}s */ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { this.defaultTransactionIsolation = defaultTransactionIsolation; } /** * Sets the disconnection SQL codes to ignore. * * @param disconnectionIgnoreSqlCodes * The collection of SQL State codes to be ignored. * @see #getDisconnectionIgnoreSqlCodes() * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}. * @since 2.13.0 */ public void setDisconnectionIgnoreSqlCodes(final Collection disconnectionIgnoreSqlCodes) { Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes); this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes; } /** * Sets the disconnection SQL codes. * * @param disconnectionSqlCodes * The disconnection SQL codes. * @see #getDisconnectionSqlCodes() * @since 2.1 * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. */ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCodes) { Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes); this.disconnectionSqlCodes = disconnectionSqlCodes; } /** * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}. * * @param autoCommitOnReturn whether to set auto-commit. */ @Deprecated public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) { this.autoCommitOnReturn = autoCommitOnReturn; } /** * @see #isFastFailValidation() * @param fastFailValidation * true means connections created by this factory will fast fail validation * @since 2.1 */ public void setFastFailValidation(final boolean fastFailValidation) { this.fastFailValidation = fastFailValidation; } /** * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1. * * @param maxConnDuration * The maximum lifetime in milliseconds. * @since 2.10.0 */ public void setMaxConn(final Duration maxConnDuration) { this.maxConnDuration = maxConnDuration; } /** * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1. * * @param maxConnLifetimeMillis * The maximum lifetime in milliseconds. * @deprecated Use {@link #setMaxConn(Duration)}. */ @Deprecated public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis); } /** * Sets the maximum number of open prepared statements. * * @param maxOpenPreparedStatements * The maximum number of open prepared statements. */ public void setMaxOpenPreparedStatements(final int maxOpenPreparedStatements) { this.maxOpenPreparedStatements = maxOpenPreparedStatements; } /** * Deprecated due to typo in method name. * * @param maxOpenPreparedStatements * The maximum number of open prepared statements. * @deprecated Use {@link #setMaxOpenPreparedStatements(int)}. */ @Deprecated // Due to typo in method name. public void setMaxOpenPrepatedStatements(final int maxOpenPreparedStatements) { setMaxOpenPreparedStatements(maxOpenPreparedStatements); } /** * Sets the {@link ObjectPool} in which to pool {@link Connection}s. * * @param pool * the {@link ObjectPool} in which to pool those {@link Connection}s */ public synchronized void setPool(final ObjectPool pool) { if (null != this.pool && pool != this.pool) { Utils.closeQuietly(this.pool); } this.pool = pool; } /** * Sets whether to pool statements. * * @param poolStatements whether to pool statements. */ public void setPoolStatements(final boolean poolStatements) { this.poolStatements = poolStatements; } /** * Sets whether to rollback on return. * * @param rollbackOnReturn whether to rollback on return. */ public void setRollbackOnReturn(final boolean rollbackOnReturn) { this.rollbackOnReturn = rollbackOnReturn; } /** * Sets the query I use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. If * not specified, {@link Connection#isValid(int)} will be used to validate connections. * * @param validationQuery * a query to use to {@link #validateObject validate} {@link Connection}s. */ public void setValidationQuery(final String validationQuery) { this.validationQuery = validationQuery; } /** * Sets the validation query timeout, the amount of time, that connection validation will wait for a response from the * database when executing a validation query. Use a value less than or equal to 0 for no timeout. * * @param validationQueryTimeoutDuration new validation query timeout duration. * @since 2.10.0 */ public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) { this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; } /** * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. * * @param validationQueryTimeoutSeconds * new validation query timeout value in seconds * @deprecated {@link #setValidationQueryTimeout(Duration)}. */ @Deprecated public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); } /** * Validates the given connection if it is open. * * @param conn the connection to validate. * @throws SQLException if the connection is closed or validate fails. */ public void validateConnection(final PoolableConnection conn) throws SQLException { if (conn.isClosed()) { throw new SQLException("validateConnection: connection closed"); } conn.validate(validationQuery, validationQueryTimeoutDuration); } private void validateLifetime(final PooledObject p) throws LifetimeExceededException { Utils.validateLifetime(p, maxConnDuration); } @Override public boolean validateObject(final PooledObject p) { try { validateLifetime(p); validateConnection(p.getObject()); return true; } catch (final Exception e) { if (log.isDebugEnabled()) { log.debug(Utils.getMessage("poolableConnectionFactory.validateObject.fail"), e); } return false; } } } PoolableConnectionMXBean.java000066400000000000000000000135571472045345700340500ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.SQLException; /** * Defines the attributes and methods that will be exposed via JMX for {@link PoolableConnection} instances. * * @since 2.0 */ public interface PoolableConnectionMXBean { /** * Clears the cached state. Call when you know that the underlying connection may have been accessed directly. */ void clearCachedState(); /** * See {@link Connection#clearWarnings()}. * * @throws SQLException See {@link Connection#clearWarnings()}. */ void clearWarnings() throws SQLException; /** * Returns this instance to my containing pool. * * @throws SQLException Throw if this instance cannot be returned. */ void close() throws SQLException; /** * See {@link Connection#getAutoCommit()}. * * @return See {@link Connection#getAutoCommit()}. * @throws SQLException See {@link Connection#getAutoCommit()}. */ boolean getAutoCommit() throws SQLException; /** * Gets whether to cache properties. The cached properties are: *
    *
  • auto-commit
  • *
  • catalog
  • *
  • schema
  • *
  • read-only
  • *
* * @return The value for the state caching flag. */ boolean getCacheState(); /** * See {@link Connection#getCatalog()}. * * @return See {@link Connection#getCatalog()}. * @throws SQLException See {@link Connection#getCatalog()}. */ String getCatalog() throws SQLException; /** * See {@link Connection#getHoldability()}. * * @return See {@link Connection#getHoldability()}. * @throws SQLException See {@link Connection#getHoldability()}. */ int getHoldability() throws SQLException; /** * See {@link Connection#getSchema()}. * * @return See {@link Connection#getSchema()}. * @throws SQLException See {@link Connection#getSchema()}. */ String getSchema() throws SQLException; /** * Gets the value of the {@link Object#toString()} method via a bean getter, so it can be read as a property via JMX. * * @return the value of the {@link Object#toString()}. */ String getToString(); /** * See {@link Connection#getTransactionIsolation()}. * * @return See {@link Connection#getTransactionIsolation()}. * @throws SQLException See {@link Connection#getTransactionIsolation()}. */ int getTransactionIsolation() throws SQLException; /** * See {@link Connection#isClosed()}. * * @return See {@link Connection#isClosed()}. * @throws SQLException See {@link Connection#isClosed()}. */ boolean isClosed() throws SQLException; /** * See {@link Connection#isReadOnly()}. * * @return See {@link Connection#isReadOnly()}. * @throws SQLException See {@link Connection#isReadOnly()}. */ boolean isReadOnly() throws SQLException; /** * Closes the underlying {@link Connection}. * * @throws SQLException Thrown if the connection can be closed. */ void reallyClose() throws SQLException; /** * See {@link Connection#setAutoCommit(boolean)}. * * @param autoCommit See {@link Connection#setAutoCommit(boolean)}. * @throws SQLException See {@link Connection#setAutoCommit(boolean)}. */ void setAutoCommit(boolean autoCommit) throws SQLException; /** * Sets whether to cache properties. The cached properties are: *
    *
  • auto-commit
  • *
  • catalog
  • *
  • schema
  • *
  • read-only
  • *
* * @param cacheState The new value for the state caching flag */ void setCacheState(boolean cacheState); /** * See {@link Connection#setCatalog(String)}. * * @param catalog See {@link Connection#setCatalog(String)}. * @throws SQLException See {@link Connection#setCatalog(String)}. */ void setCatalog(String catalog) throws SQLException; /** * See {@link Connection#setHoldability(int)}. * * @param holdability {@link Connection#setHoldability(int)}. * @throws SQLException See {@link Connection#setHoldability(int)}. */ void setHoldability(int holdability) throws SQLException; /** * See {@link Connection#setReadOnly(boolean)}. * * @param readOnly See {@link Connection#setReadOnly(boolean)}. * @throws SQLException See {@link Connection#setReadOnly(boolean)}. */ void setReadOnly(boolean readOnly) throws SQLException; /** * See {@link Connection#setSchema(String)}. * * @param schema See {@link Connection#setSchema(String)}. * @throws SQLException See {@link Connection#setSchema(String)}. */ void setSchema(String schema) throws SQLException; /** * See {@link Connection#setTransactionIsolation(int)}. * * @param level See {@link Connection#setTransactionIsolation(int)}. * @throws SQLException See {@link Connection#setTransactionIsolation(int)}. */ void setTransactionIsolation(int level) throws SQLException; } PoolablePreparedStatement.java000066400000000000000000000075001472045345700343340ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.PreparedStatement; import java.sql.SQLException; import org.apache.commons.pool2.KeyedObjectPool; /** * A {@link DelegatingPreparedStatement} that cooperates with {@link PoolingConnection} to implement a pool of * {@link PreparedStatement}s. *

* My {@link #close} method returns me to my containing pool. (See {@link PoolingConnection}.) *

* * @param * the key type * * @see PoolingConnection * @since 2.0 */ public class PoolablePreparedStatement extends DelegatingPreparedStatement { /** * The {@link KeyedObjectPool} from which I was obtained. */ private final KeyedObjectPool> pool; /** * My "key" as used by {@link KeyedObjectPool}. */ private final K key; private volatile boolean batchAdded; /** * Constructs a new instance. * * @param stmt * my underlying {@link PreparedStatement} * @param key * my key as used by {@link KeyedObjectPool} * @param pool * the {@link KeyedObjectPool} from which I was obtained. * @param conn * the {@link java.sql.Connection Connection} from which I was created */ public PoolablePreparedStatement(final PreparedStatement stmt, final K key, final KeyedObjectPool> pool, final DelegatingConnection conn) { super(conn, stmt); this.pool = pool; this.key = key; // Remove from trace now because this statement will be // added by the activate method. removeThisTrace(conn); } @Override public void activate() throws SQLException { setClosedInternal(false); add(getConnectionInternal(), this); super.activate(); } /** * Add batch. */ @Override public void addBatch() throws SQLException { super.addBatch(); batchAdded = true; } /** * Clear Batch. */ @Override public void clearBatch() throws SQLException { batchAdded = false; super.clearBatch(); } /** * Return me to my pool. */ @Override public void close() throws SQLException { // calling close twice should have no effect if (!isClosed()) { try { pool.returnObject(key, this); } catch (final SQLException | RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot close preparedstatement (return to pool failed)", e); } } } /** * Package-protected for tests. * * @return The key. */ K getKey() { return key; } @Override public void passivate() throws SQLException { // DBCP-372. clearBatch with throw an exception if called when the // connection is marked as closed. if (batchAdded) { clearBatch(); } prepareToReturn(); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java000066400000000000000000000574571472045345700327550ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.util.NoSuchElementException; import java.util.Objects; import org.apache.commons.pool2.KeyedObjectPool; import org.apache.commons.pool2.KeyedPooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; /** * A {@link DelegatingConnection} that pools {@link PreparedStatement}s. *

* The {@link #prepareStatement} and {@link #prepareCall} methods, rather than creating a new PreparedStatement each * time, may actually pull the statement from a pool of unused statements. The {@link PreparedStatement#close} method of * the returned statement doesn't actually close the statement, but rather returns it to the pool. (See * {@link PoolablePreparedStatement}, {@link PoolableCallableStatement}.) *

* * @see PoolablePreparedStatement * @since 2.0 */ public class PoolingConnection extends DelegatingConnection implements KeyedPooledObjectFactory { /** * Statement types. * * See subclasses of {@link Statement}. * * @since 2.0 protected enum. * @since 2.4.0 public enum. * @see Statement * @see CallableStatement * @see PreparedStatement */ public enum StatementType { /** * Callable statement. * * @see CallableStatement */ CALLABLE_STATEMENT, /** * Prepared statement. * * @see PreparedStatement */ PREPARED_STATEMENT } /** Pool of {@link PreparedStatement}s. and {@link CallableStatement}s */ private KeyedObjectPool pStmtPool; private boolean clearStatementPoolOnReturn; /** * Constructs a new instance. * * @param connection * the underlying {@link Connection}. */ public PoolingConnection(final Connection connection) { super(connection); } /** * {@link KeyedPooledObjectFactory} method for activating pooled statements. * * @param key * ignored * @param pooledObject * wrapped pooled statement to be activated */ @Override public void activateObject(final PStmtKey key, final PooledObject pooledObject) throws SQLException { pooledObject.getObject().activate(); } /** * Closes and frees all {@link PreparedStatement}s or {@link CallableStatement}s from the pool, and close the * underlying connection. */ @Override public synchronized void close() throws SQLException { try { if (null != pStmtPool) { final KeyedObjectPool oldPool = pStmtPool; pStmtPool = null; try { oldPool.close(); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot close connection", e); } } } finally { try { @SuppressWarnings("resource") final Connection delegateInternal = getDelegateInternal(); if (delegateInternal != null) { delegateInternal.close(); } } finally { setClosedInternal(true); } } } /** * Notification from {@link PoolableConnection} that we returned to the pool. * * @throws SQLException when {@code clearStatementPoolOnReturn} is true and the statement pool could not be * cleared * @since 2.8.0 */ public void connectionReturnedToPool() throws SQLException { if (pStmtPool != null && clearStatementPoolOnReturn) { try { pStmtPool.clear(); } catch (final Exception e) { throw new SQLException("Error clearing statement pool", e); } } } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull()); } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * @param autoGeneratedKeys * A flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql, final int autoGeneratedKeys) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), autoGeneratedKeys); } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency); } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @param resultSetHoldability * result set holdability * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, resultSetHoldability); } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @param resultSetHoldability * result set holdability * @param statementType * statement type * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final StatementType statementType) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, resultSetHoldability, statementType); } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @param statementType * statement type * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final StatementType statementType) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, statementType); } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * @param columnIndexes * An array of column indexes indicating the columns that should be returned from the inserted row or * rows. * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql, final int[] columnIndexes) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnIndexes); } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * @param statementType * statement type * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql, final StatementType statementType) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), statementType, null); } /** * Creates a PStmtKey for the given arguments. * * @param sql * the SQL string used to define the statement * @param columnNames * column names * * @return the PStmtKey created for the given arguments. */ protected PStmtKey createKey(final String sql, final String[] columnNames) { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnNames); } /** * {@link KeyedPooledObjectFactory} method for destroying PoolablePreparedStatements and PoolableCallableStatements. * Closes the underlying statement. * * @param key * ignored * @param pooledObject * the wrapped pooled statement to be destroyed. */ @Override public void destroyObject(final PStmtKey key, final PooledObject pooledObject) throws SQLException { if (pooledObject != null) { @SuppressWarnings("resource") final DelegatingPreparedStatement object = pooledObject.getObject(); if (object != null) { @SuppressWarnings("resource") final Statement innermostDelegate = object.getInnermostDelegate(); if (innermostDelegate != null) { innermostDelegate.close(); } } } } private String getCatalogOrNull() { try { return getCatalog(); } catch (final SQLException ignored) { return null; } } private String getSchemaOrNull() { try { return getSchema(); } catch (final SQLException ignored) { return null; } } /** * Gets the prepared statement pool. * * @return statement pool * @since 2.8.0 */ public KeyedObjectPool getStatementPool() { return pStmtPool; } /** * {@link KeyedPooledObjectFactory} method for creating {@link PoolablePreparedStatement}s or * {@link PoolableCallableStatement}s. The {@code stmtType} field in the key determines whether a * PoolablePreparedStatement or PoolableCallableStatement is created. * * @param key * the key for the {@link PreparedStatement} to be created * @see #createKey(String, int, int, StatementType) */ @SuppressWarnings("resource") @Override public PooledObject makeObject(final PStmtKey key) throws SQLException { if (null == key) { throw new IllegalArgumentException("Prepared statement key is null or invalid."); } if (key.getStmtType() == StatementType.PREPARED_STATEMENT) { final PreparedStatement statement = (PreparedStatement) key.createStatement(getDelegate()); @SuppressWarnings({"rawtypes", "unchecked" }) // Unable to find way to avoid this final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, pStmtPool, this); return new DefaultPooledObject<>(pps); } final CallableStatement statement = (CallableStatement) key.createStatement(getDelegate()); final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, pStmtPool, this); return new DefaultPooledObject<>(pcs); } /** * Normalizes the given SQL statement, producing a canonical form that is semantically equivalent to the original. * * @param sql The statement to be normalized. * * @return The canonical form of the supplied SQL statement. */ protected String normalizeSQL(final String sql) { return sql.trim(); } /** * {@link KeyedPooledObjectFactory} method for passivating {@link PreparedStatement}s or {@link CallableStatement}s. * Invokes {@link PreparedStatement#clearParameters}. * * @param key * ignored * @param pooledObject * a wrapped {@link PreparedStatement} */ @Override public void passivateObject(final PStmtKey key, final PooledObject pooledObject) throws SQLException { @SuppressWarnings("resource") final DelegatingPreparedStatement dps = pooledObject.getObject(); dps.clearParameters(); dps.passivate(); } /** * Creates or obtains a {@link CallableStatement} from the pool. * * @param key * a {@link PStmtKey} for the given arguments * @return a {@link PoolableCallableStatement} * @throws SQLException * Wraps an underlying exception. */ private CallableStatement prepareCall(final PStmtKey key) throws SQLException { return (CallableStatement) prepareStatement(key); } /** * Creates or obtains a {@link CallableStatement} from the pool. * * @param sql * the SQL string used to define the CallableStatement * @return a {@link PoolableCallableStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public CallableStatement prepareCall(final String sql) throws SQLException { return prepareCall(createKey(sql, StatementType.CALLABLE_STATEMENT)); } /** * Creates or obtains a {@link CallableStatement} from the pool. * * @param sql * the SQL string used to define the CallableStatement * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @return a {@link PoolableCallableStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { return prepareCall(createKey(sql, resultSetType, resultSetConcurrency, StatementType.CALLABLE_STATEMENT)); } /** * Creates or obtains a {@link CallableStatement} from the pool. * * @param sql * the SQL string used to define the CallableStatement * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @param resultSetHoldability * result set holdability * @return a {@link PoolableCallableStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { return prepareCall(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.CALLABLE_STATEMENT)); } /** * Creates or obtains a {@link PreparedStatement} from the pool. * * @param key * a {@link PStmtKey} for the given arguments * @return a {@link PoolablePreparedStatement} * @throws SQLException * Wraps an underlying exception. */ private PreparedStatement prepareStatement(final PStmtKey key) throws SQLException { if (null == pStmtPool) { throw new SQLException("Statement pool is null - closed or invalid PoolingConnection."); } try { return pStmtPool.borrowObject(key); } catch (final NoSuchElementException e) { throw new SQLException("MaxOpenPreparedStatements limit reached", e); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareStatement from pool failed", e); } } /** * Creates or obtains a {@link PreparedStatement} from the pool. * * @param sql * the SQL string used to define the PreparedStatement * @return a {@link PoolablePreparedStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { return prepareStatement(createKey(sql)); } /* * Creates or obtains a {@link PreparedStatement} from the pool. * * @param sql * the SQL string used to define the PreparedStatement * @param autoGeneratedKeys * A flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. * @return a {@link PoolablePreparedStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { return prepareStatement(createKey(sql, autoGeneratedKeys)); } /** * Creates or obtains a {@link PreparedStatement} from the pool. * * @param sql * the SQL string used to define the PreparedStatement * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @return a {@link PoolablePreparedStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { return prepareStatement(createKey(sql, resultSetType, resultSetConcurrency)); } /** * Creates or obtains a {@link PreparedStatement} from the pool. * * @param sql * the SQL string used to define the PreparedStatement * @param resultSetType * result set type * @param resultSetConcurrency * result set concurrency * @param resultSetHoldability * result set holdability * @return a {@link PoolablePreparedStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { return prepareStatement(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); } /** * Creates or obtains a {@link PreparedStatement} from the pool. * * @param sql * the SQL string used to define the PreparedStatement * @param columnIndexes * An array of column indexes indicating the columns that should be returned from the inserted row or * rows. * @return a {@link PoolablePreparedStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { return prepareStatement(createKey(sql, columnIndexes)); } /** * Creates or obtains a {@link PreparedStatement} from the pool. * * @param sql * the SQL string used to define the PreparedStatement * @param columnNames * column names * @return a {@link PoolablePreparedStatement} * @throws SQLException * Wraps an underlying exception. */ @Override public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { return prepareStatement(createKey(sql, columnNames)); } /** * Sets whether the pool of statements should be cleared when the connection is returned to its pool. * Default is false. * * @param clearStatementPoolOnReturn clear or not * @since 2.8.0 */ public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) { this.clearStatementPoolOnReturn = clearStatementPoolOnReturn; } /** * Sets the prepared statement pool. * * @param pool * the prepared statement pool. */ public void setStatementPool(final KeyedObjectPool pool) { pStmtPool = pool; } @Override public synchronized String toString() { if (pStmtPool instanceof GenericKeyedObjectPool) { // DBCP-596 PoolingConnection.toString() causes StackOverflowError final GenericKeyedObjectPool gkop = (GenericKeyedObjectPool) pStmtPool; if (gkop.getFactory() == this) { return "PoolingConnection: " + pStmtPool.getClass() + "@" + System.identityHashCode(pStmtPool); } } return "PoolingConnection: " + Objects.toString(pStmtPool); } /** * {@link KeyedPooledObjectFactory} method for validating pooled statements. Currently, always returns true. * * @param key * ignored * @param pooledObject * ignored * @return {@code true} */ @Override public boolean validateObject(final PStmtKey key, final PooledObject pooledObject) { return true; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java000066400000000000000000000203141472045345700326660ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.NoSuchElementException; import java.util.Objects; import java.util.logging.Logger; import javax.sql.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool; /** * A simple {@link DataSource} implementation that obtains {@link Connection}s from the specified {@link ObjectPool}. * * @param * The connection type * * @since 2.0 */ public class PoolingDataSource implements DataSource, AutoCloseable { /** * PoolGuardConnectionWrapper is a Connection wrapper that makes sure a closed connection cannot be used anymore. * * @since 2.0 */ private final class PoolGuardConnectionWrapper extends DelegatingConnection { PoolGuardConnectionWrapper(final D delegate) { super(delegate); } @Override public void close() throws SQLException { if (getDelegateInternal() != null) { super.close(); super.setDelegate(null); } } /** * @see org.apache.commons.dbcp2.DelegatingConnection#getDelegate() */ @Override public D getDelegate() { return isAccessToUnderlyingConnectionAllowed() ? super.getDelegate() : null; } /** * @see org.apache.commons.dbcp2.DelegatingConnection#getInnermostDelegate() */ @Override public Connection getInnermostDelegate() { return isAccessToUnderlyingConnectionAllowed() ? super.getInnermostDelegate() : null; } @Override public boolean isClosed() throws SQLException { return getDelegateInternal() == null || super.isClosed(); } } private static final Log log = LogFactory.getLog(PoolingDataSource.class); /** Controls access to the underlying connection */ private boolean accessToUnderlyingConnectionAllowed; /** My log writer. */ private PrintWriter logWriter; private final ObjectPool pool; /** * Constructs a new instance backed by the given connection pool. * * @param pool * the given connection pool. */ public PoolingDataSource(final ObjectPool pool) { Objects.requireNonNull(pool, "pool"); this.pool = pool; // Verify that pool's factory refers back to it. If not, log a warning and try to fix. if (this.pool instanceof GenericObjectPool) { final PoolableConnectionFactory pcf = (PoolableConnectionFactory) ((GenericObjectPool) this.pool).getFactory(); Objects.requireNonNull(pcf, "this.pool.getFactory()"); if (pcf.getPool() != this.pool) { log.warn(Utils.getMessage("poolingDataSource.factoryConfig")); @SuppressWarnings("unchecked") // PCF must have a pool of PCs final ObjectPool p = (ObjectPool) this.pool; pcf.setPool(p); } } } /** * Closes and free all {@link Connection}s from the pool. * * @since 2.1 */ @Override public void close() throws SQLException { try { pool.close(); } catch (final Exception e) { throw new SQLException(Utils.getMessage("pool.close.fail"), e); } } /** * Returns a {@link java.sql.Connection} from my pool, according to the contract specified by * {@link ObjectPool#borrowObject}. */ @Override public Connection getConnection() throws SQLException { try { final C conn = pool.borrowObject(); if (conn == null) { return null; } return new PoolGuardConnectionWrapper<>(conn); } catch (final NoSuchElementException e) { throw new SQLException("Cannot get a connection, pool error " + e.getMessage(), e); } catch (final SQLException | RuntimeException e) { throw e; } catch (final InterruptedException e) { // Reset the interrupt status so it is visible to callers Thread.currentThread().interrupt(); throw new SQLException("Cannot get a connection, general error", e); } catch (final Exception e) { throw new SQLException("Cannot get a connection, general error", e); } } /** * Throws {@link UnsupportedOperationException} * * @throws UnsupportedOperationException * always thrown */ @Override public Connection getConnection(final String userName, final String password) throws SQLException { throw new UnsupportedOperationException(); } /** * Throws {@link UnsupportedOperationException}. * * @throws UnsupportedOperationException * As this implementation does not support this feature. */ @Override public int getLoginTimeout() { throw new UnsupportedOperationException("Login timeout is not supported."); } /** * Returns my log writer. * * @return my log writer * @see DataSource#getLogWriter */ @Override public PrintWriter getLogWriter() { return logWriter; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } /** * Gets the backing object pool. * * @return the backing object pool. */ protected ObjectPool getPool() { return pool; } /** * Returns the value of the accessToUnderlyingConnectionAllowed property. * * @return true if access to the underlying {@link Connection} is allowed, false otherwise. */ public boolean isAccessToUnderlyingConnectionAllowed() { return this.accessToUnderlyingConnectionAllowed; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return iface != null && iface.isInstance(this); } /** * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to * the underlying connection. (Default: false) * * @param allow * Access to the underlying connection is granted when true. */ public void setAccessToUnderlyingConnectionAllowed(final boolean allow) { this.accessToUnderlyingConnectionAllowed = allow; } /** * Throws {@link UnsupportedOperationException}. * * @throws UnsupportedOperationException * As this implementation does not support this feature. */ @Override public void setLoginTimeout(final int seconds) { throw new UnsupportedOperationException("Login timeout is not supported."); } /** * Sets my log writer. * * @see DataSource#setLogWriter */ @Override public void setLogWriter(final PrintWriter out) { logWriter = out; } @Override public T unwrap(final Class iface) throws SQLException { if (isWrapperFor(iface)) { return iface.cast(this); } throw new SQLException(this + " is not a wrapper for " + iface); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java000066400000000000000000000213731472045345700320750ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.HashMap; import java.util.NoSuchElementException; import java.util.Properties; import java.util.logging.Logger; import org.apache.commons.pool2.ObjectPool; /** * A {@link Driver} implementation that obtains {@link Connection}s from a registered {@link ObjectPool}. * * @since 2.0 */ public class PoolingDriver implements Driver { /** * PoolGuardConnectionWrapper is a Connection wrapper that makes sure a closed connection cannot be used anymore. * * @since 2.0 */ private final class PoolGuardConnectionWrapper extends DelegatingConnection { private final ObjectPool pool; PoolGuardConnectionWrapper(final ObjectPool pool, final Connection delegate) { super(delegate); this.pool = pool; } /** * @see org.apache.commons.dbcp2.DelegatingConnection#getDelegate() */ @Override public Connection getDelegate() { if (isAccessToUnderlyingConnectionAllowed()) { return super.getDelegate(); } return null; } /** * @see org.apache.commons.dbcp2.DelegatingConnection#getInnermostDelegate() */ @Override public Connection getInnermostDelegate() { if (isAccessToUnderlyingConnectionAllowed()) { return super.getInnermostDelegate(); } return null; } } private static final DriverPropertyInfo[] EMPTY_DRIVER_PROPERTY_INFO_ARRAY = {}; /* Register myself with the {@link DriverManager}. */ static { try { DriverManager.registerDriver(new PoolingDriver()); } catch (final Exception ignored) { // Ignored } } /** The map of registered pools. */ protected static final HashMap> pools = new HashMap<>(); /** * The Apache Commons connection string prefix {@value}. */ public static final String URL_PREFIX = "jdbc:apache:commons:dbcp:"; /** * The String length of {@link #URL_PREFIX}. */ protected static final int URL_PREFIX_LEN = URL_PREFIX.length(); /** * Major version number. */ protected static final int MAJOR_VERSION = 1; /** * Minor version number. */ protected static final int MINOR_VERSION = 0; /** Controls access to the underlying connection */ private final boolean accessToUnderlyingConnectionAllowed; /** * Constructs a new driver with {@code accessToUnderlyingConnectionAllowed} enabled. */ public PoolingDriver() { this(true); } /** * For unit testing purposes. * * @param accessToUnderlyingConnectionAllowed * Do {@link DelegatingConnection}s created by this driver permit access to the delegate? */ protected PoolingDriver(final boolean accessToUnderlyingConnectionAllowed) { this.accessToUnderlyingConnectionAllowed = accessToUnderlyingConnectionAllowed; } @Override public boolean acceptsURL(final String url) throws SQLException { return url != null && url.startsWith(URL_PREFIX); } /** * Closes a named pool. * * @param name * The pool name. * @throws SQLException * Thrown when a problem is caught closing the pool. */ public synchronized void closePool(final String name) throws SQLException { @SuppressWarnings("resource") final ObjectPool pool = pools.get(name); if (pool != null) { pools.remove(name); try { pool.close(); } catch (final Exception e) { throw new SQLException("Error closing pool " + name, e); } } } @Override public Connection connect(final String url, final Properties info) throws SQLException { if (acceptsURL(url)) { final ObjectPool pool = getConnectionPool(url.substring(URL_PREFIX_LEN)); try { final Connection conn = pool.borrowObject(); if (conn == null) { return null; } return new PoolGuardConnectionWrapper(pool, conn); } catch (final NoSuchElementException e) { throw new SQLException("Cannot get a connection, pool error: " + e.getMessage(), e); } catch (final SQLException | RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot get a connection, general error: " + e.getMessage(), e); } } return null; } /** * Gets the connection pool for the given name. * * @param name * The pool name * @return The pool * @throws SQLException * Thrown when the named pool is not registered. */ public synchronized ObjectPool getConnectionPool(final String name) throws SQLException { final ObjectPool pool = pools.get(name); if (null == pool) { throw new SQLException("Pool not registered: " + name); } return pool; } @Override public int getMajorVersion() { return MAJOR_VERSION; } @Override public int getMinorVersion() { return MINOR_VERSION; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } /** * Gets the pool names. * * @return the pool names. */ public synchronized String[] getPoolNames() { return pools.keySet().toArray(Utils.EMPTY_STRING_ARRAY); } @Override public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) { return EMPTY_DRIVER_PROPERTY_INFO_ARRAY; } /** * Invalidates the given connection. * * @param conn * connection to invalidate * @throws SQLException * if the connection is not a {@code PoolGuardConnectionWrapper} or an error occurs invalidating * the connection */ public void invalidateConnection(final Connection conn) throws SQLException { if (!(conn instanceof PoolGuardConnectionWrapper)) { throw new SQLException("Invalid connection class"); } final PoolGuardConnectionWrapper pgconn = (PoolGuardConnectionWrapper) conn; @SuppressWarnings("unchecked") final ObjectPool pool = (ObjectPool) pgconn.pool; try { pool.invalidateObject(pgconn.getDelegateInternal()); } catch (final Exception ignored) { // Ignored. } } /** * Returns the value of the accessToUnderlyingConnectionAllowed property. * * @return true if access to the underlying is allowed, false otherwise. */ protected boolean isAccessToUnderlyingConnectionAllowed() { return accessToUnderlyingConnectionAllowed; } @Override public boolean jdbcCompliant() { return true; } /** * Registers a named pool. * * @param name * The pool name. * @param pool * The pool. */ public synchronized void registerPool(final String name, final ObjectPool pool) { pools.put(name, pool); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/SQLExceptionList.java000066400000000000000000000036251472045345700324640ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.SQLException; import java.util.List; /** * An SQLException based on a list of Throwable causes. *

* The first exception in the list is used as this exception's cause and is accessible with the usual * {@link #getCause()} while the complete list is accessible with {@link #getCauseList()}. *

* * @since 2.7.0 */ public class SQLExceptionList extends SQLException { private static final long serialVersionUID = 1L; private final List causeList; /** * Creates a new exception caused by a list of exceptions. * * @param causeList a list of cause exceptions. */ public SQLExceptionList(final List causeList) { super(String.format("%,d exceptions: %s", causeList == null ? 0 : causeList.size(), causeList), causeList == null ? null : causeList.get(0)); this.causeList = causeList; } /** * Gets the cause list. * * @return The list of causes. */ public List getCauseList() { return causeList; } } SwallowedExceptionLogger.java000066400000000000000000000041471472045345700342130ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import org.apache.commons.logging.Log; import org.apache.commons.pool2.SwallowedExceptionListener; /** * Class for logging swallowed exceptions. * * @since 2.0 */ public class SwallowedExceptionLogger implements SwallowedExceptionListener { private final Log log; private final boolean logExpiredConnections; /** * Create a SwallowedExceptionLogger with the given logger. By default, expired connection logging is turned on. * * @param log * logger */ public SwallowedExceptionLogger(final Log log) { this(log, true); } /** * Create a SwallowedExceptionLogger with the given logger and expired connection logging property. * * @param log * logger * @param logExpiredConnections * false suppresses logging of expired connection events */ public SwallowedExceptionLogger(final Log log, final boolean logExpiredConnections) { this.log = log; this.logExpiredConnections = logExpiredConnections; } @Override public void onSwallowException(final Exception e) { if (logExpiredConnections || !(e instanceof LifetimeExceededException)) { log.warn(Utils.getMessage("swallowedExceptionLogger.onSwallowedException"), e); } } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/Utils.java000066400000000000000000000242101472045345700304030ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.text.MessageFormat; import java.time.Duration; import java.time.Instant; import java.util.Collection; import java.util.HashSet; import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; import java.util.function.Consumer; import org.apache.commons.pool2.PooledObject; /** * Utility methods. * * @since 2.0 */ public final class Utils { private static final ResourceBundle messages = ResourceBundle .getBundle(Utils.class.getPackage().getName() + ".LocalStrings"); /** * Whether the security manager is enabled. * * @deprecated No replacement. */ @Deprecated public static final boolean IS_SECURITY_ENABLED = isSecurityEnabled(); /** * Any SQL State starting with this value is considered a fatal disconnect. */ public static final String DISCONNECTION_SQL_CODE_PREFIX = "08"; /** * SQL codes of fatal connection errors. *
    *
  • 57P01 (Admin shutdown)
  • *
  • 57P02 (Crash shutdown)
  • *
  • 57P03 (Cannot connect now)
  • *
  • 01002 (SQL92 disconnect error)
  • *
  • JZ0C0 (Sybase disconnect error)
  • *
  • JZ0C1 (Sybase disconnect error)
  • *
* @deprecated Use {@link #getDisconnectionSqlCodes()}. */ @Deprecated public static final Set DISCONNECTION_SQL_CODES; static final ResultSet[] EMPTY_RESULT_SET_ARRAY = {}; static final String[] EMPTY_STRING_ARRAY = {}; static { DISCONNECTION_SQL_CODES = new HashSet<>(); DISCONNECTION_SQL_CODES.add("57P01"); // Admin shutdown DISCONNECTION_SQL_CODES.add("57P02"); // Crash shutdown DISCONNECTION_SQL_CODES.add("57P03"); // Cannot connect now DISCONNECTION_SQL_CODES.add("01002"); // SQL92 disconnect error DISCONNECTION_SQL_CODES.add("JZ0C0"); // Sybase disconnect error DISCONNECTION_SQL_CODES.add("JZ0C1"); // Sybase disconnect error } /** * Checks for conflicts between two collections. *

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

* * @param codes1 The first collection of SQL state codes. * @param codes2 The second collection of SQL state codes. * @throws IllegalArgumentException if any codes overlap between the two collections. * @since 2.13.0 */ static void checkSqlCodes(final Collection codes1, final Collection codes2) { if (codes1 != null && codes2 != null) { final Set test = new HashSet<>(codes1); test.retainAll(codes2); if (!test.isEmpty()) { throw new IllegalArgumentException(test + " cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes."); } } } /** * Clones the given char[] if not null. * * @param value may be null. * @return a cloned char[] or null. */ public static char[] clone(final char[] value) { return value == null ? null : value.clone(); } /** * Clones the given {@link Properties} without the standard "user" or "password" entries. * * @param properties may be null * @return a clone of the input without the standard "user" or "password" entries. * @since 2.8.0 */ public static Properties cloneWithoutCredentials(final Properties properties) { if (properties != null) { final Properties temp = (Properties) properties.clone(); temp.remove(Constants.KEY_USER); temp.remove(Constants.KEY_PASSWORD); return temp; } return properties; } /** * Closes the given {@link AutoCloseable} and if an exception is caught, then calls {@code exceptionHandler}. * * @param autoCloseable The resource to close. * @param exceptionHandler Consumes exception thrown closing this resource. * @since 2.10.0 */ public static void close(final AutoCloseable autoCloseable, final Consumer exceptionHandler) { if (autoCloseable != null) { try { autoCloseable.close(); } catch (final Exception e) { if (exceptionHandler != null) { exceptionHandler.accept(e); } } } } /** * Closes the AutoCloseable (which may be null). * * @param autoCloseable an AutoCloseable, may be {@code null} * @since 2.6.0 */ public static void closeQuietly(final AutoCloseable autoCloseable) { close(autoCloseable, null); } /** * Closes the Connection (which may be null). * * @param connection a Connection, may be {@code null} * @deprecated Use {@link #closeQuietly(AutoCloseable)}. */ @Deprecated public static void closeQuietly(final Connection connection) { closeQuietly((AutoCloseable) connection); } /** * Closes the ResultSet (which may be null). * * @param resultSet a ResultSet, may be {@code null} * @deprecated Use {@link #closeQuietly(AutoCloseable)}. */ @Deprecated public static void closeQuietly(final ResultSet resultSet) { closeQuietly((AutoCloseable) resultSet); } /** * Closes the Statement (which may be null). * * @param statement a Statement, may be {@code null}. * @deprecated Use {@link #closeQuietly(AutoCloseable)}. */ @Deprecated public static void closeQuietly(final Statement statement) { closeQuietly((AutoCloseable) statement); } /** * Gets a copy of SQL codes of fatal connection errors. *
    *
  • 57P01 (Admin shutdown)
  • *
  • 57P02 (Crash shutdown)
  • *
  • 57P03 (Cannot connect now)
  • *
  • 01002 (SQL92 disconnect error)
  • *
  • JZ0C0 (Sybase disconnect error)
  • *
  • JZ0C1 (Sybase disconnect error)
  • *
* @return A copy SQL codes of fatal connection errors. * @since 2.10.0 */ public static Set getDisconnectionSqlCodes() { return new HashSet<>(DISCONNECTION_SQL_CODES); } /** * Gets the correct i18n message for the given key. * * @param key The key to look up an i18n message. * @return The i18n message. */ public static String getMessage(final String key) { return getMessage(key, (Object[]) null); } /** * Gets the correct i18n message for the given key with placeholders replaced by the supplied arguments. * * @param key A message key. * @param args The message arguments. * @return An i18n message. */ public static String getMessage(final String key, final Object... args) { final String msg = messages.getString(key); if (args == null || args.length == 0) { return msg; } final MessageFormat mf = new MessageFormat(msg); return mf.format(args, new StringBuffer(), null).toString(); } /** * Checks if the given SQL state corresponds to a fatal connection error. * * @param sqlState the SQL state to check. * @return true if the SQL state is a fatal connection error, false otherwise. * @since 2.13.0 */ static boolean isDisconnectionSqlCode(final String sqlState) { return DISCONNECTION_SQL_CODES.contains(sqlState); } static boolean isEmpty(final Collection collection) { return collection == null || collection.isEmpty(); } static boolean isSecurityEnabled() { return System.getSecurityManager() != null; } /** * Converts the given String to a char[]. * * @param value may be null. * @return a char[] or null. */ public static char[] toCharArray(final String value) { return value != null ? value.toCharArray() : null; } /** * Converts the given char[] to a String. * * @param value may be null. * @return a String or null. */ public static String toString(final char[] value) { return value == null ? null : String.valueOf(value); } /** * Throws a LifetimeExceededException if the given pooled object's lifetime has exceeded a maximum duration. * * @param p The pooled object to test. * @param maxDuration The maximum lifetime. * @throws LifetimeExceededException Thrown if the given pooled object's lifetime has exceeded a maximum duration. */ public static void validateLifetime(final PooledObject p, final Duration maxDuration) throws LifetimeExceededException { if (maxDuration.compareTo(Duration.ZERO) > 0) { final Duration lifetimeDuration = Duration.between(p.getCreateInstant(), Instant.now()); if (lifetimeDuration.compareTo(maxDuration) > 0) { throw new LifetimeExceededException(getMessage("connectionFactory.lifetimeExceeded", lifetimeDuration, maxDuration)); } } } private Utils() { // not instantiable } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/000077500000000000000000000000001472045345700307335ustar00rootroot00000000000000ConnectionImpl.java000066400000000000000000000316301472045345700344430ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.cpdsadapter; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.apache.commons.dbcp2.DelegatingCallableStatement; import org.apache.commons.dbcp2.DelegatingConnection; import org.apache.commons.dbcp2.DelegatingPreparedStatement; /** * This class is the {@code Connection} that will be returned from * {@code PooledConnectionImpl.getConnection()}. Most methods are wrappers around the JDBC 1.x * {@code Connection}. A few exceptions include preparedStatement and close. In accordance with the JDBC * specification this Connection cannot be used after closed() is called. Any further usage will result in an * SQLException. *

* ConnectionImpl extends DelegatingConnection to enable access to the underlying connection. *

* * @since 2.0 */ final class ConnectionImpl extends DelegatingConnection { private final boolean accessToUnderlyingConnectionAllowed; /** The object that instantiated this object */ private final PooledConnectionImpl pooledConnection; /** * Creates a {@code ConnectionImpl}. * * @param pooledConnection * The PooledConnection that is calling the ctor. * @param connection * The JDBC 1.x Connection to wrap. * @param accessToUnderlyingConnectionAllowed * if true, then access is allowed to the underlying connection */ ConnectionImpl(final PooledConnectionImpl pooledConnection, final Connection connection, final boolean accessToUnderlyingConnectionAllowed) { super(connection); this.pooledConnection = pooledConnection; this.accessToUnderlyingConnectionAllowed = accessToUnderlyingConnectionAllowed; } /** * Marks the Connection as closed, and notifies the pool that the pooled connection is available. *

* In accordance with the JDBC specification this Connection cannot be used after closed() is called. Any further * usage will result in an SQLException. *

* * @throws SQLException * The database connection couldn't be closed. */ @Override public void close() throws SQLException { if (!isClosedInternal()) { try { passivate(); } finally { setClosedInternal(true); pooledConnection.notifyListeners(); } } } /** * Gets the delegated connection, if allowed. * * @return the internal connection, or null if access is not allowed. * @see #isAccessToUnderlyingConnectionAllowed() */ @Override public Connection getDelegate() { if (isAccessToUnderlyingConnectionAllowed()) { return getDelegateInternal(); } return null; } /** * Gets the innermost connection, if allowed. * * @return the innermost internal connection, or null if access is not allowed. * @see #isAccessToUnderlyingConnectionAllowed() */ @Override public Connection getInnermostDelegate() { if (isAccessToUnderlyingConnectionAllowed()) { return super.getInnermostDelegateInternal(); } return null; } /** * Package-private for tests. * * @return the PooledConnectionImpl. */ PooledConnectionImpl getPooledConnectionImpl() { return pooledConnection; } /** * If false, getDelegate() and getInnermostDelegate() will return null. * * @return true if access is allowed to the underlying connection * @see ConnectionImpl */ public boolean isAccessToUnderlyingConnectionAllowed() { return accessToUnderlyingConnectionAllowed; } /** * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. * * @param sql * an SQL statement that may contain one or more '?' parameter placeholders. Typically, this statement is * specified using JDBC call escape syntax. * @return a default {@code CallableStatement} object containing the pre-compiled SQL statement. * @throws SQLException * Thrown if a database access error occurs or this method is called on a closed connection. * @since 2.4.0 */ @Override public CallableStatement prepareCall(final String sql) throws SQLException { checkOpen(); try { return new DelegatingCallableStatement(this, pooledConnection.prepareCall(sql)); } catch (final SQLException e) { handleException(e); // Does not return return null; } } /** * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. * * @param sql * a {@code String} object that is the SQL statement to be sent to the database; may contain on or * more '?' parameters. * @param resultSetType * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @return a {@code CallableStatement} object containing the pre-compiled SQL statement that will produce * {@code ResultSet} objects with the given type and concurrency. * @throws SQLException * Thrown if a database access error occurs, this method is called on a closed connection or the given * parameters are not {@code ResultSet} constants indicating type and concurrency. * @since 2.4.0 */ @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); try { return new DelegatingCallableStatement(this, pooledConnection.prepareCall(sql, resultSetType, resultSetConcurrency)); } catch (final SQLException e) { handleException(e); // Does not return return null; } } /** * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. * * @param sql * a {@code String} object that is the SQL statement to be sent to the database; may contain on or * more '?' parameters. * @param resultSetType * one of the following {@code ResultSet} constants: {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * one of the following {@code ResultSet} constants: {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @param resultSetHoldability * one of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * @return a new {@code CallableStatement} object, containing the pre-compiled SQL statement, that will * generate {@code ResultSet} objects with the given type, concurrency, and holdability. * @throws SQLException * Thrown if a database access error occurs, this method is called on a closed connection or the given * parameters are not {@code ResultSet} constants indicating type, concurrency, and holdability. * @since 2.4.0 */ @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); try { return new DelegatingCallableStatement(this, pooledConnection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); } catch (final SQLException e) { handleException(e); // Does not return return null; } } /** * If pooling of {@code PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. * * @param sql * SQL statement to be prepared * @return the prepared statement * @throws SQLException * if this connection is closed or an error occurs in the wrapped connection. */ @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { checkOpen(); try { return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql)); } catch (final SQLException e) { handleException(e); // Does not return return null; } } @Override public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); try { return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, autoGeneratedKeys)); } catch (final SQLException e) { handleException(e); return null; } } // // Methods for accessing the delegate connection // /** * If pooling of {@code PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. * * @throws SQLException * if this connection is closed or an error occurs in the wrapped connection. */ @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); try { return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, resultSetType, resultSetConcurrency)); } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); try { return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { checkOpen(); try { return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, columnIndexes)); } catch (final SQLException e) { handleException(e); return null; } } @Override public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { checkOpen(); try { return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, columnNames)); } catch (final SQLException e) { handleException(e); return null; } } } DriverAdapterCPDS.java000066400000000000000000001031711472045345700347300ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.cpdsadapter; import java.io.PrintWriter; import java.io.Serializable; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.time.Duration; import java.util.Hashtable; import java.util.Properties; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.Name; import javax.naming.NamingException; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.Referenceable; import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import org.apache.commons.dbcp2.Constants; import org.apache.commons.dbcp2.DelegatingPreparedStatement; import org.apache.commons.dbcp2.PStmtKey; import org.apache.commons.dbcp2.Utils; import org.apache.commons.pool2.KeyedObjectPool; import org.apache.commons.pool2.impl.BaseObjectPoolConfig; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; /** *

* An adapter for JDBC drivers that do not include an implementation of {@link javax.sql.ConnectionPoolDataSource}, but * still include a {@link java.sql.DriverManager} implementation. {@code ConnectionPoolDataSource}s are not used * within general applications. They are used by {@code DataSource} implementations that pool * {@code Connection}s, such as {@link org.apache.commons.dbcp2.datasources.SharedPoolDataSource}. A J2EE container * will normally provide some method of initializing the {@code ConnectionPoolDataSource} whose attributes are * presented as bean getters/setters and then deploying it via JNDI. It is then available as a source of physical * connections to the database, when the pooling {@code DataSource} needs to create a new physical connection. *

*

* Although normally used within a JNDI environment, the DriverAdapterCPDS can be instantiated and initialized as any * bean and then attached directly to a pooling {@code DataSource}. {@code Jdbc2PoolDataSource} can use the * {@code ConnectionPoolDataSource} with or without the use of JNDI. *

*

* The DriverAdapterCPDS also provides {@code PreparedStatement} pooling which is not generally available in jdbc2 * {@code ConnectionPoolDataSource} implementation, but is addressed within the JDBC 3 specification. The * {@code PreparedStatement} pool in DriverAdapterCPDS has been in the DBCP package for some time, but it has not * undergone extensive testing in the configuration used here. It should be considered experimental and can be toggled * with the poolPreparedStatements attribute. *

*

* The package documentation contains an example using Apache Catalina and JNDI. The * datasources package documentation shows how to use * {@code DriverAdapterCPDS} as a source for {@code Jdbc2PoolDataSource} without the use of JNDI. *

* * @since 2.0 */ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceable, Serializable, ObjectFactory { private static final String KEY_MIN_EVICTABLE_IDLE_DURATION = "minEvictableIdleDuration"; private static final String KEY_DURATION_BETWEEN_EVICTION_RUNS = "durationBetweenEvictionRuns"; private static final String KEY_LOGIN_TIMEOUT = "loginTimeout"; private static final String KEY_URL = "url"; private static final String KEY_DRIVER = "driver"; private static final String KEY_DESCRIPTION = "description"; private static final String KEY_ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED = "accessToUnderlyingConnectionAllowed"; private static final String KEY_MAX_PREPARED_STATEMENTS = "maxPreparedStatements"; private static final String KEY_MIN_EVICTABLE_IDLE_TIME_MILLIS = "minEvictableIdleTimeMillis"; private static final String KEY_NUM_TESTS_PER_EVICTION_RUN = "numTestsPerEvictionRun"; private static final String KEY_TIME_BETWEEN_EVICTION_RUNS_MILLIS = "timeBetweenEvictionRunsMillis"; private static final String KEY_MAX_IDLE = "maxIdle"; private static final String KEY_POOL_PREPARED_STATEMENTS = "poolPreparedStatements"; private static final long serialVersionUID = -4820523787212147844L; private static final String GET_CONNECTION_CALLED = "A PooledConnection was already requested from this source, further initialization is not allowed."; static { // Attempt to prevent deadlocks - see DBCP-272 DriverManager.getDrivers(); } /** Description */ private String description; /** Connection string */ private String connectionString; /** User name */ private String userName; /** User password */ private char[] userPassword; /** Driver class name */ private String driver; /** Login TimeOut in seconds */ private int loginTimeout; /** Log stream. NOT USED */ private transient PrintWriter logWriter; // PreparedStatement pool properties private boolean poolPreparedStatements; private int maxIdle = 10; private Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS; private int numTestsPerEvictionRun = -1; private Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION; private int maxPreparedStatements = -1; /** Whether or not getConnection has been called */ private volatile boolean getConnectionCalled; /** Connection properties passed to JDBC Driver */ private Properties connectionProperties; /** * Controls access to the underlying connection */ private boolean accessToUnderlyingConnectionAllowed; /** * Default no-argument constructor for Serialization */ public DriverAdapterCPDS() { } /** * Throws an IllegalStateException, if a PooledConnection has already been requested. */ private void assertInitializationAllowed() throws IllegalStateException { if (getConnectionCalled) { throw new IllegalStateException(GET_CONNECTION_CALLED); } } private boolean getBooleanContentString(final RefAddr ra) { return Boolean.parseBoolean(getStringContent(ra)); } /** * Gets the connection properties passed to the JDBC driver. * * @return the JDBC connection properties used when creating connections. */ public Properties getConnectionProperties() { return connectionProperties; } /** * Gets the value of description. This property is here for use by the code which will deploy this data source. It * is not used internally. * * @return value of description, may be null. * @see #setDescription(String) */ public String getDescription() { return description; } /** * Gets the driver class name. * * @return value of driver. */ public String getDriver() { return driver; } /** * 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 the value of the evictor thread timer * @see #setDurationBetweenEvictionRuns(Duration) * @since 2.9.0 */ public Duration getDurationBetweenEvictionRuns() { return durationBetweenEvictionRuns; } private int getIntegerStringContent(final RefAddr ra) { return Integer.parseInt(getStringContent(ra)); } /** * Gets the maximum time in seconds that this data source can wait while attempting to connect to a database. NOT * USED. */ @Override public int getLoginTimeout() { return loginTimeout; } /** * Gets the log writer for this data source. NOT USED. */ @Override public PrintWriter getLogWriter() { return logWriter; } /** * Gets the maximum number of statements that can remain idle in the pool, without extra ones being released, or * negative for no limit. * * @return the value of maxIdle */ public int getMaxIdle() { return maxIdle; } /** * Gets the maximum number of prepared statements. * * @return maxPrepartedStatements value */ public int getMaxPreparedStatements() { return maxPreparedStatements; } /** * Gets the minimum amount of time a statement may sit idle in the pool before it is eligible for eviction by the * idle object evictor (if any). * * @see #setMinEvictableIdleDuration * @see #setDurationBetweenEvictionRuns * @return the minimum amount of time a statement may sit idle in the pool. * @since 2.9.0 */ public Duration getMinEvictableIdleDuration() { return minEvictableIdleDuration; } /** * Gets the minimum amount of time a statement may sit idle in the pool before it is eligible for eviction by the * idle object evictor (if any). * * @see #setMinEvictableIdleTimeMillis * @see #setTimeBetweenEvictionRunsMillis * @return the minimum amount of time a statement may sit idle in the pool. * @deprecated USe {@link #getMinEvictableIdleDuration()}. */ @Deprecated public int getMinEvictableIdleTimeMillis() { return (int) minEvictableIdleDuration.toMillis(); } /** * Gets the number of statements to examine during each run of the idle object evictor thread (if any.) * * @see #setNumTestsPerEvictionRun * @see #setTimeBetweenEvictionRunsMillis * @return the number of statements to examine during each run of the idle object evictor thread (if any.) */ public int getNumTestsPerEvictionRun() { return numTestsPerEvictionRun; } /** * Implements {@link ObjectFactory} to create an instance of this class */ @Override public Object getObjectInstance(final Object refObj, final Name name, final Context context, final Hashtable env) throws ClassNotFoundException { // The spec says to return null if we can't create an instance // of the reference DriverAdapterCPDS cpds = null; if (refObj instanceof Reference) { final Reference ref = (Reference) refObj; if (ref.getClassName().equals(getClass().getName())) { RefAddr ra = ref.get(KEY_DESCRIPTION); if (isNotEmpty(ra)) { setDescription(getStringContent(ra)); } ra = ref.get(KEY_DRIVER); if (isNotEmpty(ra)) { setDriver(getStringContent(ra)); } ra = ref.get(KEY_URL); if (isNotEmpty(ra)) { setUrl(getStringContent(ra)); } ra = ref.get(Constants.KEY_USER); if (isNotEmpty(ra)) { setUser(getStringContent(ra)); } ra = ref.get(Constants.KEY_PASSWORD); if (isNotEmpty(ra)) { setPassword(getStringContent(ra)); } ra = ref.get(KEY_POOL_PREPARED_STATEMENTS); if (isNotEmpty(ra)) { setPoolPreparedStatements(getBooleanContentString(ra)); } ra = ref.get(KEY_MAX_IDLE); if (isNotEmpty(ra)) { setMaxIdle(getIntegerStringContent(ra)); } ra = ref.get(KEY_TIME_BETWEEN_EVICTION_RUNS_MILLIS); if (isNotEmpty(ra)) { setTimeBetweenEvictionRunsMillis(getIntegerStringContent(ra)); } ra = ref.get(KEY_NUM_TESTS_PER_EVICTION_RUN); if (isNotEmpty(ra)) { setNumTestsPerEvictionRun(getIntegerStringContent(ra)); } ra = ref.get(KEY_MIN_EVICTABLE_IDLE_TIME_MILLIS); if (isNotEmpty(ra)) { setMinEvictableIdleTimeMillis(getIntegerStringContent(ra)); } ra = ref.get(KEY_MAX_PREPARED_STATEMENTS); if (isNotEmpty(ra)) { setMaxPreparedStatements(getIntegerStringContent(ra)); } ra = ref.get(KEY_ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED); if (isNotEmpty(ra)) { setAccessToUnderlyingConnectionAllowed(getBooleanContentString(ra)); } cpds = this; } } return cpds; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } /** * Gets the value of password for the default user. * * @return value of password. */ public String getPassword() { return Utils.toString(userPassword); } /** * Gets the value of password for the default user. * * @return value of password. * @since 2.4.0 */ public char[] getPasswordCharArray() { return Utils.clone(userPassword); } /** * Attempts to establish a database connection using the default user and password. */ @Override public PooledConnection getPooledConnection() throws SQLException { return getPooledConnection(getUser(), getPassword()); } /** * Attempts to establish a database connection. * * @param pooledUserName name to be used for the connection * @param pooledUserPassword password to be used fur the connection */ @Override public PooledConnection getPooledConnection(final String pooledUserName, final String pooledUserPassword) throws SQLException { getConnectionCalled = true; if (connectionProperties != null) { update(connectionProperties, Constants.KEY_USER, pooledUserName); update(connectionProperties, Constants.KEY_PASSWORD, pooledUserPassword); } // Workaround for buggy WebLogic 5.1 class loader - ignore ClassCircularityError upon first invocation. PooledConnectionImpl pooledConnection = null; try { pooledConnection = getPooledConnectionImpl(pooledUserName, pooledUserPassword); } catch (final ClassCircularityError e) { pooledConnection = getPooledConnectionImpl(pooledUserName, pooledUserPassword); } if (isPoolPreparedStatements()) { final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotalPerKey(Integer.MAX_VALUE); config.setBlockWhenExhausted(false); config.setMaxWait(Duration.ZERO); config.setMaxIdlePerKey(getMaxIdle()); if (getMaxPreparedStatements() <= 0) { // Since there is no limit, create a prepared statement pool with an eviction thread; // evictor settings are the same as the connection pool settings. config.setTimeBetweenEvictionRuns(getDurationBetweenEvictionRuns()); config.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun()); config.setMinEvictableIdleDuration(getMinEvictableIdleDuration()); } else { // Since there is a limit, create a prepared statement pool without an eviction thread; // pool has LRU functionality so when the limit is reached, 15% of the pool is cleared. // see org.apache.commons.pool2.impl.GenericKeyedObjectPool.clearOldest method config.setMaxTotal(getMaxPreparedStatements()); config.setTimeBetweenEvictionRuns(Duration.ofMillis(-1)); config.setNumTestsPerEvictionRun(0); config.setMinEvictableIdleDuration(Duration.ZERO); } @SuppressWarnings("resource") // PooledConnectionImpl closes final KeyedObjectPool stmtPool = new GenericKeyedObjectPool<>(pooledConnection, config); pooledConnection.setStatementPool(stmtPool); } return pooledConnection; } @SuppressWarnings("resource") // Caller closes private PooledConnectionImpl getPooledConnectionImpl(final String pooledUserName, final String pooledUserPassword) throws SQLException { PooledConnectionImpl pooledConnection; if (connectionProperties != null) { pooledConnection = new PooledConnectionImpl(DriverManager.getConnection(getUrl(), connectionProperties)); } else { pooledConnection = new PooledConnectionImpl(DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword)); } pooledConnection.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); return pooledConnection; } /** * Implements {@link Referenceable}. */ @Override public Reference getReference() throws NamingException { // this class implements its own factory final String factory = getClass().getName(); final Reference ref = new Reference(getClass().getName(), factory, null); ref.add(new StringRefAddr(KEY_DESCRIPTION, getDescription())); ref.add(new StringRefAddr(KEY_DRIVER, getDriver())); ref.add(new StringRefAddr(KEY_LOGIN_TIMEOUT, String.valueOf(getLoginTimeout()))); ref.add(new StringRefAddr(Constants.KEY_PASSWORD, getPassword())); ref.add(new StringRefAddr(Constants.KEY_USER, getUser())); ref.add(new StringRefAddr(KEY_URL, getUrl())); ref.add(new StringRefAddr(KEY_POOL_PREPARED_STATEMENTS, String.valueOf(isPoolPreparedStatements()))); ref.add(new StringRefAddr(KEY_MAX_IDLE, String.valueOf(getMaxIdle()))); ref.add(new StringRefAddr(KEY_NUM_TESTS_PER_EVICTION_RUN, String.valueOf(getNumTestsPerEvictionRun()))); ref.add(new StringRefAddr(KEY_MAX_PREPARED_STATEMENTS, String.valueOf(getMaxPreparedStatements()))); // // Pair of current and deprecated. ref.add(new StringRefAddr(KEY_DURATION_BETWEEN_EVICTION_RUNS, String.valueOf(getDurationBetweenEvictionRuns()))); ref.add(new StringRefAddr(KEY_TIME_BETWEEN_EVICTION_RUNS_MILLIS, String.valueOf(getTimeBetweenEvictionRunsMillis()))); // // Pair of current and deprecated. ref.add(new StringRefAddr(KEY_MIN_EVICTABLE_IDLE_DURATION, String.valueOf(getMinEvictableIdleDuration()))); ref.add(new StringRefAddr(KEY_MIN_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(getMinEvictableIdleTimeMillis()))); return ref; } private String getStringContent(final RefAddr ra) { return ra.getContent().toString(); } /** * 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 the value of the evictor thread timer * @see #setDurationBetweenEvictionRuns(Duration) * @deprecated Use {@link #getDurationBetweenEvictionRuns()}. */ @Deprecated public long getTimeBetweenEvictionRunsMillis() { return durationBetweenEvictionRuns.toMillis(); } /** * Gets the value of connection string used to locate the database for this data source. * * @return value of connection string. */ public String getUrl() { return connectionString; } /** * Gets the value of default user (login or user name). * * @return value of user. */ public String getUser() { return userName; } /** * Returns the value of the accessToUnderlyingConnectionAllowed property. * * @return true if access to the underlying is allowed, false otherwise. */ public synchronized boolean isAccessToUnderlyingConnectionAllowed() { return this.accessToUnderlyingConnectionAllowed; } private boolean isNotEmpty(final RefAddr ra) { return ra != null && ra.getContent() != null; } /** * Whether to toggle the pooling of {@code PreparedStatement}s * * @return value of poolPreparedStatements. */ public boolean isPoolPreparedStatements() { return poolPreparedStatements; } /** * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to * the underlying connection. (Default: false) * * @param allow Access to the underlying connection is granted when true. */ public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) { this.accessToUnderlyingConnectionAllowed = allow; } /** * Sets the connection properties passed to the JDBC driver. *

* If {@code props} contains "user" and/or "password" properties, the corresponding instance properties are * set. If these properties are not present, they are filled in using {@link #getUser()}, {@link #getPassword()} * when {@link #getPooledConnection()} is called, or using the actual parameters to the method call when * {@link #getPooledConnection(String, String)} is called. Calls to {@link #setUser(String)} or * {@link #setPassword(String)} overwrite the values of these properties if {@code connectionProperties} is not * null. *

* * @param props Connection properties to use when creating new connections. * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setConnectionProperties(final Properties props) { assertInitializationAllowed(); connectionProperties = props; if (connectionProperties != null) { final String user = connectionProperties.getProperty(Constants.KEY_USER); if (user != null) { setUser(user); } final String password = connectionProperties.getProperty(Constants.KEY_PASSWORD); if (password != null) { setPassword(password); } } } /** * Sets the value of description. This property is here for use by the code which will deploy this datasource. It is * not used internally. * * @param description Value to assign to description. */ public void setDescription(final String description) { this.description = description; } /** * Sets the driver class name. Setting the driver class name cause the driver to be registered with the * DriverManager. * * @param driver Value to assign to driver. * @throws IllegalStateException if {@link #getPooledConnection()} has been called * @throws ClassNotFoundException if the class cannot be located */ public void setDriver(final String driver) throws ClassNotFoundException { assertInitializationAllowed(); this.driver = driver; // make sure driver is registered Class.forName(driver); } /** * Sets the duration to sleep between runs of the idle object evictor thread. When non-positive, no * idle object evictor thread will be run. * * @param durationBetweenEvictionRuns The duration to sleep between runs of the idle object evictor * thread. When non-positive, no idle object evictor thread will be run. * @see #getDurationBetweenEvictionRuns() * @throws IllegalStateException if {@link #getPooledConnection()} has been called * @since 2.9.0 */ public void setDurationBetweenEvictionRuns(final Duration durationBetweenEvictionRuns) { assertInitializationAllowed(); this.durationBetweenEvictionRuns = durationBetweenEvictionRuns; } /** * Sets the maximum time in seconds that this data source will wait while attempting to connect to a database. NOT * USED. */ @Override public void setLoginTimeout(final int seconds) { this.loginTimeout = seconds; } /** * Sets the log writer for this data source. NOT USED. */ @Override public void setLogWriter(final PrintWriter logWriter) { this.logWriter = logWriter; } /** * Gets the maximum number of statements that can remain idle in the pool, without extra ones being released, or * negative for no limit. * * @param maxIdle The maximum number of statements that can remain idle * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setMaxIdle(final int maxIdle) { assertInitializationAllowed(); this.maxIdle = maxIdle; } /** * Sets the maximum number of prepared statements. * * @param maxPreparedStatements the new maximum number of prepared statements */ public void setMaxPreparedStatements(final int maxPreparedStatements) { this.maxPreparedStatements = maxPreparedStatements; } /** * Sets the minimum amount of time a statement may sit idle in the pool before it is eligible for eviction by the * idle object evictor (if any). When non-positive, no objects will be evicted from the pool due to idle time alone. * * @param minEvictableIdleDuration minimum time to set in milliseconds. * @see #getMinEvictableIdleDuration() * @see #setDurationBetweenEvictionRuns(Duration) * @throws IllegalStateException if {@link #getPooledConnection()} has been called. * @since 2.9.0 */ public void setMinEvictableIdleDuration(final Duration minEvictableIdleDuration) { assertInitializationAllowed(); this.minEvictableIdleDuration = minEvictableIdleDuration; } /** * Sets the minimum amount of time a statement may sit idle in the pool before it is eligible for eviction by the * idle object evictor (if any). When non-positive, no objects will be evicted from the pool due to idle time alone. * * @param minEvictableIdleTimeMillis minimum time to set in milliseconds. * @see #getMinEvictableIdleDuration() * @see #setDurationBetweenEvictionRuns(Duration) * @throws IllegalStateException if {@link #getPooledConnection()} has been called * @deprecated Use {@link #setMinEvictableIdleDuration(Duration)}. */ @Deprecated public void setMinEvictableIdleTimeMillis(final int minEvictableIdleTimeMillis) { assertInitializationAllowed(); this.minEvictableIdleDuration = Duration.ofMillis(minEvictableIdleTimeMillis); } /** * Sets the number of statements to examine during each run of the idle object evictor thread (if any). *

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

* * @param numTestsPerEvictionRun number of statements to examine per run * @see #getNumTestsPerEvictionRun() * @see #setDurationBetweenEvictionRuns(Duration) * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { assertInitializationAllowed(); this.numTestsPerEvictionRun = numTestsPerEvictionRun; } /** * Sets the value of password for the default user. * * @param userPassword Value to assign to password. * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setPassword(final char[] userPassword) { assertInitializationAllowed(); this.userPassword = Utils.clone(userPassword); update(connectionProperties, Constants.KEY_PASSWORD, Utils.toString(this.userPassword)); } /** * Sets the value of password for the default user. * * @param userPassword Value to assign to password. * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setPassword(final String userPassword) { assertInitializationAllowed(); this.userPassword = Utils.toCharArray(userPassword); update(connectionProperties, Constants.KEY_PASSWORD, userPassword); } /** * Whether to toggle the pooling of {@code PreparedStatement}s * * @param poolPreparedStatements true to pool statements. * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setPoolPreparedStatements(final boolean poolPreparedStatements) { assertInitializationAllowed(); this.poolPreparedStatements = poolPreparedStatements; } /** * Sets 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. * * @param timeBetweenEvictionRunsMillis 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. * @see #getDurationBetweenEvictionRuns() * @throws IllegalStateException if {@link #getPooledConnection()} has been called * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}. */ @Deprecated public void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { assertInitializationAllowed(); this.durationBetweenEvictionRuns = Duration.ofMillis(timeBetweenEvictionRunsMillis); } /** * Sets the value of URL string used to locate the database for this data source. * * @param connectionString Value to assign to connection string. * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setUrl(final String connectionString) { assertInitializationAllowed(); this.connectionString = connectionString; } /** * Sets the value of default user (login or user name). * * @param userName Value to assign to user. * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setUser(final String userName) { assertInitializationAllowed(); this.userName = userName; update(connectionProperties, Constants.KEY_USER, userName); } /** * Does not print the userName and userPassword field nor the 'user' or 'password' in the connectionProperties. * * @since 2.6.0 */ @Override public synchronized String toString() { final StringBuilder builder = new StringBuilder(super.toString()); builder.append("[description="); builder.append(description); builder.append(", connectionString="); // TODO What if the connection string contains a 'user' or 'password' query parameter but that connection string // is not in a legal URL format? builder.append(connectionString); builder.append(", driver="); builder.append(driver); builder.append(", loginTimeout="); builder.append(loginTimeout); builder.append(", poolPreparedStatements="); builder.append(poolPreparedStatements); builder.append(", maxIdle="); builder.append(maxIdle); builder.append(", timeBetweenEvictionRunsMillis="); builder.append(durationBetweenEvictionRuns); builder.append(", numTestsPerEvictionRun="); builder.append(numTestsPerEvictionRun); builder.append(", minEvictableIdleTimeMillis="); builder.append(minEvictableIdleDuration); builder.append(", maxPreparedStatements="); builder.append(maxPreparedStatements); builder.append(", getConnectionCalled="); builder.append(getConnectionCalled); builder.append(", connectionProperties="); builder.append(Utils.cloneWithoutCredentials(connectionProperties)); builder.append(", accessToUnderlyingConnectionAllowed="); builder.append(accessToUnderlyingConnectionAllowed); builder.append("]"); return builder.toString(); } private void update(final Properties properties, final String key, final String value) { if (properties != null && key != null) { if (value == null) { properties.remove(key); } else { properties.setProperty(key, value); } } } } PStmtKeyCPDS.java000066400000000000000000000103541472045345700337140ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.cpdsadapter; import java.sql.PreparedStatement; import org.apache.commons.dbcp2.PStmtKey; /** * A key uniquely identifying a {@link PreparedStatement}. * * @since 2.0 * @deprecated Use {@link PStmtKey}. */ @Deprecated public class PStmtKeyCPDS extends PStmtKey { /** * Constructs a key to uniquely identify a prepared statement. * * @param sql * The SQL statement. */ public PStmtKeyCPDS(final String sql) { super(sql); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql * The SQL statement. * @param autoGeneratedKeys * A flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. */ public PStmtKeyCPDS(final String sql, final int autoGeneratedKeys) { super(sql, null, autoGeneratedKeys); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql * The SQL statement. * @param resultSetType * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. */ public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency) { super(sql, resultSetType, resultSetConcurrency); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql * The SQL statement. * @param resultSetType * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE} * @param resultSetHoldability * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. */ public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { super(sql, null, resultSetType, resultSetConcurrency, resultSetHoldability); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql * The SQL statement. * @param columnIndexes * An array of column indexes indicating the columns that should be returned from the inserted row or * rows. */ public PStmtKeyCPDS(final String sql, final int[] columnIndexes) { super(sql, null, columnIndexes); } /** * Constructs a key to uniquely identify a prepared statement. * * @param sql * The SQL statement. * @param columnNames * An array of column names indicating the columns that should be returned from the inserted row or rows. */ public PStmtKeyCPDS(final String sql, final String[] columnNames) { super(sql, null, columnNames); } } PooledConnectionImpl.java000066400000000000000000000761621472045345700356170ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.cpdsadapter; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.PooledConnection; import javax.sql.StatementEventListener; import org.apache.commons.dbcp2.DelegatingConnection; import org.apache.commons.dbcp2.DelegatingPreparedStatement; import org.apache.commons.dbcp2.Jdbc41Bridge; import org.apache.commons.dbcp2.PStmtKey; import org.apache.commons.dbcp2.PoolableCallableStatement; import org.apache.commons.dbcp2.PoolablePreparedStatement; import org.apache.commons.dbcp2.PoolingConnection.StatementType; import org.apache.commons.dbcp2.Utils; import org.apache.commons.pool2.KeyedObjectPool; import org.apache.commons.pool2.KeyedPooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; /** * Implements {@link PooledConnection} that is returned by {@link DriverAdapterCPDS}. * * @since 2.0 */ final class PooledConnectionImpl implements PooledConnection, KeyedPooledObjectFactory { private static final String CLOSED = "Attempted to use PooledConnection after closed() was called."; /** * The JDBC database connection that represents the physical db connection. */ private Connection connection; /** * A DelegatingConnection used to create a PoolablePreparedStatementStub. */ private final DelegatingConnection delegatingConnection; /** * The JDBC database logical connection. */ private Connection logicalConnection; /** * ConnectionEventListeners. */ private final List eventListeners; /** * StatementEventListeners. */ private final List statementEventListeners = Collections.synchronizedList(new ArrayList<>()); /** * Flag set to true, once {@link #close()} is called. */ private boolean closed; /** My pool of {@link PreparedStatement}s. */ private KeyedObjectPool pStmtPool; /** * Controls access to the underlying connection. */ private boolean accessToUnderlyingConnectionAllowed; /** * Wraps a real connection. * * @param connection * the connection to be wrapped. */ PooledConnectionImpl(final Connection connection) { this.connection = connection; if (connection instanceof DelegatingConnection) { this.delegatingConnection = (DelegatingConnection) connection; } else { this.delegatingConnection = new DelegatingConnection<>(connection); } eventListeners = Collections.synchronizedList(new ArrayList<>()); closed = false; } /** * My {@link KeyedPooledObjectFactory} method for activating {@link PreparedStatement}s. * * @param pooledObject Activates the underlying object. */ @Override public void activateObject(final PStmtKey key, final PooledObject pooledObject) throws SQLException { pooledObject.getObject().activate(); } /** * {@inheritDoc} */ @Override public void addConnectionEventListener(final ConnectionEventListener listener) { if (!eventListeners.contains(listener)) { eventListeners.add(listener); } } @Override public void addStatementEventListener(final StatementEventListener listener) { if (!statementEventListeners.contains(listener)) { statementEventListeners.add(listener); } } /** * Throws an SQLException, if isClosed is true */ private void assertOpen() throws SQLException { if (closed || connection == null) { throw new SQLException(CLOSED); } } /** * Closes the physical connection and marks this {@code PooledConnection} so that it may not be used to * generate any more logical {@code Connection}s. * * @throws SQLException * Thrown when an error occurs or the connection is already closed. */ @Override public void close() throws SQLException { assertOpen(); closed = true; try { if (pStmtPool != null) { try { pStmtPool.close(); } finally { pStmtPool = null; } } } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot close connection (return to pool failed)", e); } finally { try { connection.close(); } finally { connection = null; } } } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @return a {@link PStmtKey} for the given arguments. */ protected PStmtKey createKey(final String sql) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull()); } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @param autoGeneratedKeys * A flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final int autoGeneratedKeys) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), autoGeneratedKeys); } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @param resultSetType * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency); } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @param resultSetType * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE} * @param resultSetHoldability * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, resultSetHoldability); } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @param resultSetType * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE} * @param resultSetConcurrency * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @param resultSetHoldability * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * @param statementType * The SQL statement type, prepared or callable. * @return a key to uniquely identify a prepared statement. * @since 2.4.0 */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final StatementType statementType) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, resultSetHoldability, statementType); } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @param resultSetType * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @param statementType * The SQL statement type, prepared or callable. * @return a key to uniquely identify a prepared statement. * @since 2.4.0 */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final StatementType statementType) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, statementType); } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @param columnIndexes * An array of column indexes indicating the columns that should be returned from the inserted row or * rows. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final int[] columnIndexes) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), columnIndexes); } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @param statementType * The SQL statement type, prepared or callable. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final StatementType statementType) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), statementType); } /** * Creates a {@link PStmtKey} for the given arguments. * * @param sql * The SQL statement. * @param columnNames * An array of column names indicating the columns that should be returned from the inserted row or rows. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final String[] columnNames) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), columnNames); } /** * My {@link KeyedPooledObjectFactory} method for destroying {@link PreparedStatement}s. * * @param key * ignored * @param pooledObject * the wrapped {@link PreparedStatement} to be destroyed. */ @Override public void destroyObject(final PStmtKey key, final PooledObject pooledObject) throws SQLException { if (pooledObject != null) { @SuppressWarnings("resource") final DelegatingPreparedStatement object = pooledObject.getObject(); if (object != null) { @SuppressWarnings("resource") final Statement innermostDelegate = object.getInnermostDelegate(); if (innermostDelegate != null) { innermostDelegate.close(); } } } } /** * Closes the physical connection and checks that the logical connection was closed as well. */ @Override protected void finalize() throws Throwable { // Closing the Connection ensures that if anyone tries to use it, // an error will occur. Utils.close(connection, null); // make sure the last connection is marked as closed if (logicalConnection != null && !logicalConnection.isClosed()) { throw new SQLException("PooledConnection was gc'ed, without its last Connection being closed."); } } private String getCatalogOrNull() { try { return connection == null ? null : connection.getCatalog(); } catch (final SQLException e) { return null; } } /** * Returns a JDBC connection. * * @return The database connection. * @throws SQLException * if the connection is not open or the previous logical connection is still open */ @Override public Connection getConnection() throws SQLException { assertOpen(); // make sure the last connection is marked as closed if (logicalConnection != null && !logicalConnection.isClosed()) { // should notify pool of error so the pooled connection can // be removed !FIXME! throw new SQLException("PooledConnection was reused, without its previous Connection being closed."); } // the spec requires that this return a new Connection instance. logicalConnection = new ConnectionImpl(this, connection, isAccessToUnderlyingConnectionAllowed()); return logicalConnection; } private Connection getRawConnection() throws SQLException { assertOpen(); return connection; } private String getSchemaOrNull() { try { return connection == null ? null : Jdbc41Bridge.getSchema(connection); } catch (final SQLException e) { return null; } } /** * Returns the value of the accessToUnderlyingConnectionAllowed property. * * @return true if access to the underlying is allowed, false otherwise. */ public synchronized boolean isAccessToUnderlyingConnectionAllowed() { return this.accessToUnderlyingConnectionAllowed; } /** * My {@link KeyedPooledObjectFactory} method for creating {@link PreparedStatement}s. * * @param key * The key for the {@link PreparedStatement} to be created. */ @SuppressWarnings("resource") @Override public PooledObject makeObject(final PStmtKey key) throws SQLException { if (null == key) { throw new IllegalArgumentException("Prepared statement key is null or invalid."); } if (key.getStmtType() == StatementType.PREPARED_STATEMENT) { final PreparedStatement statement = (PreparedStatement) key.createStatement(connection); @SuppressWarnings({"rawtypes", "unchecked" }) // Unable to find way to avoid this final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, pStmtPool, delegatingConnection); return new DefaultPooledObject<>(pps); } final CallableStatement statement = (CallableStatement) key.createStatement(connection); @SuppressWarnings("unchecked") final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, pStmtPool, (DelegatingConnection) delegatingConnection); return new DefaultPooledObject<>(pcs); } /** * Sends a connectionClosed event. */ void notifyListeners() { final ConnectionEvent event = new ConnectionEvent(this); new ArrayList<>(eventListeners).forEach(listener -> listener.connectionClosed(event)); } /** * My {@link KeyedPooledObjectFactory} method for passivating {@link PreparedStatement}s. Currently, invokes * {@link PreparedStatement#clearParameters}. * * @param key * ignored * @param pooledObject * a wrapped {@link PreparedStatement} */ @Override public void passivateObject(final PStmtKey key, final PooledObject pooledObject) throws SQLException { @SuppressWarnings("resource") final DelegatingPreparedStatement dps = pooledObject.getObject(); dps.clearParameters(); dps.passivate(); } /** * Creates or obtains a {@link CallableStatement} from my pool. * * @param sql * an SQL statement that may contain one or more '?' parameter placeholders. Typically, this statement is * specified using JDBC call escape syntax. * @return a default {@code CallableStatement} object containing the pre-compiled SQL statement. * @throws SQLException * Thrown if a database access error occurs or this method is called on a closed connection. * @since 2.4.0 */ @SuppressWarnings("resource") // getRawConnection() does not allocate CallableStatement prepareCall(final String sql) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareCall(sql); } try { return (CallableStatement) pStmtPool.borrowObject(createKey(sql, StatementType.CALLABLE_STATEMENT)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareCall from pool failed", e); } } /** * Creates or obtains a {@link CallableStatement} from my pool. * * @param sql * a {@code String} object that is the SQL statement to be sent to the database; may contain on or * more '?' parameters. * @param resultSetType * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @return a {@code CallableStatement} object containing the pre-compiled SQL statement that will produce * {@code ResultSet} objects with the given type and concurrency. * @throws SQLException * Thrown if a database access error occurs, this method is called on a closed connection or the given * parameters are not {@code ResultSet} constants indicating type and concurrency. * @since 2.4.0 */ @SuppressWarnings("resource") // getRawConnection() does not allocate CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareCall(sql, resultSetType, resultSetConcurrency); } try { return (CallableStatement) pStmtPool.borrowObject( createKey(sql, resultSetType, resultSetConcurrency, StatementType.CALLABLE_STATEMENT)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareCall from pool failed", e); } } /** * Creates or obtains a {@link CallableStatement} from my pool. * * @param sql * a {@code String} object that is the SQL statement to be sent to the database; may contain on or * more '?' parameters. * @param resultSetType * one of the following {@code ResultSet} constants: {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * one of the following {@code ResultSet} constants: {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * @param resultSetHoldability * one of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. * @return a new {@code CallableStatement} object, containing the pre-compiled SQL statement, that will * generate {@code ResultSet} objects with the given type, concurrency, and holdability. * @throws SQLException * Thrown if a database access error occurs, this method is called on a closed connection or the given * parameters are not {@code ResultSet} constants indicating type, concurrency, and holdability. * @since 2.4.0 */ @SuppressWarnings("resource") // getRawConnection() does not allocate CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } try { return (CallableStatement) pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.CALLABLE_STATEMENT)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareCall from pool failed", e); } } /** * Creates or obtains a {@link PreparedStatement} from my pool. * * @param sql the SQL statement. * @return a {@link PoolablePreparedStatement} * @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or * the borrow failed. */ @SuppressWarnings("resource") // getRawConnection() does not allocate PreparedStatement prepareStatement(final String sql) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareStatement(sql); } try { return pStmtPool.borrowObject(createKey(sql)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareStatement from pool failed", e); } } /** * Creates or obtains a {@link PreparedStatement} from my pool. * * @param sql * an SQL statement that may contain one or more '?' IN parameter placeholders. * @param autoGeneratedKeys * a flag indicating whether auto-generated keys should be returned; one of * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. * @return a {@link PoolablePreparedStatement} * @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or * the borrow failed. * @see Connection#prepareStatement(String, int) */ @SuppressWarnings("resource") // getRawConnection() does not allocate PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareStatement(sql, autoGeneratedKeys); } try { return pStmtPool.borrowObject(createKey(sql, autoGeneratedKeys)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareStatement from pool failed", e); } } /** * Creates or obtains a {@link PreparedStatement} from my pool. * * @param sql * a {@code String} object that is the SQL statement to be sent to the database; may contain one or * more '?' IN parameters. * @param resultSetType * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or * {@code ResultSet.CONCUR_UPDATABLE}. * * @return a {@link PoolablePreparedStatement}. * @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or * the borrow failed. * @see Connection#prepareStatement(String, int, int) */ @SuppressWarnings("resource") // getRawConnection() does not allocate PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareStatement(sql, resultSetType, resultSetConcurrency); } try { return pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareStatement from pool failed", e); } } @SuppressWarnings("resource") // getRawConnection() does not allocate PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } try { return pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareStatement from pool failed", e); } } @SuppressWarnings("resource") // getRawConnection() does not allocate PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareStatement(sql, columnIndexes); } try { return pStmtPool.borrowObject(createKey(sql, columnIndexes)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareStatement from pool failed", e); } } @SuppressWarnings("resource") // getRawConnection() does not allocate PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { if (pStmtPool == null) { return getRawConnection().prepareStatement(sql, columnNames); } try { return pStmtPool.borrowObject(createKey(sql, columnNames)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Borrow prepareStatement from pool failed", e); } } /** * {@inheritDoc} */ @Override public void removeConnectionEventListener(final ConnectionEventListener listener) { eventListeners.remove(listener); } @Override public void removeStatementEventListener(final StatementEventListener listener) { statementEventListeners.remove(listener); } /** * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to * the underlying connection. (Default: false.) * * @param allow * Access to the underlying connection is granted when true. */ public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) { this.accessToUnderlyingConnectionAllowed = allow; } public void setStatementPool(final KeyedObjectPool statementPool) { pStmtPool = statementPool; } /** * @since 2.6.0 */ @Override public synchronized String toString() { final StringBuilder builder = new StringBuilder(super.toString()); builder.append("[connection="); builder.append(connection); builder.append(", delegatingConnection="); builder.append(delegatingConnection); builder.append(", logicalConnection="); builder.append(logicalConnection); builder.append(", eventListeners="); builder.append(eventListeners); builder.append(", statementEventListeners="); builder.append(statementEventListeners); builder.append(", closed="); builder.append(closed); builder.append(", pStmtPool="); builder.append(pStmtPool); builder.append(", accessToUnderlyingConnectionAllowed="); builder.append(accessToUnderlyingConnectionAllowed); builder.append("]"); return builder.toString(); } /** * My {@link KeyedPooledObjectFactory} method for validating {@link PreparedStatement}s. * * @param key * Ignored. * @param pooledObject * Ignored. * @return {@code true} */ @Override public boolean validateObject(final PStmtKey key, final PooledObject pooledObject) { return true; } } package-info.java000066400000000000000000000057401472045345700340510ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/* * 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. */ /** *

* This package contains one public class which is a * {@code ConnectionPoolDataSource} (CPDS) implementation that can be used to * adapt older {@code Driver} based JDBC implementations. Below is an * example of setting up the CPDS to be available via JNDI in the * catalina servlet container. *

*

In server.xml, the following would be added to the <Context> for your * webapp: *

* *
 *  <Resource name="jdbc/bookstoreCPDS" auth="Container"
 *             type="org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS"/>
 *   <ResourceParams name="jdbc/bookstoreCPDS">
 *     <parameter>
 *       <name>factory</name>
 *       <value>org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS</value>
 *     </parameter>
 *     <parameter><name>user</name><value>root</value></parameter>
 *     <parameter><name>password</name><value></value></parameter>
 *     <parameter>
 *       <name>driver</name>
 *       <value>org.gjt.mm.mysql.Driver</value></parameter>
 *     <parameter>
 *       <name>url</name>
 *       <value>jdbc:mysql://localhost:3306/bookstore</value>
 *     </parameter>
 *   </ResourceParams>
 * 
* *

* In web.xml. Note that elements must be given in the order of the dtd * described in the servlet specification: *

* *
 * <resource-ref>
 *   <description>
 *     Resource reference to a factory for java.sql.Connection
 *     instances that may be used for talking to a particular
 *     database that is configured in the server.xml file.
 *   </description>
 *   <res-ref-name>
 *     jdbc/bookstoreCPDS
 *   </res-ref-name>
 *   <res-type>
 *     org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS
 *   </res-type>
 *   <res-auth>
 *     Container
 *   </res-auth>
 * </resource-ref>
 * 
* *

* Catalina deploys all objects configured similarly to above within the * java:comp/env namespace. *

*/ package org.apache.commons.dbcp2.cpdsadapter; commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/000077500000000000000000000000001472045345700307565ustar00rootroot00000000000000CPDSConnectionFactory.java000066400000000000000000000476321472045345700356570ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import org.apache.commons.dbcp2.Utils; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; /** * A {@link PooledObjectFactory} that creates {@link org.apache.commons.dbcp2.PoolableConnection PoolableConnection}s. * * @since 2.0 */ final class CPDSConnectionFactory implements PooledObjectFactory, ConnectionEventListener, PooledConnectionManager { private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but I have no record of the underlying PooledConnection."; private final ConnectionPoolDataSource cpds; private final String validationQuery; private final Duration validationQueryTimeoutDuration; private final boolean rollbackAfterValidation; private ObjectPool pool; private UserPassKey userPassKey; private Duration maxConnDuration = Duration.ofMillis(-1); /** * Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated. */ private final Set validatingSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); /** * Map of PooledConnectionAndInfo instances */ private final Map pcMap = new ConcurrentHashMap<>(); /** * Creates a new {@code PoolableConnectionFactory}. * * @param cpds * the ConnectionPoolDataSource from which to obtain PooledConnection's * @param validationQuery * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one * row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate * connections. * @param validationQueryTimeoutDuration * Timeout Duration before validation fails * @param rollbackAfterValidation * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. * @param userName * The user name to use to create connections * @param userPassword * The password to use to create connections * @since 2.10.0 */ public CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final Duration validationQueryTimeoutDuration, final boolean rollbackAfterValidation, final String userName, final char[] userPassword) { this.cpds = cpds; this.validationQuery = validationQuery; this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; this.userPassKey = new UserPassKey(userName, userPassword); this.rollbackAfterValidation = rollbackAfterValidation; } /** * Creates a new {@code PoolableConnectionFactory}. * * @param cpds * the ConnectionPoolDataSource from which to obtain PooledConnection's * @param validationQuery * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one * row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate * connections. * @param validationQueryTimeoutDuration * Timeout in seconds before validation fails * @param rollbackAfterValidation * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. * @param userName * The user name to use to create connections * @param userPassword * The password to use to create connections * @since 2.10.0 */ public CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final Duration validationQueryTimeoutDuration, final boolean rollbackAfterValidation, final String userName, final String userPassword) { this(cpds, validationQuery, validationQueryTimeoutDuration, rollbackAfterValidation, userName, Utils.toCharArray(userPassword)); } /** * Creates a new {@code PoolableConnectionFactory}. * * @param cpds * the ConnectionPoolDataSource from which to obtain PooledConnection's * @param validationQuery * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one * row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate * connections. * @param validationQueryTimeoutSeconds * Timeout in seconds before validation fails * @param rollbackAfterValidation * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. * @param userName * The user name to use to create connections * @param userPassword * The password to use to create connections * @since 2.4.0 * @deprecated Use {@link #CPDSConnectionFactory(ConnectionPoolDataSource, String, Duration, boolean, String, char[])}. */ @Deprecated public CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation, final String userName, final char[] userPassword) { this.cpds = cpds; this.validationQuery = validationQuery; this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); this.userPassKey = new UserPassKey(userName, userPassword); this.rollbackAfterValidation = rollbackAfterValidation; } /** * Creates a new {@code PoolableConnectionFactory}. * * @param cpds * the ConnectionPoolDataSource from which to obtain PooledConnection's * @param validationQuery * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one * row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate * connections. * @param validationQueryTimeoutSeconds * Timeout in seconds before validation fails * @param rollbackAfterValidation * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. * @param userName * The user name to use to create connections * @param userPassword * The password to use to create connections * @deprecated Use {@link #CPDSConnectionFactory(ConnectionPoolDataSource, String, Duration, boolean, String, String)}. */ @Deprecated public CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation, final String userName, final String userPassword) { this(cpds, validationQuery, validationQueryTimeoutSeconds, rollbackAfterValidation, userName, Utils.toCharArray(userPassword)); } @Override public void activateObject(final PooledObject p) throws SQLException { validateLifetime(p); } /** * Verifies that the user name matches the user whose connections are being managed by this factory and closes the * pool if this is the case; otherwise does nothing. */ @Override public void closePool(final String userName) throws SQLException { synchronized (this) { if (userName == null || !userName.equals(this.userPassKey.getUserName())) { return; } } try { pool.close(); } catch (final Exception ex) { throw new SQLException("Error closing connection pool", ex); } } /** * This will be called if the Connection returned by the getConnection method came from a PooledConnection, and the * user calls the close() method of this connection object. What we need to do here is to release this * PooledConnection from our pool... */ @Override public void connectionClosed(final ConnectionEvent event) { final PooledConnection pc = (PooledConnection) event.getSource(); // if this event occurred because we were validating, ignore it // otherwise return the connection to the pool. if (!validatingSet.contains(pc)) { final PooledConnectionAndInfo pci = pcMap.get(pc); if (pci == null) { throw new IllegalStateException(NO_KEY_MESSAGE); } try { pool.returnObject(pci); } catch (final Exception e) { System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + "NOT BE RETURNED TO THE POOL"); pc.removeConnectionEventListener(this); try { doDestroyObject(pci); } catch (final Exception e2) { System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + pci); e2.printStackTrace(); } } } } /** * If a fatal error occurs, close the underlying physical connection so as not to be returned in the future */ @Override public void connectionErrorOccurred(final ConnectionEvent event) { final PooledConnection pc = (PooledConnection) event.getSource(); if (null != event.getSQLException()) { System.err.println("CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR (" + event.getSQLException() + ")"); } pc.removeConnectionEventListener(this); final PooledConnectionAndInfo pci = pcMap.get(pc); if (pci == null) { throw new IllegalStateException(NO_KEY_MESSAGE); } try { pool.invalidateObject(pci); } catch (final Exception e) { System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + pci); e.printStackTrace(); } } /** * Closes the PooledConnection and stops listening for events from it. */ @Override public void destroyObject(final PooledObject p) throws SQLException { doDestroyObject(p.getObject()); } private void doDestroyObject(final PooledConnectionAndInfo pci) throws SQLException { final PooledConnection pc = pci.getPooledConnection(); pc.removeConnectionEventListener(this); pcMap.remove(pc); pc.close(); } /** * (Testing API) Gets the value of password for the default user. * * @return value of password. */ char[] getPasswordCharArray() { return userPassKey.getPasswordCharArray(); } /** * Returns the object pool used to pool connections created by this factory. * * @return ObjectPool managing pooled connections */ public ObjectPool getPool() { return pool; } /** * Invalidates the PooledConnection in the pool. The CPDSConnectionFactory closes the connection and pool counters * are updated appropriately. Also closes the pool. This ensures that all idle connections are closed and * connections that are checked out are closed on return. */ @Override public void invalidate(final PooledConnection pc) throws SQLException { final PooledConnectionAndInfo pci = pcMap.get(pc); if (pci == null) { throw new IllegalStateException(NO_KEY_MESSAGE); } try { pool.invalidateObject(pci); // Destroy instance and update pool counters pool.close(); // Clear any other instances in this pool and kill others as they come back } catch (final Exception ex) { throw new SQLException("Error invalidating connection", ex); } } @Override public synchronized PooledObject makeObject() throws SQLException { PooledConnection pc = null; if (userPassKey.getUserName() == null) { pc = cpds.getPooledConnection(); } else { pc = cpds.getPooledConnection(userPassKey.getUserName(), userPassKey.getPassword()); } if (pc == null) { throw new IllegalStateException("Connection pool data source returned null from getPooledConnection"); } // should we add this object as a listener or the pool. // consider the validateObject method in decision pc.addConnectionEventListener(this); final PooledConnectionAndInfo pci = new PooledConnectionAndInfo(pc, userPassKey); pcMap.put(pc, pci); return new DefaultPooledObject<>(pci); } @Override public void passivateObject(final PooledObject p) throws SQLException { validateLifetime(p); } /** * Sets the maximum Duration of a connection after which the connection will always fail activation, * passivation and validation. * * @param maxConnDuration * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. * @since 2.10.0 */ public void setMaxConn(final Duration maxConnDuration) { this.maxConnDuration = maxConnDuration; } /** * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, * passivation and validation. * * @param maxConnDuration * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. * @since 2.9.0 * @deprecated Use {@link #setMaxConn(Duration)}. */ @Deprecated public void setMaxConnLifetime(final Duration maxConnDuration) { this.maxConnDuration = maxConnDuration; } /** * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, * passivation and validation. * * @param maxConnLifetimeMillis * A value of zero or less indicates an infinite lifetime. The default value is -1. * @deprecated Use {@link #setMaxConn(Duration)}. */ @Deprecated public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { setMaxConnLifetime(Duration.ofMillis(maxConnLifetimeMillis)); } /** * Sets the database password used when creating new connections. * * @param userPassword * new password */ public synchronized void setPassword(final char[] userPassword) { this.userPassKey = new UserPassKey(userPassKey.getUserName(), userPassword); } /** * Sets the database password used when creating new connections. * * @param userPassword * new password */ @Override public synchronized void setPassword(final String userPassword) { this.userPassKey = new UserPassKey(userPassKey.getUserName(), userPassword); } /** * * @param pool * the {@link ObjectPool} in which to pool those {@link Connection}s */ public void setPool(final ObjectPool pool) { this.pool = pool; } /** * @since 2.6.0 */ @Override public synchronized String toString() { final StringBuilder builder = new StringBuilder(super.toString()); builder.append("[cpds="); builder.append(cpds); builder.append(", validationQuery="); builder.append(validationQuery); builder.append(", validationQueryTimeoutDuration="); builder.append(validationQueryTimeoutDuration); builder.append(", rollbackAfterValidation="); builder.append(rollbackAfterValidation); builder.append(", pool="); builder.append(pool); builder.append(", maxConnDuration="); builder.append(maxConnDuration); builder.append(", validatingSet="); builder.append(validatingSet); builder.append(", pcMap="); builder.append(pcMap); builder.append("]"); return builder.toString(); } private void validateLifetime(final PooledObject p) throws SQLException { Utils.validateLifetime(p, maxConnDuration); } @Override public boolean validateObject(final PooledObject p) { try { validateLifetime(p); } catch (final Exception e) { return false; } boolean valid = false; final PooledConnection pconn = p.getObject().getPooledConnection(); Connection conn = null; validatingSet.add(pconn); if (null == validationQuery) { Duration timeoutDuration = validationQueryTimeoutDuration; if (timeoutDuration.isNegative()) { timeoutDuration = Duration.ZERO; } try { conn = pconn.getConnection(); valid = conn.isValid((int) timeoutDuration.getSeconds()); } catch (final SQLException e) { valid = false; } finally { Utils.closeQuietly((AutoCloseable) conn); validatingSet.remove(pconn); } } else { Statement stmt = null; ResultSet rset = null; // logical Connection from the PooledConnection must be closed // before another one can be requested and closing it will // generate an event. Keep track so we know not to return // the PooledConnection validatingSet.add(pconn); try { conn = pconn.getConnection(); stmt = conn.createStatement(); rset = stmt.executeQuery(validationQuery); valid = rset.next(); if (rollbackAfterValidation) { conn.rollback(); } } catch (final Exception e) { valid = false; } finally { Utils.closeQuietly((AutoCloseable) rset); Utils.closeQuietly((AutoCloseable) stmt); Utils.closeQuietly((AutoCloseable) conn); validatingSet.remove(pconn); } } return valid; } } CharArray.java000066400000000000000000000045201472045345700334170ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.Serializable; import java.util.Arrays; import org.apache.commons.dbcp2.Utils; /** * A {@code char} array wrapper that does not reveal its contents inadvertently through toString(). In contrast to, for * example, AtomicReference which toString()'s its contents. * * May contain null. * * @since 2.9.0 */ final class CharArray implements Serializable { private static final long serialVersionUID = 1L; static final CharArray NULL = new CharArray((char[]) null); private final char[] chars; CharArray(final char[] chars) { this.chars = Utils.clone(chars); } CharArray(final String string) { this.chars = Utils.toCharArray(string); } /** * Converts the value of char array as a String. * * @return value as a string, may be null. */ String asString() { return Utils.toString(chars); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof CharArray)) { return false; } final CharArray other = (CharArray) obj; return Arrays.equals(chars, other.chars); } /** * Gets the value of char array. * * @return value, may be null. */ char[] get() { return Utils.clone(chars); } @Override public int hashCode() { return Arrays.hashCode(chars); } } InstanceKeyDataSource.java000066400000000000000000001542371472045345700357460ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.time.Duration; import java.util.Properties; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Referenceable; import javax.sql.ConnectionPoolDataSource; import javax.sql.DataSource; import javax.sql.PooledConnection; import org.apache.commons.dbcp2.Utils; import org.apache.commons.pool2.impl.BaseObjectPoolConfig; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; import org.apache.commons.pool2.impl.GenericObjectPool; /** *

* The base class for {@code SharedPoolDataSource} and {@code PerUserPoolDataSource}. Many of the * configuration properties are shared and defined here. This class is declared public in order to allow particular * usage with commons-beanutils; do not make direct use of it outside of commons-dbcp2. *

* *

* A J2EE container will normally provide some method of initializing the {@code DataSource} whose attributes are * presented as bean getters/setters and then deploying it via JNDI. It is then available to an application as a source * of pooled logical connections to the database. The pool needs a source of physical connections. This source is in the * form of a {@code ConnectionPoolDataSource} that can be specified via the {@link #setDataSourceName(String)} used * to lookup the source via JNDI. *

* *

* Although normally used within a JNDI environment, A DataSource can be instantiated and initialized as any bean. In * this case the {@code ConnectionPoolDataSource} will likely be instantiated in a similar manner. This class * allows the physical source of connections to be attached directly to this pool using the * {@link #setConnectionPoolDataSource(ConnectionPoolDataSource)} method. *

* *

* The dbcp package contains an adapter, {@link org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS}, that can be * used to allow the use of {@code DataSource}'s based on this class with JDBC driver implementations that do not * supply a {@code ConnectionPoolDataSource}, but still provide a {@link java.sql.Driver} implementation. *

* *

* The package documentation contains an example using Apache Tomcat and JNDI and it * also contains a non-JNDI example. *

* * @since 2.0 */ public abstract class InstanceKeyDataSource implements DataSource, Referenceable, Serializable, AutoCloseable { private static final long serialVersionUID = -6819270431752240878L; private static final String GET_CONNECTION_CALLED = "A Connection was already requested from this source, " + "further initialization is not allowed."; private static final String BAD_TRANSACTION_ISOLATION = "The requested TransactionIsolation level is invalid."; /** * Internal constant to indicate the level is not set. */ protected static final int UNKNOWN_TRANSACTIONISOLATION = -1; /** Guards property setters - once true, setters throw IllegalStateException */ private volatile boolean getConnectionCalled; /** Underlying source of PooledConnections */ private ConnectionPoolDataSource dataSource; /** DataSource Name used to find the ConnectionPoolDataSource */ private String dataSourceName; /** Description */ private String description; /** Environment that may be used to set up a JNDI initial context. */ private Properties jndiEnvironment; /** Login Timeout */ private Duration loginTimeoutDuration = Duration.ZERO; /** Log stream */ private PrintWriter logWriter; /** Instance key */ private String instanceKey; // Pool properties private boolean defaultBlockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; private String defaultEvictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME; private boolean defaultLifo = BaseObjectPoolConfig.DEFAULT_LIFO; private int defaultMaxIdle = GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY; private int defaultMaxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; private Duration defaultMaxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT; private Duration defaultMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION; private int defaultMinIdle = GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY; private int defaultNumTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; private Duration defaultSoftMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION; private boolean defaultTestOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE; private boolean defaultTestOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW; private boolean defaultTestOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN; private boolean defaultTestWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE; private Duration defaultDurationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS; // Connection factory properties private String validationQuery; private Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1); private boolean rollbackAfterValidation; private Duration maxConnDuration = Duration.ofMillis(-1); // Connection properties private Boolean defaultAutoCommit; private int defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION; private Boolean defaultReadOnly; /** * Default no-arg constructor for Serialization. */ public InstanceKeyDataSource() { } /** * Throws an IllegalStateException, if a PooledConnection has already been requested. * * @throws IllegalStateException Thrown if a PooledConnection has already been requested. */ protected void assertInitializationAllowed() throws IllegalStateException { if (getConnectionCalled) { throw new IllegalStateException(GET_CONNECTION_CALLED); } } /** * Closes the connection pool being maintained by this datasource. */ @Override public abstract void close() throws SQLException; private void closeDueToException(final PooledConnectionAndInfo info) { if (info != null) { try { info.getPooledConnection().getConnection().close(); } catch (final Exception e) { // do not throw this exception because we are in the middle // of handling another exception. But record it because // it potentially leaks connections from the pool. getLogWriter().println("[ERROR] Could not return connection to pool during exception handling. " + e.getMessage()); } } } /** * Attempts to establish a database connection. */ @Override public Connection getConnection() throws SQLException { return getConnection(null, null); } /** * Attempts to retrieve a database connection using {@link #getPooledConnectionAndInfo(String, String)} with the * provided user name and password. The password on the {@code PooledConnectionAndInfo} instance returned by * {@code getPooledConnectionAndInfo} is compared to the {@code password} parameter. If the comparison * fails, a database connection using the supplied user name and password is attempted. If the connection attempt * fails, an SQLException is thrown, indicating that the given password did not match the password used to create * the pooled connection. If the connection attempt succeeds, this means that the database password has been * changed. In this case, the {@code PooledConnectionAndInfo} instance retrieved with the old password is * destroyed and the {@code getPooledConnectionAndInfo} is repeatedly invoked until a * {@code PooledConnectionAndInfo} instance with the new password is returned. */ @Override public Connection getConnection(final String userName, final String userPassword) throws SQLException { if (instanceKey == null) { throw new SQLException("Must set the ConnectionPoolDataSource " + "through setDataSourceName or setConnectionPoolDataSource" + " before calling getConnection."); } getConnectionCalled = true; PooledConnectionAndInfo info = null; try { info = getPooledConnectionAndInfo(userName, userPassword); } catch (final RuntimeException | SQLException e) { closeDueToException(info); throw e; } catch (final Exception e) { closeDueToException(info); throw new SQLException("Cannot borrow connection from pool", e); } // Password on PooledConnectionAndInfo does not match if (!(null == userPassword ? null == info.getPassword() : userPassword.equals(info.getPassword()))) { try { // See if password has changed by attempting connection testCPDS(userName, userPassword); } catch (final SQLException ex) { // Password has not changed, so refuse client, but return connection to the pool closeDueToException(info); throw new SQLException( "Given password did not match password used" + " to create the PooledConnection.", ex); } catch (final javax.naming.NamingException ne) { throw new SQLException("NamingException encountered connecting to database", ne); } /* * Password must have changed -> destroy connection and keep retrying until we get a new, good one, * destroying any idle connections with the old password as we pull them from the pool. */ final UserPassKey upkey = info.getUserPassKey(); final PooledConnectionManager manager = getConnectionManager(upkey); // Destroy and remove from pool manager.invalidate(info.getPooledConnection()); // Reset the password on the factory if using CPDSConnectionFactory manager.setPassword(upkey.getPassword()); info = null; for (int i = 0; i < 10; i++) { // Bound the number of retries - only needed if bad instances return try { info = getPooledConnectionAndInfo(userName, userPassword); } catch (final RuntimeException | SQLException e) { closeDueToException(info); throw e; } catch (final Exception e) { closeDueToException(info); throw new SQLException("Cannot borrow connection from pool", e); } if (info != null && userPassword != null && userPassword.equals(info.getPassword())) { break; } if (info != null) { manager.invalidate(info.getPooledConnection()); } info = null; } if (info == null) { throw new SQLException("Cannot borrow connection from pool - password change failure."); } } final Connection connection = info.getPooledConnection().getConnection(); try { setupDefaults(connection, userName); connection.clearWarnings(); return connection; } catch (final SQLException ex) { Utils.close(connection, e -> getLogWriter().println("ignoring exception during close: " + e)); throw ex; } } protected abstract PooledConnectionManager getConnectionManager(UserPassKey upkey); /** * Gets the value of connectionPoolDataSource. This method will return null, if the backing data source is being * accessed via JNDI. * * @return value of connectionPoolDataSource. */ public ConnectionPoolDataSource getConnectionPoolDataSource() { return dataSource; } /** * Gets the name of the ConnectionPoolDataSource which backs this pool. This name is used to look up the data source * from a JNDI service provider. * * @return value of dataSourceName. */ public String getDataSourceName() { return dataSourceName; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getBlockWhenExhausted()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getBlockWhenExhausted()} for each per user * pool. */ public boolean getDefaultBlockWhenExhausted() { return this.defaultBlockWhenExhausted; } /** * Gets the default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for each per user pool. * * @return The default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for each per user pool. * @since 2.10.0 */ public Duration getDefaultDurationBetweenEvictionRuns() { return this.defaultDurationBetweenEvictionRuns; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for each per user * pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for each per user * pool. */ public String getDefaultEvictionPolicyClassName() { return this.defaultEvictionPolicyClassName; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. */ public boolean getDefaultLifo() { return this.defaultLifo; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user pool. */ public int getDefaultMaxIdle() { return this.defaultMaxIdle; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per user pool. */ public int getDefaultMaxTotal() { return this.defaultMaxTotal; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. * @since 2.9.0 */ public Duration getDefaultMaxWait() { return this.defaultMaxWaitDuration; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. * @deprecated Use {@link #getDefaultMaxWait()}. */ @Deprecated public long getDefaultMaxWaitMillis() { return getDefaultMaxWait().toMillis(); } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per user * pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per * user pool. * @since 2.10.0 */ public Duration getDefaultMinEvictableIdleDuration() { return this.defaultMinEvictableIdleDuration; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per user * pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per * user pool. * @deprecated Use {@link #getDefaultMinEvictableIdleDuration()}. */ @Deprecated public long getDefaultMinEvictableIdleTimeMillis() { return this.defaultMinEvictableIdleDuration.toMillis(); } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user pool. */ public int getDefaultMinIdle() { return this.defaultMinIdle; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each per user * pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each per user * pool. */ public int getDefaultNumTestsPerEvictionRun() { return this.defaultNumTestsPerEvictionRun; } /** * Gets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * * @return The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * @since 2.10.0 */ public Duration getDefaultSoftMinEvictableIdleDuration() { return this.defaultSoftMinEvictableIdleDuration; } /** * Gets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * * @return The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * @deprecated Use {@link #getDefaultSoftMinEvictableIdleDuration()}. */ @Deprecated public long getDefaultSoftMinEvictableIdleTimeMillis() { return this.defaultSoftMinEvictableIdleDuration.toMillis(); } /** * Gets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnBorrow()} for each per user pool. * * @return The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnBorrow()} for each per user pool. */ public boolean getDefaultTestOnBorrow() { return this.defaultTestOnBorrow; } /** * Gets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnCreate()} for each per user pool. * * @return The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnCreate()} for each per user pool. */ public boolean getDefaultTestOnCreate() { return this.defaultTestOnCreate; } /** * Gets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnReturn()} for each per user pool. * * @return The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnReturn()} for each per user pool. */ public boolean getDefaultTestOnReturn() { return this.defaultTestOnReturn; } /** * Gets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestWhileIdle()} for each per user pool. * * @return The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestWhileIdle()} for each per user pool. */ public boolean getDefaultTestWhileIdle() { return this.defaultTestWhileIdle; } /** * Gets the default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns ()} for each per user pool. * * @return The default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns ()} for each per user pool. * @deprecated Use {@link #getDefaultDurationBetweenEvictionRuns()}. */ @Deprecated public long getDefaultTimeBetweenEvictionRunsMillis() { return this.defaultDurationBetweenEvictionRuns.toMillis(); } /** * Gets the value of defaultTransactionIsolation, which defines the state of connections handed out from this pool. * The value can be changed on the Connection using Connection.setTransactionIsolation(int). If this method returns * -1, the default is JDBC driver dependent. * * @return value of defaultTransactionIsolation. */ public int getDefaultTransactionIsolation() { return defaultTransactionIsolation; } /** * Gets the description. This property is defined by JDBC as for use with GUI (or other) tools that might deploy the * datasource. It serves no internal purpose. * * @return value of description. */ public String getDescription() { return description; } /** * Gets the instance key. * * @return the instance key. */ protected String getInstanceKey() { return instanceKey; } /** * Gets the value of jndiEnvironment which is used when instantiating a JNDI InitialContext. This InitialContext is * used to locate the back end ConnectionPoolDataSource. * * @param key * JNDI environment key. * @return value of jndiEnvironment. */ public String getJndiEnvironment(final String key) { String value = null; if (jndiEnvironment != null) { value = jndiEnvironment.getProperty(key); } return value; } /** * Gets the value of loginTimeout. * * @return value of loginTimeout. * @deprecated Use {@link #getLoginTimeoutDuration()}. */ @Deprecated @Override public int getLoginTimeout() { return (int) loginTimeoutDuration.getSeconds(); } /** * Gets the value of loginTimeout. * * @return value of loginTimeout. * @since 2.10.0 */ public Duration getLoginTimeoutDuration() { return loginTimeoutDuration; } /** * Gets the value of logWriter. * * @return value of logWriter. */ @Override public PrintWriter getLogWriter() { if (logWriter == null) { logWriter = new PrintWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8)); } return logWriter; } /** * Gets the maximum permitted lifetime of a connection. A value of zero or less indicates an * infinite lifetime. * * @return The maximum permitted lifetime of a connection. A value of zero or less indicates an * infinite lifetime. * @since 2.10.0 */ public Duration getMaxConnDuration() { return maxConnDuration; } /** * Gets the maximum permitted lifetime of a connection. A value of zero or less indicates an * infinite lifetime. * * @return The maximum permitted lifetime of a connection. A value of zero or less indicates an * infinite lifetime. * @deprecated Use {@link #getMaxConnDuration()}. */ @Deprecated public Duration getMaxConnLifetime() { return maxConnDuration; } /** * Gets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an * infinite lifetime. * * @return The maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an * infinite lifetime. * @deprecated Use {@link #getMaxConnLifetime()}. */ @Deprecated public long getMaxConnLifetimeMillis() { return maxConnDuration.toMillis(); } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } /** * This method is protected but can only be implemented in this package because PooledConnectionAndInfo is a package * private type. * * @param userName The user name. * @param userPassword The user password. * @return Matching PooledConnectionAndInfo. * @throws SQLException Connection or registration failure. */ protected abstract PooledConnectionAndInfo getPooledConnectionAndInfo(String userName, String userPassword) throws SQLException; /** * Gets the SQL query that will be used to validate connections from this pool before returning them to the caller. * If specified, this query MUST be an SQL SELECT statement that returns at least one row. If not * specified, {@link Connection#isValid(int)} will be used to validate connections. * * @return The SQL query that will be used to validate connections from this pool before returning them to the * caller. */ public String getValidationQuery() { return this.validationQuery; } /** * Returns the timeout in seconds before the validation query fails. * * @return The timeout in seconds before the validation query fails. * @deprecated Use {@link #getValidationQueryTimeoutDuration()}. */ @Deprecated public int getValidationQueryTimeout() { return (int) validationQueryTimeoutDuration.getSeconds(); } /** * Returns the timeout Duration before the validation query fails. * * @return The timeout Duration before the validation query fails. */ public Duration getValidationQueryTimeoutDuration() { return validationQueryTimeoutDuration; } /** * Gets the value of defaultAutoCommit, which defines the state of connections handed out from this pool. The value * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is {@code null} which * will use the default value for the drive. * * @return value of defaultAutoCommit. */ public Boolean isDefaultAutoCommit() { return defaultAutoCommit; } /** * Gets the value of defaultReadOnly, which defines the state of connections handed out from this pool. The value * can be changed on the Connection using Connection.setReadOnly(boolean). The default is {@code null} which * will use the default value for the drive. * * @return value of defaultReadOnly. */ public Boolean isDefaultReadOnly() { return defaultReadOnly; } /** * Whether a rollback will be issued after executing the SQL query that will be used to validate connections from * this pool before returning them to the caller. * * @return true if a rollback will be issued after executing the validation query */ public boolean isRollbackAfterValidation() { return this.rollbackAfterValidation; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return iface.isInstance(this); } /** * Sets the back end ConnectionPoolDataSource. This property should not be set if using JNDI to access the * data source. * * @param dataSource * Value to assign to connectionPoolDataSource. */ public void setConnectionPoolDataSource(final ConnectionPoolDataSource dataSource) { assertInitializationAllowed(); if (dataSourceName != null) { throw new IllegalStateException("Cannot set the DataSource, if JNDI is used."); } if (this.dataSource != null) { throw new IllegalStateException("The CPDS has already been set. It cannot be altered."); } this.dataSource = dataSource; instanceKey = InstanceKeyDataSourceFactory.registerNewInstance(this); } /** * Sets the name of the ConnectionPoolDataSource which backs this pool. This name is used to look up the data source * from a JNDI service provider. * * @param dataSourceName * Value to assign to dataSourceName. */ public void setDataSourceName(final String dataSourceName) { assertInitializationAllowed(); if (dataSource != null) { throw new IllegalStateException("Cannot set the JNDI name for the DataSource, if already " + "set using setConnectionPoolDataSource."); } if (this.dataSourceName != null) { throw new IllegalStateException("The DataSourceName has already been set. " + "It cannot be altered."); } this.dataSourceName = dataSourceName; instanceKey = InstanceKeyDataSourceFactory.registerNewInstance(this); } /** * Sets the value of defaultAutoCommit, which defines the state of connections handed out from this pool. The value * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is {@code null} which * will use the default value for the drive. * * @param defaultAutoCommit * Value to assign to defaultAutoCommit. */ public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { assertInitializationAllowed(); this.defaultAutoCommit = defaultAutoCommit; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getBlockWhenExhausted()} for each per user pool. * * @param blockWhenExhausted * The default value for {@link GenericKeyedObjectPoolConfig#getBlockWhenExhausted()} for each per user * pool. */ public void setDefaultBlockWhenExhausted(final boolean blockWhenExhausted) { assertInitializationAllowed(); this.defaultBlockWhenExhausted = blockWhenExhausted; } /** * Sets the default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns ()} for each per user pool. * * @param defaultDurationBetweenEvictionRuns The default value for * {@link GenericObjectPool#getDurationBetweenEvictionRuns ()} for each per user pool. * @since 2.10.0 */ public void setDefaultDurationBetweenEvictionRuns(final Duration defaultDurationBetweenEvictionRuns) { assertInitializationAllowed(); this.defaultDurationBetweenEvictionRuns = defaultDurationBetweenEvictionRuns; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for each per user * pool. * * @param evictionPolicyClassName * The default value for {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for each per * user pool. */ public void setDefaultEvictionPolicyClassName(final String evictionPolicyClassName) { assertInitializationAllowed(); this.defaultEvictionPolicyClassName = evictionPolicyClassName; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. * * @param lifo * The default value for {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. */ public void setDefaultLifo(final boolean lifo) { assertInitializationAllowed(); this.defaultLifo = lifo; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user pool. * * @param maxIdle * The default value for {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user pool. */ public void setDefaultMaxIdle(final int maxIdle) { assertInitializationAllowed(); this.defaultMaxIdle = maxIdle; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per user pool. * * @param maxTotal * The default value for {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per user pool. */ public void setDefaultMaxTotal(final int maxTotal) { assertInitializationAllowed(); this.defaultMaxTotal = maxTotal; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. * * @param maxWaitMillis * The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. * @since 2.9.0 */ public void setDefaultMaxWait(final Duration maxWaitMillis) { assertInitializationAllowed(); this.defaultMaxWaitDuration = maxWaitMillis; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} for each per user pool. * * @param maxWaitMillis * The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} for each per user pool. * @deprecated Use {@link #setDefaultMaxWait(Duration)}. */ @Deprecated public void setDefaultMaxWaitMillis(final long maxWaitMillis) { setDefaultMaxWait(Duration.ofMillis(maxWaitMillis)); } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per user * pool. * * @param defaultMinEvictableIdleDuration * The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each * per user pool. * @since 2.10.0 */ public void setDefaultMinEvictableIdle(final Duration defaultMinEvictableIdleDuration) { assertInitializationAllowed(); this.defaultMinEvictableIdleDuration = defaultMinEvictableIdleDuration; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per user * pool. * * @param minEvictableIdleTimeMillis * The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each * per user pool. * @deprecated Use {@link #setDefaultMinEvictableIdle(Duration)}. */ @Deprecated public void setDefaultMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { assertInitializationAllowed(); this.defaultMinEvictableIdleDuration = Duration.ofMillis(minEvictableIdleTimeMillis); } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user pool. * * @param minIdle * The default value for {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user pool. */ public void setDefaultMinIdle(final int minIdle) { assertInitializationAllowed(); this.defaultMinIdle = minIdle; } /** * Sets the default value for {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each per user * pool. * * @param numTestsPerEvictionRun * The default value for {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each per * user pool. */ public void setDefaultNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { assertInitializationAllowed(); this.defaultNumTestsPerEvictionRun = numTestsPerEvictionRun; } /** * Sets the value of defaultReadOnly, which defines the state of connections handed out from this pool. The value * can be changed on the Connection using Connection.setReadOnly(boolean). The default is {@code null} which * will use the default value for the drive. * * @param defaultReadOnly * Value to assign to defaultReadOnly. */ public void setDefaultReadOnly(final Boolean defaultReadOnly) { assertInitializationAllowed(); this.defaultReadOnly = defaultReadOnly; } /** * Sets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * * @param defaultSoftMinEvictableIdleDuration * The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * @since 2.10.0 */ public void setDefaultSoftMinEvictableIdle(final Duration defaultSoftMinEvictableIdleDuration) { assertInitializationAllowed(); this.defaultSoftMinEvictableIdleDuration = defaultSoftMinEvictableIdleDuration; } /** * Sets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * * @param softMinEvictableIdleTimeMillis * The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * @deprecated Use {@link #setDefaultSoftMinEvictableIdle(Duration)}. */ @Deprecated public void setDefaultSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { assertInitializationAllowed(); this.defaultSoftMinEvictableIdleDuration = Duration.ofMillis(softMinEvictableIdleTimeMillis); } /** * Sets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnBorrow()} for each per user pool. * * @param testOnBorrow * The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnBorrow()} for each per user pool. */ public void setDefaultTestOnBorrow(final boolean testOnBorrow) { assertInitializationAllowed(); this.defaultTestOnBorrow = testOnBorrow; } /** * Sets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnCreate()} for each per user pool. * * @param testOnCreate * The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnCreate()} for each per user pool. */ public void setDefaultTestOnCreate(final boolean testOnCreate) { assertInitializationAllowed(); this.defaultTestOnCreate = testOnCreate; } /** * Sets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnReturn()} for each per user pool. * * @param testOnReturn * The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestOnReturn()} for each per user pool. */ public void setDefaultTestOnReturn(final boolean testOnReturn) { assertInitializationAllowed(); this.defaultTestOnReturn = testOnReturn; } /** * Sets the default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestWhileIdle()} for each per user pool. * * @param testWhileIdle * The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTestWhileIdle()} for each per user pool. */ public void setDefaultTestWhileIdle(final boolean testWhileIdle) { assertInitializationAllowed(); this.defaultTestWhileIdle = testWhileIdle; } /** * Sets the default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for each per user pool. * * @param timeBetweenEvictionRunsMillis The default value for * {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for each per user pool. * @deprecated Use {@link #setDefaultDurationBetweenEvictionRuns(Duration)}. */ @Deprecated public void setDefaultTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { assertInitializationAllowed(); this.defaultDurationBetweenEvictionRuns = Duration.ofMillis(timeBetweenEvictionRunsMillis); } /** * Sets the value of defaultTransactionIsolation, which defines the state of connections handed out from this pool. * The value can be changed on the Connection using Connection.setTransactionIsolation(int). The default is JDBC * driver dependent. * * @param defaultTransactionIsolation * Value to assign to defaultTransactionIsolation */ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { assertInitializationAllowed(); switch (defaultTransactionIsolation) { case Connection.TRANSACTION_NONE: case Connection.TRANSACTION_READ_COMMITTED: case Connection.TRANSACTION_READ_UNCOMMITTED: case Connection.TRANSACTION_REPEATABLE_READ: case Connection.TRANSACTION_SERIALIZABLE: break; default: throw new IllegalArgumentException(BAD_TRANSACTION_ISOLATION); } this.defaultTransactionIsolation = defaultTransactionIsolation; } /** * Sets the description. This property is defined by JDBC as for use with GUI (or other) tools that might deploy the * datasource. It serves no internal purpose. * * @param description * Value to assign to description. */ public void setDescription(final String description) { this.description = description; } /** * Sets the JNDI environment to be used when instantiating a JNDI InitialContext. This InitialContext is used to * locate the back end ConnectionPoolDataSource. * * @param properties * the JNDI environment property to set which will overwrite any current settings */ void setJndiEnvironment(final Properties properties) { if (jndiEnvironment == null) { jndiEnvironment = new Properties(); } else { jndiEnvironment.clear(); } jndiEnvironment.putAll(properties); } /** * Sets the value of the given JNDI environment property to be used when instantiating a JNDI InitialContext. This * InitialContext is used to locate the back end ConnectionPoolDataSource. * * @param key * the JNDI environment property to set. * @param value * the value assigned to specified JNDI environment property. */ public void setJndiEnvironment(final String key, final String value) { if (jndiEnvironment == null) { jndiEnvironment = new Properties(); } jndiEnvironment.setProperty(key, value); } /** * Sets the value of loginTimeout. * * @param loginTimeout * Value to assign to loginTimeout. * @since 2.10.0 */ public void setLoginTimeout(final Duration loginTimeout) { this.loginTimeoutDuration = loginTimeout; } /** * Sets the value of loginTimeout. * * @param loginTimeout * Value to assign to loginTimeout. * @deprecated Use {@link #setLoginTimeout(Duration)}. */ @Deprecated @Override public void setLoginTimeout(final int loginTimeout) { this.loginTimeoutDuration = Duration.ofSeconds(loginTimeout); } /** * Sets the value of logWriter. * * @param logWriter * Value to assign to logWriter. */ @Override public void setLogWriter(final PrintWriter logWriter) { this.logWriter = logWriter; } /** *

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

*

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

* * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection. A value of zero or less indicates an infinite lifetime. * @since 2.9.0 */ public void setMaxConnLifetime(final Duration maxConnLifetimeMillis) { this.maxConnDuration = maxConnLifetimeMillis; } /** *

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

*

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

* * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an infinite lifetime. * @deprecated Use {@link #setMaxConnLifetime(Duration)}. */ @Deprecated public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { setMaxConnLifetime(Duration.ofMillis(maxConnLifetimeMillis)); } /** * Whether a rollback will be issued after executing the SQL query that will be used to validate connections from * this pool before returning them to the caller. Default behavior is NOT to issue a rollback. The setting will only * have an effect if a validation query is set * * @param rollbackAfterValidation * new property value */ public void setRollbackAfterValidation(final boolean rollbackAfterValidation) { assertInitializationAllowed(); this.rollbackAfterValidation = rollbackAfterValidation; } protected abstract void setupDefaults(Connection connection, String userName) throws SQLException; /** * Sets the SQL query that will be used to validate connections from this pool before returning them to the caller. * If specified, this query MUST be an SQL SELECT statement that returns at least one row. If not * specified, connections will be validated using {@link Connection#isValid(int)}. * * @param validationQuery * The SQL query that will be used to validate connections from this pool before returning them to the * caller. */ public void setValidationQuery(final String validationQuery) { assertInitializationAllowed(); this.validationQuery = validationQuery; } /** * Sets the timeout duration before the validation query fails. * * @param validationQueryTimeoutDuration * The new timeout duration. */ public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) { this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; } /** * Sets the timeout in seconds before the validation query fails. * * @param validationQueryTimeoutSeconds * The new timeout in seconds * @deprecated Use {@link #setValidationQueryTimeout(Duration)}. */ @Deprecated public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); } protected ConnectionPoolDataSource testCPDS(final String userName, final String userPassword) throws javax.naming.NamingException, SQLException { // The source of physical db connections ConnectionPoolDataSource cpds = this.dataSource; if (cpds == null) { Context ctx = null; if (jndiEnvironment == null) { ctx = new InitialContext(); } else { ctx = new InitialContext(jndiEnvironment); } final Object ds = ctx.lookup(dataSourceName); if (!(ds instanceof ConnectionPoolDataSource)) { throw new SQLException("Illegal configuration: " + "DataSource " + dataSourceName + " (" + ds.getClass().getName() + ")" + " doesn't implement javax.sql.ConnectionPoolDataSource"); } cpds = (ConnectionPoolDataSource) ds; } // try to get a connection with the supplied userName/password PooledConnection conn = null; try { if (userName != null) { conn = cpds.getPooledConnection(userName, userPassword); } else { conn = cpds.getPooledConnection(); } if (conn == null) { throw new SQLException("Cannot connect using the supplied userName/password"); } } finally { if (conn != null) { try { conn.close(); } catch (final SQLException ignored) { // at least we could connect } } } return cpds; } /** * @since 2.6.0 */ @Override public synchronized String toString() { final StringBuilder builder = new StringBuilder(super.toString()); builder.append('['); toStringFields(builder); builder.append(']'); return builder.toString(); } protected void toStringFields(final StringBuilder builder) { builder.append("getConnectionCalled="); builder.append(getConnectionCalled); builder.append(", dataSource="); builder.append(dataSource); builder.append(", dataSourceName="); builder.append(dataSourceName); builder.append(", description="); builder.append(description); builder.append(", jndiEnvironment="); builder.append(jndiEnvironment); builder.append(", loginTimeoutDuration="); builder.append(loginTimeoutDuration); builder.append(", logWriter="); builder.append(logWriter); builder.append(", instanceKey="); builder.append(instanceKey); builder.append(", defaultBlockWhenExhausted="); builder.append(defaultBlockWhenExhausted); builder.append(", defaultEvictionPolicyClassName="); builder.append(defaultEvictionPolicyClassName); builder.append(", defaultLifo="); builder.append(defaultLifo); builder.append(", defaultMaxIdle="); builder.append(defaultMaxIdle); builder.append(", defaultMaxTotal="); builder.append(defaultMaxTotal); builder.append(", defaultMaxWaitDuration="); builder.append(defaultMaxWaitDuration); builder.append(", defaultMinEvictableIdleDuration="); builder.append(defaultMinEvictableIdleDuration); builder.append(", defaultMinIdle="); builder.append(defaultMinIdle); builder.append(", defaultNumTestsPerEvictionRun="); builder.append(defaultNumTestsPerEvictionRun); builder.append(", defaultSoftMinEvictableIdleDuration="); builder.append(defaultSoftMinEvictableIdleDuration); builder.append(", defaultTestOnCreate="); builder.append(defaultTestOnCreate); builder.append(", defaultTestOnBorrow="); builder.append(defaultTestOnBorrow); builder.append(", defaultTestOnReturn="); builder.append(defaultTestOnReturn); builder.append(", defaultTestWhileIdle="); builder.append(defaultTestWhileIdle); builder.append(", defaultDurationBetweenEvictionRuns="); builder.append(defaultDurationBetweenEvictionRuns); builder.append(", validationQuery="); builder.append(validationQuery); builder.append(", validationQueryTimeoutDuration="); builder.append(validationQueryTimeoutDuration); builder.append(", rollbackAfterValidation="); builder.append(rollbackAfterValidation); builder.append(", maxConnDuration="); builder.append(maxConnDuration); builder.append(", defaultAutoCommit="); builder.append(defaultAutoCommit); builder.append(", defaultTransactionIsolation="); builder.append(defaultTransactionIsolation); builder.append(", defaultReadOnly="); builder.append(defaultReadOnly); } @Override @SuppressWarnings("unchecked") public T unwrap(final Class iface) throws SQLException { if (isWrapperFor(iface)) { return (T) this; } throw new SQLException(this + " is not a wrapper for " + iface); } } InstanceKeyDataSourceFactory.java000066400000000000000000000314731472045345700372720ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.time.Duration; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import javax.naming.Context; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import org.apache.commons.dbcp2.ListException; import org.apache.commons.dbcp2.Utils; /** * A JNDI ObjectFactory which creates {@code SharedPoolDataSource}s or {@code PerUserPoolDataSource}s * * @since 2.0 */ abstract class InstanceKeyDataSourceFactory implements ObjectFactory { private static final Map INSTANCE_MAP = new ConcurrentHashMap<>(); /** * Closes all pools associated with this class. * * @throws ListException * a {@link ListException} containing all exceptions thrown by {@link InstanceKeyDataSource#close()} * @see InstanceKeyDataSource#close() * @since 2.4.0 throws a {@link ListException} instead of, in 2.3.0 and before, the first exception thrown by * {@link InstanceKeyDataSource#close()}. */ public static void closeAll() throws ListException { // Get iterator to loop over all instances of this data source. final List exceptionList = new ArrayList<>(INSTANCE_MAP.size()); INSTANCE_MAP.entrySet().forEach(entry -> { // Bullet-proof to avoid anything else but problems from InstanceKeyDataSource#close(). if (entry != null) { @SuppressWarnings("resource") final InstanceKeyDataSource value = entry.getValue(); Utils.close(value, exceptionList::add); } }); INSTANCE_MAP.clear(); if (!exceptionList.isEmpty()) { throw new ListException("Could not close all InstanceKeyDataSource instances.", exceptionList); } } /** * Deserializes the provided byte array to create an object. * * @param data * Data to deserialize to create the configuration parameter. * * @return The Object created by deserializing the data. * * @throws ClassNotFoundException * If a class cannot be found during the deserialization of a configuration parameter. * @throws IOException * If an I/O error occurs during the deserialization of a configuration parameter. */ protected static final Object deserialize(final byte[] data) throws IOException, ClassNotFoundException { ObjectInputStream in = null; try { in = new ObjectInputStream(new ByteArrayInputStream(data)); return in.readObject(); } finally { Utils.closeQuietly(in); } } static synchronized String registerNewInstance(final InstanceKeyDataSource ds) { int max = 0; for (final String s : INSTANCE_MAP.keySet()) { if (s != null) { try { max = Math.max(max, Integer.parseInt(s)); } catch (final NumberFormatException ignored) { // no sweat, ignore those keys } } } final String instanceKey = String.valueOf(max + 1); // Put a placeholder here for now, so other instances will not // take our key. We will replace with a pool when ready. INSTANCE_MAP.put(instanceKey, ds); return instanceKey; } static void removeInstance(final String key) { if (key != null) { INSTANCE_MAP.remove(key); } } private Boolean booleanValueOf(RefAddr refAddr) { return Boolean.valueOf(toString(refAddr)); } /** * Creates an instance of the subclass and sets any properties contained in the Reference. * * @param ref * The properties to be set on the created DataSource * * @return A configured DataSource of the appropriate type. * * @throws ClassNotFoundException * If a class cannot be found during the deserialization of a configuration parameter. * @throws IOException * If an I/O error occurs during the deserialization of a configuration parameter. */ protected abstract InstanceKeyDataSource getNewInstance(Reference ref) throws IOException, ClassNotFoundException; /** * Implements ObjectFactory to create an instance of SharedPoolDataSource or PerUserPoolDataSource */ @Override public Object getObjectInstance(final Object refObj, final Name name, final Context context, final Hashtable env) throws IOException, ClassNotFoundException { // The spec says to return null if we can't create an instance // of the reference Object obj = null; if (refObj instanceof Reference) { final Reference ref = (Reference) refObj; if (isCorrectClass(ref.getClassName())) { final RefAddr refAddr = ref.get("instanceKey"); if (hasContent(refAddr)) { // object was bound to JNDI via Referenceable API. obj = INSTANCE_MAP.get(refAddr.getContent()); } else { // Tomcat JNDI creates a Reference out of server.xml // configuration and passes it to an // instance of the factory given in server.xml. String key = null; if (name != null) { key = name.toString(); obj = INSTANCE_MAP.get(key); } if (obj == null) { final InstanceKeyDataSource ds = getNewInstance(ref); setCommonProperties(ref, ds); obj = ds; if (key != null) { INSTANCE_MAP.put(key, ds); } } } } } return obj; } private boolean hasContent(final RefAddr refAddr) { return refAddr != null && refAddr.getContent() != null; } /** * Tests if className is the value returned from getClass().getName().toString(). * * @param className * The class name to test. * * @return true if and only if className is the value returned from getClass().getName().toString() */ protected abstract boolean isCorrectClass(String className); boolean parseBoolean(final RefAddr refAddr) { return Boolean.parseBoolean(toString(refAddr)); } int parseInt(final RefAddr refAddr) { return Integer.parseInt(toString(refAddr)); } long parseLong(final RefAddr refAddr) { return Long.parseLong(toString(refAddr)); } private void setCommonProperties(final Reference ref, final InstanceKeyDataSource ikds) throws IOException, ClassNotFoundException { RefAddr refAddr = ref.get("dataSourceName"); if (hasContent(refAddr)) { ikds.setDataSourceName(toString(refAddr)); } refAddr = ref.get("description"); if (hasContent(refAddr)) { ikds.setDescription(toString(refAddr)); } refAddr = ref.get("jndiEnvironment"); if (hasContent(refAddr)) { final byte[] serialized = (byte[]) refAddr.getContent(); ikds.setJndiEnvironment((Properties) deserialize(serialized)); } refAddr = ref.get("loginTimeout"); if (hasContent(refAddr)) { ikds.setLoginTimeout(toDurationFromSeconds(refAddr)); } // Pool properties refAddr = ref.get("blockWhenExhausted"); if (hasContent(refAddr)) { ikds.setDefaultBlockWhenExhausted(parseBoolean(refAddr)); } refAddr = ref.get("evictionPolicyClassName"); if (hasContent(refAddr)) { ikds.setDefaultEvictionPolicyClassName(toString(refAddr)); } // Pool properties refAddr = ref.get("lifo"); if (hasContent(refAddr)) { ikds.setDefaultLifo(parseBoolean(refAddr)); } refAddr = ref.get("maxIdlePerKey"); if (hasContent(refAddr)) { ikds.setDefaultMaxIdle(parseInt(refAddr)); } refAddr = ref.get("maxTotalPerKey"); if (hasContent(refAddr)) { ikds.setDefaultMaxTotal(parseInt(refAddr)); } refAddr = ref.get("maxWaitMillis"); if (hasContent(refAddr)) { ikds.setDefaultMaxWait(toDurationFromMillis(refAddr)); } refAddr = ref.get("minEvictableIdleTimeMillis"); if (hasContent(refAddr)) { ikds.setDefaultMinEvictableIdle(toDurationFromMillis(refAddr)); } refAddr = ref.get("minIdlePerKey"); if (hasContent(refAddr)) { ikds.setDefaultMinIdle(parseInt(refAddr)); } refAddr = ref.get("numTestsPerEvictionRun"); if (hasContent(refAddr)) { ikds.setDefaultNumTestsPerEvictionRun(parseInt(refAddr)); } refAddr = ref.get("softMinEvictableIdleTimeMillis"); if (hasContent(refAddr)) { ikds.setDefaultSoftMinEvictableIdle(toDurationFromMillis(refAddr)); } refAddr = ref.get("testOnCreate"); if (hasContent(refAddr)) { ikds.setDefaultTestOnCreate(parseBoolean(refAddr)); } refAddr = ref.get("testOnBorrow"); if (hasContent(refAddr)) { ikds.setDefaultTestOnBorrow(parseBoolean(refAddr)); } refAddr = ref.get("testOnReturn"); if (hasContent(refAddr)) { ikds.setDefaultTestOnReturn(parseBoolean(refAddr)); } refAddr = ref.get("testWhileIdle"); if (hasContent(refAddr)) { ikds.setDefaultTestWhileIdle(parseBoolean(refAddr)); } refAddr = ref.get("timeBetweenEvictionRunsMillis"); if (hasContent(refAddr)) { ikds.setDefaultDurationBetweenEvictionRuns(toDurationFromMillis(refAddr)); } // Connection factory properties refAddr = ref.get("validationQuery"); if (hasContent(refAddr)) { ikds.setValidationQuery(toString(refAddr)); } refAddr = ref.get("validationQueryTimeout"); if (hasContent(refAddr)) { ikds.setValidationQueryTimeout(toDurationFromSeconds(refAddr)); } refAddr = ref.get("rollbackAfterValidation"); if (hasContent(refAddr)) { ikds.setRollbackAfterValidation(parseBoolean(refAddr)); } refAddr = ref.get("maxConnLifetimeMillis"); if (hasContent(refAddr)) { ikds.setMaxConnLifetime(toDurationFromMillis(refAddr)); } // Connection properties refAddr = ref.get("defaultAutoCommit"); if (hasContent(refAddr)) { ikds.setDefaultAutoCommit(booleanValueOf(refAddr)); } refAddr = ref.get("defaultTransactionIsolation"); if (hasContent(refAddr)) { ikds.setDefaultTransactionIsolation(parseInt(refAddr)); } refAddr = ref.get("defaultReadOnly"); if (hasContent(refAddr)) { ikds.setDefaultReadOnly(booleanValueOf(refAddr)); } } private Duration toDurationFromMillis(RefAddr refAddr) { return Duration.ofMillis(parseLong(refAddr)); } private Duration toDurationFromSeconds(RefAddr refAddr) { return Duration.ofSeconds(parseInt(refAddr)); } String toString(final RefAddr refAddr) { return refAddr.getContent().toString(); } } KeyedCPDSConnectionFactory.java000066400000000000000000000377131472045345700366400ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import org.apache.commons.dbcp2.Utils; import org.apache.commons.pool2.KeyedObjectPool; import org.apache.commons.pool2.KeyedPooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; /** * A {@link KeyedPooledObjectFactory} that creates {@link PoolableConnection}s. * * @since 2.0 */ final class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory, ConnectionEventListener, PooledConnectionManager { private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but " + "I have no record of the underlying PooledConnection."; private final ConnectionPoolDataSource cpds; private final String validationQuery; private final Duration validationQueryTimeoutDuration; private final boolean rollbackAfterValidation; private KeyedObjectPool pool; private Duration maxConnLifetime = Duration.ofMillis(-1); /** * Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated. */ private final Set validatingSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); /** * Map of PooledConnectionAndInfo instances */ private final Map pcMap = new ConcurrentHashMap<>(); /** * Creates a new {@code KeyedPoolableConnectionFactory}. * * @param cpds * the ConnectionPoolDataSource from which to obtain PooledConnections * @param validationQuery * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one * row. May be {@code null} in which case3 {@link Connection#isValid(int)} will be used to validate * connections. * @param validationQueryTimeoutSeconds * The Duration to allow for the validation query to complete * @param rollbackAfterValidation * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. * @since 2.10.0 */ public KeyedCPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final Duration validationQueryTimeoutSeconds, final boolean rollbackAfterValidation) { this.cpds = cpds; this.validationQuery = validationQuery; this.validationQueryTimeoutDuration = validationQueryTimeoutSeconds; this.rollbackAfterValidation = rollbackAfterValidation; } /** * Creates a new {@code KeyedPoolableConnectionFactory}. * * @param cpds * the ConnectionPoolDataSource from which to obtain PooledConnections * @param validationQuery * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one * row. May be {@code null} in which case3 {@link Connection#isValid(int)} will be used to validate * connections. * @param validationQueryTimeoutSeconds * The time, in seconds, to allow for the validation query to complete * @param rollbackAfterValidation * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. * @deprecated Use {@link #KeyedCPDSConnectionFactory(ConnectionPoolDataSource, String, Duration, boolean)}. */ @Deprecated public KeyedCPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation) { this(cpds, validationQuery, Duration.ofSeconds(validationQueryTimeoutSeconds), rollbackAfterValidation); } @Override public void activateObject(final UserPassKey key, final PooledObject p) throws SQLException { validateLifetime(p); } /** * This implementation does not fully close the KeyedObjectPool, as this would affect all users. Instead, it clears * the pool associated with the given user. This method is not currently used. */ @Override public void closePool(final String userName) throws SQLException { try { pool.clear(new UserPassKey(userName)); } catch (final Exception ex) { throw new SQLException("Error closing connection pool", ex); } } /** * This will be called if the Connection returned by the getConnection method came from a PooledConnection, and the * user calls the close() method of this connection object. What we need to do here is to release this * PooledConnection from our pool... */ @Override public void connectionClosed(final ConnectionEvent event) { final PooledConnection pc = (PooledConnection) event.getSource(); // if this event occurred because we were validating, or if this // connection has been marked for removal, ignore it // otherwise return the connection to the pool. if (!validatingSet.contains(pc)) { final PooledConnectionAndInfo pci = pcMap.get(pc); if (pci == null) { throw new IllegalStateException(NO_KEY_MESSAGE); } try { pool.returnObject(pci.getUserPassKey(), pci); } catch (final Exception e) { System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + "NOT BE RETURNED TO THE POOL"); pc.removeConnectionEventListener(this); try { pool.invalidateObject(pci.getUserPassKey(), pci); } catch (final Exception e3) { System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + pci); e3.printStackTrace(); } } } } /** * If a fatal error occurs, close the underlying physical connection so as not to be returned in the future */ @Override public void connectionErrorOccurred(final ConnectionEvent event) { final PooledConnection pc = (PooledConnection) event.getSource(); if (null != event.getSQLException()) { System.err.println("CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR (" + event.getSQLException() + ")"); } pc.removeConnectionEventListener(this); final PooledConnectionAndInfo info = pcMap.get(pc); if (info == null) { throw new IllegalStateException(NO_KEY_MESSAGE); } try { pool.invalidateObject(info.getUserPassKey(), info); } catch (final Exception e) { System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + info); e.printStackTrace(); } } /** * Closes the PooledConnection and stops listening for events from it. */ @Override public void destroyObject(final UserPassKey key, final PooledObject p) throws SQLException { final PooledConnection pooledConnection = p.getObject().getPooledConnection(); pooledConnection.removeConnectionEventListener(this); pcMap.remove(pooledConnection); pooledConnection.close(); } /** * Returns the keyed object pool used to pool connections created by this factory. * * @return KeyedObjectPool managing pooled connections */ public KeyedObjectPool getPool() { return pool; } /** * Invalidates the PooledConnection in the pool. The KeyedCPDSConnectionFactory closes the connection and pool * counters are updated appropriately. Also clears any idle instances associated with the user name that was used to * create the PooledConnection. Connections associated with this user are not affected, and they will not be * automatically closed on return to the pool. */ @Override public void invalidate(final PooledConnection pc) throws SQLException { final PooledConnectionAndInfo info = pcMap.get(pc); if (info == null) { throw new IllegalStateException(NO_KEY_MESSAGE); } final UserPassKey key = info.getUserPassKey(); try { pool.invalidateObject(key, info); // Destroy and update pool counters pool.clear(key); // Remove any idle instances with this key } catch (final Exception ex) { throw new SQLException("Error invalidating connection", ex); } } /** * Creates a new {@code PooledConnectionAndInfo} from the given {@code UserPassKey}. * * @param userPassKey * {@code UserPassKey} containing user credentials * @throws SQLException * if the connection could not be created. * @see org.apache.commons.pool2.KeyedPooledObjectFactory#makeObject(Object) */ @Override public synchronized PooledObject makeObject(final UserPassKey userPassKey) throws SQLException { PooledConnection pooledConnection = null; final String userName = userPassKey.getUserName(); final String password = userPassKey.getPassword(); if (userName == null) { pooledConnection = cpds.getPooledConnection(); } else { pooledConnection = cpds.getPooledConnection(userName, password); } if (pooledConnection == null) { throw new IllegalStateException("Connection pool data source returned null from getPooledConnection"); } // should we add this object as a listener or the pool. // consider the validateObject method in decision pooledConnection.addConnectionEventListener(this); final PooledConnectionAndInfo pci = new PooledConnectionAndInfo(pooledConnection, userPassKey); pcMap.put(pooledConnection, pci); return new DefaultPooledObject<>(pci); } @Override public void passivateObject(final UserPassKey key, final PooledObject p) throws SQLException { validateLifetime(p); } /** * Sets the maximum lifetime of a connection after which the connection will always fail activation, * passivation and validation. * * @param maxConnLifetimeMillis * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. * @since 2.10.0 */ public void setMaxConn(final Duration maxConnLifetimeMillis) { this.maxConnLifetime = maxConnLifetimeMillis; } /** * Sets the maximum lifetime of a connection after which the connection will always fail activation, * passivation and validation. * * @param maxConnLifetimeMillis * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. * @since 2.9.0 * @deprecated Use {@link #setMaxConn(Duration)}. */ @Deprecated public void setMaxConnLifetime(final Duration maxConnLifetimeMillis) { this.maxConnLifetime = maxConnLifetimeMillis; } /** * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, * passivation and validation. * * @param maxConnLifetimeMillis * A value of zero or less indicates an infinite lifetime. The default value is -1. * @deprecated Use {@link #setMaxConnLifetime(Duration)}. */ @Deprecated public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { setMaxConn(Duration.ofMillis(maxConnLifetimeMillis)); } /** * Does nothing. This factory does not cache user credentials. */ @Override public void setPassword(final String password) { // Does nothing. This factory does not cache user credentials. } public void setPool(final KeyedObjectPool pool) { this.pool = pool; } private void validateLifetime(final PooledObject pooledObject) throws SQLException { Utils.validateLifetime(pooledObject, maxConnLifetime); } /** * Validates a pooled connection. * * @param key * ignored * @param pooledObject * wrapped {@code PooledConnectionAndInfo} containing the connection to validate * @return true if validation succeeds */ @Override public boolean validateObject(final UserPassKey key, final PooledObject pooledObject) { try { validateLifetime(pooledObject); } catch (final Exception e) { return false; } boolean valid = false; final PooledConnection pooledConn = pooledObject.getObject().getPooledConnection(); Connection conn = null; validatingSet.add(pooledConn); if (null == validationQuery) { Duration timeoutDuration = validationQueryTimeoutDuration; if (timeoutDuration.isNegative()) { timeoutDuration = Duration.ZERO; } try { conn = pooledConn.getConnection(); valid = conn.isValid((int) timeoutDuration.getSeconds()); } catch (final SQLException e) { valid = false; } finally { Utils.closeQuietly((AutoCloseable) conn); validatingSet.remove(pooledConn); } } else { Statement stmt = null; ResultSet rset = null; // logical Connection from the PooledConnection must be closed // before another one can be requested and closing it will // generate an event. Keep track so we know not to return // the PooledConnection validatingSet.add(pooledConn); try { conn = pooledConn.getConnection(); stmt = conn.createStatement(); rset = stmt.executeQuery(validationQuery); valid = rset.next(); if (rollbackAfterValidation) { conn.rollback(); } } catch (final Exception e) { valid = false; } finally { Utils.closeQuietly((AutoCloseable) rset); Utils.closeQuietly((AutoCloseable) stmt); Utils.closeQuietly((AutoCloseable) conn); validatingSet.remove(pooledConn); } } return valid; } } PerUserPoolDataSource.java000066400000000000000000001273611472045345700357460ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.IOException; import java.io.ObjectInputStream; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import java.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; import java.util.function.Supplier; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.sql.ConnectionPoolDataSource; import org.apache.commons.dbcp2.SwallowedExceptionLogger; import org.apache.commons.dbcp2.Utils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.impl.EvictionPolicy; import org.apache.commons.pool2.impl.GenericObjectPool; /** *

* A pooling {@code DataSource} appropriate for deployment within J2EE environment. There are many configuration * options, most of which are defined in the parent class. This datasource uses individual pools per user, and some * properties can be set specifically for a given user, if the deployment environment can support initialization of * mapped properties. So for example, a pool of admin or write-access Connections can be guaranteed a certain number of * connections, separate from a maximum set for users with read-only connections. *

* *

* User passwords can be changed without re-initializing the datasource. When a * {@code getConnection(userName, password)} request is processed with a password that is different from those used * to create connections in the pool associated with {@code userName}, an attempt is made to create a new * connection using the supplied password and if this succeeds, the existing pool is cleared and a new pool is created * for connections using the new password. *

* * @since 2.0 */ public class PerUserPoolDataSource extends InstanceKeyDataSource { private static final long serialVersionUID = 7872747993848065028L; private static final Log log = LogFactory.getLog(PerUserPoolDataSource.class); private static HashMap createMap() { // Should there be a default size different from what this ctor provides? return new HashMap<>(); } /** * Maps user names to a data source property: BlockWhenExhausted. */ private Map perUserBlockWhenExhausted; /** * Maps user names to a data source property: EvictionPolicyClassName. */ private Map perUserEvictionPolicyClassName; /** * Maps user names to a data source property: Lifo. */ private Map perUserLifo; /** * Maps user names to a data source property: MaxIdle. */ private Map perUserMaxIdle; /** * Maps user names to a data source property: MaxTotal. */ private Map perUserMaxTotal; /** * Maps user names to a data source property: MaxWaitDuration. */ private Map perUserMaxWaitDuration; /** * Maps user names to a data source property: MinEvictableIdleDuration. */ private Map perUserMinEvictableIdleDuration; /** * Maps user names to a data source property: MinIdle. */ private Map perUserMinIdle; /** * Maps user names to a data source property: NumTestsPerEvictionRun. */ private Map perUserNumTestsPerEvictionRun; /** * Maps user names to a data source property: SoftMinEvictableIdleDuration. */ private Map perUserSoftMinEvictableIdleDuration; /** * Maps user names to a data source property: TestOnCreate. */ private Map perUserTestOnCreate; /** * Maps user names to a data source property: TestOnBorrow. */ private Map perUserTestOnBorrow; /** * Maps user names to a data source property: TestOnReturn. */ private Map perUserTestOnReturn; /** * Maps user names to a data source property: TestWhileIdle. */ private Map perUserTestWhileIdle; /** * Maps user names to a data source property: DurationBetweenEvictionRuns. */ private Map perUserDurationBetweenEvictionRuns; /** * Maps user names to a data source property: DefaultAutoCommit. */ private Map perUserDefaultAutoCommit; /** * Maps user names to a data source property: DefaultTransactionIsolation. */ private Map perUserDefaultTransactionIsolation; /** * Maps user names to a data source property: DefaultReadOnly. */ private Map perUserDefaultReadOnly; /** * Map to keep track of Pools for a given user. */ private transient Map managers = createMap(); /** * Constructs a new instance. */ public PerUserPoolDataSource() { } /** * Clears pool(s) maintained by this data source. * * @see org.apache.commons.pool2.ObjectPool#clear() * @since 2.3.0 */ @SuppressWarnings("resource") // does not allocate a pool public void clear() { managers.values().forEach(manager -> { try { getCPDSConnectionFactoryPool(manager).clear(); } catch (final Exception ignored) { // ignore and try to close others. } }); InstanceKeyDataSourceFactory.removeInstance(getInstanceKey()); } /** * Closes pool(s) maintained by this data source. * * @see org.apache.commons.pool2.ObjectPool#close() */ @Override public void close() { managers.values().forEach(manager -> Utils.closeQuietly(getCPDSConnectionFactoryPool(manager))); InstanceKeyDataSourceFactory.removeInstance(getInstanceKey()); } /** * Converts a map with Long milliseconds values to another map with Duration values. */ private Map convertMap(final Map currentMap, final Map longMap) { final Map durationMap = createMap(); longMap.forEach((k, v) -> durationMap.put(k, toDurationOrNull(v))); if (currentMap == null) { return durationMap; } currentMap.clear(); currentMap.putAll(durationMap); return currentMap; } /** * Gets the user specific default value in a map for the specified user's pool. * * @param userName The user name key. * @return The user specific value. */ private V get(final Map map, final String userName) { return map != null ? map.get(userName) : null; } /** * Gets the user specific default value in a map for the specified user's pool. * * @param userName The user name key. * @return The user specific value. */ private V get(final Map map, final String userName, final Supplier defaultSupplier) { final V v = get(map, userName); return v != null ? v : defaultSupplier.get(); } @Override protected PooledConnectionManager getConnectionManager(final UserPassKey upKey) { return managers.get(getPoolKey(upKey.getUserName())); } /** * Gets the underlying pre-allocated pool (does NOT allocate). * * @param manager A CPDSConnectionFactory. * @return the underlying pool. */ private ObjectPool getCPDSConnectionFactoryPool(final PooledConnectionManager manager) { return ((CPDSConnectionFactory) manager).getPool(); } /** * Gets the number of active connections in the default pool. * * @return The number of active connections in the default pool. */ public int getNumActive() { return getNumActive(null); } /** * Gets the number of active connections in the pool for a given user. * * @param userName * The user name key. * @return The user specific value. */ @SuppressWarnings("resource") public int getNumActive(final String userName) { final ObjectPool pool = getPool(getPoolKey(userName)); return pool == null ? 0 : pool.getNumActive(); } /** * Gets the number of idle connections in the default pool. * * @return The number of idle connections in the default pool. */ public int getNumIdle() { return getNumIdle(null); } /** * Gets the number of idle connections in the pool for a given user. * * @param userName * The user name key. * @return The user specific value. */ @SuppressWarnings("resource") public int getNumIdle(final String userName) { final ObjectPool pool = getPool(getPoolKey(userName)); return pool == null ? 0 : pool.getNumIdle(); } /** * Gets the user specific value for {@link GenericObjectPool#getBlockWhenExhausted()} for the specified user's pool * or the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public boolean getPerUserBlockWhenExhausted(final String userName) { return get(perUserBlockWhenExhausted, userName, this::getDefaultBlockWhenExhausted); } /** * Gets the user specific default value for {@link Connection#setAutoCommit(boolean)} for the specified user's pool. * * @param userName * The user name key. * @return The user specific value. */ public Boolean getPerUserDefaultAutoCommit(final String userName) { return get(perUserDefaultAutoCommit, userName); } /** * Gets the user specific default value for {@link Connection#setReadOnly(boolean)} for the specified user's pool. * * @param userName * The user name key. * @return The user specific value. */ public Boolean getPerUserDefaultReadOnly(final String userName) { return get(perUserDefaultReadOnly, userName); } /** * Gets the user specific default value for {@link Connection#setTransactionIsolation(int)} for the specified user's * pool. * * @param userName * The user name key. * @return The user specific value. */ public Integer getPerUserDefaultTransactionIsolation(final String userName) { return get(perUserDefaultTransactionIsolation, userName); } /** * Gets the user specific value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for the specified * user's pool or the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. * @since 2.10.0 */ public Duration getPerUserDurationBetweenEvictionRuns(final String userName) { return get(perUserDurationBetweenEvictionRuns, userName, this::getDefaultDurationBetweenEvictionRuns); } /** * Gets the user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's * pool or the default if no user specific value is defined. *

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

* * @param userName * The user name key. * @return The user specific value. */ public String getPerUserEvictionPolicyClassName(final String userName) { return get(perUserEvictionPolicyClassName, userName, this::getDefaultEvictionPolicyClassName); } /** * Gets the user specific value for {@link GenericObjectPool#getLifo()} for the specified user's pool or the default * if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public boolean getPerUserLifo(final String userName) { return get(perUserLifo, userName, this::getDefaultLifo); } /** * Gets the user specific value for {@link GenericObjectPool#getMaxIdle()} for the specified user's pool or the * default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public int getPerUserMaxIdle(final String userName) { return get(perUserMaxIdle, userName, this::getDefaultMaxIdle); } /** * Gets the user specific value for {@link GenericObjectPool#getMaxTotal()} for the specified user's pool or the * default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public int getPerUserMaxTotal(final String userName) { return get(perUserMaxTotal, userName, this::getDefaultMaxTotal); } /** * Gets the user specific value for {@link GenericObjectPool#getMaxWaitDuration()} for the specified user's pool or * the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. * @since 2.10.0 */ public Duration getPerUserMaxWaitDuration(final String userName) { return get(perUserMaxWaitDuration, userName, this::getDefaultMaxWait); } /** * Gets the user specific value for {@link GenericObjectPool#getMaxWaitDuration()} for the specified user's pool or * the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. * @deprecated Use {@link #getPerUserMaxWaitDuration}. */ @Deprecated public long getPerUserMaxWaitMillis(final String userName) { return getPerUserMaxWaitDuration(userName).toMillis(); } /** * Gets the user specific value for {@link GenericObjectPool#getMinEvictableIdleDuration()} for the specified * user's pool or the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value, never null. * @since 2.10.0 */ public Duration getPerUserMinEvictableIdleDuration(final String userName) { return get(perUserMinEvictableIdleDuration, userName, this::getDefaultMinEvictableIdleDuration); } /** * Gets the user specific value for {@link GenericObjectPool#getMinEvictableIdleDuration()} for the specified * user's pool or the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. * @deprecated Use {@link #getPerUserMinEvictableIdleDuration(String)}. */ @Deprecated public long getPerUserMinEvictableIdleTimeMillis(final String userName) { return getPerUserMinEvictableIdleDuration(userName).toMillis(); } /** * Gets the user specific value for {@link GenericObjectPool#getMinIdle()} for the specified user's pool or the * default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public int getPerUserMinIdle(final String userName) { return get(perUserMinIdle, userName, this::getDefaultMinIdle); } /** * Gets the user specific value for {@link GenericObjectPool#getNumTestsPerEvictionRun()} for the specified user's * pool or the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public int getPerUserNumTestsPerEvictionRun(final String userName) { return get(perUserNumTestsPerEvictionRun, userName, this::getDefaultNumTestsPerEvictionRun); } /** * Gets the user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleDuration()} for the specified * user's pool or the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. * @since 2.10.0 */ public Duration getPerUserSoftMinEvictableIdleDuration(final String userName) { return get(perUserSoftMinEvictableIdleDuration, userName, this::getDefaultSoftMinEvictableIdleDuration); } /** * Gets the user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleDuration()} for the specified * user's pool or the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. * @deprecated Use {@link #getPerUserSoftMinEvictableIdleDuration(String)}. */ @Deprecated public long getPerUserSoftMinEvictableIdleTimeMillis(final String userName) { return getPerUserSoftMinEvictableIdleDuration(userName).toMillis(); } /** * Gets the user specific value for {@link GenericObjectPool#getTestOnBorrow()} for the specified user's pool or the * default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public boolean getPerUserTestOnBorrow(final String userName) { return get(perUserTestOnBorrow, userName, this::getDefaultTestOnBorrow); } /** * Gets the user specific value for {@link GenericObjectPool#getTestOnCreate()} for the specified user's pool or the * default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public boolean getPerUserTestOnCreate(final String userName) { return get(perUserTestOnCreate, userName, this::getDefaultTestOnCreate); } /** * Gets the user specific value for {@link GenericObjectPool#getTestOnReturn()} for the specified user's pool or the * default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public boolean getPerUserTestOnReturn(final String userName) { return get(perUserTestOnReturn, userName, this::getDefaultTestOnReturn); } /** * Gets the user specific value for {@link GenericObjectPool#getTestWhileIdle()} for the specified user's pool or * the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. */ public boolean getPerUserTestWhileIdle(final String userName) { return get(perUserTestWhileIdle, userName, this::getDefaultTestWhileIdle); } /** * Gets the user specific value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for the specified * user's pool or the default if no user specific value is defined. * * @param userName * The user name key. * @return The user specific value. * @deprecated Use {@link #getPerUserDurationBetweenEvictionRuns(String)}. */ @Deprecated public long getPerUserTimeBetweenEvictionRunsMillis(final String userName) { return getPerUserDurationBetweenEvictionRuns(userName).toMillis(); } /** * Returns the object pool associated with the given PoolKey. * * @param poolKey * PoolKey identifying the pool * @return the GenericObjectPool pooling connections for the userName and datasource specified by the PoolKey */ private ObjectPool getPool(final PoolKey poolKey) { final CPDSConnectionFactory mgr = (CPDSConnectionFactory) managers.get(poolKey); return mgr == null ? null : mgr.getPool(); } @SuppressWarnings("resource") // does not allocate a pool @Override protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userName, final String password) throws SQLException { final PoolKey key = getPoolKey(userName); ObjectPool pool; PooledConnectionManager manager; synchronized (this) { manager = managers.get(key); if (manager == null) { try { registerPool(userName, password); manager = managers.get(key); } catch (final NamingException e) { throw new SQLException("RegisterPool failed", e); } } pool = getCPDSConnectionFactoryPool(manager); } PooledConnectionAndInfo info = null; try { info = pool.borrowObject(); } catch (final NoSuchElementException ex) { throw new SQLException("Could not retrieve connection info from pool", ex); } catch (final Exception e) { // See if failure is due to CPDSConnectionFactory authentication failure try { testCPDS(userName, password); } catch (final Exception ex) { throw new SQLException("Could not retrieve connection info from pool", ex); } // New password works, so kill the old pool, create a new one, and borrow manager.closePool(userName); synchronized (this) { managers.remove(key); } try { registerPool(userName, password); pool = getPool(key); } catch (final NamingException ne) { throw new SQLException("RegisterPool failed", ne); } try { info = pool.borrowObject(); } catch (final Exception ex) { throw new SQLException("Could not retrieve connection info from pool", ex); } } return info; } /** * Creates a pool key from the provided parameters. * * @param userName * User name * @return The pool key */ private PoolKey getPoolKey(final String userName) { return new PoolKey(getDataSourceName(), userName); } /** * Returns a {@code PerUserPoolDataSource} {@link Reference}. */ @Override public Reference getReference() throws NamingException { final Reference ref = new Reference(getClass().getName(), PerUserPoolDataSourceFactory.class.getName(), null); ref.add(new StringRefAddr("instanceKey", getInstanceKey())); return ref; } Map put(Map map, final K key, final V value) { if (map == null) { map = createMap(); } map.put(key, value); return map; } /** * Deserializes an instance from an ObjectInputStream. * * @param in The source ObjectInputStream. * @throws IOException Any of the usual Input/Output related exceptions. * @throws ClassNotFoundException A class of a serialized object cannot be found. */ @SuppressWarnings("resource") private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); this.managers = readObjectImpl().managers; } private PerUserPoolDataSource readObjectImpl() throws IOException, ClassNotFoundException { try { return (PerUserPoolDataSource) new PerUserPoolDataSourceFactory().getObjectInstance(getReference(), null, null, null); } catch (final NamingException e) { throw new IOException("NamingException: " + e); } } private synchronized void registerPool(final String userName, final String password) throws NamingException, SQLException { final ConnectionPoolDataSource cpds = testCPDS(userName, password); // Set up the factory we will use (passing the pool associates // the factory with the pool, so we do not have to do so // explicitly) final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, getValidationQuery(), getValidationQueryTimeoutDuration(), isRollbackAfterValidation(), userName, password); factory.setMaxConn(getMaxConnDuration()); // Create an object pool to contain our PooledConnections @SuppressWarnings("resource") final GenericObjectPool pool = new GenericObjectPool<>(factory); factory.setPool(pool); pool.setBlockWhenExhausted(getPerUserBlockWhenExhausted(userName)); pool.setEvictionPolicyClassName(getPerUserEvictionPolicyClassName(userName)); pool.setLifo(getPerUserLifo(userName)); pool.setMaxIdle(getPerUserMaxIdle(userName)); pool.setMaxTotal(getPerUserMaxTotal(userName)); pool.setMaxWait(getPerUserMaxWaitDuration(userName)); pool.setMinEvictableIdleDuration(getPerUserMinEvictableIdleDuration(userName)); pool.setMinIdle(getPerUserMinIdle(userName)); pool.setNumTestsPerEvictionRun(getPerUserNumTestsPerEvictionRun(userName)); pool.setSoftMinEvictableIdleDuration(getPerUserSoftMinEvictableIdleDuration(userName)); pool.setTestOnCreate(getPerUserTestOnCreate(userName)); pool.setTestOnBorrow(getPerUserTestOnBorrow(userName)); pool.setTestOnReturn(getPerUserTestOnReturn(userName)); pool.setTestWhileIdle(getPerUserTestWhileIdle(userName)); pool.setDurationBetweenEvictionRuns(getPerUserDurationBetweenEvictionRuns(userName)); pool.setSwallowedExceptionListener(new SwallowedExceptionLogger(log)); final PoolKey poolKey = getPoolKey(userName); if (managers.containsKey(poolKey)) { pool.close(); throw new IllegalStateException("Pool already contains an entry for this user/password: " + userName); } managers.put(poolKey, factory); } private Map replaceAll(final Map currentMap, final Map newMap) { if (currentMap == null) { return new HashMap<>(newMap); } currentMap.clear(); currentMap.putAll(newMap); return currentMap; } void setPerUserBlockWhenExhausted(final Map newMap) { assertInitializationAllowed(); perUserBlockWhenExhausted = replaceAll(perUserBlockWhenExhausted, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getBlockWhenExhausted()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserBlockWhenExhausted(final String userName, final Boolean value) { assertInitializationAllowed(); perUserBlockWhenExhausted = put(perUserBlockWhenExhausted, userName, value); } void setPerUserDefaultAutoCommit(final Map newMap) { assertInitializationAllowed(); perUserDefaultAutoCommit = replaceAll(perUserDefaultAutoCommit, newMap); } /** * Sets a user specific default value for {@link Connection#setAutoCommit(boolean)} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserDefaultAutoCommit(final String userName, final Boolean value) { assertInitializationAllowed(); perUserDefaultAutoCommit = put(perUserDefaultAutoCommit, userName, value); } void setPerUserDefaultReadOnly(final Map newMap) { assertInitializationAllowed(); perUserDefaultReadOnly = replaceAll(perUserDefaultReadOnly, newMap); } /** * Sets a user specific default value for {@link Connection#setReadOnly(boolean)} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserDefaultReadOnly(final String userName, final Boolean value) { assertInitializationAllowed(); perUserDefaultReadOnly = put(perUserDefaultReadOnly, userName, value); } void setPerUserDefaultTransactionIsolation(final Map newMap) { assertInitializationAllowed(); perUserDefaultTransactionIsolation = replaceAll(perUserDefaultTransactionIsolation, newMap); } /** * Sets a user specific default value for {@link Connection#setTransactionIsolation(int)} for the specified user's * pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserDefaultTransactionIsolation(final String userName, final Integer value) { assertInitializationAllowed(); perUserDefaultTransactionIsolation = put(perUserDefaultTransactionIsolation, userName, value); } void setPerUserDurationBetweenEvictionRuns(final Map newMap) { assertInitializationAllowed(); perUserDurationBetweenEvictionRuns = replaceAll(perUserDurationBetweenEvictionRuns, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for the specified * user's pool. * * @param userName * The user name key. * @param value * The user specific value. * @since 2.10.0 */ public void setPerUserDurationBetweenEvictionRuns(final String userName, final Duration value) { assertInitializationAllowed(); perUserDurationBetweenEvictionRuns = put(perUserDurationBetweenEvictionRuns, userName, value); } void setPerUserEvictionPolicyClassName(final Map newMap) { assertInitializationAllowed(); perUserEvictionPolicyClassName = replaceAll(perUserEvictionPolicyClassName, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's * pool. *

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

* @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserEvictionPolicyClassName(final String userName, final String value) { assertInitializationAllowed(); perUserEvictionPolicyClassName = put(perUserEvictionPolicyClassName, userName, value); } void setPerUserLifo(final Map newMap) { assertInitializationAllowed(); perUserLifo = replaceAll(perUserLifo, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getLifo()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserLifo(final String userName, final Boolean value) { assertInitializationAllowed(); perUserLifo = put(perUserLifo, userName, value); } void setPerUserMaxIdle(final Map newMap) { assertInitializationAllowed(); perUserMaxIdle = replaceAll(perUserMaxIdle, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getMaxIdle()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserMaxIdle(final String userName, final Integer value) { assertInitializationAllowed(); perUserMaxIdle = put(perUserMaxIdle, userName, value); } void setPerUserMaxTotal(final Map newMap) { assertInitializationAllowed(); perUserMaxTotal = replaceAll(perUserMaxTotal, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getMaxTotal()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserMaxTotal(final String userName, final Integer value) { assertInitializationAllowed(); perUserMaxTotal = put(perUserMaxTotal, userName, value); } /** * Sets a user specific value for {@link GenericObjectPool#getMaxWaitDuration()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. * @since 2.10.0 */ public void setPerUserMaxWait(final String userName, final Duration value) { assertInitializationAllowed(); perUserMaxWaitDuration = put(perUserMaxWaitDuration, userName, value); } void setPerUserMaxWaitDuration(final Map newMap) { assertInitializationAllowed(); perUserMaxWaitDuration = replaceAll(perUserMaxWaitDuration, newMap); } void setPerUserMaxWaitMillis(final Map newMap) { assertInitializationAllowed(); perUserMaxWaitDuration = convertMap(perUserMaxWaitDuration, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getMaxWaitDuration()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. * @deprecated Use {@link #setPerUserMaxWait(String, Duration)}. */ @Deprecated public void setPerUserMaxWaitMillis(final String userName, final Long value) { setPerUserMaxWait(userName, toDurationOrNull(value)); } void setPerUserMinEvictableIdle(final Map newMap) { assertInitializationAllowed(); perUserMinEvictableIdleDuration = replaceAll(perUserMinEvictableIdleDuration, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getMinEvictableIdleDuration()} for the specified user's * pool. * * @param userName * The user name key. * @param value * The user specific value. * @since 2.10.0 */ public void setPerUserMinEvictableIdle(final String userName, final Duration value) { assertInitializationAllowed(); perUserMinEvictableIdleDuration = put(perUserMinEvictableIdleDuration, userName, value); } /** * Sets a user specific value for {@link GenericObjectPool#getMinEvictableIdleDuration()} for the specified user's * pool. * * @param userName * The user name key. * @param value * The user specific value. * @deprecated Use {@link #setPerUserMinEvictableIdle(String, Duration)}. */ @Deprecated public void setPerUserMinEvictableIdleTimeMillis(final String userName, final Long value) { setPerUserMinEvictableIdle(userName, toDurationOrNull(value)); } void setPerUserMinIdle(final Map newMap) { assertInitializationAllowed(); perUserMinIdle = replaceAll(perUserMinIdle, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getMinIdle()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserMinIdle(final String userName, final Integer value) { assertInitializationAllowed(); perUserMinIdle = put(perUserMinIdle, userName, value); } void setPerUserNumTestsPerEvictionRun(final Map newMap) { assertInitializationAllowed(); perUserNumTestsPerEvictionRun = replaceAll(perUserNumTestsPerEvictionRun, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getNumTestsPerEvictionRun()} for the specified user's * pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserNumTestsPerEvictionRun(final String userName, final Integer value) { assertInitializationAllowed(); perUserNumTestsPerEvictionRun = put(perUserNumTestsPerEvictionRun, userName, value); } void setPerUserSoftMinEvictableIdle(final Map newMap) { assertInitializationAllowed(); perUserSoftMinEvictableIdleDuration = replaceAll(perUserSoftMinEvictableIdleDuration, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleDuration()} for the specified * user's pool. * * @param userName * The user name key. * @param value * The user specific value. * @since 2.10.0 */ public void setPerUserSoftMinEvictableIdle(final String userName, final Duration value) { assertInitializationAllowed(); perUserSoftMinEvictableIdleDuration = put(perUserSoftMinEvictableIdleDuration, userName, value); } /** * Sets a user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleDuration()} for the specified * user's pool. * * @param userName * The user name key. * @param value * The user specific value. * @deprecated Use {@link #setPerUserSoftMinEvictableIdle(String, Duration)}. */ @Deprecated public void setPerUserSoftMinEvictableIdleTimeMillis(final String userName, final Long value) { setPerUserSoftMinEvictableIdle(userName, toDurationOrNull(value)); } void setPerUserTestOnBorrow(final Map newMap) { assertInitializationAllowed(); perUserTestOnBorrow = replaceAll(perUserTestOnBorrow, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getTestOnBorrow()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserTestOnBorrow(final String userName, final Boolean value) { assertInitializationAllowed(); perUserTestOnBorrow = put(perUserTestOnBorrow, userName, value); } void setPerUserTestOnCreate(final Map newMap) { assertInitializationAllowed(); perUserTestOnCreate = replaceAll(perUserTestOnCreate, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getTestOnCreate()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserTestOnCreate(final String userName, final Boolean value) { assertInitializationAllowed(); perUserTestOnCreate = put(perUserTestOnCreate, userName, value); } void setPerUserTestOnReturn(final Map newMap) { assertInitializationAllowed(); perUserTestOnReturn = replaceAll(perUserTestOnReturn, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getTestOnReturn()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserTestOnReturn(final String userName, final Boolean value) { assertInitializationAllowed(); perUserTestOnReturn = put(perUserTestOnReturn, userName, value); } void setPerUserTestWhileIdle(final Map newMap) { assertInitializationAllowed(); perUserTestWhileIdle = replaceAll(perUserTestWhileIdle, newMap); } /** * Sets a user specific value for {@link GenericObjectPool#getTestWhileIdle()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserTestWhileIdle(final String userName, final Boolean value) { assertInitializationAllowed(); perUserTestWhileIdle = put(perUserTestWhileIdle, userName, value); } /** * Sets a user specific value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for the specified * user's pool. * * @param userName * The user name key. * @param value * The user specific value. * @deprecated Use {@link #setPerUserDurationBetweenEvictionRuns(String, Duration)}. */ @Deprecated public void setPerUserTimeBetweenEvictionRunsMillis(final String userName, final Long value) { setPerUserDurationBetweenEvictionRuns(userName, toDurationOrNull(value)); } @Override protected void setupDefaults(final Connection con, final String userName) throws SQLException { Boolean defaultAutoCommit = isDefaultAutoCommit(); if (userName != null) { final Boolean userMax = getPerUserDefaultAutoCommit(userName); if (userMax != null) { defaultAutoCommit = userMax; } } Boolean defaultReadOnly = isDefaultReadOnly(); if (userName != null) { final Boolean userMax = getPerUserDefaultReadOnly(userName); if (userMax != null) { defaultReadOnly = userMax; } } int defaultTransactionIsolation = getDefaultTransactionIsolation(); if (userName != null) { final Integer userMax = getPerUserDefaultTransactionIsolation(userName); if (userMax != null) { defaultTransactionIsolation = userMax; } } if (defaultAutoCommit != null && con.getAutoCommit() != defaultAutoCommit) { con.setAutoCommit(defaultAutoCommit); } if (defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION) { con.setTransactionIsolation(defaultTransactionIsolation); } if (defaultReadOnly != null && con.isReadOnly() != defaultReadOnly) { con.setReadOnly(defaultReadOnly); } } private Duration toDurationOrNull(final Long millis) { return millis == null ? null : Duration.ofMillis(millis); } } PerUserPoolDataSourceFactory.java000066400000000000000000000076311472045345700372730ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.IOException; import java.time.Duration; import java.util.Map; import javax.naming.RefAddr; import javax.naming.Reference; /** * A JNDI ObjectFactory which creates {@code SharedPoolDataSource}s * * @since 2.0 */ public class PerUserPoolDataSourceFactory extends InstanceKeyDataSourceFactory { private static final String PER_USER_POOL_CLASSNAME = PerUserPoolDataSource.class.getName(); @SuppressWarnings("unchecked") // Avoid warnings on deserialization @Override protected InstanceKeyDataSource getNewInstance(final Reference ref) throws IOException, ClassNotFoundException { final PerUserPoolDataSource pupds = new PerUserPoolDataSource(); RefAddr refAddr = ref.get("defaultMaxTotal"); if (refAddr != null && refAddr.getContent() != null) { pupds.setDefaultMaxTotal(parseInt(refAddr)); } refAddr = ref.get("defaultMaxIdle"); if (refAddr != null && refAddr.getContent() != null) { pupds.setDefaultMaxIdle(parseInt(refAddr)); } refAddr = ref.get("defaultMaxWaitMillis"); if (refAddr != null && refAddr.getContent() != null) { pupds.setDefaultMaxWait(Duration.ofMillis(parseInt(refAddr))); } refAddr = ref.get("perUserDefaultAutoCommit"); if (refAddr != null && refAddr.getContent() != null) { final byte[] serialized = (byte[]) refAddr.getContent(); pupds.setPerUserDefaultAutoCommit((Map) deserialize(serialized)); } refAddr = ref.get("perUserDefaultTransactionIsolation"); if (refAddr != null && refAddr.getContent() != null) { final byte[] serialized = (byte[]) refAddr.getContent(); pupds.setPerUserDefaultTransactionIsolation((Map) deserialize(serialized)); } refAddr = ref.get("perUserMaxTotal"); if (refAddr != null && refAddr.getContent() != null) { final byte[] serialized = (byte[]) refAddr.getContent(); pupds.setPerUserMaxTotal((Map) deserialize(serialized)); } refAddr = ref.get("perUserMaxIdle"); if (refAddr != null && refAddr.getContent() != null) { final byte[] serialized = (byte[]) refAddr.getContent(); pupds.setPerUserMaxIdle((Map) deserialize(serialized)); } refAddr = ref.get("perUserMaxWaitMillis"); if (refAddr != null && refAddr.getContent() != null) { final byte[] serialized = (byte[]) refAddr.getContent(); pupds.setPerUserMaxWaitMillis((Map) deserialize(serialized)); } refAddr = ref.get("perUserDefaultReadOnly"); if (refAddr != null && refAddr.getContent() != null) { final byte[] serialized = (byte[]) refAddr.getContent(); pupds.setPerUserDefaultReadOnly((Map) deserialize(serialized)); } return pupds; } @Override protected boolean isCorrectClass(final String className) { return PER_USER_POOL_CLASSNAME.equals(className); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java000066400000000000000000000042601472045345700332050ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.Serializable; import java.util.Objects; /** * The key type for entries in a {@link PerUserPoolDataSource}. * * @since 2.0 */ final class PoolKey implements Serializable { private static final long serialVersionUID = 2252771047542484533L; private final String dataSourceName; private final String userName; PoolKey(final String dataSourceName, final String userName) { this.dataSourceName = dataSourceName; this.userName = userName; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final PoolKey other = (PoolKey) obj; if (!Objects.equals(dataSourceName, other.dataSourceName)) { return false; } return Objects.equals(userName, other.userName); } @Override public int hashCode() { return Objects.hash(dataSourceName, userName); } @Override public String toString() { final StringBuilder sb = new StringBuilder(50); sb.append("PoolKey("); sb.append(dataSourceName); sb.append(')'); return sb.toString(); } } PooledConnectionAndInfo.java000066400000000000000000000036631472045345700362530ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import javax.sql.PooledConnection; /** * Immutable poolable object holding a {@link PooledConnection} along with the user name and password used to create the * connection. * * @since 2.0 */ final class PooledConnectionAndInfo { private final PooledConnection pooledConnection; private final UserPassKey userPassKey; PooledConnectionAndInfo(final PooledConnection pooledConnection, final UserPassKey userPassKey) { this.pooledConnection = pooledConnection; this.userPassKey = userPassKey; } /** * Gets the value of password. * * @return value of password. */ String getPassword() { return userPassKey.getPassword(); } /** * Gets the pooled connection. * * @return the pooled connection. */ PooledConnection getPooledConnection() { return pooledConnection; } /** * Gets the value of userName. * * @return value of userName. */ String getUserName() { return userPassKey.getUserName(); } UserPassKey getUserPassKey() { return userPassKey; } } PooledConnectionManager.java000066400000000000000000000044361472045345700363060ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.sql.SQLException; import javax.sql.PooledConnection; /** * Methods to manage PoolableConnections and the connection pools that source them. * * @since 2.0 */ interface PooledConnectionManager { /** * Closes the connection pool associated with the given user. * * @param userName * user name * @throws SQLException * if an error occurs closing idle connections in the pool */ void closePool(String userName) throws SQLException; /** * Closes the PooledConnection and remove it from the connection pool to which it belongs, adjusting pool counters. * * @param pc * PooledConnection to be invalidated * @throws SQLException * if an SQL error occurs closing the connection */ void invalidate(PooledConnection pc) throws SQLException; // /** // * Sets the database password used when creating connections. // * // * @param password password used when authenticating to the database // * @since 2.10.0 // */ // default void setPassword(char[] password) { // setPassword(String.copyValueOf(password)); // } /** * Sets the database password used when creating connections. * * @param password * password used when authenticating to the database */ void setPassword(String password); } SharedPoolDataSource.java000066400000000000000000000222361472045345700355620ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.IOException; import java.io.ObjectInputStream; import java.sql.Connection; import java.sql.SQLException; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.sql.ConnectionPoolDataSource; import org.apache.commons.pool2.KeyedObjectPool; import org.apache.commons.pool2.KeyedPooledObjectFactory; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; /** *

* A pooling {@code DataSource} appropriate for deployment within J2EE environment. There are many configuration * options, most of which are defined in the parent class. All users (based on user name) share a single maximum number * of Connections in this data source. *

* *

* User passwords can be changed without re-initializing the data source. When a * {@code getConnection(user name, password)} request is processed with a password that is different from those * used to create connections in the pool associated with {@code user name}, an attempt is made to create a new * connection using the supplied password and if this succeeds, idle connections created using the old password are * destroyed and new connections are created using the new password. *

* * @since 2.0 */ public class SharedPoolDataSource extends InstanceKeyDataSource { private static final long serialVersionUID = -1458539734480586454L; /** * Max total defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MAX_TOTAL}. */ private int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; /** * Maps user credentials to pooled connection with credentials. */ private transient KeyedObjectPool pool; /** * A {@link KeyedPooledObjectFactory} that creates {@link PoolableConnection}s. */ private transient KeyedCPDSConnectionFactory factory; /** * Default no-argument constructor for Serialization */ public SharedPoolDataSource() { // empty. } /** * Closes pool being maintained by this data source. */ @Override public void close() throws SQLException { if (pool != null) { pool.close(); } InstanceKeyDataSourceFactory.removeInstance(getInstanceKey()); } @Override protected PooledConnectionManager getConnectionManager(final UserPassKey userPassKey) { return factory; } /** * Gets {@link GenericKeyedObjectPool#getMaxTotal()} for this pool. * * @return {@link GenericKeyedObjectPool#getMaxTotal()} for this pool. */ public int getMaxTotal() { return this.maxTotal; } /** * Gets the number of active connections in the pool. * * @return The number of active connections in the pool. */ public int getNumActive() { return pool == null ? 0 : pool.getNumActive(); } /** * Gets the number of idle connections in the pool. * * @return The number of idle connections in the pool. */ public int getNumIdle() { return pool == null ? 0 : pool.getNumIdle(); } @Override protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userName, final String userPassword) throws SQLException { synchronized (this) { if (pool == null) { try { registerPool(userName, userPassword); } catch (final NamingException e) { throw new SQLException("registerPool failed", e); } } } try { return pool.borrowObject(new UserPassKey(userName, userPassword)); } catch (final Exception e) { throw new SQLException("Could not retrieve connection info from pool", e); } } /** * Creates a new {@link Reference} to a {@link SharedPoolDataSource}. */ @Override public Reference getReference() throws NamingException { final Reference ref = new Reference(getClass().getName(), SharedPoolDataSourceFactory.class.getName(), null); ref.add(new StringRefAddr("instanceKey", getInstanceKey())); return ref; } /** * Deserializes an instance from an ObjectInputStream. * * @param in The source ObjectInputStream. * @throws IOException Any of the usual Input/Output related exceptions. * @throws ClassNotFoundException A class of a serialized object cannot be found. */ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); this.pool = readObjectImpl(); } private KeyedObjectPool readObjectImpl() throws IOException, ClassNotFoundException { try { return ((SharedPoolDataSource) new SharedPoolDataSourceFactory().getObjectInstance(getReference(), null, null, null)).pool; } catch (final NamingException e) { throw new IOException("NamingException: " + e); } } private void registerPool(final String userName, final String password) throws NamingException, SQLException { final ConnectionPoolDataSource cpds = testCPDS(userName, password); // Create an object pool to contain our PooledConnections factory = new KeyedCPDSConnectionFactory(cpds, getValidationQuery(), getValidationQueryTimeoutDuration(), isRollbackAfterValidation()); factory.setMaxConn(getMaxConnDuration()); final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setBlockWhenExhausted(getDefaultBlockWhenExhausted()); config.setEvictionPolicyClassName(getDefaultEvictionPolicyClassName()); config.setLifo(getDefaultLifo()); config.setMaxIdlePerKey(getDefaultMaxIdle()); config.setMaxTotal(getMaxTotal()); config.setMaxTotalPerKey(getDefaultMaxTotal()); config.setMaxWait(getDefaultMaxWait()); config.setMinEvictableIdleDuration(getDefaultMinEvictableIdleDuration()); config.setMinIdlePerKey(getDefaultMinIdle()); config.setNumTestsPerEvictionRun(getDefaultNumTestsPerEvictionRun()); config.setSoftMinEvictableIdleDuration(getDefaultSoftMinEvictableIdleDuration()); config.setTestOnCreate(getDefaultTestOnCreate()); config.setTestOnBorrow(getDefaultTestOnBorrow()); config.setTestOnReturn(getDefaultTestOnReturn()); config.setTestWhileIdle(getDefaultTestWhileIdle()); config.setTimeBetweenEvictionRuns(getDefaultDurationBetweenEvictionRuns()); final KeyedObjectPool tmpPool = new GenericKeyedObjectPool<>(factory, config); factory.setPool(tmpPool); pool = tmpPool; } /** * Sets {@link GenericKeyedObjectPool#getMaxTotal()} for this pool. * * @param maxTotal * {@link GenericKeyedObjectPool#getMaxTotal()} for this pool. */ public void setMaxTotal(final int maxTotal) { assertInitializationAllowed(); this.maxTotal = maxTotal; } @Override protected void setupDefaults(final Connection connection, final String userName) throws SQLException { final Boolean defaultAutoCommit = isDefaultAutoCommit(); if (defaultAutoCommit != null && connection.getAutoCommit() != defaultAutoCommit) { connection.setAutoCommit(defaultAutoCommit); } final int defaultTransactionIsolation = getDefaultTransactionIsolation(); if (defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION) { connection.setTransactionIsolation(defaultTransactionIsolation); } final Boolean defaultReadOnly = isDefaultReadOnly(); if (defaultReadOnly != null && connection.isReadOnly() != defaultReadOnly) { connection.setReadOnly(defaultReadOnly); } } @Override protected void toStringFields(final StringBuilder builder) { super.toStringFields(builder); builder.append(", maxTotal="); builder.append(maxTotal); } } SharedPoolDataSourceFactory.java000066400000000000000000000034231472045345700371070ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import javax.naming.RefAddr; import javax.naming.Reference; /** * A JNDI ObjectFactory which creates {@code SharedPoolDataSource}s * * @since 2.0 */ public class SharedPoolDataSourceFactory extends InstanceKeyDataSourceFactory { private static final String SHARED_POOL_CLASSNAME = SharedPoolDataSource.class.getName(); /** * Constructs a new instance. */ public SharedPoolDataSourceFactory() { // empty } @Override protected InstanceKeyDataSource getNewInstance(final Reference ref) { final SharedPoolDataSource spds = new SharedPoolDataSource(); final RefAddr ra = ref.get("maxTotal"); if (ra != null && ra.getContent() != null) { spds.setMaxTotal(Integer.parseInt(ra.getContent().toString())); } return spds; } @Override protected boolean isCorrectClass(final String className) { return SHARED_POOL_CLASSNAME.equals(className); } } UserPassKey.java000066400000000000000000000066621472045345700337720ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.Serializable; import java.util.Objects; import org.apache.commons.pool2.KeyedObjectPool; /** *

* Holds a user name and password pair. Serves as a poolable object key for the {@link KeyedObjectPool} backing a * {@link SharedPoolDataSource}. Two instances with the same user name are considered equal. This ensures that there * will be only one keyed pool for each user in the pool. The password is used (along with the user name) by the * {@code KeyedCPDSConnectionFactory} when creating new connections. *

* *

* {@link InstanceKeyDataSource#getConnection(String, String)} validates that the password used to create a connection * matches the password provided by the client. *

* * @since 2.0 */ final class UserPassKey implements Serializable { private static final long serialVersionUID = 5142970911626584817L; private final CharArray name; private final CharArray password; UserPassKey(final CharArray userName, final CharArray userPassword) { this.name = userName; this.password = userPassword; } UserPassKey(final String userName) { this(new CharArray(userName), CharArray.NULL); } UserPassKey(final String userName, final char[] password) { this(new CharArray(userName), new CharArray(password)); } UserPassKey(final String userName, final String userPassword) { this(new CharArray(userName), new CharArray(userPassword)); } /** * Only takes the user name into account. */ @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final UserPassKey other = (UserPassKey) obj; return Objects.equals(name, other.name); } /** * Gets the value of password. * * @return value of password. */ String getPassword() { return password.asString(); } /** * Gets the value of password. * * @return value of password. */ char[] getPasswordCharArray() { return password.get(); } /** * Gets the value of user name. * * @return value of user name. */ String getUserName() { return name.asString(); } /** * Only takes the user name into account. */ @Override public int hashCode() { return Objects.hash(name); } } package-info.java000066400000000000000000000130351472045345700340700ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/datasources/* * 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. */ /** *

* This package contains two DataSources: {@code PerUserPoolDataSource} and * {@code SharedPoolDataSource} which provide a database connection pool. * Below are a couple of usage examples. One shows deployment into a JNDI system. * The other is a simple example initializing the pool using standard Java code. *

*

JNDI

*

* Most * J2EE containers will provide some way of deploying resources into JNDI. The * method will vary among containers, but once the resource is available via * JNDI, the application can access the resource in a container independent * manner. The following example shows deployment into tomcat (catalina). *

*

In server.xml, the following would be added to the <Context> for your * webapp: *

*
 *  <Resource name="jdbc/bookstore" auth="Container"
 *             type="org.apache.commons.dbcp2.datasources.PerUserPoolPoolDataSource"/>
 *   <ResourceParams name="jdbc/bookstore">
 *     <parameter>
 *       <name>factory</name>
 *       <value>org.apache.commons.dbcp2.datasources.PerUserPoolDataSourceFactory</value>
 *     </parameter>
 *     <parameter>
 *       <name>dataSourceName</name><value>java:comp/env/jdbc/bookstoreCPDS</value>
 *     </parameter>
 *     <parameter>
 *       <name>defaultMaxTotal</name><value>30</value>
 *     </parameter>
 *   </ResourceParams>
 * 
*

* In web.xml. Note that elements must be given in the order of the dtd * described in the servlet specification: *

*
 * <resource-ref>
 *   <description>
 *     Resource reference to a factory for java.sql.Connection
 *     instances that may be used for talking to a particular
 *     database that is configured in the server.xml file.
 *   </description>
 *   <res-ref-name>
 *     jdbc/bookstore
 *   </res-ref-name>
 *   <res-type>
 *     org.apache.commons.dbcp2.datasources.PerUserPoolDataSource
 *   </res-type>
 *   <res-auth>
 *     Container
 *   </res-auth>
 * </resource-ref>
 * 
*

* Apache Tomcat deploys all objects configured similarly to above within the * java:comp/env namespace. So the JNDI path given for * the dataSourceName parameter is valid for a * {@code ConnectionPoolDataSource} that is deployed as given in the * cpdsadapter example *

*

* The {@code DataSource} is now available to the application as shown * below: *

*
 *     Context ctx = new InitialContext();
 *     DataSource ds = (DataSource)
 *         ctx.lookup("java:comp/env/jdbc/bookstore");
 *     Connection con = null;
 *     try
 *     {
 *         con = ds.getConnection();
 *         ...
 *         use the connection
 *         ...
 *     }
 *     finally
 *     {
 *         if (con != null)
 *             con.close();
 *     }
 * 
*

* The reference to the {@code DataSource} could be maintained, for * multiple getConnection() requests. Or the {@code DataSource} can be * looked up in different parts of the application code. * {@code PerUserPoolDataSourceFactory} and * {@code SharedPoolDataSourceFactory} will maintain the state of the pool * between different lookups. This behavior may be different in other * implementations. *

*

Without JNDI

*

* Connection pooling is useful in applications regardless of whether they run * in a J2EE environment and a {@code DataSource} can be used within a * simpler environment. The example below shows SharedPoolDataSource using * DriverAdapterCPDS as the back end source, though any CPDS is applicable. *

*
 * public class Pool {
 *
 *     private static DataSource ds;
 *
 *     static {
 *         DriverAdapterCPDS cpds = new DriverAdapterCPDS();
 *         cpds.setDriver("org.gjt.mm.mysql.Driver");
 *         cpds.setUrl("jdbc:mysql://localhost:3306/bookstore");
 *         cpds.setUser("foo");
 *         cpds.setPassword(null);
 *
 *         SharedPoolDataSource tds = new SharedPoolDataSource();
 *         tds.setConnectionPoolDataSource(cpds);
 *         tds.setMaxTotal(10);
 *         tds.setMaxWaitMillis(50);
 *
 *         ds = tds;
 *     }
 *
 *     public static getConnection() {
 *         return ds.getConnection();
 *     }
 * }
 * 
*

* This class can then be used wherever a connection is needed: *

*
 *     Connection con = null;
 *     try {
 *         con = Pool.getConnection();
 *         ...
 *         use the connection
 *         ...
 *     } finally {
 *         if (con != null) {
 *             con.close();
 *         }
 *     }
 * 
*/ package org.apache.commons.dbcp2.datasources; commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/000077500000000000000000000000001472045345700300355ustar00rootroot00000000000000BasicManagedDataSource.java000066400000000000000000000253321472045345700350770ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.SQLException; import javax.sql.DataSource; import javax.sql.XADataSource; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.ConnectionFactory; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.PoolingDataSource; import org.apache.commons.dbcp2.Utils; /** *

* BasicManagedDataSource is an extension of BasicDataSource which creates ManagedConnections. This data source can * create either full two-phase-commit XA connections or one-phase-commit local connections. Both types of connections * are committed or rolled back as part of the global transaction (a.k.a. XA transaction or JTA Transaction), but only * XA connections can be recovered in the case of a system crash. *

*

* BasicManagedDataSource adds the TransactionManager and XADataSource properties. The TransactionManager property is * required and is used to enlist connections in global transactions. The XADataSource is optional and if set is the * class name of the XADataSource class for a two-phase-commit JDBC driver. If the XADataSource property is set, the * driverClassName is ignored and a DataSourceXAConnectionFactory is created. Otherwise, a standard * DriverConnectionFactory is created and wrapped with a LocalXAConnectionFactory. *

* * @see BasicDataSource * @see ManagedConnection * @since 2.0 */ public class BasicManagedDataSource extends BasicDataSource { /** Transaction Registry */ private TransactionRegistry transactionRegistry; /** Transaction Manager */ private transient TransactionManager transactionManager; /** XA data source class name */ private String xaDataSource; /** XA data source instance */ private XADataSource xaDataSourceInstance; /** Transaction Synchronization Registry */ private transient TransactionSynchronizationRegistry transactionSynchronizationRegistry; @Override protected ConnectionFactory createConnectionFactory() throws SQLException { if (transactionManager == null) { throw new SQLException("Transaction manager must be set before a connection can be created"); } // If XA data source is not specified a DriverConnectionFactory is created and wrapped with a // LocalXAConnectionFactory if (xaDataSource == null) { final ConnectionFactory connectionFactory = super.createConnectionFactory(); final XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(getTransactionManager(), getTransactionSynchronizationRegistry(), connectionFactory); transactionRegistry = xaConnectionFactory.getTransactionRegistry(); return xaConnectionFactory; } // Create the XADataSource instance using the configured class name if it has not been set if (xaDataSourceInstance == null) { Class xaDataSourceClass = null; try { xaDataSourceClass = Class.forName(xaDataSource); } catch (final Exception e) { throw new SQLException("Cannot load XA data source class '" + xaDataSource + "'", e); } try { xaDataSourceInstance = (XADataSource) xaDataSourceClass.getConstructor().newInstance(); } catch (final Exception e) { throw new SQLException("Cannot create XA data source of class '" + xaDataSource + "'", e); } } // finally, create the XAConnectionFactory using the XA data source final XAConnectionFactory xaConnectionFactory = new DataSourceXAConnectionFactory(getTransactionManager(), xaDataSourceInstance, getUserName(), Utils.toCharArray(getPassword()), getTransactionSynchronizationRegistry()); transactionRegistry = xaConnectionFactory.getTransactionRegistry(); return xaConnectionFactory; } @Override protected DataSource createDataSourceInstance() throws SQLException { final PoolingDataSource pds = new ManagedDataSource<>(getConnectionPool(), transactionRegistry); pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); return pds; } /** * Creates the PoolableConnectionFactory and attaches it to the connection pool. * * @param driverConnectionFactory * JDBC connection factory created by {@link #createConnectionFactory()} * @throws SQLException * if an error occurs creating the PoolableConnectionFactory */ @Override protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory) throws SQLException { PoolableConnectionFactory connectionFactory = null; try { connectionFactory = new PoolableManagedConnectionFactory((XAConnectionFactory) driverConnectionFactory, getRegisteredJmxName()); connectionFactory.setValidationQuery(getValidationQuery()); connectionFactory.setValidationQueryTimeout(getValidationQueryTimeoutDuration()); connectionFactory.setConnectionInitSql(getConnectionInitSqls()); connectionFactory.setDefaultReadOnly(getDefaultReadOnly()); connectionFactory.setDefaultAutoCommit(getDefaultAutoCommit()); connectionFactory.setDefaultTransactionIsolation(getDefaultTransactionIsolation()); connectionFactory.setDefaultCatalog(getDefaultCatalog()); connectionFactory.setDefaultSchema(getDefaultSchema()); connectionFactory.setCacheState(getCacheState()); connectionFactory.setPoolStatements(isPoolPreparedStatements()); connectionFactory.setClearStatementPoolOnReturn(isClearStatementPoolOnReturn()); connectionFactory.setMaxOpenPreparedStatements(getMaxOpenPreparedStatements()); connectionFactory.setMaxConn(getMaxConnDuration()); connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn()); connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration()); connectionFactory.setFastFailValidation(getFastFailValidation()); connectionFactory.setDisconnectionSqlCodes(getDisconnectionSqlCodes()); connectionFactory.setDisconnectionIgnoreSqlCodes(getDisconnectionIgnoreSqlCodes()); validateConnectionFactory(connectionFactory); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e); } return connectionFactory; } /** * Gets the required transaction manager property. * * @return the transaction manager used to enlist connections */ public TransactionManager getTransactionManager() { return transactionManager; } /** * Gets the transaction registry. * * @return the transaction registry associating XAResources with managed connections */ protected synchronized TransactionRegistry getTransactionRegistry() { return transactionRegistry; } /** * Gets the optional TransactionSynchronizationRegistry. * * @return the TSR that can be used to register synchronizations. * @since 2.6.0 */ public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() { return transactionSynchronizationRegistry; } /** * Gets the optional XADataSource class name. * * @return the optional XADataSource class name */ public synchronized String getXADataSource() { return xaDataSource; } /** * Gets the XADataSource instance used by the XAConnectionFactory. * * @return the XADataSource */ public synchronized XADataSource getXaDataSourceInstance() { return xaDataSourceInstance; } /** * Sets the required transaction manager property. * * @param transactionManager * the transaction manager used to enlist connections */ public void setTransactionManager(final TransactionManager transactionManager) { this.transactionManager = transactionManager; } /** * Sets the optional TransactionSynchronizationRegistry property. * * @param transactionSynchronizationRegistry * the TSR used to register synchronizations * @since 2.6.0 */ public void setTransactionSynchronizationRegistry( final TransactionSynchronizationRegistry transactionSynchronizationRegistry) { this.transactionSynchronizationRegistry = transactionSynchronizationRegistry; } /** * Sets the optional XADataSource class name. * * @param xaDataSource * the optional XADataSource class name */ public synchronized void setXADataSource(final String xaDataSource) { this.xaDataSource = xaDataSource; } /** * Sets the XADataSource instance used by the XAConnectionFactory. *

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

* * @param xaDataSourceInstance XADataSource instance */ public synchronized void setXaDataSourceInstance(final XADataSource xaDataSourceInstance) { this.xaDataSourceInstance = xaDataSourceInstance; xaDataSource = xaDataSourceInstance == null ? null : xaDataSourceInstance.getClass().getName(); } } DataSourceXAConnectionFactory.java000066400000000000000000000246461472045345700364700ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.PooledConnection; import javax.sql.XAConnection; import javax.sql.XADataSource; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAResource; import org.apache.commons.dbcp2.Utils; /** * An implementation of XAConnectionFactory which uses a real XADataSource to obtain connections and XAResources. * * @since 2.0 */ public class DataSourceXAConnectionFactory implements XAConnectionFactory { private static final class XAConnectionEventListener implements ConnectionEventListener { @Override public void connectionClosed(final ConnectionEvent event) { final PooledConnection pc = (PooledConnection) event.getSource(); pc.removeConnectionEventListener(this); try { pc.close(); } catch (final SQLException e) { System.err.println("Failed to close XAConnection"); e.printStackTrace(); } } @Override public void connectionErrorOccurred(final ConnectionEvent event) { connectionClosed(event); } } private final TransactionRegistry transactionRegistry; private final XADataSource xaDataSource; private String userName; private char[] userPassword; /** * Creates an DataSourceXAConnectionFactory which uses the specified XADataSource to create database connections. * The connections are enlisted into transactions using the specified transaction manager. * * @param transactionManager * the transaction manager in which connections will be enlisted * @param xaDataSource * the data source from which connections will be retrieved * @since 2.6.0 */ public DataSourceXAConnectionFactory(final TransactionManager transactionManager, final XADataSource xaDataSource) { this(transactionManager, xaDataSource, null, (char[]) null, null); } /** * Creates an DataSourceXAConnectionFactory which uses the specified XADataSource to create database connections. * The connections are enlisted into transactions using the specified transaction manager. * * @param transactionManager * the transaction manager in which connections will be enlisted * @param xaDataSource * the data source from which connections will be retrieved * @param userName * the user name used for authenticating new connections or null for unauthenticated * @param userPassword * the password used for authenticating new connections */ public DataSourceXAConnectionFactory(final TransactionManager transactionManager, final XADataSource xaDataSource, final String userName, final char[] userPassword) { this(transactionManager, xaDataSource, userName, userPassword, null); } /** * Creates an DataSourceXAConnectionFactory which uses the specified XADataSource to create database connections. * The connections are enlisted into transactions using the specified transaction manager. * * @param transactionManager * the transaction manager in which connections will be enlisted * @param xaDataSource * the data source from which connections will be retrieved * @param userName * the user name used for authenticating new connections or null for unauthenticated * @param userPassword * the password used for authenticating new connections * @param transactionSynchronizationRegistry * register with this TransactionSynchronizationRegistry * @since 2.6.0 */ public DataSourceXAConnectionFactory(final TransactionManager transactionManager, final XADataSource xaDataSource, final String userName, final char[] userPassword, final TransactionSynchronizationRegistry transactionSynchronizationRegistry) { Objects.requireNonNull(transactionManager, "transactionManager"); Objects.requireNonNull(xaDataSource, "xaDataSource"); // We do allow the transactionSynchronizationRegistry to be null for non-app server environments this.transactionRegistry = new TransactionRegistry(transactionManager, transactionSynchronizationRegistry); this.xaDataSource = xaDataSource; this.userName = userName; this.userPassword = Utils.clone(userPassword); } /** * Creates an DataSourceXAConnectionFactory which uses the specified XADataSource to create database connections. * The connections are enlisted into transactions using the specified transaction manager. * * @param transactionManager * the transaction manager in which connections will be enlisted * @param xaDataSource * the data source from which connections will be retrieved * @param userName * the user name used for authenticating new connections or null for unauthenticated * @param userPassword * the password used for authenticating new connections */ public DataSourceXAConnectionFactory(final TransactionManager transactionManager, final XADataSource xaDataSource, final String userName, final String userPassword) { this(transactionManager, xaDataSource, userName, Utils.toCharArray(userPassword), null); } /** * Creates an DataSourceXAConnectionFactory which uses the specified XADataSource to create database connections. * The connections are enlisted into transactions using the specified transaction manager. * * @param transactionManager * the transaction manager in which connections will be enlisted * @param xaDataSource * the data source from which connections will be retrieved * @param transactionSynchronizationRegistry * register with this TransactionSynchronizationRegistry */ public DataSourceXAConnectionFactory(final TransactionManager transactionManager, final XADataSource xaDataSource, final TransactionSynchronizationRegistry transactionSynchronizationRegistry) { this(transactionManager, xaDataSource, null, (char[]) null, transactionSynchronizationRegistry); } @Override public Connection createConnection() throws SQLException { // create a new XAConnection final XAConnection xaConnection; if (userName == null) { xaConnection = xaDataSource.getXAConnection(); } else { xaConnection = xaDataSource.getXAConnection(userName, Utils.toString(userPassword)); } // get the real connection and XAResource from the connection final Connection connection = xaConnection.getConnection(); final XAResource xaResource = xaConnection.getXAResource(); // register the XA resource for the connection transactionRegistry.registerConnection(connection, xaResource); // The Connection we're returning is a handle on the XAConnection. // When the pool calling us closes the Connection, we need to // also close the XAConnection that holds the physical connection. xaConnection.addConnectionEventListener(new XAConnectionEventListener()); return connection; } @Override public TransactionRegistry getTransactionRegistry() { return transactionRegistry; } /** * Gets the user name used to authenticate new connections. * * @return the user name or null if unauthenticated connections are used * @deprecated Use {@link #getUserName()}. */ @Deprecated public String getUsername() { return userName; } /** * Gets the user name used to authenticate new connections. * * @return the user name or null if unauthenticated connections are used * @since 2.6.0 */ public String getUserName() { return userName; } /** * Gets the user password. * * @return the user password. */ public char[] getUserPassword() { return Utils.clone(userPassword); } /** * Gets the XA data source. * * @return the XA data source. */ public XADataSource getXaDataSource() { return xaDataSource; } /** * Sets the password used to authenticate new connections. * * @param userPassword * the password used for authenticating the connection or null for unauthenticated. * @since 2.4.0 */ public void setPassword(final char[] userPassword) { this.userPassword = Utils.clone(userPassword); } /** * Sets the password used to authenticate new connections. * * @param userPassword * the password used for authenticating the connection or null for unauthenticated */ public void setPassword(final String userPassword) { this.userPassword = Utils.toCharArray(userPassword); } /** * Sets the user name used to authenticate new connections. * * @param userName * the user name used for authenticating the connection or null for unauthenticated */ public void setUsername(final String userName) { this.userName = userName; } } LocalXAConnectionFactory.java000066400000000000000000000367011472045345700354630ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import org.apache.commons.dbcp2.ConnectionFactory; /** * An implementation of XAConnectionFactory which manages non-XA connections in XA transactions. A non-XA connection * commits and rolls back as part of the XA transaction, but is not recoverable since the connection does not implement * the 2-phase protocol. * * @since 2.0 */ public class LocalXAConnectionFactory implements XAConnectionFactory { /** * LocalXAResource is a fake XAResource for non-XA connections. When a transaction is started the connection * auto-commit is turned off. When the connection is committed or rolled back, the commit or rollback method is * called on the connection and then the original auto-commit value is restored. *

* The LocalXAResource also respects the connection read-only setting. If the connection is read-only the commit * method will not be called, and the prepare method returns the XA_RDONLY. *

*

* It is assumed that the wrapper around a managed connection disables the setAutoCommit(), commit(), rollback() and * setReadOnly() methods while a transaction is in progress. *

* * @since 2.0 */ protected static class LocalXAResource implements XAResource { private static final Xid[] EMPTY_XID_ARRAY = {}; private final Connection connection; private Xid currentXid; // @GuardedBy("this") private boolean originalAutoCommit; // @GuardedBy("this") /** * Constructs a new instance for a given connection. * * @param localTransaction A connection. */ public LocalXAResource(final Connection localTransaction) { this.connection = localTransaction; } private Xid checkCurrentXid() throws XAException { if (this.currentXid == null) { throw new XAException("There is no current transaction"); } return currentXid; } /** * Commits the transaction and restores the original auto commit setting. * * @param xid * the id of the transaction branch for this connection * @param flag * ignored * @throws XAException * if connection.commit() throws an SQLException */ @Override public synchronized void commit(final Xid xid, final boolean flag) throws XAException { Objects.requireNonNull(xid, "xid"); if (!checkCurrentXid().equals(xid)) { throw new XAException("Invalid Xid: expected " + this.currentXid + ", but was " + xid); } try { // make sure the connection isn't already closed if (connection.isClosed()) { throw new XAException("Connection is closed"); } // A read only connection should not be committed if (!connection.isReadOnly()) { connection.commit(); } } catch (final SQLException e) { throw (XAException) new XAException().initCause(e); } finally { try { connection.setAutoCommit(originalAutoCommit); } catch (final SQLException ignored) { // ignored } this.currentXid = null; } } /** * This method does nothing. * * @param xid * the id of the transaction branch for this connection * @param flag * ignored * @throws XAException * if the connection is already enlisted in another transaction */ @Override public synchronized void end(final Xid xid, final int flag) throws XAException { Objects.requireNonNull(xid, "xid"); if (!checkCurrentXid().equals(xid)) { throw new XAException("Invalid Xid: expected " + this.currentXid + ", but was " + xid); } // This notification tells us that the application server is done using this // connection for the time being. The connection is still associated with an // open transaction, so we must still wait for the commit or rollback method } /** * Clears the currently associated transaction if it is the specified xid. * * @param xid * the id of the transaction to forget */ @Override public synchronized void forget(final Xid xid) { if (xid != null && xid.equals(currentXid)) { currentXid = null; } } /** * Always returns 0 since we have no way to set a transaction timeout on a JDBC connection. * * @return always 0 */ @Override public int getTransactionTimeout() { return 0; } /** * Gets the current xid of the transaction branch associated with this XAResource. * * @return the current xid of the transaction branch associated with this XAResource. */ public synchronized Xid getXid() { return currentXid; } /** * Returns true if the specified XAResource == this XAResource. * * @param xaResource * the XAResource to test * @return true if the specified XAResource == this XAResource; false otherwise */ @Override public boolean isSameRM(final XAResource xaResource) { return this == xaResource; } /** * This method does nothing since the LocalXAConnection does not support two-phase-commit. This method will * return XAResource.XA_RDONLY if the connection isReadOnly(). This assumes that the physical connection is * wrapped with a proxy that prevents an application from changing the read-only flag while enrolled in a * transaction. * * @param xid * the id of the transaction branch for this connection * @return XAResource.XA_RDONLY if the connection.isReadOnly(); XAResource.XA_OK otherwise */ @Override public synchronized int prepare(final Xid xid) { // if the connection is read-only, then the resource is read-only // NOTE: this assumes that the outer proxy throws an exception when application code // attempts to set this in a transaction try { if (connection.isReadOnly()) { // update the auto commit flag connection.setAutoCommit(originalAutoCommit); // tell the transaction manager we are read only return XA_RDONLY; } } catch (final SQLException ignored) { // no big deal } // this is a local (one phase) only connection, so we can't prepare return XA_OK; } /** * Always returns a zero length Xid array. The LocalXAConnectionFactory cannot support recovery, so no xids * will ever be found. * * @param flag * ignored since recovery is not supported * @return always a zero length Xid array. */ @Override public Xid[] recover(final int flag) { return EMPTY_XID_ARRAY; } /** * Rolls back the transaction and restores the original auto commit setting. * * @param xid * the id of the transaction branch for this connection * @throws XAException * if connection.rollback() throws an SQLException */ @Override public synchronized void rollback(final Xid xid) throws XAException { Objects.requireNonNull(xid, "xid"); if (!checkCurrentXid().equals(xid)) { throw new XAException("Invalid Xid: expected " + this.currentXid + ", but was " + xid); } try { connection.rollback(); } catch (final SQLException e) { throw (XAException) new XAException().initCause(e); } finally { try { connection.setAutoCommit(originalAutoCommit); } catch (final SQLException ignored) { // Ignored. } this.currentXid = null; } } /** * Always returns false since we have no way to set a transaction timeout on a JDBC connection. * * @param transactionTimeout * ignored since we have no way to set a transaction timeout on a JDBC connection * @return always false */ @Override public boolean setTransactionTimeout(final int transactionTimeout) { return false; } /** * Signals that a connection has been enrolled in a transaction. This method saves off the current auto * commit flag, and then disables auto commit. The original auto commit setting is restored when the transaction * completes. * * @param xid * the id of the transaction branch for this connection * @param flag * either XAResource.TMNOFLAGS or XAResource.TMRESUME * @throws XAException * if the connection is already enlisted in another transaction, or if auto-commit could not be * disabled */ @Override public synchronized void start(final Xid xid, final int flag) throws XAException { if (flag == TMNOFLAGS) { // first time in this transaction // make sure we aren't already in another tx if (this.currentXid != null) { throw new XAException("Already enlisted in another transaction with xid " + xid); } // save off the current auto commit flag, so it can be restored after the transaction completes try { originalAutoCommit = connection.getAutoCommit(); } catch (final SQLException ignored) { // no big deal, just assume it was off originalAutoCommit = true; } // update the auto commit flag try { connection.setAutoCommit(false); } catch (final SQLException e) { throw (XAException) new XAException("Count not turn off auto commit for a XA transaction") .initCause(e); } this.currentXid = xid; } else if (flag == TMRESUME) { if (!xid.equals(this.currentXid)) { throw new XAException("Attempting to resume in different transaction: expected " + this.currentXid + ", but was " + xid); } } else { throw new XAException("Unknown start flag " + flag); } } } private final TransactionRegistry transactionRegistry; private final ConnectionFactory connectionFactory; /** * Creates an LocalXAConnectionFactory which uses the specified connection factory to create database connections. * The connections are enlisted into transactions using the specified transaction manager. * * @param transactionManager * the transaction manager in which connections will be enlisted * @param connectionFactory * the connection factory from which connections will be retrieved */ public LocalXAConnectionFactory(final TransactionManager transactionManager, final ConnectionFactory connectionFactory) { this(transactionManager, null, connectionFactory); } /** * Creates an LocalXAConnectionFactory which uses the specified connection factory to create database connections. * The connections are enlisted into transactions using the specified transaction manager. * * @param transactionManager * the transaction manager in which connections will be enlisted * @param transactionSynchronizationRegistry * the optional TSR to register synchronizations with * @param connectionFactory * the connection factory from which connections will be retrieved * @since 2.8.0 */ public LocalXAConnectionFactory(final TransactionManager transactionManager, final TransactionSynchronizationRegistry transactionSynchronizationRegistry, final ConnectionFactory connectionFactory) { Objects.requireNonNull(transactionManager, "transactionManager"); Objects.requireNonNull(connectionFactory, "connectionFactory"); this.transactionRegistry = new TransactionRegistry(transactionManager, transactionSynchronizationRegistry); this.connectionFactory = connectionFactory; } @Override public Connection createConnection() throws SQLException { // create a new connection final Connection connection = connectionFactory.createConnection(); // create a XAResource to manage the connection during XA transactions final XAResource xaResource = new LocalXAResource(connection); // register the XA resource for the connection transactionRegistry.registerConnection(connection, xaResource); return connection; } /** * Gets the connection factory. * * @return The connection factory. * @since 2.6.0 */ public ConnectionFactory getConnectionFactory() { return connectionFactory; } /** * Gets the transaction registry. * * @return The transaction registry. */ @Override public TransactionRegistry getTransactionRegistry() { return transactionRegistry; } } ManagedConnection.java000066400000000000000000000320171472045345700342000ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.Connection; import java.sql.SQLException; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.dbcp2.DelegatingConnection; import org.apache.commons.pool2.ObjectPool; /** * ManagedConnection is responsible for managing a database connection in a transactional environment (typically called * "Container Managed"). A managed connection operates like any other connection when no global transaction (a.k.a. XA * transaction or JTA Transaction) is in progress. When a global transaction is active a single physical connection to * the database is used by all ManagedConnections accessed in the scope of the transaction. Connection sharing means * that all data access during a transaction has a consistent view of the database. When the global transaction is * committed or rolled back the enlisted connections are committed or rolled back. Typically, upon transaction * completion, a connection returns to the auto commit setting in effect before being enlisted in the transaction, but * some vendors do not properly implement this. *

* When enlisted in a transaction the setAutoCommit(), commit(), rollback(), and setReadOnly() methods throw a * SQLException. This is necessary to assure that the transaction completes as a single unit. *

* * @param * the Connection type * * @since 2.0 */ public class ManagedConnection extends DelegatingConnection { /** * Delegates to {@link ManagedConnection#transactionComplete()} for transaction completion events. * * @since 2.0 */ protected class CompletionListener implements TransactionContextListener { @Override public void afterCompletion(final TransactionContext completedContext, final boolean committed) { if (completedContext == transactionContext) { transactionComplete(); } } } private final ObjectPool pool; private final TransactionRegistry transactionRegistry; private final boolean accessToUnderlyingConnectionAllowed; private TransactionContext transactionContext; private boolean isSharedConnection; private final Lock lock; /** * Constructs a new instance responsible for managing a database connection in a transactional environment. * * @param pool * The connection pool. * @param transactionRegistry * The transaction registry. * @param accessToUnderlyingConnectionAllowed * Whether or not to allow access to the underlying Connection. * @throws SQLException * Thrown when there is problem managing transactions. */ public ManagedConnection(final ObjectPool pool, final TransactionRegistry transactionRegistry, final boolean accessToUnderlyingConnectionAllowed) throws SQLException { super(null); this.pool = pool; this.transactionRegistry = transactionRegistry; this.accessToUnderlyingConnectionAllowed = accessToUnderlyingConnectionAllowed; this.lock = new ReentrantLock(); updateTransactionStatus(); } @Override protected void checkOpen() throws SQLException { super.checkOpen(); updateTransactionStatus(); } @Override public void close() throws SQLException { if (!isClosedInternal()) { // Don't actually close the connection if in a transaction. The // connection will be closed by the transactionComplete method. // // DBCP-484 we need to make sure setClosedInternal(true) being // invoked if transactionContext is not null as this value will // be modified by the transactionComplete method which could run // in the different thread with the transaction calling back. lock.lock(); try { if (transactionContext == null || transactionContext.isTransactionComplete()) { super.close(); } } finally { try { setClosedInternal(true); } finally { lock.unlock(); } } } } @Override public void commit() throws SQLException { if (transactionContext != null) { throw new SQLException("Commit cannot be set while enrolled in a transaction"); } super.commit(); } @Override public C getDelegate() { if (isAccessToUnderlyingConnectionAllowed()) { return getDelegateInternal(); } return null; } // // The following methods can't be used while enlisted in a transaction // @Override public Connection getInnermostDelegate() { if (isAccessToUnderlyingConnectionAllowed()) { return super.getInnermostDelegateInternal(); } return null; } /** * Gets the transaction context. * * @return The transaction context. * @since 2.6.0 */ public TransactionContext getTransactionContext() { return transactionContext; } /** * Gets the transaction registry. * * @return The transaction registry. * @since 2.6.0 */ public TransactionRegistry getTransactionRegistry() { return transactionRegistry; } /** * If false, getDelegate() and getInnermostDelegate() will return null. * * @return if false, getDelegate() and getInnermostDelegate() will return null */ public boolean isAccessToUnderlyingConnectionAllowed() { return accessToUnderlyingConnectionAllowed; } @Override public void rollback() throws SQLException { if (transactionContext != null) { throw new SQLException("Commit cannot be set while enrolled in a transaction"); } super.rollback(); } @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { if (transactionContext != null) { throw new SQLException("Auto-commit cannot be set while enrolled in a transaction"); } super.setAutoCommit(autoCommit); } @Override public void setReadOnly(final boolean readOnly) throws SQLException { if (transactionContext != null) { throw new SQLException("Read-only cannot be set while enrolled in a transaction"); } super.setReadOnly(readOnly); } /** * Completes the transaction. */ protected void transactionComplete() { lock.lock(); try { transactionContext.completeTransaction(); } finally { lock.unlock(); } // If we were using a shared connection, clear the reference now that // the transaction has completed if (isSharedConnection) { setDelegate(null); isSharedConnection = false; } // autoCommit may have been changed directly on the underlying connection clearCachedState(); // If this connection was closed during the transaction and there is // still a delegate present close it final Connection delegate = getDelegateInternal(); if (isClosedInternal() && delegate != null) { try { setDelegate(null); if (!delegate.isClosed()) { delegate.close(); } } catch (final SQLException ignored) { // Not a whole lot we can do here as connection is closed // and this is a transaction callback so there is no // way to report the error. } } } private void updateTransactionStatus() throws SQLException { // if there is an active transaction context, assure the transaction context hasn't changed if (transactionContext != null && !transactionContext.isTransactionComplete()) { if (transactionContext.isActive()) { if (transactionContext != transactionRegistry.getActiveTransactionContext()) { throw new SQLException("Connection cannot be used while enlisted in another transaction"); } return; } // transaction should have been cleared up by TransactionContextListener, but in // rare cases another lister could have registered which uses the connection before // our listener is called. In that rare case, trigger the transaction complete call now transactionComplete(); } // the existing transaction context ended (or we didn't have one), get the active transaction context transactionContext = transactionRegistry.getActiveTransactionContext(); // if there is an active transaction context, and it already has a shared connection, use it if (transactionContext != null && transactionContext.getSharedConnection() != null) { // A connection for the connection factory has already been enrolled // in the transaction, replace our delegate with the enrolled connection // return current connection to the pool @SuppressWarnings("resource") final C connection = getDelegateInternal(); setDelegate(null); if (connection != null && transactionContext.getSharedConnection() != connection) { try { pool.returnObject(connection); } catch (final Exception e) { // whatever... try to invalidate the connection try { pool.invalidateObject(connection); } catch (final Exception ignored) { // no big deal } } } // add a listener to the transaction context transactionContext.addTransactionContextListener(new CompletionListener()); // Set our delegate to the shared connection. Note that this will // always be of type C since it has been shared by another // connection from the same pool. @SuppressWarnings("unchecked") final C shared = (C) transactionContext.getSharedConnection(); setDelegate(shared); // remember that we are using a shared connection, so it can be cleared after the // transaction completes isSharedConnection = true; } else { C connection = getDelegateInternal(); // if our delegate is null, create one if (connection == null) { try { // borrow a new connection from the pool connection = pool.borrowObject(); setDelegate(connection); } catch (final Exception e) { throw new SQLException("Unable to acquire a new connection from the pool", e); } } // if we have a transaction, out delegate becomes the shared delegate if (transactionContext != null) { // add a listener to the transaction context transactionContext.addTransactionContextListener(new CompletionListener()); // register our connection as the shared connection try { transactionContext.setSharedConnection(connection); } catch (final SQLException e) { // transaction is hosed transactionContext = null; try { pool.invalidateObject(connection); } catch (final Exception ignored) { // we are try but no luck } throw e; } } } // autoCommit may have been changed directly on the underlying // connection clearCachedState(); } } ManagedDataSource.java000066400000000000000000000072021472045345700341310ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; import org.apache.commons.dbcp2.PoolingDataSource; import org.apache.commons.pool2.ObjectPool; /** * The ManagedDataSource is a PoolingDataSource that creates ManagedConnections. * * @param * The kind of {@link Connection} to manage. * @since 2.0 */ public class ManagedDataSource extends PoolingDataSource { private TransactionRegistry transactionRegistry; /** * Creates a ManagedDataSource which obtains connections from the specified pool and manages them using the * specified transaction registry. The TransactionRegistry must be the transaction registry obtained from the * XAConnectionFactory used to create the connection pool. If not, an error will occur when attempting to use the * connection in a global transaction because the XAResource object associated with the connection will be * unavailable. * * @param pool * the connection pool * @param transactionRegistry * the transaction registry obtained from the XAConnectionFactory used to create the connection pool * object factory */ public ManagedDataSource(final ObjectPool pool, final TransactionRegistry transactionRegistry) { super(pool); this.transactionRegistry = transactionRegistry; } @Override public Connection getConnection() throws SQLException { if (getPool() == null) { throw new IllegalStateException("Pool has not been set"); } if (transactionRegistry == null) { throw new IllegalStateException("TransactionRegistry has not been set"); } return new ManagedConnection<>(getPool(), transactionRegistry, isAccessToUnderlyingConnectionAllowed()); } /** * Gets the transaction registry. * * @return The transaction registry. * @see #setTransactionRegistry(TransactionRegistry) * @since 2.6.0 */ public TransactionRegistry getTransactionRegistry() { return transactionRegistry; } /** * Sets the transaction registry from the XAConnectionFactory used to create the pool. The transaction registry can * only be set once using either a connector or this setter method. * * @param transactionRegistry * the transaction registry acquired from the XAConnectionFactory used to create the pool */ public void setTransactionRegistry(final TransactionRegistry transactionRegistry) { if (this.transactionRegistry != null) { throw new IllegalStateException("TransactionRegistry already set"); } Objects.requireNonNull(transactionRegistry, "transactionRegistry"); this.transactionRegistry = transactionRegistry; } } PoolableManagedConnection.java000066400000000000000000000103301472045345700356500ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.Connection; import java.sql.SQLException; import java.util.Collection; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.pool2.ObjectPool; /** * PoolableConnection that unregisters from TransactionRegistry on Connection real destroy. * * @see PoolableConnection * @since 2.0 */ public class PoolableManagedConnection extends PoolableConnection { private final TransactionRegistry transactionRegistry; /** * Creates a PoolableManagedConnection. * * @param transactionRegistry * transaction registry * @param conn * underlying connection * @param pool * connection pool */ public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool) { this(transactionRegistry, conn, pool, null, true); } /** * Creates a PoolableManagedConnection. * * @param transactionRegistry * transaction registry * @param conn * underlying connection * @param pool * connection pool * @param disconnectSqlCodes * SQL State codes considered fatal disconnection errors * @param fastFailValidation * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to * run query or isValid) */ public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool, final Collection disconnectSqlCodes, final boolean fastFailValidation) { this(transactionRegistry, conn, pool, disconnectSqlCodes, null, fastFailValidation); } /** * Creates a PoolableManagedConnection. * * @param transactionRegistry * transaction registry * @param conn * underlying connection * @param pool * connection pool * @param disconnectSqlCodes * SQL State codes considered fatal disconnection errors * @param disconnectionIgnoreSqlCodes * SQL State codes considered fatal disconnection errors * @param fastFailValidation * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to * run query or isValid) * @since 2.13.0 */ public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool, final Collection disconnectSqlCodes, final Collection disconnectionIgnoreSqlCodes, final boolean fastFailValidation) { super(conn, pool, null, disconnectSqlCodes, disconnectionIgnoreSqlCodes, fastFailValidation); this.transactionRegistry = transactionRegistry; } /** * Gets the transaction registry. * * @return The transaction registry. * @since 2.6.0 */ public TransactionRegistry getTransactionRegistry() { return transactionRegistry; } /** * Actually close the underlying connection. */ @Override public void reallyClose() throws SQLException { try { super.reallyClose(); } finally { transactionRegistry.unregisterConnection(this); } } } PoolableManagedConnectionFactory.java000066400000000000000000000121711472045345700372050ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import javax.management.ObjectName; import org.apache.commons.dbcp2.Constants; import org.apache.commons.dbcp2.DelegatingPreparedStatement; import org.apache.commons.dbcp2.PStmtKey; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.PoolingConnection; import org.apache.commons.pool2.KeyedObjectPool; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; /** * A {@link PoolableConnectionFactory} that creates {@link PoolableManagedConnection}s. * * @since 2.0 */ public class PoolableManagedConnectionFactory extends PoolableConnectionFactory { /** Transaction registry associated with connections created by this factory */ private final TransactionRegistry transactionRegistry; /** * Creates a PoolableManagedConnectionFactory and attach it to a connection pool. * * @param connFactory * XAConnectionFactory * @param dataSourceJmxName * The data source name. */ public PoolableManagedConnectionFactory(final XAConnectionFactory connFactory, final ObjectName dataSourceJmxName) { super(connFactory, dataSourceJmxName); this.transactionRegistry = connFactory.getTransactionRegistry(); } /** * Gets the transaction registry. * * @return The transaction registry. * @since 2.6.0 */ public TransactionRegistry getTransactionRegistry() { return transactionRegistry; } /** * Uses the configured XAConnectionFactory to create a {@link PoolableManagedConnection}. Throws * {@code IllegalStateException} if the connection factory returns null. Also initializes the connection using * configured initialization SQL (if provided) and sets up a prepared statement pool associated with the * PoolableManagedConnection if statement pooling is enabled. */ @SuppressWarnings("resource") // Connection is released elsewhere. @Override public synchronized PooledObject makeObject() throws SQLException { Connection conn = getConnectionFactory().createConnection(); if (conn == null) { throw new IllegalStateException("Connection factory returned null from createConnection"); } initializeConnection(conn); if (getPoolStatements()) { conn = new PoolingConnection(conn); final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotalPerKey(-1); config.setBlockWhenExhausted(false); config.setMaxWait(Duration.ZERO); config.setMaxIdlePerKey(1); config.setMaxTotal(getMaxOpenPreparedStatements()); final ObjectName dataSourceJmxName = getDataSourceJmxName(); final long connIndex = getConnectionIndex().getAndIncrement(); if (dataSourceJmxName != null) { final StringBuilder base = new StringBuilder(dataSourceJmxName.toString()); base.append(Constants.JMX_CONNECTION_BASE_EXT); base.append(connIndex); config.setJmxNameBase(base.toString()); config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX); } else { config.setJmxEnabled(false); } final KeyedObjectPool stmtPool = new GenericKeyedObjectPool<>( (PoolingConnection) conn, config); ((PoolingConnection) conn).setStatementPool(stmtPool); ((PoolingConnection) conn).setCacheState(getCacheState()); } final PoolableManagedConnection pmc = new PoolableManagedConnection(transactionRegistry, conn, getPool(), getDisconnectionSqlCodes(), getDisconnectionIgnoreSqlCodes(), isFastFailValidation()); pmc.setCacheState(getCacheState()); return new DefaultPooledObject<>(pmc); } } SynchronizationAdapter.java000066400000000000000000000022271472045345700353260ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import javax.transaction.Synchronization; /** * Implements {@link Synchronization} for subclasses. */ class SynchronizationAdapter implements Synchronization { @Override public void afterCompletion(final int status) { // Noop } @Override public void beforeCompletion() { // Noop } } TransactionContext.java000066400000000000000000000213511472045345700344550ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.lang.ref.WeakReference; import java.sql.Connection; import java.sql.SQLException; import java.util.Objects; import javax.transaction.RollbackException; import javax.transaction.Status; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAResource; /** * TransactionContext represents the association between a single XAConnectionFactory and a Transaction. This context * contains a single shared connection which should be used by all ManagedConnections for the XAConnectionFactory, the * ability to listen for the transaction completion event, and a method to check the status of the transaction. * * @since 2.0 */ public class TransactionContext { private final TransactionRegistry transactionRegistry; private final WeakReference transactionRef; private final TransactionSynchronizationRegistry transactionSynchronizationRegistry; private Connection sharedConnection; private boolean transactionComplete; /** * Provided for backwards compatibility * * @param transactionRegistry the TransactionRegistry used to obtain the XAResource for the * shared connection * @param transaction the transaction */ public TransactionContext(final TransactionRegistry transactionRegistry, final Transaction transaction) { this (transactionRegistry, transaction, null); } /** * Creates a TransactionContext for the specified Transaction and TransactionRegistry. The TransactionRegistry is * used to obtain the XAResource for the shared connection when it is enlisted in the transaction. * * @param transactionRegistry * the TransactionRegistry used to obtain the XAResource for the shared connection * @param transaction * the transaction * @param transactionSynchronizationRegistry * The optional TSR to register synchronizations with * @since 2.6.0 */ public TransactionContext(final TransactionRegistry transactionRegistry, final Transaction transaction, final TransactionSynchronizationRegistry transactionSynchronizationRegistry) { Objects.requireNonNull(transactionRegistry, "transactionRegistry"); Objects.requireNonNull(transaction, "transaction"); this.transactionRegistry = transactionRegistry; this.transactionRef = new WeakReference<>(transaction); this.transactionComplete = false; this.transactionSynchronizationRegistry = transactionSynchronizationRegistry; } /** * Adds a listener for transaction completion events. * * @param listener * the listener to add * @throws SQLException * if a problem occurs adding the listener to the transaction */ public void addTransactionContextListener(final TransactionContextListener listener) throws SQLException { try { if (!isActive()) { final Transaction transaction = this.transactionRef.get(); listener.afterCompletion(this, transaction != null && transaction.getStatus() == Status.STATUS_COMMITTED); return; } final Synchronization s = new SynchronizationAdapter() { @Override public void afterCompletion(final int status) { listener.afterCompletion(TransactionContext.this, status == Status.STATUS_COMMITTED); } }; if (transactionSynchronizationRegistry != null) { transactionSynchronizationRegistry.registerInterposedSynchronization(s); } else { getTransaction().registerSynchronization(s); } } catch (final RollbackException ignored) { // JTA spec doesn't let us register with a transaction marked rollback only // just ignore this and the tx state will be cleared another way. } catch (final Exception e) { throw new SQLException("Unable to register transaction context listener", e); } } /** * Sets the transaction complete flag to true. * * @since 2.4.0 */ public void completeTransaction() { this.transactionComplete = true; } /** * Gets the connection shared by all ManagedConnections in the transaction. Specifically, connection using the same * XAConnectionFactory from which the TransactionRegistry was obtained. * * @return the shared connection for this transaction */ public Connection getSharedConnection() { return sharedConnection; } private Transaction getTransaction() throws SQLException { final Transaction transaction = this.transactionRef.get(); if (transaction == null) { throw new SQLException("Unable to enlist connection because the transaction has been garbage collected"); } return transaction; } /** * True if the transaction is active or marked for rollback only. * * @return true if the transaction is active or marked for rollback only; false otherwise * @throws SQLException * if a problem occurs obtaining the transaction status */ public boolean isActive() throws SQLException { try { final Transaction transaction = this.transactionRef.get(); if (transaction == null) { return false; } final int status = transaction.getStatus(); return status == Status.STATUS_ACTIVE || status == Status.STATUS_MARKED_ROLLBACK; } catch (final SystemException e) { throw new SQLException("Unable to get transaction status", e); } } /** * Gets the transaction complete flag to true. * * @return The transaction complete flag. * * @since 2.4.0 */ public boolean isTransactionComplete() { return this.transactionComplete; } /** * Sets the shared connection for this transaction. The shared connection is enlisted in the transaction. * * @param sharedConnection * the shared connection * @throws SQLException * if a shared connection is already set, if XAResource for the connection could not be found in the * transaction registry, or if there was a problem enlisting the connection in the transaction */ public void setSharedConnection(final Connection sharedConnection) throws SQLException { if (this.sharedConnection != null) { throw new IllegalStateException("A shared connection is already set"); } // This is the first use of the connection in this transaction, so we must // enlist it in the transaction final Transaction transaction = getTransaction(); try { final XAResource xaResource = transactionRegistry.getXAResource(sharedConnection); if (!transaction.enlistResource(xaResource)) { throw new SQLException("Unable to enlist connection in transaction: enlistResource returns 'false'."); } } catch (final IllegalStateException e) { // This can happen if the transaction is already timed out throw new SQLException("Unable to enlist connection in the transaction", e); } catch (final RollbackException ignored) { // transaction was rolled back... proceed as if there never was a transaction } catch (final SystemException e) { throw new SQLException("Unable to enlist connection the transaction", e); } this.sharedConnection = sharedConnection; } } TransactionContextListener.java000066400000000000000000000024461472045345700361670ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; /** * A listener for transaction completion events. * * @since 2.0 */ public interface TransactionContextListener { /** * Called after a transaction commits or rolls back. * * @param transactionContext * the transaction context that completed. * @param committed * true if the transaction committed; false otherwise. */ void afterCompletion(TransactionContext transactionContext, boolean committed); } TransactionRegistry.java000066400000000000000000000143451472045345700346460ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import java.util.Objects; import java.util.WeakHashMap; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAResource; import org.apache.commons.dbcp2.DelegatingConnection; /** * TransactionRegistry tracks Connections and XAResources in a transacted environment for a single XAConnectionFactory. *

* The TransactionRegistry hides the details of transaction processing from the existing DBCP pooling code, and gives * the ManagedConnection a way to enlist connections in a transaction, allowing for the maximal rescue of DBCP. *

* * @since 2.0 */ public class TransactionRegistry { private final TransactionManager transactionManager; private final Map caches = new WeakHashMap<>(); private final Map xaResources = new WeakHashMap<>(); private final TransactionSynchronizationRegistry transactionSynchronizationRegistry; /** * Provided for backwards compatibility * @param transactionManager the transaction manager used to enlist connections */ public TransactionRegistry(final TransactionManager transactionManager) { this (transactionManager, null); } /** * Creates a TransactionRegistry for the specified transaction manager. * * @param transactionManager * the transaction manager used to enlist connections. * @param transactionSynchronizationRegistry * The optional TSR to register synchronizations with * @since 2.6.0 */ public TransactionRegistry(final TransactionManager transactionManager, final TransactionSynchronizationRegistry transactionSynchronizationRegistry) { this.transactionManager = transactionManager; this.transactionSynchronizationRegistry = transactionSynchronizationRegistry; } /** * Gets the active TransactionContext or null if not Transaction is active. * * @return The active TransactionContext or null if no Transaction is active. * @throws SQLException * Thrown when an error occurs while fetching the transaction. */ public TransactionContext getActiveTransactionContext() throws SQLException { Transaction transaction = null; try { transaction = transactionManager.getTransaction(); // was there a transaction? if (transaction == null) { return null; } // This is the transaction on the thread so no need to check its status - we should try to use it and // fail later based on the subsequent status } catch (final SystemException e) { throw new SQLException("Unable to determine current transaction ", e); } // register the context (or create a new one) synchronized (this) { return caches.computeIfAbsent(transaction, k -> new TransactionContext(this, k, transactionSynchronizationRegistry)); } } private Connection getConnectionKey(final Connection connection) { final Connection result; if (connection instanceof DelegatingConnection) { result = ((DelegatingConnection) connection).getInnermostDelegateInternal(); } else { result = connection; } return result; } /** * Gets the XAResource registered for the connection. * * @param connection * the connection * @return The XAResource registered for the connection; never null. * @throws SQLException * Thrown when the connection does not have a registered XAResource. */ public synchronized XAResource getXAResource(final Connection connection) throws SQLException { Objects.requireNonNull(connection, "connection"); final Connection key = getConnectionKey(connection); final XAResource xaResource = xaResources.get(key); if (xaResource == null) { throw new SQLException("Connection does not have a registered XAResource " + connection); } return xaResource; } /** * Registers the association between a Connection and a XAResource. When a connection is enlisted in a transaction, * it is actually the XAResource that is given to the transaction manager. * * @param connection * The JDBC connection. * @param xaResource * The XAResource which managed the connection within a transaction. */ public synchronized void registerConnection(final Connection connection, final XAResource xaResource) { Objects.requireNonNull(connection, "connection"); Objects.requireNonNull(xaResource, "xaResource"); xaResources.put(connection, xaResource); } /** * Unregisters a destroyed connection from {@link TransactionRegistry}. * * @param connection * A destroyed connection from {@link TransactionRegistry}. */ public synchronized void unregisterConnection(final Connection connection) { xaResources.remove(getConnectionKey(connection)); } } XAConnectionFactory.java000066400000000000000000000043751472045345700345120ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.sql.Connection; import java.sql.SQLException; import org.apache.commons.dbcp2.ConnectionFactory; /** * XAConnectionFactory is an extension of ConnectionFactory used to create connections in a transaction managed * environment. The XAConnectionFactory operates like a normal ConnectionFactory except a TransactionRegistry is * provided from which the XAResource for a connection can be obtained. This allows the existing DBCP pool code to work * with XAConnections and gives the ManagedConnection a way to enlist a connection in the transaction. * * @since 2.0 */ public interface XAConnectionFactory extends ConnectionFactory { /** * Creates a new {@link Connection} in an implementation specific fashion. *

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

* * @return a new {@link Connection} * @throws SQLException if a database error occurs creating the connection */ @Override Connection createConnection() throws SQLException; /** * Gets the TransactionRegistry for this connection factory which contains the XAResource for every connection * created by this factory. * * @return the transaction registry for this connection factory */ TransactionRegistry getTransactionRegistry(); } package-info.java000066400000000000000000000036201472045345700331460ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/managed/* * 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. */ /** *

* This package provides support for pooling of ManagedConnections. A managed * connection is responsible for managing a database connection in a * transactional environment (typically called Container Managed). * A managed connection operates like any other connection when no global * transaction (a.k.a. XA transaction or JTA Transaction) is in progress. * When a global transaction is active a single physical connection to the * database is used by all ManagedConnections accessed in the scope of the * transaction. Connection sharing means that all data access during a * transaction has a consistent view of the database. When the global * transaction is committed or rolled back the enlisted connections are * committed or rolled back. *

*

* This package supports full XADataSources and non-XA data sources using * local transaction semantics. non-XA data sources commit and rollback as * part of the transaction but are not recoverable in the case of an error * because they do not implement the two-phase commit protocol. *

*/ package org.apache.commons.dbcp2.managed; commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/overview.html000066400000000000000000000017131472045345700311770ustar00rootroot00000000000000 Overview of the org.apache.commons.dbcp component

Commons Database Connection Pooling

commons-dbcp-rel-commons-dbcp-2.13.0/src/main/java/org/apache/commons/dbcp2/package-info.java000066400000000000000000000156011472045345700316330ustar00rootroot00000000000000/* * 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. */ /** *

* Database Connection Pool API. *

* Overview in Dialog Form *

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

*

* A: There are two primary ways to access the DBCP pool, as a {@link java.sql.Driver Driver}, or as a * {@link javax.sql.DataSource DataSource}. You'll want to create an instance of * {@link org.apache.commons.dbcp2.PoolingDriver} or {@link org.apache.commons.dbcp2.PoolingDataSource}. When using one * of these interfaces, you can just use your JDBC objects the way you normally would. Closing a * {@link java.sql.Connection} will simply return it to its pool. *

*

* Q: But {@link org.apache.commons.dbcp2.PoolingDriver PoolingDriver} and * {@link org.apache.commons.dbcp2.PoolingDataSource PoolingDataSource} both expect an * {@link org.apache.commons.pool2.ObjectPool ObjectPool} as an input. Where do I get one of those? *

*

* A: The {@link org.apache.commons.pool2.ObjectPool ObjectPool} interface is defined in Commons Pool. You can use one * of the provided implementations such as {@link org.apache.commons.pool2.impl.GenericObjectPool GenericObjectPool}, * {@link org.apache.commons.pool2.proxy.ProxiedObjectPool ProxiedObjectPool} or * {@link org.apache.commons.pool2.impl.SoftReferenceObjectPool SoftReferenceObjectPool} or you can create your own. *

*

* Q: Ok, I've found an {@link org.apache.commons.pool2.ObjectPool ObjectPool} implementation that I think suits my * connection pooling needs. But it wants a {@link org.apache.commons.pool2.PooledObjectFactory PooledObjectFactory}. * What should I use for that? *

*

* A: The DBCP package provides a class for this purpose. It's called * {@link org.apache.commons.dbcp2.PoolableConnectionFactory}. It implements the factory and lifecycle methods of * {@link org.apache.commons.pool2.PooledObjectFactory} for {@link java.sql.Connection}s. But it doesn't create the * actual database {@link java.sql.Connection}s itself, it uses a {@link org.apache.commons.dbcp2.ConnectionFactory} for * that. The {@link org.apache.commons.dbcp2.PoolableConnectionFactory} will take {@link java.sql.Connection}s created * by the {@link org.apache.commons.dbcp2.ConnectionFactory} and wrap them with classes that implement the pooling * behavior. *

*

* Several implementations of {@link org.apache.commons.dbcp2.ConnectionFactory} are provided--one that uses * {@link java.sql.DriverManager} to create connections * ({@link org.apache.commons.dbcp2.DriverManagerConnectionFactory}), one that uses a {@link java.sql.Driver} to create * connections ({@link org.apache.commons.dbcp2.DriverConnectionFactory}), one that uses a {@link javax.sql.DataSource} * to create connections ({@link org.apache.commons.dbcp2.DataSourceConnectionFactory}). *

*

* Q: I think I'm starting to get it, but can you walk me though it again? *

*

* A: Sure. Let's assume you want to create a {@link javax.sql.DataSource} that pools {@link java.sql.Connection}s. * Let's also assume that those pooled {@link java.sql.Connection}s should be obtained from the * {@link java.sql.DriverManager}. You'll want to create a {@link org.apache.commons.dbcp2.PoolingDataSource}. *

*

* The {@link org.apache.commons.dbcp2.PoolingDataSource} uses an underlying {@link org.apache.commons.pool2.ObjectPool} * to create and store its {@link java.sql.Connection}. *

*

* To create a {@link org.apache.commons.pool2.ObjectPool}, you'll need a * {@link org.apache.commons.pool2.PooledObjectFactory} that creates the actual {@link java.sql.Connection}s. That's * what {@link org.apache.commons.dbcp2.PoolableConnectionFactory} is for. *

*

* To create the {@link org.apache.commons.dbcp2.PoolableConnectionFactory}, you'll need at least two things: *

*
    *
  1. A {@link org.apache.commons.dbcp2.ConnectionFactory} from which the actual database {@link java.sql.Connection}s * will be obtained.
  2. *
  3. An empty and factory-less {@link org.apache.commons.pool2.ObjectPool} in which the {@link java.sql.Connection}s * will be stored.
    * When you pass an {@link org.apache.commons.pool2.ObjectPool} into the * {@link org.apache.commons.dbcp2.PoolableConnectionFactory}, it will automatically register itself as the * {@link org.apache.commons.pool2.PooledObjectFactory} for that pool.
  4. *
*

* In code, that might look like this: *

*
 * GenericObjectPool connectionPool = new GenericObjectPool(null);
 * ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:some:connect:string", "userName",
 *         "password");
 * ObjectName oName = new ObjectName("MyTests:DataSource=test"); // or null to not use JMX
 * PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, oName);
 * PoolingDataSource dataSource = new PoolingDataSource(connectionPool);
 * 
*

* To create a {@link org.apache.commons.dbcp2.PoolingDriver}, we do the same thing, except that instead of creating a * {@link javax.sql.DataSource} on the last line, we create a {@link org.apache.commons.dbcp2.PoolingDriver}, and * register the {@code connectionPool} with it. E.g.,: *

*
 * GenericObjectPool connectionPool = new GenericObjectPool(null);
 * ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:some:connect:string", "userName",
 *         "password");
 * ObjectName oName = new ObjectName("MyTests:DataSource=test"); // or null to not use JMX
 * PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, oName);
 * PoolingDriver driver = new PoolingDriver();
 * driver.registerPool("example", connectionPool);
 * 
*

* Since the {@link org.apache.commons.dbcp2.PoolingDriver} registers itself with the {@link java.sql.DriverManager} * when it is created, now you can just go to the {@link java.sql.DriverManager} to create your * {@link java.sql.Connection}s, like you normally would: *

*
 * Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:example");
 * 
*/ package org.apache.commons.dbcp2; commons-dbcp-rel-commons-dbcp-2.13.0/src/main/resources/000077500000000000000000000000001472045345700230555ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/resources/org/000077500000000000000000000000001472045345700236445ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/resources/org/apache/000077500000000000000000000000001472045345700250655ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/resources/org/apache/commons/000077500000000000000000000000001472045345700265405ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/resources/org/apache/commons/dbcp2/000077500000000000000000000000001472045345700275325ustar00rootroot00000000000000LocalStrings.properties000066400000000000000000000025111472045345700341740ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/main/resources/org/apache/commons/dbcp2# 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. connectionFactory.lifetimeExceeded=The lifetime of the connection [{0}] exceeds the maximum permitted value of [{1}]. poolableConnectionFactory.validateObject.fail=Failed to validate a poolable connection. poolableConnection.validate.fastFail=Fatal SQLException was thrown previously on this connection. swallowedExceptionLogger.onSwallowedException=An internal object pool swallowed an Exception. poolingDataSource.factoryConfig=PoolableConnectionFactory not linked to pool. Calling setPool() to fix the configuration. pool.close.fail=Cannot close connection pool. commons-dbcp-rel-commons-dbcp-2.13.0/src/media/000077500000000000000000000000001472045345700211765ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/media/dbcp-logo-white.xcf000066400000000000000000000573311472045345700246750ustar00rootroot00000000000000gimp xcf filePBB<K gimp-commentCreated with The GIMPgimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) 0 N$3\ TM     ><8gimp-text-layer(text "TM") (font "Sans") (font-size 8.000000) (font-size-unit pixels) (hinting yes) (antialias yes) (language "en-us") (base-direction ltr) (color (color-rgb 0.000000 0.000000 0.000000)) (justify left) (box-mode fixed) (box-width 12.000000) (box-height 11.000000) (box-unit pixels)   #ɰ->8x88w8P8?8nDBCP     j%7n Bn F8U UU88Uq ƪUU 8U8Uq qUU Uq U8 U  8qUU  U UU U  U q8 qU  U  U UU UUqUU UU Uq8UU 8UUU  88U  8U U8 U  UUqU 8q UUU  qU  U 8 UUUU U q8 U8 q 8ƪ8 q U UMdddU8UU U qUUqqUUU qUq8UUq8qUUU8 Uq8 qUUqUUU8UUUqUUUUUUU8UUUUUqUUqUUUƪUUU UU U U U qU UqU q U U 8U UU UU UqUƍUUq8q888 qUU7<Drop-Shadow#2     c8 < $$< ,#g                              !!  !!   $&()('&$#!  #&())('&%$##"" "&+.010/-+)'&%%$#!  #'*-/11/.,+**) !'-2588631.,+**+*)'%#"!"$'*.258998753211 &-39=?@?<9630/../01221/-+))+.15:=@AA@><98778 ")18>CEEDA=9631012467898753100148<@DGHGFCA><;<<>? $-5=CHJJHE@<74212469;>??>=;9778;>BGJMNMKHEB@??ACE &/8@GKNMKGB<8411247;>BDEEDB@>>ADHLPRRQOLHECBCEGJ (1:CJNQPMHB<730/037;@DHJKKIGEEGIMQTVWURNJGEDEGKN (2;DKPRQNHB;50-,.15:@FJNPPOMLJJLNRUXZZXUPLIFFGJNR )3FMSWYYXWUTUVY\^__\YTPLIIKNSW  )3=FMQSQMF>6.($#$'-45.'#""&+2:CKRX[\\[YXXY\^`a`]YSNIFEFINS  )3=FMQSRMG?70*&%&).5DKOSTTSQPOPRUX[\[YUOJEA@ACHM (2DIMOOMKJJLNRUXZYWSNHD@>?AFK (1;CJOQQMHB<62/./15:>CGIJJIGEEGJNRUWWUQLGB?==@CH &09AHLONLGB<73100369=ACDEDB@?>?AEIMQSSQNJEA><<>AE %-6>DIKKIFA<74101358:=>><:9879;?DHLNONKGC?<::<>A "*2:@DGGEB>:63100135788753101259>BFHIHFC?<9889:=  '.5;?ABA>;741/../01221/-+*)*,/37;8644568 #)/48:;:8630.,++,+)(&$#"#%(,058;<<;86420012 $)-02331/-*)'&&%$#" "%)-024431/-,+**+ "&)*++*(&%#"!  "%(*+,+*)'&%$$ !##"!  "#$##!                           @*                      !""!  !   !#%')**)('&%$"! ('%" !""!"#$%&(*,/1233210/.-,*(&#  1/-*'#!#%&''&%$$%&&'(())*+,.1479;<;;98765421.+'"8763/+&""$')+,,+*)(&&'()*+,--.0247;>ACCBA?>=<;:963/)$@?>;73.*&$$%&),.011/-+)'&&'(*+-./01369=ADGIJJIGEDCBB@>;60*#FFEC?:61.++,.03577642/,)'%%&')+-/02369=AEJMOPONLJIHHGEB=70)!LMLJFB=8522357:<<:73/+(%#"#$%'),.0247;?DIMQSTTRPNMLLMM;KHD=6-%QRRQMID?<:9:5+"Y[\[XTOKHFFGIKLLJFA:3,& !$'*.39?FMSX[\[YVTSRSUVWVTOH@7-#\^`_\XTPMLLMOQQPMHB:2*##'+07>EMSY\]\ZXUTSTUWXWUPIA7-$^acb_\XTRPQRTUUTPJB:1(!"'-44+"begfda]ZXXYZ\\[XSKB8.% !(08BKSY]__]ZWTSRRSRQNIB:1( dghhfc_][[\]__^ZTLB8-$  %.7AJRY^`_]ZWTRPPONLID=5-%dgiigda_]]^`aa`\UMB8-#  #,6@IRY^`_]ZVROMLJIFC=70(!dgiihec`__`bcca\VMC8-#  "+5?IRY^`_]YTPLIGEB?;60*#cgiihfdbaacdda]VMC8-$  !*4?IQY]_^[WRMHDA>;84/)$aehihgecbbdb^WND:/%  !*4>HQX\^]ZUOID?;740,'"_cghhgecbbcddb^WOE;0&  !*4>HQW\][WRLE?940,($  \aeggfecaabcca]XPG<2)   "*4>HPVZ[YUOH@93.)%! Y_cefeca`__``_\WPH>5+# #+4>HPVYYWRKD<4.(# V\`bcba^]\\]ZVPI@7.& $,5>GOTWWTOH@80(" SY]_`_][YWWXXYYXUPIB91*#%,5>FNSUURLE<4+$ PUY[[ZXVSRQRSTUTRNIC<4-'!%-5=ELQSROIB90(  MQTVVUROMKJKLNOONLHC=70*%  &-46-$ IMOPPNKHECCEGHJJIFB=82-($  &,3:AGKMKHB;2*! EGIIHFC@=;:;CGHGD>7/' ?ABB@>;75322479<>?>=;840,(%"#(.49>ABA>92+# 9:;:852/,*)*,.146898752/,)%#  %*/49<=<84.'  31/-*&$"!"$&),/12321/-*'$"!%*.25542-(" +*)'$!!$')+,,*)'$"  $(+-.-+'# $##!"$%&&%$"!!$&&%$!                          Qk                  F#commons     %O%k33%)-218qU8Uq8q8q q UU88UU8qUqUUUqUUUqUUq8U8 UU 8q8U8 q   8U 8U UU UU UU 8UU U 8 88 U q 8888 q8 q8qUUUUUqU UUUU U 8qUq q8UqUU8qU 8q8U8 8UqU8qqq88qqUUqUUUqƪUqUUUU8Uqq q8UUU 88UUqq UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU UUUU qUq qUqU8qU88qU8UƍUUUU8q qq q8  8qUU88qU 88 8UU UUUU8U8UUUUUUUUU8q 8UqUUU UUUUU 8UUUU UUUUU UUUU UUUU UUUUUU UUUUUU UUUUU UUUUUU UUUUU8 UUUU qUUUUq UUUUq8UUUUUUUUqUqU88UUqqU8q8qUU 8Uq8 q 8VVV UU ⪪88888Uqqq88  q 8 qU  qU qq8qƪq888UUk 58 Drop-Shadow     94{84\\84?ITU                    !#$%%$# !"##$%%$"   "$&')*+,,+*'%"!#$&'())*+,,*(&#! !$&(*+-.01221.,)&#! !#$'(*+,--./0234431.,)  #'),-/01346787642/,)(''(*,./11223568:;;9752 !&*-/12334679:;<;9742/..0245677665668:=?ABCB@=: "',02456678:<=>>=;97544579;<==<:9878:>=;:99:<>ABCCB@=;988:=@EIMOPONK &-38;==<:8655679;<=>==>@BEGIIHFC?;9779<@FKPSUVTR $+29=@AA>;853223579:;<==?ADGKMOOMJE@;7556:?EKQVZ[ZX  (08>CEED@<830..024689;=@CGLPSTSQLGA;63237=CKRX\__] $,5=CGJIGB=72.+))*,.1369<@EJOTWXWTOHA:40/04:AJRY^aba '09AHLNMID>71+(%%'),/26:@FLRW[\[WQIA93.,-17?HQY_cdd  )3=ELPRPLF?70*%"!!"$'*.38?FMTZ^_^YSJA92-*+/5=FOX_dfe ",6@HOTUSOIA81*$!!#'+06>ENU\`a`[TKB91,))-3;DNW^cff #-8BKSWYWRLC;2+% !$(.55-'" #'-471,)&%&'*.3:AJRZ_bc`ZSJA93/-/28@HOUY[[ !+6ALV]bdd`[TME>83/,*)*+.38?GOV\`a_ZTLC<610149@FMRUWW (3>IS[aeec_ZSLE?:52/--/27=DKRX\]\YSME>94336:?EJOQRR %/:EOX_ceeb^XRLFA<741/./149?FMSWYYWSMF@;7557;?CGKLML !+5@JS[`dec`\WQLFA<741/./15:@FLQTUSPLGB=9778;>ADFGGF &0:DMU\`bba]YTOID?:51.-,.04:?EJMOOMJFA=:88:<>@AA@? !*3=FNUZ]_^\YUPJE?:50-*))+.27=AEHIHFC@=:87789:;;:98 $-5>FMRVYYXVRNIC>83.*'%$%(+059=@BBA?=:8755421 &-5=DINPRQPMID?:4/*%" !$(,048:;;:875321100/.,+* %,3:?CFHIHEB>94/*%! $(,/13310/.-,+*('%$# $*059<>?><:62.)$  #&)+,,+*)('&%#"  !&+.134431.*&"!#$%%$$#"!  !$')**)'%"                    "                              !!"#$$%%$#"!  !"##! !!"#$%!$&'))*+,-.//.-,*))()*+,,*(%!"$&())**+,-. #&*-/123345789987642112345531-*&" #'*-012334567'%%&(+/369;<==<<=>@ACCDCB@><::;=>>=:62.)&$$%'+/37:;<=<<=>@/--.037<@CEFFEDDFGIKMMKIGECAABCDFGFEC?:51-+*,.27<@CEFFEDDEFH86558;@DILNOOMLKJJLNPSUVVTROMJHGGIJLMNMKGB=841125:?DILNONMKJJKLN@>==?CHLQTVWVTRPOOPRUX[\]\YVSPMLLMOQSTTRNID?:778;@FKPTVVUSQOOQSHEDDFJNSX[]][YVSRQRUX\_aba_\XTQONOQTVXXWTPJE@=<=@EKQWZ\\ZXUSQQSVOLKJLOTY]`ba_\XUSRSUY^adfec_[VRPOPRUX[\[YUOJEA@ADJPV[_``^ZWTRRTWUSQPQTY]adedb^YURQRUY^bfhgea\WSONOQUY\^^\XSNHECDHMSY_bcb`\WTQQSV[XUU;X\`dggfc^YTPOPSW]bfhhfb\WRNLMPTX\_`_[VQLHFGJOU\aded`[WRPOQT_\YXY[^bfhhfb]WRNLMPU[`ehhfb\VPLJKNRW\_a`]YSNJHHKPW]befd`[UPMLNRb_\[[]`dgiifb\UPKIJMRY_dggea[TNJHHKPU[_ba_ZUPKIJLQW]beec_YSNJIKOca^\\^adgiheaZTMIGGJPV]befd`YSLHEFINTZ_ab`\VQLJJMRX]beeb^WQKHGHLda_]]^adghhe`YRKGDEHMT[`dec^XQKFCDGLRY^ab`\WQMJJMRW]bdda\VOIFDFJda_]]^adghgd^XPJEBCFLRY_cdb]WPIDBBEKQX^aba]XRNKKMRW]adc`[UNHDBDHc`^\\^`cfgfc^WOICAAEJQX^bca\VOHCAADJPW]aba]XSNKKMRW]acc`ZTMFBABG`^\[[]_cegfc]VNHC@@DJQX^aba\UNHB@@DIPW]aba^YSOLLNRW]acc_ZSLFB@BF][YXY[^befeb\UNGB?@CIPW]ab`\UNGB@@CIPW]aba^YSOLLNRW\`cb_YRKEA@AEZXVVWY]`deea\UNGB?@CIPW]ab`[UNGB@@CIOW]aba^YTOLLNRW\`bb_YRKEA?AEUTRRTW[_bdda[UMGB?@CIPW\`a`[UNGB@@CIOV\`ba^YTOMLNRW\`ba^YRKEA?AEPONNPTX]acb_[TMFB?@CHOV\_`_ZTMGB@@CHOV\`a`]YTPMMNRW\_a`]XQJEA?AEJIIJLPUZ^``^YSLFA??CHNU[^_^YTMGB@@CHNU[_`_\XSOMLNRV[^`_\WQJD@?ADD2EHMRW[^^\WQKEA>?BGMSY\]\XRLFA??BGMSY]^][WRNLLMQUY]^]ZUOIC@>@D>=>@CHMSWZZXTNHC?==@EKQVYZXUOJD@>>AEKQVY[ZXTPLJIKNRVY[ZWRLFA>=>B778:>CHNRUUTPKE@=;;>BHMRUVTQLGB><<>CHMRUWVTPLIGGHKOSUVVSOID?<;CHLOPNKGB>:88;>CHLOPPNKHECCDFJMOPPMID?;878;))+.27BFHIHEA=96446:>BFHJIGEB?>>?ADGIIGC?:64347"#$'+059=?@?<952/..037;>@A@>:731//147;>@AA@=;9878:=?AA?<841/./1!$(-146641.+)((*,/2578752/,*))*-035788753100134688630-*)()+!%(+-.-+)'$#""#%(*-./.,*(%$##$&(+-.//.-+*))+,.//-+)&$""$!#$%$#!  #$%&%$" !#$&&%$#"!!"#$%&&%#!                         9 ,                     %%$#"!  !""##"    !"#//.,+*)(()*+,,+)&# !"#$%%$#!"$')+,,89987532112245542/+'" "$%&'()*+,--,+*(&#"!!"$'*.13566BCDCCA?=;::;<=>><84/*&" "%')*+,-./01234420.,*))*-037;=?@@JLMMLKIFDBAABCEFGFDA=83.)&%%&(*,.0112234689;<<;975321358=AEGIJJQSUVUTQNLIHGHIKMNNLJE@;61.,,-/24567665679<>ABCCB@><::;>AFJNQSSVY[\\[XUROMLLMORSTSQMHC>964468:;==<;9889;>BEHJKJIGECBCFINRVY[[ZZ]`bba^ZVRPNNPRUWYYWTOJEA><=>@ACCB@>;9889;?CHLOQQPOMKJKMQUY]`aa_[_cefeb^YUQOOQSWZ\]\ZVQLHFDEFGIIGD@=9778;?DIOSVWWVTRQRTW[_cefebZ_dghgd`ZUQONPSV[^``^[WSOMLLMOPONKGB=86458=CIPUZ\]\ZYWWY\_cghigdY^cghhe`ZUPMLNQUZ^acb_\XUSRSTUVURNIC=74236;AIPW\`aa`^\\]`cfikjhdW]bfhhe`ZTOKJLOTY_bdec`][YXYZ[[ZVQJC<61/028?GOW^bdedb``acehklkhcT[`eggd_XRMIHIMRX^cfgfda_^^=`a`^ZTLD<50--055.*(*.5>HQZaeggfeddegijjhc]LSZ_bb_ZSLFA@AFLS[bgijjhggijkkid]TJ@70+)+/5>GPX_ceedcbbdfhiigb\LSY_bb_YSLEA@AELS[afijihffhijjid^ULB92-+,/5=FNV\`bba``bdghhfb\KRY^aa^YRKEA?AEKSZafhihfeddeghigd^VMD<50-.16=EMTY]^^]]^`ceggea[KRY^aa^YRKEA@AEKSZ`eghfdbaabdefeb^WOF>830037=DKQVXZYYXYZ]`cefd`ZKQX]``]XRKEA@AEKRY_dffdb_^]^_abb`\WPHA:63358>CINRTTUWZ]addc_ZJQW\__\WQKEA@AEJQX^bcca^[YXYZ\]^]ZUOIC=86569=BGJMNONNPRVZ^aba^XIOUZ]]ZVPJDA?@DIPV[_``]ZWTSRSUWXXVSNIC>:878:=@DFHIHHJMRV[^_^[WGMRWYYWSMHB?>?BGMSX[\[XUQNLLNPQRQOLGC?;9889;>@ABBABDHLQVY[ZXSDJOSUUSOJE@=<=@DJOSVWVSOKHEDEFHIKKJGDA>;97789:;<<;::<>BGLPTVVSO@EIMOOMJE@<989<@EIMPPOLHD@><<=?ABCCB@>;976556543357;@EJMOOMJ;?CGHIGD@;85457;?CFHIGDA=9654568:;<;:9754221100/.-,+,.049>BFHHFC48?@><-14677641.+*))+.13677530,)&%$$%'(*+,,+*)('&%$"!  "&*.256764&)+-./.,)'%##$&)+-..,*(%" "#$%%$#"! #&),-.-+!#$%%#" !#$%%$" !#$%$#                        !   *                  #$$%$"  -.-,)&"  678753/+'"!#$%&&%$#! @?@AA@?<84/*%" !#%(*,--,+*(&# IHGGHIIGEA<71,)&%&'*-/1344321/-*'# QPNNOPPOMJE?94/-,,.1479:;::8641.*&! WUSRRSTUVVTQLF@;632247;>@AA?=;851-(# \YVUUWYZ[ZWRMGA<978:=ADFHHGEB?<840*% _[XVUVX[]^^\XRLFA><=?BFJLNNMKHD@<72,'! _[WUTUX[^`a_\VPJEB@ACGKNQSSRPMID@:5/(" _ZVSRSVZ^aba^YTMHDCCFINRUWXWURNID>81*$ ^XSPOQTX]acc`\VPJFDEGKPTXZ\[YWSNHB<4-& \VQNMNRV\`cca]WQKGEEGKPUY\^^][WSMG@91)" ZTNKJKOTZ_bcb^XRLGEDFJOTY]`aa_\XSLE=5-% YRLIGIMSY^bcb^XRLGDCDHMRW\_bcb`\XRKC:1)  WPJGFGLQX^bcb^XRKFBABEJOUZ^acdc`\WPH?6-$ VOIEDFJPW]acb^XQKEA?@BFKQV[_bddc`[UMD;1( UNHDCEJPV]acb^XQJD@==?CGMRW\`bdcb^XQH?5+" UNHDCEIPV\acb^XQJD?<;;:;=@EINSX\_aa_[UMD:0& TMGDCEIOV\`bb^XQJD>;99;>AEJNSW[]^]ZUNE;1( SMGDCEIOU[`ba^XQJD>;98:<>BFJNRVYZZXSMD;1( RLGCCDINUZ_a`]WQJD>;989::8789:@CFIJJIE@:2*" JEA?>?CHMRUWVSOJD?;75445678:<>@BCCB?:4-& EA=;:BFHJIGC?;630/../0123455430,'" 95311247;>@AA?<840.+*))*+,--..-+)%! 1.,**+-025787630-*'%$$%&'&%$! )'%$$&(*-./.-+(&#!  ! !"$%&%$#!                    z=,d Background     ],d]^^^,d]^^^/^?^O^u^^^:        &>>Q            00002K% commons-dbcp-rel-commons-dbcp-2.13.0/src/site/000077500000000000000000000000001472045345700210635ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/000077500000000000000000000000001472045345700230755ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/download_dbcp.cgi000077500000000000000000000002351472045345700263630ustar00rootroot00000000000000#!/bin/sh # Just call the standard mirrors.cgi script. It will use download.html # as the input template. exec /www/www.apache.org/dyn/mirrors/mirrors.cgi $*commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/000077500000000000000000000000001472045345700243425ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/dbcp-logo-blue.jpg000066400000000000000000000125671472045345700276520ustar00rootroot00000000000000JFIF``C  !"$"$CF" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?-CUa{5ƻpC#Fle8ebp_ =w_7??jɯYM^gZ#_i?|M_ =w*4;/:ݑ4_]o&i?|M|E4;u#_i/|M_ =w*?hw?vG޿ =u?᤾z5Udi쏽᤾z4I% k(ɡ_ ӭzI|% hKATQCA[>KA %/&w|Nd} '_/K/_7_QGMnK/_7G4_]o& :ݑ4_]o&i/|M|E4;u#_i?|M_ =w*?hw?vG޿_ =w?z5Udi쏽%Gi ?z҅ٽ}Y>h'эY5/Okَ% (>|qo:246ٴkS+dn ~CǃhmֳX*u}q UHНG;٣hzYX|k03n^~a^TS~gvfGj_ %.4ՙYtoG߲_xYӵ¨KBm']ĩYkt:dcWv]ÿf<]o-\c/.GYNT U6y5U/+M(kZ^Ve=l ЫyA5|cO n[,cucFO Tg迳O MxVR$y9#iGJO?eðҧM,K#3g +gǯCxFτ|7WW]V!eF<&|$9ZXuoy$:VmGi$8\r+ό:~QҌSЂөm , 2 =0W?ٻWu1C tE]TNOPn*|77E& AH#_>[5Zw ~Sp# P*g/(u<VL]8TaSp0З>uh 6$ͫ f  A^[[_ 2̛APl1~guW^ԵFP渐s\*'KvGkîZkgEtS>MŧX[@*Bq5e-kP Fܵόt/=x¿Ɩ'ӭ/I"z#pz;?M:|Iv(DqB1 үR .HӥZ~f3[#1INN7Xdzֿzc63B?^+n-xj?XWI]Cgl표)߱cVV&L&]'xmRJe+z}|sKSּ5qZaa`-# 031_Wܟċ ¶# |;ۆC_ ^XW9sMTQE_VUmrzXn2Y1&e#~a cVMtdsKvQE1xV=g]߈nbI wGr'*%wֵ4oJ\(aFl`g ŎxWߜu?>g&}4 O~cstumb+f[h X/y^ :5㤛FC'p󃟛08jߏO/ fpP` &:/Aջ+k{_QսDg}[D9/ۋgNo5'I>PpDp'y~wK ^8uAjǠFo.= 1=@0yn.'Y\rYI$s#Z;Ԧ@PcY(>>yk㎋SGH;OGn*s2QҼa.\B㵍b_gΟgMekmdv` $.=EGvNjam%揻2MyYy"?6xу0jTcRծ*،EJϡ _t85/a}>% `ARRĂ̠5ij/qEin_k\LAܐ'y⏅dž4T^(Ċ2@?v>@#jkk_w_ze¬{;xDN\3ێ MOh򹯷r9sM~ƿ bծ`&n&RCJW ~Ե9xv.juIsS׮[6/nBmYiNG9#v3 ~x$J$ŝ=I=m_Ze2ĿRTcex3ώȘ#/#a^q[Sm:t120~Kֳ{w!y9go Th$<QEm|_V.'Ն|/Ok[_7k?F5dLvG4aES/'Ntτ^u{kK l*B$ 'rZƻ;&%׉'IZ]3-ǜ|A_x7zwm׋5켿+j2[1Kcn8J*9krnrG,(꺳>/~,r~WȔ`U}, x}WJ)G J7pѿD^1 [v 8di>ZZ)QQW~eUթyI&I;bz{'^őx+ w {D1PT8 +5RNnԗC?^$/ ~%O5+QA@e*ᕰd`kf ~K%$$__ahe+`Ȯ}+$^Hima܃7F}׌|Mw+coi;sZRrGй׍[PLmj{wU|kKsilqщHJkm}n hy ^jwȈـ.ON@+XմK߷huipɴ7W5=bt)v$TUTJ$e:(0((k*q=7SɼWSxUo4{3 &p\Vg*_d(3/I¥?O")\?Rt'G*_d(y*T#'Q ?(Aʃ/I¥?O"(rK?E|G?O9?Rt'G*_d(y*T#'Q ?(Aʃ/I¥?O"(rK?E|G?O9?Rt'G*_d(y*??Rt'Es9P¥?O"T#'QET|G?O?տo&+7Նcommons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/dbcp-logo-white.png000066400000000000000000000300421472045345700300330ustar00rootroot00000000000000PNG  IHDRP sRGBbKGD pHYs  tIME c4H!iTXtCommentCreated with The GIMPm IDATx}ypU\3C!d H2:*@"P%" %"Rd "C{C3ysͷbBrgaM-ixKc6:s[c*}c\~?8pתm|||H՝_Ǜ㸁ҫ1RH#dgg#''u<' 999ѣ?8f͚%N76\ٳg7;;8QWW}~@ `Aި7f͚Fnnn ƚ5k5k`7vmt];vݍs7nܰ3fpj[[[kiW[[kZ>̘5kb;sL1{1x7n0Ξ=ktLuP(6JԸ!"&ExSooƸv1}tۢcccjʨ6somc)Q_~<.fffcqKS(Dڵm6/42cǎk[d0JJJWoEEQYYi=zԈ^zը4"ncƌ1?n;m4[G}0SNZYYi,]Tl+}_]]mS,9tPLڵkY._\cǎΓ"DYYYFii'FEEQQQa$''-Yq}۷oHKIpz5AHO#o>TD?s0 444Y{tɦ$###b(x<())AZZ]nݰcaj,vX zz-Zh瘙e˖kSԩSo[_zz:,X`Q5uTK͛7#))oXX6oތ~6e0x`\|vjX`;x`>|&&&sMLLĥKoΜ9cAϓ'OƢE,@~~e^jLǣݛK"##JJJ=C:Zߔ)SpB@VVVZcQ5&:vhk[PP`Cs6nCD`AFϏ1 ھ01ʕ+o aҥK7o6:պa#/I)L}w,ڵ9[j"\t 0 @vE¤$FK2&iiiX| ~XB_444%e544N'񧾾6aaa櫨ԎW͙m jkkm\ @2_%nݺ/_|o{j~y0K.s?194`0:s_sO]]M C0DN{N< 9rEdaXv\R1ռ3 /^\vL-Ta:y"## m| r-5ytc߆GGNru!﷈!K!n:T"ytUUR國yvѸrMׯmQTGD|)b|>s=x饗,O24i5&$$ XΗ#%wdz޽{-ʼnHISknᜮBp :ŝ/B:t T1CALS/ukz-ލcRO-!tr判".:uwr^2\1q$IB퉒\ZlxVСCѹsg̞=5JF0Z$Q8`H|,)EO?T1uB7/** W^W^^6m9qLt|7GPD@Pm|>;Wຊ: VRE8!@-:ǃ2A$jeʕ+&qC&(rDm-FA=77W\mlm9{?>DFFj@W0 "d\r򇤇.|SG9= :EץCjhijWOju{E*~pB`귺BK☺Am\N,tjo$XvI>}:zjqo&mۆ?O6lMZ87g@\J8&.q9^Y m&Ϲ$<]ƕ$'-NoWUV7_ =L'~Sds"U_r9DuGR݂ rss|r@EE͛,\tɆ+|J%P$^tI1%[j):,,Ly͗5tiH)Ĺ.Җs7s p:ĢR͜[ ٶmH v2@BB uIL:H7@*"sDIrBi?ez}WXX(J?T kҼ0dNt&i+;.cذaؼy3 E " z @vvR'XǤ>͚5CflPZZ*X:czҧcǎ6@LbJbn@C{oA=ݨb94W][NJ[liKu8y0vT@oDDƌk"55UDεk׊̆NU6H,YN`ر!qM@=twE6aJE A⺳:MwKNpcL>W1OzL.c~?C;gttvP9%0 aGDDó>k{׮]$w{b{nn.mH#BjQGѣxbbR'jѓ#Z~D$.8$N )B;qPP87JrLQN۾߸qtoSwɹ_Ĉ;L7Q.QV1u;T BDtMc{}QQ+pwl#znwƜv-ˆwC $_gQ\7N۷oǨQPZZ5|rXhx}zkXvf54 gyFjE'>:55 e(NkJOOG֭-WWW@DLNV"Rb[֭Ϝ;^ڴix#t@_ь7?-Z;w1̙`ƌ^{ 111Z s /7)Xt1ᔄ)T'TS2օ2) l"o*1W\ yp]wi6~HYQQ!2555v={YwZJ,d2++ K,BUU6mڄӧ^)Sf5nΜ9HKKs 4h^yN<<0 |&u#} 9'MjQ RHy}ϟ? u9zO'!>ea?k*Nsƍf^zYtN'IIeffZ"Cy"##K/H IKKêU,쿨ÇGAAP 1bkSx'#'K~g;v,;8l 6 [p-̙3g&$$ 55-Zo[vm6WL>}˖-3щ?xMX>4(ѣ(++Æ {ӪU+[6 Duu5Ν;{H;FϞ=͵y<̜9Ո58** 6 ۷o7?CEbkf͚[n~+KC HEr߸q9>;v)<<[Fjj*|>Y- ji<ߏG^}Abb"nv >Kɓacx;-Μ9 r r6m0x`>}ڵW!͛EÒtb|Ism3gޭJ4ƶwass0 3!!:uBRR,W[oǏ0 ={[lm}Q={ш5z TVVԼ扌Dзo_ޟ™͛Hټys &n5oܸaPhT&N7[QB~p#.t|>sҪoߖR++MfY"2(_PE=@cJ~SbmJ۪uJzj?z1Uksuڈ{;Y:OKI&%tn|LGб8 8\sf]*C !%,Mx ,C-E&w*J1 عWb)=L V`VNFÞ/>X+[[Vr śE7';͕[%,/q,|':W "5}讚TRxK=>[|ZcG,NbفS CR. m+4>U s*qt"WY&pYhIGϚªĝ3/ƜP 19qsf͚47tD9S*JsW$ OVm85TIDC>WnPLϖs7 NR)I&tBY"I6_RęJ(Tj,$;\)D#GLNP}7SDΠI8פnmnS:GU2HV\o墵19'׵TND;\ܐ!_jǥg*In,ץ-eF 65H2PRㄟ'\|ݤF]2|\0 4kL n.P1@կ0`9+7)"#v\wF ]nX;z|>1HDOt1%Íoke7Yr'WMO6.)H˄0 1% ;-`CT_:b#\x?Nb*݂ݚPoDλYt0 \tVRNfll,tbG+((ÇZ:&&#FQφh"L<_]vEllrt|jt6n܈zʬ9vX= y~~>LbèQ̢R@]tiӐln˖-Xh:d!>SNErNqY u=*ϡ n_+n2bF߬S|'~ҥKMЉa ??K, hll,}]9rQP (~W^^AܲeF_ƼyO"իѵkW%t{9 YpDVr5J#GZ#??< H$kiIDAT-"^򳔮Bx4~FgْԹ59H}_e>tinsxQLԝGM,:tH[$J!J2H8*$I(fÆ &Rիѭ[7gbw˺o4GoIRB"juu{CI=܂W&** DRRQF .ɡ$ ^CJ ZڕcѢEE> ƍg"%pwLLBnr[T?]@eQ[T( @uP.T]LKZB7!YN򺜵 %)[ps9RDhC<擖;vh-[Li2常8YJ!r #zm%!&uZ:wliSRR/Œ1iElyenc]mL7c_I*BE؈L8P7nR%}jW`iI&q<. #<Çwjk y)..} )5,cs{)4gcܯG-iZ z!&&L IiiiEб:-}ki+Çcڴi:0(2H uu;U5nfP^K+ _y5;{Cˋ>ԡ~)MVEVѥӠ)OlKɫoW\i+11Ri)ۻs=x D|xD%1=:=HJ*,򀀴4 bUe PьMmee-b~laaat˷8EĄ#خT?NǓI$:*"KYչ=4!M}.)ET%&p@wBL''°a,8`}M4)9"DxK\;v찴СexH΅ h9T`hAajb'7)8q-ytnn.Zje-VDi}(5RB?-'1cW:fc pj ѹY{уzgHHH]UTVVɓصkL>6"9r䈨Q  >ܩHj΋/Ɔ lwڵcmi`AT&2V> n2YfM۷/Ə1S$Iϔ34HcO}G}}=^[2GDD+RSShA 26MyqSɏYsUuܺM ݻQ]]m)QXXBtƍCvD龔R|(Ej]doϝ#l*>}X M\[&ļɑsJɽ2g{s26zEvv6Μ9.VVVQFaʔ)mN 19il4BHcFGG#//tڠQTTbD#XM|󋽡7Ҫch!\SrJPP)xrPc8/ Xc?$Ɂ-;_]Ϟ=mmذvW٣NH+e@4nM~x}RRէBi QRv~ײeKdddX~i&mZP .Y~=^}Uȉc!%OMRUuAue-^obG}Ԓt*66֖e1JOعs]V!aVUUaӦM!Kw/^O<ǻ&os[S U[ 9Kǔcr,^LVRzصkN8aiIsC=d~ٲe(**P{/\޽{INw$N٬Y3Kh5iqʿ,ʕ+?~<{= ,))1sI"SFDǃ]v)#ӧOזFճgO<vfž={BZZŋѷo_̘1ݺu Y I"1GbL8!9'9r$:(1OڻwG<}41m4K}bڴi ӫW/<69s& n^Cv퐗!ChM_y(]H#rRW Y+r .;֯_/~ q.11 oTaU`Ǐ-i۶-Zje<WСƏoΓFѻI՘1cN:e}ر555(--ᅬd ѣJCCΝgy6 77zjF}>(gRJ37=+}YI8;|>$%%oPmHq~&MNzV(lu7O:7ԩSZBiii5jwnhܹsm]]mbС{"5&U&]TVVԩSW;wo~z%!`@QA9s }݇-[Yf8z(N'#PZZCiR4EdX8<>$S*,^s$QhB*^e)%'7p'5U-::111HB(x87ԕ1\s* ȯLx&-oCR2Lw:[ a|A >DAA[ǼTJ%CV}u8`c]k)?Ef=0NcyY7BNW"r62L[o$}&RqeԑmS?K5)pdFy9ϖnMRGn)sjѩxM ţIy jmDEѧOGNidyф(h9/%.ӱ8'C‘zN9'T#%94pI@2P£.*ޅB 8EKzsH $./), *1:U}b2/`)-.{"⸔VP*ل7!*`1<4Rx$ɺauG'Uu[eZRJ9)(\#Id.憜MypKe!H)\V +CpR CSIvn⢬; 9i7 %xnNG$8'.IjX%!'ז@,\bYgCMsAL/ER/)95yL "NVZ'NY(r 9HY©[]JjqkT?'QV!ÿt.S`SqQ%tj\'Ouc:q7zRiwLtxX~$6Vl.^ttDbH)qPhKȥCkt4iln.NKk䏔?H'7!/ 9%qL!}(I @i]<]'$AZS.N;IENDB`commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/000077500000000000000000000000001472045345700251375ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/AbandonedObjectPool.gif000066400000000000000000000540651472045345700314740ustar00rootroot00000000000000GIF89aJ{{{{{{{{{{{{)1)19ƽƽƽƽ,J;H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻxꕸA{+^̘fKL1[̹7jL麣/^ͺaMTqͻ7PCN8M_μH;N:_ֳk~D7=".?8?z7ԏ-V !h j B6(OEHQ\ aX%rIX/(Xc2Xh#h7 Ic7^dHF)e)裕O8\Ĥj])fI_6hffl9朙vxީg|g)hjhgaca%*VJ饖f馚vjt2l`ꩨꪬzZj*zJ+ [뫭&첰fBy&-f{~{͎ A:k .[d o/ jp+LjKng .lH $ko_q6̫$/\<~/N[\jܫMG 3G#ƾdu42cg -7\-Ź޽U-=7Q7mD8Ԃkp1ހ#B[pd+Ny7[;mЭ +v+7k:,=Ĵ#*{MtzG]@K]=꯱ovo;|;G< ޒl1/gɮu{^JƼ9KoC/xhE8Y}7B}@0`HZ/wW} |BP&:"}GV#!1U6 B xPV3 @B+bs"߀gѐ oD0j "d]0a,A-bO\bXŇu.|$obȸQq6H-RjBAC$!I42򕉓X!Z.$˟2Bʤ({I`rR E]ҔL3j²bT˲Y`&)8EWVݪ"h+Ӌ+ŹKJ.9que?_'fj2(!Lg$!yuATtf*YyGsX69t%19Nb0b&RVjPe=ш"BFMu|7g;ZC^OSDJd0XUQ&͘P5Dԣ~5KZӝՋ [VsMg cNMj)k_V hbԥFw&VPJQZztYTI3ƌjRdZzOx\OG*^,Gfe(0O Uֶu2ULpkayP hۭwEAo=&/-Vs a3z`u ޷x[yƲ.=ozOaeo%$]+&<>-kkB05W|* P_=M[2ROWWgF*,$&ܠm3q{'b克\r:f7.3cg?gV?M{*եryG~O\I`5va|5˺EO 6{H1d%m.p@MWЦi ct2c:Nj^ߟQxgb 8[sX:BK.5L攡3M_^}b;9@Z py/o݀8{v~#>oK\x]o=978y[NF#]}L5w6JU չ9I '+j8nEvh=vs+-tL,S©f(YNwkV90bo5@g0.5={`iC:rc;p+DcY*j3/Ь{drO΅>=Oި{gs,8ewWeܠSO\+C>;"/Srnw?/P+7_UG=cؗ:0;/6eT7 XX8r'|&5L3vI{ۣԥWy@|6Jp,GxMNfTx{WlGȃbi-*COthG2mU聫#>씃ZFT|iR+;hg#fvS>lal|D1(&ow~i'D蕈'3Ff*O8Z+cS}TNF$i3SAnub3hvBR]"6I\ȄscM,=؃H4R0@7FS\v@tW'DnAsN6T[X|&8.he<'mG{ʗ4X-zEjAc?lnxB ad`*puNuFS6Z2VSgtdh֑0&zx IuB8$Ƒ' z#POPR!t)YtCWevd:,D٨JeZV~H1H{oq"pwo\q[q7-pdpeq pp b9 bKjgV7;RdIF42UJmV#62. S"y䲄9BA%U7%0fv|?UH 7TQ39i~r܄M)2({5X9한w*#%$0tkh7pb=Ԝ+}Mg靔Ty1%%՜x=a=.B0R2a.x1B s /!`SًIx0"ZhmyRMT>x,W[3uuuTob$xI,[@BM8H:Jg7%%)3$.#y>?Ԝ4f(_)_.j( :Ȕ3WbN衙JئXysu,&4=UN64XvTm;/Z S5IR)wL7vcGP'@&|8*Jz9WB1DTe7S-$sW) iG8:UȞhr-PXA3j19O;W;HO .:3v9'7qrwqږt9vqa'hIriznɖ˰[Q8:hdNVT%Lelu%"xV]DYR`g:24EHlV<%g ʦQtbN.ܵ턘*EWMe܆53n00ݵhflY4F4u6C:ZzÁʼqʩIM9;TZVSb+cxS-5/v?Dc۟zbbd3Jt;D lJjRM*t:6S<_/st %<8[@o3t9:Lc,ڞE)=U%Qzk2A;`/e7:0ѺtLxHf}ċ6Zf}Ǟ2zt,Ү+\n=,bdi=eyźK5[OгŐhiZO0ͧkncۈf;;=<9`mHm.^-a;U0%xnKs; D'!ӫ-G'Ӽq 88lZծbR߂+bdgk3k~FT^i2,G,݆mX9QV(2rf㇅ƻ:C~$ukGcscgyFc }U|k+8'޸$t%3[e+$RͬVȂ4e޹>yGv/x"eȣ[D f#37Z,.L涜o}}F:u|xgktꨫޫ>3*~˙|۷ .y3<:7wx1KNE#N T/a/,_r|=4Y'{a=zPቿKH N ̘\/~ TE;⧅vДUwI逝#, 4}?>v.HS*>U2=1@a2R)# h` j8С%C 5\\hТGz j!˕*c\Id͘2K\OA%Zh50˓*_2|T dV,ijU'Liom[l=͵ { ]`ߒUZj)^2Caqt\3\#yCE1ȗ?&piD|im#YF7­Rg;;s]޽wsѓ]*Yf8x/)|˫]ʟk~m,.0M*6ʤ A =ԩ, J8B-)j$8`($M.5C,otND&` P<,+Bq;vlwz)r@ CH#l3Ml/0 ״<&Z#p mN=[I'<hlq!k$"O][ʫNYlQ":Uԏ|K4\Hov-cNDiSKM&C|7%\TDOʅ(Q"(.xʘB-0ey#rIz21}r!`CD7ud1j jTsreQلgwb fG6 c8,5KdevRUA$ l(HJ~2 (sG?./d!E ~:["a_dCaR&s&5r7 ~{C&sFS#G/jx'?aT@;rP qU?kaTEbG&a\ne[ Ү Md6[%5˜b&{JURJQW#jd4JfBt*]&mx$>{ϦjǓ٤jvQ*U,3"*o9VV)QAM TG=Ωn?kK(J #UgS n4iLB7=hK)^Sr;{e<̞>K:33@2_hPھ3ԨE̲>o-`R2>($;Z :Stոh+*lrTUV;qK]]RkM!mdвХErɈC,TMk_urr8cR!E5͘l|њU^<R *a/R)&_Џ[_^lz :5}(n_lǶCF5 o%$@f- z`әe\\S5] hTEQ*ji؆Y)VZ$%BKF"Zs0c=YuC}#ԷNSC`=*fE &zxb7Muu ڈu5VuPy'*KvLܹIƕls(_ UbǡJ}4SKdH/BG 4~&㱃f@DcWCr#vG&L'`WYzU?۰@!]; [:Tz݆Kʡ{`8bPO!G8Jj%xXwsV2rm$i%9cyW-xGQS?:i Ք㽽/+\DMr4 tХs'餉kgզ/@pw0yvN{7<xC~w#o<9Ƀ>ownciSt5|zyV$5$ #9PVә#Q6~A=qKA rú)ќ I4IsAҿ@AS$87 1")i3)\C Cۣ5{JC: xS19[A೗J[r!x+Ծ c+̕Jį"0|YfC,ADrăc;7|ŗ[[E\E_E`Ej;a F`l :3,4BR5EDnt+D3"PXB3$, bJ4v"ӱ=Iܑ4: CK#?]D\,HHٻE ƀHU( 4J8j|+35W<-KGȜRP[!"ZS-: k526L6D-`X θ܃APJs \dVC(>K1ޘDZ$4#3铐݉5޳)FB&{sH;\}ۚFq2IdG,k& u 3# Ԓk3,B>"#yLt,ˠ2Zk FWDCCZI o*>#A ? 26_\ђ*+&ԭBP"͊u<+@ @*,- pXQ0UyQīD{,d@71uƾ||3̓d7BNڶY DX?DNv;LSRdz.LbiWS`RJ)  a,iDIEP- ?K@Orէ)ڡF^CcQt~bLtG)G͑$+͏4+AY)0]aRMrUy!u riKr;m{c9pL;3ZO\u$sXDDl|Sd ՂIFM3L-Q@)d*CTlryx X-s5ڡ`-8Hʈu6ԌseXC*\|KzXc 3N5/1؂ X[[*R(e)8;q퀛 M \\ܖ})aqC,ɴ#|D2}>ѽBtJbKİ](VX%Zik,sX("4BsbL[2bE%Y \5TCUT/FX1OrsOiܣZZXAn*SBH%$:Ke#)DyD8*"DŽ\NvDQrJ8Rݓ[xb"M8Z:p #~Eׯ jՊS܍tZS a8իL\<`Dﴟ[2 N{=74:>Oٟ@&hF7$)" -.Ia> #ma ոK'Dxʺh%إ%v$ɪZɜSǛiL@:Z(һ=1qtcUK"9?!z](> -1$ґJ:r)] _F UPι̊ɛ-3ÿRY%SYdf@'9 B)[`=3GDC}'kO^rTKVl5CxVE|KL\ٝLגAށ9{`dNIM1k=sCQ)D[ᬣ*Bˆ*2F\hzf~}1:RZchwm<PFf Z AOիcgP5cYM֏ڒ1b%{bY.BK\=^uF"]?_zR}Di6b_e@Jݲu Wڅ 7'kLYCl桪514z#zTN1*js2K.6Ms.G ð(lle$ڛ@4k[:\ۅ6 iJi7m7lc8Z57i:ɱr4{ )mgXr@wIQraF .Ns++<%; )h $txxd-l߂_|37_OzS;8u)&£ʚarSqo3*0:8q4uܓgz[5fBbcѰQ9z{Qzs~Ih㠲/qy׫>;eH+j."iW`jX&i"qkl}L/z{%qVpl2CmeʿQ14j_ՆV@&-7hPo 6@ &D`CN(E+rQaƐAt(qA*;,h ^j$H%Cv|PÅA5p@9e q L5$ɏX^bbǒ-klKn*i۶;yj %HjlԈk&W]Ժx`Bg'SlYeyj8!M6ؐt҉q{Ek:"Y0J穹iE8e}e#2#%inWRB^{U&iY8*覫0j.ndUv׈uB٬%%S2# .zzu.7]Hd &dP1wl(LYp/ gga1n~&"{<~9;sUmtF] pwg= 2ؕ[4p}r*]rVҟ.OI&Erי7Z_Gs_9!kn[~ A{眮Wֵ1I*]3ˣ[&|~Љl9"xy{vħ* '2MO,*NV'WJά򕺱Q6VQ2L_rON/)lI"' Q}>"-fqئčPK|"%Z4 "31eN] _-Pe?ɎlIrG (Q ! EAQ-nIνt4$ "w*0TƢFtJQ\:$oF-Uv#c ᤐBpv hGL dX8 BKW 538lpװ̅09v0#JBAuN ſӝ:eRHI= ҽe,?%7YGcsA1}_J" /`"9 uh%yIJvY(CR0F)M<$>'X'&O+ʛ(aP$Ō(:51 ƖBl}zjaBRo3+6z՞u]6gxQjm椊DZfǺz!+UljU֭@TSBή2?U*Scr|Jc+'Io(bЀ̶ pmsvo{+\v5nqkwMp+2m@skB7ϵXGF`>UZ,Kyȵ'{WׁN+F,bO=cU`}0/l$=N6P΅J0bɦBѣeHHRlg̑WDq1KA1\%!ǩlHRyTy7|6e܈vCIrR)|{ $ ׌+ʚ6 L)>w_}6UQS6oɓ*52|kj== v;9A)N a1߿ i^@=a_EXH`a_b[ 3}Nѯč_d]0KɞjۡDK[Db}HՀGZЉɠ`Zǧb\Z7em5`D=uA\D]I ܇TVQ^dKA2yW͞x`-mUI6o ]Ćt}ٌ#kՋMDXE689!xAY`%N \Ni"~Pνe ]\M$#RRHazF0ιgqHi29@t$QfNcD !*"&'qO3S!npٙ'щ٪hV D.! G^^#LX4&a ב)Y'EHњ%AQ,Fʸ0wpM[1t0MIRP?!٭B$aےqm=_a#:A `A#c7֘\ۨM b#"S#$|-#EkHO%1M]V$qqlmenƂlvҖ~˞֬vj)\ ,a͔#|lK1>œ >::jH,fh-8i Ec0d!Fվ-Q,[mlgQd;cݝtlL֣?& nVmkVn'|bEcG}EI֬dn mƮnKf. FC]]%Vޅ( RB.l&^o,]V$Kы$Я%j5JoVjbnzh DV]ʒ!N^JFBoRnN0E -EJNMf\H&h`뀩2.iR0 YlhܗM(n7PWj`061\0G::? rO'!i{*[\ZaW,E/3iogC q)(u+1 Ԯ@q12#/*k{5xL:2$?r#G&c%GG&2 (py*7NcҶR*ϲ,r*G(E";qsuv 1sr%svuWqAW:Ws=3uAs1+2k52S31w35Wm /e=Dz293;;3Ka^HSEcIW/G4HR%t&t4ӴLKcH4OL4P{DK4tE5#5/SI+5TGCK*GT_2uti5Vgz5X[XXYuu)[7[s\/W\5^uu^5uXS_F[vA5`b#v;6dCLdo]OP egf^ogc8WA6isiwi3P6i7vjkOkǶ6mlsVn߶osokXo6q;q_:7sksOIn=w&wa7_ug7v_wnvw7xCy7zywz{7|[7CS U'&_23'w&0mҀxw6P.838'+}mO*vxz88wچjx8w'Je0d 3r%F7٠d1α]DŸ$Y]O *}~o1hG"xyzjQWXHg)Il BZOrf7 $lOi+sdE1'噣k{blǬ TĞ0bH0nz O2- b{\:OҭzdxVG.!P]8._~8tT } ZM,]ߌ)%xȑzcB;;{h2,^!zK`oXN쀩 p.0[ǥ9Ȧpq>  h;è.."=ܛSX+=3dO<~ 3~)M{+uhߘ닔,yOcA9}.:~@\K8񧽣~/~u, ݿn6lP`B 6daD5XhcF9vdH#I4yrI+Yfl`̅2Ҕ9慁; 'PBy 'ϤJ}8ҡDu_#BL$1&8MܑB#YS ϩ>L1@*=P9:mK2 55 aP.j,mGo=UB9,OWiR,yU3EsUв6 j ZE6Y?5V5D=tRt"3lmUUq& /RDM=6ZTW#v}T^饉oR_e7o+&!]&8]^EY饓nbkWf0UUKSŗ;Zv~zfjvjꮧv6;쩫Zj.׮{ovln_\lkU\#Rl= gapS1i&[Bwd&ÙW0*NZQ>r40A$!C>h"񈀚P d0}e"aÀ'lNrW6al׭h4ʉ9Td:7G;q!i֣4Du+H/5"52-GlL^&_&FS #I)PbʜW ZAdUj%-Q4}ga/5^G !&$Igߨ9MkVf6m~ӛ66I=/U!SaCvi2?2N\񙭾C{@!a`hLp2,[eBPʡKLƬІ.Nt4(Fz40̠I4Y#5pw*Cq ; ''Mo294P:3F~ ݃d g^{U[窂6k*lˆuO]9RRmb;1L~֌fO?T͟O13dZX&40P}3W(eHֽ>x+"5gb,Z4NFH-8y>./hKH4q轱FA ʞJH?D\*RYhS7=Bbl&&n,=Pa`l}HR Y,IR|i0 YvG(p"ﴎ,kp]l@ ̏ M=+ mdI2-&Rh* 2p4hPD zjнξ 0 в,Ћt/R+Ǵٍ̼#wCȰA0,101t '`C+.K8(pj+8++йLh>nW kc2.E P-Lv,&-Y L,+K <,0њ"{yr*}Bp1 lNoqt/JwklLQJ*FrBb~l| OPNo ( 7Nb10 (#dJ)DU**D "~8 *ga1ϊfۈ6mxCF-"V-b8(irR-R]`p?p-FMiܐ`vRHr.HpE产Dd*E-4an4E j-}1(PN8\ED1Q^ODNH~R$K $$9/51=-H>I-6l:$odP(R1K,K~3ا4S+(HRXOBfgp㣸f)).iQِ’,J^ -"&> C9-N o69J,FblK(C;TtF> 6.1دZDVGD/YmE3(='6ë-bu) (,*C )E+9SbYD..%dZoZ#B[, ي? yygjj$ci-z4Fk#k=7vB Z/%ezBe/^'b;]cr#M /MNOmz[YA,;e֭/p:-y%VN1`æ5c/CU0hy :wϬ]CE CH/1Jl\bɄ]1`\9>b*)R.PO锧q)5{d7^w{DEAs \z91Ĕ Uqcc9{=,^']^^ǽ4JO󾧎_"]MGOyL;?C/ 'JA/AOu_kogOAZ\_M#q'mn#Gk_m_?EoN_{n3?$_ <0… :|1C$Z1ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{;commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/BasicDataSource.gif000066400000000000000000000373111472045345700306270ustar00rootroot00000000000000GIF89a{{)1)19ƽ,%H*\ȰÇ#JHŋ3jx)$ɓ&S\%˗.cœ)&͛6s,P@@JtѢH*MtӦPJJuժXj}pQ_+Tؠf,+-ٴnњݹw}^< ʠn[#^1ǎH`-]{fuAYeӤCf;YqҕYٟc|7ݣm>\xm]>>tPСhuaF^֭sEF[2ݭ^Pt;빫뜭n[Kx}vwA^Q=Ͻd@Y % gZFtq(PJءQ*HX쩅[g fqvFxx`88^?]@'ݒ ia`;:x~hT5Q}݃>)%؅ȠW>q:CugY'[gqym9fFccuVg ~gyU *iY^)[h`V(#zI+I f 3afzfk,V+Q86)Z:v;j>NTckTr} [sKRӪF%^dQ! gXc쁊Phr52ƹrjl7sUzCZ%XNVRg@(!M="QUg5[w ]m6Tdgu-r]'} L7ҁmxAwт⃃7\˖,˙eyf 1wY\qzoǭN\/Nc_:WKŮۺ# ;+|KS{.JjKQJ}IkT>)}藯>$w$?~ڏ~_\ "9'HAv4yp G(B: D=Uس^ 'f^*tvF4@~PPIbjB:͝LtCQL 0hݕŋ]z0>kQzEpqAQPv0Xz)yb5LT) }[OsGy?_}isO~o|W|'~ȗ'ww hx 8Xx(ݗ"8$X&Hv x*y؂0284,Xw8x/9(>HyA(xAEw%?P8#UHtZYÅc`(aeg>q0fdprtXE`xy8}h7VAX!r-S8A "s84mX92r29XkT $^R!͕\ Ub*tj[Xh~+T)&k (܂B" $QVr&TFbA1?&YQ&(urD(O'`hqؕ'$Q"#heT v򱖤2Lh6R_(I%&Մ!W5ݑVqQb5sOB2:E{Q\n*QpD$t= 'UKUK^r&`$`$=ff/H^AJVx3/)<_KHraaԨr37p#@I@v>[c5WIup'stx6c7]#kHd0yAm8@>s\W#]Epgm_(Ff1Q/I FϩZ r!^EikԋfsO/!E/"σ(29K9ȚT*dj5㘴4B1l~qkh傍uŝhuq!ųGUʦݳ @`Jʸ-\IIXmJnERd{Z[&PԨ&ꆞNxkehus)5|r6bU`_ jP^2q0uJfhH\W*Y*eBZ&P6cȤgmp-O8"SMD& bQ^u *L!"9&WDSniJRdvĩ^fU֔SQDVVկYRz@%9%5JQ&Z>Q0ő9%JN'ua)N@6+NQ."U!5{[5Wb`BԱ:ukrOGD-#g`"iRPS R#k$%"cHj^etU e'hY;'㔲-K3k&1Q^KU蒁XȪ!MPk!q$G_?fƣ(6WK'D4]/CkuvHqhAfE8-JZӲ|o.V5G$,S K꼀)k嘢kK*:ʻ \ R;~a DhS(^J)bif_6F45 ¦e[4T#]4e!G )6CKi!w:<ڻF\c!JgE;8`մZ*b5v(^pԼce,M'\Wq%XTL"gYdaCI: 0}l㛝ƕn6Zql_K\{ ܬYZ<[ZQ4jtcZ=38KujNK[g|LloE_0T DՉj*):\,fYgEmƁ{0:Kǡ}C0G%Xkq_eQ;mOeS`4Mf;n\Ӛ4^RRJ Tmek:d PadFL>q鲪qy`+LcVgl/9a$=$gft*tlVF3J`֤O !;rPGG{ҳƴU7CE`ۑm3WMRȞgM\Q:]X|m`<Ωce@r\R*ά{\i}ᄛ=ҳG[2I (TUP{6kĄѮVc&#'^E5 ɇ9ƛ)" t" KH0AʦzM1]8ll#Yrqh;  lϮ!ȕv}M绢y cx=hBڡxBlqO  <8@ *d &XPD paF& 9TJ( 2K$E~txR 5gzg}.@#{ŨĠ4Kh2M)W(cĹ3*ԞSvXaΦ9َwьR\Ⱦ&b]r!pcn^t[Q*NJ'ܼS̴ĈBj&M!攜\J52ZtͲycAɣumjv˪4+9׃vm27,^Z \{C$8yN3oj8`3,,ܓ'N7̥ Cp1[7ī;:1I$O\FCEDQLR,UTsTJ%2 jM LƄTCKwU̦8=ΫfkVrRhL2/dL0PrL<r+uMj AH-*" s5FdI=}UG %![/^'?e47 m G"ԵL1%k~ʩjcX6 gO&B Y* g)g(B-;9隂#z9+)s+ZΧ N5m.h¾S;s Ib9v;kxu:lN7҈U[#sr4z ޖíAÊj7eË\Uu<Ә zbs@W(7'AZ*I;{+}-iuj93U>&E9CW6+'y"U,e$(UHƂh`#R}"ڤKOƒcQ^U2žg&4Q "dcS]Ej8խ'x0 ^L(PX %ZoEQƢnZo سLKs-+`X:@adRTǞ'm*PeçLkI@dRVC"PSy=Q!YJi^+3DJĪݪnI`g7لgJ9MDҔN)/A6A LϳZ?$tхW[0[SFUn@XKݺW$Y.JTO 6 * zK9śح1*], X֪(t=J`9)KB ^o$8eڎh ~h=מ,y3 o ?V.>T| #t'*fCHjJkS,ֹkɦ^%ZdClK9e}Ϩ~b!COvM@nJ4ۥp^%IouĢTF5Wx{kMP;TϞ N"j9$ `b'nƪ[}gk/ W\4RpШSOʅѵJz8 GɄ*RT狡l(5HE]'6We]b[YAEEq"ZﺡN,&+({\ݳyy3z갌䪾WsL񦰶]OeNbjf^Ѩ$V [VcC i:XfO<;@^bͯnYS^29|,àF1'ޚ'-`K]kH 4Ǥ˜9nFN hmkd8s5?e*Mm_ P2<ɰ{%(EW1d2kCUkd(5{\@ y "( H!6a!?1s8) lȊj˰ӴE%# "A<;䴳\3hB9Œ<:,jDy dS0:1ߺ4K 6&A8&'0cL@@2t6܌rA\ ^B첖 N>=sN M3sqEBCqd=/$"|,5P)-Qr $IőE IQr ^*3P\:؛8KǙG.9ӈ0 + %-J%qHHB,-sRn Q &³#z1ӛDۥ h_>?<K.˺Q0$`b9$8hB?4$[R:)j kUGEű3*I/말s{bySJPUsDCC{(rGhI k|N O qRJx^MJtSUK& Kl:b?;Q[tV+ UV1 B+kei X˴@kJMtL8AҜ\?\ګ --@\I !uP{?4GS֫.GO\=%$Jkw,$A̡FEZ 04:ɳ-;< wb*ARa1;J-|k=ɢeƠSYTW;PPP#Y>]2T;{K3J &˔ဨ0z)>ܴiEBtS8|_g/`W$'K|ó6U|mWt#0 `(cĐLAzVlEM1|t|5?6Ye*alzJ>)㴷[b16[ ᴶH:q25::0b{ FR9+13D8N~8OmX7bHl0Bmc)1۸#H3yK + 5ڮ>\"Y! MIůSZ{#e9iπ,3S y@! Z#G)ZD #uC*s|a#.`-; +:U1< oޕ{2_dZ2X30;t w&JLR}KCSwea"@CQfZ|wڦ3F,ڿ~(ܟ93LӀ}sZW(by=/MF:[Ÿ.'GAvM4ˣ+J{j^EkߐhDðT3>E '+mI<.ݫ/Э4婔hBU_4ͦݱfj9`tDZTP彋]>!.=MH\FR-%ݩc[=."qTSe_)nXBj&z7:1] i ٷ2=qy?].I[%7o\T5:;qC+ [zTgś3jS^5qjdJh;@땏䤖{Q_Pe9 #Vl[DZs9&jcmf:'TL2a1lA)DV$#`SapGc&S]4ᨌlY4laFldkboy䳄tbgBU%Str $?e'?madM\ti01j 'ߙ\/KX=C:`kg{9>/ CA8i!eoذH>6$21H~bKY /ж'j@ 2 aГ2QG]%:N\Еss- I7]XTI\/%Vfi# Hf00q\Uj='K16e9:5y6ȧc]'4yIV=(Zi]LOjH!hۺq:Här=lHs6tQ?-,Zl{PEIE9J z_@QvSe|!Ui5;V,Ŷj*ˢkzsZĂWՀ~pG XP ؐÂ%.EBCbhq Ã!.PdD1#JivJ(ɐ8_f(N72]YȈm>(ST hS7 @-٨A ~5UJ H1R ƨ[m8U(Hm-pЙmnG``'L mU}h .xeJGϖ:ޱ< m[ш jvۦng] $v-tǢns9ӯTnetshfLWQi4zQqg[J!hP5{Sp!Alyh?A[ זB)8!|鍷t9Vpmp=f݌l{9nE9vr[ؑaJk9]U$VYߜmUYien$oNfU*с[ٞ>W#)D/7&9mǠ{wcZe>j-5A̍sZQN÷eMԆ=ӄdV$faUgvLc-=E%> =O&:7dOFmQ-3ٖ΂nA f<()[C}v]U ߆VTqJZ3yWR*kӥժ&+N*@ LB@ʷ7ӴD7XO YXNJQ5f1G W(7irJNۚA+[jt(]#좸'K9Ȋ5B%: 2_Vl;23|F{jX-Q5k~%Ctt rt/Z䈉YǩAp|#&|"foVQ24XL=ǭ{I+10V ..[4B)iRzX^6Vlie{D1=LeØ NgzRŝN|I_w4SŹbBΧ T {kܱNɩ<}W旻\WRǑÌM0Ga'4Q#L\=ǵݙyNzWDjG`9 qI\ ZuY]1US9܀ˈ_B[BY_)zy.|@e)g mB| ŐJYL|xvQDͨV܆Ҹj~\]LqOqƝ>\_uiyHvY!~QL,FjX$]&-{]׽  HR&Ր9>"?MuJ1QXО|XZʴ|hfkF`ca]IŅXbܱ=S1#@zNCƢAܚ~bYD$N@KE͐UL裲Q4] &n4D>cܬh-H1UZX\Viiepa-r! sŽ ".e E!d:]%ۚph I1Wyd 5Xݍ^-I`$ϺE&""ݐ׊9XW=U ur펻rM`9Wڡa-Vs'wLO( kQ-!U+p'eݰX! ڐ ˒'EDfaioD訏q§͸ȱ^Aܥ1ۋPD]7jZhQ(ިF?fiޠ @臶WܵcRcZa(Zj=Z%)"a:6Y଍6쉩8)ifKF)_ZH*jj٣NjHHnj"zj @^jbꨚꥂn**j*꩞j꫺*檬*jk*j*vҜΟ^+Xj)rfk=y+fkp@V@Д#QCN6)6!mN).$]hrS\H9ZC[`$E,g?.5Ԑ1P#՞R*)P = \hYlCBQl4+_]|4łddci,lۡ(u~QTB!];ᗺnR:F4>)~&Z e,tBԚ-tϺdb%8ЎncHnԒ,ɖ띴-mQZ |ˡn"@^Y.ߺ8ny`=g 5gl' ٖ-jsf"&Ź !l1noRmF`b yP( ˇՋz-bvV.Dg+ن8F)m#;^[RU^/~~ t.p mƕnFlme`WmJB*^Űݕ^rI [pk%`pLep"^"0xX-?2F l )Jq⬭2,Q8ŰqB` Emlh/ c0C1Vm | XJyq%sXy,hWqKΟ2*G17j% ߲rQR>irr..\*i0^Y=5S*6_6= _5/*~ZY%NG87;;nDQƎ=7޳>3?r뛢T6_ 4"AB74COn6#m3FOtFot|>k4r򳸎kJw+Ԫ4MϴMgMjjMtN4PP5QQ*`R/5S7S?5TGTO5UWU_5VgVo5WwW5Xou@;commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/ConnectionFactory.gif000066400000000000000000000127361472045345700312660ustar00rootroot00000000000000GIF89ab)1)19,bH*\ȰÇ#JHŋ3jȱǏ CIɓ$ @˖0_ʌIs͚8og˝@s ѣH 8 AӧNB**իVbTӦ],׳R $]˶Hazܻu޵W.޾~woÀ+න5Kʕ|3fƐC-}Q'Zujֆ2ulط%ͻZ~ 7wp/~cʏ~0D=z|x;‚=Yp _Pg#AG:#1poJtJ<VҺ ?'Ywj$h+6 q5L&X dlkahl`4H ,~fYcմr3 U` HT0Nv,\p#\մ,qT?V/ &*`C*67$bC5v\ZRD,Y2K̲ .B\%%.c L,%/yL[TfʛD d$:1dMq<$̾lm-7a7[3v|Y̅Fӆ<\dAHS3:$@*1*a] vI'f,d(fu'6e\*S:qc&6L$`Pj `gA"DT@R]Ҩ4GzXO/M9H zuGOVF5iSU`u:?O%##Iq'qT}ڈִREPI>mv |yj%IoD(OeLKRX)AjYBmKUf)? Q/<hVmQ4+<%F{m=<-վHOc VPb25-MQkZ[.{;/Ԑ7w"H:f酄-KG֢j|xkEJ(q~-\njoLuMFmp;%7QRN'$.WH#2󗓭6yug+y~?̑zIM_wˣN@WJs}xg@{$:vӖ}w;bS]nXg[4ˬ%2%L%<7}C_Maz9;tϯGۆ { ${w"G[_)<=D~ݹ?ЗA>Q\v \hWG=Ab/ֻZ|oڐ?ԯ~9(gfEV_sN 8g7s2 `;5W3uPgIszd7'ӇgNcIc\mG'E-GA DŽjy;؃#;@u+}^UUIPI89iS=AD@r#e~(U/|4~5XhY0!|)}$GODiXGY@'4@-@ȉkwl#|HےC7/ RF$QocQw.GȈ*,ǵ,#D:$C>` czĢ:8;Ba$L@hNu08j gUhgI 3Ev6TT})<&$3 9<,Ų@<@IiT0(e4OJx{$hHV>I@IT('YC!CH^1WEP3!`U%a5/-/V} {(iu8B<=)>)!qӗ 6A雝ECI\3cH1Qg(&jU9G`9:c&sR{>A+R`EгA|"aȞ&h$,9J),/#%>Z7#!vN~_03 b} _>6Ù'+S@&;Ƹz 446,[`Q脦7 =HZCٞSJjuࣝxhi:@YT1g.EFeח%Ar[۵i\bdeckjgKri;6!ejv{c W5?F8N1 xQyV%!9䜶{y뜐FS f%FOꚵL֮;cb**"i9jj5j:fKM6Kq+;[{k ^Ƽ]w;[ [t˛;ֻKkrޛzK`+JJTK 'z뿵7뗔INIE<CxyikrUF” i[x灑+0+ӺIO)VaR{Z#æ,x{+tkC9ffa8fPLŰqā^h( DKdZwe̒9:Yj[R4Ɓ=%<\"Z(%\f#2< 9!}Ck|<;J毵\U6x/NP~1gIKh+zӁI |ɁbYDǓHMB$ATNI;QDUEp%6 2#G!)DoC0:{Xw; EuL1N-DO" -S˦JlDȃjl;L$iM.Fy;Xj{7\;commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/Delegating.gif000066400000000000000000001052011472045345700276700ustar00rootroot00000000000000GIF89a)1)19,!H*\ȰÇ#JHŋ3jȱǏ C.L HT)eF X̙8sɳϟ@ JѣoIsҦ)իXjʵׯ` P`ٲhɪMv۶xKܲ wmڻ|,mN*^̸ǐ#Kf\A-c|3ϞCs| 3Ӣ5F3fիc-;e&ͻk:iǑwVrơ#.tˣ3]Nӫ2\Z_;!ހh&XPe}1@}^Yi^faw6v`(,(ZWuh`#ȣuY@θ#I#UPF)+2h#X.9h &0d]iuhye H埀*蠺U'@rqN8dhxvfi=ᚚٹ}CVc=ew&j$LꪬOV(zzpz_iek`v:lxVkf`FܖJ짚{>j B&GUf$ @κ0n. #Īnr'w $l2oB.18;_^r"lH'T /l۱>J w&Jpz:-f~*lQ{z)Y}6PͷB{Wی7$PwiZjzW_ڐ%3hɕ*Yʰn $o|hf|j 8 Gmܳqg |>~:r(!no]d7i̓x@[BF/z1Z,s!K2 z#Єl72 1%F@io󝍓eAI:>= FCVZ"\0.H1(І:DJDJъ&\JJ4Q HLD$hINz0uKPRGibbӞ>}JԢH RԦfTSJ@U^jUլh"_IXJֲeA+Njֶ?akIֺq]W!I`J^3Y5b՞ #edلT6ͬfrكt6 mh?;O%-'MVmEdUZR+TijAEq:Wmnt+Rͮuzx;EVH25|K_ů~ ڀҶ /p&15B`w{ ilU4Xii)Qtd@,RyrZ$fO␶ĺydLQ26^3?xGvgܕ%݄2P)GS bv9} f`Yd.sP66jv 8uθyk .`D+9 \a&&Nb-r’LR*NH+fPSѓδsD.ANuukSַy#jFՍN"\;iMg ˎDg{6kkk{ƵWmsIy6's\J7ukt[ܾ&TwEw5 çQ%Nm@ GV('K[/Og<]Ÿi~s1:)t=O/{+PWzѥƨ#SǺ"I@%&֍qTK]E{섂bv:][LnƐ2x;y&>U&]UnH6'R9`SuLۛ0'2y#szL*WR/-ђ{^K—?|/ΏpI.~}.߾?,O%׏}/oÐ:s$e#x/M$X#҃hxO%88"h!$%-424f!!H&c9@:t"':89tC2HA9-zR>g!CaDh7r"x7q)=H4&`87h0qjWt'e75>-#=ib'I<a$8(s'L34aR!#_r@xᅕWxhx;-K?79́>a/(="~8Wd6D-h)2h6hC42bc9@?*W؍8#H#808F㉥XVɣR?߸7$#VH)@lx*iւ}ሺxy8(9H!h?rs7r@s'(&*%:roa`4S5=e(΁&z+ڡڬELjZ9 ȱ9Z 6>ӊ1*1z3*5p*v 'J1B5_:{<=k^BK94!30)+ [%)Zz[#Oth[dFf[`;cjAҶc~d GFXHoʮ93V.a)8ѫJ!ɤV# m*ZS._ʟ8z#1B\UIi`2ʪ{`3' Zkxc>B^z,>ڮ${+K%i1 I63CyA("Y3+> M:(#IHDؾZ~] a(?H<2 J@› 0[ٛ8+ zx gq_ᩓi$ͩq*$H";kZ'x(ӑY;J;῾jA}[Uq!4bY9p";>-JM7I+K<"[-acHxR*@c֬ᩞd+#lfpzmYj惀y s'{zO +,G(̒ ١NHb?sDOEʼ$Z'OI@l}ٚ==9*t~24D5 еA;l<>(-;S0_7 `"prMv$FkJ=LL,jg$BtB.\_BBb`0XtB?/=R"FQK%` ?Et8 qNqAwaڧ|T4`/EH`F% EGPQ!or=-g iUI䱏 O= oXʯ~4n?_T_VDˍTqGAfa2ʽMuēBIqSf @H0pdC%NXE5n8G!E(I)Ud%I/eΤYM2|```8%Jr΢I:SQm6Zբ hUIaŮ:,Hgծe+l[q29ٺw/[fi^‰U6mcȑo\C_挑qA&Qti}5NǦtmboN]p7oC=8-/LsvGrzuś_v_>lqW~ {jǯOjI@+|*T>.B BϮ.РA9L+DET1E alEk h 2 _G!lHT"3hѡ'tr" % sL(Y%, 쵲$6CJ(6㒳NT, sJ>rJ΀ƻ G,oϸ5k 4;FQsT 9T< ӥ6uLTZHSkTlGJj&H E=_ PaR}5׿z˿.ٸj[m[pq5\tUt]7v}\wEWDW^{7xஶ:_v8[ fXێ3y〯//i`pa9ey{nsg磍饕&:f馡zk:曹jlmf!Q [nN;m{o] X o~8 gG=moه?<{p#hRv~w7<׵Knhv0Q#iBsEbvf !)R} K0y˽{:{؋ @ثYӁ-SқHA*"s*|&zMv*4! ?LBE|-/7"D*ۣ;N̍AݸA'@B.Y?9ţjOB$ &DBPd&bJ+tԜbGxrGD-Үڔw[H.?4t(%"!dF")@lBQD+G:Djt?dAT=Ⱥ1ȯF?,:t(] EleԦII` q`H8jFBeGAG?B%25l!FK`) tKsnˏL Lo1~qkQLl˯ t\LĴLm銼$*00T̽t̻͏ M|M͜ތMĄ ̐pMKoJ˂1׌dThξKvΜN͌N\LLLoNT̉rp,ə]C;HkħtP)=4#$)J-u|āLZK^ZFe:s R|J!F1ZSdAHG*mcĠIhC^P u ̥/I?j*=RˢS?)*[uD,.$-DMR@jQt39DD;Tzi#3r56@SP @rt%~}T_{L\}"'"j4ȲLPQI-4PAݩaRܸQd ?Uo["qMWH*ʦUY1=5W}%W DWXy#)LBѼ"X׆ S"tkJzX}ꚡI׎nNH >{*H@\!Q+.ig >[yk K`Q724]i]l4|\eimAX~`J.deMnbY m1eƽ4Z&1=2i:)8-gY8~3nǞ &G d,1&iavg7"&/VychIe- טGRciof뼮NޯR dI-0`{8V38^,0rm-cIщD =%^ViJkhfh!VN#^jj=~ho&doݺl'c%Ġ$e&jN-pϹA*}n~oFa7l^\ξj".ihj-ֳRf޷{.93*gӹR:f1]Tq@좉Ln+gJ>r;4^V_o1 8^`͝DIs7p@$_vl7>B^\/hr-7N3bCW&%odn(ɚ}ˡ9~FPmqķ<7Į~?Q*e#.t(DO b+:R#dQ\2G:l1j0bc'vh dyvv$Iv$YjvjCvl*uP+%uiT-«nV2# p,MI kyrlᲤW%֣?F?F#>m"+6H~!Y>.D\$UdNhTܽ 4bs%AVy:V-pttiX4JY%N UwIai~lqǔH5CEqHsZy%uRJ'Z ТA5 qZ+-,XP^ꊐwgbNw(ZlPu+h׈ +Ⱦ:u9Jd.oShZƎqoeg!"Au@ε$-v[E%.F9+ Gd+8}GL=5NtI R[Wu_'mp3A`ν[ۼugǾЋ)s%t&3%@\ dA|q>^ޗO78":~H'PuVf\slA@.4hBg;ڎ^yvC.GwKE%L aVQ%U%x 5;hg<>$\-'q0`</$}H$B',Kk,}]j9\Cf#)cDS`X$0QE@/RҍR/؛z%WٷfRr,aMMj1Ҥ)M 3u^-VxV\qaM'ęMXHՐ{"WxOݛ'id;VIC8}SW\› ŲkXA]6,xZ霏80]lβex7G F2uZi!d+hg/+s]ٕ5sN1z+yWOD$8&-P#w$ iv˫q$t . li$-I)ѧM1PnzY-P*_6Աjɗ@A yʭkM (D$E`kW4;Jjr!O b-rJ4hoHtӫ< blU~b{4\޶k{ݕ"a91B{mӝomϊn]U1xEϹ(S]RWP.쎌/ٍ(Eo'2 C&vGJSM".KSD-'::sn}kRBSl^f;wIn/Hܟnkؿb4Qᅯ2ޭk _㖿ñ^q4C$JY2 S}pMvT"+桯y;=:riP>236о#q\YXѓ k6ܢZdNZmaK%JʹAۡt`pa E#C4j}10p=cQ#:ZTvX5#X#31b^VX hR"! D-1&.Mg)*B@b9KE"L$M֤Mj0MF"cCF2f0ŗa`L0ISaiR$d?2V⽋=XS(%B%Y%?zbN~E W$^IeZ[%:^wgY]"nE-)%Ud3>E֑fRg>$!M\&J c;Cj%UE]XH8ȑcR;% W ڠDrr2'@gsFs.guR'tMt^t:tFgwxgvy~'skD#fYj||VRUJ> nKRY`=a%0'а!% l&PҧDar]_̹a޵| NӊX"eddZ-%HT(熺&q~hF}#q^\T]9M]̋%HgՎ"\B'cFͩ@"fΩQ 'ީ)*G@\\!Dnę&0  hh^cJq*D6 VH~h#M>P>*h[hRߙ4EVBC."** 2!nӔ+w++>Lv뼮+ҫra]߽u0 hF^ 6Ğf vI,vaɷ^l@`8+p"PXHzbXُxIʵ~Œ?Q,l>i\dlXbTP`9o]R0͐EJkEBNsgN4-Jm~ڦ퇀۲Z(xX<,'i"TD % pfb&uWF.IڶfHhܶ-))Ϫl$mqşlsA큜ʋYPAc *jjQ. %­ܲ-z.x 58lg)İN8mqA2nެ+.o"έrnmDK@a.^؏PۘqnhߜM!9.)q^/aNN(J zwP `.ᄪ} hۧIdρz5بr|@n D#Jƺo Xo ܾX !ںJ8[k\pХKp5q7lj=`] 9_V(lZE% qג*`qf±#F]%=j[ޢwqYO4d)"W2,\23X֘~ߪ rI"V#.Gﮪ>/dIMQ͖g\A?n^`qܵ:p16;-nD3Mn-m_4N2G&!m9N!whU"n.3˴BFGn#jb5WR~~""˵$Y /f{-QvcDwtl׵];#`ͯqŦQݴ8ΩHb2S):5eOnUWJvpm".*Ë}BoLXv%Rdf62mvI egSi 7Yonds4׳n@VWwJ)hǽv^)&ٵE*^iYs?w\ln|kwc8M,}ĈB ٙʐ\Չ߱E+K^IzQ\r'UژCJ7._~rSHG4JEWbB,@6=_S^R8| Mo~w8(Q-v\m] a/eC͵gylx~cT~R`a0=`K9*X;s#Cw"uУY'"X鹬ҹ}ZlOyu7qvܪ&`t3hhD tĞs^w8oMVu1utAH2FzO5XnzOin!J*HCwsb6;,\O;1J۵vP[D4UpLx:e:4t %0x/J\v3UT7sswQ(y{ qr+vܐC9iةWy>qxRU>>e>=T2]};<}I̽ox"QFX^9yX++cu};eb > x0@&\`@ BH8cF9vdH0hpI'<`%ʗ0Q682˘&g<ٳAK5]MiL0QPQRi4UQV3們cɖ5{-un\s.Ko^ BKD3> <^ŋ:[iT9`i^fpsg4~飤klسn};ɻyV֢oÉp˙(:ҟS(uԟg}.9t5'Z)׫_ʲ~kM zʤ̶N[pڭ%H -0(Đò6D HQ=i滛LHM-AW0.0L cѻTS;s:jmt&f/%.>l=jZTQ\@*TKN3]K;ERGT/[lE6amQS1&aR:&L;22% R:%VWF%vW4S2AnS5P%]0 5 hY\3YהSk~ZW>Ih2p=Qc^R R#å4+mM_Q- /R. +B02\ j<-.p|-6)5haN_a@Eܰ0-m 9nn}* jʮ2τ@_jT#YIrS ֑YL(+F5!*{Jђ|diZ)f )v/LbӘ2Ya:ܥcBf/9jD4psYj2T$` O{f=6yd'!2Ѐs-ꄑÑZXd9 MUDQtL |]dXʣL9D[ƠqCP%3 #J)B[*|V4U*qGK2MgSVRU0ԫsJڌ C륯k幈UYָҥ+o V5_0Dzӟw^-!*6~+k^r&8e5lG22g+KeEQJZյ]cc[[~Le+W$XzijU _XFr_\u\̹e m҅sjuˡJMX\UA{P~Brъ$ /|]q ۍ$gp?; P UC噃azx q6`G#%NLl'uSqs^OŀINaX:QVc" O[ rc*}o-cUIj2]O#m.F:ӊ͚ ɳ68sŔr9At[gs =3z'T"޾Mo2Q=[yө~$bu:[=ߡD/FZ%t[/AWղ6e[,4&z̆٥n-#]^ڶ,vmuCb 1j4զ:6>hzTdo79^pWx,38-g 9FYq*EW)WYr'g[-Hڶm;z5:6e>'HzS}7yH \g= 1W{mv)g@xad_ş唝%5S⽦W=)ew戭 t$o^/ `'A{t=|Y %΄?d əJ/YcaB΋CIq_'d OEtIr @MVp^ FbͻxNQ O-$ ې6q31O0+C(1ID1Xb%sQq- J-I0n|Py>|QZe`&!C%wT"/ }00Td ӊdqp-$ͭj-U:1TV&]&Z0"qY,v'pv&91"q$͐vij QpLxq-F\2@CO\w(?R,Lcbpr(-%yj | Ť*Cq3,#d-L"3&S2+2/2337S3;3)*lf.6b0#NL41m cR3FH%oNx3Nv8}3Lbs#. „+6a1P-[icN'S(/<3']Q9nf5s/ch$μ3/.c2-gR@ϲną*0)elE*#CyhI0˃9IYT Q,Q'QRRϳ 6ć I,:ױa1TAHUNC{L>T|.#^h(k*F5#e!V$mE:*T!厴%*{TZOg_JH\M\_j"K)Sp?VU :Q耬ںUI"]i(1tՆ/TCɆՀ`!(gOVF2P jOEݨ)T-lk:}qʤLLcBR m#a=j"2B fzt'~P%7 hOW3PQk.B‚/f4.q2LSB"LPcl ,[v"B1ܐ;V8S07P3DcH)7T+O_vmefe%?rU4u^3+m#L]y"w0ft^Emնmz @$tW6c4x_G'n;APfqoW2zX/+z2>b>3rwyr3z5{#7pm@ud)rQ\Z1 5w{8Fa0H&aooncR]ކK⟐ 8ès/gNt.VMZcV&Qx"fZFJbvI6~o|4`bƄJO]xV'x q×y f蘏 9]T'؏q ؑ)YxزK\tն*poQt;Gq]7RVXaQxkP%ar9I~A?~Lwd!ko%Mu!$cX`&X~YuEW%ŕ-bn9b|iט7B&זA;Wvxr1RkXjWZi1|%/cg*z٩86y)t~O>)AzPz(&J? :NswGvB}Xn5 %9"ؘ,e zNP"Xoc)S?po+43<ĺ,V~gϟ^eZpSGfDY3ncZ n7zʖE_R5c`:n'eX}&#ViAQ:tZ‡*b:$HL,J"=m/Xt.;z'7)gl>|F$tYFטURõohJwiؔhZ nwFhE#=YY*>t_wUo&ce5MRLyƌd1Pu]KTcm75aXwar7V9A`:/} 4R?B8yƝB]=7r;FTtQm-a (wU8+hZv`zvf2;mp߰}f۽A:.HU4ҬmmаO2$%BGtB`:(йpX dQ*yMPcf?5DYP{ e/ F\ 8: &6ҽ\ `HyxWp&FQ)szg"M}tJ}7(J</<h1dMP' ؛W %u\${C]m,; ҋ/If뗁|qcwbjU*\"[}ܯ{>cӄ[@ڭ,7] `39dhQwZ\=owYh= }`fn]HIkY3s.?=|;̜܀JdКߊI2BK/ϖfhXo>(vb_=7?9Y>C7W{OVoAhH5>Jzl[%`}P(Q܇kL̶Ĉy\Lӓ"Pc&,;^{EwXm4zwRaW;s5>>4y'1`!q ?B/`XhG0òm".\WV6q<7SY" ,0… :|1ĉq"A0bƑ$KDxJ \ia/fa>& &8- IF8G66dR8T^G?&$QzYDbaA:N(fUi5UTTBUTzi9VzI)uT|^v'~󩷔 gVOV :S*]mI*Dlj~)E+Xꭶ뭽֧kTj&|,,^JmǾ,IuNʭn, 8,Fx`R!0TPJ4Kݣ(Q #^&<}ߥ1U=ISMxuEKŴzOS.>.AuA>^ݡawhKOvv'Wx=?iy2csoW'g,ƕ]*fWi~ HK^ 25ǫ`u2ȑp% !4蒗mOXG%vU 6O>pf O7v!&KBFa~RT:"Do~rR]Eۺ7O|gԠDžMr|G?Re_%H X=s**@KIILBEwRA$ubuhKX_W6e(2l^JJ3BLoYR[TF vel-mM\%*3YLQʰN!fSL&]썙P1 P벷0b̎#ӾdC(67?od쒩mb"Y?wĦ*3Ft}K>CuڦWYIGj |qP%`PjU&JYEU@ :@lm\0r2Xl@Ц(£,jfQϚҔTiՌ!ʮ`5VEҦ'_*T(,([6Su Er5e^M/6+[ϻn%(xgg~{XUSSlb)a^q&hUc?žײ#~3r ˪ RL쿤{KV"$EvBr.XNPfq԰(w̺[JZ2J P}[˶9%`ls Axz/Pd|٠:'ovYʒ?fE 9afjEpUZ݂5Eb*r[1b|,S;q{1:֤Gr\%p^:&9כjڹSWPTvu[d`%-\ WF62'8Ԡ^qSTrXV7l3dZ_1PUvW0Ln<)i&0L[2*oղ9g]OSZYw䳓\*#~,}qТuA-6oGd{^|T;ߟ+y4<ͷ*^U.3|˳(~י҅LEk]I+9L>=Z^ꌚYyr\\sb:yv~Ap =;2zӫ9r=zӧ>_j7=mƀa,a够058^y *=:{kW}1a|!/gi}S$6 0nO b# ?h@S>X UgRxENÃ?ҶgZ]GSVt5măm%lnt?b&lvt5y#lw6\xxP}qn''.Xh|]]i;Y,&:XCRJ$jΤ_ YH(9iɐh%ZgiD.Beb((\$9v=SHژ1NkuX!ׂpɞw{#JFaCK.jZpZ|]%qya1^[)8I}Vb?z2D /c!n)l7iX*5Aw-t1V`EqzqN<╼9C`!ag,X q,ǻ^b4CB(2Ǔ-0DMv!2)asWq,[Z,g œ/ƓLəL:ǡ,ʣib_XTXpHZF[i^xyyF ɘme ƙ,nl6 ~􋣸0 8!\`p{GxI1pL|ɟ\̝\̞Lϟ ;0t›I\7@s{-wm,*ނ 3NΒOJ -IUf,Ț@>y1}J^%QMQ^}B&"(׼4A]~jL.hm!m@O|b)>Nx< ;!Z+ jjT荮 2197mY7/@lSeGP)Bl}G=R6Ճc+$gDI'kff^nd.TО^t Ҟ^Ԏۮ+Ӗn͚(sc~'{jXV>Ú&,Qù[\,_q>\U`]57귚,eۆ>v?^ O#B j=(ع؎ 1NyF{<*OC/v(1: P]s v3=ӕ]~syLHZk[[psɠ>⽠X'1oG;ς }qΎKOK1=DyDXûWI~ $$ ~*ZFG\u.xMԧ4aět_?"L/<ןZ1I_,`;CA褧j?kl<;l A Hp`$D‚&\ŁFLX1$ő!+RJ-]SL5męSN=}TPEeQ"G#rԈæ1:U`SC"0iՑTMmZkE0WJc-i$سV {U*، 7WO"VW$ȦR82]k9ZhҥMFZjHnjᾎ?kTr|"Hχ+b[Rree6;qRE>4u|Wߊny]ywOJǟ_~@ؾR8#+,L2PkjB(t c:LK!4D2)<!S˭ vh6w!+PdI'2\+ B]+"-8\Jd;QJM <б=z ˴dB62$M.,3*h1jNSO?5'\@-/>@<HUo#(6$"^3`MU(J Y6%Y$k4*WֽC69-6]ue]Jp -\+Ķ\}$^z+ݳLH5 \=|ݝTLMJi _B]ЋDX=|ո͗!ijbfKn9eF[ЕgIRG$Ye_0iFUi fCJ1p3˵Ksv :&<.ҏ?AWYon8)=6y]t偽)fq/ ^R,!̪uz]vtj(K̊־!wbMhキ~{ѧո4Yء䉾vޯY\v'UFUV<"cK+Ϸco]=ȝk*;eH=/p؞6%x]*t^> `TBKrZ57KBֲpRi#i{ cپg;#&IeuD63Pܦ%*He'bR2]Ɋ`t Ѝoc&QF9HMKݏӿg} y`,:Ѐt"%!b$%DK-[Z,CbaktVJV25#7!0Wc1]!@Žx hLH֢&5L< d7iR0IUҜDgPƧ5ɕRB;zo BGI5qD"9 KbL rr bPMŠIL4cDLgHE:R2AΡz/B$(`h,fMD-@J'%ͅV:Ay=&8o`85q!iVՖqOZԤ'b6Uw;nSvԩ_*N(OF( C",Dm?ⴄ jd%BɵT dFgz0X7 asʹHK\+dו$l@p .ns;\(*-sw\]t\7խs].w}yK7y\/s;Y7^. Dy@\ _/6JaʁUWH|mUb[$3%fW@ Vae3{(Sm-^gb\aǏ3).+jW(~HWhT25fR@3\.׷=Ó"m6S&y U5,4a< Gi~g>6*E'7Y"UFhovS+KvREvug lTre%˩[՜OqXExgZS/aFyQJ=h tVVfb,'!k'Itg%Hj>3)eju Ӷu彟IHok2 mi+=0~/򓲓fW9.v0 *xj5Vuw,3wҒ3ȉc9KŪ"oaXWre>T!I˜Ph21W- px%3og ZIO#h0KuUjYBMs].KKR~Ģ{$ę :6(=SCLvWˌeASLy>Ow{Uf\%=5$q3zbkLl,Y;+ XG\Mae u-"? ^R6M_}Ou.6F-_efq8@䰏r,s8?'4ؠ2})8$ɘܐ0y<ɖ.+` 7`5 $ ڥ @;1=b7n7j8T7dc>K 3:Y@# B68A2>q$:2![ -);T9۫u[`> q?"Cz¤h@d;2|/zADZ5Z}Ü|"14Ks= L@C"rK)l sI '*t[}p!Q-nLX<À;CRd6I !2ZJ`|H) o*  + ;#K[@L PCw-#bO$sg*@#!"Ѣ!5`{T+TSP[<?Ĭlҫ7:m B 9A]ѾUEx ʤߠ +>ݴ4hS:#I9 lȶ¨^O7XD-eT>ŵR{r3;DGE̖5;?R QՌE,͏CBq4EHD ˜ .d&DN,Ւ0FVP{C9 Hwrݘ= !DRƪS&tٛ67/!`LQųRPu`{`G(˺?$W{Ăv9CC GYQLL!CrGODuו*"49?$?L*lʲxNKUAWfL(TߤOHpMK5d@ŠB$^VU:W[CLJZ`<ڳJay(̀T(pLO'L9P60K DK]Y8,63q֖̐CҮu5QgNoԨjިN%TtUL[րʪܘ,1247WQD@1WtAAD]X@]ϥP S_آs\]D2JWcU8 15Ү%riB,зUk!Y_D=5`;0<RL\RϝO7ܶRFIXpuk*nmz3NR͊>SN5} 0$4a lU` VTMO L팳t+X5yW.>ZyaFݎ6aX$2Q_ebpt ˿€1°"WeWfAMKvC5@-b$[Md3BU2Τ?.(fS7{\@Đd_#T9cLF)yA -4cBz^O-=%v/eQ Kdj1=9,g%g6jJ>ꯞB[H"Y~5Q#i6@iv#{뻮9쒮.j/6&./&ll"N2l/.*4N&V{hlw)궋9.֦҆ 0mp8PmPmmy ֮(nf m[wWn ۂm|n&foo45V9.<g&g܋-o o :o 1F=0Hy 홰i gгM  GqX"3 1Q Yr&O %p'gr>%,r~zF#q 2rG(?s(-W3r8GE ;G$/sHs9s3q'7s6t"5tAt_Q'u4't>^OX0ܖ+qN_/уK&@ g7^v%QphvIvv)mGw wo^nmxw{y|~}x}xi{xw~GW|/tN(qH///_'7y*y?y2xy_WlY/wXu6#Sdi$e0ţdy.w֨0 {.177۾CwI ϳ{/=;gǔO賧ٛ˽fӥVk Ŋiďd4c|]l E^f:YBأBbgy$P[җ}L}_)DԬJAZ1X*ԇqзp^ȯof.z婨A59RxdgVzUAI^IϑɄ!# Ahp $(ѡĈ^xč r$ɒ&OLr%˖._Œ)s&͚6o̩s'Ϟ> *thАD,GM.rCpLx!دǂeWl٪-bٵBuE|.5t0†#Nx1Ǝ# YR}/Ɯ9ҫc"]УmVheYxp Yogy%O.|8Ə#O&,+o~wDmW?1jfpnq=k]]fOA:ϯ?x$5`e-HQBK=Q{1B X$VzWUlxeH[F||.3X7(ԁ1CjFPqdA\!TW\%_A-$WT򘣘cYgrB RZ)]IUU6PYV ʼnQנ^Χ&BRRp_&ݡ ꧔W7՝J:ԓz69yNr)[:Zñ6i*Q٧[Fh.e,T[M&ۮ/ڛo[0s+E${m  hDӞ̆h۱r~l+lb𨧆h9j'bıC]8FU|q~pb7w5[)yh> fGݶocGM+E2-Ѓ9@rg#-\ve n=֠]0~pc曋 ]u-v*:9Փ.9muxoI԰;Vogs`?*w3w{{gD{;{S=?yN_tN3a*9*"J@iSRRqb(gKR\vJX6Ji%/{yd 0 Lb_Kf9ә\fMhbӘ$3IfmS'95Npvܦ6Ùd@.}i{8rc&4(A jP1 ](C#iU*5R(GQ@2` )IK)Td"җ4*iқ4JVS4@PJԣ5H]RzT4RU>[ Ĥ'eիbXjLsj]H `5Dˣ]s驋yՂت%l!d*q5{yM> yV*[+k6bw؏h3 ~ح8-{]@IA- V}-o4-Dak*0<zΜdX4 \jX]Yҥ]mo]A_lL]hDVHƂ;Y(EԈ*p=$n[ .~7[C^<%Dcҝ=o z%h5si-r]Z"߀KlbUFa\aךf4ǙOsyB4eJm{J^b'6y\|\GXfJ ,g+u[좱K$f2|rp^hW= J am.a Y#}Ihk$;TJ QvO!=KMg^5+5L[ [fJk֯ʓ*jLظ6}c:>SugC;d=-m2Pm9{-Yss-؎=7׽n&i6뽜z֤޷0Jwm#(lrkp|:a!^m@w;q+9Gn*O9W>/ar2wkNd9ϛK=:ыnz;commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/PoolingConnection.gif000066400000000000000000001104651472045345700312640ustar00rootroot00000000000000GIF89a{{{{{{{{{{)1)19ƽ,IH*\ȰÇ#JHŋ?`8EArQ$ɓ(S\ɲ˗0cʜqfÚqVis%Ϟ@ JѣH?4hӦPJJuժM^ݺ SX:,ٳf2]۷pʝ;wݫ/߿~+`~ F|p^ƐKLy28̹ϠW.pLqŤQ;Vmtש]Ӱo^Mk}fȓnС^bꪟk2qOyvm󖍛ovsCtz¹@Aᝧ 6hV{vXn槡"`8~8ۈX%0(M}]{$aiftZsaC!53yg;Y?y^2'I~ğ (ĠMhġ h Ģͨ0P G 2ғ41\XҍTLi)JEt-8JNoӞ; O ԡH%R{"/HTUԙ*Fԣr^ +Ti~ tUg˘ֲ:H%*iAcp"ocv_[!WE1*,*ty$ &B.]f"mDY6r}kiǵA]Lb7 Q۲t[xۏfձq{47R .r;NteuT ܮw'"^~ׯMyV\{"ߍw/ߎם}q/W-\+ $YiJT4<7E:KVF\#VCa{ iNb/$M݇>&1u"(n@1@G\bTKS2 {R1c2Piye27Y~]pe7+ nQBe癗UpBM3hʭGkP-JS8 7at+LG:рɚ<Ըi&MhBKԤE;G|\5AWyRN .u|؁hЙg7֨PtbAP϶#j2g*JZ$%;ۊQu] NN:͛P]t4(woi'݂rhS[n7)l31X)Otnl+K6.fp_>Ë{W-u>8k漩M# K݌mr9әrY}8]K27jX3;w4f$1ٺf=n^ -Iֆp\ gGlޭ]i6'~q|VbL> iK\y_wUx@+^26\gvX4hf?=5_-zG}$.Y*-Fcl&tsF4h#,w)wu&nGuQgu<,9guB0j cs&(.R|H0j'87x"1·$'y܆Wj!;3#r%)+)F_H/42?{P(xqyp7fzGRF&c*d05'\h3_XOz?$"}5#3'3P‰†)Fh)54lfCƇ~.S*ؗRR" c0G1,'2Wbl/-G-8* c3H1b(,]Ho8ȷq!c|UӋr ㌼3zbwkf#4Ęc3rh**"sC+ıVmE)&c.W~ٌhV1.)^s/s26Ɏz(2 r4I]'5h|}.hP3 y0k2,i1wl0N!#Hs=WX4ﲕ锖2/%18&"j9p)U,4͈*".Gǔ|Y+؍2BɆX2;X0:gWhҏihU V)V`S'r3!s?9)y}92lƹ+|+yYX35G%vgtaFmYhn)Rr;LwC5V4YA#W6'yFrJ'~vh=hxujZ40pii}2zRC'W!*8(Ht/:r١Iv4.Q3lzH<{&t5!wB!278br0?M`|ٗ|KNE@C;A!Y)Jg\ qm쉆I)D3k1=<;?KbS:?W& M˶<̴L=F/DȜL6$L{sQbscaD,6|2Cܬ&t3:jm S~Ϯ;? еXeL O D̬D5[ Q\ 21?DHI&^+ms4-^137fqg8 VQYn^f^.d=%ɘ߸+:0z'!82 |D>5WYE!'-u٣*qG$xhqJÚ$Y^/##~ZiT:\8NHŜM5HR}#gB0(OZÒv')NYkWV>b;t#? |"xU~A&Myi*àc7Oj Z*ҷ|:GMQ>~xY{4I w_i l͒(*YXCZX))չ]o_o+'{qyBY{jt'(Ak!ѯX;pX$.ʒ<$$XA .BC!JH1ċ)NǏC9$HpRʔ;T2͏)AءK-k\ȟjܘ"ӈ XX*p+Uj`>!$JhQ;ߺdVn̙lg]rRm‡=)wQ N\e̙5o欐ҧAv:1ʠ|]9tј]mD#.3vQ'nRɕ~e H;:έ\^sp C nyޮ^ Eݍ$|,<@TpA'c"",N҄CꧻVJo.@ϦT/.5DzK)Z4ᒚ +m ruq,ВC:m1M,I<\ҥ =<쥡|*P7 lpM6t&$MN YOrȃƛ(4<*!>S;/3 S9UӪ| R;Q=ݴ:LЇ]on REH'X%rѤ4HrE=%*?EEhW|Yh֬]:-Y YH['ĕk#3X03YYÖRIe4R5^PQPo4U!#1 +uY[IK`;`D%iCy5nO)IMw#-V-=ÅNuWU^JK-4w;b!ꛍuX9X]c Ыi֫3BvhM].Cꨩ^;pszr9jγRZe *mUr9uV]f5t]vlYٍr^d6~ 5v/6eQݭl кHOu"m~Env+{T0R#`U4` t.0` ^PT,Xjp M &p* GB^1SAP2` M7$"B<$.0 XB!QQ !gƐ (BaKx 0rc773tbȠ[eS$ zbT+KRBp,H fj -zawBjt*]y;T6r\'my˂|vۤV(JYe1-}|Q3G(Rj.D/@`1{ո k'ExA:szHl.t5@|֤g==rZVhkɬ.F6L H-F& 9K!EЄ3{zRzRQxhnmLm1ecCfhZ'ITA%"VEMNntCU Gԩbh2Oux x'~t mXcf RoN4\vi6K*̔eH&zmu=l_Jʯ՘9[ 2fvjG@&m)D)A忊f/OC--4(ĪY@Xb(?T2 t&[R 5hjм@mq{]9]J+RZ VVLkSW%fKN-۝Z9v&H`4]Tlz_ #d>i {aƺ\4tmV@_/ĥ  5Ǖ <1G |`% iv?)QrUKXp!_WLFlGHF\ŭSݰЫbyn󳊷i-xJvTq=#}niι5گ-xxߧyw7'Ǜwd-#s%9*ۆZg87\93nvC\ ;W?iO7*ֽ{ڤQK*G> ;@ZlekG:7l r ˟rD|e!_zʬǻ{ynҰ8 khc>aklk40C۲98L:3> ~}ZJ:?٩)/9 IZ;?ʛ7yɈPLB,8 ,"\2DB!<%K  )dT3 \wBQ¿p4k@9󚴱>l*z0V!@dډᐮ).A<@&QsxDЋʸYB5RҺw(!u)r NCZ̛jx!1sauB1 ,FE$H?:Fwb)H3C`EL4aDF;%ErĻ21C ~$ FQ:QDbz4Db X< Ձ"0bGyG-br% ު[읓Y.G{KFTH93>ڭKCD3#v[ yɄǀ;dKLDKEr;㓕lI5s0<)Ґ2Ԩ,H-q"j;4> 2 K!D,KˌɾLjT[.t ﻸ;|1LkM,αI\L$8[,4NLLIüdr ( ;ȿtMtOFG(4@3(TδL A3!<\=<2/3ЧF (<ۥJR@tb+3ɬ7eYF!bGAܩdKzt))QC=zX D)VxCJ ԛ4IbCH)ӗCV|U YEԳb[BTqe&*DKMkܫNz7Et*C땂ĚMRF~ 5UnUTYVzJrK D։E5, ˬ? y]ҥQ* #IB5kQu2BD؉3TK6w3^=TDDת{jLօEL,Z+d--Z}U Գ϶Y[҄*.0 IKl=SXΌH<cU>-=Bܲk; 9Ln^kmL+m[:ϛ`k!ƐcH!DK؏ΰK3USc۸qS[N`-93c6`J->D*}US;`=܌G YBmZ,;e_LCP4 ;aWMXl?7I%@X;J][ӏ(Pn f6eOibχU&=H9MCLKM|oppJpz?56a-mU$޽>q0άav݅vӜ V/? nbohT=aMNrGĀ Gq)g diF/9\v;zjA fE'|ci5r*ш=د.g(M0G;[kOf;9΢a>knE? r$y8?7sK:OҋR8=x5&UreyL KuL/:ODJ҈H@BaCJo3GXar."u\Uݦɒd4JR8KqZ]+g3:8{nwiy)DrŲHxLJڿ^vxXwj|x~x;0y&hYUl6je_tsw~ym/[b$Ğ"I"Voy}RӮ,zI:VZ{ ?93Dw_r_޿~\_V~+a+91n6ɇxxUg4Hz 럻FcG:=@dmDX E(4A%&\8!C/jĘ#ȇ+h*Wl%̘2g|&Nr'РB-j(R H~B J-(UbT=PUu E]UWJIo2(w.ݺzIRD/7~l0Ċ3n siSq=xq2ŧ EXVAgl(C[n \92/ۺ591 n8ʗѲ"C^}zE C,F,fԻ歾{&9A ? 8`JeRg]iuw1у=Xuҕjiх|xG[}"18# 6Xt|]Fxi#>j'Q GCZEҍ&߉yEG#Q-ާRXz%adcwI5QgEGBd V nQRVٞ}盘AqR*(bneeZZei}YwiXdsibEԖkz+وgVM֎YkmqUNڈ:%k\Sq݊;.F=JY ETWVDYUYgSWZK qK~$Z.K,ӮiҽeQnz6t^Dju0 } 赂|WF,;1=ChȞ Vl*b;/X!k*e*-lB5CI6Z>}6^ȝuYE1p O Z}̱[hH}ۅh\"]<א"-fq0ڕ[kWkPY\qZzUR4uAC[۾תnk_;"^)y"bךˑ;Zjzxs=s!.ka?>_>JiIui_" W!X=v;Q\Reesv"FNZw;ioE(=&u Lҫ6u,k]EnfФթ,ɤ2ȱKk*=,#AN.OLfxy޶ #ʌ;Y&D3xE:mguGSaSβ%]ɍL\pk>2bnݜF0"9Av]&4wbIliqr m88U0_S4PƚM2y-Ӽ(I'3člkb8C:ܗ5֩KlhL:[uι{+sLP_<jwL A:@{[ Dc "inb'iPj8!N齡BV\񌊺sӞaKJ$'yա2=p6U[7-سťڇPeV$yoG^+aOl--ȖF䩟Tõ>*[l>2> qE̍kq]IIY xFUJ}^|zI)^^e{iͯP]iPf< !ͼϡM 889EIP^!f!janV%b~av!r!aFqN8„u 1` .a##NbRuRM߀Gl'r)BޭJ:+ @*-m@\K" hDXL@h2*->L@ĄX0^"d0Zlc5j@2(c2^# ;*#4#K1f@Kd@d\X.b7<@d@5f@:@f7^d:=o">$ dAD:&#$";*c9@;&Kbt:cf^X8!b_J$_채D .c}$G6fF%3L nhg&p`hNbiUhj&%@"$Ŧl!mj:`nnQo g@Ibqf܅Se6'kK#Et"rQ0gnf'mmZxy'g)r='w٧|B#}&{:\~'| Ra'b%~^'6M@'rN&VIA܆bV_"yH(.j٦it(}.-.bZwFbrhmvWz)I%τfϓ*a1it "J) K nDi.ahr ziXEZVi) ^⚮)sipѩ䩞6 g.娚!&jbHڡD%Qjb~Ki?Մ_,כĥIc.#Ѓکª ݪisg+X&ZNV+^f+6a&n++k"k*R` p+מeކF@ ڏ,˨>F[uLf,bj,zRmɾu&= ɖ,ʢQu :jAݫT]I\G{ʇŬ1m\i*j"$>-lX`,W]z T]Y!7٫2Qi+Je`Sdtlu_ux4`vmGWQ-r-m4M4XtI f٭ؕR*&F(狕js mnFPt1SPԥ,V䭮tkbf/n.Zﷆj}o/>':@O vگ]1E02[!,lݲJv[0{p'D8&].,ų'O߸ A^iE =ٸ唻d^,^@~&GՒ lp1Ĺ 1IҚ\~\UA-D4uE\@-5pq6MI Ґ1//ZCTܘ ˩'Ei(QEp*լfEdm F"{m (`#JB@2 r<,& d$[n`ɪ!Mh +U`k(w$GEq=TؑUf|hN$OG\!1d QO`r6_&1 6vNUIxlB4Apkb+ p('̬n^tu !d%WDss1Ne2 R״W3*ML *gVR5uR*0 QkHR495 qTW ,nd,QCvI'ΟlܯWz{J5,y;K[r q6}co9߾__#VJSպ3: /z?y3yve?#:u=pb3,O/`"a 2\Hp`D"NaC3>E;. qeJ+YtfL$@l9SΝ>9O< =J4SF9)Ђ9ZJVP@bV`blhrf\sֵ{o^ 4~ \a/8lxp!#ƚ+,cЛ辎IclseziמէB A-W@f=kTlG~t$}hŋ ucpm7}z5CT~|IGS@ث(9S :#j9꧵pB +ϻޠ)!Kp8DeƖ41$u IE ‘?rlJkr%C>FN'R=< IBEx< J"S1 M$9H8“@ :b7d?ֵ͕/u޹4s7}X[Vz"Zn]ޘeqs.g&R$Y\'Nc&^~ByhCK;yT;o5ǒyÚ7q[&H['zqE/]2{8Gm)ZFSq\fRC}/{W1E:NDȐ}/Lg>Qvr[?IZ0(1N ;8ͅ/RLEGg3<*PvW(Yx{pdz+phJHӉ֓3=GQyE%FTuI#Ҵ^ޕ (a j2(ZBӍ6K:[)[".ugv"l:~ mʹ Br;VHzU=>,5 P`՜/!j8FILr=.q@r?[dFul&mc*[^.E @]deIaO!Z8 Qֱ- VSh3pC)CPd:"2UŽLJoR>~/H!+TѼت,l~a~J`/2-Rya4׀zU\Jme~Ao\'.17.,FaL#K^sgA%?̫R@ m[mw3A). Tp h)mWL6s&4TgزHW֯ui=kѴ$xr|L PKye]dj^';'=;=Oo&RQ5Q9M;y?Rh?$J2ލw.̺+7L-=ShF˩ʫy݇8d*CG#R:-zqg? ȗ̔ico_ԷW d956Pz:jӲ^IVW^SG[|SYβS:'Io,REL/X-frx0›>O -"d È*CBڂF̿h, + Z̎ NfZ|.-d:^-QEr*lشl|npƂi՚PNrHOc2(d $p+Zƌ ob'.'pBvjO*E*ːJ' exD|vC7Hb-#}ZZP r21PpnG *Z:/(ZP i1GbP*n#8($- L БvΣlqTjR%,MccQ A qeZM$('v愖 K ˪hpҤ эh\p kZ*S#mi"icR|oF qϯl8'li42$#iPId &Q4O %K/ 7l&&K/"'dҢN-qLd.A$E$$)g$K 0Ⱥ O<ZvaH,q $#LJoXު*yMQk̫1 )9DŦ*w+mf3IOE%2ݑYXDP㼇j̫q..sI["۱HHm-)&Oz[ nzKFS/,x,r  oO"(DK^k\,[DB6@̕VM^5E)dA0-A[3?+(pMjEhĒmzl#1xi2?>E De[1 C% B6[~"н<4Rs2H"Lb~r,-qy3L:}+m.$pTjKl/O&` R-E #S&O+h C(R!Mp"&1ԱrRhLw<@;2ҺYZZNGLU50[@ + :6d7.C20S\\ղ<| 1D[,uvo?ԓ?$S[k&_c3,մn9cX 8Վ 1x-lEu]Ms tO8YQ`{*8p[{8f9orSBsʌbUkO.ԁl0\%h3b̬ [P?~cKUjsImU250"}[3 lj%)iFϕcZɵnN8cΦ*xeo?Z\ĝR<,';,HOeL7yr3c-®@=7Pɗ9bTJLQ]ֈ QkgINlx1gGX*e?"5̭,4Y@{YhUwTQEd6L4w}/oMgdhDz%s ļժoF w=5P}#炭qnS 4T7F[LĨPVΜ:h'v}Upi=>.$:e|4A_8+xc f٣~]f9Q;4~euDv_쉁s~&ޖ ],u&#p> ?<5O} hމ.aѹ4_&^>>S3/1nׄL[w ĖvC8AdcIkSq[c%i)tEC $(PB.XÉVHŃ+\@"ȑ$K<2ʕ,[| 3L 0`Ĝ<b64(Ģ":,P4Ġt1VAfƯ_A<6-ɚ!)YG"UnԂD5:0.şq\;56͜;{.aۅPƅARt=EKviC6=4N857--܍!r?&t܎rz/^+ x2Õ~ۿ?f͌kv8u%BBڅR%H@ !'Y{ZHadї_)[! E"A&J"C`,fib1(zѦXr2HdeqaJ.YhE 4R)8u"]]7QdWy^j`{e {EL&Y8M5RbUCTV'C':נ AiChpYMgƗ搗i_[R()SmP 9GSHhyT&i礫Fui1&Ji-NT{؝Fcvh|뤺ѯdM'wɖ(QccTbΩXꭷoY{Fhm(ʪӌ.e, c8u䈄-{V-E^Jp&iTu.c;oݽ*2g^"cr@\'7I0uL؝oז ,Cj1 tGͶLj_7mcC.*#/lsl0{t+ClLS鯖%ꃂgQTYVT؄+.$ږx㪳F"gnj7ޑ (ō :mTFYC"^鉧KNFXRb%)UvvHu}Uc&Os| DN_)jS #玫~ ۸J1[hy+F5myV$ #eW$ݿȗ88 ,Zw=KB1[0"+w0|$yT}&ܠ$'gJl(~i>C"6īYKRm/XUOC G4!ZQ$ x<cF,G@$9*eB8S^\Y:k!-ݘ̍YIB[)АU^ r:)rm#!R9pgJ+6` 5jjsټ7mbS$9yMtӜTg9Nqsf=yun$̥?}m㻉w|%!al q?T4ьhgPyrkBc'ty'sCH &S}ϙe(s!r9O]*Y]Ok*Sf4R[DoZShiG9հ}tLm"MJb69?dLO^\$|݈Wꡝ `ĞE AlkMn&[W_{*$8-j_QT&]ϊ 'V-kڎjgm/|hҺhH2wdlYE(ݖvjh-}WgnqQ^5UtE-!&/Akrvv+&YKg}!94,-iuڠ&OVlS0)̋_{ fGn g JWʍjt#1m]9M*Z2?zmqo6(K((T9AJ\JQVވ|Qjpf~=y( $]Zȕ>o72h \2{8͊nt} a@{8ARҸL3;юMO:," @䉦TI,d0E\:9FuHz`r~SSo+kԪk"qZL6q*lf{2l?D_b*Pi8-u߽!n77h2c@)Wj!zZn}BTɏj [S>׸>=^ʆT$O@H+cR+gKDA~I;9#g^й%~9|ș <nᎦ}aP^vtzRP?so5Y]kz YފDFYR%OqRG;Ev8lo$Y=3:;*sa9=r fokOJ/}Evy(cqsA^:gKV{N]e%.q9'wp ?g cCeoABC?n_}fMʹs/x] 6?_O?sodQFBUn3wf7G_%r[ynxfk {~'UX~zBBv~V%|&gp'(胭/51e#f+6kz:(0?x<(8%a/Yb1u5`]RÄ8#xTZhXcAw'?`f w xzaՇkHeI<&exe%G8zce )7g BmWI"hhhx(hiT<9A(ZfHQ(VVjlY& 4%?o6wWU؋&$TXOqQU!}B'Rhb$86yq*1'^)_1UXW><qD%oĈ]]zȇjAhE^{5%sh4&v{㸐xT)msra0[+uǎFՌ 9xz&Q:y'C'c5d.:p5i U$vtvYȓ4=Y2YG{Cu?[NPS wai;wO5$>&%&A1n78AUKVC9F8;@y3Pf .&8$yFBml9({4 Hm5!Qu"PM%PPD%Vp|yԚwtOB$I92PA(xחm%v}ULGynd uw7ȌIJYoWɉQ[2c6v!Û+YEz?Z^jU._= Jm##s'q7U-VsY07+Gi%hس">swe,E(0ɝck/&8ꓤ4syR5L_Ţy]ցZ6KڏL*lY|=C.2#,E6+RU]j#ֆKF8qS5`$#5C!-P^vX'LL| U{r`@nO韋ajpgHM)aJG)p"8}nI$bAcoy^zGvdeZVk3{؄Ids R'3j}ɪ<zᙢy{zg)g iVWIH fW.TI(Jذ;EK#+%K'+0e-/1 3 ;.6tĔRij=yA+CDAc(9 ]BM+O;1=NKPkUKI)ZՄN`Mb[d 0j{lNhM޴w۶xy˷{d[XEJ{cGk\k$ XU\+a~۸Sud9IeK}VZ[{C]$Ak2+飹5k˻bz!;ݖbQkЫQ{B֫F{K;$D+;e»'$Լ)+fOTB[2˿$$,& ,Lt(,›A”X( /X2LyzÍÈ;|7\.S6%S,iqYdORLSlUOX|[]_TMO2M6 ^DkmN\f̦gs&!S#sgJR+\gОa>=̆OL5fd5u' EDwmyaR-~'\THKWo'DAѹ"09}@};EZ"]cOFm̉i/=|W7'EiG5ZZrc[[o7#Z2 =R1}E3|ƒ1v3UzR%cCm9\'}}j:Aוk")Z}b 4&'4N]L}~x lʗ}7A I PV5}D|6PAAeۿ|ύ4\߁F4 ˽)?[-۶* JdFtN͉dsr&Sms{7&h >9ЁRBCW4mʅENk >"NtkNT/N+"6^(޶^M E% EilA[]A.t%ȟ<墜U>mVXsP!ƙL>lg6{ *[ʢ1SĴL1>`$̞%Px!f<”&eA$u9SDB@Np/sy+lkiW ei*WR]"ΈɝNQ !u4YDTՊ|V`}^:ƹrx9Jiv,V>ܞ P6g2ad-W *btQ>*1\$&*J@?r+ .jؒr'8aYؘacEV,r';YqM4MPEa.Ђ#L,1EH,ddtl?g#WS:;vbE8Mq >f/L?#V[ibHn^Cv]--55x9Cu]"k@ `>pTQFc\u5#bk_':BS݌wrfAșs&^ B?]H/V;J\HB @[RTSCh;LW/ɱ;;Dy5\^3(rxb^p'3 $% ȇta:V<Vо!B`ELG%8r,oʹ'kDUD]FҫG7p"{Jy-uwBj&-ő'f"g{2 &pi"M!n 8"ky Q,giMi',hI󠓭 >Kf8֐‰E1O[J+C l@ Øόq֊62^5$gIe7i'E-Q'|eĕ-ı ,ʶْjx޹v7mnNb]p1BqyCcq+u EdqW2!9u=u;'z -l lu5rM]N;ܰ8UvO? 9Aҩ}nu>~%:"4S: ɬӾyw8 ,hPj1s6I ?{A7fˇbUC}>,ZM_͜Xpvl>(k0pxup u nՔ{%؍Mfn)Ҳ }H-@_R%'s=x3  Ӵe)` ÓmsI5bf3I؝Y "[r"Y=i(a;q yIaLK9 txづz$l¬V!%21UAe"0Ž(&3M A ҠL*RR!-B ;,c$X#'8cɨl&o) ɑ<ʭ",ߢA={9?kɫ|ќTCfr3̠';sw)0v;t4dR:'/J`J|T|KSERaL咧ӽ8Ø$zKt*e1!; mRFF>iX!E'ϫ"/eiKCD! @)7t ,JT .+4,GRXRX+CC~ôIKLG,!x5(HL5 TҞN CEUҔPakE_? 't[E'QO9by-3z eikmY64l.)LX)L}<& `;)Ngz]xXY d̡$L 7*MxH\8Hcz1V{X=[KJE-A%Y+bE)(&?gp=$c5?<* X Jhg!S:s^+N%N |FIn 1Mt[Γyߚ] -[ [ [POLCFݴ[M' ޾=#\W$Uv1_kз۫xh͌3$A[C9;>vK934/["fk ߆QP2Jڡ]S?}lO 1nkDE6U2u<%9w' A*9=?_.: ъTJ^lU`TNGi%6Q$)q&[O9df\ fM)#}*ZSb|U&[QP;V[X|c۴H{X]TLT:l:yңmni˭=kcQΘL8c֞oF|׾>^dikg-Ҭw;KoSm~pXh6f=;vIYŔ^2.>N*"?0t!8מ񍍛ZؤMhmĬ\*uqwXtf׭h,rh.[=N[BI\]G=Kiwl PUVsyF<(\8d^t k60\~*3u5\GlXH*tj-]#;ݒ! >/yy3 ]M@o,q$AXuV;Qf& cPG˰$EgweK]u j-^87D`_He'#'#gvc]D ^l phο2fN[qœ#Kl^k/da6a|1YY%=KC lcVI9 pOx☄¢=$nqH,bW,fnqcf 2eRgGz!-cdyRHt恍M,ʒ{^TQt d-?g\F VCD^ˊcS=MBa[ Dpbz/MFRafF0@ĔT4&,HÉ):4q/.Qd$NLr%˖._Œ)s&͚6o̩s'Ϟ> *t( @I6XƐE^=x1ԋ =hMhQ+ث%RaŒ=b=lƨur؀(߾~,x0†6htӭrt1ƁMr\tnfW2a5ءk]я7 {x6ڶoέ{QOF\w5C[Vd[$r6؜];Ft!F sFޭ~=[rhaЍOUj&krH%dBsi# |v}M^w@!eUC1՟}PMXB PhHW\-d#dA)e[r٥_U}QgCMg@1ETՙל9Yj|akp9%dS*8)Rrr%RZdD +p`pPAEE<&jHV~Z;V詍-j@@NA'^ IR[m|!$@B Exh䮹Z(qS}j@66oB۪.kY|:pUP2ܰ%C:u@eTSr' ,Ć|gRkw x\̹QEE C]Kbl2 nolPCFkL[a4_?}cX7f-ls=||4ߢʬy3k[,;kx{#X6{AA裋(1I1fdn:UR~瑔fQ蜩eGYgq QGEI޼&Xgf6͹>9cg8ݸUP:+Zç7?_ C,&!0; g`iLX]d\$ D|5(" KhB(;x%h')O;DCgi’#hCJ10pJ\"Wқ ?Vu\(o=J] :93G$Xt<.agF7±y bĸIdz izVv\Y&F\#_nKla#it1cH2?Z(F̠jJ{#*qrzSPƘ7n2´VbRx[wV/gL֝iNrKFufLq*Sv/ԌU]A#;a3zP(IlM.\鲿*$;۲1٬mgAG5Z2"'G;")"er 2w3 MSh.sB]xJG0]caX)7)bV΂F=ԧ[uP+O(ڌBc,t koiΈUwqL+Z3[L5 )3 g `<gN8*ss X[+ij z-io",QTD"d9 6Q Ro|Hb*c6 Q.NUxv_eRS&{~M .J+M].{ۋbkZngg۝Ezr~ ð Q]D4ң KozlRtF. bk<>t}r1 ?Ç ~h2l62ւ;~g>qLaaKE{+f`#gxw8tyg-E{ѳ+QDS}#Z/E>Df4ϴ`C>8:.s>mBy5ʟqo~ח/  u}4_8DZQQ-\P y\I elUB`^U =SNT>WTş ] Hԏ[kyb[ɹ ۽}Gmj`δ-! >A񔒡SXA Իd\V]A .Iʽa#> _c %VDS a5h%}Ʉ:*%YrYb%Y:Y%ZJ%\¥Z%Z~e[e^eV%Ye\ΥYV(@\ ^eUvT.ecGs HN]dZQ;I$.<6G%Xc_hVN n46kpAކ6bfpܢmZKqr}rR*M^EER uş5Pwwwguygo y2Hzd8bg|O yj6}k'w#z'~Jv6Jiڄ2~ .'al$څfmJ]Ŧc8@hҩ %^xݮ0Yב !(Zڰ\}hL T(AB#D.A _P[QUXCiiW$A1JRɕH,N5Iϼ; Z߄!V˙Py)߬oQMmR\) N]W NA\N  .ԲRRVV-|yb>ҝu*fhzJEӁm4m">q-U5fmJO>'m♈m-li-fu|#u!tFY.VamᢦTB[r\.Yz[fz]@e%nTna.*ꎮ.bn ono{p@Ok@;commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/PoolingDataSource.gif000066400000000000000000001325041472045345700312150ustar00rootroot00000000000000GIF89aJ{{{{{{{{{{)1)19ƽƽ,J5H*\ȰÇ#JHŋ3jȱǏ)<(bɊ'Gn N4-aVݞ_j7dbrvw$`;; [ГhlTWbKЅُ{ փIiؖ=&lr-Y+ gVwۄnxgdvaE/xa5ׂI!xw7wߨ-4{Ô_^;ؒ~^@K.SU`_U[e1Z+|wV'=χVo~O)>L#%qk@Z瑒>!q6: Ā 7A0'piGRj(LR\IyaTH a"@tZQ"a¥h~'s!6X+$}̢(/MQ I"($ HW~ , 3p y@XB=cLEȅ$^<$'"0#$LH#  g|Fğ@DsbMh@ N:}HD·ZtgC/}f!cGG:ϐrr$M:MPTT0%K2әAfR:5FhUIܨZ̨ *AL*@zAթ-bXJRz`X:ְfMkY׊Vp}\J׸ի> Oj׾u_VVL2=j)aDχ6+d5.(fER&h} y Y4j5P֖U2qCV-P) i אTr{ѹ[.s"1VKםnTEȻm x8JU bzǧ{q _׷5_| o U88(}ܥt sūGav9p9_k) DrTlo-.sëC#L8*} cИDr$;Pf dJ򓧬(];Ir{ [/>r N(B1EISj^)!62hmiIZ`s yolC$ItγGHB˩345mZ#QGP N!t`Mn$MzjZ= 0t83 YMQo_@a=Fcͦ,6(+=Svoc#$ hVY;!QukHjN[}Y^wʿ}c//"&(Gtr,G3~ygso3rO5x'yS"6hWy]6t>cp|¡x$ d~v@RzG'!z!(ph'gvCv50#h1:wg{w;c~}wywsʷ77+I5X$A}w"7!07|Ey}'5^G0˲&G"GGPݗ/)7,Q3q2!!o7*Q4HtJ}W1iv-&wwt1w! z&3{`E{(:r! lwg,؇xS'3!'$w|(GTGa҉1h0u#G"07lr&_86wja0芡9hW9*܂*n"h6g#wv4W! {RÈ&F3$'ׅ.0A(?+.}x,vh)r)2)'S0B,.&Y)2EE|1 c.,+ )#sEI.=G)ג3)*")r'ɓ,y+/Y/M]Iy8P"$# 38.R0$c0WIyx Ȁs/Tax"XB2҇ )/yi0pI"~0)0/ؒ.#%aw~ҖՊ:ّ.+^y)+;S.-+KH%t`?aar2fyY/RP眗y#D"+1|342&C,y⎷_ٙY){9.Ilih0i R:)0˩bȂtl[5X.*X0ZV_U#) S+-;)D.)zxňDhؗI')$òvYYx0Y2d&u"ﳑ|h2삠򙔞ɕɥ2}x!əe2)/*zA|Fy[#ɹZɣ(3*x9)2!37H7"Ӌuo*HV22Mr,w}hui:By}SxmJ4V8IR|x%؍'⪂QHu6K䚄z&zߧ:4ΚOI7.&2zmwP| (pi'v߷g4~'2J|wwv!(CJu&ȂCt3 zCk5HG|T (7y @#+*۵t*qXcZ|kZU2Os+zu;GgS;jr"Cqj"{{P+Ȱ#f';p{ m4 @R3.{-_$9sVCy1p*aTۮOEwk#F?;yU+"c#zxˈWH#ys2 i &캱14nI""&K˳҈!?h{UǷ;v(s2{;q;?Cs 80oVdj6?\6AX!'5ށRqL(l; ,=Z/JXh@D/M_nVe  }8Xѯxҗ&$9 ](',}+0P1=64=(9MwӲ7}>Z CG jUE-A;NhO=bMղRXH^m8Ff]h}jljUx6JntM== ~"ˤ .b~1٢ǜ5}]c,5I" k*&RZ`+3.] ,by!+Q0v~2 )= ᒸSʭIWyr}<*Zڤد!a2;;܉Q2z+6{~" (K.;2nq4Y*eBb| B+x.~h  2]jѐ.y)ءB$/~lןB5痗g{.ة)ʥo!?j媬,񨉢[/"vY"nоUDGn,(+~١,J "n o!Z!1JOQhx"X+Zߣ.8yAHiLz#o[9//Cqe/8!A⽎^2Cɒb2?/>'_I(6/oY3,\ׅ y魻鳑 ZwNZ9#M4=k~uN#D~C>.`} (Ïz;gHl[^`<:o .`H ,XpC /L@bŇjp"ċ =6P)UdK1eΤYM9uOAT(ɣ *Ո$ĉ)bU;qԄ K+T%Ӫ]`M o5XYHw~taե  :`Yx"=I5ogE,vr޼ٲZ{ yQD36qӦy4]CddUUSHWĔ#dK{oDԒC^?kSLzê6Ko+@` cP Sp:˰B@B40?:z.D1Fsq`GH$DH%T',R"%T'2/I/lr++S7<-t=VkDOM)62rC-tJ(ѤS'LD'rJ)մGlM3HSUuUV[ű So#ޮ(Zעյ\mV6ayk Y PhV\LmD] C-m]}ֹW`OWw^zɾc ?~K̯WfĴ]VЗ TA^E..@A*u% ^{[vekVckF}=Tѯ*8XXo 5\n@hh6 }yݘV{m*!{onQjif`;s )q/HmC}+on[WVS ;tg=> Iဥ]o jΗsuwvz '{WV&u^W?Q~PQ*~M(Q@̇>iy@^mh}`w} 0@P#l]cцB.=E^IQdaaDeIw"4 m/" PaZӐa#J'#;xE1!H@u$-aĦE b$cGD,V@`dHEDHd7Ck e""BТk}1FXhk ,2B +",CI,/"0?iZGhFst&I#hBN"ad/M,6Cp1-,9G1Ή (0P H[uAN$Hm4"8Jt̊< 97 mXv +Ukw +S"o{knqov51L@8FX ,WԲŋ1CM,U^NE!Kf]V"N6g<WMK{.SbPBj9!mTt63Rorq͟F_kЇ&yuv]'p趲 I+Sq//wf@biq DRyb/fn)[j2>9٭H w_tsrId>bB A 3XU{b33t DVdDFF̧mn6A0ilgqre H,LL"ѳ/tͰz.KFc3v2gZMB;|^[ gf@,.侢$hs]gU!Q8(PokhlTg?$ٻ?rc#Hs )!Z"{ɢ,"KΘU¤~u;UFIWl཈®vǣvԹ:)5s|t]&Fy[(F?-[O=^˕ 5ͬF@xuh xk]Jc>- ɍ;QxߗD;jbKBT"ofi z 1N}z&0=sd}OmYq{wӹv|lٿ>##x}JZh?;پ>kOڪc/br1?:Kʖ#>jQ mJt1ü)qC C =q63@".Ȧˬ";4) 6z:H5?y\0SB(3Bs*R Bwy0=t0ش=>Dz#D:2DgAD=QDdĔ@A|?Ҏ#R)3v9,sR>IA# п /qp[%ѹ!7A‘DIq)%cݓ,H lJ ѬLHJKKLJL9B0:,8 8(0,T$ǍթR𵚸7(*:sϛ)59$a-~uG \-Bi}J4c4+a.(!3;%| rMUSv 9 C$ cɯSu\8[czĤ™V# '5L*r0J- jJ1!c-ċvw C#kj 0;JdSq#Ph=X壔*3) IZ,Z *z8츳f $ \Y؆tLJ,RԪ#0@@ҲۡԪږł4*z+"kUvB%A X-ŸK ۖ/}Cj[m[i]e }(mq2ڦ\mBM[YW 50:/ $ ۮuICF`jfbz(iCaLi: ~~}h6B h^h~hn"hk@UZ-eSh12gt6~ ɲᏚ?VvV(izNiImiϨFYE-͗Hay gnםi9;>HxIjHq^CK.knެ۫>0Jf:k6kl–=k0SՖ>Fm581׾m0ymܶmY&jVkn.Bx&IR}RF%!lnvrn=nRn븎nb oSsn6C# -|o]oQ(%Wlp n~pgV n<.BY)q n/ ?rq4^qWT$0;ipr*r/_n L?"//\r#-h:q3oQs7s^8_=%!+_s<Cc@tD>qNtIF[IrL8nMup0M'u [CNguZoWoRuZo[uG_?vJa_ldv> i;eis n?bul'wu&5:fnjkuzs҉ +djahHQS[^>Yq,ctz2Gh 1˜0j+1挛"۱)U\ϵmq^3Ԟ<3cղU[ ( S\KI#s/ڝ9LURk}=Uivt֧q]{*fNCD+B=P{o蟛.sjv;'yqc5t짖_ky f}:;x넻S2Ƌ~E)ܿWtd ,f!k1Pox?zޤE2 dP+:\.:u@|Ȏ2$y< AP B nP 3YS%h^}տm-} 9^ RXF̠Ax%2&d(ŅRsaC0Z `Z)"Uj:l5FS<XB"fNA#~"E,^ESX/k^yFpeբ>K'̘0 X*Y)R P%.iK\R+c`ڲ %+o9K\S2cTf+j2e4Mm&SReky;?I(P)0O'ҡG4ʒFD՘| T| ^ C# 8 u&dyS'HmeU2c$ yi/|"KcnLSݪ2Ґbm$ڮE7{ ,_1ۈ.M`ћP֭s9(x "Q7.k]WEvC_] 3W C5L›ޖO7%dqnS-nn._TRviL#O"vH15q[dR1̫Žmplb1 986,./]4LiY͓ V,_]IuÖ<ٹܘ.2ɱ^1ż#|gTtƍ'XSUlMI BeB,kY%!ڟTCIh*ҒuEdIr׾͒TոY}u_6vs&J:ϔ,5g%d}2tS>1#d5U%Gu8NҀfP"v(\"'J.2pks=V6tS1k$W )zR32}&ze "Z&Ed Dqs=@93'lI=)JI QH&|ϔ" ww"<٥ LACMݻAɶW22E1ͣڕvpы:|_:%Z%9A(oyH}9ingy/_w>_|7ѿ>Oz?zcaTr` O =RoY[9;NHm"("*CYAcnS`#[H=6Eb |I5pܛ6"9"(PXR cE%vN28M"JDeٸq]M\ZJ%$ @Խu{Q"T-KfSjgUL  ` Nfٌjf$Xq|%f@zb2&= r^bJ-Ǣ^SY[3Gf#dLHB>R| &y&ma MgmDŰDn~Lb^^pjJ !FD 'q~qnisP`Y ,hhJ4v.eP%L\f{&4Ň&l[*ˉ]\%迍aXs\e-&^\"3ZDF<ze` }ݮ0@Sqe` ?&%<[܅(b)['}xz U&(mnnfnI#PJfjhJIa]TCP"i6RVB\vdxՍi)[ZBʛ'$dfwyPTg>%SA Yg.M\b\)F*J[~`ƚM^tL,ĆkՈI:\ %۵$af*UIgTA"gʩaOF>XEUqFx֤UiGWFV-TtQ#elG"JfL`Pe Պ `YDך" $,[|l!66)ZTH%x \sD,Ňg9]Q>ף쨶(6c[In Uf vDY#6j-S-Y-2R9]9.E9Ů8)Rnn,ͮ/’2ͮ2*-՘Ȇ#mLe>"hJdFe)WHaZ&Jru$$DU #]]:Wv,^| "beof*:ʇ 0%"%K'vJ}bA2}%g*W"]^PfnVR-$T6%U$%PE#R^" ?HʰsY"`HV(eʟpJEpJYjƂI]МoY+oqu%>d]nȇz)"}1aQorVfRiKqѾW$"OU""KM{qXJډmj*Kpu&g&'kG2g#X83@c̋I~,R9rs Gx&&j22wı|фתbȧ#o!XnSUw6V4~w 4Fۅb1q;eʀ$fğ5(a,,&1<{N83KsPL_,J"Ųf6@QF-.ִ,tvҽKTkNxp]}LFRtLyeD+@B?i+.زnh+l^$>z UwG-cR {骟֛z-*aNJ` fI ߴT*IwJ5!;RڄzE_ޡ=jfF|&N s Vr VdiIK[Ș؞)o):%q-dw3!RkrE[r!36!!u^0sds8!zZG'.cM7Z^ŭ~,ҶDm+G,sꎃMu h 8?i$ 5?K#epejYX7# jޖEuMh6CAb{ Ʌ`$H pp FZߓu!(5aND1˶Uyun*89՝9Z`I.U砓o2,x[8A':LWDkX jpI_8㣭|ȣH ?FN5, 5M e㭵S# 0)jI5S tmGx.<H$e8^8J(Ab?* z;U+ Ѣ̪6|0N@M*2.Wz" -K 3 T;! G NRO< >4Uʠ\OO*@/nYjB(%JMA 1b"YpC[oq27[H/5d@"U $:>n!~c q(<].J=!La>g" j9j k:s(F):Q"OG pq taQ8E+D t>*TVAXC-D>K[OdJR+ ΃2k4y8kSQޓhT73} GDdp9ReE%y"pe(I9JSTe*YJWe,[PfN@%h9 *4sQ!KVA!hѤ <^7zǨ@+*JshcrLJg%D,p_cgvq;%ONK0l':GTU(AdMV"FuVy'X'2ٓNsc5ϧiVk42'TeT}hEUI8:m;#]"qQ5I/.gN%],XjVUv_kX:VYutֽ3b{?Em4W5rpb[ M`RDtb`+\9ҽtaAe8e>ldHsQd*Zɀ07!N&0Zhӝ!ŸխMK\uld3uka+^j$)GhW A*9 .;iJxi !օKT- N}L(O?42˄Y-K6Ef͝ LPr 1k -{PZ-5 &JEƤ!'(;0, U󒗰,4 ^iLF($0P#L%;yK\_fF>c?OJg-7(e Kx 6QJ+<9\%~n' e8X jHN !n?sS$2ҕ S4UԋRvƖ׻a$ = V:-QI,`XeE~~L4߶Fe! ef}a~`\Z097V!tɀi;aFWK5@4K9 FmuOEsTiEXM[nlWkJJ ߼7!1ԙN i$'^ZpfLu7ma}hmZrx󛞯;o~ rw,tot*]x4>IB=Ga[$HX`wJƗI=WG`Ŀ^vQQY}Xv7O)8]͠HsHsyq푩b*aDݹjSjy!zJ}BDQ(E \wl?+Z3JKBK R/ +쯰-ZIg,E\jk&Of@(f+`'DЎtK0|G.Ψ'fp6$'~e="$K9ʜ pv*PpBC(=`#TE>ϙKV.N/*Rd>,!R(?|Pȑm&ԠkBՎ GFip"`e꫽^epX/6,`oȌ.` 00&-'qCq#"f摒݌$#tn.$ч8(&]Pz '!I+?+1DT,2{kL-2} f)i ,yB,'7LL#eRjEs5n  -X 1%g, HE ' 9 Iܾ I̘BԂ JodQ;HoT.;p0w0-1]GS(S43# R $D "J 3ȸ%5p6r'xC\s@*8*L)} .gHĂt@["5C ofv4Ǹ09'i4 %>uB!d OOuxG"Ou4G)Gy7>+DZ/"[x+m%-T_sn4dj*bMunB4CQtXLHѬ XUXXuXCrQmQiG>UPu&ZuZuY=&,KL/mo0#,"$Q1Ε!NB6pXLLCHhaF2ɬVgL1k_6yb"v+N)*60VbG$'U[udOE[uZG,'pPCӂ蕺uf2lv8:mIhTx6^;-L/yH;FZ1@"^Ǵ`yj5LN[?k!lu'PveVeIVZmu[6.\\f\ev, .G:dN1Xט B"tjVsCNQtR}}~-,ubAQ=w|XyghUTGe"w߼@?u"h M/O:|vIdli@ɖ\bXl?ɅmXk{sx8Xiq>GI;I؈]X'{Ck -,蜣S4=I0*/G '$gp|)r7RC,biKcu9+Ax( 7'`x#7"?c.lDAD|} 8*(tΟ@|3]58ɊDSmeR0tC7:gM{a,i_fc@cO~X; ޹X2ak9G퐯RԄd_s؅-nYLVfcp0{"dj,1$ `UuODuMEH%y_>-6c'y+ %*כ-ZhdPt?)Θzbx؈Xڪ:Zs_&&eLGض 7RŖ8gBZ:zAɮؑ[m#(rspn.ʂ*RY&9d\;X5Nc^J3lzh&kSl!;EWIzة۸ ;ۇ) jp;_H|,u;QkVwuMuYpuTUTBBy5*p돓ۚ_ZrNfILL]r_ze#+ #O ;|#u HK) jkѺǰ-$F/z"|u=!'7# )<%(m",(Uyd>FM٥/i['vcIH)c/X(~Q^oi8/P9ˈًkѨ\CGfdQe8zD[:;|H? aj;.EцϷ ڄWwz|̝q=>\g n?&=Tn yr_1dןR"/\& ʆe]/ [+5-7f25_>ɝsPqoˇryK|tf-Wm5)l A쪳LBDL:.dֽB /jEjAS dr/2m磊0[rkO󳝹gOE6Z!œ\G1{e -M1/xQ3Z#Å 7 NxdXWF4+5ўLV>M=3Rxr-֝OXQ4L,2,s&{ N"6U|g3чy jg]6@&lv4Q%x e$<;ev-5k+48ʘCԂqR>n6!(Ks_Z@j˝ؾuj4ȄqLXTOsCsd[1'it*VҴS  PB 2Ā„ ' 4! #B4HB/BDᅆ &t@̙4kڼ3Ν<{eB*TXH0dR!_J`xA—z$8iӖBNP ˭-"ңP\vm+`̟tsR7^ Ć Ԯ=>Mp*D5Ni\hU½L6[vm˹{K`gj [tZCߵn˂\mڒiso[o[4XCmG+E棐%̹[im_-t_e9UA5z!yaIn!%F'D mdYI6Չp ߖ]e<-[SOqb:e)ѐ6Vȅۈ8J2eD@1V%A-Y^%wAP~Pǡ\v+2ݒUDTEAHY} 'juݺio:v'he zm51ғF]`^Ync)FU:1x!oO񿻕;%ug),L2\d\K1 9WVqu9Va.޷_G˹.b+ɕaqIuZ$c\1h!]2},6u]a=`^qtt1zTϿvU8.Ký 82tlyGߦtᶁ%t)Fx -b&Qg!I$Ua6<2g̍s&ìK)D]aXb@ThNkj<%0J4 d=^sp#$ QP#$Dv}&f͒I2Lfe I.%?'1cLOBPMӬ(9}hp8QxVt}g2:QiN?1NwTi$׌@Mf5N-]-AL:T䖫Su(v, زB(V)JE~z6F?- 'J&2τJ^ve:jILn毙p2mr\ .s * ܽ.r~ tv]r^{W5/qĬ쥁 +X$)3eCXyoqUg8q\N]k%in^%hQ%E ];NJ3IUƃ㧲JOddhSY\ڮd\\Yozf9t|:yճ =YЁst/<|>_;f6,4P'hENȷfS˸ƪnlF>K3)3t6vJ%6%tlYgzvcRlcX٨kuJMe*)Z3f%NZVb@֔ZnwOb±T{v5 X|"ӇKvI{1w$4Hl^/zǘ4x=JP6sJ411ۖەn݌$崥j-e뙊[} zU hP"m%J%HMe}Ã;CP|>% fGBδi4 e*!e=9g=ڗۤ](^y[RcM\1gmGohl/jҀ*"YmYws}>ẸykfU~2:hs~6~h G %T>-&K$kUxTGOD%f1FVPjf(-r.Xd)M2%(ϑiwI EX)KsG1(,"~5{ȂMW{ThCzc !,8(}UV;#|sPa{7 L1m^qtsxhf"B2J,_S4&HBx3Eh`s|HT/vcrh>R9|wU3r2 eX*j!b7n1Sx{_ܕ{Vm)Q'$2h[W&yS.Twj5zՆ0ĈHvX>=HTFWҌ̈'6Cz2iTI-f_i(9aHDMQ[8.ab;V5S#s3Czv}zӏ MHx>1 ATI+Ewg5T.Wނ0rا$v1{X')yK:ِ/V![&VhRz'X(\LؔgYkPF|Y#&W [V'ظ>irߓ'Gn YLA\(|yI.tea plHфI{jI9jFAb08 8Z)yėQPIHY4ʼnEhlyrDI4pDmyF"I8FcT(EfY%$iQ(ա:_Vr*7"G&%aC8YYicȟ݂eSC/)Hup1A6DsY9|ء|8m%avKVK#уT%h5ᅠs*cH?Z~RmG)T:\M͹N9BWCܩU:>x< [o1&=4d, Cn_zk@ҎFOJ2\-j)t `xqGqSp֐3rWki;f"c|k"לzꄖꍩ#4SsKd7ɁwQY'C5R'8'#Kt#iةry364ȌWd$p灏:N# wUիjhoe텮窮ʮڮ:jnb;{iDhVR0,w:D1n PB^G8aƱ;amIjƺIAI9?Z2 )$V'~^W,ȀqxoI(F'ddմbOJ%YSҶ?uWƢsnօMZD/NF/zx(rfo$%[w{${DvKwrZs+**&/ 61KA5dOh ~iQn8"CXzvq* KI"AI&`sPܡ?ZEFC՚#$sHPX(sD;,irV%?i'l~hS8|o+zH4ʪFUmįXr`72Nh_72 ~$ƓDmњaR9˕rdI6D8S !jPaA[x%KX3:Dϋ) ƪÐzr|}LSaXqD,.=̫OH뤬v;s5t*9̓iYȿkdfl\y{klRͯ¬Druc t2l**I|TيLzu9p;(CGn˧9ĵ\5A;y&g"}0>|ˀRTWiǰNKbХ:Ã)7%Eټ[X֪.{h-~uZ;^;ʂD^笉Y_9.M:I>=: ~ UnN|]>஦ׁ/)>l͏k8NǽM|!ó @v#ml{@JfaT=!.o("q+󧓱!tl㉜`ΑKN7"2*$Dš"|5ND>ziZd #VLccO`B WMRB[ͭ/쾷+ux3в^LP31̌DZz5>-u"z%5|KFR>1LGRնG-SbqS'Eyqz*U9Trte,ayӄR 𓖦4iJr:C ׸&Hi6U"hUQ2fFKN{k^K} 'OdNd"A g˞&YgG(i}ͶEf>,is lVԢCv]hHA:R'5iJ€ks (ZDR*M,Гbd6'hS{,,wVSt6)5"u-/N͌8n_*:ΰ*n/R%MU֖ fOЅB\$0JkZM x R˄A=g[RPԪureTGK !^).5=}ݤ1>1_ׂ%XVY@ HE|ruC W"L.@9;5(Mx_!~%Yc4E\1ZKNjmo;[ ˨w%^iS/,zlJeMڪhd+ [2\ 9LaJkLҮ<\<*nW綘 y9sLJRR/|c(FzC~/-` RAWV] yyNP>V7jE0Kļ L3PhɆ Z1f͌2k+ 軓]W)U[%hE)[q4E,f Ny:̍k["c -ǂ.o8Xs-`՞UzlfW6 2X]uLx!ml1~ 6ވ.J֓nSkڌx\Zg)|=G6#5'pϚ% n*#:uy .,Z ud`WFl+^JH<-ǸQHos[5sظ4j-NA3۽0_EL4ͱ7wèTv+Y5Br5oVm[* D_Guiw,R}rˉMrFkU +{\+DX:dGo3T^$oIi!uMgT2Y9l(3yfx)82B Rè礦+gP7nXk>l{Gyr`%綵s_}iVQ-;Ϊ1ʋÐQ Ucs>>Yr3mq".EJp%c$4@?뛞Q>&뀤s"`Z[k:x75Z2zZ>?""@"' l(#&7{Z&sT #- ?(,;m%-+a '-*CS /1P ?X'; G 8ۺCi1 ); ,÷>D )41@)7,Ÿ$HAj#ŲDB (X< O/s*B:$aҩ'ˆ$wѓ%+3;G;3OErn$1t,r!4|T457\Øbw BF'0q 5!B4iPQst{YA2+@pS?1PR;} r\4ٛ^xaP 1A-6u{C]T 5uFLROF$ %;~kS?u#F>&+SdL1uTA;SX]LH嫧1 [F#GFFS4?9.rt<4 Sq<yp:U-B8a"Z+?,}=m>*1u%Bb"J<8)rEd3;NpZ0Q`UTlV1(+B%BiQwW<sBDY?CiX<3wdB8U*zp%y JyBT(n}TWM6>۟6LUXTe7yٕ8x=\&6Y#6g۝- G=t~ނVK@%̖X)Agjj 1Zhu/C(_tK)x6K ylkgXSorUָl-ÜEɝtYAqZXE4PM~Ii)z~XXMnT+_D$q%ǺU6E-Y?3UUdYؗ <ٙcSoV'J,aJ+a(ͧ=^oq q[F?7PR 5W{Cػ[hs:[oDMOC~d$m<b1-'6XU:G _` [RKWlPnύ)*QN\X1+L$ߣ>\87OhI&3gә/q5t;狳k2`rtIV@QSV̷b519WZu rLG܍[LIl= ̨2Zݝvxv>n%-?ʤ4ԭnqQs;^$9sJМwNc[8{y9ZиrQimtEIDI_v̒P nsW_։`Lp̄R%>#UJL3! bM_O+G`Glvf|@qۚ&%UGX e}%bv3Q"❶qkE^wx<њ lO6+Vzic0ݓ׵ng^7I:nԈ7їUg>}ƽ\ TqXQ݋\K`&vōe GBnu@  aA ,(QÇ!JbD fxQ&OLr%˖._L`H N@h8/JS'; JΦ&G Lk:̓$c +v,ٲfϢ-ɀBIܶVnI pOKܻzM{†Y*8`1t^`PWE2Ic֚58PaQ1ŚVVfpx6퓄MT E.~H:2 18EP\x!yJYQi~-~?JAqUYGw[udh=eSw;9nUUO`VmMXT %PxVn]y֜d6sap"E3j\d! H#$zOBzG|E{Q:ɀuCNa?Tr Y)\$lυ4k4 U ~+ZWAs8PEUjCiऐ&iG<*&j䗅*w||VW*nx Y਑XAԟ,*oz2(e8܀(碿={-*l+2dD27A;M/8֋nqCdc2"c\/zSLIvq5E l9]A#ېk&YByoDvrU`Paȕ#v(o [BV=JTK35%,(h:I̴s7ZwL7zV PšEu\JV,GDIa8\eU}Ai|KXf‹n]TP“63N~ӐM\X @ F?tVʏ]g;]c)~ xo~$t  urY΃D=[Ffk]AH-yIrwY RD\! [($bZHr Т2qmWKůs+kX%!FGb|_gRDuK$/Q0!:ƅfsp'D*5x#@%Q " iH.TL gHIHrwC<&8űH0Ov+׿+%Z9CQ劊O#@yv:3itAZ"FD!-1k҆`4Sn&J\*CEOm;<'sB<95IS8=M[y:FSe7֦(H.7[lJ5'&'6;Z7ΦME_$.5] =_TD)y+:s"<(RlV$9޸ 4q`i$Q_d G#`FAaҳh5Z[E.:ҪZkD'̓wTQ UKfەi#G&!tRѤq\1W;3K26uCص.] #"/}2\1Zfd '`vbfd46;95*M; )wY;aQg{ 3-(29Ѭ*֢7ik m1NJps >ZBY#ZN+<îFj PPaHưT 0Ia _5)pN _cX=qw\s.^ՋV:1UL:M(5-A5gVAi%qqSMRXՂʣp4gOa0'2ra7lf=(?d In@3;O40ˊԥ>­w[tS8#mu—bъ(?zY;riV_-~+PPJW4{%+͚^f]j"^Yh3SEl~o's#=G&NedZMN\Pz-XDnZriP! tR>"kY<.G9gndo \' 5ij[C|QO'&@bݡWɰd1j+F/0CG٢Sy.fm}I4WC*syl~? ఠJ$*NơE$5̱&P4"|?$v.˪ @\Cv,qǘ Qc&;l8I|ITKȾj˵@L''ѹ|meOUMŰ29w^#u)4'e,̯?%2`ܼU%E\@ *橑Ŗ >qp`㩍SȔy9LTT@ahPfhDd@ 8W}dHKaa M ` IEL.ڔՍ9KOyRďe^d8ԥἈ<@8!90 :TN4Q@JA! )H`n!I0a{^Onȗ"&Tyɉo]ٚ٣}e nEVHKuXA<" awf{#yrZ#{{VeJɼ%  Sة3UէQpJڠDJ<c BhWXl' J)[xbCy}N#ihr^苺 eYjhG& , g\2YS"pDq*nqom9VK~oĨJ^[ h݅DfhYBD܆{1j5 <D3R%eQ-IIyPQ=  jAeƺJnl(}*w +sJ۞/eŊg|,d~ѝ)MV:hܮ>I"mSt 秎m%,"F^孌9))!Vbg ZaMvrtƒ"-Ʋaeք` =thhibA~kKqP*TоTкn%eb ̐oI*r6i.yՈNT N5d*]XE xv$F-/BC᪮M%Z)SPj,vz.dd iʛ(P$/9[خ\L&\ v9z/Jd+l9)ݓ&WyiodEHDNVʂYDcIalnTl5 -FL Mռͪ>pԑCҲg/ S5SyB4ZI8Z-J)WsH,톙i hj(n[3Q"zفY*~QtBuSyR$O/Q_1е#8ݡzDv5KPROv6gkR~bE?\L,* M$ } Niht3&yyEk"Z/hv*6&QKw>COE%$1T5hydS lA܏ˀ 7!ܧF gٶɬ햶H V`uY3vn%5eXAe#$Dx |_8|\VkmajӸ߭-B% M([]09ҵSVHϐk;[CR({jݒ zaXb9i+ewJi1c#D-9ʖyo)-CXuYA ^(<]i2N 09m牞mqK%`:q\iidžf橛zbw!/^ (.y S*[6kFo: Ω*z {_fU֩eEY߮^ <uaAɋ#g9b1r$!\"TuREa\*[hlE މ?uﶩ01S;{V~\ksο>zuױg~ޙHkZ]C}?z㇙-O7ko+o h@, .#{hݐNjz)(ːÚ\ [0<RJJ;n Py d :h5l-1,! ՛JK507ے+ -J( MN9q|3ChToɨ$  Дjīj* 1TM94{$;?O7d| h> n+VU*uYԢlNt:#ɤS-dI]`J5aԝhubWޣNZiL%H@`TQ'܈ *(tZhnCa o'dM sSrjT-L㌐@e㜳Yf}LM@+S.9K!3=)ymY>sƠ9:]Iw Qw m^CO7] s b cMvJrv7ﯽ"页1ixחU3<{\WM}#-K:ޜXǼ/B "}CcQWlC$pCML^+ "=cU1Uc%΃Q^>7{T#0o>#ZEE44-rByf;("``Caaٶ 'x"m^;\Uz3%dP{ PH%XjS$*T`;ے.<qg޳%JA|S3rNjx74\J5"06ۢiy"LoK (6m~%5G䈢Pq0Ϊh-l+J6yV8*]JyI z.$K UN^T FzRa/ҞWSL3*YW:a;iqg8u =8[z3el`)D%2_<یh#Q*w1T"Y!5Uy0ՙd@N@6TPɳ15nK[Sx5N6S:NEDI%'w(d[ Je$kV*׽}2FBR9(doQ(s'a~\~eTDBTM}SbBOdڙ*#.|fCIanr %14BG) mOlCxHeԃ7mrD% ~8PtPx)Xm[ )TOg6IɠZ̠XhK̥| O4K^64lj(#F m玈vp"Pj5F[~&L름„I5P<ЩM1R؆ .ࢰbjH΂g)\ sYNѽO\- AM q򩺶e+"~АC nvLmEFl(ƆۃL o3ZqyH{*ZR[XmdJh/>$$hd[V1F_ڭ*+̄[ +Rm0+-@c$=‘eP q#*+,ކ,̵IXz"F^JFfŸ:K0P!C! 8b1 eCJ&/)FЅ#5 *g܈f2*m++OoP)*|*r"Q5@r.O*-Pd+~@蛐E031s111!S1.)~|/"a r/O"]r)")5-5X4U5Qs5]S6n*6k.A337S޾ۓ>S>?S?3??@3@S@@:tt3/{<}s8ooI4==4ItJsLsMדJ3M4K JLϓHO-p6cr%1C}:QqE5S5uA{{H-9 .dHR!n-*h:7VmU\dp*rGVl$`|t%"3V?/h6lu ;C6Eo#ˏFŠ5`vfeh(VNQc+o&D<)v,.h7&GFx+FT305p=sӒDK Nh6`%kmv.f:tyw;ep)R0F|k+W .xf388ww7{{xC Cd7jPnի\ڀ0vṮlEƴL{~xQ%w `WFX1n%^uG`7%,@4@ [U{34 '9&kT/낧30('4Du]%dQ퀣K|zRWݠm*~1A5Bza$d 'ImdҌQ [k;8xQ+xjcXUK7}^NE۸FB2BA x}lYp+ fk6b9CƬ]zotx)9$dBkzx'PQ& ͑#َ8+lǐڮMN (yF\0D鼸So]9+Uf(kjvf0 c)xf2\ ŃV2yT&f`G|K4GBgD7ΜY/s0"/܌e'%Z8%("m4ya#l>Vx|Dh(DWDړ"tR`-,X8%D TCY!Nhu7y[ sOx `qT'LL5X(7:ku+5\gQie+[kuB;T-Q[<ȨU 'cNX(M~ڬ!T2:Iq ;xرE&F¯1;)ou: mCOM䉹q~]ke{9eh)X^`‚ͨ}\ َ1,6V< 91%z7Cy.:iӻrjj k &{`uS%A|E׎RUɓ&rII/ځY ̣˘|]5,o88*XmEex˓:TV~B5 hǛ5!%;UU8X|? ?5K*COȚ\;gf$mݩ%qhh VT"Ee!xގyeDiH9"F%dywGMTYғ~RdZe#Υ@p)tYؒY2$rwY~gIUǚ.hm)ibԀf馜9wIzBPxeשlRHjR 䬭t뮼اqw#l'kNvf5U"=k~JlTAYݴ.Fork钢IߑWlRZWl1|TXVĐsjG#.W,oT^,4׼U6WDZh,t7n66G-TdFxѡIefJ3̴NËAUTZHf&kez-/j܈'#ߠUG&&P"BcN6e^$騧/!9Wm\1:zvI! jw'7tgwk"%Aj"sץ/c/{q{;_; I̵3 |{@ߩt'!; Ȣ8֌'ygp W™[c Q53wXߝp"l8Č,1WD*YP JCRK!E5 SɎu9y,%әbSm:~rÚ^gH.vnU4w4*sU<-񑐌*144˚,iэHpÓr?eA_dW1e.U^fydh,MeLR I\>t/I]$I,M)uԥ{HJPCL:&MY b;`4'")·q h%QUc2:x,g3mIGZqIt@TXAQ$}1>OF 0)4u;2x2:zK'Q2D2MR-!\F Y.B+%e3Բ7;jBRvg<&Oai+kKԳ1:Urk,rIL.acf? ?tM ./heO3j'9GsiPIP,3lypK#XK<ak/RYLjˋ2DEJPB3[?+Ymny>D]{ŇW]jơyN'W=P1NQ60ʧ]ex#p8b%N}~gL HXޒNWB,AC1|Lms:AcbNY_Fҗ\䗄g{eZO)en—?뤦`TjxB^RʐW">ᬒ֊艗&*Cq mXƅސHwl'댴Xi+:(" -&Mj{ޞREgCRHkF*\^AeT[_'IՙC9uV0`//]Dc:ۻݻ흟yq߮7J0O3.GckM{\~g6p@i6Վ@ 4du qZ̯q{K6q"d&xE~Sg^Ђ_6 -uc,?C G2O7y|x):6"CZ$#+wP}:}D#Jщ~(/t%DB6E"P&fuR (hJWҖi%(#R4WO@PJԡsAќ=.0rtҡZXVd"GJ֬egeiPDY*׺hGQu)4'v-l]t(,yF;:M,b7[Xfh;f[ ԜU74 RRz6-au{ִm;RhĤ 06psXR׶nt{]rװݮoA|u5պ u;_>o>32W騮t_e!%j0woKaҖxpqt#4^ iҨs@q7\c˨ [ hpрF4|[9X-{9~q̍bԦ(Pzj`xpLg0v3u mTݠmm3ֳF3ю`hL6PtښիF!MQF` 's#=KMY:Ǔs\Ou-lG X00A Gx6Mj[ؾ6 Xl&(! f iP7p̠F0lη#A F8AÓ!伛z@C2@4A'N[G d2xB[S@uCOW&X  _М8lcvЇNM̠Pԣtko EMZ 2@׮Nva,a rTG5Axϻ!}F3t,qrz #л'O[{5qk!9Φp 3ֻ|9ARmiM9 D>O|sGpXX4-zYdQ3~_[3h~P봃`۱O ߯n H##( 8xh Ȁ Ȁ @ X@7z"aG& .؂01Ȃ2X4x /h(x3 2=ͧ ?#V Gy 3Q8HRȃVS @p t0as{, \XmxnorXqxpT(g JpPGpcx0hzxH舍 p 'xQ~ȇp-Ä@,Xhxp($0 + PȀ8^،00 6|g 30G 0Ȍ꘎Hx(Pڐ#R' FP h؎ YYI` F -&;G ` I*+9,.) 3)^x`x{3 rsH5YْFGIKi( E sȔJZٕNIٕ`%ܐM_nm9'` A(ؗt @ 0p`|'׀z3r`Xȕp>ȀGF0 Ǔ S ɖ)ٖ)c v1V"r1! G虴)y(ƠJuP[aHr.@Yܙ)P0؝i0-6@ )Ypb0g@7*ʠ *J A R0 ' :02 3j4z61;J( (H1r1Qz\=ʣ5SjUzZ\zHCj75cS%(]JlnX s*[Jw UIa0㸗uymʨxڨ5 'rEy j:J:W%N **Z*:b(H6*jj* RQCp͈ Ś:z*ڮ z`DJAR*AEqh K;[+ bjTE%'Aĺ ˰䪮; {#{ q/s$F X۳ )+ &+[G5P(y`HK?kA*;X ⠪/[{D{]T+[Y  F0 0 )*8K ' 0 S` `ȷ+蹅+k;k۹QkzB33$'%Y$(ۺ뻩˺ۻǻ{p S PK:J%'Nk۽˽⻽;; }wW'q!<lxۿ˿[Py4Ij l| _knK L"||$<#|ȫiy (xPH8 `G` Ee0? ť+ŰJSU\ Sj1H[$ ȗZ\ Vos,Ǭ{t C|z3 c! jJxl6|Ō\p|ȃ;ɒLXɘ|ɡǎƳ {^7f8BUx<ɑ 7L˚\T\˚<~ CUJĢ̬sZ< wiO|͹lɭ<x5 ހ\τ)󜌿@ (1p1CsNIz >>@ H m^ =x1,#=? \80e\%3 O-? %݌ſ 8! Ȑ?H5 MYM0=MlsDQ B]8b-ǧz}ߠ]=kI-e ֈ W^hҔ =zmt-|j3=$ف а상m_RM*m0hїݠX-RE҃1ʪ˄)h w ش dm LҶҹ`Ϲpˋ ޼ p1:&]݀ ݪk ݹPw.؄) M]7l R nÝ[ܳl|HA͆QZ _} @w  850 50c(88MKƸ Ѕ.=п)׷YfnӺ-m=V}˗/&ְ ɂ-A,_] +ѽ-!-=ˬC';S%y=Ӛ=ްHє}}݄9ߌMd_xߺc `=M5L +N XςI; Ep\{~]^S~˛\=_ZoY͠M _z}r~ h %yK<ܾ"ðȺN_ӭ=l >kΠX݌H~3"+~Y>~Ȥ)k =Q=1e^=)= UH?}Y 87n[}Fx *MWYހ;ˇ _ " C O/֥ z=M}` ~{v`  }`xM'_M'1n t/ J {xPGԾPϠ@#M0@Ҫ@` xЌnx?0 g' 7_AvD<~E8QtыHo.yABTB{JqDPtJM䰱i&wɳ%/<@Imjo kHRvOI jňʕmX~ *A&\0}MWCto]R݊g"GP(Iy%i*&9'ayu_'Ho9vDw/!ujUsGDivGRw O#9&3-yʫҶ-igmt*"d:JnYrCrE$fC12y9nK2cnUJAVYK!PRBjB(;\0.q)n(4yPYPoX I6hCB)L+ʡʢ`Di q_9K(g ɛ( gzŗ.Fv9Sۧ "blM -DWaz衤PǓ[1)ozBYe<0EVZ$T*S%Ur]U6iĒH~3Eu^z5x_֊kD)%JDPqh7Z6Y$KzPY\WV)oPCJIP֍.UL\PVPK.'z x]Qd#-'KE]TYVy,aDU@$P dMJ] >U6Qa74z8qoJ!$d <@Ha*$_"VutŹ+^[iMMa*s܄a,o,)rFVpWrj&/M~)UP9&%@#Mte]AdCz6HQAAi${"m1*D|S;6]Hѣ'mE)I>& pۈ*bX) V sMKE6GUx H#<1P@ V& AMqU<‘m844MNZ֢diH/3 qYX ! u )U0[Bk1cD%px!u0a-j *AgabJ]&rnDtZH7P =}BՇRE1\0$5G`Ȅ> Obp& Oa|Y= ;tF>3Q1K!& ;G"> 7Dy p <0Cz8X`|JEAZC ub}VP'ЉOԡwjN *N$ZAW 0O'ˉA5Cq VЁw' C`⺣PD80A jtEx^<ꗐƷu+cJ?cJEC" >;zTbD>]QXp" Q~ `pN+qK# q\)Pk{W E(P8猉_J#1 7kZp%P]I"`.* V7<RH2qH:n0'Z~"+z CPCr9Z'P1]8Re6qE+E&L$Be!aR 7'qzXpH5x3V@MN?ȃpX\C|2D 0 `9{AÐؑB@FKA\q(?z8L>2JbT@CjXrHEz\b"Sq@qۃ44Q-LCX7pL8xB59A %Sx 8 O X  x"Vx ;M|O@!bMxB(pJ?˕P$yD0˧P1>X3D[oQHXX*)QRB)BT˸7<>xoJE~*.WEObEX44}%C!~JXQ:8DPMK#M.\ <:WP\iG|ȫ@9jF)**SJ% [\)H{ȕzzx zJ Yf(k;rh:ڙ9 H%û0TNC%kҶ\)6bFyV*T\HL2CCP{@I;"xJZTAq ڥHJECh/kp:X^CA@o -4xFoZхw"?zHLЊ&8 Pë#P&[hh/(ԕ⺊n_IM`:]ITE@9ދ](7Hw&z@7@PKȸJDqEzz.OW@Hx7(+L09zPI~Zd#*IФO(KhB ʬQSbJ 8#]PQFL@*MNDB*oP}z/Kx,ۄ?Xgɕbu2H@ʄQcjIxa:TDL + Z;QKFnl\-oppS$lD$ͱ2LʞMppBO0DLHIOVIVhc'Ѣs*! ]yuM@ȑFT+T? z+qW8{z(qڅ"H;Q3ox\ɕ E̮qL]@0Xe7X5۫Ѫ:t?HxCJx7P7:NSB7:Z8+LJ#;8%X钎WbqoPW?'`cD/Ӵ:HOD 5?"[LH]7H:U74x?OA 5X7qVS;>>(|aARCAoXC 5H7O`@<rb 2Umz%7 ED%[C25;PXE:H3ݰO8Hp1޼Op;7X8,FWC C ZleAgU@@T7:F@?*pq -덃W?dC<ɼl a2@ZT8֢VPz߅W$^ =Fp =ݼ3D<<7`q-6MEp΄[@QGÅp CL@<4يVݻØr*]@Y\8SBO@ m-qr8Jٕ29qh#h) iSc YJyhjJ+Ji;꧞jqȕj%)V͕ˀ;u(e;>a.)S;1z zkr1Jijaj<@afn&yzVlF-P`T@hUnmkmkk6۞lkmlE즔kNnגl-ڦ1j% aXi">4 IVܮ1qp arNjľkzClan;6?V6JjovzY6ԺX/>H/\ɾt-jAum7>njVnqGTGn.Oa,JmU2j~[ko.l-7i}NG~snVlB/=ɕJʝ\Wɔ8h{iRʻx&nc`CBI(GOV_uGwXGuYwuYuT_u]'9Y(CBT@kUbD#RSu]v;tSu^vXu_]umou\uVvl7ʊ"R^qf%qAo?u=tjgv`wi/jwUuGv^wlu/wYGsxCu[ -!dW&oArY`W_v~_yS`oyvW u~xSgykvS~7} DcyuYx_nWYuu;pSu7x/_/m'78nyuCOx~O{o{u/Z{G}Ggs( 8~Ƀkި T[pν8{pxrVUKtQFF+]ʥ\)2ɥow~\*j)6Q0`od'7ξMߥ1~~%yoygP=].P/qGǏ߿2rXqF!D-BeDiL:s洙sC(G(=-ɐLL[J6V1bh,ڴjײUcȱ43yR+U }׊+zy 757ޖ&w5^Db 4Ԅ~KtiiT iؠķ["BrlwڴDm?S`ԙ 8Mi:tا/O>y2 ˃jxV'VѣnG7!VTZt HUgCe Re7B zN<Ҕ//P *@0@:c|/%"NndZ`?PD .] U(B#<߄ Sbd~ LfeĦiih2%j֕Q{YTzhG]ġߔ} RSCKb % Vh~Yihb*ɦbBLm_C@?JrDFǡ|vexߤWWW„A9["_ʳˬ߈ت꥚sAmKb=5ڇW /$3liDK=}C%AFuIu9fiK;eB1cM?]ګ@ֆ;z9-_r&=4LǪZ-G)a0S]g(fu8_eDiXihMm>-&ͦQC.ulda*4ĂQ 0=*K a܂rK atgAh\eTSғKVUkDc[G+IvL?f| { &C v%Q6]Cq_o\dWA{%3 @W?xp@O$0xV4(4" 5L&x2' 7 )lMúF4Q0 c 84_~/akgK9ұ2A^B[N"I|ȶ3%+` 'u|?H!0JǨY._l jO*1<2E#% >pV0+QKJs+.wبy&[!0>9,d;,uw1 '$|'~(E:eńZɞװ]UJMi,}'2gd.XVHN1d\(F ]]ML^)7RaS- P \xb* o&T|B!D4@+CD',Nlh+4O7z֣>%"* IDP塊UX9TbJqH:#(^ΙQ4T}:z%b6%,q%ĒT=`O' Ak@4jv(IhmkMb6BW!,& [aBN>Bl8.ޕ/f:4Xc.WhHV /x!B$".}K:Dׄ$ ?y}pGe)Q_TL+S<| ^R#N{_)Kc!t/A^]DP Y fOwzB]XoVKn2dVd>þ+NZRbsYquݓe%&_Ȅdd0orQKtFE&C4 !ĺOzxq% 4!B/`.дҥy[ݳ^:u geO/H44;=$ ٽTZ8ޱwݸqvޫd⺫[UH߳pc{on=no_=+FHOz9rAgXY&c1Ԁ WxhpC&!9(԰F,* &7i,L,e7݄]⨛` J!kbhv),$BA($<$B(&0*B<8• JJ}]a ^^ꥠ Ϟ 4A5u  m^  .amWJ"?Cy \.YBT[}T.]WA>胓`q;50|aCL!!b!,,Β$U" bz,87ChIՌy97̀Ҷ4+ ,F"-%R$^x/.!-"&]1H. 4?4CP^I!&b!""8~V/B<¥$0b75⟥6Q?)FGD Ly&|7,B' $PL(C"x&B='9 $=(D#dBxB#+xT%P#T7X%l L̓Gj8'4B8'MSAЃ m$T>0`,="6jYz#0F8f#,};Yc F+_΢8ElK);t48 jqc]cZe0֗<cyct0T_-5ڣ n,^^+ןIe .fl##U6"9W\V:^X8}IهK,+ B=!++A87!A+'@'"8B=!A+L$+ `$,G=@.A#A,$LUa'!+Bj+(؃ҩ7pԇN;J? Iuh&F++B\/jgu>^'V뀎gi=ܶ/:DC7;4vC4(=bBbwYN9(r >f:^;p F|DBBԄR=EٖĘC2#)zD? \8F<nN(hүί#QJ289?- /qMRQW84@9TVC5W a 4 09-L9Ж۰ p FW@ -gE^:3Xp7p p Kqp p    q_q O ?1Cp-hC?qnin@q |00pqq p4hq /p=D c 3r 0#';2=C5 @jD~oG52gr 1{0-#r. _qSMC Wq"Sq&0K1522 FF걡\.U^k=*xȎ (䈊@s䈏=<ϳ4,tC3܈DHC0lԋbYy3l1=81g1#;3-s(!Jr5`G3S3.csu(CqP C1/59F/WsQO!4Wq$c2QO4 _q!tW5tWtVǵ52p&6\C9 C34ZC` v`va#b71C3\585XeV`5 C5\3fy ,(Ca3a'kvk6l/fS6bO0 5 cl6ll#pw3 13@1LA4 19EXC?uKk_Gvp7x7p/xǶfy`wvx{|[0@37(biN1xc{{w99nz7f9+8sxw0@4>>q4Hy_899|wmcz0k;8z'zyyk;G7@ ̀ A  ::A:: z @Ar)'y6+_;go{ Ad;(8~g [7bDA Ѐ A   3;o<zA :w-<8A@<+ɓ<ʧ:>?ЫT߳z~s{ʋA< TS> D?C;~>C駃C;>C>>8(^C>~:C9~;D*,}:4p??Ӿ췃nk~[?~;\W6h_s{?.~:g? w_B~qktIlE'rqFE1]G4MƓ%cvIdΒ=l_Ą+Hsjʚ(yuM&5_tai@IYMݪGnmhD0?G 6|qFKخH3q(|Ye̺Q&*z}#]/]*ΔI̺\l._a[fj߻:ߒYiҽs>oFW~Y3xߚTڸy K~ιT_ˉi-o@RI|Z}ᇝ,,jk*6Ͽv0B -c1.'xg=21DŽrL l"'xZ}:h gg}H\23R2{R2*M6LN3lP>a~<+bGcGJ4ēI-S #(RL uKKj@!j,ʯ)%:sST]MWj!b d}:Myǟw"D0(U& 2̐38ՐrŗxTLx̕6y\na 8ذN_^ˎw7Ìs+"S1}DfM|#[]VٓKNQ٧JDO0qu栙MyIMnVe.jI&bǁݚ(VCP7,[n V)1&H-Vѡnom,[Ʊ\́/r-'nۨc=s!qH}[}p;_=Y\e,nwDQ xIG\3˥˲s{W{s/9:l>accl~޻oG@1hHRCxF1N1:LjmKV]75Qok W(Z8h@ɩG kHB.Q 4hq`6Cv&am;CgQ`CEzla44l6v(^T㖒@6Xc1;z#xh}/<=>L|#=Ғ *UGuC=0J[qm Ǡ,)FEoKu8G!P^At EZBq1ql mә& r1\<ɣ4 b zS\P<7Pک`?OVJN΃d"QHϑ _H roVRFϑx\D8|< Qumo)@y:ԞΒG ) zJQBQ׹XwMMQjTmT- 'pLX͖38 3yRҚH*nô?N&毆 MJهֻ>N[_wRy= dt'`#[ڲV ٞ Di0Uv H[8JS%}L SrUnrӐ8n:t}iWxoml-OVҟ$vETMLz ޷, ky@wy~U [Q%!`wWps*BZ,cl)ah*1t,vn gcלaI 1 t;--%diY,ans.U.$"\Dg \ B嚝B5Ct},ErMhGӖkҒ@uJv O'XAYkZJl7ʴβӯ 0jv\7W KZ}=8{bu)~ ׻ε=miZs>1ᄯvrZ2qJ æMzӛ7\j_I&8O-}pyE.v\V2$9e,g2g<} ٞvC5w\~}u+}vwkZ' :y{ut/ 7 %pD3ԭ+\XGaWGRT xdcѢs'^ؘc=y@K|X)!LxNXx#^O}X /l-ڣe|{7эC?[/Im9xE$?J~/{IS۞o-3.lhoY"^`/.30ª, p7/Z/pAF5gMPmdqF)GlD,V~my hKgǞypoPLnmh H BvOmJBzPŐG GX0pp'v>lQ QI0(OIȄ 7;oyProAA^1aQeacQwbv1ogkB 0p q _G0qn0ڪGݑ)W0 q12 I* zE1 ZH"&2M1s$#OroɜLR%q vNlrG&gr'e'(R)))(**)2+)*+)),r,R*r)-(Pg~0N "z`$b'HMBFJ0.+s10%33!44Mv<(0C5 #(PP d6gn6sS7ys6O@78{S7ds7s8S76fN`` D@88s999m;ms8e!l?gLhP4)0 2BE!8'"BK1yxB;pi%&?J#NB-zDSEWt"PEUTFa#"+(A%,E{E[tF_THetHtHi$b"ŴPVBA=43Mkp$K_˯) tA1HƯTM,%TMSN|M=أ=OPUP5Hd!v!Ρ"PQte 5p ?NUX\PS7UtJT-2"MOUEOsB'UɴKJ5g55&gJV*UX/XYeX0! "t PY}U 5[P[% Uśt17'Sq55)B15?T^ `_nB_AoNSZ`/ɾHkvz ȠoaZbCPʦcodLPas5K83? aհS deBenuPgy eL#63₾fi srFEf"m!xa u "]BDQ0o[ ,A009Hx_Y'ޙvӞG2"Q"B)⚅(AyqE(x (9taUu5Y(>ڗS/^l:@Sn0ntqZg7pzwt4"(r=yǶ))v9s/L:oDa(L(4R4Gx@aUvZc㡟w? (2Gx:4=gb3]ڣbUxY.O5~ŕG5/ԫG;QZ dhU;w4m4f1`}/yu;"q [Muso;'|e 7e_ںu,,B!Tl{/7})W!մFW[JhYT a7h{B3ۮ _ Mw7Uҳ*jAK<=ܿoVS\ Ծ{}k8oBQ|{uҗŭ)y6ȍ܁/q<:+m%})^ܵ^M ;Pх:'=->Bm<.!`lܺ ~Z dEFQ9PԝI5~)8}%xSb=] Z_^m_b/ _zW]Pϑ_37fhw{|^}약bi?X^ )~^I?^ 4(]d1i1ƍ;z2ȑ$Ki;h̙4kڔ OߵСD=je;^4ԩ]oeE\zu*4;ū@pw Ă2.Lz bz `}լ[tUlX״k$k Am dLtCKbΫ"h-1um ՛=\Ksz{cƆ_|מ?gE aya&-JՎNۆ"?ؽ2NaGbYHI-5ulYc)`qؒ}9O>Yg5 $a-YdYPgu31Flhn&5ub'vmgdK "*'z i.)6iVWᎢ"Q4i V*꛽9Ma*UJ& aErY]Xl1wl^E,:*J >7Xcَ? ꣖bj)qԎ]_i? ٥K֎Ol#]*6uk+'?령.^qK2 <}-RChsi 'Z6/G>?P:Kq(!)#/Y$2@;Kz~e@@f'l k:,D Vb?6Kɰ#9D Iz@QG7i榦I5)\\)&Lr:eE-6Ms:(ƙxlN;8qte ^B 88[)lZ#5Fd[-a "0Î}I~$W{)\ `)C~qaAaIƜJ˘HFj/5d*d3 d2sL}ձLΊL7R51!uzd;ˠ_7H{vC>O@ zЄԠ (CЂ:teFЅ.Xa W`3hHq1,d%m?aK[ ӗƧ!1P<9ɽ)B>&y[V6=jK&F.?K:ħ{d]^ ֘f\iGube[ ׷5tLQ7'/<f Op9򄅰ڥ3n(B CP2@LtZ~L` HkZԞejKYlc %mo9[ئ}-q.xA ZШP$aa, Ƞ2MXa ^r>FYG&JK[c|ˍ Tvߧj\{+mhcIpCkbcFX?,a&1M,xNbΙ"eo,eQF7͊H"kg*6BHt=ciN Nr$`[F@E ?дx3[x^qGt(Y^LJ'{O?A^4W6OTE;WN9}oɭrYܰe 6d]r/GQ=3=+KH_T;ڱ)qQZ4jOLd105DӴzfW-#^i׀ȀHM]N@?E)8-Ec#öXX~78%.`}F~!~g5w:9'=m;0c*{g(1  ȅ ﰅ.1#5f"j8,b!7 *a8. :n+ч 8Tts2T-q!.>1ux#~Ȉa7*}8,1.2.Rxd #3&hl(.(5]^svxe((_xy(\`~8cih¸dH!Jq6WQ% " ffqqǃ\5a8ˡQ%a3AlCH3SXmB+1Lߒ=^kDWV mVM-tԏF8aPOz )T YeYQ arXR1(ko:s|!II /p!(l,c[GNhL='^d;ɓ=? A)>i0:-1U Pe8ZUZUiWY[9[QYZ])`fpZ]g[9]dqbI^)iYNȵ[dLfyiNU_^iQE/V~.)F-s"Y7//HY3'! (lIy,Ci).xMÐU@Q4ROʼnɩɜ͙4RP oiٜPډݹD)#e RѨɞ I) Y}ٗ`c".; r1cFy1 b,1B/?@NLsjSsQf vkG".֢/.0:Gf,:9*; I t:ڣCyDʣ9e?a5H*BJIjSzU[J- Qe" -h׈~EaI/z/Rݱk)LJHhJ-A@Vn/`6r&abj35~ HjR)ʪ^ V3 *ګJJj')fbj1iKQ& /PHbMe-"kHظC, ƎL;瑱;A8-D9@a!e+#FM(/n 62u0I>@ 33#Ù .GoȱJA($# ?:;wdbc);E譋~5g4B{!q; G!'T[ O43=[vm:Zi7jlۦnP K['5H'9Ļ#DHCUp~ =a+B88gWLk{ i J ,:9rnwKBDJ{V} 5#PdҦ=6Kupr@AZG.]7 iJ6Z'gt5K#ߋpkٙE>](s3/A%Q2<ØSy56J1rӽlPu[.(l~?EB$b|{#N~VW83!Jþ#7 /CP1$ BslAt~xcAߒ?hCe<+n:Ps4=a64'lOF=7LN*lEQ ~vl TA7L˕GØrwA tG|10saŤ]kL>g!Ӭ}!7S!N?gda47 dqK4vLC,̾A6[{|ČL.-차E NaLLQ,eA~+U3g"yiVEX0u+]9plu,<Ǿsx\qy4t:]K N46"HrfX\,E+m-p" l,,Ra$-QEϔ~lLw97sf|mRUcgrn@s;Ȱ4H\_Dik׼WR|y!>-"7;]?8$4.- ]calkJ,!ٽ;4c}Mz"htf<~1e냍e31$a9V2wA9A^RJa$JBF 6AVAWw]M tQrjNmXcfˑ!- ]yh9~2%qT FWͼN. aWc+#&n~&Mk,ڔaQ!pn$%|IIUq})RbgCyQ̨ߚ40Sէ+Ce.+ۗ/* @QӖDhqBA$jqK -]TL}J 6X!*]>6d4>.> ^/z. }]1>Kd,,&jގaN0AxmzQ% a>K w{ >`KT8\v?$Wj#?o@By vCKM߃D/T;vi҇sdۃ^ܰfUMNkclp͎g=y2/_DAfo8H&9C/p䬗&޶?obf@[ǡ`c8u[?kk jΚsa:sgzvx&?|qcyd'' :-+lw7:~%w3sk"jmjs;JhO?Dx *t("Ç )JXp"F9fbGK iQdʓ&MB);x5[7m5q:ZDTRM>UBMT]~_ձIcUZl1J\S *|bMxNi:ѺJYzMZݚ"&*92WkWsݏ察 BiZ^'60(ARg!#YЃCX:a IB=* ֥ h8UKNx(jBbW$rkPڡ 1b Lg*&KUqcPE4zыa"F1vQplh9⑏oܣ?P"Mm !41d$19;?d>蓈>A)^ DF}{ÐҘ9 1jGmI]MJf4 >e Lf/8!F\jXZBQ /}@j-zTk#VA+}wr7l|)zM- diatҀ[4 #0K@ 6VC@B'ڣ@ Kx q $ p8K{37C>}? $gC8h BlHLw#L8̸%|BX@ɸ(8v ޻> 6(`oC8[1L (;z3C6Z t+qJJ; T7ryDMH[ȡ۷rIH˼䌼\ |Km ǼDKwCKdd,t̸4 N4v ƅС ͇۔<xp hJs3X.,* hI K|7e\хNtSN7 XN9K0 2m̡ ҄8"牉B-4$%; xzM، +ԧ4F [; J밌mTBoFE܉l@7 RV W ,HzR~!M=' MGkdBDDa7 $D\@$WzvI O Ϛ0 uh @tJm`7Uo,Oz-0NUdÐKhBtedjfH!`"L,mu;Zӵ4BWP=N҈h7XN@mHЖ(h5NXh!T#}@*suh : |G;S<+QRU :P($K]NS jc^Uo X}a]U>Q 4JdLwl qE0Wg3%O}}r{xۚclFnWaX6 ÅaHxq'm# ^rم4t5ن:A)f "6 VrH!2!}0 xxܷQ';`pTguTwUO;+QRpXuu1_uZG]u!Nsu&R<;\vUVkumvkvlpmno, \wg.xwxy`wy~zw~|7xWx梈d2rsxrxsӹ49.Z6&raH,;CxG0ESDr8A,aa8 zwzDCPgzhzzz {߲'@/{{{{ Gɝ08}RyR&@)3@i:.ɧ wh|!e!& +ۡ +[U!2}/Rg}S.0P.2\ںRz~jp~@m~it27~~wx۩1)Xz,䫡2@p„|8ПĈ xÄBȌ5dQJ.GiR%M0'4s>O(Uog?Ou4Td[$4mArdӍjrhv#zS6tDdࠃL04292<A8B"Yd?*$O NFYR.ieGإLlq>0XRyin&orY'L:q)@:Ì:8t:v¹h"(JEzDf琔F*NZ<č:UXхZENeث&SXS,l>Epa0Mc2bd˭݂;{鲻+X뭵+o0 m2W0;2VoCS<m0Øw^2"Ln6 lE]dqEHHm9Τ۰4klB#m':~*ןWc_7a06Y}4QkvfvQ_]~p? Pla[ mI#V>ClkҷA8چ4?K_A9Unyd?af+Of“B7W 4:sC)";y=M}g>PUqfomj>oA'{!p(fGp3sJe֑86If(,*I0  IȬ%L wB#C`eBp:]C 0?a!ЈDaGmIDb h%*qu#)gZ,1ksn87&oK#gz'lp% YCɐP)u8#+E?#-yqF~ĸ4ѓӕ`"CJB[a*coYя"/_*0E bc26H%dt`$;V?Sl&7⯆&2irsTg:Nr!g1N{'?׹O@ICxx`|O>?ux>T)b<-݈`=hn(95uĐSK>4^hr KSWR=)QxF= VM'D"//T]$^^&h(GPַ5r+]j׺MSsO[:w"CуB6c!٥q5,g;ς6qL;pp9P]j =;(HNJ4rmmkL3Ʀ6J"W}rRL`X"E)uvqDwkW }uq/k%M0W\+-\s`'ъRԡͧCxD!Ћ0D!,J ~KalA8UX\ R5Yiu~;hjp==#[kM) 94N&64xiS,1)M2g"9x2w ϙo C9"W<'Бzf2RE!g~04!ƐUft`k{c-ÎviNcLȰŎ4/Sa}=vByǯ2m8J*gtzͰMkH!re;bTw7p~R^5uվqH<4(dFcF?,]חieܜrkF- 6رfPkǎw`kfoC7+}qˬKE虦sLeGǯzsHͨ.V4\%KV7ٳ&ZsCxPd.H[E 7݀,9%<+-c[fzmj/MkTjvr[Zy߻2'94œu)YSG>4014ڸ8qH[nԃ{ͯǰ5w?^ȿ_lf+G;,`ӵZ 6SPYPQ ]F;P V=HL]PNW4X\UݭDL\^Z?P9^)-D!1!C(G4V F?`eޙ9InT:xTJHǵQD{X_QT bui|yZZm!˽R!N IQA_&5i?TE  hw>cy2(VaRRqAdf.<@VzR 5_8 1'I]N֭gvHʅm$mjfg{M\{>SPg9H;2? bh8Y">)eD ADB<<rw.IԈ[RiW\b˭^٦#F~B]-]mbB]7 ѕ߽&fܱE94RDi8R\Vjer_p9ܦP)Dc3*Gj4m%%<fQeq B`i"i^fM8D?lڨF4|Qak%E[-~q1 bemxNױi ś௬_^޿^ӥ&Z!ycM㳙*£i*a*-(6ޱ#>H@X(~+8?`*JϲGcY kV5nR޵jj6&X,N^z9&$'B*#BԂQ9n(nYʬN_,/:OeF6 *䫭6F-=עDR-f9fm%==cg*`;&PܮCjHU jf+٭+z+0S'pQӂFH -*J!}O!fh;_!6扢f-'zm!BS~+P폠5oM68+ lI#0bfU{Le.QYƣ:£ҤCg_:\j?c#uL_E՟9^5%1x#XBXhF6cjьjW"5VJ(.jR$"OҧMڤ1__'LٯnMIFeGg&<(_$;eC]fX,.؁p녀K|r,e6^"O1f=ӁB!)'P71D|fU$)Vd! ;Y&ﲸ3 -eeK2'˔.dC&o"֧`2ө=13>r4b.rjXI4O\WQ8iwFZfE)$g\^mcB?-r2]$iB?m)nB(jFWOO`sZHDCca^=h:~dCz4k8lvo.=f>c, %Qti0Y ifZOx5SKRUP5&[(7@̒Zx51|%lr~'γL$L%f%@PS,o^(6Ҍb)s`cs{QZv&%qjQ/whq<ȱM%"7wZӤ;-S=6;?tOQ<3aCE͞B.rd&^qYR_&y䪲Dzs:v^Ԣj>zc0인̍^ƶ0N{렖b x#"?@7@o^0jB9\8|kRnDaErU3O:i{Bn/X7Tž>b6%ҭY%${^֟j"M.z6pC:a-a [ 29O&;X\rRB:h7ϯu蓙 _*Cݍ a(Jj2 m Z7"ڒmL ^fpAe%`ͮv:@l;S(ywvN(2F"87{[+ZJʲ&`N"*pR$2IlCla78@ph/}fiWNYWÉDf'6rQWYy~v+v̏_<;*ڪ8%>>4cLǖ.歞Z&C(sT*L)mXSŅw%2RSW 6#)^3vl5+ϳ&kl %_ksZpTBS5+QpW Kvr>ctN6wB 4~G݆Y)+=|ZDr3~ kN37ckC[n)6ǐf5@`A&TaC!&D@cG?NF"-1%Ȏnc̚4qM'Ι j&B>5Ѣ Eh͟C Jh;5;lYuS1&nƕ;n]Yc亙-xIx|V8۷Ecq(?L5+n#^){iҭRd**ZTJ*۲|6<(6x(˙zui'_,IzwG7n+qnáfxҲ?v 3F;R-v*'C"dǀ†6 (6m}}Ɉ"F Fz%~4P/Bg RɏCl'r ȸJ0H3 #-j& S쉹)!,Šn*=D*r 4O4.͙< -!)-HS#TӇLzlJJoSM8ې14 4?԰ 7D&/$HSU/襫chDRQ[Ov1Ipu9IdWaPn6=DgZ.6== F'&h'Ȋ.(Iq#' FH UD%  )MFI^HIF )&?&$F,= k `a-lh9,7 k&tM¬x eHDXMl3-1ZJfj%sm-6)lkS)*z抧D\diHLZoCPA7AP*Jg{XqH;p d9IҹFѡ)mW@x?6-(Q՚+ڲTAyٔq4 #IRI`2,h5w%o'1ChAĠ!ѡg4Hױl NI:Ho=$A7Á> UeƪLUSo,TCJZȝ1zxZVGd( t-Fێ_M ]cVY#.uǪ8t[efOb,H6=v@ƏALkwxl9kRRwrWf"*B$,2~=)/Q7QR,1mzKǬ[}l<ǽYءQe4@ݵ[HJ <\$ 11Kqw{u$X}@^4`# 2_1c~`soA`9nʈgS8VK4άp&L}:YcqqBr$P&ASst:UI&NF#.^>a[%f#:Nf¥pN<%&uU;P2Abjܟݭ:yJ@w_֤3pЦW0kx3:Fm:>Jc^ٜd1{Mxwakrּ:zCj™-XwǸn۬ rNQ3NvEw\ ;awS>ǣ%u1y{e݊My< %-̗P3^{ušCUviHnFU6Y"&8 ʝMG9 yv*Y}[ !kc{0xczi}^Kl` HcOy6hО'xO>KLВ(49n\,(jn]Fs F&`|mxCj[  DHnZ*h#l3rPv|@p\Ó"pDŽI|(mz˷iDp\,|éjCϰ*⪠* ~ (sP_30THNV lkR6 k ENPgB~)DZl< Xp71,'/KQ!&e %(dWc--1z (F=0],rF mdj)B 뗨i ʱ9"<D|1#AGF21CVJ$M-EqUJsI(V/GXb.#ZS!6'h欬30Q: o@L57vOD B(n)eZo~iqL4ث-! ACAs15=e~ Ds. .Rړ-qӈH7]@6âK#/7lFq5NT}$ ɰP, jK%A5;B:دBc/ B[.O*Hߐcȱ<=jtJ9isRNtV⬺a$6ÿx ّޥu$hFąBmBœd@[j}D M *ggjffb~nEU֨]+fVTq@Nl<ٴjb#Xh̪[[%*\-b5vb96c;cOkSc/d7cUcYeM6e[f]veg6eyfeg{6ff專܀g6iVii6(`#| t 늊d"l@xIP~a%T)&@8-b-+^t+x(ְ oC<]-l=bq%?(3r-7s9r7: UW1k(Uvju~>$l]Q}xx  6£d *I"D~j-Bi"bB,@zi&b$\o$'yݖ~R)#ywk2,8w؁#X/XyfI+8X-8)]6~IxK8OxQ8mw]݂ ITSSUX HW܌~ )|5fx58|e#I'Z"IX8J~78p:(t"%sӠwщ7~8y؏8UK8W~ yy y9/3Y';YT?˓!9?YOYS W 3ٔ+s' #4 p tWkq|K6V>)7'*>|$I JHKXQ b=*5Sv^ü:IU2r. @^ju/Y6 S-1:5z3Z)ɴ=SF:INCHu8Y 쥟oFu5:-v9:z=N_ө:z3\ɺ͚)Nzٺ;ڎ! ^!sJ阷E]A:_!{%#' Z;--7۱1/;O[K{#;![!?{CsA;C?-{u9{oO][{{[{ۺ/{۷{ۻ㻻۽﻾;|m !j[{<|߻k)A\EA ̠t  əɝ<ʡ|ʥʩʭ<˱|˵˹˽<˛\̼ȫ @p`t<\|Ώ\Qv`t@ȍ=}Ћ R T =A}ͫ`~ńԼ#gi6៶fi^>dA5>!^;cb2E>䡖SW~Y^+%\\Q_>A\OqUlo>b,Ӣa `@knх6ǐIB ծbn]$ d;F:N*Şў]L~^^2^ڡ۞>  _/9jlG$'7KY?[]?a5-37'Eu#_?bQH__e5,$` A<.Irf_LM^}°-~ 7A&<(pC#6A)Bdq#FCr퟿vR9#ˎ-?jr&̛/s !ΝH{*fӋIJu:ӌW=Rj"0ѠLI,֪gV+[nמMXT`nь.lߣY v0O,!u~*K˘3k̙3yeПΨS^^&$׍2wr??{I?>\9<Ó/N9s֩;:ӻoxgw&kwLK(;q7` "(2BXRρ5f=3Ao"{5h;?B ^GdK$)n&P ƒ[yyyI&\~%f*i#u1{>gȧ?833f饘^Iie*ꨤÄ4+ njҬJ뭶뮺믾 K쮟Qy>+mNkmC;$ikn螫n Ky% "<ICF,1VYQgeDlZil(W[œa0 O78L1<_mB逪=mQ|L'HMWȮ<5үrmٞzh]/pnm7e*cBQ}ߘހ>j E3]4&7'D8ِgJckp֥nY7$7u4K>kWRNZlbi'Z +:r+˶Է +V_m~9\<~g^|~k}D:su.ήэOiϻwj1_)>l*^+`Py{g#La*y u=]I\$"ʚ\,@qqw? nPLiLOBi1fKūvO!oV!!ਲ਼0t#nH*˃y<Ho/cOM'?l!Y"6,r IRғ$e(ߠ?6)Kdqle)CɎQ6ėDڡB權D㿌E+Q `KIsd51e'.l<!wA5ӄ tE(_Ғlܙ] *4vS <$OÖLA[IOҗ4BO|z Nm ԦGI!L4QHq4c7EvT$ЂHI#^ B KXҔ&|6hChi 5VzD[`~*'Efj8}2-S= <
3q]caYIqKZ1s3XӼPRWrYyJV2z;;Ƣ{ ,خ6Rv}ӛJSIk]9Pt n$nàY,UӸ(2O} 7vzFO#(Χ~A|[J?я˄)I „@)jT%[l46qρEy>LS8"!Znwg8[_a\6韵"ߓOd,C,ߚnoF-*ﬧ:FH۝")G"f b6(˘`z^x*GcdNQ.)Pc=7hI>ֿO(-8~KeFV?F1Pb'D! WVcp wlzķv{{/bpyBWp2"H(*5BFN +G*>@B8DxRbWHJ@-Dv>!K0D1t> V_YN%qeǁxL-ȃf@hSf\{>{rpuaWDb(U@8:/aLL0Hh(`d؉xȉhPfa`H) dȋX9Laha^^W` .Hm(E1Q3G85rW<8l-z@P:Ԏ 4mC )9y ِyY9y xq3# ˠ) V\0]U a)h| rMĆ#/!*zG~IGf6`C!2bS`IMXMf)TȄ>XJd)=H[`TP$ ;&Q'G7F =R&D"vox]P ̥HV3<6*+G6iB}EM\3ѤKϡ;QxO'w5n /xI> i852fH>wk97 H;!\$mb*BbV[HxA\vFf]gy9ă - DVfY W:@% :G Dg3x@I@2EG(j^5QEy <ᙄwڪ:Z(-Ekƕlvs„dv2 𐧄et;QS55&Ϡ=GV76ڭʪKkz)v x'-v'}cw؇9ѕyF+{%!Ph)5˻gl埗k|ۻ3ِKkR2xcKz|aP̀H>q?%  03%5`LP3(p§!<3ʠ*<%'L?>/E2%5|Q5 =?*P5Kx.9PYUdl4|ykXX8TbUSN f9菒 #Ȋ+=)*7ӄH(93?ȦI aɘ<3<>QzL*go<>J㸆93SI|4:`zLkjDxAך+  p)Av!"R)|REcaEB* a΅F|"w`!D{_cocХưa`SL@0%vx,f 1#~f0xJ2NW(ǟ")2Q/wr,.+0E |P40S pvL:7 WAxL d]fwV^ H=3;A71'pQr%7pm+D#xm%E|iC)&ZuxhVhpc {>Dpyf}ZuH+ q'+)bQbۻ-[tҸ-= "wR*=m]u Sp4y2 i1PGH-UYR)b6]+W߰r-Q!0=Л_(s aȆߝ3ЕJwwuÁDs$ϡ<(߀Gݬ-ɡm%*a @qル<^q pլ)r]t$P<72oäS:J]ЈXYP I%-)}zK-eڙ.8z%%\7Pz}YMІu$ [=b]`)|Fn~2TUeZm{EC .vKj3Q! (/@?8+kAus {@uy7bv+`$!nkH2jCP4):^p~6tp'>$΁ф-2YgE.*:(og}%0˰2^ɧ,HvLƒks *Dc,k&AK[R>A"<3ʘQ'ց:;T(zt*܀T vfz=,7h|B+ q'E72(qewX_2.B\O Ή!6ϴ)y<}. z5I_vXk*8 QDXJtD=>D$*;8y#bDho8 Yo:Ԇ]GL?:w15𺩀?&\C%NXE5n#‚ 9tϟvUdrVM9uRl64;pFr+0zPH [(n>DIH*Dk쬝„J)4#blQ3Zj˾L=f3FͶF+$[Z jhBbgSr_vB |tV7X_lu/W6s1wܔPፌ}[H)]TZEn186ƊDTՓ[ W[޷טTP&͉e&Y9A^Sف׼=g[pej酚g؟gChʂ{ԻL&.oGo( 3,`Jo젪Ԡ7>\rG 9:*KGnա_[u-'2"v ;commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/getConnection.gif000066400000000000000000002406221472045345700304330ustar00rootroot00000000000000GIF89a- B B!9)J J%HB)RLRR!J)R!R%R)^Z!^%Z)c!Z!R!Z!Z)c)c)c)R1Z1c1c1n&y$lk1s 1p6{1{1)/~99) 669=!%J)J)!R!!R)R)R)!Z!!9!)B!)J!)R!)B!1J!1R!1R!9Z)c!Z)!c!!Z!)c!)Z!1Z!9c)!k!%c!1c!9q%&!1k!9}!>6).B)1R))L)3R)9Z))Z)1f)-P1)Z1=c)9p*=bB=qoIZZ\`ikgsos}|ƽƌƽƽƔƜƔƜƥΜ˟Ҝҩ֭ޥޥε֭ޭطޭ޵޽ޭ޹,[ݻOa…#Bćw6p}dHcœi̚8o괹}*{oʍH*dBv'ɓ՝Wbݪ";,٩Է(~KnZذ.f+nWwEOBD ӷ^J~<9rM=s2G_kܷiʨ-wboؑ юO{uঀ͗٭?麹!>hqWUIl#,bƎŃ.&cMpB qdрpgG)7~FyDTAhH Dg.S =Њ'U-x)U cg`VZ(gg;>;d +eT[ (aC^ dHf@acaђI_~Qiىf$F"B"nXb")fx'ΩeA_ag=At(Aew⤦:'vїYj0l?yXndU`vPaxRsX&l0:F 滍Bk-f((iRs`y&ͶrG˪6˯~V-!7#c[绨: m6n~%) ,%^ s˪{*d9e2PhԩgR(ngP*uuVq,fȝcI0u^Jjˤ BL.:y1;unccF9t_gAպ؆)՞miai z-{"˿3<ѷRF@m= YH/<ē/O~BꈤPRK6~+^K`I|kEr@e*9c %\7P)$ )$ڰD]HYP&AڒS833In+ TTD{SrEkKjT եA*CӯHat[*uU{:SwԦ]MzV *`Q{,ʆSclZ͊ؕ1-Qnu*v]oMr?w6s&Xz͢ݫLMkSrjv~}I=/Φ1PIQzu-M,pW*܇Eq [T,J(DW|ͫ_kzΗl~Y5$Xޑ*ݱ ;%J[C8/\:ԑ, ~A{=|R0Ҏ#D)T8vE=w=N}ól8=]dwbXF.uLd [X;/b t>[N35/V g2bPO|=yĨa |NtQ|b3ϻ:rwd ɭI>{ZѠ)bH#dSKVzq v} ff]k ґ Yfj6k|ld3[%ֱs-dF5mm>vfr6 h;,,j1`0Bow/i|dلIi ?[s^s\'8#/Y)Ճr5yS[ۂQR8c ]8ITzεnrX/Y%Psg}л~RǺԭ8¡0;h:vT~8@c+λaÍ}Hc3a#fϫu* mx=7oOH7^ڦRoX۰6{OH6yC#Cx/ հ 'RURU }WxH|| ڰ;ڷo*+؂,p{۷{4|0Q>?/!^a ׀N(P|S|{ 7*B҃Q8RH~yM+q@;X(eXd}ޠ~~#qw)hx|~۷ ^ G0bPG@x؉(JUTe@W^gpfGpGP؋XUSPG`ef~)q.;QKph Kؘڸg0pxa"EJwpgU`8Xe0K0j dq fI`B`h 8(^Hg`J B "98T`AQ6)&  I0xK C`bfXje!f2YF HƈT` s۠CLɉxZSp^GfЇ`YDa j`xDnɍUR0SP3@  ~ Yy  c^we 0|9i9}ٗ0i eP.g"TeT` К9Yiřé Tc$8> ęٝɘٗɜ@ G@lKb` 9Y` <`ܰI::@bnɗZǙȩ IY Fp  K` (9iA GС 8J0;@@K@l+n˥p본 P򰘁vFEq[m{sor 븈˸ۦϊPDtV0;ۺˮ뮁y8R@!Uڥmʺ;+ Ûˋp h Rx9  Wૼ+;KmZʾ R@M/֐+ۿ+~)pq p <,ھp @˴`u$zdLzY,*rˮ.;:k@,|=Òkmڱ ٩180@ò+|竱Kc;Хci{>-mӿLƂz 2U0 Ш\{[̎kf XZ ǰ L K+൭eݶeg=؆M؀hAMA 8N&3SЭkk؉ر[ؚلهقַ AW2j̾س=ڶ]۴ۃټڅٿ-Z̐#Gtfڙ-ݸ ܜ]ݷ ܝ}ݻ={[ Pd ź}ؽMވ-Lt`k ۭ ݾ-߂͵W͘pJ?]}]؏?-}+ Y@ Pg-=✍Yڪe).?N>*zѪ2p]dʹc "݉ P~\P@ e&A|z{aCXhQ[;-+{MiLԸ3q4f0u wPnݗ.] إyxĠܐ; 㱞mN߽c ]FU0 .>^'$Tq 0~~~N[ UʱGD+Q\].ѮN߅>25J"m>鷎`M$ )(^+]x.\ 8 ]g @ j p 0kXU`=VOoUyoR0 Y&ꊞ9xN tߦ~no`oz9P'agRgo?{֔Orw|螟l?ĥu 0Mg7S0 i_p__Qq^ { _My庅k`/x>) ɓ!GRI%`ɛ$[ L;UJ=hPxʪxc'߻oަ<(ПO<N'ˊ3&ؑfqʜ6Y:e0א}=kFeŊ]ϟ>tU[ͱv|N̋Ϥh̵pòӗ߿ey W+…蕞Ic^mZ'r }کKU 7:܈~nʰp|WܺRҕ+m}y2iHXr٧`n28+deGᆡ&"vYyɎNK5.ꌮ=u5![ 7&t!ȡ\rQ>l,k5M iq"H|rO&I<џWlxH\Ϥ84,>`L*}/ͱz&=~a\񮢈#/29!c4tJɜ4V\ 6 sJ…9 ܼra%q wWik18p%Q{UV: },;GrA˝(4ѢA\t<[`#]-f9y$$<;"Kt8[4c\%L IUu |Cp g>}T<w7@Mb)BdP/$q^txMNt. !J;EaYyGhBIo'KfTV·seuZ$юcRqVa%ȌIrasս >_zxܿZ*<*4C?!Hֈ]Yr'6m5G˖Q6y&g'?o#| qoצ:ū|̊bzl_gJ0$h&Y1<^_4/sYiMHEg1I7Z_o Ccf׈{A L%*~t~-z&2ƉE۟ucz0H;2fV9J)m3H\Qi~5M]Hʣ.TLq`H=^ձ}sss撾{E"B/tP!9oZ=-#:jvo!۞&xPjZ6%`KhM:1*ElJxg,}Ri # W"BXOj\-@0PfnQN{(c<:"_3#.x\K*L!q,L GzPD2"`ca:A\sܾ"RѝDv_>!G 0:r*y"!yU$&P˱b=0!nܥbvA!>ͤ@pZYҤSA,{ ]p2M?$(<'!~ Zqx`7Sb[AG;Z=<5K»HL8!$ZPPp e(fv1-?j>&+PPHpYH;@p<@IPpnNx7Ip2H!As& DR5!.aH4Ӡӻ18Yȃ>LxJE(ʑJ<ȰӤkHQі <ȃ;7+Ɂ@l4TVqI8=4/6 ;MPhܛD(̺E,I1=8(pDp␇c,铀CzH =RLyPAr@:=H(ǡ\AHhMy@DD3/WT KPEJrS)0>'Yzj.NC3xL8ZJxA@W<@>TpEY@DZH[xQYGT\J`(LPH;H LgP$&h1 1{9KTGxL OLOM@AP\=Lpg\]S:x#=T PXkIT@ǙG;Ȅ5O?'LFU1tN[$uH\S@,?IFSAL:1"d(|}ߓSGW]QZQK1֑ 5C<6i%#ĭPH7v3Xy(+(;ǒ#t2΀V7~ ف3j$PaA>D>g$σ}TPK>뢃sNP܃JGA+>G]gSKOXC apP91CABH:S]k]WOLMGHIHLp9LEWIU| [MEHKNYTI( >"'mSxrʡ=J7fvX4/7$H?MUQxEGHQSQ8EȃLXH8LxE([`HY?PFKH`MP<: ! N1c҃уt[aPMF>:XQLU68;UUQHpQ9M=ȄWY8V8UȄ<؄9TyL8HPD<sTPe$d1>/eCɻY><(P9^MԄLHSF=(,]RSAp[Sh(zAyzy^U(7hKd_dM҃99<Whp>R`JHЃHAO:;:P9xH"]9=9>CA0yrChWQLX]cH7/>՟RЃVds+KgKgqFk9KMR8(Q7EW1UUMHGXDApλV3Ѹ0EzQ(VM9Mx^=M:(+ud([ȅQKV9fŋ7pl;Hb:HJ@f5 K˴wf1Gd΃MRhypdYCh6W6 kRmMW8Cz3BPNhzꦄqNgRW8mf̟JoΎGYz:@h[@hWzoszH@y/o2\ 4!*\.r.ohJ:t6o+:H~HCzyۊ(Ot^nnM(>D9c^MXz0p0[b77)ND.N+yr=y~g.9<?0h&V{zFERdbp{Dh[hSE@pyPGЃ: p_Qgb{W\>p8x-: \ofyYe A5g(Qj /^.xT‹ wN '_+Y.%/fc\$HóJ8m"]8hc#Tp0QE5T<1SK۠Qn0O@8ijW.d /Ĝq P<5; #ůJN-7UJ"4x d$}"ap <8SޠH <2AD[􃊍z~)8TX r0kOqa_L1J4`Z>lDxx YU3>hqQ< fsc%UpH(~qS1f>!u'DJA@[\$P (`XHq! @[ q"#%>xa H =d+FY ~' a h9#@U7:aK"B%uw(X<9^v*`gPBT8F%zŠ$s .bbZVJ0-@Lب#h 8"rE‘ˋ/#!8v (Ũl19Jر5W80y(SYǯqv |yӡ]`Z< zz\ DPPkVjEI)*a]Q d9ϱtBaC 賊x dCH>}8##u]lL`1i@ X 8dخ E<8@RRBku,D(^BО-p]l -RAa^"āB FE\J$i&X5lT =m8観&|f`M };-L/T\d{ZMڶ!SgqrLtKv<S~֨k|g}>>fn(&oNpg8\vJ0`21E5Pqvȃ,JmvFi>Kj tjo:h<)oJ{fZ^DDN=NqfuHXy=) 2O|.JC= @7][JLEL%ǁ^eo\ ۮ.KKJ˺4#  K-HoXDqX? NCMǹa*Cú P../﮼Bo&/Nnnn-jJO]fơQjuoS?J o^.onj0./ !_҄M}/ҙQ ߮ 1~_Fo//vO1'qΊ=zQNk`ՔQM`v`[KNcұKﺰ*1 / =x!ɭpon _n{0&10?@ r(cHPJ 0EK#.ʩ|o E0B'^@)K=` D-$+  8/n B@}mtKtPXxldLoR=ÿ\OX)L3}p& %;/pot D0d 9Ğ.H/{0qqggjt(cXv Z8.wZ)G:ǽզQ]﵍ˠ腪]]ϵf $ -_j vsjk;6c3vlvp5n*] e6fgf?Lն~ 0VآD0H7\5p3`pc{7d0^xDz Œ. j6 yOq_x7o|wfRԚ-f_f6'xvf ~lKQf&*Pl|U(S$,99E.H^+8xSQ{vm[cRBv^ef׻V0{4^ 8(K(R 80f܃o"9 c+ zQ˖RX2xkSbٺRv6캨爁Zo.euЄ]|@,X2r1.<) &X-$qfBSw+FPLlG#;՛>}~=M-cr"!~_GPͲ.7kNMՒ>cKh-l8jWY4L\>Lr 0"k0G2o1jqC kr1&S3(P  XJ4H`y83H G}pp}+W'FDg NJ&M)Rj(/PºWZTZjIR%v;B,ǚ#Av1(Gu2(*WEبNN֨Am!'#ax:|F,>vS"ًuZemXx۵wot~݊WquEʏ<*$*Tb}Z%9BT T8O<'>d?R1B Km<¡›tYw)#uC,R|TtDDJKdAL*^; aǮdVKrF *8 UObq>rꐪnLjN{GH1N$i-yP['BS5>@4UbMQ4 \;Gb'&9SCΣ62őkg[ŬlD[ yc<ѤJC✣֖pL;'±EteRcGH'y$V'[-EHt"(y1WGGl.ꗴxN-ÍRh-[zئ*JRA쾃mVfqΕ2wEȸWJy2KA𬘩&(84+ֲA T%D)"D._]zIG٤9Zyxl=4U@@M,Ɛ/)abc m+)J.\ɳVHGV`ީ(| 5etr#bK.w/lxU /$bڥkAaScT&SŏlMOeL-=#xX/8 }zXpwJTړaaOVڢRs!xi}uQUc$F1 7 /qpEKkS /LV4i䃟#8T[acQ\d JwXPL{YLMzo9OC 0+6J0!+-2qya( KԊ"FYly(z,C" M-<чQ,B"䑉>ȃ}H<Sģ} Pg G$ zu&D u#[B5h/l:CzVAC~qm<{f'꩔pxPZs#W,#A1%[Vcdl]ytEF2P c&>\EŹ.yqS Ab#D9)75ΨJ_|{*?"}ڻP.šGiA2ZLl-z,7ײtGC*/ȓLl%5?'SHn3rիX%E5oFQis!! YH]NGxEwM+*ZPt@M̫Ot+aK{NF$ˣ!Ȋkm+HX,I^][؎ࢵ4qmc`+mm]+Xdj IdVpjtlZٽ;pmD[oTjf^5s ޏhV1l=)9q!l:wXbәVpϜFY߱sR`ǻpSpb?a}odHt.v/>{m#S-Q?9o^_0)w_$ -2wflK2zX:jnz.{Gn<'?yK~V-[9q5Pdn7|gK>K;`>S-@6`'x y@l2A2*oDaH`@@0!d2 a¨¸(¨l6"' )v5fPAA`Jdcޡnl$9iFaW]ٍy-dȑ89Z)Y 9.*j&g`8$ُ!92xYEbYٍa?$Kc(z!yw"ay"DQr/~x8l]ٜ ٨U[ٕwYW9uٙ%)Xq9A%%A Ɓ9͙v.Z&gP'Z٢ɰ"!)ADYHSm:\9C wt0DsTq ~7E Z%~98~㭋CHh9Zu%H"tjwG;*No=h!t4 CAP!A~C `Z[pš4 ZCġ8[#b[~E%-*Tj$6V!۸bxaUv#e;.`XaA%!Ĭ9)o :93dB,)!A8/9ĥ1Ï8IEG\ȃjŏ9v>\Z=ȅÕ!ʋI;Xs.n<.JWñʥͧa?ΟaEC?\/*S`+tt<+)a<ӭ3ȝwuHQ|ЫO}7=Sӟ_#"#"/:>~~/E X %I{CpaD[|9= "dPkTHTAA)"v偷[4"9WjA}YhnC# BaA} ]=C|7UÛߩnYn&O3ЋW=#K|K=W؃a]ZAɝA A&“!ONy…Aav.a!??a?1f3hƒ $61ƌ ;n92HJ{4vT#P`L4g:y3!Aۉs͡A l$ǑT?7wVDLQ9ɚ[fbdlYsM젰fUƍթ(߱ذfH. qP%VvW0e͌_?~wݶj쌛n2 p As!f |UcMtV wR !pQ zKۂv {-A6(/ LԆ>ܞ3l q&w-"MZUka:p]`1C O<+.s{t]v8~]-"g+O.W^.׊G%z"?808C=D"& Kx81iBǰ5#N.1a ;Jydr\Im[S&E dc,[@X Ѭm =ޱ@G5ilb èf3V] OTygSĦ={Ӛװ79ps,(AMj66VTJH`YPj4g6akݨIKLf^#ѐ$]JYҜt=1v\CթQyeZ\&Sٱ5fuH5jB:Tkj]-+W9Zs:Ӛ]Eqv>5]ϚoK2 X󫄝&Q#(x|嫅s!<#旣iG%|h1n4Mf2"%LK⚨c0Ϝ4;YUFs0Jns\; "]8҅1_cGawch^Hbhh(ixs8!!$b"A"n]5ww>g#Y?!?aw!4Ȉ8?Z1YbqrH0NRxl7h~K g؋!\q{'q脹x|˘MȌ+fAEOBr~S!H)$8X|xGfӀ}(.X~`ShHVЎEjnjґx(ԐHy.V)yI- OPB%}&AUh[uwK3tMpS PigȆn[y> (sI x{CB}ȔX؆?"sYpYpGwٖxi>uhBryi~X"|H\؀> 痋H(Kx4命3c8ْ4(ӗ(b(D(.&_&J99 VXyɜ)嘏yh_H>yɜ Hb1X)0~ُ㉝IGWX98Q/9WyZxYaGfB *&XWJ܈hTWUZنYy4Z9jT=Ig#b[%Ej]Kyq]B5{!!Yzs!Wɥa:Zgإw66`ơoG+ ڡj~B9zjJٝypZ'y/ R8Z嘞#qdX~qzh~:""9T1駎jڪZڪg } 1U6H:ڬz0~' j(6zGzsԸ鹮Y5jF68RãQgȣ;J 8:2="h (B|d-B7?[b:]qHYRLj>3dqGGi$:Qxt:շ̨j0%☚YʊڐZ꟫*%W82 y(6)S+cKe{IˀhmRڪnyzYz ex4PQ) ˸ -帕Y}ʮz|'*kHhw1k˪ H x[xJ֢ N#%ԅYbw+YߡXʼ%K_(uh)ihs%k#Vk];PcX&ldW{(yBܶac* '/"WbXeǘ׳Uų.\y/13\A ~5,UV~4"J7UE6,QbP,SȤܑ XW*lҜ6ܥ w9BzGA hy_ ˊdhȊ`˾}wb HSNʿ<0U' ̤Ef^fM ̦|mIy[ŷ0]=Bʇ@xeB`c{/W|P,q1z;Ě[yIfxRQdހ|,ԖgOM+P=խF ˅K3@a<L֡ױdbNQfm uVc=U x 3gL{Or sp=ٗ"U \U-؀ ڟ-ڞ]X▂YaeQM}گ-ֲB֢+ ֔tm½ (Vf (O_=۰=ٖZUU< ޮmݐ?xx. 1*Љ[+l!)! ˽ aiK^_J ^ӕ~ɲT0gaQoL1M➽B=/iy XJX/ P<-FRodq> ԀlAͻq `NTKONac^ýylnbvm6ԑB~-Wm-ֆ\έ _ x;yn^NԵ~] x>mM~eDP9TN<}苎n-Z!媾oNe|}푂zݸ^ѮN8.B^zn.xPNp"~"~"`/_P UnO !!O~N p".>n=^xn.ב>ZZ@>_ 2ũ?=+{SևmJ;Jgh}mOn/%}(QD s-?:KH%KdGYSLlN=}"ȃ7ETiЖ;&l1RUdha©WyrX;nb 9S*k۶e ܸqڝW^e!2Tv;b{ .d*g̠rMdװ赏#Sرj*eʈ) !N-:n*J%Jn׉]]ft6q^o $2O- <^UC_?3/@F:hcAvvСpB ѱ 7̐ ?1D?Ck2+QCGd -=cdvygYmuhY6:hMv9iWƦ YhznYǖ웛F:9>[ iIC#xK ;q>:ǼoW[qbjw0MN+f_4-UcԠ6|q"-=u @\N;{e'Po\W2#}G`᥹=zWoE?Cq6~7=8_twW+9}n㽗%@)S?q5S#7샻(prҡa{`2(pNAsw)S^}`Dn1dY;8 9aԡ9">FXuđ(;b%Vъk"XʝO LjD+QsK:V5F1+.!{<c>h0#P^rBA&`&7u# (Y$ Τp d"AP%leT9S3N+]r1畼e-(_)ABxlP&8X 0JQaSA2ɯm.[ww 7>I #<2%9GN j hC:Jt A#*QJj)3z*EdIH:(jY!mH53T)\ĠQ e-9ԧ=OjRT.tS:UV=dêJUjNY#≔YՌLVn"UMQem@PA+E%PjlD[P6zHG]AQ.j=|L!JqaJi٬Z9BCַ@?QՆ7 qćLv7o-hC`Ӆnz[b \\IGz-L,Hяq cXSk@!::xD%f<&(4Yzg`C xf\E,Nnb⼶w pL8*\н8+A  a7i^?KNj'|͚qR#QNS%Y&z@JamJ))d=۩)o'~% \:i@KC*c D A;X)͉$3 $@8S@l%"?xB )Ýw LKeu9 ._14.>_c0BU%xk??!KoP?Gq wDT$$}D0 1j1E|1'p"\y&LT 62Ah0 kD5:ao0j`8; x>J0ilF:1}5=69/ +0;CopM:jwXēx.np\} ko@D  O4> ST"@ŵ@,/ڱHThIqD^L8 z2–!BXpD6?T[nlQBsdF7\$fDʷ65 :K [IJ| {5T0[S1){b[>dp u,gQMpgCcF}(u0F>n5-\y!",h菻@ɴ%ԇ2΅R&:?C+@qP[Plϝ&<1_JϊO D̼T7'>KlwjI1 1Ji,W0r!".t˫2ȔR=1eT;;u{V%ou9ETr=*Ӱ39kWJ*)8WtVԔQYReMyhv"uҭ%cMj%*G}sv+XoiL-:>$EvQ[kM5cD c9X -:vZh0ƣT\'-OJ6aStVڥy1r5{[!Z:WK:;^۸j` mmjjYC攭uGk ɤBF79%.-s#kF9JsRs• %bC"%Q?:\uϲec@=R8N_Po dMSМ!fZ6dq_ފ}؇S&BR l(.=c}':?56 eSC6Ԉn7h.k8e-m K91BE!CFڮo@5ȥ~:XdNaJ*J%cKi嗀c9$)>qIJ*->:.H'*eV`ۉlȅ6BZ˲Wr RuEӇ=hNXɄV0 7p0 nwЧe JkHj&M DNڶ,nˍ}P0s]kʨclQ%.* w9 R}0V@oDmr!C6ew@i"pçVduVauQv,u<M 8%t+V Bۼ}cw.J鑍|#o+p؂-p'pf5+_fe+p}pO+0Pf d\dJ%ط}Q}dJVS~~'X]Ve55 J5%h'L&~ge-dKb/i6p 'jxÆ6\P"Ċ/Nt"Ǝ)q$ɒ{Λ)MŒ)s&͚6-\P;+t *t(Ѣ/ֲˢNBI74*׮^coܚ6u-۔9\v.]9Ak]|{۾7Qdm~.x_޾}vy7m.o9t͞q.-z[iРEoLjյ~7Ԝeϸ#7Z6zcϘZ2쮵° ;"u:ѧ'/{UDT&eDE OJxǠCwԄ;-D\qX~'޷&[w5;-F4(IXC:XV(ť[;G"K2٤O*R.I%W6i%]@yLz;3N A|e; `:k@waE>9y!-;gwQJ_|;Z!b^~?)0qQpI*R1mޙլNJ Oa[[AgˎdO!) unjΝMI- _A'xbLQMoGnChŒ5I$f4{5gТ Y'CL4?)' F; 3xʸ#򥧢l~/އ[y(?S4$FnD0)j-P?$KI#,\J-5bI)ģ~f-a,bT8jE}s{պ7r=Wm fH}cN唯Da}q{QzPwq~rH>KCf"3\}ؙ⇔^j:lߜ GrI,4D}%bؘK H돣&--fuAm(gBX?g$GL]wL~?nsd%9irR P`(Xc'Ƈ VR#%7تv+w妬pQѲdArm\aOLVC(%5c(A i)<H1EAz[%")'$)]\eHgBAH’Q\PDJX@; ;U&p<ɘtR[ֶ2|z_t#aqY9ŘT'=I*@USS^}ecM6UБȖΤZ{dÌlzAk,d U',YG =m'oz\l&gM,:qг5V;Oz26y>Ӝy5IWs6܈~E̹+06%@|E.@8>f8!k%13َv=L-o'Xc l/Æ_`Dl|5ȰXxGY$1^|+q\QQ~wirֵ.reE/ϡ4wu!C.|- ,NԖO^͇\$#Vr?ʵ10Dr&>ذQg \ ߠ0 P~c Z.Ne!x)1v{#AMquxTZ7UKLK:.-hj+=4aZ(vc0vRu*e-{z98/6\û޹CR1eLu.#^20݌i[s},́GWi'Gۅ2t7f@g8 0[\ >4Ě{3IjnZzJ#QMFaW16OGǞ (+Vm&uk0G ti\IҌP1D^Rƪk`?^HT ZM[J"ml乛!VÉ=>xɻ83 xa%b s#cK8eޭ˧W"fc2ohFbRqdjf.&qj ڀ @ t tnm\`0A^YbUDDUΚPD&|0q-QJyAO+%>H$au"q3^X iawbJcUZa9[v%N4Z)%N]iVI^H<5XH(=[<ܭ>IJSHYؑIj\ER͍1]|'5g|1E T^Br{ɔ7|_ I꟮_iYI:[LN[ٰЋ];j8AC{H=MDZ\C,io%ZZef5IsFܚ W}W!+Vɳ.9^9k'u)Fzy e:ĵ-V(D'K|m:Tg6nczc'z}dQ ̈mG^a>n)ƮIƊ[ɒ,\ ۑd ۱鸄BQFXpٕeKm lA-D_YQkp`XLX_e2Oj[lHĤU^ &ejk)fu+~xcbV+rCYZvKE| ̀A;NǘSEd1U"T܎$b[ 5Dp&0/6LWx U`֪[|Q: ̗n E|K> fPZU1p,!5mnDNzhCyR(Ա텴)ٯ>LBK3Hh|_ P4N 0\଒?|gt寤7\6KW 4|+(?,ҵK QJ L0P e0!0m{q 9?oV7Wٕ?>[Em]_o1>[֒b!1]2V". r,,2 bRxeVp@hK}+1R:@ 03/qSsRMq?@oj{q8g>3X51 TL\E!2S 2iIfYR^rܵ/6D#pUk+6k@ DI D88tLM#N48dS#WH?876SR8NV*$HnAV|߾ )ECkvn%} dChfewpr+wr3r;wsCsKwtStqwd  XF q?p78@Nۜ:Rl56f4ޜ ^O 0/_J2D}OJYeٵ6vjѷI3qt,t*c6hWgm.*]xkyV w"-Yn'OHga7Ťs-;Cy-[ s0WXG-K7ʝCsn^EDHҜ9fgDCIo qt(NՕH&78_W&klrvvdvx*[&%PEriọ0X荺ũӱ} `(5-ʡJ5 DĴ MeLz\Jĉ?II'NbpC '5l,1}"Doρ%_m;z{JFk#kGw(f  ۈ[O}|ț|<]%Ѕ {rxz[%Aێ^XGO|٭o ̀te0c\kEQ<0vV}%ỰkZj-O !CiK'wgz}m!g%,-qZ6:}yLwެC,d1gi>;Ysiӧwyݳ5jۨ'ש׿u99nސ'۷Ρ?tձ_v_oysm9~Ɨn37mjֿӨv PzʫrPi3phs~yf .1RK,nHCQ,3+4YQG8ͮ|6*#LR%l'2IjӍ} tJvЦ+vʫ3:st4TS8t;=O?ʚol Xf/n+ Ҭf*/ DOmƼy/nSR?,JQ2XtDTMR ]}Ɇq%omXѐMVZHոXQo 7!]%!jz3֠0N[ɴ=+_Z|W wV'}Ra{r8b_KZ KթXvړ{ *Qn9wBe  gVx䜍z kx&/?;S3^h ezc_жl g ,ܳMBF{flݎ)Kwnxrܷ-ÅMm7<_q#kf/}"Xo(ha̶=L|+$?qh#NujK͉w cMolDE"V 'H coH?C`m~2UH*$XIbC!_ƓF|HMJODVFk`iTQQm4>Q@2Ec7FSZ:H;Caf2` cPͨ޸DC ސSJ3_d9i|e=I(S*kLزGA4:yT˙8B|jDƆ,iehBE~52 T*:)ؕ\1uC]:F))9ۘΧ[Ӟu+xީV:jbjb7+慠vyQv6Ð.֊re+Xg֚5~WΦZV$s_{(EMZϲS$4[TyZWTUs+b(*wӫ[zo8 #I4ęޝ 1f3S Hߥ4LR#B%4Q<."*@ 1 9KF8-DUh-q՚G͖x~Ie&@QgSH=rYDEeByln=@+.Z2E?^S3'^հ+[Me=ulҙ>KgZFNYJK%\Px=.ymM6S6,3yԗVL+kdGgqGr2-Uٸˬywn)f2)wn#i34)+] 4mØNw5nƇ^@cSUγN& }me[4[C[O Sq+<z:*ޢ-F{9ue麀&aȏkÜ^,?N\O,*fkN}Rͦ <#+O/wEmsG]OⅡCVhat3"hP_ZþM\>Sيg"Χt:CAz0{ E;^ӵ,'i#.oʨ>{f|nNl8 C/.BU,H.6bdXFa+d殚1D[EpA:G 2nt Gx*~6˰P ~t)<h P̘pܞ  H!?,m-d" h|"I'qpL'qqȽt,a & &؁ h􋸔v,Off1n il *`s`5b)DN4H!ݜb'JOgeV71b[΄M'DM1I-FEF/7Xe!A dMD*zMvn߬t Nb$kV ;oF FPpL O,< iJf8Q4'8 )aLʣ+b)$(%R/rR4rMF4rL2Rč)<2(,+3N6>ʃa L:P"q\-Pk) 7@^2dNp&PPP ŨqdžޡfjR! D r( F@ X@t4R4 .ǀ $LR 6 r z7` b8s 9: :";;9;8|TDE\t3Z%qԈPd)ERHsRH# 4a 4N$mX%NCM aP  jVC%lѯfҤ_ܡSCVdy[м$U$.% ^SDgjc/35L2%2dji!,gg^gȕ3gZvb&Vxl'+%|"!wXV "l&SzuLULWzcPI9xi juG d{q%eWvel8. An=8 z@"l:nJ&U{D3or 0Hlڴ6W 7xQl'#+2H3/_2ɃOi?q.3ujRW*S%47"uW{$6~ފqJ2fyvAւKe6w_Aňu (zޯ >wH⥴g( 5BJ;ϢkV>!#(43@7?  m@U.Z]u! !ا 磮YO1K#PMdE{baOOG$,޷A,=>ˤ5u}??3/' l{*\ȰÇ#JHqbBf4mCII6˗.9QÌa괘߻Vp[НH*=;9/vtիXJu $ʄt]3ٳh瓫׃)Lx݅^j{Po_@x;`w+>_i':5Ny pƓ#_7_Dƺj~[l[-,.r7fqlb|DS85UP6UR)}sTvjMU Vh!Y>tP](bZRCqycWobqXb;;ceXZ`Eڸ?(l IN܌y.2G`~)fcH&o]I6߈tDL ֩p_垀BT7AN?]:`uM4PuEf*aP 5 ]Xc)H`}VCEW܇}gЍO"5U#F SN7,QۯA ұ(6 үaJb+ЖJ7tn(5^m)}yk_lIaоHk#A CO?upл9 *:\2T3J э7S@?,}#r·%\O '-"v~QRf?H#^' ui֙6ԊN!Y u,Cu27tU|m8\(8nޜ.䎗d^IFO9+ᠳ_⍋N䦗^9嬯] |cF,+H}Q6C,47Il7.8?_%8@}W))vtHJ78Bhbe;g (L%7.i5lCdşhu^ѢM3„$3aBz^#YRBc7!mBw+Z> a8!7:"# 4 T\*PAHD^"B"Q-)Dm| = o)+xHU&<I }>аAfs#!=%aj =LS;:N%!#AGN$I6K-o9)ԠpS%C0GķW1$w-*DjZ̦6nzf4q%4Z8vLJl`4@6q Qߠ ;d"r"=K!J l"# 9YHJ':2M-d|ֵF6Ei ,ܞ2cb)~n),RIKQ13@e"ujl18i1p VXJֲhMkZ[VZpmZָUwkYj`x[V:cl=كРZHV+< dpfս(Ƣ6s4*̅Hf4Evg9{ȝW9)eܬiZ04FlR3OXl @6FUt#1"*!U;Qnt#o~LF `'v} Rÿu<6O GL3=pfq|56*ώdހ.pa{[EfbfSFG h : ;2Wu[_@f&Qe RQ(ME (P咈BR9jg…X3zZ&p'7mhu:э#MI[ش5+-NOӜt5# r~hO69Kӯg kZӢ'@+Mk&FC?0,dVf IR0k@GMی*D3OYH8RFnGgA3#55#w$/uBF̡J3'ct̞&5w^ֲm g8/n=+Vg 4!h5l&xv1L0BL4u~e)sgt۹S~w#p2Efnq|f@5yÔ? ,4h9e:tTeqȔ?ȂZ2:A)Q^<R"4aQwN(}N#uw.|gnBFwAeܶ+1޷؀m+ pZ:lNhW 5Q#>*Rf h{mK 35(?E؈NfljgL4pQ CxqD$7`};(. ( P~lsp2ܸX(J1Ř D 1栍1Z Lr]Hó؈-^'%U |S{ p'%'0Nc]7p)05HPov ʨEɏ;ؓD.vиLK..Sٔ,89겎KvypvC+z{&XdJ89*o? 4ɗ1)gT Z6q"w}IA|~( x[ٷ+79dvgh1nQfQ'yrm@0iwP!31 S^DSx{+x>)5f!6 @&^xsLR%:2 {8Q$Cc$G f4 7@l$p~54f% ɁQ ;}4>X3Dy4ɗ+ᗻGS7i0x(s֙wVgc=XhKZْ9|Z*gNRQH\s#2HdJ [,Kf)13 &f&ʈj*qC!&iqbʫŕWZ! FOf{h 70 K 崋K! M ({6kxg+]'*y#+g;!ݐaa;[{ۺ)&`<9b6p +2:JYZٯ?A{BI;5x&)'%TKYd:f ^9PD5@%VVX;V[{ۿlKVnu/(p#>bp'(xAHhǫ7۫2Y)HʘkP{'ac֫/,eZ Bb405u"kJ i@GzޓS|J9@Gћ/2RqJ[),ok@ b$0B} \:*6ȇȄȆ@ȐlɗwSCߠqD#5P Y/zK,طYk'S(?V]XggMu*˫x L;8`#Ll\;R2c#dl^<+ffp K|Q{7*iU f${,\yY6ơ}/1q1h4s/s9Cz"=]m !3s.1* Ҽ()PZ "!loaϺA(R PQf-SlrfVE%,;.; &xv }/i&im;8#Fb:oNehg o}A(]8BK|F4DOe;RL}!]%XόKƊcWM1|n p<)r$9OMKZ!/:&yx +c\br,I{$w#}|q)L+9= & պːΐ{\7q9 u+]P:t7r*<5m:}^8^.U z*~fDJXK K(T2)*)ޝxWݸk RFB$Z:(.# 7wb^^:-S@q:u>9=w>] j:Er@hh(azAN~G->qm!i̭LTڥ!YNջذ]#ԄC +%b?!nԁAp΁<ذI75NǞsc\m+x7A3n龻i>R9Z}aC˘ <+C~HJn":`p$1רs эF.xQ3/!$c\Ú"|"!! jC8-RBюx5{dp_!K;'cǂ⿚#_k99"B7cffW#"(?)xͥEm<W@c3M sCFATg &AvR0eC-F1y'0ooDS6'4,90?E+rbj//-6%>]I918ƒjd|KQ8Wbա=Kڡ>K.68 .Pa$Xf+SkR;&~//ov,1rP/E?{N`,C $n;nߜPoE /&CSL%B,P"B}AYH-/|gr?IœozD*ITYnWaŎ%[6lR'8j]k[qNe[c1m/նɰ[O޿uB%-J;oVzH)ɡEƬagAf5X5:[׹uK]ZmэIaj'!7&d`& mD/8Cu9laOj3&?3z_1@O->p>C1;o,YƈooZX"Nw #1 C,@Bn>P 3dA"oH' p@ od2AQ_d THj֔37 h9 M6N,2?2 Zx''B/RPHGE 匠m4tSN#3r,Ц*иBfB,k JKqSƚۑo2񟌼odu핻5#omI}cU5dg3o&55dtUmei `Xo} .zt]m)yfj1RW-`s F/MTk"Zf9ӫNoyhnF)T : #M:D"Gl˪6{U ٌ plF:o!"gnsk[9w wǹHi\8s|(WFǘLUG8Zv,4q}Jr R>}2gJiok2f{ "i>͵ Qܩ,s]F5RزMJSSHI| mT*AgZ"-G8"C<02z;0_Ӧ0'zcLCqi!bāp ID !EQHiP2)LӞC!A" zą^(FQal"#)V#bC ɠmv4a 0nvzHfBi`&Id5\A W@ǧ#﹀RL_ȿ7*~CC4",\>W/;zožLmw Fsp?"S;k:?֫;Ӿ˪+%;ED@S=CA%{34sA/;A+j)<lpnHm{>̨ S /A !-ʮ/$+ 4)C?;@6P4##{k'v臡'%tb @c*[C ;Y@ۯBA4 J6s=[=N36Y l`'B6b  ,.,/<4VBL=Sf=R0CFSnȋ]0%p™txB4@(ԊcWj͒AKc\%x$RD{S| 9V<0{ ';@̊H-"-K!*I1Ų! 1Dn"س-y r䮬#Sh5¾臂!Jp8*1A$l|4lRD7As; I ɎK JɻLd˚Ȏ 4ov0Z(#-n AǣLB p:T1%Z, IKI0L8Л8|йPt8Q̴=TK-;Rs t*QdLPQ%Q4QHMRKIpQHuLیb H>a][]cUP ˺uրE;7HP_`at, 8L p2F+nnb~b)&:4b'b-b0>E1Jzb0b5".fhE`hAeCS6^ȯ YnPHi`@i!,)dPPdQ>e 41 4r80l=cRe%KnOsX;`d\KeVN]V#SegfU^finfh~ifjfkfjRֺ2G̰Yΰ|"KgSgwngxFuwzfg{g|gz~nCX^%嘤USh^Hkhfh~Nhhh舦tZB~] +&Fl=VD>9eиKނPoj.j>jNj^jf~jjkXoІTjnjkkko.k^knkV3ykk֕o؁[M ,a=5mզ.N֎vҦmHmmކj|mo n)@mnn&mi6oFoVofonNon&mvnVѶmنȁЁnKGcO? Af<$;iV GЁP2h2p'h&qw+'hqqqq !7r q$?_/)q(>+P*!*q'$!p50+r'Wh+>&Ss5r%'&0sD7r,/s,grG_ /W1FGLt@Ng'%0s/5t"U39/YtXuFwt2]XrW`avH/--s7souJ?tItHD_uPMspvqg5!Lu^iji^My4`DVl ˮ~/Gǭ/Іn kkZj/jx?f&Gyy^yxmЁ膘U<^xppK3xcPCiWx Nḃ`@9@DWnIo( Q{KW~{/{{gఋg'|w?]ʷa@2]]{ȷ$" @p؁NHD@|G=>EȤJC $qEVħh"]=W~Mo~_~{~~^Z>C4/7??4thAvŷ&~s.!ƌ7r#Ȑ"5E#Wlo)&Nj,>Qzb3'ҤJywی2j*ք5chK 5+ڴjU-Q0e"4.^(9d2nEXBmn#ߋN,1Zy?3F[r̳ν8V(ͪ~WiԲܨfy.9t؃[ej5HRh`;H|~)&!%x(Ƨ;DA^/ e҈RkNpxT*[})騦 =}Su:oiL(QܨZa/\1_O%>6Jt217mAWlӲʼ,O?AƢ7/l:1VAJRRHܓC 55Y0cv 6yqk[^jbq[8wpmw%}Z֖wXx }rtrx~CaYQWFK>/d97%qh(zM;=ƫeMe50e_N W&qU;F<yS_Jǖwӟxo&_>;/xb~SA۾}Ro4aQ;;XuRPf58dv T]0meAD-fW ҷڥ<_JXNPԸD'p"(rB8pa&B'hi,}bzD0|^6c-\i&q9Fyn'ó.ʑQGA8d')P;Ң! 42ԯjK]xL%D쀗JNؓFy:8u3@*h`C 8Dad!BXV:h!?W%+ɤ6Z4lE\B}ƛĉbB m(G]Dhj=Zns&8>y*2%6L-mJirLKi2. L%G2JyT= A53tc(;S?Rh†;fIU$LePЪ 0R'*:-# U Iuh0/JҹNTASw9Ă C9i` LA[UeXUӭTO) ~gWb)PMA_۳V) PH 5sf!H)j&Ve,]tà4>[ۍEI\ʧ3yV>#u_䎑F޸w$W."V #D:.Mkf's+U1b2EIʰVdY.k'qrZfn(†ҷ:,V2X/Z'gP9'u)n Zvus< I4wbGOx? ʶx.GF ,dXK xE1):ڮ$Asβ CO~|P4$\QMiRF`_adCLl2Xm fCw dp"4YS4̩t gA]ۏ VsǙ]&gs rܖf w/߳[ږ8C;9`x!Ȗ҄ox:2#ll&^Q`Nr uQO2R9bl"j{+\dޮ=/3it-\+/LE:aA\݋Hoܖ-ja8qGaNTx΋Dz$|Iqk_vצ/Džz_V'oxUf_.:Yter_:~X94Cxr/i ОyߐfF-Q]TDJy͔Q^XԔL\]D%f억]Xy ^@˹TMD}*1mX̕8?@[/Y2 KxL`@\) ?7I:yYdOp! "o!H) tE*/9D=MfyC?iEbv5x JTpH} `NCg%ź*6Um a]Y"%XUK="Ea076}DbxC 4:DZ^}! 5#Jblq_p) =M\Ȉk7TëjZ.ޑ<`=ռyYSa ڐ ed H#I,EL%K1ٕGi6UJ$7DI>B˼F1LL70FCUwD,;hC5|CТѬ LNl٩ڕ Fd[y$1bKHQG)N\FldF|``&aa&bJ` RP Kd(`B IfeFc =^f`ûdfIԢ"ev& qfbj&kk Ik&m֦mjj&_E`n&p'k~p'r7x6DD7ѺHI5]d\0c}\ 0Ghuٸ \Qz'Z-N,lVw'g \y t7lÁz7|6'q6z8(.hJh2j(vrhh(qF*Fhhb艞hhn聞V*h (B(nh)"*2ihh B^FĂr7hC7D*(R.i(ViZi&i:i(zC6h^ij*JUF(5th7hF*"jJf*J|*؀@7\C %y]l%EV1RgG GkJ}e ||\ذZPX8X8AZj+zkr~븆++빶kƫ++n\x @:b++++.l>FlRk\|@jRÂlÎ,ĆɒĞlƫ~x+͊Ȯ,Φ,ެ*f+jxH|@ Ϊl6->-B΀| Q<]XM RƬ2فIm!#1~[Q-Ɔ#I~Nc~C 0Y74HrFNnbz&ՇqRnn27@irmTLnnpû\QdήrҀs@7HMsp9Cm0ʪ1ܱ%`]ݺְ rޥ| Zo ߖ& \2Z 9%~cT"DJ;| l D7hP] 0;$m]>!xxjN~б~-άov 0}ް[D$?PD5bF[(1/q?GqOX@13qKq_oc1wq9:6JNaq91zı1ӱ1˱q1  c r ##72$W2%_$g$4CĎPfvЉ))oQ))+2,,r,,+_q601e(3111 23332?2;s4's3 |RpXC_zFfv0pժj ; HS ӳ8_z=׳J?=eJ7䲰zCۈCFCCCwDRtDkDCF{tGdWJH4ItKs,}`KMsMtNY1|EK uOtQ5Zee`5ܯ{w3t.:UT} .]ܢG4IQ8[\jP y7LpA3-:A"wY7P$7rP{J|Zͷw7{x~g_PXwaOc+NX-[x3`GwQox[)6wgwh`$Bj6j7j8?QxJlUo ݚ&Yf󶳏37T&Jy([X5}G}¹%/<Z\]i:!KI ܅9*9;z:O:G:sK73%;*:*2```#!Lo{|F9RkQ D < HK@۳ ޮtw՘>t~Axp~=W>_i >>۾/~\W0>?wC$=o?S4 m|C S%Z?3[ ,)VxcF9vdH 2lHЛĐ+YtfLY6@V{r[GPuF5O]RO6:}EѤIju U?%fAa-,ZjU+Wr=o +=OdXAv+Ie͕9g|3fОI6-ҩC>u9j׹_woÅ7'vzğKN;''^6>W';Qk_|?|گL A (9z % ;:m$Et!m1 v1J,jڇ)gËx|"J GёGM +'*#gtF|ҟ"*0i9wZ,7>4<ӓSPyȫ"@}PH[.C*buuhϋ)!r{=CdvCo??uwofo>MY7TL"߹F֙[ vFŦf{ " {qE^\)zto=tDiQ$,?,(@>ЁlGi ?&q  (RaIAp(,!> YB s8Ѓp ЇFL"DʬKl@DKt.Z2 `\ [PV@3jZ*C0IW6<1]a҂n#Hz|cơtg)Z&'u9ި $v.IMO'{r(Q*eJe'gZ&gJ.OxwfrшlԦwT q6) PN<:dK(Ai:w@ArO# ,%oˍ ?Չ! ipwdDY.^ to Vh;/PaC4WL CI0}ci1@MH20*ei^;ҴC67t:RX*QaT*'hjLgZӛ<)Pj6.j k̞ehQ◹ceSt7duIcO|C 8 (MZ=$ClZ.,t%ىZn Wxӛ"ФW)Ⱦ`è^C3? +׸;r+814jp;O.Mv]&cvcOuHU'lAMl椞FVT`!,bk͗НL>q[` '{J' 8 1 ^R.1?k)C.`?/ENgSfCazX҇;b Qֈ D`-+]ot,Dfэm9[Bcވ;yTƲk*Wֺ!A4},1# @L#h:SS_oaCoD̫,k%UFlM J 0luѲ*iQ> 7Qo/ef Bܓ'D`pOqrs[(ã)Pm9^'a\d2OrZpYğO"Gbsc\hήC.q.91zHYc\Fz I8 yK4,C=;G;bWH_M  #$]`f X-ln#w+ ln#_l6ww=DR/e6G<7Uu4I}i! ?"qa/ dbH/+! b[lܺ , Ng Ό0a FH.Q +d[k > ^\ @|9J'l0 6r2i/n w $c-O0'`u{#"0]fctd fBՇqȠ}Q/te5`/nP:e(6Oܪ1ϵ1 .Ȟ ߌ Q բDx$cq}\e,2+7"ѸAvc#K`#4N3#'ynt3R'Sm Q'@Q6v I2@b'jބ!Qp#i+r6 {~&.Q4ƒߐ *H" "  +l0F@\F9$?vs ɺ$0C kb6,$lmO1L:'4a<[2c uFU , RZ KfU",X5HZ!ށ.bscR06ށW6NI r" |;t66> Np@Q8GȆg("\:! 'f !`Q5+"H3#UHYkWy W( HyTd->DfBvdy,+L5%E*-hSE!hqh;cC),DWN*O2lD8,+6Ձ?:ԟ& -Q*4rB1ն_SA*a "V=PHJOs VJqqTc=3rs/V(X)GJ B!a=PJEs1Fc "L![uR#[)u\Hm'=/Ogq(kG1&It̤0WbQ}(sD+#5o9#P "dcG%u BJ+JbFbdbcT6(@$*vrobSua]`#g)VN!,86aOWJ9U`,1";̔ AhS,M7r$o4MêbwQmx1ӄ~0lP 9r5 Un3RIRbW'"E BS W-"! U*8rγqqsS)G*(7rK$g}ρиԐ6Ÿ<(J_83れ'o%wRx1scB&P2 "*4H]S:Mk2x[/-[g}[bd=7 K$#ae"$HdV-`t)27d&J1!:6f"*pxKcXvf6J .vAWP⋭2 ́ bhzk'`',)}AiH5'qnPlDU/1-U u%Q5G9w{r]3FŨA%ׁXo=fڤBnc>Fr8s)*QcȠH$Ơlmw|Q˗|Kԥgfs HZ\dn,;IId-1K(s":EgrT⭥g_l4UW['*Ph*X&K@x{\*eX9,7Eo4 Rj ѼIi19"b"$܁`;bG" S$4aqcmk \]Zk^òxk`!x("gقns*0O#FxƽD'8 Ԩ(KbpJE"Hp$<Ҝz0f!vt vl4~\1^ggxI FY~"OD9؜zٚSP'<{cQE\_;o!^@gw&+/3]'^f)/'%?}!W2ijxx Evi].i'z}Ѓ#N\LnLgZ%%.iU'r|QNj`Z * ߝ=}D ր޷ Z` ]ݷ@ > Ԁv` X ~) @ `f}~vj`Z@ < X րU BLäӰuRB&u0X @M"{SMb.|BC۝+빻r)>ޞ^~~v?!%>2Iߞ!zzfha J臾Q7<>zen#Y(ħ*,hsO/۷]۷]2=/skAgң ߻(G6ԫ'5}x^J'6wjn &^; u{߿:|1ĉ+Z1ƍ ‡9<2ʕ *dݿ3Ό{͟;ī< 5N hTVxC/̱JdݷZ.liYtTTϐskWh?|_ۃ:1Ӷ.ݧP!f!'9Xb f&=-%xyCB.([BrE۷߾}@0,XL.cԫST$Qܻ#oۻ;Lϻ/mWoGUCEXmW^nM}>;|eƘOrA_5HO:BSSy).ER{Et \X\/ G}yR|8TbD.?o d$%D6ܰh{6]BXZM8&J81XV%Dh9; iWZv_{zҚ]yÍHe(A&QM`J7^BgYYC8h^Bd>r7H9kLS7'v됝;m,`4"7g,E5䨨Ji,SU.xnx(55X;j }ҋMJZc_VT͉Kr.iOҊ :\qZ L^L\I[ ()\wm*l΅)PZ\cuZW0`C<"]7}_j1y$7d QzoeOJ ,QME+\we8CB|ؠ7Yd;BS 3?欳oGzExpo4WM vv-5=:`im#fsGbLL{ MHSjiW6B }@)ʳUC4aH~ '(C܁8&kXGw81n"@p~XŇ/LesNGHHCnY5m#&aVoiFl\R񾦭i8):}A3kM%΋Pvx[27~#/}NE_K&Ȱ#n|CH=Q> YV<̅ja}FFe _V`Íop$N0)ʄ Y8I`L ѠvNf(ZƘJ ~2cb.wB@wc o0t K0(DXB;昒3Ę5V7US7=B k.Ed\Z$T#)0/ d 'Tl8{ >h%6Hk&O1K얠z:!T#Kї]Ca61$P2< eӛu%Ciz`z2D&0qbs޾;9\O͇ä0o.9JknٮB%h~v|`RqT-~b[DYxe.QΒ`kF?ʨ CJom`ڒ^x^̉P" \cAگ7Mzo}fZچHjcQA>7- RqxG?Kת9+2an͑MB[Pq5`Ѵ?W$Ejh(7$L{WB_r('ׁ8'"kG`BL@Lh60 @[Vr]wx "4yEzaYI8rWOd0D oqz{{qzA&!uXHyUqow8t"4|h(xh{[WUdLJd@2 QX~e,/jO}E_8xzgG32s(׃3T\h?BE4h$*_rUAK &L"GapA>PT:ȍ$r$CN2sC1Ҩ49!'ehyBaF 0DUrDÏizP?dP%,ۡ(YTIi"Giĸq[1ؑ~B`Ȑh\"Ij/)O6LJQVՏj @oAӓ!uC2]wP&'蒀ihxy:Y>1 #wg)^I)D!?qwR/R~^YW$)%~~ r@QQjI`3Y-ؒ Yז@w1T~veod4AgT1&WKה!?jI)I" ^:]UG"Rx^?D= ~;QD,.,I{>Y&Ǜ^IDS/pљoo [ DKMlit4,~-'hgM]9-ix/$I4\ʩ0-XB 9z9(#58@& D 5L .LJx{%؁wQZ'T:W.̧81p'pmK""BiDܔwJ5ڞ0:#)S%zd#[~A"8{zzO: qzZh'qjaA"*|Jr٫Ƈ5;%*@-C97Èqs㹆,%"7 T_q؀!3]jx aR*\Jگڪ۪š98F:OY``[FDz8tK.'V)XfX\YjZE 03 zJ뇮J~&KJA [0jWj*rhP8QԘZ`u7mKyۂP޲?*jAz:EJRjQꪰ!{kz Kʴ({z-0ikEwI ۀ JpJQ 4w6m+i{⚇"j'Jp @3[5 9 @˹W(MPS䋺 8Ѿ+髩'&q-lg<4sGpeCP۬ L'KW2YBI$yˣRhY@|`~{@K䫯U 7ܹ۸8Lz9A5';ȦIހ#AA*6K+xK$-+ J) + +M  [-a `"[LP\\ Si:%%2q^K;zJj [O2DrlI^ A=ZIMJzCq49@·8!!;0jpēgLC!ʭG< %l:k c"l [7=8y\ZV%BT\AJ3fB*(8p@a;O#_H7HU,aw'܍#hrD=r7DaH#! i<8|xwqإxfWmU%sYm/a0 4J!e0C)1-w>!%0Lf1R٪= ]9B5_x:{5:'"IqCt<.g/8]؀MsLGt 0}h\ 12;}( ݹ']ٝusx5$2ݛY96!I* p+"Uvh/DQYqdQHY͠J#4ս-N1Sjn1YzI N9c DK ԯ̃7rY?G7:@lY`N7eX=RU=C6wO|d8=U=䢣ʳi %C桹ox#pg}[֗%7t0G}]ǔsF}ge}s.9^wn5<>f,"] ("샃 Q65Y'by%h̢#GBb&ߚ%,FюlP7qfNjp[W3fpNjf,jW`POk[o?,`GfZpMXMo`rrE?ckgNVE@pW443&4Fc>g@Nq[_@=89`4c0AO]܃?I2?8ruˎ(|\m d@'882;歹GPbxq^w nN0okF k$j@Jj /fJd nn'6o ͠ ~K8B 'lA!r[[7=pБ - zfgM=}TPEEt;ôTU^ŚU+w9UXe2-a;; ś׬ۮdحϭ^Ezcojx.&ӝ8zXfel`ΥMlO[lڵmƝ[n޽qW/txlŲq2Ч_7ؽoN{c퓲)+zﬨ j m4)ɲm20C$Tͭ֜P1ƪӰğ.[l bGD*X H#‰&J#4̟}fzD*&,!>g|l?(-n0,3 Ac:**Ӧ-54B-QEQHu4J)%2nRQ;'nA-4onjl >m|V ;e״F{m-K%X$1eo5|թ&[p&{=f3{B:ݓ?yjL,Lh;*wZ 4)nl*GBoTP1腮Ew@r YAήR[u!u.֋f\7s[w~6ZQZ_7[M/yOBg[mL@>wDRi騡fj,ƺjk}ggQ`Gio264`nmQIK LYw>\,Ia]C~46k)l0f#w-C7\/1iMIl2F'}oU>v<'3r5qo^yyGQcvֶa)ܖli3E;)ڱ(+nYK^Ž|X dǺ(?>Q10"&Gsb:Zw儤eҕV:&"?D$)5i免.Bo/!QJ), uxӉצ,ىA>'myɰ$TbI;!`}$E[kx1TӏZ *HimNVԣi:umfB)M]\bfǻskN%oGyR3ΌĤFX>fy2H4y&gT9Jܠ U@&*%pOÝkMVڄ.0;EZSh>$izBt{3f2L 7nq|DT9ōRt uEY%7:nUIZt?ӄzg:@B,Dfâ42NԱ~ 0g; o4DŽ)Ș<1k"'vu:M)McwI^צ|씈}&V޼x,IR.ʪJ tv=&`$k";#oi1.dC)5MEWnfSUIxdlA@̈́C3剓"S1 {>^xB^d`MT)Mx=Jmo5=kb1QEJڢ[ #YM([Eit>CUL;ZS)b>Q\qFȒy,Q 7N]FEd2OђޡB_Qz61]\4Զq }8.nF`}WZ1$ C&A=If+{ JW&llhkNrlg[͍ywў;}mn{6c3r;h l jt+ exkpiæ&yxE ( rFq 4r>Ũ!YDj|_Ўcs9:jt. V /d9pZ0D O D<hy Ϯd=$L{e8I6%+y1Ǝ]}{v%ߠ7f XTS1 ʕDZN F/C[lO"PP?H.l.W鹼[c#2@G7^y$q]u0%'"MJco4 04shOc~oP<'?S?ػ';!Z[maHoH-bK1ӢнӢ h06r@Cm1 #q:v0$&&4 !]T# U۩A :9|C9ɦEԣ&[ģ:]s!9a4 <)xZŨ1[\]tN DbV<8Q"CFSĿIܡDQa ;{Qz"{*eD\c 9)wdߓ)BY}E+0l! '^[@9Q<޻r#A1 '^-Zt*)'Z8J⃠[s.K:vt!*,||]L9HK Ba$9*)5<5ux"9Mʭ# (SHL|PJ͙ј|{ 250j9IIɟAqJ;LSCcQB2J\J~h2$.At˄31&8|-MԁŃ$"{YJZ{I,-ދ$5\Π4L ̓TLKJd#VIΔs>G ,D&ư v tZLOYJtN[qG(>2G0uqG)hbNI=|P*ǚd %7LvF!|5%If\Ԗ+a3ͬ"1Qx2éDD:">ZILK9ۭ3ݕYNRҜŒG^)J}c}y%vQ`zkD)OmkAQ,MC ` s6J<<O\ )R鲌 P O<Ԭ.$wx!jBm$9HqI!35ˑA&6D*M9cZ1"C3uoHvBQ2WHKĥF%*KAlNLN蜗dL\WAPu)kZ V*G' who1BO.j ;#aȖʸKI 9EPUd~К * ɠk`WI'F1# PvTj*Fw x؀L֣͊@$Qu$ m1 pi=kYUdҩZ''[܏ϺuڪVW/u9OĝH5ZstTVToZءֹ,:]a'|GMY,\ ҼeUu[v]]MzUqB $}}\z:dw Zl'&Z9#%u)%rmJ[io"ך[Ԋ#ԧm$G1ىSEb%;zR Yv|@&˿Fy MQX,e5e Jt3I ]Ġ aQ(jt=QTBFZދ1t-%-Vkn4h2n@>@Xm׭!AIn]WDPk0 E'Z#_݁!D=MI5GV>:Fid\Kf L?1[a^5D2`]FBQϱ'\ m-=9v-#ͦNkMם$k-P(39p.A`T2{A=$(g+fx]gvIwnzgYIgPe(5Z va~%0vn"`NHq#c=7]<' [qTlDʝe=YɘlЁnֻoQ#;C"046 ӗ[И6Nꭚjs*^j%HJNJE&Oɕmnx-Ae41^ ^ad4bV,A޺?N+UMH X$HK& ``0D4@' %-bfN$nkm21Hwzhގ~Nn֮>nھnӆ&T -5h2'p+e̒]G4qh#h3*f"gY'G6f_%#-|mH¨Y+Ș4q eVX|_G+'0spp/d)s@JBةlI+A;x>f[1ixWKyw؆;22 hYIYȢXO{X4K *VN֭3 BAl ^|8D  w빱gɢF"Mt)ӦNBu:wVmu+׮^n*pN`ϢMBnP#s-ݺvTN7nDf+xpә37,Kx1c9hPn%ߍfUtM&q6 o߶q,[@F/vߦ-pvK 0>ȃ?Տǭ9b1vb"nܑdxCw- 3~仇7/çYVCx#D{#} bDRttDpsE\L eXbRՄf&"Z.X?nm DXN XeҏG"%l#OvuhMM}!NuQw>k/\k޴ cNcJqSjpNBL8FcfId$wyg٧@,qhhk<if| 4Q(yMEnܴ%3~,~ OmvQQ^ez-bY\rJZfA1;TUe{c^ɥ@e-_C7M qq&%j8Al6vma.>f>A 4Y!,fnQ/_~{Hč~zKCk{moIOĂ$1 q>Ԓ#QRd= qhR dVIJ^H0¤~DT Jh+\ Z tE͈$ Ƿ#}m1b68aTs!0}mt m@@oIAI"(QP@vo")`7.h rYbcPHmC49҆%P?я2>!Q(ƯÍ iBKVoiAOR4M1z:$ip4 mf+=7NmLC+" :blGTF`hiFQ0v$A< -ͅ\ddh6L+~9DQG?(ǎCZˢ3V!s+?2ю !`(Q¤J/R)I^;8rrg$'@2E=aO %~۱7-|TVN@4r։Ard mA ,R40~:FCD"&}$,YMtl&a @D1dKƷm341H %}& n >AiA4Ja1Up]m6e.Rw4zdY V$P;TuuEBqbc4\V%|x#&ĩI woX7[ *olפ:!-?A8D +fʓb832FI2ȬK5mnؚ_ոa81aH+y!ɹF!hM#f+ryfepyAX3LLj]G>f6s| <źVüo4|>qTAoj@h LrLfi$ y鲑hbf@,.Y4a.#: Ys^FRfBFgMnCx(NdLHyؐs@Ԇ?$;y4y˴`Pˑ^7PnQՓfwm"i"heۘ3Y"iy*.bm_Yֺ!o2| 4֧T*2bڐlHN6*n0.֫\NPN۱9Cqi /u+=*r(&'݋k-; ]V6玔{IU xuN%=Q؃>s ҤFdA3+a -bGx~us|!e&bcl uSh!VK
c#^e ٯ%A)o @F0_P"MF|-LJ#An U.Z$JB 9760PEbk$aeTZZ YI߉$eT%)rcӷbeDp&Yc@8XSOH;Zc"eɕ!2}X%yU e^ٜIX"tfTr7x^GR[]?XI@e0f-!C n!o q>q;wafr`t`gHQߋ]d&Tͼ[9٘f!9ɜDP5Ei'0Z (dxdXd1LRk[X T"mAy)5\$dWJ^XN mh DŽ(Z%ubrL!hhb ǔGxY#DLXUpR:L+%[7JFR> 3l靹=[؜J[a`#qTD֥%N?(ԇVpD=_HzG7rIpҡb @Ī>|(#4q~w>")EEDIW֪iCV܆9pb,d}"l]RB9[ҡP]`[Al\e^49^2ln, !f!*ԗÑd}DEBpxLhe̊4Apqepdq[8e'$mDpH@cMlV^Ѩ0eO[MV6!ƚ[!F3N,c;X K'iH~,A\c iVdZ=69Rn+߼px}dndLCqMi mJlȒd6 L9XL^_7ڣ0 4p ,.YDHOBHԇp { DBh4id<ڎP~Û-0e\RQ*g]$7Dp.)M"ڑ| @MؐvG־LیP܈5%Mf$")<]^($7m,JW#'π 4͘%ΠCXR!SO-N.-*j}$[C0sZ_;cVAFkM2Lz%d\I){2^47̀t7TlD l@#Ymݎ pN fT 4Ae 5(twZ? ΰ6<kHʬt~}\VBPDhmDe=kGl'F\p:VgM3kT.N l3PK68y+rϑX$V#Zmad FE|uL LFUǫ g{ԮAīho70Mz7a5V3vO8oe0%Q6qLؽRErU>4džG tCI|x6Z~ ;=6Js3GMà*i*xʄkYSzKy`_\!\seR{x!ǎM1eV_!N{wv;0|o? Gc%:[cXM/Qzgi['a 4Xc[z >hHtgc z>wQI|mq9;.7u/wD w~< ENhT$FtbCyC5-DyiI6Mh@ jwzze *2;1q%{⟇;(;lzeE1kΙ bhļ#s-eSSJ~}lS9;e{les>Zk|&2?*[w%w#vNˢx;T7'@8`A&TaÂaE1cGAvdI'QTeˏ$t9f͌dԹoV/(OG|g[сC9E:u>W]JŪ0 ;commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/images/uml/prepareStatement.gif000066400000000000000000001363231472045345700311610ustar00rootroot00000000000000GIF89at!)!11!9%B!JDJ!B)R R!J!NZ!ZZZ!J)N)R)R1Z)Z)Z)Z1e g!f )q&c1p 1{+s)!+13)536R!N! B!J!R!Z!J!!R!!1!)9!)B!)J!)R!)B!1J!1R!1c!Z!!c!!Z!)Z!1c1c!)g1k!m.k9s9{9{!19?H)R)!1))R))B)1J)1R)1J)9Z) R)9Z!9c!9e) m)/k!9y!>H1*V-9]1 f15N5BZ5Bc)9m,@rnI^`kkq{ƔƜÙ˙ΜƽʥΥҩֵֵ֭ޭޭޭ޵޵޽޽,tKOa…#BDK#okH?~Pj׮0)ƴ(&͛3sԉ>}Νw{*tӥOBew$}UYf|+ԯRz v!ۨAG3ӘݱxUxr`ƌ[߻|2/ǎ#,k6xuB\ꯝç;e J~ $xF~\Eo,xaǗf5t 0v (;c{' qߺn%hw\sسew7yug!i zR;WnvWmWqM疅m_]%8jz-Bi iQAumF'#߱gs8czYj?c;htډFɱ)ob#nIͥmW*z~٩(qDmIB 6PUe_kEaI Ցs`ΑmЬ)驸:QVj걿;`%ufY\>!m+..;иkZ,\'Aoql '믿>]9@hȪ;p 54BR4e2p0If/z1 bsLXouOWQ-i:ITW Zjee\X͹I*r?lKV_ǍZ-7KZko\iZM]g_!-Ob=7z7܆8Յ}x ~xՆ'](4`g^8Zw{:^.zޖ5ުkuz~#֨ε?"`s9)YB;ͯ.w#W4oJo1 n>7^{ `%,]^F2%$IRӔd{_|/yL]RSĦ0S #X Vd#4kAԩmLGG: PD;wZs (( *xғ 4> o|Ffâ FHG*ҒhGҔ^Jld#7IMӝ@PJԡh6%hQzԪRVjIAftS=RUh=Z:RԦHj66O|dh^ٺ־67QC\ZQ:}d RG#a GFҎMjWZ+ (S) pKE`#؁ FpZM#La S T&dMzUk@ h`jXgiT037 0qFL ;&E*o pv;N! L`!(cHqɡ 0UbrX2r(\f r3N&;KVƑ1TS@2.{9a1ޠ6.6L*ϧ0iINlcCeLg1 ')ƅ'M/,s@ |3axcԣG/V ^իu_MXԵ=gX<P;;$G@1=~ qОueMZK՞m{[(nnn7-zǻa0Q7Mo.nh"̞GxK򔟼3b1ayΛ~󨯼5ηZw=q `qb`.\ {(|"L6@_=zuQk}CNo|Otq?E{uwpWa0aI{kw׀agt(x7`W j lpv S@H)ȁxX/1(3F~picbꆂ-+HChHGhMȄFtV Rgby: A(E.vwu .h% `uF'n1b(IȄvDȁ{5x`h FjgLG  jtl6jXu~yGo@X@ lodR7\NJ芲XWtx#A p(Hxv@~FhP tK&lxȸ،8uWWCha@~FXXxxP{j ,ftHHȐy&nsl Y0 aHlζjqφ DPX 7FSrb' SG u*iV؍A(Wl`nDXK XIv~ht|@Nqɔ+\@9yj^_gf{1Ћr wYaqH_gtH1Q qAУpJٖY(ntSwt^Həojl@W 70 I|S'6JiК@l gQQttXjɛ)YJ')ٝ qij깛ɞ9RP%ɞ¹ܩ9ϖ jéٛvt *% V  yj"J* I&P 1*4'{(*z%z'z %I{=lcؐpj ڞ2-z:ON*gʤI3.ʢ#J j> 'P ~(mJyY A ej('wpfZ|9'5DI雀JS:+ڪGn>zgf8 j))z*v .IV`ڞjHʬs 7uɦjy *FxxqI"笞|D٦ʢu ?3+5(x* v:Ίʰ+˅ڱ&[,{utE rHyj` `j `C FuJ+ ` jfސZdI ydGYJ td[ 9f+x?umKnp kpYf{Q0 'jF|Njo˷Hwbljq;t K Tij0 qslJ&?kJDȴf`jdKfCK[XS(ujjǩPt+vJ۴F{LkjN {`0Ii,H|7fK$K p{?; kCk {j [e{BK$bwj Kjk #t[ H0:+7YkVP`j@Y)wQ Á볦. +t)(Z›+c%\¦ 2|¸&j<@4년{nuhVƶkœ[϶n+ɋkF}*VCJeK391gS */Cӎ?6EѢX=DpɐI(I䃶O?4!┈ҞP|(9 $zpѫH <,9%DŇCK~H@R"U$55i%\,KE~?$.?*CDpIn҄UPIHHQ-NhBdZN15UCNB4"NvjLN𰧒?8񣓑&CI0$^܏^ġv`$qzh+   X\jqlm͟^*(l{x1nY*q $ K$$z@aeA:YB"T#BED}tuN"إO ED<$A CP"(BO!C(QX4& b!¡& ]"+Ѝ;Bb)Z rEQRzqC#,A+Y|pPD/bCDX@!@ez=&*G0q\28"{`!3"KkE( ,c `#yhnCթ' PzcѫG87;uvױpal]҆q8Z`%Ú{\r0򖺺4W$zjğm g^ q[^=WV}%(NtnsιDz:DGnр&Lʬ$HHHD2 >I;Cj M~p$*: Cpx"Bc#(/$qp &"3sR!KT"H'xz5!" Ws>a_{GA aŜiá}  ;QQ ؃,Ua=p 8nJPR\ O"NjOtU+3g \b<\b"T<x p!_<"yYb@8*!jEgO2cyMѨxO܌E2{"<&5{]ЉyHa BC+<{.mNX+Ԕq}BRv›vqސch@& }}]QaOdUqTyG/ G1m\UI^$%*Uġ:ɑUTԃl={T|tvXxy6IG( W~Xs(^qU{-?ۥy8) _ zC8կ2>=̃y D"9! $.IԙN+>@K6x_Z0*@Uwhe+\1(QU &zAm2[١X[97zD(23Ah(*s(yGHK挔#ؤ8<3ֱ<VWi)ְ#o:YaFg 8 +)zx I "`*κz0z7g,\\h @a8LBa$R~ȍtўv,<C +{Cr,(- 6@Y*ڜ⠙ ꞜZ(W0@>[; O<MKa#@T8?C@;2S,A6{z Vh{]  Kpp)2nAk) [=f j;I hil!|G}41~|G|;#H41,~E.-Qsss`rP|pR/Up<Ќ G < CH;=aϬʪSO!PUQ(QUP[UòD4řT=2 |$I;XI7͑Сhk gslÕ-RS"c @{ZWt%Aay5wxWw5 TW;tutwDSAH KAҨ=6؀}y%:%A(ׂX);X}أ٣XYuT H& }6TVieVǠɀ ښ hID{DH֕5eHE+  zDdHENT IhşhEېؤ iPԚ %٭ )Xu4E~\'u-ؒMѨUqAu]zUyU'1 s#zZwI;|:N#qopqPcCViMSz-=ydUCq5_~U@0ɩX\QR(`$[M]AF( ^ ,Eb$ú]l Ib`928%-x]c9Sb4ޱ*\8^حYV[b >P"TvTL Wtc5:B_U(`cˮx]ڏ)uF K 7U QAI%ۣ^vܽS 1աu%dQJ9n4eQ-\f\]WPHdtB 9tSXZ庌Q u"r[`Ob& u# f `gg6U8 >[a]eӾz9 ĊSE9h3mA`~2z'f݅x 0NG\&kcEHh8C>g%9>UlFƢF^M KauOE<"U_£* {2xZ ^0ՏEq0mKރǘB7[Sn=k=~kl.ܚSՀFn=znlgN`gO eqy UX, s$y^~ln~lt|Nnk 9.콶mk.>kW@MJMzߓ[ه C ZZpt'^ eԱ,'^')a ~bȫfe Yi7s:msDa2C3#=bf2ؤ"e[j<1#`A" 5 +rD&1Mk"2t' Xj9aIGcY޲Ҏk{[Opqpc93@d2RCqZr2~:B1>J83ZJ`2B#h`+pĥ=I|#¬\hJ[T"HH R댴;h,7VPxZL5XSd@ }>zV0JkZA e.d 0GCqᦷR( wVqʚcTdPZfF/dF=J{9ow̏gUZWDL>́tHu3KG;h|fF1Dcщn tpЪUǎ? ?g}hLSҚn5_Jz֮hGctsmX:ľt8Ѝ?}##k}as{6{=DkC6]s;F]3{/ z|&c 8%/"=E 'QZZ;IMYD^;ā6@*>V>,^ V V ݌" QUVZd7<}x x_XD RĮCy!O!~!ڡ"!E!Z # "#lS$>bbb#fՓ}-ZKd)>BԊdb<3pdrb+ (.ob(G0Gb0dЎSWQq!B&b!*e%r ^Z9c&;&a<HR^>FL|ƒ7AB#;&bO$%%ʣ;#&"4AF ?n$IJ$:>j>z#CRT#G$M $(b)Jd͘ _^ԊN,"B ƈ .ڢʈ SL\-"RcOnWZ`.#nc>#c*=[d&^Xey!Z$\=<=d#$_f !"az`^!2$He*⼑aEZ)cf$:b$Rg&=.7L$hfehTBbfVk&ifkb7ojf=&[N4X{4SؓtJWI@'4Fgvnǰ@y픩5cn'zMdR's"鎔sRGuJO^&:w6NŘi# 郊f^cO]芲Ga}b}T_(i&{桝ibąa)WY!j(hjh~pfjm:l2=vmC&ɶɂ,n,Ɋb޽fvhr̾,Ƭ-͆2m-眖ʐvEOJ~2+Bif+VnW^'rَƗզFVΨ-!ޜ!J<:m:䢬fU)l-JmG6(H5R)-f&,LRҮĴ!FyhGn. o.b"oF[Fxt`ElR/Vo*^j6"]J/!EooF/ȟeC@Ư// l6jEHntzRk~TObq'dd'N|N**/baFD۩Q`] ߯)fl]rzfop?h̰00.&fz_ha"fgL6ư_^Gίr1qnVgoޱq G /oo G  2!!%*\2'WM'p(C(){2*2)'2**,G'r+C .۲8 Ryz/'!$pl쒰r2r&~, q4C4s7Kr$p lw383:n[ rv(&;EhÉvvhth>s\ 4B(eB 4ckCOQ>SQm4GR+mGw4GUH4.U%1$uJH4LtHtG1L䱃jBz,P8Rt4z4Q'u#>iRGuQs&>KVk5AJnX$V"Y(}Z Hdhgu\5^u^ߵ^5_ @\ӵ]ib+vb?6c H D L 2D[u%'=uZ6iYa[iiƦ6kǶr]lvB+7ⶊ|!ڥ7qq)rrs]ݺ9wr37q;7wg7twsm9HT'G6{u{6gK|o5DX}oᾎ5/87?x>3@8g^4]Fu}[OzE7c{7B*6%7Ǔ*ɋϷ9k1o&;p9E6ԁ6\+y/{< 1+KyWl ?X]VR% W2|CF*RyR3X~4nrv6A6q,*95ig5<8`j6u;rW5~#`6;f'欿`^#R?49*6qxwg:O=}?~C4s#Q=W}[^$7~{`)C׾-%6~Whz#|\RlY47R QV,~wy'W>C=ꃡ3H;nk?!Vv@ 6tbD)FBx6[ݿs +4y?de/cœ)M9y HxOȲNJt}z*?(n1e?}izmZk^ƌڦo^qU.lQ% xX!b \xl97pac3fX!b)uuzifدF@kʍ3 taHg%6;o򉷐G9F1t.>~V󛊴fp҅:\~~kj\Oۏ@+}؁+A Z51&ې5bg6;,!G!@Q PFc ѡBNJl%r&l9)Ԓ,\O't#0ч#\MB:-,vTjc bdM 54D@29A"P0)V V^$oĪ#xP`Y&QzzKd p@{d 8C9\5C*2A "VCxS;(iM'*h.)e$P9de|xL \;j$d8u` &X' c wMH (A1dDc8"@3A e4@; Ͷ}(PzpiU!!OδwѴ; E:q܈zz1TsKe`oXh#ՏWfXu_KӼ芉8aA`٦Li?x0Y] M&jG6j*$B\PD s, ; pmDU͒b #XM G`xMJ5f2HUR0Eb{ P,D:I% uY8ɆdiuV =-&y%ElLC:!=f+z5R%|p U%OKS;m< iS#\67:y48FeM_LEYeI $y;".s]櫽SAZ(U G* rfm/qlyt*ECVᰁV[2}M=b$eFr`gPUf88Zc )KQ%! :EG5q ʨ7!/ؠU( oE G5ywӞְjdG*9y^=crQ;@<&Tm@L!dV-E\[zCNAU7z#2-=z-ת`}8B69G:x^`vPnTU6L`BnUCӶz Qqb)EE"%RXO#%c:| JM`')6.gS6D4<00DH71*OJP36l4@T&VdB|.ހ/\tzbMTMX4mln8bAe*Ioj klwX*X1C$bkpNDŽ'ah0rԤ&I%3^DDQ3_U^$p01BdD`NIBHIrbzIVtt'gNFpqvk$!V``>f x7 gw(+N.'%X4+XŒQXi"4h%F|hd* E[&lp|0DfMdbD ca8 C gF<[I:`#B\LXHpCLPn$Mf1-RJ%]" A`7*%4hhlɮh,(r ɂ(ƪh2vǜ2V)Zrv (yRJPuiH0e2@&   T%mF!4er./aHSe2!5 @bYR.%D9xC3tZbkM\H5OW%Yv/#Lڨֺۘ| r|3ݤ֜ ڞ87{S٘7omS;m۸ r r:HH__`bUr^R1c$8_:`H/1f B AM|35B3'?RqoW~nR1F4DO5U7%Z ^ ` n T Gn^Tn vGkt@ \`rR` t舎T R@G FstKnKUDt ԠLNvG\܀ R @t.z`d @h`G 4!FTb;i1Ն`Rrm͆mZ%!0"[S2&FcT# zr21T/^E?Md%a7(IةBhʠ$-njR)(NJNJYPh~,Z*iY[7BDvz ͓̊ʀA<l2/':p%!;0f_&B,rrU7ePc%0PH;\I~&܄}#7}3uA^aHOTZ&ӧQz5X]:= ԫ˱l^5R-j| M[P~At#?~4Ōk 9ǒ)G 伉ƴdO[=S*_E ;U~#RDu6Xz{I}]>~_ |<S;؁Xw>Et]oQP~v>ah"O(XVr=/HS\U8M6.΄iSu) w8ꔕ?3%sO&V$*_W2eG ה'mhM'@cSMJ,.Vo4%N;,hlԎX*^Vr/sNa,(S Xh&O?~t~ɜsk|a'c6OsP%6nn8cPr軚Z?0S: O nSk0r&-Y\Ý>d smIņ:O5Weg|9Rs\5*Х n; N&:.Քsrw|$UIR#@Iw,| ~^?/}W)%TjM fWwTh6wYƶ~R]R>BS @H4a r~c" N됀,/@ Iн}@xk?q)`k c< a.H%NvaT&&$̀;IV;-!QM-[ԑ-&%M6%FtEPVٲ;=ET)xP{ Ҋx&JMɑ%OBuzf oXVCS|#u setnl'-m#VǹN@4rpʋۑg/EuWkb;0li[iO|S(̈́˩ƝLr@!tɂmBjfHl7GT%JRȅ_WݎڈC8d]\FBIڑIf*ܥ~N~*9j%̉x~UBawm I"1{ޫ St}4n47xJAI'A;hC aEzn>=V&K*RxY4>' ͒Ijih2XTL\θ$kU1Xltٹ3V˧J`fiy3cG;(Pۻu*ZЯJo$g~LL^Zn7* 7xrgX6iizNV9.*Z/wэ߈'yԗ6shޜ/7`ow6 NX}ʼnJ=s Mn1ЂuYh6y#Zt,˙NוFZuW1R3q*b~ʫgfXJux+CsjgG'IǜPߜ툯y^1;>C;{ܠ3s M(V8Fo~rnW0_xCZ?5O0J.Z!GH0 MM.e&/Q/F*>.JCd8^`>38N+';k~e8%vvtG(iwW 04 KVfa*1$QCA8q!P` gR"hdOA/O9vFF1'A ?.C\zK1/sd%*Q/3uXm'(k)ts]Vh":4#N$OG0IHONAC,#+ޡ `@ 0#3 @Y4Zc,.3S"#!ɕ_3 8Zu׆(7Qd:͒^9hLW]'jڱ%5#[Ii:`<Ktn!H'By<(iA$qQ 0@CS/N  ?΀<cSyybQ$8(SΦ7ׄhqRĔmmmqd1L"jIW/#%&iA'5GHsYY3 6CSU!1 5[ @HeB$%=4B5&:%t7ʝ߉zz 8*7!AQω>ERht0p9Mq_ (Y/H/F57S4TSAN;;5DDSu (jẐ=Ox9W 'e\|Wt)pdr#[ +ٕtnn6 z=c֐+ %#K!K: 5F \(gr`97Zmzmdz=c0w1$h/Hgki;) bOB;[4&b2\nvjQRK(KK:qyuv@+Kk50P * ژG9¢TFyBwZZZL/w뻿΢@˻zQ(ۻz n (*Հ׋ \ z(†jyUDgLXVech/ۼ ,Ll ـ \ + l 0  ;p ܼ 5 ذ+- 3|5L !;P5 l|wqF? _`VctFV[K[{eZkԫ[@/Pc,elfgikflqTk"@vmOPOv\_POTw \vq}T)`kq|ɡɣ,wL=?9н[-pKPj@^lKM@H<jiW[L}y;V,K\ lGr་ v g4{ ^ltAEL)"Ka'it)7q)k$ex,.dSie+By9cc#M%$!+ҵ <88 4<ܹPq k8Vzz' '+tJ-ɬgXK}ZvrzF1Ma$"~$W&qzq=tF[]{8zUy}owVbq>Ay4zMc7$b[Qlж~0yi{nJ7to Ѐ+݇7Q-%Mi"Х;}Tv.Qum8kq-!$7"IW٤6q =teT`/{zvMqwR.w-u&-ؿVdОgvb])=bνԭrq!"JśTՉ̧`kj#jKZc]Fg!,,"'\n>f܍`mҵf/% bםs]TbJ}\=]wf}Q'L4H֪1K#;q7,CQ}Tv{Xh~KaQ|@XG=>Wotc+2Z)amctF{,˙]}qp]F-?_B@bT:vX{1ִ=ftװ~Xl]wv..hPއS^zZ/u1E w缾Cn}f2I)}Wc&ʣÌeQ<`~2'+IqoWMhv]3ުr>+ǕÞ٪H7d;g贸"o'Ǖ1$.,d.3?MƃM2@Sf?рfo,K- #kVhVk?pESx\Cap%ATt:*p`AD3!z~Pg(jQ2,O%M#lͫ٠jP*6 aFMa @ 'a/Sb<L[Rj bfɿo M ge ܑMJ,#l>"b ͟ "lrv!v cO[CASpv8*'@Sh߾Tek-a6m$M<}TPEEZt?߾p󶂊o߰٤7!ޘOc~7o6CRPfa3k&lGK,nexYkܙg>Mn/-p7lު YlС>-vȓYlrmnzzjWg^8+*XS%i>_?q D0A:oR0±:kA- 7ܐ+9%liƎ4 2舩3RC'Xxa c*#8J H'̸/2H8#vH#TI'k2iH30j2:jFx.*X#$$i*2-G#9T'tT"HԒSJuTLL,HHӤK+flqoJM/0Xj46٤,gѪC֭Ya'k q75l":P:șf%QUMyf!^j %_'!:H5їtC>B_ X ~*Mybݗy ͦQ38v*`ʛ'zٮP+HplCD&5mڇ/x'bjZy>K4ߩƩy#?;Z}r*\l4gGDO"\mh!5QMj(ʺf"glBFo I%FžG].) J.@DJekYAxLPpt586Ȕ5tCFPt@UGD2Ј"`t,){dE~ZϢr3 kP>ۡZr\]"a/c> ]Y( R " xVͫ]I9r%"JR ck9;x r<2gKqrۤ;iIPJr;P-ow\\w>6?!F<ʏX?)_ Qhgm~SXr[|xW=zbFMb\ʉ9{Y Iϻ/(OylOF t(b2(?E'$k'~Osn(RJJ7N&+ dGtXVk،<6Q3:n=O0Գskh B56RC jOZF6ըI kXT)aAŧϓڴCSj)U}/UdpzNX1^l?pe(@z-leZѳȕ=Kf5S6. l竆M5V,- `mKBimҳ>`(ŏBב6LmtJm( M55nV{QJE/Yj,4 e4B[2ZUg?b $JQV7}o`N A'^ g6ʄV3C]\WXA/m]\܆mhz Rփym5 v*ܝV+6]-J[0e-ivAcjd>J~uvvZh~ : :܍d. ݫЙZ 5W%+Ywu,m6sYJ~4- PK#5uE\va,;XmwRSW0|g,ja莭H#pbk;lwvwj_XCTbd9vYe_zAtd#u{zZכ7%HtLo+-$!BsxTiBy#L/;Jpϼ1|>\m51rwlT*Γ;x:C*,}Kg + ovFp߶4ٺb?87R~w׎%C `}P!x)g=\au@,pGRpQ/:֏tF;Y-o|RX^PfTx7dqşdۡB2BW˭<7x?O|q|!)BRi3## NgŴ6nW^Cǵ<] =l9s>2 ;`u PiP=;)9[<2S >[j Y?H1Iw+A cJA3 3= )%vp<+B;ۻ9‹  C tҸ= l!)dC !&gz"<آS,5&K=])'AXB۝D+pB0TCd  `9hB*;;YBɀ5>k>{>lDi>L56 C9t7:p?2Aƣ38I:ƃ҆! 1|XCgXC[,hŃę;0}(+dv2[EYD tEC @]tX$,*f%h Ơ <5p>4 ?FT*S{|Fh9G`ZM ]TDDt|p<HĚtJpFH|Y0E'\D<ț HɛD5|yŢIXĦTs4Hx8=Th40b/'X[2=ck;BDRAHJIo\JrdVlE}0J5Jxhz 2$G ~ K LJtL̓PLd GeYHlK:T$ ^k5[ɠF2F0LDśW JDMrTL̛4q˴0 HLMolG[JƴM;TØL#\L'̰ Hp;Lj 1#1CA?@ILhp HDWQ<~\ vtQ,VFJ(<ej* S3*({DSb'dKc=>LlD@@#EYv #h3TSќ"4Vnt/>/#\1h3mUWU4F"[MN\Ku"֓NϪ3EF,/>3pD1CCs<=C)ńc9Dlwv}Q2xMUFZz Q\,QX Le ;se>[ͱ w`0EPR<4DVo5#W>=V$gNDlZ[ؒ?zS2 W_*-+2P>C2%餘kPTiŘ)"}ٽŃ;V=]9]X2:œeթ\Mۥ].{ܵ]u9QYj76}m7UQ=S,.,[* -(;E dHe]vPeb5Ը^ڍ9%+͘+0ʺx%Ϛ^酰a+12`ƯQ~+ ?PA~N($S v p_ua+ҐQLmxy<Gw8\ͨjII_%FVb&6Nx6@j`17{=K^ٝb_ʂc2 z"% ul `@HPn kSP Ⴭ>)L܍bqNN/ S@A48w2 &2霞4pc f䞌DI0TfW\5LPtO< `ŝ ɪl  ?RԛۋМh{4ߺ}Sxe||Ca&h)sY%#c3c~c8͏PlNV)ЬG]u8߹V2"\Cx` ӜfPQ8YϴXqBf$i**hj&9my{X32kS]`'4JKk'JibkA 6H(GvX;ho` 0̓Xzsfm0lVJ!Zl k%_Um&4n>n&n`P tjA]We aW+a8vx@@RkHuMҶ~I(Gt`X퓀vRX܄J|v~C _N`Q_.gJ"<N˹N .Fqrh(q~%dGL#/u"Gpn?O;)m' WLmR1+? u[b?5s9g~,-('Hj䅨qBV޺j]D^;ƬY<DqI`a7e5 9N\p8;Le9>[PpHNGu\W1v ^z`}⨛>|e^SYc'v6脶vN?lmMr6Ktvnf0vvvz/}4B'zЩ#=:2t62&gxxKqxjֽ"G;;i'pGZsX }$+뒞$@ųO zuwzz{-`3:ҥ|8vwGJ^AjC;К'7ßQ ƿopІpo{Q|xB||_'}ҟ|Wgw}/ȁ-5(vh/i>c|=tWzlhk( ]q~]ʐlx ]Y'8l ~')~]m7 "<0!Å~M`l߲aspƎ?z rȒCG=jX6o̩s'Ϟ>Lxff4(ӦN2QHU^ Sꓣo];lʋU7/߽~+80 XCΚ.Sbn'Ox掊5PAaǎf*j̨io5|[6'/,[B1i*whN[9Λ7ru?xݿw5łPnvF<>rɏh֩ϯ*XY?Uy'}|'}yh{zC_ML6s(:X6v|JSj:UVJ%}jgxZjh*hgljh(l",F4#5԰E7iqbMܕYW]u#U7iuE[Xh7ZpSab/3EpՖju7TdS%zYK^z|XWlz > 0.˲y/7m3T}?([◮}WGrg5fgjYY1]X)2m]TWMUPޝּ5Q=\.ɇu+͸MZx7ޒsQ@=NEy~Ic?m;w/Y[ejU`Wv̷_n8|#ucE.MO0Q2!=XQm_[|hۨM-}{Y y7VpYz)@e%|Y-Gv󈝬f%Mr0uz\hPFs) 7Iٞ OS̫?WuNptJYB(@Znd)޹2Zh6D2)TjSkoFknf1r#ZzFOCP}(1U? ayGIt4KMV%+XtDRX:Av&y8kQݛ>Y( G;`.MqyǴGv \ZZBY-vj~Uɤ\+7ؑuPj&`]CY8 ]eҎw(7QG EV{tk~(K82FQ\"r{ʼnuq]䮵Y VΒ` QWTZ=QAp}\P7Ѝ(":npt%GpB2WdFFuI>E졛YQV,.Ɩ:]d@[^nnD!ra:P4쪌i E麢27KCъ @NF-B LCehL2!":CƜeH1nT4I8}#'!KnB,iMu4;5ҨV5] X(g0Cpڸ!ޠb9i)k? cj8k 8k:}~fe7ci{#ߐƃq"žС/ Ʉ GzL\(ja ?R2p"(#o` /Xmt|p-ޛs{u6&qU)Bac i@|S7%6NbLJ\%g(+ߡ:Cj((T kM ,L~Ď=e @lDD m+6ˮkn p}mP*_m")$5;Q:k0"Yxw,dCA=#*NJ[M_vȵP F TgY(Jh-#'ؤBJo䍿jVF<ʮEZ_ɚ:hf񟟌ߠ dĤ\fqˁ<a<^ZL;A`7LBB_ ))מAOǠ ! Z<-YmYiU G%aQR TbKԗy!`  OԤ$JLߩKܤS>QyTNXEWtMM yx Ԟ0=S!:a:bvX"YUdPEJ>YQ@b$MU!&$1TZ?d LaP *,-L6 R,!^"K#)F ӿ͠rq zbO]KRcHHn QcV#VU AfJ590R?d`E}I?*BF$K.( L ]# E[T:ZPQd FpIJor?`]N9"j$8ZWbO"^k7͉'aRAn!"w n8YZz雐 wz!i΄5R+>g4P_[>hH UNKDxYi*'YTx)e>d*YXOjI*;C?8?kVQ)櫙ސΩ3 ;*}YEy&R:azETKW&L`ֳy>A5&}RTԦb,VafgQ?ibݐÜC3C8V,V6CUĬى6UcWlV¸Ճr'"h^Q\/UyLJfdVjbp}*v ¬ߚ)Inf)b i-&UCMrȅnlk]r}È7,R9zrZ$M)~ƮĬpTL=q ~?|%kmՍH Ej^iz|>d`lG;`7 H)k򋩬p I͚&ޯM/Ω3U/M@J|wNFÁbtnqQt>Y؛\: r\x>LIcjnY߼qj"ua "zX|"[q=h"26o>dEsۤS6x%WI W1gJ1 1<ܩ|5KzUr w|@IӠ\ś5vU?CۊRǶ0#݌hHA[6lA 1N}"'ZMi.q2r`"ǡ*:L/[b[|X&B<ʋ6#qxE7tCyC p Ȇ ?C'A'[Y,n77);ūps 95uel?@!p-'n݉AVD_XIXWɹ_]Y`:jM?עSXĥUXYYfy=Q]gZ(3fǝhUJǵ 99@c: -hR[wy ئLz{bXpcx#LNokm7o޸IQG*͒Qr2gHWi0B 5xʤZCߜɝz߯c3mnex.\q7̓h ۖ*`Ê{6c#k2!Կ -ϤLp@ĂlBP ![Z(5PB *^5poÀ(rP(3ȉtLH̚,%̀fIQ$(j~&7? 9l"st?ݤMB![pJTPKhNOg!0;'JhUX?ՕHSxP׈zu$dRuӦ>D\ z?v@8ŊV[;#3?CÅCVMa]!i?}\JR)iStb0w LT*;f '2g Cp>iS1ìY*ݔbϖO&k4>O9]бH͸<ٽmisgi>RuSNk_ 1ø$k]۱|&ȿki[6M)ʷ;~s}Ώ/ 01[u4:zOmO{~4Z _B=C/γybjcVa}^* =CJvv] =AiQ1b;[s7lk$0[)V@%{7C~ Q (ȐpdYJA"nNNR>&@th[bZ@n" ϒ-@:F U)2od^S bKXnnO'v]D)*v_vY2/ljG@FP" )0ZR'%qe(J!ްYJA$&lGX%>l ;yLe ,0yia`.UFō3|(˷IN.HCdqʲA 7K;a*ahq`&qoP $rF udn,dItRE ;Lju(LcRSI4i |NyYu6e!k'dNx)\csJwD)ZŘ8;1;DJ7PĘ3P:j3h$&P6RxlC\һLDt]B>."߬?JRť˙4,JOru mU3TA*#gu)dqiE+ؒ+[r8͛o! :=UzM5d@7TIE8Hp] X4C Y=tYRբtN}tH0W6֭2X[`VxWݐ Xgjh^E4Z>?2dIsgn!2ڑ`pڹ J{fPx 1=|gZS. 1p,cbc:Q61S[L$0226 Tj$ ,Q~wplM)+}ַja:^8foʯa)OdQO_މ.Zio??IS)&ذy?/LS`af,fwЍwdf'~b:y]^|}D3 P(QUN?@=P.t՗d,;l̜ P'@"#.˶gSo/Tѻt״>/|S%ѿ<BN̾/+Hac,RʦK>o{$ !G.%4+ҫzϙ`CǘL 1@&vǪ/+ t Q"gL'F 5 d8bF !fXT ` JTh c a!_VFLˢ#)bx`Hi)uHr `@!aB"P*a? J5kJ̠2LȊB!|SJEGd4n<. -PDĂ@Zίzk5VHFD6xF lt SZB72"#4B!B6"&!D!!!%nq!e"=#)Ij" d1 ,Q+%f?hmd`^K_کD $@t~t6*J*J+2+R+2,+2+2-HEPR,UB'Z%&DC&7_ wgWҎR"%04 ` D` j`v)} x * Nc4E4I4M35Qs5U5Y5]36Q h4i  ^ހdH0ql0o.$@Vrvd~'Q|0~ r;@ )l 1==3>s>s>;Z*ȁp0(9d,!"x)M^:E2N6BT2JtCA vl (]ԑT4EQE_EY H01{_lt)TA@;+z&G^"B$$,=D'j'%LfLL}K4MєMM۔Msp#XP2X2@E_B'4>V:eh\ɨ b~"&,Fv|zS1T)GTA@BSTQlO94,$&"Pn.dX'\"(BمIIaD%r&UpkSU*$мOR[5\Yk\\e\x]\U]͵]5a~,!TAq~ 폐Vb_QR,cf _·HjEkvq Nwvth-iN Y4>P3tԎ2Z '`FQHgMgEev$eGbej)䅃`e'D)m뚮@sOMnP~L]QU]T(Gcdj7E]v|ՑwshPTw&'7O$ Q86Nd24buotw}Vi\rh;=$7~XWk㾰hA$e7qm%dȀs?%ВfyVh yNz7.{no"A)B6xi-n~d~f&酊rTȀ D"giu&sVG?7P$t7EiBd3d33A6lDfE…wwY~.Xn$R=\ B%5yښ7sin4Y;Ԁ6`\` \`V rL!cLUYX zbYUY&~f=!($)A l4Mv"l¸@C y wR1[#Ei;A Ȁ5 X"`T` tI:Ҡ ; 89!b:Lfc`' L (h2Ykkp?x2-F_$# :H23p|#G!:C!PKmGF1&Z8![I& SJY2WW\TzGimtKB5%Ur&zٹGCƒ2o"‡HueGbIa.%C'[6,!Lp'r>IZ`rzw 㩦_kg!xT$sU k6c(p<{Tt&j`NQsbʹEF?F!0wpBaw.LڀYd]PLGv_42"a*qa[Cd`E_aP}[##O~Qb \l}ZaphK\?[TrfN0_7p)<%B^H`J!lȋpn ϟ£ A|Ë3jȱǏ /a3J\ɲ˗0w3ϟ@E$YP7'A*Be{:sի1>q( o[OaMDe a۵ZRZqߺ8ߋgP$DU^3kYu`8ٸLcg ]ƦO[XRJҩfY`Yvc|?}G6͇{lΡw^]Po^I߿c3f$= .UE{*EWav`uW[A`m5mvVzYԔ %!dc B<9wPEr͇{c͕l0F?Fӎ1%#zЎ=vNB>(cG6jF 䟇I??U~ WIHqެgi$Wmr` 7WM6d8v7Ύ&$6m:됥s"N6F4ɭJ}e cF>54!w(0j϶P.P(\cFi vO`&E$ RѸ&ceGwL,ͿmMZc$ӽs_}x>fjT "fBmki ?*\Ʃ3Ȍd,I3 wyA6h2{\x/y%ڛIcsVНmEE,YX5ԇ$\/7) "Ω̣#FI?(IE-Y&J GN&}slKJ%~4c6ls։mظtʳK pg;4-" ҏصltӅ7|# >[Zuj( T %$f?PHk^wZ6wM SŒzNr:KA&Lۛ#8e~K'c!x|ԋtcZ(WT:DC'f~Wi| J\hІvjGph A7ʐ Xyz E?:?Sum/Pʐ'ā qHA鑊ݸ3Ę>ƭҰƌ*3Z7h{5E `CM'mi7ekND-kRkWچ| M64ڃ+4ltLZoL<93yx،ipQ+:m99<p@pFۘks{'1DyE CD o^x0'2YɶB 8^b/ |{%FG;@Gg;vl[c0>tYG7g~a[57q(w0) UI5&J)Dhr$Y8jVT"Y8EV8/uN0QQOGxNJ#1UܢB<9D:p_K#BU!VJ$"S !!)"{U"W8#WdHHشG5I/@DRpsՇ &d]U0`׆+q 7P2\(ғM-TU]H9cR#k?"vZ4s5Y sbh\"[ȎQсMA߀+Ir6+\d3.AR6Gg%$X~%I[ SEb&1"-!Or9SՂ|}Yb1&a 1kwE_PYG5ON(UUynAC@(KU\4 `#-29xqn,%zdf>"Gg|D$ZgRĖQnv exx ]M3FH}0t.I-e|eEg)f'9\.` g9FaT@)?2>e\nQqfEVŐ?ST~LDV{R%"gXYnDq%IK9QUle!P`^ )4s̕_i1YF5~CZڐ(jC 4AYq }9miWA)k5ܤ' V"DU`\y]BAy0Bn@zgo#WءACN4&1v'hZJD BjR2؞4a\0gL*6)kK١ߠ\`5 f?fP v3+LP+;*<è5s[ zZmd @Wp0.)٣q!%*\z:&sGbCp b/nCؠ( |N-Q{EzY3J}2{F6Gc+WPݷ;ʞa(8C$,u 2wF/p%Nd1^rCYI;/ % 1%;n!#K)ہPr*4 :) B[0G.頗.HPZʬFMkinJJڂ0azSd)FjI}P431ފ( 5 |3 Dk?F*25DQ&z9q T"id@bƉi1#;I$Sc}kP/5W[F+]f c]r갞UN+[LTptj"LPѼ5l[KQiՋjA q .ziah%aV=B.LgSd Dj;*o)[{o>te|DtGaʦ4" Bg9Zԡ{ʞKb(F_K*i!oBnVo1v)W3?ZArCqF0Bem*@`  \UxE b«YgW`tahoq0l'ǀ|3pe\Ȇ|Ȉ8xT~ȎȐb,ɖl!;commons-dbcp-rel-commons-dbcp-2.13.0/src/site/resources/profile.jacoco000066400000000000000000000016611472045345700257210ustar00rootroot00000000000000# 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. # ----------------------------------------------------------------------------- # # Empty file used to automatically trigger JaCoCo profile from commons parent pom commons-dbcp-rel-commons-dbcp-2.13.0/src/site/site.xml000066400000000000000000000052531472045345700225560ustar00rootroot00000000000000 Commons DBCP /images/dbcp-logo-white.png /index.html commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/000077500000000000000000000000001472045345700220205ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/building.xml000066400000000000000000000035601472045345700243430ustar00rootroot00000000000000 Building Commons Documentation Team

Commons DBCP uses Maven or Ant as a build system. The maven build requires maven 2 and JDK 1.6. The Ant build works with JDK 1.4, 1.5 or 1.6.

To build a jar file, change into DBCP's root directory and run mvn package. The result will be in the "target" subdirectory.

To build the Javadocs, run mvn javadoc:javadoc. The result will be in "target/site/apidocs/".

To build the full website, run mvn site. The result will be in "target/site".

commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/configuration.xml000066400000000000000000000447021472045345700254200ustar00rootroot00000000000000 BasicDataSource Configuration Commons Documentation Team

ParameterDescription
username The connection user name to be passed to our JDBC driver to establish a connection.
password The connection password to be passed to our JDBC driver to establish a connection.
url The connection URL to be passed to our JDBC driver to establish a connection.
driverClassName The fully qualified Java class name of the JDBC driver to be used.
connectionProperties The connection properties that will be sent to our JDBC driver when establishing new connections.
Format of the string must be [propertyName=property;]*
NOTE - The "user" and "password" properties will be passed explicitly, so they do not need to be included here.

ParameterDefaultDescription
defaultAutoCommit driver default The default auto-commit state of connections created by this pool. If not set then the setAutoCommit method will not be called.
defaultReadOnly driver default The default read-only state of connections created by this pool. If not set then the setReadOnly method will not be called. (Some drivers don't support read only mode, ex: Informix)
defaultTransactionIsolation driver default The default TransactionIsolation state of connections created by this pool. One of the following: (see javadoc)
  • NONE
  • READ_COMMITTED
  • READ_UNCOMMITTED
  • REPEATABLE_READ
  • SERIALIZABLE
defaultCatalog The default catalog of connections created by this pool.
cacheState true If true, the pooled connection will cache the current readOnly and autoCommit settings when first read or written and on all subsequent writes. This removes the need for additional database queries for any further calls to the getter. If the underlying connection is accessed directly and the readOnly and/or autoCommit settings changed the cached values will not reflect the current state. In this case, caching should be disabled by setting this attribute to false.
defaultQueryTimeout null If non-null, the value of this Integer property determines the query timeout that will be used for Statements created from connections managed by the pool. null means that the driver default will be used.
enableAutoCommitOnReturn true If true, connections being returned to the pool will be checked and configured with Connection.setAutoCommit(true) if the auto commit setting is false when the connection is returned.
rollbackOnReturn true True means a connection will be rolled back when returned to the pool if auto commit is not enabled and the connection is not read-only.

ParameterDefaultDescription
initialSize 0 The initial number of connections that are created when the pool is started.
Since: 1.2
maxTotal 8 The maximum number of active connections that can be allocated from this pool at the same time, or negative for no limit.
maxIdle 8 The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit.
minIdle 0 The minimum number of connections that can remain idle in the pool, without extra ones being created, or zero to create none.
maxWaitMillis indefinitely The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or -1 to wait indefinitely.

NOTE: If maxIdle is set too low on heavily loaded systems it is possible you will see connections being closed and almost immediately new connections being opened. This is a result of the active threads momentarily closing connections faster than they are opening them, causing the number of idle connections to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good starting point.


ParameterDefaultDescription
validationQuery The SQL query that will be used to validate connections from this pool before returning them to the caller. If specified, this query MUST be an SQL SELECT statement that returns at least one row. If not specified, connections will be validation by calling the isValid() method.
validationQueryTimeout no timeout The timeout in seconds before connection validation queries fail. If set to a positive value, this value is passed to the driver via the setQueryTimeout method of the Statement used to execute the validation query.
testOnCreate false The indication of whether objects will be validated after creation. If the object fails to validate, the borrow attempt that triggered the object creation will fail.
testOnBorrow true The indication of whether objects will be validated before being borrowed from the pool. If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another.
testOnReturn false The indication of whether objects will be validated before being returned to the pool.
testWhileIdle false The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to validate, it will be dropped from the pool.
timeBetweenEvictionRunsMillis -1 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.
numTestsPerEvictionRun 3 The number of objects to examine during each run of the idle object evictor thread (if any).
minEvictableIdleTimeMillis 1000 * 60 * 30 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).
softMinEvictableIdleTimeMillis -1 The minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the idle connection evictor, with the extra condition that at least "minIdle" connections remain in the pool. When minEvictableIdleTimeMillis is set to a positive value, minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are visited by the evictor, idle time is first compared against minEvictableIdleTimeMillis (without considering the number of idle connections in the pool) and then against softMinEvictableIdleTimeMillis, including the minIdle constraint.
maxConnLifetimeMillis -1 The maximum lifetime in milliseconds of a connection. After this time is exceeded the connection will fail the next activation, passivation or validation test. A value of zero or less means the connection has an infinite lifetime.
logExpiredConnections true Flag to log a message indicating that a connection is being closed by the pool due to maxConnLifetimeMillis exceeded. Set this property to false to suppress expired connection logging that is turned on by default.
connectionInitSqls null A Collection of SQL statements that will be used to initialize physical connections when they are first created. These statements are executed only once - when the configured connection factory creates the connection.
lifo true True means that borrowObject returns the most recently used ("last in") connection in the pool (if there are idle connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle instance pool in the order that they are returned to the pool.

ParameterDefaultDescription
poolPreparedStatements false Enable prepared statement pooling for this pool.
maxOpenPreparedStatements unlimited The maximum number of open statements that can be allocated from the statement pool at the same time, or negative for no limit.

This component has also the ability to pool PreparedStatements. When enabled a statement pool will be created for each Connection and PreparedStatements created by one of the following methods will be pooled:

  • public PreparedStatement prepareStatement(String sql)
  • public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)

NOTE - Make sure your connection has some resources left for the other statements. Pooling PreparedStatements may keep their cursors open in the database, causing a connection to run out of cursors, especially if maxOpenPreparedStatements is left at the default (unlimited) and an application opens a large number of different PreparedStatements per connection. To avoid this problem, maxOpenPreparedStatements should be set to a value less than the maximum number of cursors that can be open on a Connection.


ParameterDefaultDescription
accessToUnderlyingConnectionAllowed false Controls if the PoolGuard allows access to the underlying connection.

When allowed you can access the underlying connection using the following construct:

Connection conn = ds.getConnection(); Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate(); ... conn.close()

Default is false, it is a potential dangerous operation and misbehaving programs can do harmful things. (closing the underlying or continue using it when the guarded connection is already closed) Be careful and only use when you need direct access to driver specific extensions.

NOTE: Do not close the underlying connection, only the original one.


ParameterDefaultDescription
removeAbandonedOnMaintenance
removeAbandonedOnBorrow
false Flags to remove abandoned connections if they exceed the removeAbandonedTimout.
A connection is considered abandoned and eligible for removal if it has not been used for longer than removeAbandonedTimeout.
Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one of the execute methods) resets the lastUsed property of the parent connection.
Setting one or both of these to true can recover db connections from poorly written applications which fail to close connections.
Setting removeAbandonedOnMaintenance to true removes abandoned connections on the maintenance cycle (when eviction ends). This property has no effect unless maintenance is enabled by setting timeBetweenEvictionRunsMillis to a positive value.
If removeAbandonedOnBorrow is true, abandoned connections are removed each time a connection is borrowed from the pool, with the additional requirements that
  • getNumActive() > getMaxTotal() - 3; and
  • getNumIdle() < 2
removeAbandonedTimeout 300 Timeout in seconds before an abandoned connection can be removed.
logAbandoned false Flag to log stack traces for application code which abandoned a Statement or Connection.
Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because a stack trace has to be generated.
abandonedUsageTracking false If true, the connection pool records a stack trace every time a method is called on a pooled connection and retains the most recent stack trace to aid debugging of abandoned connections. There is significant overhead added by setting this to true.

If you have enabled removeAbandonedOnMaintenance or removeAbandonedOnBorrow then it is possible that a connection is reclaimed by the pool because it is considered to be abandoned. This mechanism is triggered when (getNumIdle() < 2) and (getNumActive() > getMaxTotal() - 3) and removeAbandonedOnBorrow is true; or after eviction finishes and removeAbandonedOnMaintenance is true. For example, maxTotal=20 and 18 active connections and 1 idle connection would trigger removeAbandonedOnBorrow, but only the active connections that aren't used for more then "removeAbandonedTimeout" seconds are removed (default 300 sec). Traversing a resultset doesn't count as being used. Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one of the execute methods) resets the lastUsed property of the parent connection.


ParameterDefaultDescription
fastFailValidation false When this property is true, validation fails fast for connections that have thrown "fatal" SQLExceptions. Requests to validate disconnected connections fail immediately, with no call to the driver's isValid method or attempt to execute a validation query.
The SQL_STATE codes considered to signal fatal errors are by default the following:
  • 57P01 (ADMIN SHUTDOWN)
  • 57P02 (CRASH SHUTDOWN)
  • 57P03 (CANNOT CONNECT NOW)
  • 01002 (SQL92 disconnect error)
  • JZ0C0 (Sybase disconnect error)
  • JZ0C1 (Sybase disconnect error)
  • Any SQL_STATE code that starts with "08"
To override this default set of disconnection codes, set the disconnectionSqlCodes property.
disconnectionSqlCodes null Comma-delimited list of SQL_STATE codes considered to signal fatal disconnection errors. Setting this property has no effect unless fastFailValidation is set to true.
disconnectionIgnoreSqlCodes null Comma-delimited list of SQL State codes that should be ignored when determining fatal disconnection errors. These codes will not trigger a fatal disconnection status, even if they match the usual criteria. Setting this property has no effect unless fastFailValidation is set to true.
jmxName Registers the DataSource as JMX MBean under specified name. The name has to conform to the JMX Object Name Syntax (see javadoc).
registerConnectionMBean true Registers Connection JMX MBeans. See DBCP-585).
commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/download_dbcp.xml000066400000000000000000000236341472045345700253510ustar00rootroot00000000000000 Download Apache Commons DBCP Apache Commons Documentation Team

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

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

[if-any logo][end]

Other mirrors:

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

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

commons-dbcp2-2.13.0-bin.tar.gz sha512 pgp
commons-dbcp2-2.13.0-bin.zip sha512 pgp
commons-dbcp2-2.13.0-src.tar.gz sha512 pgp
commons-dbcp2-2.13.0-src.zip sha512 pgp
commons-dbcp2-2.4.0-bin.tar.gz sha256 pgp
commons-dbcp2-2.4.0-bin.zip sha256 pgp
commons-dbcp2-2.4.0-src.tar.gz sha256 pgp
commons-dbcp2-2.4.0-src.zip sha256 pgp

Older releases can be obtained from the archives.

commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/guide/000077500000000000000000000000001472045345700231155ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/guide/classdiagrams.xml000066400000000000000000000026511472045345700264600ustar00rootroot00000000000000 Class Diagrams Commons Documentation Team
commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/guide/index.xml000066400000000000000000000024251472045345700247510ustar00rootroot00000000000000 Developers Guide Commons Documentation Team
commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/guide/jndi-howto.xml000066400000000000000000000102231472045345700257170ustar00rootroot00000000000000 JNDI Howto Commons Documentation Team

The Java Naming and Directory Interface (JNDI) is part of the Java platform, providing applications based on Java technology with a unified interface to multiple naming and directory services. You can build powerful and portable directory-enabled applications using this industry standard.

When you deploy your application inside an application server, the container will setup the JNDI tree for you. But if you are writing a framework or just a standalone application, then the following examples will show you how to construct and bind references to DBCP datasources.

The following examples are using the sun filesystem JNDI service provider. You can download it from the JNDI software download page.

commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/guide/sequencediagrams.xml000066400000000000000000000024731472045345700271650ustar00rootroot00000000000000 Sequence Diagrams Commons Documentation Team
commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/index.xml000066400000000000000000000104031472045345700236470ustar00rootroot00000000000000 Overview Commons Documentation Team

Many Apache projects support interaction with a relational database. Creating a new connection for each user can be time consuming (often requiring multiple seconds of clock time), in order to perform a database transaction that might take milliseconds. Opening a connection per user can be unfeasible in a publicly-hosted Internet application where the number of simultaneous users can be very large. Accordingly, developers often wish to share a "pool" of open connections between all of the application's current users. The number of users actually performing a request at any given time is usually a very small percentage of the total number of active users, and during request processing is the only time that a database connection is required. The application itself logs into the DBMS, and handles any user account issues internally.

There are several Database Connection Pools already available, both within Apache products and elsewhere. This Commons package provides an opportunity to coordinate the efforts required to create and maintain an efficient, feature-rich package under the ASF license.

The commons-dbcp2 artifact relies on code in the commons-pool2 artifact to provide the underlying object pool mechanisms.

DBCP now comes in four different versions to support different versions of JDBC. Here is how it works:

Developing

  • DBCP 2.5.0 and up compiles and runs under Java 8 (JDBC 4.2) and up.
  • DBCP 2.4.0 compiles and runs under Java 7 (JDBC 4.1) and above.

Running

  • DBCP 2.5.0 and up binaries should be used by applications running on Java 8 and up.
  • DBCP 2.4.0 binaries should be used by applications running under Java 7.

DBCP 2 is based on Apache Commons Pool and provides increased performance, JMX support as well as numerous other new features compared to DBCP 1.x. Users upgrading to 2.x should be aware that the Java package name has changed, as well as the Maven co-ordinates, since DBCP 2.x is not binary compatible with DBCP 1.x. Users should also be aware that some configuration options (e.g. maxActive to maxTotal) have been renamed to align them with the new names used by Commons Pool.

See the downloads page for information on obtaining releases.

The Javadoc API documents are available online. In particular, you should read the package overview of the org.apache.commons.dbcp2 package for an overview of how to use DBCP.

There are several examples of using DBCP available.

commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/issue-tracking.xml000066400000000000000000000133231472045345700254740ustar00rootroot00000000000000 Apache Commons DBCP Issue tracking Apache Commons Documentation Team

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

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

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

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

Please also remember these points:

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

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

You may also find these links useful:

commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/mail-lists.xml000066400000000000000000000213271472045345700246250ustar00rootroot00000000000000 Apache Commons DBCP Mailing Lists Apache Commons Documentation Team

Apache Commons DBCP shares mailing lists with all the other Commons Components. To make it easier for people to only read messages related to components they are interested in, the convention in Commons is to prefix the subject line of messages with the component's name, for example:

  • [dbcp] Problem with the ...

Questions related to the usage of Apache Commons DBCP should be posted to the User List.
The Developer List is for questions and discussion related to the development of Apache Commons DBCP.
Please do not cross-post; developers are also subscribed to the user list.
You must be subscribed to post to the mailing lists. Follow the Subscribe links below to subscribe.

Note: please don't send patches or attachments to any of the mailing lists; most of the lists are set up to drop attachments. Patches are best handled via the Issue Tracking system. If you have a GitHub account, most components also accept PRs (pull requests). Otherwise, please upload the file to a public server and include the URL in the mail.

Please prefix the subject line of any messages for Apache Commons DBCP with [dbcp] - thanks!

Name Subscribe Unsubscribe Post Archive Other Archives
Commons User List

Questions on using Apache Commons DBCP.

Subscribe Unsubscribe Post lists.apache.org www.mail-archive.com
Commons Developer List

Discussion of development of Apache Commons DBCP.

Subscribe Unsubscribe Post lists.apache.org www.mail-archive.com
Commons Issues List

Only for e-mails automatically generated by the issue tracking system.

Subscribe Unsubscribe read only lists.apache.org www.mail-archive.com
Commons Commits List

Only for e-mails automatically generated by the source control system.

Subscribe Unsubscribe read only lists.apache.org www.mail-archive.com

Other mailing lists which you may find useful include:

Name Subscribe Unsubscribe Post Archive Other Archives
Apache Announce List

General announcements of Apache project releases.

Subscribe Unsubscribe read only lists.apache.org www.mail-archive.com
commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/release-notes-1.1.xml000066400000000000000000000447361472045345700256230ustar00rootroot00000000000000 Release notes for Commons-DBCP 1.1 Commons Documentation Team

There were a lot changes since the 1.0 release on 12 Aug 2002.

  • All existing features can now be configured by JNDI Context providers (Tomcat)

  • The double close() of a pooled connection is more effectively blocked (you may experience more "Already closed" SQLExceptions)

  • Prepared statement pooling is now implemented in BasicDataSource (set poolPreparedStatements=true, maxOpenPreparedStatements=xxx)

  • Access to the underlying connection is blocked by default You can access the underlying connection by setting accessToUnderlyingConnectionAllowed=true and by using the following construct: Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate();

  • New minIdle parameter for a minimum number of idle connections ready for use

  • New connection default properties: defaultCatalog and defaultTransactionIsolation

  • Missing driverClassName will now give the following error "No suitable driver"

  • Bad validationQuery will produce a meaningful SQLException

  • UML Class and sequence diagrams, configuration documentation

  • The following issues were resolved since v1.0: (see Bugzilla for complete description)
    IDDateSevStateSummary
    69342003-09-20BloDUPLSQLTransformer.java - infinite loop in getConnection
    70382002-03-18NorFIXEDBCP does not build under JDK 1.4
    77272002-04-20MajFIXEInfinite loop (stack overflow) in BasicDataSource
    77282002-04-20MajFIXEBasicDataSource cannot use many JDBC drivers
    86202002-04-29NorINVAClosed Connection Exception on setAutoCommit
    90732002-07-20NorFIXEBasicDataSource - invalid connections are not checked
    98502002-07-20NorFIXENo way to get at SQLException if connection to database fail
    105922002-07-20NorDUPLdataSource.getConnection never returns in Tomcat using DBCP
    106142002-07-20NorFIXEDBCP connection pooling broken in Tomcat-4.1.7 (regression)
    106882002-07-20MinFIXEVersion in the Manifest
    109692002-07-20MajFIXEBasicDataSource defaults are unusable
    115072002-08-06NorINVACleanup dead connections
    120472002-11-01NorINVAvalidationQuery + MSSQL
    124002002-11-07NorWORKsame connections
    124092002-11-01BloFIXEConnection can be closed twice
    127332003-02-06NorFIXE[DBCP][PATCH]Statement.getResultSet() doesn't return null if
    128692002-11-01MajFIXEAbandoned Connections are never closed
    130772002-11-07EnhFIXEJdbc2PoolDataSource issues
    131292002-11-01NorFIXECPDSConnectionFactory prints invalid error messages
    131552002-10-30NorDUPLunexpected "exhausted pool" error
    132352002-11-16BloFIXEreferenced UserPassKey instances get erroneously returned to
    139302003-03-06EnhFIXEAdding connection parameters to BasicDataSourceFactory
    139882003-03-17EnhDUPLpermission error makes connection loop
    142672003-04-28MajINVADBCP doesn't work on Tomcat 4.1.12 and Oracle JDBC driver
    145922002-11-15EnhINVADBCP must be robust against e.g. database shutdowns
    146632003-05-14NorREMITomcat5 server hangs when trying to get the database connect
    151232003-08-21MajFIXEIncorrect stack trace shown when abandoned connections are c
    155392003-02-06MajDUPLStrange Result Set on output
    162832003-02-01NorWONTInproper use of Exception
    165812003-03-06MajFIXEDeadlock in AbandonedObjectPool when firewall closes connect
    166292003-03-06NorFIXEorg.apache.commons.dbcp.jdbc2pool.Jdbc2PoolDataSource: setti
    169872003-08-11MajFIXErace condition in PoolableConnection.close()
    170152003-03-06NorFIXEGenericObjectPool.invalidateObject() doesn't work with Aband
    172002003-03-06MajFIXEDBCP: org.apache.commons.dbcp.cpdsadapter.PooledConnectionIm
    173012003-04-08NorWONTNPE in Oracle driver when using DBCP PoolingDataSource
    174562003-04-08EnhFIXEBasicDataSource should use commons-logging
    176352003-03-06MinFIXEPoolableConnectionFactory-Construction declared to throw Exc
    176772003-05-31MajINVAPooled connection architecture vulnerable to double use
    176782003-04-01MajFIXEDBCP Fails silently in many cases
    176802003-03-13MajINVAPoolableConnection.reallyClose() doesn't decrement active co
    179112003-04-07MajWONTProblem with getConnection() and Informix
    180122003-08-26EnhFIXEBasicDataSource doesn't include PreparedStmt Pooling
    184832003-04-08NorWONTAbandonedObjectPool.removeAbandoned never cleans up the trac
    185022003-03-30BloINVAjava.lang.ClassNotFoundException: org.apache.commons.pool.St
    185502003-08-25EnhFIXEAdd defaultTransactionIsolation to BasicDataSource
    188342003-04-08NorFIXEJdbc2PoolDataSource throws a RuntimeException when database
    189052003-08-11NorFIXECouldn't get connection (Jdbc2PoolDataSource)
    189212003-08-11EnhFIXEPer User methods not working in Jdbc2PoolDataSource
    189822003-04-13MajINVABinary distribution missing package
    193742003-08-11NorFIXEPotential for DelegateStatement, DelegateResultSet to be lef
    196142003-08-13MajFIXEPoor performance under load
    196152003-05-02MajINVAUnnecessary global synchronized in AbandonedObjectPool method
    197062003-08-26EnhWONTAdd Initial Commons Logging to DBCP
    206492003-08-11CriINVAdeadlock when acquiring connections from a pool
    211322003-08-11CriDUPLBroken pipe despite validation query set
    211822003-08-21NorINVA[dbcp] removing a webapp does not force connections closed
    212292003-08-11NorFIXEConnectionFactory throws SQLException but implementations do
    212732003-08-11NorFIXEMemory-leak like behaviour in DBCP due to warnings chained t
    214182003-08-11MinFIXEExample code
    214532003-08-11MajINVANullPointerException in DBCP when used for client-server ap
    214582003-08-11NorFIXEStatements and connections don't implement equals()/hashCode
    217482003-08-11NorFIXEBasicDataSource.close() throws NPE
    220782003-08-12NorFIXE[DBCP] testOnBorrow fails if setAutoCommit() throws an excep
    220792003-08-13NorFIXE[DBCP] if connection closed twice *closed* connection is ret
    222142003-08-11MajFIXEDelegating ResultSet causing NPE
    222292003-08-13CriFIXEFoul connection causes livelock of all pool operations
    225982003-08-21EnhFIXEminIdle Functionality for DBCP via Patches Posted for common
    227362003-08-29MajINVAvalidationQuery parameter hangs getConnection method.
    227502003-08-27NorFIXEBasicDataSource always sets testOnBorrow if given a validati
    227762003-09-20NorWONTDBCP should not be writing messages to stderr or stdout
    230662003-09-13MajFIXEDriverManager.getConnection() throws DbcpException
    230812003-09-20NorFIXEDBCP - Bad DB Validation Query Hangs Everything
    231382003-09-13NorFIXEgetDelegate no longer useful since v1.7 of PoolingDataSource
    231572003-09-20EnhFIXEadd defaultCatalog to BasicDataSource
    231852003-09-21NorWONTPoolableConnection.close() won't allow multiple close
    232912003-09-20NorFIXEimpossible to turn off all validation tests when a validatio
    232932003-09-20NorFIXEsetAutoCommit(true) when returning connection to the pool
    233042003-09-21NorFIXENullpointerException when no driverClassName is specified

  • The following issues were resolved since v1.1RC1:
    IDDateSevStateSummary
    227762003-09-30NorFIXEDBCP should not be writing messages to stderr or stdout (removed unneeded logging in AbandonedObjectPool)
    234912003-10-13CriFIXECan't configure PerUserPoolDataSource for use with tomcat, more...

  • The following issues were resolved since v1.1RC2:
    IDDateSevStateSummary
    238432003-10-20BloFIXEPerUserPoolDataSource.getConnection(username, pw) may return connection under wrong username

commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/release-notes-1.2.1.xml000066400000000000000000000044151472045345700257510ustar00rootroot00000000000000 Release notes for Commons-DBCP 1.2.1 Commons Documentation Team

NOTE: DBCP v1.2.1 requires Pool v1.2, make sure you use the correct version!


DBCP 1.2.1 is a maintenance release to restore full JDK 1.3 compatibility.

The problem lies in the improper use of a JDK 1.4 method: java.lang.Boolean.valueOf(boolean)

This method was used in the defaultReadOnly property processing.

We recommend to upgrade to DBCP 1.2.1 to avoid this problem altogether.


If you use the defaultReadOnly property in a JRE <1.4, you will get the following error: java.lang.NoSuchMethodError at org.apache.commons.dbcp.BasicDataSource.setDefaultReadOnly(BasicDataSource.java:75) at org.apache.commons.dbcp.BasicDataSourceFactory.createDataSource(BasicDataSourceFactory.java:162) at org.apache.commons.dbcp.BasicDataSourceFactory.getObjectInstance(BasicDataSourceFactory.java:144) at org.apache.naming.factory.ResourceFactory.getObjectInstance(ResourceFactory.java:176)

The simple workaround is not to use this property. For example remove the following from the tomcat config.xml. defaultReadOnly true ]]>

commons-dbcp-rel-commons-dbcp-2.13.0/src/site/xdoc/release-notes-1.2.xml000066400000000000000000000203611472045345700256100ustar00rootroot00000000000000 Release notes for Commons-DBCP 1.2 Commons Documentation Team

NOTE: DBCP v1.2 requires Pool v1.2, make sure you use the correct version!

There were some new features were added since the 1.1 release on 20 October 2003.

  • Performance optimizations for the PoolableConnectionFactory of BasicDataSource.

  • Add BasicDataSourceFactory.createDataSource(Properties properties) for creating a BasicDataSource.

  • Add initialSize parameter to do pre-loading of the connection.

  • Refactoring of the DelegatingStatement classes.

  • Make some properties dynamic (changeable at runtime), this will be completed in next release.

  • Improvements to the prepared statement pooling.

  • Driver specific changes/optimizations for: Oracle, Informix, DaffodilDB.

  • Several fixes for PerUserPoolDataSource

  • PoolingDriver uses now a PoolGuardConnectionWrapper by default. If access to the underlying connection is needed, you have to enable it: PoolingDriver.setAccessToUnderlyingConnectionAllowed(true)

  • The following issues were resolved since v1.1: (see Bugzilla for complete description)
    IDDateSevStateSummary
    245622003-11-10EnhFIXEPoolingDriver needs a closePool method
    243282003-11-10NorFIXEPooledConnectionImpl ignores resultsetType and Concurrency
    246782003-11-14MajINVADelegatingStatement.getResultSet() never returns null
    250962003-11-30EnhFIXEPoolableConnectionFactory synchronized methods
    250012003-11-30NorFIXEOracle 9i and default isolation settings
    257622003-12-26NorFIXESharedPoolDataSource getConnection() throws ClassCastException
    250672003-12-26NorFIXEPlease give possibility to access ObjectPools from PoolingDriver
    257952003-12-29NorDUPLNumberFormatException: For input string: "myDB"
    257942003-12-29NorFIXEClassNotFoundException: org.apache.xerces.parsers.SAXParser
    249662004-01-06NorFIXENullPointer with Oracle 9 driver
    260722004-01-18NorFIXENull pointer exception being thrown in SQLNestedException
    262622004-01-20MinFIXEDBCP log message in tomcat has incorrect day
    264222004-01-25EnhFIXEAdd BasicDataSourceFactory.createDataSource(Properties properties)
    255142004-02-07EnhFIXEAdd initialSize parameter to do pre-loading of the connection
    240822004-02-28BloFIXENumberFormatException: For input string: "myDB"
    241362004-02-28NorFIXEClassCastException in DriverAdapterCPDS when setPoolPreparedStatements(true)
    272142004-02-29EnhFIXEbad &gt; entity in javadoc
    273202004-02-29NorFIXEDBCP 1.1 incompatible with Informix (driver doesn't support setReadOnly(...))
    274652004-03-07MajFIXEmemory leak in KeyedCPDSConnectionFactory
    269662004-03-07NorWORKConnectionpool's connections always returns same hashCode
    272462004-03-07NorFIXEPreparedStatement cache should be different depending on the Catalog
    274362004-03-08EnhFIXEWith Oracle jdbc driver, an unnecessary SQL "set transaction read write" is issued each time a connection is retrieved from the pool
    285792004-04-25NorFIXENumActive can become incorrect when removeAbandoned=true
    285802004-04-25EnhFIXEAbandonedObjectPool/Trace should log to stdout
    282512004-05-01NorFIXEReturning dead database connections to BasicDataSource
    286882004-05-01CriINVACant Deserialize the Class PerUserPoolDataSource
    288932004-05-12MinFIXEPoolableConnectionFactory has incomplete javadoc on validationQuery
    289122004-05-17MajFIXEConnection re-use conflates logical and physical connections
    290542004-05-20NorFIXEsetTestOnReturn(boolean)
    290552004-05-20NorFIXEAutoCommit and ReadOnly

commons-dbcp-rel-commons-dbcp-2.13.0/src/test/000077500000000000000000000000001472045345700210765ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/000077500000000000000000000000001472045345700220175ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/000077500000000000000000000000001472045345700226065ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/000077500000000000000000000000001472045345700240275ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/000077500000000000000000000000001472045345700255025ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/000077500000000000000000000000001472045345700264745ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/AbstractDriverTest.java000066400000000000000000000030341472045345700331160ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.DriverManager; import java.sql.SQLException; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; /** * Abstracts testing a JDBC driver. */ public abstract class AbstractDriverTest { //private static final String KEY_JDBC_DRIVERS = "jdbc.drivers"; @AfterAll public static void afterClass() throws SQLException { //System.clearProperty(KEY_JDBC_DRIVERS); DriverManager.deregisterDriver(TesterDriver.INSTANCE); } @BeforeAll public static void beforeClass() throws SQLException { //System.setProperty(KEY_JDBC_DRIVERS, "org.apache.commons.dbcp2.TesterDriver"); DriverManager.registerDriver(TesterDriver.INSTANCE); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/Jdbc41BridgeTest.java000066400000000000000000000170651472045345700323340ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.math.BigDecimal; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.h2.jdbcx.JdbcDataSource; import org.junit.jupiter.api.Test; import org.mockito.Mockito; /** * Tests {@link Jdbc41Bridge}. */ public class Jdbc41BridgeTest { private Connection getConnection() throws SQLException { return DriverManager.getConnection("jdbc:h2:mem:test"); } @SuppressWarnings("resource") @Test public void testAbort() throws SQLException { // Normal try (Connection conn = getConnection()) { Jdbc41Bridge.abort(conn, r -> { // empty for now }); } // Force AbstractMethodError try (Connection conn = getConnection()) { final Connection spy = Mockito.spy(conn); Mockito.doThrow(new AbstractMethodError()).when(spy).abort(r -> { // empty for now }); Jdbc41Bridge.abort(spy, r -> { // empty for now }); } } @SuppressWarnings("resource") @Test public void testCloseOnCompletion() throws SQLException { // Normal try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) { Jdbc41Bridge.closeOnCompletion(stmt); } // Force AbstractMethodError try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) { final Statement spy = Mockito.spy(stmt); Mockito.doThrow(new AbstractMethodError()).when(spy).closeOnCompletion(); Jdbc41Bridge.closeOnCompletion(spy); } } @SuppressWarnings("resource") @Test public void testGeneratedKeyAlwaysReturned() throws SQLException { // Normal try (Connection conn = getConnection()) { assertTrue(Jdbc41Bridge.generatedKeyAlwaysReturned(conn.getMetaData())); } // Cannot mock a final class // Force AbstractMethodError // try (Connection conn = getConnection()) { // final DatabaseMetaData spy = Mockito.spy(conn.getMetaData()); // Mockito.when(spy.generatedKeyAlwaysReturned()).thenThrow(AbstractMethodError.class); // assertTrue(Jdbc41Bridge.generatedKeyAlwaysReturned(spy)); // } } @Test public void testGetNetworkTimeout() throws SQLException { // Normal try (Connection conn = getConnection()) { Jdbc41Bridge.setNetworkTimeout(conn, r -> { }, 30_000); // noop in H2 assertEquals(0, Jdbc41Bridge.getNetworkTimeout(conn)); } } @Test public void testGetObjectIndex() throws SQLException { // Normal try (Connection conn = getConnection(); ResultSet rs = conn.getMetaData().getTypeInfo()) { rs.next(); assertNotNull(Jdbc41Bridge.getObject(rs, 1, String.class)); // assertNotNull(Jdbc41Bridge.getObject(rs, 2, Integer.class)); assertNotNull(Jdbc41Bridge.getObject(rs, 2, Long.class)); assertNotNull(Jdbc41Bridge.getObject(rs, 2, Double.class)); assertNotNull(Jdbc41Bridge.getObject(rs, 2, Float.class)); assertNotNull(Jdbc41Bridge.getObject(rs, 2, Byte.class)); assertNotNull(Jdbc41Bridge.getObject(rs, 2, BigDecimal.class)); // assertNotNull(Jdbc41Bridge.getObject(rs, 7, Short.class)); assertNotNull(Jdbc41Bridge.getObject(rs, 8, Boolean.class)); } } @Test public void testGetObjectName() throws SQLException { // Normal try (Connection conn = getConnection(); ResultSet rs = conn.getMetaData().getTypeInfo()) { rs.next(); assertNotNull(Jdbc41Bridge.getObject(rs, "TYPE_NAME", String.class)); // assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Integer.class)); assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Long.class)); assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Double.class)); assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Float.class)); assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", Byte.class)); assertNotNull(Jdbc41Bridge.getObject(rs, "DATA_TYPE", BigDecimal.class)); // assertNotNull(Jdbc41Bridge.getObject(rs, "NULLABLE", Short.class)); assertNotNull(Jdbc41Bridge.getObject(rs, "CASE_SENSITIVE", Boolean.class)); } } @Test public void testGetParentLogger() throws SQLException { // Normal try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) { // returns null for H2 (not supported). Jdbc41Bridge.getParentLogger(new JdbcDataSource()); } } @SuppressWarnings("resource") @Test public void testGetSchema() throws SQLException { // Normal try (Connection conn = getConnection()) { assertNotNull(Jdbc41Bridge.getSchema(conn)); final Connection spy = Mockito.spy(conn); Mockito.when(spy.getSchema()).thenThrow(AbstractMethodError.class); assertNull(Jdbc41Bridge.getSchema(spy)); } } @Test public void testIsCloseOnCompletion() throws SQLException { // Normal try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) { assertFalse(Jdbc41Bridge.isCloseOnCompletion(stmt)); } } @Test public void testSetNetworkTimeout() throws SQLException { // Normal try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) { // noop in H2 Jdbc41Bridge.setNetworkTimeout(conn, r -> { // empty for now }, 30_0000); assertEquals(0, Jdbc41Bridge.getNetworkTimeout(conn)); } } @Test public void testSetSchema() throws SQLException { // Normal try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) { Jdbc41Bridge.setSchema(conn, Jdbc41Bridge.getSchema(conn)); final String expected = "PUBLIC"; Jdbc41Bridge.setSchema(conn, expected); assertEquals(expected, Jdbc41Bridge.getSchema(conn)); } } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java000066400000000000000000000073651472045345700323660ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.EmptyStackException; import java.util.List; import java.util.Stack; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.logging.impl.SimpleLog; /** * A logger that pushes log messages onto a stack. The stack itself is static. * To get a log exclusive to a test case, use explicit lock / unlock and clear. */ public class StackMessageLog extends SimpleLog { private static final long serialVersionUID = 1L; private static final Stack MESSAGE_STACK = new Stack<>(); private static final Lock LOCK = new ReentrantLock(); public static void clear() { LOCK.lock(); try { MESSAGE_STACK.clear(); } finally { LOCK.unlock(); } } /** * Gets a copy of the message stack. *

* Note: lock the stack first. *

* * @return a new list. */ public static List getAll() { return new ArrayList<>(MESSAGE_STACK); } public static boolean isEmpty() { return MESSAGE_STACK.isEmpty(); } /** * Obtains an exclusive lock on the log. */ public static void lock() { LOCK.lock(); } /** * @return the most recent log message, or null if the log is empty */ public static String popMessage() { LOCK.lock(); try { return MESSAGE_STACK.pop(); } catch (final EmptyStackException ex) { // ignore, return null return null; } finally { LOCK.unlock(); } } /** * Relinquishes exclusive lock on the log. */ public static void unLock() { try { LOCK.unlock(); } catch (final IllegalMonitorStateException ex) { // ignore } } public StackMessageLog(final String name) { super(name); } /** * Ignores type. Pushes message followed by stack trace of t onto the stack. */ @Override protected void log(final int type, final Object message, final Throwable t) { LOCK.lock(); try { final StringBuilder buf = new StringBuilder(); buf.append(message.toString()); if (t != null) { buf.append(" <"); buf.append(t.toString()); buf.append(">"); final java.io.StringWriter sw = new StringWriter(1024); try (final java.io.PrintWriter pw = new PrintWriter(sw)) { t.printStackTrace(pw); } buf.append(sw.toString()); } MESSAGE_STACK.push(buf.toString()); } finally { LOCK.unlock(); } } } TestAbandonedBasicDataSource.java000066400000000000000000000407151472045345700347170ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; import java.time.Instant; import org.apache.commons.pool2.KeyedObjectPool; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * TestSuite for BasicDataSource with abandoned connection trace enabled */ public class TestAbandonedBasicDataSource extends TestBasicDataSource { private StringWriter sw; /** * Verifies that con.lastUsed has been updated and then resets it to 0 */ private void assertAndReset(final DelegatingConnection con) { assertTrue(con.getLastUsedInstant().compareTo(Instant.EPOCH) > 0); con.setLastUsed(Instant.EPOCH); } /** * Verifies that PreparedStatement executeXxx methods update lastUsed on the parent connection */ private void checkLastUsedPreparedStatement(final PreparedStatement ps, final DelegatingConnection conn) throws Exception { ps.execute(); assertAndReset(conn); try (ResultSet rs = ps.executeQuery()) { Assertions.assertNotNull(rs); } assertAndReset(conn); ps.executeUpdate(); assertAndReset(conn); } /** * Verifies that Statement executeXxx methods update lastUsed on the parent connection */ private void checkLastUsedStatement(final Statement st, final DelegatingConnection conn) throws Exception { st.execute(""); assertAndReset(conn); st.execute("", new int[] {}); assertAndReset(conn); st.execute("", 0); assertAndReset(conn); st.executeBatch(); assertAndReset(conn); st.executeLargeBatch(); assertAndReset(conn); try (ResultSet rs = st.executeQuery("")) { Assertions.assertNotNull(rs); } assertAndReset(conn); st.executeUpdate(""); assertAndReset(conn); st.executeUpdate("", new int[] {}); assertAndReset(conn); st.executeLargeUpdate("", new int[] {}); assertAndReset(conn); st.executeUpdate("", 0); assertAndReset(conn); st.executeLargeUpdate("", 0); assertAndReset(conn); st.executeUpdate("", new String[] {}); assertAndReset(conn); st.executeLargeUpdate("", new String[] {}); assertAndReset(conn); } private void createStatement(final Connection conn) throws Exception{ final PreparedStatement ps = conn.prepareStatement(""); Assertions.assertNotNull(ps); } @Override @BeforeEach public void setUp() throws Exception { super.setUp(); // abandoned enabled but should not affect the basic tests // (very high timeout) ds.setLogAbandoned(true); ds.setRemoveAbandonedOnBorrow(true); ds.setRemoveAbandonedOnMaintenance(true); ds.setRemoveAbandonedTimeout(Duration.ofSeconds(10)); sw = new StringWriter(); ds.setAbandonedLogWriter(new PrintWriter(sw)); } @Test public void testAbandoned() throws Exception { // force abandoned ds.setRemoveAbandonedTimeout(Duration.ZERO); ds.setMaxTotal(1); for (int i = 0; i < 3; i++) { assertNotNull(ds.getConnection()); } } @Test public void testAbandonedClose() throws Exception { // force abandoned ds.setRemoveAbandonedTimeout(Duration.ZERO); ds.setMaxTotal(1); ds.setAccessToUnderlyingConnectionAllowed(true); try (Connection conn1 = getConnection()) { assertNotNull(conn1); assertEquals(1, ds.getNumActive()); try (Connection conn2 = getConnection()) { // Attempt to borrow object triggers abandoned cleanup // conn1 should be closed by the pool to make room assertNotNull(conn2); assertEquals(1, ds.getNumActive()); // Verify that conn1 is closed assertTrue(((DelegatingConnection) conn1).getInnermostDelegate().isClosed()); // Verify that conn1 is aborted final TesterConnection tCon = (TesterConnection) ((DelegatingConnection) conn1) .getInnermostDelegate(); assertTrue(tCon.isAborted()); } assertEquals(0, ds.getNumActive()); // Second close on conn1 is OK as of dbcp 1.3 } assertEquals(0, ds.getNumActive()); final String string = sw.toString(); assertTrue(string.contains("testAbandonedClose"), string); } @Test public void testAbandonedCloseWithExceptions() throws Exception { // force abandoned ds.setRemoveAbandonedTimeout(Duration.ZERO); ds.setMaxTotal(1); ds.setAccessToUnderlyingConnectionAllowed(true); final Connection conn1 = getConnection(); assertNotNull(conn1); assertEquals(1, ds.getNumActive()); final Connection conn2 = getConnection(); assertNotNull(conn2); assertEquals(1, ds.getNumActive()); // set an IO failure causing the isClosed method to fail final TesterConnection tconn1 = (TesterConnection) ((DelegatingConnection) conn1).getInnermostDelegate(); tconn1.setFailure(new IOException("network error")); final TesterConnection tconn2 = (TesterConnection) ((DelegatingConnection) conn2).getInnermostDelegate(); tconn2.setFailure(new IOException("network error")); try { conn2.close(); } catch (final SQLException ex) { /* Ignore */ } assertEquals(0, ds.getNumActive()); try { conn1.close(); } catch (final SQLException ex) { // ignore } assertEquals(0, ds.getNumActive()); final String string = sw.toString(); assertTrue(string.contains("testAbandonedCloseWithExceptions"), string); } @Test public void testAbandonedStackTraces() throws Exception { // force abandoned ds.setRemoveAbandonedTimeout(Duration.ZERO); ds.setMaxTotal(1); ds.setAccessToUnderlyingConnectionAllowed(true); ds.setAbandonedUsageTracking(true); try (Connection conn1 = getConnection()) { assertNotNull(conn1); assertEquals(1, ds.getNumActive()); // Use the connection try (Statement stmt = conn1.createStatement()) { assertNotNull(stmt); stmt.execute("SELECT 1 FROM DUAL"); } try (Connection conn2 = getConnection()) { // Attempt to borrow object triggers abandoned cleanup // conn1 should be closed by the pool to make room assertNotNull(conn2); assertEquals(1, ds.getNumActive()); // Verify that conn1 is closed assertTrue(((DelegatingConnection) conn1).getInnermostDelegate().isClosed()); // Verify that conn1 is aborted final TesterConnection tCon = (TesterConnection) ((DelegatingConnection) conn1) .getInnermostDelegate(); assertTrue(tCon.isAborted()); } assertEquals(0, ds.getNumActive()); } assertEquals(0, ds.getNumActive()); final String stackTrace = sw.toString(); assertTrue(stackTrace.contains("testAbandonedStackTraces"), stackTrace); assertTrue(stackTrace.contains("Pooled object created"), stackTrace); assertTrue(stackTrace.contains("The last code to use this object was:"), stackTrace); } /** * DBCP-180 - verify that a GC can clean up an unused Statement when it is * no longer referenced even when it is tracked via the AbandonedTrace * mechanism. */ @Test public void testGarbageCollectorCleanUp01() throws Exception { try (DelegatingConnection conn = (DelegatingConnection) ds.getConnection()) { Assertions.assertEquals(0, conn.getTrace().size()); createStatement(conn); Assertions.assertEquals(1, conn.getTrace().size()); System.gc(); Assertions.assertEquals(0, conn.getTrace().size()); } } /** * DBCP-180 - things get more interesting with statement pooling. */ @Test public void testGarbageCollectorCleanUp02() throws Exception { ds.setPoolPreparedStatements(true); ds.setAccessToUnderlyingConnectionAllowed(true); final DelegatingConnection conn = (DelegatingConnection) ds.getConnection(); final PoolableConnection poolableConn = (PoolableConnection) conn.getDelegate(); final PoolingConnection poolingConn = (PoolingConnection) poolableConn.getDelegate(); final KeyedObjectPool gkop = poolingConn.getStatementPool(); Assertions.assertEquals(0, conn.getTrace().size()); Assertions.assertEquals(0, gkop.getNumActive()); createStatement(conn); Assertions.assertEquals(1, conn.getTrace().size()); Assertions.assertEquals(1, gkop.getNumActive()); System.gc(); // Finalization happens in a separate thread. Give the test time for // that to complete. int count = 0; while (count < 50 && gkop.getNumActive() > 0) { Thread.sleep(100); count++; } Assertions.assertEquals(0, gkop.getNumActive()); Assertions.assertEquals(0, conn.getTrace().size()); } /** * Verify that lastUsed property is updated when a connection * creates or prepares a statement */ @Test public void testLastUsed() throws Exception { ds.setRemoveAbandonedTimeout(Duration.ofSeconds(1)); ds.setMaxTotal(2); try (Connection conn1 = ds.getConnection()) { Thread.sleep(500); try (Statement s = conn1.createStatement()) { // Should reset lastUsed } Thread.sleep(800); final Connection conn2 = ds.getConnection(); // triggers abandoned cleanup try (Statement s = conn1.createStatement()) { // Should still be OK } conn2.close(); Thread.sleep(500); try (PreparedStatement ps = conn1.prepareStatement("SELECT 1 FROM DUAL")) { // reset } Thread.sleep(800); try (Connection c = ds.getConnection()) { // trigger abandoned cleanup again } try (Statement s = conn1.createStatement()) { // empty } } } /** * DBCP-343 - verify that using a DelegatingStatement updates * the lastUsed on the parent connection */ @Test public void testLastUsedLargePreparedStatementUse() throws Exception { ds.setRemoveAbandonedTimeout(Duration.ofSeconds(1)); ds.setMaxTotal(2); try (Connection conn1 = ds.getConnection(); Statement st = conn1.createStatement()) { final String querySQL = "SELECT 1 FROM DUAL"; Thread.sleep(500); try (ResultSet rs = st.executeQuery(querySQL)) { Assertions.assertNotNull(rs); // Should reset lastUsed } Thread.sleep(800); try (final Connection conn2 = ds.getConnection()) { // triggers abandoned cleanup try (ResultSet rs = st.executeQuery(querySQL)) { Assertions.assertNotNull(rs); // Should still be OK } } Thread.sleep(500); st.executeLargeUpdate(""); // Should also reset Thread.sleep(800); try (Connection c = ds.getConnection()) { // trigger abandoned cleanup again } try (Statement s = conn1.createStatement()) { // Connection should still be good } } } /** * Verify that lastUsed property is updated when a connection * prepares a callable statement. */ @Test public void testLastUsedPrepareCall() throws Exception { ds.setRemoveAbandonedTimeout(Duration.ofSeconds(1)); ds.setMaxTotal(2); try (Connection conn1 = ds.getConnection()) { Thread.sleep(500); try (CallableStatement cs = conn1.prepareCall("{call home}")) { // Should reset lastUsed } Thread.sleep(800); final Connection conn2 = ds.getConnection(); // triggers abandoned cleanup try (CallableStatement cs = conn1.prepareCall("{call home}")) { // Should still be OK } conn2.close(); Thread.sleep(500); try (CallableStatement cs = conn1.prepareCall("{call home}")) { // reset } Thread.sleep(800); try (Connection c = ds.getConnection()) { // empty } try (Statement s = conn1.createStatement()) { // trigger abandoned cleanup again } } } /** * DBCP-343 - verify that using a DelegatingStatement updates * the lastUsed on the parent connection */ @Test public void testLastUsedPreparedStatementUse() throws Exception { ds.setRemoveAbandonedTimeout(Duration.ofSeconds(1)); ds.setMaxTotal(2); try (Connection conn1 = ds.getConnection(); Statement st = conn1.createStatement()) { final String querySQL = "SELECT 1 FROM DUAL"; Thread.sleep(500); Assertions.assertNotNull(st.executeQuery(querySQL)); // Should reset lastUsed Thread.sleep(800); final Connection conn2 = ds.getConnection(); // triggers abandoned cleanup Assertions.assertNotNull(st.executeQuery(querySQL)); // Should still be OK conn2.close(); Thread.sleep(500); st.executeUpdate(""); // Should also reset Thread.sleep(800); try (Connection c = ds.getConnection()) {} // trigger abandoned cleanup again try (Statement s = conn1.createStatement()) {} // Connection should still be good } } /** * DBCP-343 - verify additional operations reset lastUsed on * the parent connection */ @Test public void testLastUsedUpdate() throws Exception { try (DelegatingConnection conn = (DelegatingConnection) ds.getConnection(); final PreparedStatement ps = conn.prepareStatement(""); final CallableStatement cs = conn.prepareCall(""); final Statement st = conn.prepareStatement("")) { checkLastUsedStatement(ps, conn); checkLastUsedPreparedStatement(ps, conn); checkLastUsedStatement(cs, conn); checkLastUsedPreparedStatement(cs, conn); checkLastUsedStatement(st, conn); } } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestAbandonedTrace.java000066400000000000000000000023751472045345700330400ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import java.sql.SQLException; import org.junit.jupiter.api.Test; /** * Tests {@link AbandonedTrace}. */ public class TestAbandonedTrace { @Test public void testDeprecated() throws SQLException { try (AbandonedTrace trace = new AbandonedTrace()) { assertEquals(trace.getLastUsedInstant().toEpochMilli(), trace.getLastUsed()); } } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java000066400000000000000000001325771472045345700332120ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import javax.management.AttributeNotFoundException; import javax.management.MBeanAttributeInfo; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.sql.DataSource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * TestSuite for BasicDataSource */ public class TestBasicDataSource extends TestConnectionPool { private static final String CATALOG = "test catalog"; protected BasicDataSource ds; protected BasicDataSource createDataSource() throws Exception { return new BasicDataSource(); } @Override protected Connection getConnection() throws Exception { return ds.getConnection(); } @BeforeEach public void setUp() throws Exception { ds = createDataSource(); ds.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); ds.setUrl("jdbc:apache:commons:testdriver"); ds.setMaxTotal(getMaxTotal()); ds.setMaxWait(getMaxWaitDuration()); ds.setDefaultAutoCommit(Boolean.TRUE); ds.setDefaultReadOnly(Boolean.FALSE); ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); ds.setDefaultCatalog(CATALOG); ds.setUsername("userName"); ds.setPassword("password"); ds.setValidationQuery("SELECT DUMMY FROM DUAL"); ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "SELECT 2")); ds.setDriverClassLoader(new TesterClassLoader()); ds.setJmxName("org.apache.commons.dbcp2:name=test"); } @Override @AfterEach public void tearDown() throws Exception { super.tearDown(); ds.close(); ds = null; } @Test public void testAccessToUnderlyingConnectionAllowed() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); assertTrue(ds.isAccessToUnderlyingConnectionAllowed()); try (final Connection conn = getConnection()) { Connection dconn = ((DelegatingConnection) conn).getDelegate(); assertNotNull(dconn); dconn = ((DelegatingConnection) conn).getInnermostDelegate(); assertNotNull(dconn); assertInstanceOf(TesterConnection.class, dconn); } } @Test public void testClose() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); // active connection is held open when ds is closed final Connection activeConnection = getConnection(); final Connection rawActiveConnection = ((DelegatingConnection) activeConnection).getInnermostDelegate(); assertFalse(activeConnection.isClosed()); assertFalse(rawActiveConnection.isClosed()); // idle connection is in pool but closed final Connection idleConnection = getConnection(); final Connection rawIdleConnection = ((DelegatingConnection) idleConnection).getInnermostDelegate(); assertFalse(idleConnection.isClosed()); assertFalse(rawIdleConnection.isClosed()); // idle wrapper should be closed but raw connection should be open idleConnection.close(); assertTrue(idleConnection.isClosed()); assertFalse(rawIdleConnection.isClosed()); ds.close(); // raw idle connection should now be closed assertTrue(rawIdleConnection.isClosed()); // active connection should still be open assertFalse(activeConnection.isClosed()); assertFalse(rawActiveConnection.isClosed()); // now close the active connection activeConnection.close(); // both wrapper and raw active connection should be closed assertTrue(activeConnection.isClosed()); assertTrue(rawActiveConnection.isClosed()); // Verify SQLException on getConnection after close assertThrows(SQLException.class, this::getConnection); // Redundant close is OK ds.close(); } @Test public void testConcurrentInitBorrow() throws Exception { ds.setDriverClassName("org.apache.commons.dbcp2.TesterConnectionDelayDriver"); ds.setUrl("jdbc:apache:commons:testerConnectionDelayDriver:50"); ds.setInitialSize(8); // Launch a request to trigger pool initialization final TestThread testThread = new TestThread(1, 0); final Thread t = new Thread(testThread); t.start(); // Get another connection (should wait for pool init) Thread.sleep(100); // Make sure t gets into init first try (Connection conn = ds.getConnection()) { // Pool should have at least 6 idle connections now // Use underlying pool getNumIdle to avoid waiting for ds lock assertTrue(ds.getConnectionPool().getNumIdle() > 5); // Make sure t completes successfully t.join(); assertFalse(testThread.failed()); } ds.close(); } /** * JIRA: DBCP-444 * Verify that invalidate does not return closed connection to the pool. */ @Test public void testConcurrentInvalidateBorrow() throws Exception { ds.setDriverClassName("org.apache.commons.dbcp2.TesterConnRequestCountDriver"); ds.setUrl("jdbc:apache:commons:testerConnRequestCountDriver"); ds.setTestOnBorrow(true); ds.setValidationQuery("SELECT DUMMY FROM DUAL"); ds.setMaxTotal(8); ds.setLifo(true); ds.setMaxWait(Duration.ofMillis(-1)); // Threads just borrow and return - validation will trigger close check final TestThread testThread1 = new TestThread(1000,0); final Thread t1 = new Thread(testThread1); t1.start(); final TestThread testThread2 = new TestThread(1000,0); final Thread t2 = new Thread(testThread1); t2.start(); // Grab and invalidate connections for (int i = 0; i < 1000; i++) { final Connection conn = ds.getConnection(); ds.invalidateConnection(conn); } // Make sure borrow threads complete successfully t1.join(); t2.join(); assertFalse(testThread1.failed()); assertFalse(testThread2.failed()); ds.close(); } /** * Test disabling MBean registration for Connection objects. * JIRA: DBCP-585 */ @Test public void testConnectionMBeansDisabled() throws Exception { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // Unregister leftovers from other tests (TODO: worry about concurrent test execution) final ObjectName commons = new ObjectName("org.apache.commons.*:*"); final Set results = mbs.queryNames(commons, null); for (final ObjectName result : results) { mbs.unregisterMBean(result); } ds.setRegisterConnectionMBean(false); // Should disable Connection MBean registration try (Connection conn = ds.getConnection()) { // Trigger initialization // No Connection MBeans shall be registered final ObjectName connections = new ObjectName("org.apache.commons.*:connection=*,*"); assertEquals(0, mbs.queryNames(connections, null).size()); } } /** * JIRA: DBCP-547 * Verify that ConnectionFactory interface in BasicDataSource.createConnectionFactory(). */ @Test public void testCreateConnectionFactoryWithConnectionFactoryClassName() throws Exception { Properties properties = new Properties(); // set ConnectionFactoryClassName properties = new Properties(); properties.put("initialSize", "1"); properties.put("driverClassName", "org.apache.commons.dbcp2.TesterDriver"); properties.put("url", "jdbc:apache:commons:testdriver"); properties.put("username", "foo"); properties.put("password", "bar"); properties.put("connectionFactoryClassName", "org.apache.commons.dbcp2.TesterConnectionFactory"); try (BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties)) { try (Connection conn = ds.getConnection()) { assertNotNull(conn); } } } /** * JIRA: DBCP-547 * Verify that ConnectionFactory interface in BasicDataSource.createConnectionFactory(). */ @Test public void testCreateConnectionFactoryWithoutConnectionFactoryClassName() throws Exception { // not set ConnectionFactoryClassName final Properties properties = new Properties(); properties.put("initialSize", "1"); properties.put("driverClassName", "org.apache.commons.dbcp2.TesterDriver"); properties.put("url", "jdbc:apache:commons:testdriver"); properties.put("username", "foo"); properties.put("password", "bar"); try (BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties)) { try (Connection conn = ds.getConnection()) { assertNotNull(conn); } } } /** * JIRA: DBCP-342, DBCP-93 * Verify that when errors occur during BasicDataSource initialization, GenericObjectPool * Evictors are cleaned up. */ @Test public void testCreateDataSourceCleanupEvictor() throws Exception { ds.close(); ds = null; ds = createDataSource(); ds.setDriverClassName("org.apache.commons.dbcp2.TesterConnRequestCountDriver"); ds.setUrl("jdbc:apache:commons:testerConnRequestCountDriver"); ds.setValidationQuery("SELECT DUMMY FROM DUAL"); ds.setUsername("userName"); // Make password incorrect, so createDataSource will throw ds.setPassword("wrong"); // Set timeBetweenEvictionRuns > 0, so evictor will be created ds.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); // Set min idle > 0, so evictor will try to make connection as many as idle count ds.setMinIdle(2); // Prevent concurrent execution of threads executing test subclasses synchronized (TesterConnRequestCountDriver.class) { TesterConnRequestCountDriver.initConnRequestCount(); // user request 10 times for (int i = 0; i < 10; i++) { try { @SuppressWarnings("unused") final DataSource ds2 = ds.createDataSource(); } catch (final SQLException e) { // Ignore } } // sleep 1000ms. evictor will be invoked 10 times if running. Thread.sleep(1000); // Make sure there have been no Evictor-generated requests (count should be 10, from requests above) assertEquals(10, TesterConnRequestCountDriver.getConnectionRequestCount()); } // make sure cleanup is complete assertNull(ds.getConnectionPool()); } /** * JIRA DBCP-93: If an SQLException occurs after the GenericObjectPool is * initialized in createDataSource, the evictor task is not cleaned up. */ @Test public void testCreateDataSourceCleanupThreads() throws Exception { ds.close(); ds = null; ds = createDataSource(); ds.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); ds.setUrl("jdbc:apache:commons:testdriver"); ds.setMaxTotal(getMaxTotal()); ds.setMaxWait(getMaxWaitDuration()); ds.setDefaultAutoCommit(Boolean.TRUE); ds.setDefaultReadOnly(Boolean.FALSE); ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); ds.setDefaultCatalog(CATALOG); ds.setUsername("userName"); // Set timeBetweenEvictionRuns > 0, so evictor is created ds.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); // Make password incorrect, so createDataSource will throw ds.setPassword("wrong"); ds.setValidationQuery("SELECT DUMMY FROM DUAL"); final int threadCount = Thread.activeCount(); for (int i = 0; i < 10; i++) { try (Connection c = ds.getConnection()){ } catch (final SQLException ex) { // ignore } } // Allow one extra thread for JRockit compatibility assertTrue(Thread.activeCount() <= threadCount + 1); } @Test public void testDefaultCatalog() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = getConnection(); assertNotNull(c[i]); assertEquals(CATALOG, c[i].getCatalog()); } for (final Connection element : c) { element.setCatalog("error"); element.close(); } for (int i = 0; i < c.length; i++) { c[i] = getConnection(); assertNotNull(c[i]); assertEquals(CATALOG, c[i].getCatalog()); } for (final Connection element : c) { element.close(); } } @Test public void testDeprecatedAccessors() throws SQLException { try (BasicDataSource bds = new BasicDataSource()) { int i = 0; // i++; bds.setDefaultQueryTimeout(i); assertEquals(i, bds.getDefaultQueryTimeout()); assertEquals(Duration.ofSeconds(i), bds.getDefaultQueryTimeoutDuration()); // i++; bds.setMaxConnLifetimeMillis(i); assertEquals(i, bds.getMaxConnLifetimeMillis()); assertEquals(Duration.ofMillis(i), bds.getMaxConnDuration()); // i++; bds.setMaxWaitMillis(i); assertEquals(i, bds.getMaxWaitMillis()); assertEquals(Duration.ofMillis(i), bds.getMaxWaitDuration()); // i++; bds.setMinEvictableIdleTimeMillis(i); assertEquals(i, bds.getMinEvictableIdleTimeMillis()); assertEquals(Duration.ofMillis(i), bds.getMinEvictableIdleDuration()); // i++; bds.setRemoveAbandonedTimeout(i); assertEquals(i, bds.getRemoveAbandonedTimeout()); assertEquals(Duration.ofSeconds(i), bds.getRemoveAbandonedTimeoutDuration()); // i++; bds.setSoftMinEvictableIdleTimeMillis(i); assertEquals(i, bds.getSoftMinEvictableIdleTimeMillis()); assertEquals(Duration.ofMillis(i), bds.getSoftMinEvictableIdleDuration()); // i++; bds.setTimeBetweenEvictionRunsMillis(i); assertEquals(i, bds.getTimeBetweenEvictionRunsMillis()); assertEquals(Duration.ofMillis(i), bds.getDurationBetweenEvictionRuns()); // i++; bds.setValidationQueryTimeout(1); assertEquals(1, bds.getValidationQueryTimeout()); assertEquals(Duration.ofSeconds(1), bds.getValidationQueryTimeoutDuration()); } } @Test public void testDisconnectionIgnoreSqlCodes() throws Exception { final ArrayList disconnectionIgnoreSqlCodes = new ArrayList<>(); disconnectionIgnoreSqlCodes.add("XXXX"); ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); ds.setFastFailValidation(true); try (Connection conn = ds.getConnection()) { // Triggers initialization - pcf creation // Make sure factory got the properties final PoolableConnectionFactory pcf = (PoolableConnectionFactory) ds.getConnectionPool().getFactory(); assertTrue(pcf.isFastFailValidation()); assertTrue(pcf.getDisconnectionIgnoreSqlCodes().contains("XXXX")); assertEquals(1, pcf.getDisconnectionIgnoreSqlCodes().size()); } } /** * JIRA: DBCP-437 * Verify that BasicDataSource sets disconnect codes properties. * Functionality is verified in pcf tests. */ @Test public void testDisconnectSqlCodes() throws Exception { final ArrayList disconnectionSqlCodes = new ArrayList<>(); disconnectionSqlCodes.add("XXX"); ds.setDisconnectionSqlCodes(disconnectionSqlCodes); ds.setFastFailValidation(true); try (Connection conn = ds.getConnection()) { // Triggers initialization - pcf creation // Make sure factory got the properties final PoolableConnectionFactory pcf = (PoolableConnectionFactory) ds.getConnectionPool().getFactory(); assertTrue(pcf.isFastFailValidation()); assertTrue(pcf.getDisconnectionSqlCodes().contains("XXX")); assertEquals(1, pcf.getDisconnectionSqlCodes().size()); } } /** * JIRA DBCP-333: Check that a custom class loader is used. * @throws Exception */ @Test public void testDriverClassLoader() throws Exception { try (Connection conn = getConnection()) { final ClassLoader cl = ds.getDriverClassLoader(); assertNotNull(cl); assertInstanceOf(TesterClassLoader.class, cl); assertTrue(((TesterClassLoader) cl).didLoad(ds.getDriverClassName())); } } @Test public void testEmptyInitConnectionSql() throws Exception { // List ds.setConnectionInitSqls(Arrays.asList("", " ")); assertNotNull(ds.getConnectionInitSqls()); assertEquals(0, ds.getConnectionInitSqls().size()); // null ds.setConnectionInitSqls(null); assertNotNull(ds.getConnectionInitSqls()); assertEquals(0, ds.getConnectionInitSqls().size()); // Collection ds.setConnectionInitSqls((Collection) Arrays.asList("", " ")); assertNotNull(ds.getConnectionInitSqls()); assertEquals(0, ds.getConnectionInitSqls().size()); } @Test public void testEmptyValidationQuery() throws Exception { assertNotNull(ds.getValidationQuery()); ds.setValidationQuery(""); assertNull(ds.getValidationQuery()); ds.setValidationQuery(" "); assertNull(ds.getValidationQuery()); } @Test @Disabled public void testEvict() throws Exception { final long delay = 1000; ds.setInitialSize(10); ds.setMaxIdle(10); ds.setMaxTotal(10); ds.setMinIdle(5); ds.setNumTestsPerEvictionRun(3); ds.setMinEvictableIdle(Duration.ofMillis(100)); ds.setDurationBetweenEvictionRuns(Duration.ofMillis(delay)); ds.setPoolPreparedStatements(true); try (Connection conn = ds.getConnection()) { // empty } final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); while (Stream.of(threadBean.getThreadInfo(threadBean.getAllThreadIds())).anyMatch(t -> t.getThreadName().equals("commons-pool-evictor-thread"))) { if (ds.getNumIdle() <= ds.getMinIdle()) { break; } Thread.sleep(delay); } if (ds.getNumIdle() > ds.getMinIdle()) { fail("EvictionTimer thread was destroyed with numIdle=" + ds.getNumIdle() + "(expected: less or equal than " + ds.getMinIdle() + ")"); } } @Test public void testInitialSize() throws Exception { ds.setMaxTotal(20); ds.setMaxIdle(20); ds.setInitialSize(10); try (Connection conn = getConnection()) { assertNotNull(conn); } assertEquals(0, ds.getNumActive()); assertEquals(10, ds.getNumIdle()); } /** * JIRA: DBCP-482 * Verify warning not logged if JMX MBean unregistered before close() called. */ @Test public void testInstanceNotFoundExceptionLogSuppressed() throws Exception { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try (Connection c = ds.getConnection()) { // nothing } final ObjectName objectName = new ObjectName(ds.getJmxName()); if (mbs.isRegistered(objectName)) { mbs.unregisterMBean(objectName); } StackMessageLog.clear(); ds.close(); assertNull(StackMessageLog.popMessage()); assertNull(ds.getRegisteredJmxName()); } @Test public void testInvalidateConnection() throws Exception { ds.setMaxTotal(2); try (final Connection conn1 = ds.getConnection()) { try (final Connection conn2 = ds.getConnection()) { ds.invalidateConnection(conn1); assertTrue(conn1.isClosed()); assertEquals(1, ds.getNumActive()); assertEquals(0, ds.getNumIdle()); try (final Connection conn3 = ds.getConnection()) { conn2.close(); } } } } @Test public void testInvalidConnectionInitSqlCollection() { ds.setConnectionInitSqls((Collection) Arrays.asList("SELECT 1", "invalid")); final SQLException e = assertThrows(SQLException.class, ds::getConnection); assertTrue(e.toString().contains("invalid")); } @Test public void testInvalidConnectionInitSqlList() { ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "invalid")); final SQLException e = assertThrows(SQLException.class, ds::getConnection); assertTrue(e.toString().contains("invalid")); } @Test public void testInvalidValidationQuery() { ds.setValidationQuery("invalid"); final SQLException e = assertThrows(SQLException.class, ds::getConnection); assertTrue(e.toString().contains("invalid")); } // Bugzilla Bug 28251: Returning dead database connections to BasicDataSource // isClosed() failure blocks returning a connection to the pool @Test public void testIsClosedFailure() throws SQLException { ds.setAccessToUnderlyingConnectionAllowed(true); final Connection conn = ds.getConnection(); assertNotNull(conn); assertEquals(1, ds.getNumActive()); // set an IO failure causing the isClosed method to fail final TesterConnection tconn = (TesterConnection) ((DelegatingConnection) conn).getInnermostDelegate(); tconn.setFailure(new IOException("network error")); assertThrows(SQLException.class, () -> conn.close()); assertEquals(0, ds.getNumActive()); } @Test public void testIsWrapperFor() throws Exception { assertTrue(ds.isWrapperFor(BasicDataSource.class)); assertTrue(ds.isWrapperFor(AutoCloseable.class)); assertFalse(ds.isWrapperFor(String.class)); assertFalse(ds.isWrapperFor(null)); } /** * Make sure setting jmxName to null suppresses JMX registration of connection and statement pools. * JIRA: DBCP-434 */ @Test public void testJmxDisabled() throws Exception { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // Unregister leftovers from other tests (TODO: worry about concurrent test execution) final ObjectName commons = new ObjectName("org.apache.commons.*:*"); final Set results = mbs.queryNames(commons, null); for (final ObjectName result : results) { mbs.unregisterMBean(result); } ds.setJmxName(null); // Should disable JMX for both connection and statement pools ds.setPoolPreparedStatements(true); try (Connection conn = ds.getConnection()) { // Trigger initialization // Nothing should be registered assertEquals(0, mbs.queryNames(commons, null).size()); } } /** * Tests JIRA DBCP-562. *

* Make sure Password Attribute is not exported via JMXBean. *

*/ @Test public void testJmxDoesNotExposePassword() throws Exception { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try (Connection c = ds.getConnection()) { // nothing } final ObjectName objectName = new ObjectName(ds.getJmxName()); final MBeanAttributeInfo[] attributes = mbs.getMBeanInfo(objectName).getAttributes(); assertTrue(attributes != null && attributes.length > 0); Arrays.asList(attributes).forEach(attrInfo -> assertFalse("password".equalsIgnoreCase(attrInfo.getName()))); assertThrows(AttributeNotFoundException.class, () -> mbs.getAttribute(objectName, "Password")); } @Test public void testManualConnectionEvict() throws Exception { ds.setMinIdle(0); ds.setMaxIdle(4); ds.setMinEvictableIdle(Duration.ofMillis(10)); ds.setNumTestsPerEvictionRun(2); try (Connection ds2 = ds.createDataSource().getConnection(); Connection ds3 = ds.createDataSource().getConnection()) { assertEquals(0, ds.getNumIdle()); } // Make sure MinEvictableIdleTimeMillis has elapsed Thread.sleep(100); // Ensure no connections evicted by eviction thread assertEquals(2, ds.getNumIdle()); // Force Eviction ds.evict(); // Ensure all connections evicted assertEquals(0, ds.getNumIdle()); } @Test public void testMaxConnLifetimeExceeded() throws Exception { try { StackMessageLog.lock(); ds.setMaxConn(Duration.ofMillis(100)); try (Connection conn = ds.getConnection()) { assertEquals(1, ds.getNumActive()); Thread.sleep(500); } assertEquals(0, ds.getNumIdle()); final String message = StackMessageLog.popMessage(); Assertions.assertNotNull(message); assertTrue(message.indexOf("exceeds the maximum permitted value") > 0); } finally { StackMessageLog.clear(); StackMessageLog.unLock(); } } @Test public void testMaxConnLifetimeExceededMutedLog() throws Exception { try { StackMessageLog.lock(); StackMessageLog.clear(); ds.setMaxConn(Duration.ofMillis(100)); ds.setLogExpiredConnections(false); try (final Connection conn = ds.getConnection()) { assertEquals(1, ds.getNumActive()); Thread.sleep(500); } assertEquals(0, ds.getNumIdle()); assertTrue(StackMessageLog.isEmpty(), StackMessageLog.getAll().toString()); } finally { StackMessageLog.clear(); StackMessageLog.unLock(); } } /** * Bugzilla Bug 29832: Broken behavior for BasicDataSource.setMaxTotal(0) * MaxTotal == 0 should throw SQLException on getConnection. * Results from Bug 29863 in commons-pool. */ @Test public void testMaxTotalZero() throws Exception { ds.setMaxTotal(0); assertThrows(SQLException.class, ds::getConnection); } /** * JIRA: DBCP-457 * Verify that changes made to abandoned config are passed to the underlying * pool. */ @Test public void testMutateAbandonedConfig() throws Exception { final Properties properties = new Properties(); properties.put("initialSize", "1"); properties.put("driverClassName", "org.apache.commons.dbcp2.TesterDriver"); properties.put("url", "jdbc:apache:commons:testdriver"); properties.put("username", "foo"); properties.put("password", "bar"); try (BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties)) { final boolean original = ds.getConnectionPool().getLogAbandoned(); ds.setLogAbandoned(!original); Assertions.assertNotEquals(original, ds.getConnectionPool().getLogAbandoned()); } } @Test public void testNoAccessToUnderlyingConnectionAllowed() throws Exception { // default: false assertFalse(ds.isAccessToUnderlyingConnectionAllowed()); try (Connection conn = getConnection()) { Connection dconn = ((DelegatingConnection) conn).getDelegate(); assertNull(dconn); dconn = ((DelegatingConnection) conn).getInnermostDelegate(); assertNull(dconn); } } @Test public void testNoOverlapBetweenDisconnectionAndIgnoreSqlCodes() { // Set disconnection SQL codes without overlap final HashSet disconnectionSqlCodes = new HashSet<>(Arrays.asList("XXX", "ZZZ")); ds.setDisconnectionSqlCodes(disconnectionSqlCodes); // Set ignore SQL codes without overlap final HashSet disconnectionIgnoreSqlCodes = new HashSet<>(Arrays.asList("YYY", "AAA")); ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); assertEquals(disconnectionSqlCodes, ds.getDisconnectionSqlCodes(), "Disconnection SQL codes should match the set values."); assertEquals(disconnectionIgnoreSqlCodes, ds.getDisconnectionIgnoreSqlCodes(), "Disconnection Ignore SQL codes should match the set values."); } @Test public void testOverlapBetweenDisconnectionAndIgnoreSqlCodes() { // Set initial disconnection SQL codes final HashSet disconnectionSqlCodes = new HashSet<>(Arrays.asList("XXX", "ZZZ")); ds.setDisconnectionSqlCodes(disconnectionSqlCodes); // Try setting ignore SQL codes with overlap final HashSet disconnectionIgnoreSqlCodes = new HashSet<>(Arrays.asList("YYY", "XXX")); final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes)); assertEquals("[XXX] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); } /** * Verifies correct handling of exceptions generated by the underlying pool as it closes * connections in response to BDS#close. Exceptions have to be either swallowed by the * underlying pool and logged, or propagated and wrapped. */ @Test public void testPoolCloseCheckedException() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); // Allow dirty tricks final TesterConnection tc; // Get an idle connection into the pool try (Connection conn = ds.getConnection()) { tc = (TesterConnection) ((DelegatingConnection) conn).getInnermostDelegate(); } // After returning the connection to the pool, bork it. // Don't try this at home - bad violation of pool contract! tc.setFailure(new SQLException("bang")); // Now close Datasource, which will cause tc to be closed, triggering SQLE // Pool 2.x swallows and logs exceptions on pool close. Below verifies that // Either exceptions get logged or wrapped appropriately. try { StackMessageLog.lock(); StackMessageLog.clear(); ds.close(); // Exception must have been swallowed by the pool - verify it is logged final String message = StackMessageLog.popMessage(); Assertions.assertNotNull(message); assertTrue(message.indexOf("bang") > 0); } catch (final SQLException ex) { assertTrue(ex.getMessage().indexOf("Cannot close") > 0); assertTrue(ex.getCause().getMessage().indexOf("bang") > 0); } finally { StackMessageLog.unLock(); } } @Test public void testPoolCloseRTE() throws Exception { // RTE version of testPoolCloseCheckedException - see comments there. ds.setAccessToUnderlyingConnectionAllowed(true); final TesterConnection tc; try (Connection conn = ds.getConnection()) { tc = (TesterConnection) ((DelegatingConnection) conn).getInnermostDelegate(); } tc.setFailure(new IllegalStateException("boom")); try { StackMessageLog.lock(); StackMessageLog.clear(); ds.close(); final String message = StackMessageLog.popMessage(); Assertions.assertNotNull(message); assertTrue(message.indexOf("boom") > 0); } catch (final IllegalStateException ex) { assertTrue(ex.getMessage().indexOf("boom") > 0); // RTE is not wrapped by BDS#close } finally { StackMessageLog.unLock(); } } @Override @Test public void testPooling() throws Exception { // this also needs access to the underlying connection ds.setAccessToUnderlyingConnectionAllowed(true); super.testPooling(); } /** * Bugzilla Bug 29054: * The BasicDataSource.setTestOnReturn(boolean) is not carried through to * the GenericObjectPool variable _testOnReturn. */ @Test public void testPropertyTestOnReturn() throws Exception { ds.setValidationQuery("select 1 from dual"); ds.setTestOnBorrow(false); ds.setTestWhileIdle(false); ds.setTestOnReturn(true); try (Connection conn = ds.getConnection()) { assertNotNull(conn); assertFalse(ds.getConnectionPool().getTestOnBorrow()); assertFalse(ds.getConnectionPool().getTestWhileIdle()); assertTrue(ds.getConnectionPool().getTestOnReturn()); } } @Test public void testRestart() throws Exception { ds.setMaxTotal(2); ds.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); ds.setNumTestsPerEvictionRun(2); ds.setMinEvictableIdle(Duration.ofMinutes(1)); ds.setInitialSize(2); ds.setDefaultCatalog("foo"); try (Connection conn1 = ds.getConnection()) { Thread.sleep(200); // Now set some property that will not have effect until restart ds.setDefaultCatalog("bar"); ds.setInitialSize(1); // restart will load new properties ds.restart(); assertEquals("bar", ds.getDefaultCatalog()); assertEquals(1, ds.getInitialSize()); ds.getLogWriter(); // side effect is to init assertEquals(0, ds.getNumActive()); assertEquals(1, ds.getNumIdle()); } // verify old pool connection is not returned to pool assertEquals(1, ds.getNumIdle()); ds.close(); } /** * Bugzilla Bug 29055: AutoCommit and ReadOnly * The DaffodilDB driver throws an SQLException if * trying to commit or rollback a readOnly connection. */ @Test public void testRollbackReadOnly() throws Exception { ds.setDefaultReadOnly(Boolean.TRUE); ds.setDefaultAutoCommit(Boolean.FALSE); try (Connection conn = ds.getConnection()) { assertNotNull(conn); } } @Test public void testSetAutoCommitTrueOnClose() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); ds.setDefaultAutoCommit(Boolean.FALSE); final Connection dconn; try (Connection conn = getConnection()) { assertNotNull(conn); assertFalse(conn.getAutoCommit()); dconn = ((DelegatingConnection) conn).getInnermostDelegate(); assertNotNull(dconn); assertFalse(dconn.getAutoCommit()); } assertTrue(dconn.getAutoCommit()); } @Test public void testSetProperties() throws Exception { // normal ds.setConnectionProperties("name1=value1;name2=value2;name3=value3"); assertEquals(3, ds.getConnectionProperties().size()); assertEquals("value1", ds.getConnectionProperties().getProperty("name1")); assertEquals("value2", ds.getConnectionProperties().getProperty("name2")); assertEquals("value3", ds.getConnectionProperties().getProperty("name3")); // make sure all properties are replaced ds.setConnectionProperties("name1=value1;name2=value2"); assertEquals(2, ds.getConnectionProperties().size()); assertEquals("value1", ds.getConnectionProperties().getProperty("name1")); assertEquals("value2", ds.getConnectionProperties().getProperty("name2")); assertFalse(ds.getConnectionProperties().containsKey("name3")); // no value is empty string ds.setConnectionProperties("name1=value1;name2"); assertEquals(2, ds.getConnectionProperties().size()); assertEquals("value1", ds.getConnectionProperties().getProperty("name1")); assertEquals("", ds.getConnectionProperties().getProperty("name2")); // no value (with equals) is empty string ds.setConnectionProperties("name1=value1;name2="); assertEquals(2, ds.getConnectionProperties().size()); assertEquals("value1", ds.getConnectionProperties().getProperty("name1")); assertEquals("", ds.getConnectionProperties().getProperty("name2")); // single value ds.setConnectionProperties("name1=value1"); assertEquals(1, ds.getConnectionProperties().size()); assertEquals("value1", ds.getConnectionProperties().getProperty("name1")); // single value with trailing ; ds.setConnectionProperties("name1=value1;"); assertEquals(1, ds.getConnectionProperties().size()); assertEquals("value1", ds.getConnectionProperties().getProperty("name1")); // single value wit no value ds.setConnectionProperties("name1"); assertEquals(1, ds.getConnectionProperties().size()); assertEquals("", ds.getConnectionProperties().getProperty("name1")); // null should throw a NullPointerException assertThrows(NullPointerException.class, () -> ds.setConnectionProperties(null)); } @Test public void testSetValidationTestProperties() { // defaults assertTrue(ds.getTestOnBorrow()); assertFalse(ds.getTestOnReturn()); assertFalse(ds.getTestWhileIdle()); ds.setTestOnBorrow(true); ds.setTestOnReturn(true); ds.setTestWhileIdle(true); assertTrue(ds.getTestOnBorrow()); assertTrue(ds.getTestOnReturn()); assertTrue(ds.getTestWhileIdle()); ds.setTestOnBorrow(false); ds.setTestOnReturn(false); ds.setTestWhileIdle(false); assertFalse(ds.getTestOnBorrow()); assertFalse(ds.getTestOnReturn()); assertFalse(ds.getTestWhileIdle()); } @Test public void testStart() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); ds.setMaxTotal(2); final DelegatingConnection conn1 = (DelegatingConnection) ds.getConnection(); final DelegatingConnection conn2 = (DelegatingConnection) ds.getConnection(); final Connection inner1 = conn1.getInnermostDelegate(); final Connection inner2 = conn2.getInnermostDelegate(); assertFalse(inner2.isClosed()); conn2.close(); assertFalse(inner2.isClosed()); // One active, one idle in the pool ds.close(); // Idle connection should be physically closed, checked out unaffected assertFalse(conn1.isClosed()); assertTrue(inner2.isClosed()); assertEquals(0, ds.getNumIdle()); // Reopen creates a new pool, so we can have three out ds.start(); final Connection conn3 = ds.getConnection(); final Connection conn4 = ds.getConnection(); conn3.close(); conn4.close(); // Old pool's orphan should get physically closed on return conn1.close(); assertTrue(inner1.isClosed()); } @Test public void testStartInitializes() throws Exception { ds.setInitialSize(2); // Note: if we ever move away from lazy init, next two will fail assertEquals(0, ds.getNumIdle()); assertNull(ds.getRegisteredJmxName()); // Start forces init ds.start(); assertEquals(2, ds.getNumIdle()); assertNotNull(ds.getRegisteredJmxName()); } @Test public void testTransactionIsolationBehavior() throws Exception { try (final Connection conn = getConnection()) { assertNotNull(conn); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn.getTransactionIsolation()); conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); } final Connection conn2 = getConnection(); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn2.getTransactionIsolation()); final Connection conn3 = getConnection(); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn3.getTransactionIsolation()); conn2.close(); conn3.close(); } @Test public void testUnwrap() throws Exception { assertSame(ds.unwrap(BasicDataSource.class), ds); assertSame(ds.unwrap(AutoCloseable.class), ds); assertThrows(SQLException.class, () -> ds.unwrap(String.class)); assertThrows(SQLException.class, () -> ds.unwrap(null)); } @Test public void testValidationQueryTimeoutNegative() throws Exception { ds.setTestOnBorrow(true); ds.setTestOnReturn(true); ds.setValidationQueryTimeout(Duration.ofSeconds(-1)); try (final Connection con = ds.getConnection()) { // close right away. } } @Test public void testValidationQueryTimeoutSucceed() throws Exception { ds.setTestOnBorrow(true); ds.setTestOnReturn(true); ds.setValidationQueryTimeout(Duration.ofMillis(100)); // Works for TesterStatement try (final Connection con = ds.getConnection()) { // close right away. } } @Test public void testValidationQueryTimeoutZero() throws Exception { ds.setTestOnBorrow(true); ds.setTestOnReturn(true); ds.setValidationQueryTimeout(Duration.ZERO); try (final Connection con = ds.getConnection()) { // close right away. } } @Test public void testValidationQueryTimoutFail() { ds.setTestOnBorrow(true); ds.setValidationQueryTimeout(Duration.ofSeconds(3)); // Too fast for TesterStatement final SQLException e = assertThrows(SQLException.class, ds::getConnection); assertTrue(e.toString().contains("timeout")); } } /** * TesterDriver that adds latency to connection requests. Latency (in ms) is the * last component of the URL. */ final class TesterConnectionDelayDriver extends TesterDriver { private static final String CONNECT_STRING = "jdbc:apache:commons:testerConnectionDelayDriver"; public TesterConnectionDelayDriver() { // DBCP expects an explicit no-arg constructor } @Override public boolean acceptsURL(final String url) throws SQLException { return url.startsWith(CONNECT_STRING); } @Override public Connection connect(final String url, final Properties info) throws SQLException { final String[] parsedUrl = url.split(":"); final int delay = Integer.parseInt(parsedUrl[parsedUrl.length - 1]); try { Thread.sleep(delay); } catch (final InterruptedException ex) { Thread.currentThread().interrupt(); } return super.connect(url, info); } } /** * TesterDriver that keeps a static count of connection requests. */ final class TesterConnRequestCountDriver extends TesterDriver { private static final String CONNECT_STRING = "jdbc:apache:commons:testerConnRequestCountDriver"; private static final AtomicInteger connectionRequestCount = new AtomicInteger(); public static int getConnectionRequestCount() { return connectionRequestCount.get(); } public static void initConnRequestCount() { connectionRequestCount.set(0); } public TesterConnRequestCountDriver() { // DBCP expects an explicit no-arg constructor } @Override public boolean acceptsURL(final String url) throws SQLException { return CONNECT_STRING.startsWith(url); } @Override public Connection connect(final String url, final Properties info) throws SQLException { connectionRequestCount.incrementAndGet(); return super.connect(url, info); } } TestBasicDataSourceFactory.java000066400000000000000000000252041472045345700344470ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.management.ManagementFactory; import java.sql.Connection; import java.time.Duration; import java.util.List; import java.util.Map.Entry; import java.util.Properties; import javax.management.MBeanServer; import javax.naming.Reference; import javax.naming.StringRefAddr; import org.apache.commons.pool2.impl.GenericObjectPool; import org.junit.jupiter.api.Test; /** * TestSuite for BasicDataSourceFactory */ public class TestBasicDataSourceFactory { private void checkConnectionPoolProperties(final GenericObjectPool cp) { assertEquals(10, cp.getMaxTotal()); assertEquals(8, cp.getMaxIdle()); assertEquals(0, cp.getMinIdle()); assertEquals(Duration.ofMillis(500), cp.getMaxWaitDuration()); assertEquals(5, cp.getNumIdle()); assertTrue(cp.getTestOnBorrow()); assertFalse(cp.getTestOnReturn()); assertEquals(Duration.ofSeconds(1), cp.getDurationBetweenEvictionRuns()); assertEquals(Duration.ofSeconds(2), cp.getMinEvictableIdleDuration()); assertEquals(Duration.ofSeconds(3), cp.getSoftMinEvictableIdleDuration()); assertEquals(2, cp.getNumTestsPerEvictionRun()); assertTrue(cp.getTestWhileIdle()); assertTrue(cp.getRemoveAbandonedOnBorrow()); assertTrue(cp.getRemoveAbandonedOnMaintenance()); assertEquals(Duration.ofSeconds(3000), cp.getRemoveAbandonedTimeoutDuration()); assertTrue(cp.getLogAbandoned()); assertTrue(cp.getLifo()); } private void checkDataSourceProperties(final BasicDataSource ds) throws Exception { assertEquals("org.apache.commons.dbcp2.TesterDriver", ds.getDriverClassName()); assertEquals("jdbc:apache:commons:testdriver", ds.getUrl()); assertEquals(10, ds.getMaxTotal()); assertEquals(8, ds.getMaxIdle()); assertEquals(0, ds.getMinIdle()); assertEquals(Duration.ofMillis(500), ds.getMaxWaitDuration()); assertEquals(5, ds.getInitialSize()); assertEquals(5, ds.getNumIdle()); assertEquals(Boolean.TRUE, ds.getDefaultAutoCommit()); assertEquals(Boolean.FALSE, ds.getDefaultReadOnly()); assertEquals(Connection.TRANSACTION_READ_COMMITTED, ds.getDefaultTransactionIsolation()); assertEquals("test", ds.getDefaultCatalog()); assertEquals("testSchema", ds.getDefaultSchema()); assertTrue(ds.getTestOnBorrow()); assertFalse(ds.getTestOnReturn()); assertEquals("userName", ds.getUsername()); assertEquals("userName", ds.getUserName()); assertEquals("password", ds.getPassword()); assertEquals("SELECT DUMMY FROM DUAL", ds.getValidationQuery()); assertEquals(Duration.ofSeconds(100), ds.getValidationQueryTimeoutDuration()); assertEquals(2, ds.getConnectionInitSqls().size()); assertEquals("SELECT 1", ds.getConnectionInitSqls().get(0)); assertEquals("SELECT 2", ds.getConnectionInitSqls().get(1)); assertEquals(Duration.ofMillis(1000), ds.getDurationBetweenEvictionRuns()); assertEquals(Duration.ofMillis(2000), ds.getMinEvictableIdleDuration()); assertEquals(Duration.ofMillis(3000), ds.getSoftMinEvictableIdleDuration()); assertEquals(2, ds.getNumTestsPerEvictionRun()); assertTrue(ds.getTestWhileIdle()); assertTrue(ds.isAccessToUnderlyingConnectionAllowed()); assertTrue(ds.getRemoveAbandonedOnBorrow()); assertTrue(ds.getRemoveAbandonedOnMaintenance()); assertEquals(Duration.ofSeconds(3000), ds.getRemoveAbandonedTimeoutDuration()); assertTrue(ds.getLogAbandoned()); assertTrue(ds.getAbandonedUsageTracking()); assertTrue(ds.isPoolPreparedStatements()); assertTrue(ds.isClearStatementPoolOnReturn()); assertEquals(10, ds.getMaxOpenPreparedStatements()); assertTrue(ds.getLifo()); assertTrue(ds.getFastFailValidation()); assertTrue(ds.getDisconnectionSqlCodes().contains("XXX")); assertTrue(ds.getDisconnectionSqlCodes().contains("YYY")); assertEquals("org.apache.commons.dbcp2:name=test", ds.getJmxName()); // Unregister so subsequent calls to getTestProperties can re-register final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); mbs.unregisterMBean(ds.getRegisteredJmxName()); } private Properties getTestProperties() { final Properties properties = new Properties(); properties.setProperty("driverClassName", "org.apache.commons.dbcp2.TesterDriver"); properties.setProperty("url", "jdbc:apache:commons:testdriver"); properties.setProperty("maxTotal", "10"); properties.setProperty("maxIdle", "8"); properties.setProperty("minIdle", "0"); properties.setProperty("maxWaitMillis", "500"); properties.setProperty("initialSize", "5"); properties.setProperty("defaultAutoCommit", "true"); properties.setProperty("defaultReadOnly", "false"); properties.setProperty("defaultTransactionIsolation", "READ_COMMITTED"); properties.setProperty("defaultCatalog", "test"); properties.setProperty("defaultSchema", "testSchema"); properties.setProperty("testOnBorrow", "true"); properties.setProperty("testOnReturn", "false"); properties.setProperty("username", "userName"); properties.setProperty("password", "password"); properties.setProperty("validationQuery", "SELECT DUMMY FROM DUAL"); properties.setProperty("validationQueryTimeout", "100"); properties.setProperty("connectionInitSqls", "SELECT 1;SELECT 2"); properties.setProperty("timeBetweenEvictionRunsMillis", "1000"); properties.setProperty("minEvictableIdleTimeMillis", "2000"); properties.setProperty("softMinEvictableIdleTimeMillis", "3000"); properties.setProperty("numTestsPerEvictionRun", "2"); properties.setProperty("testWhileIdle", "true"); properties.setProperty("accessToUnderlyingConnectionAllowed", "true"); properties.setProperty("removeAbandonedOnBorrow", "true"); properties.setProperty("removeAbandonedOnMaintenance", "true"); properties.setProperty("removeAbandonedTimeout", "3000"); properties.setProperty("logAbandoned", "true"); properties.setProperty("abandonedUsageTracking", "true"); properties.setProperty("poolPreparedStatements", "true"); properties.setProperty("clearStatementPoolOnReturn", "true"); properties.setProperty("maxOpenPreparedStatements", "10"); properties.setProperty("lifo", "true"); properties.setProperty("fastFailValidation", "true"); properties.setProperty("disconnectionSqlCodes", "XXX,YYY"); properties.setProperty("jmxName", "org.apache.commons.dbcp2:name=test"); return properties; } @Test public void testAllProperties() throws Exception { try { StackMessageLog.lock(); StackMessageLog.clear(); final Reference ref = new Reference("javax.sql.DataSource", BasicDataSourceFactory.class.getName(), null); final Properties properties = getTestProperties(); for (final Entry entry : properties.entrySet()) { ref.add(new StringRefAddr((String) entry.getKey(), (String) entry.getValue())); } final BasicDataSourceFactory basicDataSourceFactory = new BasicDataSourceFactory(); try (final BasicDataSource ds = (BasicDataSource) basicDataSourceFactory.getObjectInstance(ref, null, null, null)) { checkDataSourceProperties(ds); checkConnectionPoolProperties(ds.getConnectionPool()); final List messages = StackMessageLog.getAll(); assertEquals(0, messages.size()); } } finally { StackMessageLog.clear(); StackMessageLog.unLock(); } } @Test public void testNoProperties() throws Exception { final Properties properties = new Properties(); try (final BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties)) { assertNotNull(ds); } } @Test public void testProperties() throws Exception { try (final BasicDataSource ds = BasicDataSourceFactory.createDataSource(getTestProperties())) { checkDataSourceProperties(ds); } } @Test public void testValidateProperties() throws Exception { try { StackMessageLog.lock(); StackMessageLog.clear(); final Reference ref = new Reference("javax.sql.DataSource", BasicDataSourceFactory.class.getName(), null); ref.add(new StringRefAddr("foo", "bar")); // Unknown ref.add(new StringRefAddr("maxWait", "100")); // Changed ref.add(new StringRefAddr("driverClassName", "org.apache.commons.dbcp2.TesterDriver")); // OK final BasicDataSourceFactory basicDataSourceFactory = new BasicDataSourceFactory(); basicDataSourceFactory.getObjectInstance(ref, null, null, null); final List messages = StackMessageLog.getAll(); assertEquals(2, messages.size(), messages.toString()); for (final String message : messages) { if (message.contains("maxWait")) { assertTrue(message.contains("use maxWaitMillis")); } else { assertTrue(message.contains("foo")); assertTrue(message.contains("Ignoring unknown property")); } } } finally { StackMessageLog.clear(); StackMessageLog.unLock(); } } } TestBasicDataSourceMXBean.java000066400000000000000000000143531472045345700341550ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.management.ManagementFactory; import javax.management.JMX; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.OperationsException; import org.junit.jupiter.api.Test; /** * Tests for BasicDataSourceMXBean. */ public class TestBasicDataSourceMXBean { public static void testMXBeanCompliance(final Class clazz) throws OperationsException { assertTrue(JMX.isMXBeanInterface(clazz)); final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); final ObjectName objectName = ObjectName.getInstance("com.sun.management:type=DiagnosticCommand"); JMX.newMBeanProxy(server, objectName, clazz, true); } private final BasicDataSourceMXBean bean = new BasicDataSourceMXBean() { @Override public boolean getAbandonedUsageTracking() { return false; } @Override public boolean getCacheState() { return false; } @Override public String[] getConnectionInitSqlsAsArray() { return null; } @Override public Boolean getDefaultAutoCommit() { return null; } @Override public String getDefaultCatalog() { return null; } @Override public Boolean getDefaultReadOnly() { return null; } @Override public int getDefaultTransactionIsolation() { return 0; } @Override public String[] getDisconnectionIgnoreSqlCodesAsArray() { return null; } @Override public String[] getDisconnectionSqlCodesAsArray() { return null; } @Override public String getDriverClassName() { return null; } @Override public boolean getFastFailValidation() { return false; } @Override public int getInitialSize() { return 0; } @Override public boolean getLifo() { return false; } @Override public boolean getLogAbandoned() { return false; } @Override public boolean getLogExpiredConnections() { return false; } @Override public long getMaxConnLifetimeMillis() { return 0; } @Override public int getMaxIdle() { return 0; } @Override public int getMaxOpenPreparedStatements() { return 0; } @Override public int getMaxTotal() { return 0; } @Override public long getMaxWaitMillis() { return 0; } @Override public long getMinEvictableIdleTimeMillis() { return 0; } @Override public int getMinIdle() { return 0; } @Override public int getNumActive() { return 0; } @Override public int getNumIdle() { return 0; } @Override public int getNumTestsPerEvictionRun() { return 0; } @Override public String getPassword() { return null; } @Override public boolean getRemoveAbandonedOnBorrow() { return false; } @Override public boolean getRemoveAbandonedOnMaintenance() { return false; } @Override public int getRemoveAbandonedTimeout() { return 0; } @Override public long getSoftMinEvictableIdleTimeMillis() { return 0; } @Override public boolean getTestOnBorrow() { return false; } @Override public boolean getTestOnCreate() { return false; } @Override public boolean getTestWhileIdle() { return false; } @Override public long getTimeBetweenEvictionRunsMillis() { return 0; } @Override public String getUrl() { return null; } @Override public String getUsername() { return null; } @Override public String getValidationQuery() { return null; } @Override public int getValidationQueryTimeout() { return 0; } @Override public boolean isAccessToUnderlyingConnectionAllowed() { return false; } @Override public boolean isClearStatementPoolOnReturn() { return false; } @Override public boolean isClosed() { return false; } @Override public boolean isPoolPreparedStatements() { return false; } }; /** * Tests the interface defined default method. */ @Test public void testDefaultSchema() { assertNull(bean.getDefaultSchema()); } /** * Tests if the {@link BasicDataSourceMXBean} interface is a valid MXBean interface. */ @Test public void testMXBeanCompliance() throws OperationsException { testMXBeanCompliance(BasicDataSourceMXBean.class); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestConnectionPool.java000066400000000000000000001105171472045345700331350ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; import java.util.Hashtable; import java.util.Random; import java.util.Stack; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; // XXX FIX ME XXX // this class still needs some cleanup, but at least // this consolidates most of the relevant test code // in a fairly re-usable fashion // XXX FIX ME XXX /** * Base test suite for DBCP pools. */ public abstract class TestConnectionPool { protected class PoolTest implements Runnable { /** * The number of milliseconds to hold onto a database connection */ private final Duration connHoldDuration; private final int numStatements; private volatile boolean isRun; private String state; // No need to be volatile if it is read after the thread finishes private final Thread thread; private Throwable thrown; private final Random random = new Random(); // Debug for DBCP-318 private final long createdMillis; // When object was created private long started; // when thread started private long ended; // when thread ended private long preconnected; // just before connect private long connected; // when thread last connected private long postconnected; // when thread released connection private int loops; private int connHash; // Connection identity hashCode (to see which one is reused) private final boolean stopOnException; // If true, don't rethrow Exception private final boolean loopOnce; // If true, don't repeat loop public PoolTest(final ThreadGroup threadGroup, final Duration connHoldDuration, final boolean isStopOnException) { this(threadGroup, connHoldDuration, isStopOnException, false, 1); } private PoolTest(final ThreadGroup threadGroup, final Duration connHoldDuration, final boolean isStopOnException, final boolean once, final int numStatements) { this.loopOnce = once; this.connHoldDuration = connHoldDuration; stopOnException = isStopOnException; isRun = true; // Must be done here so main thread is guaranteed to be able to set it false thrown = null; thread = new Thread(threadGroup, this, "Thread+" + currentThreadCount++); thread.setDaemon(false); createdMillis = timeStampMillis(); this.numStatements = numStatements; } public PoolTest(final ThreadGroup threadGroup, final Duration connHoldDuration, final boolean isStopOnException, final int numStatements) { this(threadGroup, connHoldDuration, isStopOnException, false, numStatements); } public Thread getThread() { return thread; } @Override public void run() { started = timeStampMillis(); try { while (isRun) { loops++; state = "Getting Connection"; preconnected = timeStampMillis(); try (Connection conn = getConnection()) { connHash = System.identityHashCode(((DelegatingConnection) conn).getInnermostDelegate()); connected = timeStampMillis(); state = "Using Connection"; assertNotNull(conn); final String sql = numStatements == 1 ? "select * from dual" : "select count " + random.nextInt(numStatements - 1); try (PreparedStatement stmt = conn.prepareStatement(sql)) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); state = "Holding Connection"; Thread.sleep(connHoldDuration.toMillis()); state = "Closing ResultSet"; } state = "Closing Statement"; } state = "Closing Connection"; } postconnected = timeStampMillis(); state = "Closed"; if (loopOnce) { break; // Or could set isRun=false } } state = DONE; } catch (final Throwable t) { thrown = t; if (!stopOnException) { throw new RuntimeException(); } } finally { ended = timeStampMillis(); } } public void start(){ thread.start(); } public void stop() { isRun = false; } } final class TestThread implements Runnable { final Random random = new Random(); boolean complete; boolean failed; int iter = 100; int delay = 50; public TestThread() { } public TestThread(final int iter) { this.iter = iter; } public TestThread(final int iter, final int delay) { this.iter = iter; this.delay = delay; } public boolean complete() { return complete; } public boolean failed() { return failed; } @Override public void run() { for (int i = 0; i < iter; i++) { try { Thread.sleep(random.nextInt(delay)); } catch (final Exception e) { // ignored } try (Connection conn = newConnection(); PreparedStatement stmt = conn.prepareStatement("select 'literal', SYSDATE from dual"); ResultSet rset = stmt.executeQuery()) { try { Thread.sleep(random.nextInt(delay)); } catch (final Exception ignore) { // ignored } } catch (final Exception e) { e.printStackTrace(); failed = true; complete = true; break; } } complete = true; } } private static final Duration MAX_WAIT_DURATION = Duration.ofMillis(100); private static final boolean DISPLAY_THREAD_DETAILS= Boolean.getBoolean("TestConnectionPool.display.thread.details"); // To pass this to a Maven test, use: // mvn test -DargLine="-DTestConnectionPool.display.thread.details=true" // @see https://issues.apache.org/jira/browse/SUREFIRE-121 private static int currentThreadCount; private static final String DONE = "Done"; /** Connections opened during the course of a test */ protected final Stack connectionStack = new Stack<>(); protected void assertBackPointers(final Connection conn, final Statement statement) throws SQLException { assertFalse(conn.isClosed()); assertFalse(isClosed(statement)); assertSame(conn, statement.getConnection(), "statement.getConnection() should return the exact same connection instance that was used to create the statement"); final ResultSet resultSet = statement.getResultSet(); assertFalse(isClosed(resultSet)); assertSame(statement, resultSet.getStatement(), "resultSet.getStatement() should return the exact same statement instance that was used to create the result set"); final ResultSet executeResultSet = statement.executeQuery("select * from dual"); assertFalse(isClosed(executeResultSet)); assertSame(statement, executeResultSet.getStatement(), "resultSet.getStatement() should return the exact same statement instance that was used to create the result set"); final ResultSet keysResultSet = statement.getGeneratedKeys(); assertFalse(isClosed(keysResultSet)); assertSame(statement, keysResultSet.getStatement(), "resultSet.getStatement() should return the exact same statement instance that was used to create the result set"); ResultSet preparedResultSet = null; if (statement instanceof PreparedStatement) { final PreparedStatement preparedStatement = (PreparedStatement) statement; preparedResultSet = preparedStatement.executeQuery(); assertFalse(isClosed(preparedResultSet)); assertSame(statement, preparedResultSet.getStatement(), "resultSet.getStatement() should return the exact same statement instance that was used to create the result set"); } resultSet.getStatement().getConnection().close(); assertTrue(conn.isClosed()); assertTrue(isClosed(statement)); assertTrue(isClosed(resultSet)); assertTrue(isClosed(executeResultSet)); assertTrue(isClosed(keysResultSet)); if (preparedResultSet != null) { assertTrue(isClosed(preparedResultSet)); } } protected abstract Connection getConnection() throws Exception; protected int getMaxTotal() { return 10; } protected Duration getMaxWaitDuration() { return MAX_WAIT_DURATION; } protected String getUsername(final Connection conn) throws SQLException { try (final Statement stmt = conn.createStatement(); final ResultSet rs = stmt.executeQuery("select username")) { if (rs.next()) { return rs.getString(1); } } return null; } protected boolean isClosed(final ResultSet resultSet) { try { resultSet.getWarnings(); return false; } catch (final SQLException e) { // getWarnings throws an exception if the statement is // closed, but could throw an exception for other reasons // in this case it is good enough to assume the result set // is closed return true; } } protected boolean isClosed(final Statement statement) { try { statement.getWarnings(); return false; } catch (final SQLException e) { // getWarnings throws an exception if the statement is // closed, but could throw an exception for other reasons // in this case it is good enough to assume the statement // is closed return true; } } /** * Launches a group of 2 * getMaxTotal() threads, each of which will attempt to obtain a connection * from the pool, hold it for {@code holdTime} ms, and then return it to the pool. If {@code loopOnce} is false, * threads will continue this process indefinitely. If {@code expectError} is true, exactly 1/2 of the * threads are expected to either throw exceptions or fail to complete. If {@code expectError} is false, * all threads are expected to complete successfully. * * @param holdDuration Duration that a thread holds a connection before returning it to the pool * @param expectError whether or not an error is expected * @param loopOnce whether threads should complete the borrow - hold - return cycle only once, or loop indefinitely * @param maxWaitDuration passed in by client - has no impact on the test itself, but does get reported * * @throws Exception */ protected void multipleThreads(final Duration holdDuration, final boolean expectError, final boolean loopOnce, final Duration maxWaitDuration) throws Exception { multipleThreads(holdDuration, expectError, loopOnce, maxWaitDuration, 1, 2 * getMaxTotal(), 300); } /** * Launches a group of {@code numThreads} threads, each of which will attempt to obtain a connection * from the pool, hold it for {@code holdTime} ms, and then return it to the pool. If {@code loopOnce} is false, * threads will continue this process indefinitely. If {@code expectError} is true, exactly 1/2 of the * threads are expected to either throw exceptions or fail to complete. If {@code expectError} is false, * all threads are expected to complete successfully. Threads are stopped after {@code duration} ms. * * @param holdDuration Duration that a thread holds a connection before returning it to the pool * @param expectError whether or not an error is expected * @param loopOnce whether threads should complete the borrow - hold - return cycle only once, or loop indefinitely * @param maxWaitDuration passed in by client - has no impact on the test itself, but does get reported * @param numThreads the number of threads * @param duration duration in ms of test * * @throws Exception */ protected void multipleThreads(final Duration holdDuration, final boolean expectError, final boolean loopOnce, final Duration maxWaitDuration, final int numStatements, final int numThreads, final long duration) throws Exception { final long startTimeMillis = timeStampMillis(); final PoolTest[] pts = new PoolTest[numThreads]; // Catch Exception so we can stop all threads if one fails final ThreadGroup threadGroup = new ThreadGroup("foo") { @Override public void uncaughtException(final Thread t, final Throwable e) { for (final PoolTest pt : pts) { pt.stop(); } } }; // Create all the threads for (int i = 0; i < pts.length; i++) { pts[i] = new PoolTest(threadGroup, holdDuration, expectError, loopOnce, numStatements); } // Start all the threads for (final PoolTest pt : pts) { pt.start(); } // Give all threads a chance to start and succeed Thread.sleep(duration); // Stop threads for (final PoolTest pt : pts) { pt.stop(); } /* * Wait for all threads to terminate. This is essential to ensure that all threads have a chance to update success[0] * and to ensure that the variable is published correctly. */ int done = 0; int failed = 0; int didNotRun = 0; int loops = 0; for (final PoolTest poolTest : pts) { poolTest.thread.join(); loops += poolTest.loops; final String state = poolTest.state; if (DONE.equals(state)) { done++; } if (poolTest.loops == 0) { didNotRun++; } final Throwable thrown = poolTest.thrown; if (thrown != null) { failed++; if (!expectError || !(thrown instanceof SQLException)) { System.err.println("Unexpected error: " + thrown.getMessage()); } } } final long timeMillis = timeStampMillis() - startTimeMillis; // @formatter:off println("Multithread test time = " + timeMillis + " ms. Threads: " + pts.length + ". Loops: " + loops + ". Hold time: " + holdDuration + ". maxWaitMillis: " + maxWaitDuration + ". Done: " + done + ". Did not run: " + didNotRun + ". Failed: " + failed + ". expectError: " + expectError); // @formatter:on if (expectError) { if (DISPLAY_THREAD_DETAILS || pts.length / 2 != failed) { final long offset = pts[0].createdMillis - 1000; // To reduce size of output numbers, but ensure they have 4 digits println("Offset: " + offset); for (int i = 0; i < pts.length; i++) { final PoolTest pt = pts[i]; // @formatter:off println("Pre: " + (pt.preconnected-offset) // First, so can sort on this easily + ". Post: " + (pt.postconnected != 0 ? Long.toString(pt.postconnected-offset): "-") + ". Hash: " + pt.connHash + ". Startup: " + (pt.started-pt.createdMillis) + ". getConn(): " + (pt.connected != 0 ? Long.toString(pt.connected-pt.preconnected) : "-") + ". Runtime: " + (pt.ended-pt.started) + ". IDX: " + i + ". Loops: " + pt.loops + ". State: " + pt.state + ". thrown: "+ pt.thrown + "."); // @formatter:on } } if (didNotRun > 0) { println("NOTE: some threads did not run the code: " + didNotRun); } // Perform initial sanity check: assertTrue(failed > 0, "Expected some of the threads to fail"); // Assume that threads that did not run would have timed out. assertEquals(pts.length / 2, failed + didNotRun, "WARNING: Expected half the threads to fail"); } else { assertEquals(0, failed, "Did not expect any threads to fail"); } } /** * Acquires a new connection and push it onto the connections stack. * * @return a new connection. * @throws Exception Defined in subclasses. */ @SuppressWarnings("resource") // Caller closes protected Connection newConnection() throws Exception { return connectionStack.push(getConnection()); } void println(final String string) { if (Boolean.getBoolean(getClass().getSimpleName() + ".debug")) { System.out.println(string); } } @AfterEach public void tearDown() throws Exception { // Close any connections opened by the test while (!connectionStack.isEmpty()) { Utils.closeQuietly((AutoCloseable) connectionStack.pop()); } } @Test public void testAutoCommitBehavior() throws Exception { final Connection conn0 = newConnection(); assertNotNull(conn0, "connection should not be null"); assertTrue(conn0.getAutoCommit(), "autocommit should be true for conn0"); final Connection conn1 = newConnection(); assertTrue(conn1.getAutoCommit(), "autocommit should be true for conn1"); conn1.close(); assertTrue(conn0.getAutoCommit(), "autocommit should be true for conn0"); conn0.setAutoCommit(false); assertFalse(conn0.getAutoCommit(), "autocommit should be false for conn0"); conn0.close(); final Connection conn2 = newConnection(); assertTrue(conn2.getAutoCommit(), "autocommit should be true for conn2"); final Connection conn3 = newConnection(); assertTrue(conn3.getAutoCommit(), "autocommit should be true for conn3"); conn2.close(); conn3.close(); } @Test public void testBackPointers() throws Exception { // normal statement Connection conn = newConnection(); assertBackPointers(conn, conn.createStatement()); conn = newConnection(); assertBackPointers(conn, conn.createStatement(0, 0)); conn = newConnection(); assertBackPointers(conn, conn.createStatement(0, 0, 0)); // prepared statement conn = newConnection(); assertBackPointers(conn, conn.prepareStatement("select * from dual")); conn = newConnection(); assertBackPointers(conn, conn.prepareStatement("select * from dual", 0)); conn = newConnection(); assertBackPointers(conn, conn.prepareStatement("select * from dual", 0, 0)); conn = newConnection(); assertBackPointers(conn, conn.prepareStatement("select * from dual", 0, 0, 0)); conn = newConnection(); assertBackPointers(conn, conn.prepareStatement("select * from dual", new int[0])); conn = newConnection(); assertBackPointers(conn, conn.prepareStatement("select * from dual", new String[0])); // callable statement conn = newConnection(); assertBackPointers(conn, conn.prepareCall("select * from dual")); conn = newConnection(); assertBackPointers(conn, conn.prepareCall("select * from dual", 0, 0)); conn = newConnection(); assertBackPointers(conn, conn.prepareCall("select * from dual", 0, 0, 0)); } @Test public void testCanCloseCallableStatementTwice() throws Exception { try (Connection conn = newConnection()) { assertNotNull(conn); assertFalse(conn.isClosed()); for (int i = 0; i < 2; i++) { // loop to show we *can* close again once we've borrowed it from the pool again final PreparedStatement stmt = conn.prepareCall("select * from dual"); assertNotNull(stmt); assertFalse(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); } } } /** * Verify the close method can be called multiple times on a single connection without * an exception being thrown. */ @Test public void testCanCloseConnectionTwice() throws Exception { for (int i = 0; i < getMaxTotal(); i++) { // loop to show we *can* close again once we've borrowed it from the pool again final Connection conn = newConnection(); assertNotNull(conn); assertFalse(conn.isClosed()); conn.close(); assertTrue(conn.isClosed()); conn.close(); assertTrue(conn.isClosed()); } } @Test public void testCanClosePreparedStatementTwice() throws Exception { try (Connection conn = newConnection()) { assertNotNull(conn); assertFalse(conn.isClosed()); for (int i = 0; i < 2; i++) { // loop to show we *can* close again once we've borrowed it from the pool again final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); assertFalse(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); } } } @Test public void testCanCloseResultSetTwice() throws Exception { try (Connection conn = newConnection()) { assertNotNull(conn); assertFalse(conn.isClosed()); for (int i = 0; i < 2; i++) { // loop to show we *can* close again once we've borrowed it from the pool again final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertFalse(isClosed(rset)); rset.close(); assertTrue(isClosed(rset)); rset.close(); assertTrue(isClosed(rset)); rset.close(); assertTrue(isClosed(rset)); } } } @Test public void testCanCloseStatementTwice() throws Exception { final Connection conn = newConnection(); assertNotNull(conn); assertFalse(conn.isClosed()); for (int i = 0; i < 2; i++) { // loop to show we *can* close again once we've borrowed it from the pool again final Statement stmt = conn.createStatement(); assertNotNull(stmt); assertFalse(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); stmt.close(); assertTrue(isClosed(stmt)); } conn.close(); } @Test public void testClearWarnings() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = newConnection(); assertNotNull(c[i]); // generate SQLWarning on connection try (CallableStatement cs = c[i].prepareCall("warning")) { // empty } } for (final Connection element : c) { assertNotNull(element.getWarnings()); } for (final Connection element : c) { element.close(); } for (int i = 0; i < c.length; i++) { c[i] = newConnection(); } for (final Connection element : c) { // warnings should have been cleared by putting the connection back in the pool assertNull(element.getWarnings()); } for (final Connection element : c) { element.close(); } } @Test public void testClosing() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; // open the maximum connections for (int i = 0; i < c.length; i++) { c[i] = newConnection(); } // close one of the connections c[0].close(); assertTrue(c[0].isClosed()); // get a new connection c[0] = newConnection(); for (final Connection element : c) { element.close(); } } /** "https://issues.apache.org/bugzilla/show_bug.cgi?id=12400" */ @Test public void testConnectionsAreDistinct() throws Exception { final Connection[] conn = new Connection[getMaxTotal()]; for(int i=0;i hash = new Hashtable<>(); hash.put(con, "test"); assertEquals("test", hash.get(con)); assertTrue(hash.containsKey(con)); assertTrue(hash.contains("test")); hash.clear(); con.close(); } @Test public void testIsClosed() throws Exception { for (int i = 0; i < getMaxTotal(); i++) { @SuppressWarnings("resource") final Connection conn = newConnection(); try { assertNotNull(conn); assertFalse(conn.isClosed()); try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } finally { conn.close(); } assertTrue(conn.isClosed()); } } @Test public void testMaxTotal() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = newConnection(); assertNotNull(c[i]); } // should only be able to open 10 connections, so this test should // throw an exception assertThrows(SQLException.class, this::newConnection); for (final Connection element : c) { element.close(); } } // Bugzilla Bug 24966: NullPointer with Oracle 9 driver // wrong order of passivate/close when a rset isn't closed @Test public void testNoRsetClose() throws Exception { try (Connection conn = newConnection()) { assertNotNull(conn); try (PreparedStatement stmt = conn.prepareStatement("test")) { assertNotNull(stmt); final ResultSet rset = stmt.getResultSet(); assertNotNull(rset); // forget to close the resultset: rset.close(); } } } @Test public void testOpening() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; // test that opening new connections is not closing previous for (int i = 0; i < c.length; i++) { c[i] = newConnection(); assertNotNull(c[i]); for (int j = 0; j <= i; j++) { assertFalse(c[j].isClosed()); } } for (final Connection element : c) { element.close(); } } @Test public void testPooling() throws Exception { // Grab a maximal set of open connections from the pool final Connection[] c = new Connection[getMaxTotal()]; final Connection[] u = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = newConnection(); if (!(c[i] instanceof DelegatingConnection)) { for (int j = 0; j <= i; j++) { c[j].close(); } return; // skip this test } u[i] = ((DelegatingConnection) c[i]).getInnermostDelegate(); } // Close connections one at a time and get new ones, making sure // the new ones come from the pool for (final Connection element : c) { element.close(); try (Connection con = newConnection()) { final Connection underCon = ((DelegatingConnection) con).getInnermostDelegate(); assertNotNull(underCon, "Failed to get connection"); boolean found = false; for (int j = 0; j < c.length; j++) { if (underCon == u[j]) { found = true; break; } } assertTrue(found, "New connection not from pool"); } } } // Bugzilla Bug 24328: PooledConnectionImpl ignores resultsetType // and Concurrency if statement pooling is not enabled // https://issues.apache.org/bugzilla/show_bug.cgi?id=24328 @Test public void testPrepareStatementOptions() throws Exception { try (Connection conn = newConnection()) { assertNotNull(conn); try (PreparedStatement stmt = conn.prepareStatement("select * from dual", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, rset.getType()); assertEquals(ResultSet.CONCUR_UPDATABLE, rset.getConcurrency()); } } } } @Test public void testRepeatedBorrowAndReturn() throws Exception { for (int i = 0; i < 100; i++) { try (Connection conn = newConnection()) { assertNotNull(conn); try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } } } @Test public void testSimple() throws Exception { try (Connection conn = newConnection()) { assertNotNull(conn); try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } } @Test public void testSimple2() throws Exception { @SuppressWarnings("resource") final Connection conn = newConnection(); assertNotNull(conn); try { try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } finally { conn.close(); } assertThrows(SQLException.class, conn::createStatement, "Can't use closed connections"); try (Connection conn2 = newConnection()) { assertNotNull(conn2); { try (PreparedStatement stmt = conn2.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } { try (PreparedStatement stmt = conn2.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } } } @Test public void testThreaded() { final TestThread[] threads = new TestThread[getMaxTotal()]; for (int i = 0; i < threads.length; i++) { threads[i] = new TestThread(50, 50); final Thread t = new Thread(threads[i]); t.start(); } for (int i = 0; i < threads.length; i++) { while (!threads[i].complete()) { try { Thread.sleep(100L); } catch (final Exception e) { // ignored } } if (threads[i] != null && threads[i].failed()) { fail("Thread failed: " + i); } } } long timeStampMillis() { return System.currentTimeMillis(); // JVM 1.5+ System.nanoTime() / 1000000; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestConstants.java000066400000000000000000000031021472045345700321470ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; /** * Tests for Constants. */ public class TestConstants { @Test public void testConstants() { assertNotNull(new Constants()); assertEquals(",connectionpool=", Constants.JMX_CONNECTION_POOL_BASE_EXT); assertEquals("connections", Constants.JMX_CONNECTION_POOL_PREFIX); assertEquals(",connectionpool=connections,connection=", Constants.JMX_CONNECTION_BASE_EXT); assertEquals(",connectionpool=connections,connection=", Constants.JMX_STATEMENT_POOL_BASE_EXT); assertEquals(",statementpool=statements", Constants.JMX_STATEMENT_POOL_PREFIX); } } TestDataSourceConnectionFactory.java000066400000000000000000000077611472045345700355350ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger; import javax.sql.DataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test for DataSourceConnectionFactory. */ public class TestDataSourceConnectionFactory { private static final class TestDataSource implements DataSource { @Override public Connection getConnection() throws SQLException { return new TesterConnection(null, null); } @Override public Connection getConnection(final String username, final String password) throws SQLException { return new TesterConnection(username, password); } @Override public int getLoginTimeout() throws SQLException { return 0; } @Override public PrintWriter getLogWriter() throws SQLException { return null; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } @Override public void setLoginTimeout(final int seconds) throws SQLException { // noop } @Override public void setLogWriter(final PrintWriter out) throws SQLException { // noop } @Override public T unwrap(final Class iface) throws SQLException { return null; } } private DataSource datasource; private DataSourceConnectionFactory factory; @BeforeEach public void setUp() { datasource = new TestDataSource(); factory = new DataSourceConnectionFactory(datasource); } @Test public void testCredentials() throws SQLException { final DataSourceConnectionFactory factory = new DataSourceConnectionFactory(datasource, "foo", "bar"); try (Connection conn = factory.createConnection()) { assertEquals("foo", ((TesterConnection) conn).getUserName()); } } @Test public void testDefaultValues() throws SQLException { try (Connection conn = factory.createConnection()) { assertNull(((TesterConnection) conn).getUserName()); } } @Test public void testEmptyPassword() throws SQLException { final DataSourceConnectionFactory factory = new DataSourceConnectionFactory(datasource, "foo", (char[]) null); try (Connection conn = factory.createConnection()) { assertEquals("foo", ((TesterConnection) conn).getUserName()); } } @Test public void testEmptyUser() throws SQLException { final DataSourceConnectionFactory factory = new DataSourceConnectionFactory(datasource, null, new char[] { 'a' }); try (Connection conn = factory.createConnection()) { assertNull(((TesterConnection) conn).getUserName()); } } } TestDelegatingCallableStatement.java000066400000000000000000001032011472045345700354650ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.SQLException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @SuppressWarnings({ "deprecation", "unchecked", "rawtypes" }) // BigDecimal methods, and casting for mocks public class TestDelegatingCallableStatement { private TesterConnection conn; private DelegatingCallableStatement delegate; private CallableStatement obj; @BeforeEach public void setUp() throws Exception { conn = new TesterConnection("test", "test"); obj = mock(CallableStatement.class); final DelegatingConnection delegatingConnection = new DelegatingConnection<>(conn); delegate = new DelegatingCallableStatement(delegatingConnection, obj); } @Test public void testExecuteQueryReturnsNotNull() throws Exception { final TesterCallableStatement delegateStmt = new TesterCallableStatement(conn,"select * from foo"); obj = new DelegatingCallableStatement(new DelegatingConnection<>(conn), delegateStmt); assertNotNull(obj.executeQuery()); } @Test public void testExecuteQueryReturnsNull() throws Exception { final TesterCallableStatement delegateStmt = new TesterCallableStatement(conn,"null"); obj = new DelegatingCallableStatement(new DelegatingConnection<>(conn), delegateStmt); assertNull(obj.executeQuery()); } @Test public void testGetArrayInteger() throws Exception { try { delegate.getArray(1); } catch (final SQLException e) { } verify(obj, times(1)).getArray(1); } @Test public void testGetArrayString() throws Exception { try { delegate.getArray("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getArray("foo"); } @Test public void testGetBigDecimalInteger() throws Exception { try { delegate.getBigDecimal(1); } catch (final SQLException e) { } verify(obj, times(1)).getBigDecimal(1); } @Test public void testGetBigDecimalIntegerInteger() throws Exception { try { delegate.getBigDecimal(1, 1); } catch (final SQLException e) { } verify(obj, times(1)).getBigDecimal(1, 1); } @Test public void testGetBigDecimalString() throws Exception { try { delegate.getBigDecimal("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getBigDecimal("foo"); } @Test public void testGetBlobInteger() throws Exception { try { delegate.getBlob(1); } catch (final SQLException e) { } verify(obj, times(1)).getBlob(1); } @Test public void testGetBlobString() throws Exception { try { delegate.getBlob("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getBlob("foo"); } @Test public void testGetBooleanInteger() throws Exception { try { delegate.getBoolean(1); } catch (final SQLException e) { } verify(obj, times(1)).getBoolean(1); } @Test public void testGetBooleanString() throws Exception { try { delegate.getBoolean("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getBoolean("foo"); } @Test public void testGetByteInteger() throws Exception { try { delegate.getByte(1); } catch (final SQLException e) { } verify(obj, times(1)).getByte(1); } @Test public void testGetBytesInteger() throws Exception { try { delegate.getBytes(1); } catch (final SQLException e) { } verify(obj, times(1)).getBytes(1); } @Test public void testGetBytesString() throws Exception { try { delegate.getBytes("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getBytes("foo"); } @Test public void testGetByteString() throws Exception { try { delegate.getByte("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getByte("foo"); } @Test public void testGetCharacterStreamInteger() throws Exception { try { delegate.getCharacterStream(1); } catch (final SQLException e) { } verify(obj, times(1)).getCharacterStream(1); } @Test public void testGetCharacterStreamString() throws Exception { try { delegate.getCharacterStream("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getCharacterStream("foo"); } @Test public void testGetClobInteger() throws Exception { try { delegate.getClob(1); } catch (final SQLException e) { } verify(obj, times(1)).getClob(1); } @Test public void testGetClobString() throws Exception { try { delegate.getClob("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getClob("foo"); } @Test public void testGetDateInteger() throws Exception { try { delegate.getDate(1); } catch (final SQLException e) { } verify(obj, times(1)).getDate(1); } @Test public void testGetDateIntegerCalendar() throws Exception { try { delegate.getDate(1, (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).getDate(1, (java.util.Calendar) null); } @Test public void testGetDateString() throws Exception { try { delegate.getDate("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getDate("foo"); } @Test public void testGetDateStringCalendar() throws Exception { try { delegate.getDate("foo", (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).getDate("foo", (java.util.Calendar) null); } @Test public void testGetDelegate() throws Exception { final TesterCallableStatement delegateStmt = new TesterCallableStatement(conn,"select * from foo"); obj = new DelegatingCallableStatement(new DelegatingConnection<>(conn), delegateStmt); assertEquals(delegateStmt,((DelegatingCallableStatement)obj).getDelegate()); } @Test public void testGetDoubleInteger() throws Exception { try { delegate.getDouble(1); } catch (final SQLException e) { } verify(obj, times(1)).getDouble(1); } @Test public void testGetDoubleString() throws Exception { try { delegate.getDouble("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getDouble("foo"); } @Test public void testGetFloatInteger() throws Exception { try { delegate.getFloat(1); } catch (final SQLException e) { } verify(obj, times(1)).getFloat(1); } @Test public void testGetFloatString() throws Exception { try { delegate.getFloat("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getFloat("foo"); } @Test public void testGetIntInteger() throws Exception { try { delegate.getInt(1); } catch (final SQLException e) { } verify(obj, times(1)).getInt(1); } @Test public void testGetIntString() throws Exception { try { delegate.getInt("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getInt("foo"); } @Test public void testGetLongInteger() throws Exception { try { delegate.getLong(1); } catch (final SQLException e) { } verify(obj, times(1)).getLong(1); } @Test public void testGetLongString() throws Exception { try { delegate.getLong("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getLong("foo"); } @Test public void testGetNCharacterStreamInteger() throws Exception { try { delegate.getNCharacterStream(1); } catch (final SQLException e) { } verify(obj, times(1)).getNCharacterStream(1); } @Test public void testGetNCharacterStreamString() throws Exception { try { delegate.getNCharacterStream("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getNCharacterStream("foo"); } @Test public void testGetNClobInteger() throws Exception { try { delegate.getNClob(1); } catch (final SQLException e) { } verify(obj, times(1)).getNClob(1); } @Test public void testGetNClobString() throws Exception { try { delegate.getNClob("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getNClob("foo"); } @Test public void testGetNStringInteger() throws Exception { try { delegate.getNString(1); } catch (final SQLException e) { } verify(obj, times(1)).getNString(1); } @Test public void testGetNStringString() throws Exception { try { delegate.getNString("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getNString("foo"); } @Test public void testGetObjectInteger() throws Exception { try { delegate.getObject(1); } catch (final SQLException e) { } verify(obj, times(1)).getObject(1); } @Test public void testGetObjectIntegerClass() throws Exception { try { delegate.getObject(1, Object.class); } catch (final SQLException e) { } verify(obj, times(1)).getObject(1, Object.class); } @Test public void testGetObjectIntegerMap() throws Exception { try { delegate.getObject(1, (java.util.Map) null); } catch (final SQLException e) { } verify(obj, times(1)).getObject(1, (java.util.Map) null); } @Test public void testGetObjectString() throws Exception { try { delegate.getObject("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getObject("foo"); } @Test public void testGetObjectStringClass() throws Exception { try { delegate.getObject("foo", Object.class); } catch (final SQLException e) { } verify(obj, times(1)).getObject("foo", Object.class); } @Test public void testGetObjectStringMap() throws Exception { try { delegate.getObject("foo", (java.util.Map) null); } catch (final SQLException e) { } verify(obj, times(1)).getObject("foo", (java.util.Map) null); } @Test public void testGetRefInteger() throws Exception { try { delegate.getRef(1); } catch (final SQLException e) { } verify(obj, times(1)).getRef(1); } @Test public void testGetRefString() throws Exception { try { delegate.getRef("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getRef("foo"); } @Test public void testGetRowIdInteger() throws Exception { try { delegate.getRowId(1); } catch (final SQLException e) { } verify(obj, times(1)).getRowId(1); } @Test public void testGetRowIdString() throws Exception { try { delegate.getRowId("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getRowId("foo"); } @Test public void testGetShortInteger() throws Exception { try { delegate.getShort(1); } catch (final SQLException e) { } verify(obj, times(1)).getShort(1); } @Test public void testGetShortString() throws Exception { try { delegate.getShort("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getShort("foo"); } @Test public void testGetSQLXMLInteger() throws Exception { try { delegate.getSQLXML(1); } catch (final SQLException e) { } verify(obj, times(1)).getSQLXML(1); } @Test public void testGetSQLXMLString() throws Exception { try { delegate.getSQLXML("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getSQLXML("foo"); } @Test public void testGetStringInteger() throws Exception { try { delegate.getString(1); } catch (final SQLException e) { } verify(obj, times(1)).getString(1); } @Test public void testGetStringString() throws Exception { try { delegate.getString("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getString("foo"); } @Test public void testGetTimeInteger() throws Exception { try { delegate.getTime(1); } catch (final SQLException e) { } verify(obj, times(1)).getTime(1); } @Test public void testGetTimeIntegerCalendar() throws Exception { try { delegate.getTime(1, (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).getTime(1, (java.util.Calendar) null); } @Test public void testGetTimestampInteger() throws Exception { try { delegate.getTimestamp(1); } catch (final SQLException e) { } verify(obj, times(1)).getTimestamp(1); } @Test public void testGetTimestampIntegerCalendar() throws Exception { try { delegate.getTimestamp(1, (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).getTimestamp(1, (java.util.Calendar) null); } @Test public void testGetTimestampString() throws Exception { try { delegate.getTimestamp("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getTimestamp("foo"); } @Test public void testGetTimestampStringCalendar() throws Exception { try { delegate.getTimestamp("foo", (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).getTimestamp("foo", (java.util.Calendar) null); } @Test public void testGetTimeString() throws Exception { try { delegate.getTime("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getTime("foo"); } @Test public void testGetTimeStringCalendar() throws Exception { try { delegate.getTime("foo", (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).getTime("foo", (java.util.Calendar) null); } @Test public void testGetURLInteger() throws Exception { try { delegate.getURL(1); } catch (final SQLException e) { } verify(obj, times(1)).getURL(1); } @Test public void testGetURLString() throws Exception { try { delegate.getURL("foo"); } catch (final SQLException e) { } verify(obj, times(1)).getURL("foo"); } @Test public void testRegisterOutParameterIntegerInteger() throws Exception { try { delegate.registerOutParameter(1, 1); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter(1, 1); } @Test public void testRegisterOutParameterIntegerIntegerInteger() throws Exception { try { delegate.registerOutParameter(1, 1, 1); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter(1, 1, 1); } @Test public void testRegisterOutParameterIntegerIntegerString() throws Exception { try { delegate.registerOutParameter(1, 1, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter(1, 1, "foo"); } @Test public void testRegisterOutParameterIntegerSQLType() throws Exception { try { delegate.registerOutParameter(1, (java.sql.SQLType) null); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter(1, (java.sql.SQLType) null); } @Test public void testRegisterOutParameterIntegerSQLTypeInteger() throws Exception { try { delegate.registerOutParameter(1, (java.sql.SQLType) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter(1, (java.sql.SQLType) null, 1); } @Test public void testRegisterOutParameterIntegerSQLTypeString() throws Exception { try { delegate.registerOutParameter(1, (java.sql.SQLType) null, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter(1, (java.sql.SQLType) null, "foo"); } @Test public void testRegisterOutParameterStringInteger() throws Exception { try { delegate.registerOutParameter("foo", 1); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter("foo", 1); } @Test public void testRegisterOutParameterStringIntegerInteger() throws Exception { try { delegate.registerOutParameter("foo", 1, 1); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter("foo", 1, 1); } @Test public void testRegisterOutParameterStringIntegerString() throws Exception { try { delegate.registerOutParameter("foo", 1, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter("foo", 1, "foo"); } @Test public void testRegisterOutParameterStringSQLType() throws Exception { try { delegate.registerOutParameter("foo", (java.sql.SQLType) null); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter("foo", (java.sql.SQLType) null); } @Test public void testRegisterOutParameterStringSQLTypeInteger() throws Exception { try { delegate.registerOutParameter("foo", (java.sql.SQLType) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter("foo", (java.sql.SQLType) null, 1); } @Test public void testRegisterOutParameterStringSQLTypeString() throws Exception { try { delegate.registerOutParameter("foo", (java.sql.SQLType) null, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).registerOutParameter("foo", (java.sql.SQLType) null, "foo"); } @Test public void testSetAsciiStreamStringInputStream() throws Exception { try { delegate.setAsciiStream("foo", (java.io.InputStream) null); } catch (final SQLException e) { } verify(obj, times(1)).setAsciiStream("foo", (java.io.InputStream) null); } @Test public void testSetAsciiStreamStringInputStreamInteger() throws Exception { try { delegate.setAsciiStream("foo", (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setAsciiStream("foo", (java.io.InputStream) null, 1); } @Test public void testSetAsciiStreamStringInputStreamLong() throws Exception { try { delegate.setAsciiStream("foo", (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setAsciiStream("foo", (java.io.InputStream) null, 1L); } @Test public void testSetBigDecimalStringBigDecimal() throws Exception { try { delegate.setBigDecimal("foo", java.math.BigDecimal.valueOf(1.0d)); } catch (final SQLException e) { } verify(obj, times(1)).setBigDecimal("foo", java.math.BigDecimal.valueOf(1.0d)); } @Test public void testSetBinaryStreamStringInputStream() throws Exception { try { delegate.setBinaryStream("foo", (java.io.InputStream) null); } catch (final SQLException e) { } verify(obj, times(1)).setBinaryStream("foo", (java.io.InputStream) null); } @Test public void testSetBinaryStreamStringInputStreamInteger() throws Exception { try { delegate.setBinaryStream("foo", (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setBinaryStream("foo", (java.io.InputStream) null, 1); } @Test public void testSetBinaryStreamStringInputStreamLong() throws Exception { try { delegate.setBinaryStream("foo", (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setBinaryStream("foo", (java.io.InputStream) null, 1L); } @Test public void testSetBlobStringBlob() throws Exception { try { delegate.setBlob("foo", (java.sql.Blob) null); } catch (final SQLException e) { } verify(obj, times(1)).setBlob("foo", (java.sql.Blob) null); } @Test public void testSetBlobStringInputStream() throws Exception { try { delegate.setBlob("foo", (java.io.InputStream) null); } catch (final SQLException e) { } verify(obj, times(1)).setBlob("foo", (java.io.InputStream) null); } @Test public void testSetBlobStringInputStreamLong() throws Exception { try { delegate.setBlob("foo", (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setBlob("foo", (java.io.InputStream) null, 1L); } @Test public void testSetBooleanStringBoolean() throws Exception { try { delegate.setBoolean("foo", Boolean.TRUE); } catch (final SQLException e) { } verify(obj, times(1)).setBoolean("foo", Boolean.TRUE); } @Test public void testSetBytesStringByteArray() throws Exception { try { delegate.setBytes("foo", new byte[] { 1 }); } catch (final SQLException e) { } verify(obj, times(1)).setBytes("foo", new byte[] { 1 }); } @Test public void testSetByteStringByte() throws Exception { try { delegate.setByte("foo", (byte) 1); } catch (final SQLException e) { } verify(obj, times(1)).setByte("foo", (byte) 1); } @Test public void testSetCharacterStreamStringReader() throws Exception { try { delegate.setCharacterStream("foo", (java.io.StringReader) null); } catch (final SQLException e) { } verify(obj, times(1)).setCharacterStream("foo", (java.io.StringReader) null); } @Test public void testSetCharacterStreamStringReaderInteger() throws Exception { try { delegate.setCharacterStream("foo", (java.io.StringReader) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setCharacterStream("foo", (java.io.StringReader) null, 1); } @Test public void testSetCharacterStreamStringReaderLong() throws Exception { try { delegate.setCharacterStream("foo", (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setCharacterStream("foo", (java.io.StringReader) null, 1L); } @Test public void testSetClobStringClob() throws Exception { try { delegate.setClob("foo", (java.sql.Clob) null); } catch (final SQLException e) { } verify(obj, times(1)).setClob("foo", (java.sql.Clob) null); } @Test public void testSetClobStringReader() throws Exception { try { delegate.setClob("foo", (java.io.StringReader) null); } catch (final SQLException e) { } verify(obj, times(1)).setClob("foo", (java.io.StringReader) null); } @Test public void testSetClobStringReaderLong() throws Exception { try { delegate.setClob("foo", (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setClob("foo", (java.io.StringReader) null, 1L); } @Test public void testSetDateStringSqlDate() throws Exception { try { delegate.setDate("foo", new java.sql.Date(1529827548745L)); } catch (final SQLException e) { } verify(obj, times(1)).setDate("foo", new java.sql.Date(1529827548745L)); } @Test public void testSetDateStringSqlDateCalendar() throws Exception { try { delegate.setDate("foo", new java.sql.Date(1529827548745L), (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).setDate("foo", new java.sql.Date(1529827548745L), (java.util.Calendar) null); } @Test public void testSetDoubleStringDouble() throws Exception { try { delegate.setDouble("foo", 1.0d); } catch (final SQLException e) { } verify(obj, times(1)).setDouble("foo", 1.0d); } @Test public void testSetFloatStringFloat() throws Exception { try { delegate.setFloat("foo", 1.0f); } catch (final SQLException e) { } verify(obj, times(1)).setFloat("foo", 1.0f); } @Test public void testSetIntStringInteger() throws Exception { try { delegate.setInt("foo", 1); } catch (final SQLException e) { } verify(obj, times(1)).setInt("foo", 1); } @Test public void testSetLongStringLong() throws Exception { try { delegate.setLong("foo", 1L); } catch (final SQLException e) { } verify(obj, times(1)).setLong("foo", 1L); } @Test public void testSetNCharacterStreamStringReader() throws Exception { try { delegate.setNCharacterStream("foo", (java.io.StringReader) null); } catch (final SQLException e) { } verify(obj, times(1)).setNCharacterStream("foo", (java.io.StringReader) null); } @Test public void testSetNCharacterStreamStringReaderLong() throws Exception { try { delegate.setNCharacterStream("foo", (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setNCharacterStream("foo", (java.io.StringReader) null, 1L); } @Test public void testSetNClobStringNClob() throws Exception { try { delegate.setNClob("foo", (java.sql.NClob) null); } catch (final SQLException e) { } verify(obj, times(1)).setNClob("foo", (java.sql.NClob) null); } @Test public void testSetNClobStringReader() throws Exception { try { delegate.setNClob("foo", (java.io.StringReader) null); } catch (final SQLException e) { } verify(obj, times(1)).setNClob("foo", (java.io.StringReader) null); } @Test public void testSetNClobStringReaderLong() throws Exception { try { delegate.setNClob("foo", (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setNClob("foo", (java.io.StringReader) null, 1L); } @Test public void testSetNStringStringString() throws Exception { try { delegate.setNString("foo", "foo"); } catch (final SQLException e) { } verify(obj, times(1)).setNString("foo", "foo"); } @Test public void testSetNullStringInteger() throws Exception { try { delegate.setNull("foo", 1); } catch (final SQLException e) { } verify(obj, times(1)).setNull("foo", 1); } @Test public void testSetNullStringIntegerString() throws Exception { try { delegate.setNull("foo", 1, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).setNull("foo", 1, "foo"); } @Test public void testSetObjectStringObject() throws Exception { try { delegate.setObject("foo", System.err); } catch (final SQLException e) { } verify(obj, times(1)).setObject("foo", System.err); } @Test public void testSetObjectStringObjectInteger() throws Exception { try { delegate.setObject("foo", System.err, 1); } catch (final SQLException e) { } verify(obj, times(1)).setObject("foo", System.err, 1); } @Test public void testSetObjectStringObjectIntegerInteger() throws Exception { try { delegate.setObject("foo", System.err, 1, 1); } catch (final SQLException e) { } verify(obj, times(1)).setObject("foo", System.err, 1, 1); } @Test public void testSetObjectStringObjectSQLType() throws Exception { try { delegate.setObject("foo", System.err, (java.sql.SQLType) null); } catch (final SQLException e) { } verify(obj, times(1)).setObject("foo", System.err, (java.sql.SQLType) null); } @Test public void testSetObjectStringObjectSQLTypeInteger() throws Exception { try { delegate.setObject("foo", System.err, (java.sql.SQLType) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setObject("foo", System.err, (java.sql.SQLType) null, 1); } @Test public void testSetRowIdStringRowId() throws Exception { try { delegate.setRowId("foo", (java.sql.RowId) null); } catch (final SQLException e) { } verify(obj, times(1)).setRowId("foo", (java.sql.RowId) null); } @Test public void testSetShortStringShort() throws Exception { try { delegate.setShort("foo", (short) 1); } catch (final SQLException e) { } verify(obj, times(1)).setShort("foo", (short) 1); } @Test public void testSetSQLXMLStringSQLXML() throws Exception { try { delegate.setSQLXML("foo", (java.sql.SQLXML) null); } catch (final SQLException e) { } verify(obj, times(1)).setSQLXML("foo", (java.sql.SQLXML) null); } @Test public void testSetStringStringString() throws Exception { try { delegate.setString("foo", "foo"); } catch (final SQLException e) { } verify(obj, times(1)).setString("foo", "foo"); } @Test public void testSetTimestampStringTimestamp() throws Exception { try { delegate.setTimestamp("foo", (java.sql.Timestamp) null); } catch (final SQLException e) { } verify(obj, times(1)).setTimestamp("foo", (java.sql.Timestamp) null); } @Test public void testSetTimestampStringTimestampCalendar() throws Exception { try { delegate.setTimestamp("foo", (java.sql.Timestamp) null, (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).setTimestamp("foo", (java.sql.Timestamp) null, (java.util.Calendar) null); } @Test public void testSetTimeStringTime() throws Exception { try { delegate.setTime("foo", (java.sql.Time) null); } catch (final SQLException e) { } verify(obj, times(1)).setTime("foo", (java.sql.Time) null); } @Test public void testSetTimeStringTimeCalendar() throws Exception { try { delegate.setTime("foo", (java.sql.Time) null, (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).setTime("foo", (java.sql.Time) null, (java.util.Calendar) null); } @Test public void testSetURLStringUrl() throws Exception { try { delegate.setURL("foo", (java.net.URL) null); } catch (final SQLException e) { } verify(obj, times(1)).setURL("foo", (java.net.URL) null); } @Test public void testWasNull() throws Exception { try { delegate.wasNull(); } catch (final SQLException e) { } verify(obj, times(1)).wasNull(); } }TestDelegatingConnection.java000066400000000000000000000331741472045345700342130ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Savepoint; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link DelegatingConnection}. */ public class TestDelegatingConnection { /** * Delegate that doesn't support read-only or auto-commit. It will merely take the input value of setReadOnly and setAutoCommit and discard it, to keep * false. */ static class NoReadOnlyOrAutoCommitConnection extends TesterConnection { private final boolean readOnly = false; private final boolean autoCommit = false; public NoReadOnlyOrAutoCommitConnection() { super("", ""); } @Override public boolean getAutoCommit() { return autoCommit; } @Override public boolean isReadOnly() throws SQLException { return readOnly; } @Override public void setAutoCommit(final boolean autoCommit) { // Do nothing } @Override public void setReadOnly(final boolean readOnly) { // Do nothing } } /** * Delegate that will throw RTE on toString Used to validate fix for DBCP-241 */ static class RTEGeneratingConnection extends TesterConnection { public RTEGeneratingConnection() { super("", ""); } @Override public String toString() { throw new RuntimeException("bang!"); } } private DelegatingConnection delegatingConnection; private Connection connection; private Connection connection2; private DelegatingConnection h2DConnection; private TesterStatement testerStatement; private TesterResultSet testerResultSet; @AfterEach public void afterEach() throws SQLException { h2DConnection.close(); } @BeforeEach public void setUp() throws Exception { connection = new TesterConnection("test", "test"); connection2 = new TesterConnection("test", "test"); delegatingConnection = new DelegatingConnection<>(connection); testerStatement = new TesterStatement(delegatingConnection); testerResultSet = new TesterResultSet(testerStatement); h2DConnection = new DelegatingConnection<>(DriverManager.getConnection("jdbc:h2:mem:test")); } @Test public void testAbort() throws Exception { h2DConnection.abort(r -> { }); } @Test public void testAutoCommitCaching() throws SQLException { final Connection con = new NoReadOnlyOrAutoCommitConnection(); final DelegatingConnection delCon = new DelegatingConnection<>(con); delCon.setAutoCommit(true); assertFalse(con.getAutoCommit()); assertFalse(delCon.getAutoCommit()); } @Test public void testCheckOpen() throws Exception { delegatingConnection.checkOpen(); delegatingConnection.close(); try { delegatingConnection.checkOpen(); fail("Expecting SQLException"); } catch (final SQLException ex) { // expected } } /** * Verify fix for DBCP-241 */ @Test public void testCheckOpenNull() throws Exception { try { delegatingConnection.close(); delegatingConnection.checkOpen(); fail("Expecting SQLException"); } catch (final SQLException ex) { assertTrue(ex.getMessage().endsWith("is closed.")); } try { delegatingConnection = new DelegatingConnection<>(null); delegatingConnection.setClosedInternal(true); delegatingConnection.checkOpen(); fail("Expecting SQLException"); } catch (final SQLException ex) { assertTrue(ex.getMessage().endsWith("is null.")); } try { final PoolingConnection pc = new PoolingConnection(connection2); pc.setStatementPool(new GenericKeyedObjectPool<>(pc)); delegatingConnection = new DelegatingConnection<>(pc); pc.close(); delegatingConnection.close(); try (PreparedStatement ps = delegatingConnection.prepareStatement("")) { } fail("Expecting SQLException"); } catch (final SQLException ex) { assertTrue(ex.getMessage().endsWith("is closed.")); } try { delegatingConnection = new DelegatingConnection<>(new RTEGeneratingConnection()); delegatingConnection.close(); delegatingConnection.checkOpen(); fail("Expecting SQLException"); } catch (final SQLException ex) { assertTrue(ex.getMessage().endsWith("is closed.")); } } @Test public void testCommit() throws Exception { h2DConnection.commit(); } @Test public void testConnectionToString() throws Exception { final String s = delegatingConnection.toString(); assertNotNull(s); assertFalse(s.isEmpty()); } @Test public void testCreateArrayOf() throws Exception { assertNotNull(h2DConnection.createArrayOf("CHARACTER", new Object[] { "A", "B" })); } @Test public void testCreateBlob() throws Exception { assertNotNull(h2DConnection.createBlob()); } @Test public void testCreateClob() throws Exception { assertNotNull(h2DConnection.createClob()); } @Test public void testCreateNClob() throws Exception { assertNotNull(h2DConnection.createNClob()); } @Test public void testCreateSQLXML() throws Exception { assertNotNull(h2DConnection.createSQLXML()); } @Test public void testCreateStruct() throws Exception { // not supported by H2 assertThrows(SQLException.class, () -> h2DConnection.createStruct("CHARACTER", new Object[] { "A", "B" })); } @Test public void testGetCacheState() throws Exception { assertTrue(h2DConnection.getCacheState()); } @Test public void testGetClientInfo() throws Exception { assertNotNull(h2DConnection.getClientInfo()); } @Test public void testGetClientInfoString() throws Exception { assertNull(h2DConnection.getClientInfo("xyz")); } @Test public void testGetDefaultQueryTimeout() throws Exception { assertNull(h2DConnection.getDefaultQueryTimeout()); } @Test public void testGetDefaultQueryTimeoutDuration() throws Exception { assertNull(h2DConnection.getDefaultQueryTimeoutDuration()); } @Test public void testGetDelegate() throws Exception { assertEquals(connection, delegatingConnection.getDelegate()); } @Test public void testGetHoldability() throws Exception { assertEquals(1, h2DConnection.getHoldability()); } @Test public void testGetNetworkTimeout() throws Exception { assertEquals(0, h2DConnection.getNetworkTimeout()); } @Test public void testGetTypeMap() throws Exception { assertNull(h2DConnection.getTypeMap()); } @Test public void testIsClosed() throws Exception { delegatingConnection.checkOpen(); assertFalse(delegatingConnection.isClosed()); delegatingConnection.close(); assertTrue(delegatingConnection.isClosed()); } @Test public void testIsClosedNullDelegate() throws Exception { delegatingConnection.checkOpen(); assertFalse(delegatingConnection.isClosed()); delegatingConnection.setDelegate(null); assertTrue(delegatingConnection.isClosed()); } @SuppressWarnings("resource") @Test public void testIsWrapperFor() throws Exception { assertTrue(delegatingConnection.isWrapperFor(delegatingConnection.getClass())); assertTrue(delegatingConnection.isWrapperFor(delegatingConnection.getDelegate().getClass())); assertThrows(SQLException.class, () -> delegatingConnection.isWrapperFor(Integer.class)); } @Test public void testNativeSQL() throws Exception { assertNotNull(h2DConnection.nativeSQL("select 1")); } @Test public void testPassivateWithResultSetCloseException() { try { testerResultSet.setSqlExceptionOnClose(true); delegatingConnection.addTrace(testerResultSet); delegatingConnection.passivate(); Assertions.fail("Expected SQLExceptionList"); } catch (final SQLException e) { Assertions.assertInstanceOf(SQLExceptionList.class, e); Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size()); } finally { testerResultSet.setSqlExceptionOnClose(false); } } @Test public void testPassivateWithResultSetCloseExceptionAndStatementCloseException() { try { testerStatement.setSqlExceptionOnClose(true); testerResultSet.setSqlExceptionOnClose(true); delegatingConnection.addTrace(testerStatement); delegatingConnection.addTrace(testerResultSet); delegatingConnection.passivate(); Assertions.fail("Expected SQLExceptionList"); } catch (final SQLException e) { Assertions.assertInstanceOf(SQLExceptionList.class, e); Assertions.assertEquals(2, ((SQLExceptionList) e).getCauseList().size()); } finally { testerStatement.setSqlExceptionOnClose(false); testerResultSet.setSqlExceptionOnClose(false); } } @Test public void testPassivateWithStatementCloseException() { try { testerStatement.setSqlExceptionOnClose(true); delegatingConnection.addTrace(testerStatement); delegatingConnection.passivate(); Assertions.fail("Expected SQLExceptionList"); } catch (final SQLException e) { Assertions.assertInstanceOf(SQLExceptionList.class, e); Assertions.assertEquals(1, ((SQLExceptionList) e).getCauseList().size()); } finally { testerStatement.setSqlExceptionOnClose(false); } } @Test public void testReadOnlyCaching() throws SQLException { final Connection con = new NoReadOnlyOrAutoCommitConnection(); final DelegatingConnection delCon = new DelegatingConnection<>(con); delCon.setReadOnly(true); assertFalse(con.isReadOnly()); assertFalse(delCon.isReadOnly()); } @Test public void testReleaseSavepoint() throws Exception { final Savepoint s = h2DConnection.setSavepoint(); h2DConnection.releaseSavepoint(s); } @Test public void testRollback() throws Exception { h2DConnection.rollback(); } @Test public void testRollbackSavepoint() throws Exception { h2DConnection.setAutoCommit(false); try { h2DConnection.rollback(h2DConnection.setSavepoint()); } finally { h2DConnection.setAutoCommit(true); } } @Test public void testSetClientInfo() throws Exception { // TODO // h2DConnection.setClientInfo("ApplicationName", "app1"); } @Test public void testSetDefaultQueryTimeout() throws Exception { final int expected = 1; delegatingConnection.setDefaultQueryTimeout(expected); assertEquals(expected, delegatingConnection.getDefaultQueryTimeout()); } @Test public void testSetHoldability() throws Exception { final int expected = 1; h2DConnection.setHoldability(expected); assertEquals(expected, h2DConnection.getHoldability()); } @Test public void testSetNetworkTimeout() throws Exception { h2DConnection.setNetworkTimeout(r -> {}, 1); assertEquals(0, h2DConnection.getNetworkTimeout()); } @Test public void testSetSavepoint() throws Exception { h2DConnection.setSavepoint(); } @SuppressWarnings("javadoc") @Test public void testUnwrap() throws Exception { assertNotNull(delegatingConnection.unwrap(delegatingConnection.getClass())); assertNotNull(delegatingConnection.unwrap(delegatingConnection.getDelegate().getClass())); assertThrows(SQLException.class, () -> delegatingConnection.unwrap(Integer.class)); } } TestDelegatingDatabaseMetaData.java000066400000000000000000001564431472045345700352260ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; /** * Test suite for {@link DelegatingDatabaseMetaData}. */ public class TestDelegatingDatabaseMetaData { private TesterConnection testConn; private DelegatingConnection conn; private DelegatingDatabaseMetaData delegate; private DelegatingDatabaseMetaData delegateSpy; private DatabaseMetaData obj; @BeforeEach public void setUp() throws Exception { obj = mock(DatabaseMetaData.class); testConn = new TesterConnection("test", "test"); conn = new DelegatingConnection<>(testConn); delegate = new DelegatingDatabaseMetaData(conn, obj); delegateSpy = Mockito.spy(delegate); } @Test public void testAllProceduresAreCallable() throws Exception { try { delegate.allProceduresAreCallable(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).allProceduresAreCallable(); // SQLException Mockito.when(obj.allProceduresAreCallable()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::allProceduresAreCallable); } @Test public void testAllTablesAreSelectable() throws Exception { try { delegate.allTablesAreSelectable(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).allTablesAreSelectable(); // SQLException Mockito.when(obj.allTablesAreSelectable()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::allTablesAreSelectable); } @Test public void testAutoCommitFailureClosesAllResultSets() throws Exception { try { delegate.autoCommitFailureClosesAllResultSets(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).autoCommitFailureClosesAllResultSets(); // SQLException Mockito.when(obj.autoCommitFailureClosesAllResultSets()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::autoCommitFailureClosesAllResultSets); } @Test public void testCheckOpen() throws Exception { delegate = new DelegatingDatabaseMetaData(conn, conn.getMetaData()); final ResultSet rst = delegate.getSchemas(); assertFalse(rst.isClosed()); conn.close(); assertTrue(rst.isClosed()); } @Test public void testDataDefinitionCausesTransactionCommit() throws Exception { try { delegate.dataDefinitionCausesTransactionCommit(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).dataDefinitionCausesTransactionCommit(); // SQLException Mockito.when(obj.dataDefinitionCausesTransactionCommit()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::dataDefinitionCausesTransactionCommit); } @Test public void testDataDefinitionIgnoredInTransactions() throws Exception { try { delegate.dataDefinitionIgnoredInTransactions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).dataDefinitionIgnoredInTransactions(); // SQLException Mockito.when(obj.dataDefinitionIgnoredInTransactions()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::dataDefinitionIgnoredInTransactions); } @Test public void testDeletesAreDetectedInteger() throws Exception { try { delegate.deletesAreDetected(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).deletesAreDetected(1); // SQLException Mockito.when(obj.deletesAreDetected(1)).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, () -> delegate.deletesAreDetected(1)); } @Test public void testDoesMaxRowSizeIncludeBlobs() throws Exception { try { delegate.doesMaxRowSizeIncludeBlobs(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).doesMaxRowSizeIncludeBlobs(); // SQLException Mockito.when(obj.doesMaxRowSizeIncludeBlobs()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::doesMaxRowSizeIncludeBlobs); } @Test public void testGeneratedKeyAlwaysReturned() throws Exception { try { delegate.generatedKeyAlwaysReturned(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).generatedKeyAlwaysReturned(); // SQLException Mockito.when(obj.generatedKeyAlwaysReturned()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::generatedKeyAlwaysReturned); } @Test public void testGetAttributesStringStringStringString() throws Exception { try { delegate.getAttributes("foo", "foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getAttributes("foo", "foo", "foo", "foo"); } @Test public void testGetBestRowIdentifierStringStringStringIntegerBoolean() throws Exception { try { delegate.getBestRowIdentifier("foo", "foo", "foo", 1, Boolean.TRUE); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getBestRowIdentifier("foo", "foo", "foo", 1, Boolean.TRUE); } @Test public void testGetCatalogs() throws Exception { try { delegate.getCatalogs(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getCatalogs(); // SQLException Mockito.when(obj.getCatalogs()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::getCatalogs); } @Test public void testGetCatalogSeparator() throws Exception { try { delegate.getCatalogSeparator(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getCatalogSeparator(); // SQLException Mockito.when(obj.getCatalogSeparator()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::getCatalogSeparator); } @Test public void testGetCatalogTerm() throws Exception { try { delegate.getCatalogTerm(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getCatalogTerm(); // SQLException Mockito.when(obj.getCatalogTerm()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::getCatalogTerm); } @Test public void testGetClientInfoProperties() throws Exception { try { delegate.getClientInfoProperties(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getClientInfoProperties(); // SQLException Mockito.when(obj.getClientInfoProperties()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::getClientInfoProperties); } @Test public void testGetColumnPrivilegesStringStringStringString() throws Exception { try { delegate.getColumnPrivileges("foo", "foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getColumnPrivileges("foo", "foo", "foo", "foo"); } @Test public void testGetColumnsStringStringStringString() throws Exception { try { delegate.getColumns("foo", "foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getColumns("foo", "foo", "foo", "foo"); } /** * This method is a bit special, and doesn't call the method on the wrapped object, instead returning the connection from the delegate object itself. * * @throws Exception */ @Test public void testGetConnection() throws Exception { try { delegate.getConnection(); } catch (final SQLException e) { // ignore } verify(obj, times(0)).getConnection(); } @Test public void testGetCrossReferenceStringStringStringStringStringString() throws Exception { try { delegate.getCrossReference("foo", "foo", "foo", "foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getCrossReference("foo", "foo", "foo", "foo", "foo", "foo"); } @Test public void testGetDatabaseMajorVersion() throws Exception { try { delegate.getDatabaseMajorVersion(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getDatabaseMajorVersion(); // SQLException Mockito.when(obj.getDatabaseMajorVersion()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::getDatabaseMajorVersion); } @Test public void testGetDatabaseMinorVersion() throws Exception { try { delegate.getDatabaseMinorVersion(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getDatabaseMinorVersion(); // SQLException Mockito.when(obj.getDatabaseMinorVersion()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::getDatabaseMinorVersion); } @Test public void testGetDatabaseProductName() throws Exception { try { delegate.getDatabaseProductName(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getDatabaseProductName(); // SQLException Mockito.when(obj.getDatabaseProductName()).thenThrow(SQLException.class); // The default handler rethrows assertThrows(SQLException.class, delegate::getDatabaseProductName); } @Test public void testGetDatabaseProductVersion() throws Exception { try { delegate.getDatabaseProductVersion(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getDatabaseProductVersion(); } @Test public void testGetDefaultTransactionIsolation() throws Exception { try { delegate.getDefaultTransactionIsolation(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getDefaultTransactionIsolation(); } @Test public void testGetDelegate() throws Exception { assertEquals(obj, delegate.getDelegate()); } @Test public void testGetDriverMajorVersion() throws Exception { delegate.getDriverMajorVersion(); verify(obj, times(1)).getDriverMajorVersion(); } @Test public void testGetDriverMinorVersion() throws Exception { delegate.getDriverMinorVersion(); verify(obj, times(1)).getDriverMinorVersion(); } @Test public void testGetDriverName() throws Exception { try { delegate.getDriverName(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getDriverName(); } @Test public void testGetDriverVersion() throws Exception { try { delegate.getDriverVersion(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getDriverVersion(); } @Test public void testGetExportedKeysStringStringString() throws Exception { try { delegate.getExportedKeys("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getExportedKeys("foo", "foo", "foo"); } @Test public void testGetExtraNameCharacters() throws Exception { try { delegate.getExtraNameCharacters(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getExtraNameCharacters(); } @Test public void testGetFunctionColumnsStringStringStringString() throws Exception { try { delegate.getFunctionColumns("foo", "foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getFunctionColumns("foo", "foo", "foo", "foo"); } @Test public void testGetFunctionsStringStringString() throws Exception { try { delegate.getFunctions("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getFunctions("foo", "foo", "foo"); } @Test public void testGetIdentifierQuoteString() throws Exception { try { delegate.getIdentifierQuoteString(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getIdentifierQuoteString(); } @Test public void testGetImportedKeysStringStringString() throws Exception { try { delegate.getImportedKeys("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getImportedKeys("foo", "foo", "foo"); } @Test public void testGetIndexInfoStringStringStringBooleanBoolean() throws Exception { try { delegate.getIndexInfo("foo", "foo", "foo", Boolean.TRUE, Boolean.TRUE); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getIndexInfo("foo", "foo", "foo", Boolean.TRUE, Boolean.TRUE); } @Test public void testGetInnermostDelegate() { assertNotNull(delegate.getInnermostDelegate()); } @Test public void testGetJDBCMajorVersion() throws Exception { try { delegate.getJDBCMajorVersion(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getJDBCMajorVersion(); } @Test public void testGetJDBCMinorVersion() throws Exception { try { delegate.getJDBCMinorVersion(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getJDBCMinorVersion(); } @Test public void testGetMaxBinaryLiteralLength() throws Exception { try { delegate.getMaxBinaryLiteralLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxBinaryLiteralLength(); } @Test public void testGetMaxCatalogNameLength() throws Exception { try { delegate.getMaxCatalogNameLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxCatalogNameLength(); } @Test public void testGetMaxCharLiteralLength() throws Exception { try { delegate.getMaxCharLiteralLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxCharLiteralLength(); } @Test public void testGetMaxColumnNameLength() throws Exception { try { delegate.getMaxColumnNameLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxColumnNameLength(); } @Test public void testGetMaxColumnsInGroupBy() throws Exception { try { delegate.getMaxColumnsInGroupBy(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxColumnsInGroupBy(); } @Test public void testGetMaxColumnsInIndex() throws Exception { try { delegate.getMaxColumnsInIndex(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxColumnsInIndex(); } @Test public void testGetMaxColumnsInOrderBy() throws Exception { try { delegate.getMaxColumnsInOrderBy(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxColumnsInOrderBy(); } @Test public void testGetMaxColumnsInSelect() throws Exception { try { delegate.getMaxColumnsInSelect(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxColumnsInSelect(); } @Test public void testGetMaxColumnsInTable() throws Exception { try { delegate.getMaxColumnsInTable(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxColumnsInTable(); } @Test public void testGetMaxConnections() throws Exception { try { delegate.getMaxConnections(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxConnections(); } @Test public void testGetMaxCursorNameLength() throws Exception { try { delegate.getMaxCursorNameLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxCursorNameLength(); } @Test public void testGetMaxIndexLength() throws Exception { try { delegate.getMaxIndexLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxIndexLength(); } @Test public void testGetMaxLogicalLobSize() throws Exception { try { delegate.getMaxLogicalLobSize(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxLogicalLobSize(); } @Test public void testGetMaxProcedureNameLength() throws Exception { try { delegate.getMaxProcedureNameLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxProcedureNameLength(); } @Test public void testGetMaxRowSize() throws Exception { try { delegate.getMaxRowSize(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxRowSize(); } @Test public void testGetMaxSchemaNameLength() throws Exception { try { delegate.getMaxSchemaNameLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxSchemaNameLength(); } @Test public void testGetMaxStatementLength() throws Exception { try { delegate.getMaxStatementLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxStatementLength(); } @Test public void testGetMaxStatements() throws Exception { try { delegate.getMaxStatements(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxStatements(); } @Test public void testGetMaxTableNameLength() throws Exception { try { delegate.getMaxTableNameLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxTableNameLength(); } @Test public void testGetMaxTablesInSelect() throws Exception { try { delegate.getMaxTablesInSelect(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxTablesInSelect(); } @Test public void testGetMaxUserNameLength() throws Exception { try { delegate.getMaxUserNameLength(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getMaxUserNameLength(); } @Test public void testGetNumericFunctions() throws Exception { try { delegate.getNumericFunctions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getNumericFunctions(); } @Test public void testGetPrimaryKeysStringStringString() throws Exception { try { delegate.getPrimaryKeys("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getPrimaryKeys("foo", "foo", "foo"); } @Test public void testGetProcedureColumnsStringStringStringString() throws Exception { try { delegate.getProcedureColumns("foo", "foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getProcedureColumns("foo", "foo", "foo", "foo"); } @Test public void testGetProceduresStringStringString() throws Exception { try { delegate.getProcedures("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getProcedures("foo", "foo", "foo"); } @Test public void testGetProcedureTerm() throws Exception { try { delegate.getProcedureTerm(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getProcedureTerm(); } @Test public void testGetPseudoColumnsStringStringStringString() throws Exception { try { delegate.getPseudoColumns("foo", "foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getPseudoColumns("foo", "foo", "foo", "foo"); } @Test public void testGetResultSetHoldability() throws Exception { try { delegate.getResultSetHoldability(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getResultSetHoldability(); } @Test public void testGetRowIdLifetime() throws Exception { try { delegate.getRowIdLifetime(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getRowIdLifetime(); } @Test public void testGetSchemas() throws Exception { try { delegate.getSchemas(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSchemas(); } @Test public void testGetSchemasStringString() throws Exception { try { delegate.getSchemas("foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSchemas("foo", "foo"); } @Test public void testGetSchemaTerm() throws Exception { try { delegate.getSchemaTerm(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSchemaTerm(); } @Test public void testGetSearchStringEscape() throws Exception { try { delegate.getSearchStringEscape(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSearchStringEscape(); } @Test public void testGetSQLKeywords() throws Exception { try { delegate.getSQLKeywords(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSQLKeywords(); } @Test public void testGetSQLStateType() throws Exception { try { delegate.getSQLStateType(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSQLStateType(); } @Test public void testGetStringFunctions() throws Exception { try { delegate.getStringFunctions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getStringFunctions(); } @Test public void testGetSuperTablesStringStringString() throws Exception { try { delegate.getSuperTables("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSuperTables("foo", "foo", "foo"); } @Test public void testGetSuperTypesStringStringString() throws Exception { try { delegate.getSuperTypes("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSuperTypes("foo", "foo", "foo"); } @Test public void testGetSystemFunctions() throws Exception { try { delegate.getSystemFunctions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getSystemFunctions(); } @Test public void testGetTablePrivilegesStringStringString() throws Exception { try { delegate.getTablePrivileges("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getTablePrivileges("foo", "foo", "foo"); } @Test public void testGetTablesStringStringStringStringArray() throws Exception { try { delegate.getTables("foo", "foo", "foo", (String[]) null); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getTables("foo", "foo", "foo", (String[]) null); } @Test public void testGetTableTypes() throws Exception { try { delegate.getTableTypes(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getTableTypes(); } @Test public void testGetTimeDateFunctions() throws Exception { try { delegate.getTimeDateFunctions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getTimeDateFunctions(); } @Test public void testGetTypeInfo() throws Exception { try { delegate.getTypeInfo(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getTypeInfo(); } @Test public void testGetUDTsStringStringStringIntegerArray() throws Exception { try { delegate.getUDTs("foo", "foo", "foo", (int[]) null); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getUDTs("foo", "foo", "foo", (int[]) null); } @Test public void testGetURL() throws Exception { try { delegate.getURL(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getURL(); } @Test public void testGetUserName() throws Exception { try { delegate.getUserName(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getUserName(); } @Test public void testGetVersionColumnsStringStringString() throws Exception { try { delegate.getVersionColumns("foo", "foo", "foo"); } catch (final SQLException e) { // ignore } verify(obj, times(1)).getVersionColumns("foo", "foo", "foo"); } @Test public void testInsertsAreDetectedInteger() throws Exception { try { delegate.insertsAreDetected(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).insertsAreDetected(1); } @Test public void testIsCatalogAtStart() throws Exception { try { delegate.isCatalogAtStart(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).isCatalogAtStart(); } @Test public void testIsReadOnly() throws Exception { try { delegate.isReadOnly(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).isReadOnly(); } @Test public void testLocatorsUpdateCopy() throws Exception { try { delegate.locatorsUpdateCopy(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).locatorsUpdateCopy(); } @Test public void testNullArguments() throws Exception { assertThrows(NullPointerException.class, () -> new DelegatingDatabaseMetaData(null, null)); assertThrows(NullPointerException.class, () -> new DelegatingDatabaseMetaData(new DelegatingConnection(null), null)); } @Test public void testNullPlusNonNullIsNull() throws Exception { try { delegate.nullPlusNonNullIsNull(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).nullPlusNonNullIsNull(); } @Test public void testNullsAreSortedAtEnd() throws Exception { try { delegate.nullsAreSortedAtEnd(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).nullsAreSortedAtEnd(); } @Test public void testNullsAreSortedAtStart() throws Exception { try { delegate.nullsAreSortedAtStart(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).nullsAreSortedAtStart(); } @Test public void testNullsAreSortedHigh() throws Exception { try { delegate.nullsAreSortedHigh(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).nullsAreSortedHigh(); } @Test public void testNullsAreSortedLow() throws Exception { try { delegate.nullsAreSortedLow(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).nullsAreSortedLow(); } @Test public void testOthersDeletesAreVisibleInteger() throws Exception { try { delegate.othersDeletesAreVisible(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).othersDeletesAreVisible(1); } @Test public void testOthersInsertsAreVisibleInteger() throws Exception { try { delegate.othersInsertsAreVisible(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).othersInsertsAreVisible(1); } @Test public void testOthersUpdatesAreVisibleInteger() throws Exception { try { delegate.othersUpdatesAreVisible(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).othersUpdatesAreVisible(1); } @Test public void testOwnDeletesAreVisibleInteger() throws Exception { try { delegate.ownDeletesAreVisible(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).ownDeletesAreVisible(1); } @Test public void testOwnInsertsAreVisibleInteger() throws Exception { try { delegate.ownInsertsAreVisible(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).ownInsertsAreVisible(1); } @Test public void testOwnUpdatesAreVisibleInteger() throws Exception { try { delegate.ownUpdatesAreVisible(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).ownUpdatesAreVisible(1); } @Test public void testStoresLowerCaseIdentifiers() throws Exception { try { delegate.storesLowerCaseIdentifiers(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).storesLowerCaseIdentifiers(); } @Test public void testStoresLowerCaseQuotedIdentifiers() throws Exception { try { delegate.storesLowerCaseQuotedIdentifiers(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).storesLowerCaseQuotedIdentifiers(); } @Test public void testStoresMixedCaseIdentifiers() throws Exception { try { delegate.storesMixedCaseIdentifiers(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).storesMixedCaseIdentifiers(); } @Test public void testStoresMixedCaseQuotedIdentifiers() throws Exception { try { delegate.storesMixedCaseQuotedIdentifiers(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).storesMixedCaseQuotedIdentifiers(); } @Test public void testStoresUpperCaseIdentifiers() throws Exception { try { delegate.storesUpperCaseIdentifiers(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).storesUpperCaseIdentifiers(); } @Test public void testStoresUpperCaseQuotedIdentifiers() throws Exception { try { delegate.storesUpperCaseQuotedIdentifiers(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).storesUpperCaseQuotedIdentifiers(); } @Test public void testSupportsAlterTableWithAddColumn() throws Exception { try { delegate.supportsAlterTableWithAddColumn(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsAlterTableWithAddColumn(); } @Test public void testSupportsAlterTableWithDropColumn() throws Exception { try { delegate.supportsAlterTableWithDropColumn(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsAlterTableWithDropColumn(); } @Test public void testSupportsANSI92EntryLevelSQL() throws Exception { try { delegate.supportsANSI92EntryLevelSQL(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsANSI92EntryLevelSQL(); } @Test public void testSupportsANSI92FullSQL() throws Exception { try { delegate.supportsANSI92FullSQL(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsANSI92FullSQL(); } @Test public void testSupportsANSI92IntermediateSQL() throws Exception { try { delegate.supportsANSI92IntermediateSQL(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsANSI92IntermediateSQL(); } @Test public void testSupportsBatchUpdates() throws Exception { try { delegate.supportsBatchUpdates(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsBatchUpdates(); } @Test public void testSupportsCatalogsInDataManipulation() throws Exception { try { delegate.supportsCatalogsInDataManipulation(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsCatalogsInDataManipulation(); } @Test public void testSupportsCatalogsInIndexDefinitions() throws Exception { try { delegate.supportsCatalogsInIndexDefinitions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsCatalogsInIndexDefinitions(); } @Test public void testSupportsCatalogsInPrivilegeDefinitions() throws Exception { try { delegate.supportsCatalogsInPrivilegeDefinitions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsCatalogsInPrivilegeDefinitions(); } @Test public void testSupportsCatalogsInProcedureCalls() throws Exception { try { delegate.supportsCatalogsInProcedureCalls(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsCatalogsInProcedureCalls(); } @Test public void testSupportsCatalogsInTableDefinitions() throws Exception { try { delegate.supportsCatalogsInTableDefinitions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsCatalogsInTableDefinitions(); } @Test public void testSupportsColumnAliasing() throws Exception { try { delegate.supportsColumnAliasing(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsColumnAliasing(); } @Test public void testSupportsConvert() throws Exception { try { delegate.supportsConvert(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsConvert(); } @Test public void testSupportsConvertIntegerInteger() throws Exception { try { delegate.supportsConvert(1, 1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsConvert(1, 1); } @Test public void testSupportsCoreSQLGrammar() throws Exception { try { delegate.supportsCoreSQLGrammar(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsCoreSQLGrammar(); } @Test public void testSupportsCorrelatedSubqueries() throws Exception { try { delegate.supportsCorrelatedSubqueries(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsCorrelatedSubqueries(); } @Test public void testSupportsDataDefinitionAndDataManipulationTransactions() throws Exception { try { delegate.supportsDataDefinitionAndDataManipulationTransactions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsDataDefinitionAndDataManipulationTransactions(); } @Test public void testSupportsDataManipulationTransactionsOnly() throws Exception { try { delegate.supportsDataManipulationTransactionsOnly(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsDataManipulationTransactionsOnly(); } @Test public void testSupportsDifferentTableCorrelationNames() throws Exception { try { delegate.supportsDifferentTableCorrelationNames(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsDifferentTableCorrelationNames(); } @Test public void testSupportsExpressionsInOrderBy() throws Exception { try { delegate.supportsExpressionsInOrderBy(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsExpressionsInOrderBy(); } @Test public void testSupportsExtendedSQLGrammar() throws Exception { try { delegate.supportsExtendedSQLGrammar(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsExtendedSQLGrammar(); } @Test public void testSupportsFullOuterJoins() throws Exception { try { delegate.supportsFullOuterJoins(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsFullOuterJoins(); } @Test public void testSupportsGetGeneratedKeys() throws Exception { try { delegate.supportsGetGeneratedKeys(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsGetGeneratedKeys(); } @Test public void testSupportsGroupBy() throws Exception { try { delegate.supportsGroupBy(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsGroupBy(); } @Test public void testSupportsGroupByBeyondSelect() throws Exception { try { delegate.supportsGroupByBeyondSelect(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsGroupByBeyondSelect(); } @Test public void testSupportsGroupByUnrelated() throws Exception { try { delegate.supportsGroupByUnrelated(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsGroupByUnrelated(); } @Test public void testSupportsIntegrityEnhancementFacility() throws Exception { try { delegate.supportsIntegrityEnhancementFacility(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsIntegrityEnhancementFacility(); } @Test public void testSupportsLikeEscapeClause() throws Exception { try { delegate.supportsLikeEscapeClause(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsLikeEscapeClause(); } @Test public void testSupportsLimitedOuterJoins() throws Exception { try { delegate.supportsLimitedOuterJoins(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsLimitedOuterJoins(); } @Test public void testSupportsMinimumSQLGrammar() throws Exception { try { delegate.supportsMinimumSQLGrammar(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsMinimumSQLGrammar(); } @Test public void testSupportsMixedCaseIdentifiers() throws Exception { try { delegate.supportsMixedCaseIdentifiers(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsMixedCaseIdentifiers(); } @Test public void testSupportsMixedCaseQuotedIdentifiers() throws Exception { try { delegate.supportsMixedCaseQuotedIdentifiers(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsMixedCaseQuotedIdentifiers(); } @Test public void testSupportsMultipleOpenResults() throws Exception { try { delegate.supportsMultipleOpenResults(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsMultipleOpenResults(); } @Test public void testSupportsMultipleResultSets() throws Exception { try { delegate.supportsMultipleResultSets(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsMultipleResultSets(); } @Test public void testSupportsMultipleTransactions() throws Exception { try { delegate.supportsMultipleTransactions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsMultipleTransactions(); } @Test public void testSupportsNamedParameters() throws Exception { try { delegate.supportsNamedParameters(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsNamedParameters(); } @Test public void testSupportsNonNullableColumns() throws Exception { try { delegate.supportsNonNullableColumns(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsNonNullableColumns(); } @Test public void testSupportsOpenCursorsAcrossCommit() throws Exception { try { delegate.supportsOpenCursorsAcrossCommit(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsOpenCursorsAcrossCommit(); } @Test public void testSupportsOpenCursorsAcrossRollback() throws Exception { try { delegate.supportsOpenCursorsAcrossRollback(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsOpenCursorsAcrossRollback(); } @Test public void testSupportsOpenStatementsAcrossCommit() throws Exception { try { delegate.supportsOpenStatementsAcrossCommit(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsOpenStatementsAcrossCommit(); } @Test public void testSupportsOpenStatementsAcrossRollback() throws Exception { try { delegate.supportsOpenStatementsAcrossRollback(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsOpenStatementsAcrossRollback(); } @Test public void testSupportsOrderByUnrelated() throws Exception { try { delegate.supportsOrderByUnrelated(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsOrderByUnrelated(); } @Test public void testSupportsOuterJoins() throws Exception { try { delegate.supportsOuterJoins(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsOuterJoins(); } @Test public void testSupportsPositionedDelete() throws Exception { try { delegate.supportsPositionedDelete(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsPositionedDelete(); } @Test public void testSupportsPositionedUpdate() throws Exception { try { delegate.supportsPositionedUpdate(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsPositionedUpdate(); } @Test public void testSupportsRefCursors() throws Exception { try { delegate.supportsRefCursors(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsRefCursors(); } @Test public void testSupportsResultSetConcurrencyIntegerInteger() throws Exception { try { delegate.supportsResultSetConcurrency(1, 1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsResultSetConcurrency(1, 1); } @Test public void testSupportsResultSetHoldabilityInteger() throws Exception { try { delegate.supportsResultSetHoldability(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsResultSetHoldability(1); } @Test public void testSupportsResultSetTypeInteger() throws Exception { try { delegate.supportsResultSetType(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsResultSetType(1); } @Test public void testSupportsSavepoints() throws Exception { try { delegate.supportsSavepoints(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSavepoints(); } @Test public void testSupportsSchemasInDataManipulation() throws Exception { try { delegate.supportsSchemasInDataManipulation(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSchemasInDataManipulation(); } @Test public void testSupportsSchemasInIndexDefinitions() throws Exception { try { delegate.supportsSchemasInIndexDefinitions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSchemasInIndexDefinitions(); } @Test public void testSupportsSchemasInPrivilegeDefinitions() throws Exception { try { delegate.supportsSchemasInPrivilegeDefinitions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSchemasInPrivilegeDefinitions(); } @Test public void testSupportsSchemasInProcedureCalls() throws Exception { try { delegate.supportsSchemasInProcedureCalls(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSchemasInProcedureCalls(); } @Test public void testSupportsSchemasInTableDefinitions() throws Exception { try { delegate.supportsSchemasInTableDefinitions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSchemasInTableDefinitions(); } @Test public void testSupportsSelectForUpdate() throws Exception { try { delegate.supportsSelectForUpdate(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSelectForUpdate(); } @Test public void testSupportsStatementPooling() throws Exception { try { delegate.supportsStatementPooling(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsStatementPooling(); } @Test public void testSupportsStoredFunctionsUsingCallSyntax() throws Exception { try { delegate.supportsStoredFunctionsUsingCallSyntax(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsStoredFunctionsUsingCallSyntax(); } @Test public void testSupportsStoredProcedures() throws Exception { try { delegate.supportsStoredProcedures(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsStoredProcedures(); } @Test public void testSupportsSubqueriesInComparisons() throws Exception { try { delegate.supportsSubqueriesInComparisons(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSubqueriesInComparisons(); } @Test public void testSupportsSubqueriesInExists() throws Exception { try { delegate.supportsSubqueriesInExists(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSubqueriesInExists(); } @Test public void testSupportsSubqueriesInIns() throws Exception { try { delegate.supportsSubqueriesInIns(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSubqueriesInIns(); } @Test public void testSupportsSubqueriesInQuantifieds() throws Exception { try { delegate.supportsSubqueriesInQuantifieds(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsSubqueriesInQuantifieds(); } @Test public void testSupportsTableCorrelationNames() throws Exception { try { delegate.supportsTableCorrelationNames(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsTableCorrelationNames(); } @Test public void testSupportsTransactionIsolationLevelInteger() throws Exception { try { delegate.supportsTransactionIsolationLevel(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsTransactionIsolationLevel(1); } @Test public void testSupportsTransactions() throws Exception { try { delegate.supportsTransactions(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsTransactions(); } @Test public void testSupportsUnion() throws Exception { try { delegate.supportsUnion(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsUnion(); } @Test public void testSupportsUnionAll() throws Exception { try { delegate.supportsUnionAll(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).supportsUnionAll(); } @Test public void testUpdatesAreDetectedInteger() throws Exception { try { delegate.updatesAreDetected(1); } catch (final SQLException e) { // ignore } verify(obj, times(1)).updatesAreDetected(1); } @Test public void testUsesLocalFilePerTable() throws Exception { try { delegate.usesLocalFilePerTable(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).usesLocalFilePerTable(); } @Test public void testUsesLocalFiles() throws Exception { try { delegate.usesLocalFiles(); } catch (final SQLException e) { // ignore } verify(obj, times(1)).usesLocalFiles(); } @Test public void testWrap() throws SQLException { assertEquals(delegate, delegate.unwrap(DatabaseMetaData.class)); assertEquals(delegate, delegate.unwrap(DelegatingDatabaseMetaData.class)); assertEquals(obj, delegate.unwrap(obj.getClass())); assertNull(delegate.unwrap(String.class)); assertTrue(delegate.isWrapperFor(DatabaseMetaData.class)); assertTrue(delegate.isWrapperFor(DelegatingDatabaseMetaData.class)); assertTrue(delegate.isWrapperFor(obj.getClass())); assertFalse(delegate.isWrapperFor(String.class)); } } TestDelegatingPreparedStatement.java000066400000000000000000000441541472045345700355430ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.sql.PreparedStatement; import java.sql.SQLException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @SuppressWarnings({ "deprecation", "rawtypes" }) // BigDecimal methods, and casting for mocks public class TestDelegatingPreparedStatement { private TesterConnection testerConn; private DelegatingConnection connection; private PreparedStatement obj; private DelegatingPreparedStatement delegate; @BeforeEach public void setUp() throws Exception { testerConn = new TesterConnection("test", "test"); connection = new DelegatingConnection<>(testerConn); obj = mock(PreparedStatement.class); delegate = new DelegatingPreparedStatement(connection, obj); } @Test public void testAddBatch() throws Exception { try { delegate.addBatch(); } catch (final SQLException e) { } verify(obj, times(1)).addBatch(); } @Test public void testClearParameters() throws Exception { try { delegate.clearParameters(); } catch (final SQLException e) { } verify(obj, times(1)).clearParameters(); } @Test public void testExecute() throws Exception { try { delegate.execute(); } catch (final SQLException e) { } verify(obj, times(1)).execute(); } @Test public void testExecuteLargeUpdate() throws Exception { try { delegate.executeLargeUpdate(); } catch (final SQLException e) { } verify(obj, times(1)).executeLargeUpdate(); } @Test public void testExecuteQuery() throws Exception { try { delegate.executeQuery(); } catch (final SQLException e) { } verify(obj, times(1)).executeQuery(); } @Test public void testExecuteQueryReturnsNotNull() throws Exception { obj = new TesterPreparedStatement(testerConn, "select * from foo"); delegate = new DelegatingPreparedStatement(connection, obj); assertNotNull(delegate.executeQuery()); } @Test public void testExecuteQueryReturnsNull() throws Exception { obj = new TesterPreparedStatement(testerConn, "null"); delegate = new DelegatingPreparedStatement(connection, obj); assertNull(delegate.executeQuery()); } @Test public void testExecuteUpdate() throws Exception { try { delegate.executeUpdate(); } catch (final SQLException e) { } verify(obj, times(1)).executeUpdate(); } @Test public void testGetDelegate() throws Exception { obj = new TesterPreparedStatement(testerConn, "select * from foo"); delegate = new DelegatingPreparedStatement(connection, obj); assertEquals(obj, delegate.getDelegate()); } @Test public void testGetMetaData() throws Exception { try { delegate.getMetaData(); } catch (final SQLException e) { } verify(obj, times(1)).getMetaData(); } @Test public void testGetParameterMetaData() throws Exception { try { delegate.getParameterMetaData(); } catch (final SQLException e) { } verify(obj, times(1)).getParameterMetaData(); } @Test public void testSetArrayIntegerArray() throws Exception { try { delegate.setArray(1, (java.sql.Array) null); } catch (final SQLException e) { } verify(obj, times(1)).setArray(1, (java.sql.Array) null); } @Test public void testSetAsciiStreamIntegerInputStream() throws Exception { try { delegate.setAsciiStream(1, (java.io.InputStream) null); } catch (final SQLException e) { } verify(obj, times(1)).setAsciiStream(1, (java.io.InputStream) null); } @Test public void testSetAsciiStreamIntegerInputStreamInteger() throws Exception { try { delegate.setAsciiStream(1, (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setAsciiStream(1, (java.io.InputStream) null, 1); } @Test public void testSetAsciiStreamIntegerInputStreamLong() throws Exception { try { delegate.setAsciiStream(1, (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setAsciiStream(1, (java.io.InputStream) null, 1L); } @Test public void testSetBigDecimalIntegerBigDecimal() throws Exception { try { delegate.setBigDecimal(1, java.math.BigDecimal.valueOf(1.0d)); } catch (final SQLException e) { } verify(obj, times(1)).setBigDecimal(1, java.math.BigDecimal.valueOf(1.0d)); } @Test public void testSetBinaryStreamIntegerInputStream() throws Exception { try { delegate.setBinaryStream(1, (java.io.InputStream) null); } catch (final SQLException e) { } verify(obj, times(1)).setBinaryStream(1, (java.io.InputStream) null); } @Test public void testSetBinaryStreamIntegerInputStreamInteger() throws Exception { try { delegate.setBinaryStream(1, (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setBinaryStream(1, (java.io.InputStream) null, 1); } @Test public void testSetBinaryStreamIntegerInputStreamLong() throws Exception { try { delegate.setBinaryStream(1, (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setBinaryStream(1, (java.io.InputStream) null, 1L); } @Test public void testSetBlobIntegerBlob() throws Exception { try { delegate.setBlob(1, (java.sql.Blob) null); } catch (final SQLException e) { } verify(obj, times(1)).setBlob(1, (java.sql.Blob) null); } @Test public void testSetBlobIntegerInputStream() throws Exception { try { delegate.setBlob(1, (java.io.InputStream) null); } catch (final SQLException e) { } verify(obj, times(1)).setBlob(1, (java.io.InputStream) null); } @Test public void testSetBlobIntegerInputStreamLong() throws Exception { try { delegate.setBlob(1, (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setBlob(1, (java.io.InputStream) null, 1L); } @Test public void testSetBooleanIntegerBoolean() throws Exception { try { delegate.setBoolean(1, Boolean.TRUE); } catch (final SQLException e) { } verify(obj, times(1)).setBoolean(1, Boolean.TRUE); } @Test public void testSetByteIntegerByte() throws Exception { try { delegate.setByte(1, (byte) 1); } catch (final SQLException e) { } verify(obj, times(1)).setByte(1, (byte) 1); } @Test public void testSetBytesIntegerByteArray() throws Exception { try { delegate.setBytes(1, new byte[] { 1 }); } catch (final SQLException e) { } verify(obj, times(1)).setBytes(1, new byte[] { 1 }); } @Test public void testSetCharacterStreamIntegerReader() throws Exception { try { delegate.setCharacterStream(1, (java.io.StringReader) null); } catch (final SQLException e) { } verify(obj, times(1)).setCharacterStream(1, (java.io.StringReader) null); } @Test public void testSetCharacterStreamIntegerReaderInteger() throws Exception { try { delegate.setCharacterStream(1, (java.io.StringReader) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setCharacterStream(1, (java.io.StringReader) null, 1); } @Test public void testSetCharacterStreamIntegerReaderLong() throws Exception { try { delegate.setCharacterStream(1, (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setCharacterStream(1, (java.io.StringReader) null, 1L); } @Test public void testSetClobIntegerClob() throws Exception { try { delegate.setClob(1, (java.sql.Clob) null); } catch (final SQLException e) { } verify(obj, times(1)).setClob(1, (java.sql.Clob) null); } @Test public void testSetClobIntegerReader() throws Exception { try { delegate.setClob(1, (java.io.StringReader) null); } catch (final SQLException e) { } verify(obj, times(1)).setClob(1, (java.io.StringReader) null); } @Test public void testSetClobIntegerReaderLong() throws Exception { try { delegate.setClob(1, (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setClob(1, (java.io.StringReader) null, 1L); } @Test public void testSetDateIntegerSqlDate() throws Exception { try { delegate.setDate(1, new java.sql.Date(1529827548745L)); } catch (final SQLException e) { } verify(obj, times(1)).setDate(1, new java.sql.Date(1529827548745L)); } @Test public void testSetDateIntegerSqlDateCalendar() throws Exception { try { delegate.setDate(1, new java.sql.Date(1529827548745L), (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).setDate(1, new java.sql.Date(1529827548745L), (java.util.Calendar) null); } @Test public void testSetDoubleIntegerDouble() throws Exception { try { delegate.setDouble(1, 1.0d); } catch (final SQLException e) { } verify(obj, times(1)).setDouble(1, 1.0d); } @Test public void testSetFloatIntegerFloat() throws Exception { try { delegate.setFloat(1, 1.0f); } catch (final SQLException e) { } verify(obj, times(1)).setFloat(1, 1.0f); } @Test public void testSetIntIntegerInteger() throws Exception { try { delegate.setInt(1, 1); } catch (final SQLException e) { } verify(obj, times(1)).setInt(1, 1); } @Test public void testSetLongIntegerLong() throws Exception { try { delegate.setLong(1, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setLong(1, 1L); } @Test public void testSetNCharacterStreamIntegerReader() throws Exception { try { delegate.setNCharacterStream(1, (java.io.StringReader) null); } catch (final SQLException e) { } verify(obj, times(1)).setNCharacterStream(1, (java.io.StringReader) null); } @Test public void testSetNCharacterStreamIntegerReaderLong() throws Exception { try { delegate.setNCharacterStream(1, (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setNCharacterStream(1, (java.io.StringReader) null, 1L); } @Test public void testSetNClobIntegerNClob() throws Exception { try { delegate.setNClob(1, (java.sql.NClob) null); } catch (final SQLException e) { } verify(obj, times(1)).setNClob(1, (java.sql.NClob) null); } @Test public void testSetNClobIntegerReader() throws Exception { try { delegate.setNClob(1, (java.io.StringReader) null); } catch (final SQLException e) { } verify(obj, times(1)).setNClob(1, (java.io.StringReader) null); } @Test public void testSetNClobIntegerReaderLong() throws Exception { try { delegate.setNClob(1, (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(obj, times(1)).setNClob(1, (java.io.StringReader) null, 1L); } @Test public void testSetNStringIntegerString() throws Exception { try { delegate.setNString(1, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).setNString(1, "foo"); } @Test public void testSetNullIntegerInteger() throws Exception { try { delegate.setNull(1, 1); } catch (final SQLException e) { } verify(obj, times(1)).setNull(1, 1); } @Test public void testSetNullIntegerIntegerString() throws Exception { try { delegate.setNull(1, 1, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).setNull(1, 1, "foo"); } @Test public void testSetObjectIntegerObject() throws Exception { try { delegate.setObject(1, System.err); } catch (final SQLException e) { } verify(obj, times(1)).setObject(1, System.err); } @Test public void testSetObjectIntegerObjectInteger() throws Exception { try { delegate.setObject(1, System.err, 1); } catch (final SQLException e) { } verify(obj, times(1)).setObject(1, System.err, 1); } @Test public void testSetObjectIntegerObjectIntegerInteger() throws Exception { try { delegate.setObject(1, System.err, 1, 1); } catch (final SQLException e) { } verify(obj, times(1)).setObject(1, System.err, 1, 1); } @Test public void testSetObjectIntegerObjectSQLType() throws Exception { try { delegate.setObject(1, System.err, (java.sql.SQLType) null); } catch (final SQLException e) { } verify(obj, times(1)).setObject(1, System.err, (java.sql.SQLType) null); } @Test public void testSetObjectIntegerObjectSQLTypeInteger() throws Exception { try { delegate.setObject(1, System.err, (java.sql.SQLType) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setObject(1, System.err, (java.sql.SQLType) null, 1); } @Test public void testSetRefIntegerRef() throws Exception { try { delegate.setRef(1, (java.sql.Ref) null); } catch (final SQLException e) { } verify(obj, times(1)).setRef(1, (java.sql.Ref) null); } @Test public void testSetRowIdIntegerRowId() throws Exception { try { delegate.setRowId(1, (java.sql.RowId) null); } catch (final SQLException e) { } verify(obj, times(1)).setRowId(1, (java.sql.RowId) null); } @Test public void testSetShortIntegerShort() throws Exception { try { delegate.setShort(1, (short) 1); } catch (final SQLException e) { } verify(obj, times(1)).setShort(1, (short) 1); } @Test public void testSetSQLXMLIntegerSQLXML() throws Exception { try { delegate.setSQLXML(1, (java.sql.SQLXML) null); } catch (final SQLException e) { } verify(obj, times(1)).setSQLXML(1, (java.sql.SQLXML) null); } @Test public void testSetStringIntegerString() throws Exception { try { delegate.setString(1, "foo"); } catch (final SQLException e) { } verify(obj, times(1)).setString(1, "foo"); } @Test public void testSetTimeIntegerTime() throws Exception { try { delegate.setTime(1, (java.sql.Time) null); } catch (final SQLException e) { } verify(obj, times(1)).setTime(1, (java.sql.Time) null); } @Test public void testSetTimeIntegerTimeCalendar() throws Exception { try { delegate.setTime(1, (java.sql.Time) null, (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).setTime(1, (java.sql.Time) null, (java.util.Calendar) null); } @Test public void testSetTimestampIntegerTimestamp() throws Exception { try { delegate.setTimestamp(1, (java.sql.Timestamp) null); } catch (final SQLException e) { } verify(obj, times(1)).setTimestamp(1, (java.sql.Timestamp) null); } @Test public void testSetTimestampIntegerTimestampCalendar() throws Exception { try { delegate.setTimestamp(1, (java.sql.Timestamp) null, (java.util.Calendar) null); } catch (final SQLException e) { } verify(obj, times(1)).setTimestamp(1, (java.sql.Timestamp) null, (java.util.Calendar) null); } @Test public void testSetUnicodeStreamIntegerInputStreamInteger() throws Exception { try { delegate.setUnicodeStream(1, (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(obj, times(1)).setUnicodeStream(1, (java.io.InputStream) null, 1); } @Test public void testSetURLIntegerUrl() throws Exception { try { delegate.setURL(1, (java.net.URL) null); } catch (final SQLException e) { } verify(obj, times(1)).setURL(1, (java.net.URL) null); } } TestDelegatingResultSet.java000066400000000000000000001464371472045345700340550ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Tests for DelegatingResultSet. */ @SuppressWarnings({ "deprecation", "unchecked", "rawtypes" }) // BigDecimal methods, and casting for mocks public class TestDelegatingResultSet { private TesterConnection testConn; private DelegatingConnection conn; private ResultSet rs; private DelegatingResultSet delegate; @BeforeEach public void setUp() { testConn = new TesterConnection("foo", "bar"); conn = new DelegatingConnection<>(testConn); rs = mock(ResultSet.class); delegate = (DelegatingResultSet) DelegatingResultSet.wrapResultSet(conn, rs); } @Test public void testAbsoluteInteger() throws Exception { try { delegate.absolute(1); } catch (final SQLException e) { } verify(rs, times(1)).absolute(1); } @Test public void testAbsolutes() throws Exception { try { delegate.absolute(1); } catch (final SQLException e) { } verify(rs, times(1)).absolute(1); } @Test public void testAfterLast() throws Exception { try { delegate.afterLast(); } catch (final SQLException e) { } verify(rs, times(1)).afterLast(); } @Test public void testBeforeFirst() throws Exception { try { delegate.beforeFirst(); } catch (final SQLException e) { } verify(rs, times(1)).beforeFirst(); } @Test public void testCancelRowUpdates() throws Exception { try { delegate.cancelRowUpdates(); } catch (final SQLException e) { } verify(rs, times(1)).cancelRowUpdates(); } @Test public void testClearWarnings() throws Exception { try { delegate.clearWarnings(); } catch (final SQLException e) { } verify(rs, times(1)).clearWarnings(); } @Test public void testClose() throws Exception { try { delegate.close(); } catch (final SQLException e) { } verify(rs, times(1)).close(); } @Test public void testDeleteRow() throws Exception { try { delegate.deleteRow(); } catch (final SQLException e) { } verify(rs, times(1)).deleteRow(); } @Test public void testFindColumnString() throws Exception { try { delegate.findColumn("foo"); } catch (final SQLException e) { } verify(rs, times(1)).findColumn("foo"); } @Test public void testFirst() throws Exception { try { delegate.first(); } catch (final SQLException e) { } verify(rs, times(1)).first(); } @Test public void testGetArrayInteger() throws Exception { try { delegate.getArray(1); } catch (final SQLException e) { } verify(rs, times(1)).getArray(1); } @Test public void testGetArrayString() throws Exception { try { delegate.getArray("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getArray("foo"); } @Test public void testGetAsciiStreamInteger() throws Exception { try { delegate.getAsciiStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getAsciiStream(1); } @Test public void testGetAsciiStreamString() throws Exception { try { delegate.getAsciiStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getAsciiStream("foo"); } @Test public void testGetBigDecimalInteger() throws Exception { try { delegate.getBigDecimal(1); } catch (final SQLException e) { } verify(rs, times(1)).getBigDecimal(1); } // FIXME: this appears to be a bug @Disabled @Test public void testGetBigDecimalIntegerInteger() throws Exception { try { delegate.getBigDecimal(1, 1); } catch (final SQLException e) { } verify(rs, times(1)).getBigDecimal(1, 1); } @Test public void testGetBigDecimalString() throws Exception { try { delegate.getBigDecimal("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getBigDecimal("foo"); } // FIXME: this appears to be a bug @Disabled @Test public void testGetBigDecimalStringInteger() throws Exception { try { delegate.getBigDecimal("foo", 1); } catch (final SQLException e) { } verify(rs, times(1)).getBigDecimal("foo", 1); } @Test public void testGetBinaryStreamInteger() throws Exception { try { delegate.getBinaryStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getBinaryStream(1); } @Test public void testGetBinaryStreamString() throws Exception { try { delegate.getBinaryStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getBinaryStream("foo"); } @Test public void testGetBlobInteger() throws Exception { try { delegate.getBlob(1); } catch (final SQLException e) { } verify(rs, times(1)).getBlob(1); } @Test public void testGetBlobString() throws Exception { try { delegate.getBlob("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getBlob("foo"); } @Test public void testGetBooleanInteger() throws Exception { try { delegate.getBoolean(1); } catch (final SQLException e) { } verify(rs, times(1)).getBoolean(1); } @Test public void testGetBooleanString() throws Exception { try { delegate.getBoolean("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getBoolean("foo"); } @Test public void testGetByteInteger() throws Exception { try { delegate.getByte(1); } catch (final SQLException e) { } verify(rs, times(1)).getByte(1); } @Test public void testGetBytesInteger() throws Exception { try { delegate.getBytes(1); } catch (final SQLException e) { } verify(rs, times(1)).getBytes(1); } @Test public void testGetBytesString() throws Exception { try { delegate.getBytes("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getBytes("foo"); } @Test public void testGetByteString() throws Exception { try { delegate.getByte("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getByte("foo"); } @Test public void testGetCharacterStreamInteger() throws Exception { try { delegate.getCharacterStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getCharacterStream(1); } @Test public void testGetCharacterStreamString() throws Exception { try { delegate.getCharacterStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getCharacterStream("foo"); } @Test public void testGetClobInteger() throws Exception { try { delegate.getClob(1); } catch (final SQLException e) { } verify(rs, times(1)).getClob(1); } @Test public void testGetClobString() throws Exception { try { delegate.getClob("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getClob("foo"); } @Test public void testGetConcurrency() throws Exception { try { delegate.getConcurrency(); } catch (final SQLException e) { } verify(rs, times(1)).getConcurrency(); } @Test public void testGetCursorName() throws Exception { try { delegate.getCursorName(); } catch (final SQLException e) { } verify(rs, times(1)).getCursorName(); } @Test public void testGetDateInteger() throws Exception { try { delegate.getDate(1); } catch (final SQLException e) { } verify(rs, times(1)).getDate(1); } @Test public void testGetDateIntegerCalendar() throws Exception { try { delegate.getDate(1, (java.util.Calendar) null); } catch (final SQLException e) { } verify(rs, times(1)).getDate(1, (java.util.Calendar) null); } @Test public void testGetDateString() throws Exception { try { delegate.getDate("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getDate("foo"); } @Test public void testGetDateStringCalendar() throws Exception { try { delegate.getDate("foo", (java.util.Calendar) null); } catch (final SQLException e) { } verify(rs, times(1)).getDate("foo", (java.util.Calendar) null); } @Test public void testGetDoubleInteger() throws Exception { try { delegate.getDouble(1); } catch (final SQLException e) { } verify(rs, times(1)).getDouble(1); } @Test public void testGetDoubleString() throws Exception { try { delegate.getDouble("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getDouble("foo"); } @Test public void testGetFetchDirection() throws Exception { try { delegate.getFetchDirection(); } catch (final SQLException e) { } verify(rs, times(1)).getFetchDirection(); } @Test public void testGetFetchSize() throws Exception { try { delegate.getFetchSize(); } catch (final SQLException e) { } verify(rs, times(1)).getFetchSize(); } @Test public void testGetFloatInteger() throws Exception { try { delegate.getFloat(1); } catch (final SQLException e) { } verify(rs, times(1)).getFloat(1); } @Test public void testGetFloatString() throws Exception { try { delegate.getFloat("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getFloat("foo"); } @Test public void testGetHoldability() throws Exception { try { delegate.getHoldability(); } catch (final SQLException e) { } verify(rs, times(1)).getHoldability(); } @Test public void testGetIntInteger() throws Exception { try { delegate.getInt(1); } catch (final SQLException e) { } verify(rs, times(1)).getInt(1); } @Test public void testGetIntString() throws Exception { try { delegate.getInt("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getInt("foo"); } @Test public void testGetLongInteger() throws Exception { try { delegate.getLong(1); } catch (final SQLException e) { } verify(rs, times(1)).getLong(1); } @Test public void testGetLongString() throws Exception { try { delegate.getLong("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getLong("foo"); } @Test public void testGetMetaData() throws Exception { try { delegate.getMetaData(); } catch (final SQLException e) { } verify(rs, times(1)).getMetaData(); } @Test public void testGetNCharacterStreamInteger() throws Exception { try { delegate.getNCharacterStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getNCharacterStream(1); } @Test public void testGetNCharacterStreamString() throws Exception { try { delegate.getNCharacterStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getNCharacterStream("foo"); } @Test public void testGetNClobInteger() throws Exception { try { delegate.getNClob(1); } catch (final SQLException e) { } verify(rs, times(1)).getNClob(1); } @Test public void testGetNClobString() throws Exception { try { delegate.getNClob("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getNClob("foo"); } @Test public void testGetNStringInteger() throws Exception { try { delegate.getNString(1); } catch (final SQLException e) { } verify(rs, times(1)).getNString(1); } @Test public void testGetNStringString() throws Exception { try { delegate.getNString("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getNString("foo"); } @Test public void testGetObjectInteger() throws Exception { try { delegate.getObject(1); } catch (final SQLException e) { } verify(rs, times(1)).getObject(1); } @Test public void testGetObjectIntegerClass() throws Exception { try { delegate.getObject(1, Object.class); } catch (final SQLException e) { } verify(rs, times(1)).getObject(1, Object.class); } @Test public void testGetObjectIntegerMap() throws Exception { try { delegate.getObject(1, (java.util.Map) null); } catch (final SQLException e) { } verify(rs, times(1)).getObject(1, (java.util.Map) null); } @Test public void testGetObjectString() throws Exception { try { delegate.getObject("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getObject("foo"); } @Test public void testGetObjectStringClass() throws Exception { try { delegate.getObject("foo", Object.class); } catch (final SQLException e) { } verify(rs, times(1)).getObject("foo", Object.class); } @Test public void testGetObjectStringMap() throws Exception { try { delegate.getObject("foo", (java.util.Map) null); } catch (final SQLException e) { } verify(rs, times(1)).getObject("foo", (java.util.Map) null); } @Test public void testGetRefInteger() throws Exception { try { delegate.getRef(1); } catch (final SQLException e) { } verify(rs, times(1)).getRef(1); } @Test public void testGetRefString() throws Exception { try { delegate.getRef("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getRef("foo"); } @Test public void testGetRow() throws Exception { try { delegate.getRow(); } catch (final SQLException e) { } verify(rs, times(1)).getRow(); } @Test public void testGetRowIdInteger() throws Exception { try { delegate.getRowId(1); } catch (final SQLException e) { } verify(rs, times(1)).getRowId(1); } @Test public void testGetRowIdString() throws Exception { try { delegate.getRowId("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getRowId("foo"); } @Test public void testGetShortInteger() throws Exception { try { delegate.getShort(1); } catch (final SQLException e) { } verify(rs, times(1)).getShort(1); } @Test public void testGetShortString() throws Exception { try { delegate.getShort("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getShort("foo"); } @Test public void testGetSQLXMLInteger() throws Exception { try { delegate.getSQLXML(1); } catch (final SQLException e) { } verify(rs, times(1)).getSQLXML(1); } @Test public void testGetSQLXMLString() throws Exception { try { delegate.getSQLXML("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getSQLXML("foo"); } /** * This method is a bit special. It actually calls statement in the * {@link DelegatingResultSet} object itself, instead of calling in the * underlying {@link ResultSet}. * * @throws Exception */ @Test public void testGetStatement() throws Exception { try { delegate.getStatement(); } catch (final SQLException e) { } verify(rs, times(0)).getStatement(); } @Test public void testGetStringInteger() throws Exception { try { delegate.getString(1); } catch (final SQLException e) { } verify(rs, times(1)).getString(1); } @Test public void testGetStringString() throws Exception { try { delegate.getString("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getString("foo"); } @Test public void testGetTimeInteger() throws Exception { try { delegate.getTime(1); } catch (final SQLException e) { } verify(rs, times(1)).getTime(1); } @Test public void testGetTimeIntegerCalendar() throws Exception { try { delegate.getTime(1, (java.util.Calendar) null); } catch (final SQLException e) { } verify(rs, times(1)).getTime(1, (java.util.Calendar) null); } @Test public void testGetTimestampInteger() throws Exception { try { delegate.getTimestamp(1); } catch (final SQLException e) { } verify(rs, times(1)).getTimestamp(1); } @Test public void testGetTimestampIntegerCalendar() throws Exception { try { delegate.getTimestamp(1, (java.util.Calendar) null); } catch (final SQLException e) { } verify(rs, times(1)).getTimestamp(1, (java.util.Calendar) null); } @Test public void testGetTimestampString() throws Exception { try { delegate.getTimestamp("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getTimestamp("foo"); } @Test public void testGetTimestampStringCalendar() throws Exception { try { delegate.getTimestamp("foo", (java.util.Calendar) null); } catch (final SQLException e) { } verify(rs, times(1)).getTimestamp("foo", (java.util.Calendar) null); } @Test public void testGetTimeString() throws Exception { try { delegate.getTime("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getTime("foo"); } @Test public void testGetTimeStringCalendar() throws Exception { try { delegate.getTime("foo", (java.util.Calendar) null); } catch (final SQLException e) { } verify(rs, times(1)).getTime("foo", (java.util.Calendar) null); } @Test public void testGetType() throws Exception { try { delegate.getType(); } catch (final SQLException e) { } verify(rs, times(1)).getType(); } @Test public void testGetUnicodeStreamInteger() throws Exception { try { delegate.getUnicodeStream(1); } catch (final SQLException e) { } verify(rs, times(1)).getUnicodeStream(1); } @Test public void testGetUnicodeStreamString() throws Exception { try { delegate.getUnicodeStream("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getUnicodeStream("foo"); } @Test public void testGetURLInteger() throws Exception { try { delegate.getURL(1); } catch (final SQLException e) { } verify(rs, times(1)).getURL(1); } @Test public void testGetURLString() throws Exception { try { delegate.getURL("foo"); } catch (final SQLException e) { } verify(rs, times(1)).getURL("foo"); } @Test public void testGetWarnings() throws Exception { try { delegate.getWarnings(); } catch (final SQLException e) { } verify(rs, times(1)).getWarnings(); } @Test public void testInsertRow() throws Exception { try { delegate.insertRow(); } catch (final SQLException e) { } verify(rs, times(1)).insertRow(); } @Test public void testIsAfterLast() throws Exception { try { delegate.isAfterLast(); } catch (final SQLException e) { } verify(rs, times(1)).isAfterLast(); } @Test public void testIsBeforeFirst() throws Exception { try { delegate.isBeforeFirst(); } catch (final SQLException e) { } verify(rs, times(1)).isBeforeFirst(); } @Test public void testIsClosed() throws Exception { try { delegate.isClosed(); } catch (final SQLException e) { } verify(rs, times(1)).isClosed(); } @Test public void testIsFirst() throws Exception { try { delegate.isFirst(); } catch (final SQLException e) { } verify(rs, times(1)).isFirst(); } @Test public void testIsLast() throws Exception { try { delegate.isLast(); } catch (final SQLException e) { } verify(rs, times(1)).isLast(); } @Test public void testLast() throws Exception { try { delegate.last(); } catch (final SQLException e) { } verify(rs, times(1)).last(); } @Test public void testMoveToCurrentRow() throws Exception { try { delegate.moveToCurrentRow(); } catch (final SQLException e) { } verify(rs, times(1)).moveToCurrentRow(); } @Test public void testMoveToInsertRow() throws Exception { try { delegate.moveToInsertRow(); } catch (final SQLException e) { } verify(rs, times(1)).moveToInsertRow(); } @Test public void testNext() throws Exception { try { delegate.next(); } catch (final SQLException e) { } verify(rs, times(1)).next(); } @Test public void testPrevious() throws Exception { try { delegate.previous(); } catch (final SQLException e) { } verify(rs, times(1)).previous(); } @Test public void testRefreshRow() throws Exception { try { delegate.refreshRow(); } catch (final SQLException e) { } verify(rs, times(1)).refreshRow(); } @Test public void testRelativeInteger() throws Exception { try { delegate.relative(1); } catch (final SQLException e) { } verify(rs, times(1)).relative(1); } @Test public void testRowDeleted() throws Exception { try { delegate.rowDeleted(); } catch (final SQLException e) { } verify(rs, times(1)).rowDeleted(); } @Test public void testRowInserted() throws Exception { try { delegate.rowInserted(); } catch (final SQLException e) { } verify(rs, times(1)).rowInserted(); } @Test public void testRowUpdated() throws Exception { try { delegate.rowUpdated(); } catch (final SQLException e) { } verify(rs, times(1)).rowUpdated(); } @Test public void testSetFetchDirectionInteger() throws Exception { try { delegate.setFetchDirection(1); } catch (final SQLException e) { } verify(rs, times(1)).setFetchDirection(1); } @Test public void testSetFetchSizeInteger() throws Exception { try { delegate.setFetchSize(1); } catch (final SQLException e) { } verify(rs, times(1)).setFetchSize(1); } @Test public void testToString() { final String toString = delegate.toString(); assertTrue(toString.contains("DelegatingResultSet")); assertTrue(toString.contains("Mock for ResultSet")); } @Test public void testUpdateArrayIntegerArray() throws Exception { try { delegate.updateArray(1, (java.sql.Array) null); } catch (final SQLException e) { } verify(rs, times(1)).updateArray(1, (java.sql.Array) null); } @Test public void testUpdateArrayStringArray() throws Exception { try { delegate.updateArray("foo", (java.sql.Array) null); } catch (final SQLException e) { } verify(rs, times(1)).updateArray("foo", (java.sql.Array) null); } @Test public void testUpdateAsciiStreamIntegerInputStream() throws Exception { try { delegate.updateAsciiStream(1, (java.io.InputStream) null); } catch (final SQLException e) { } verify(rs, times(1)).updateAsciiStream(1, (java.io.InputStream) null); } @Test public void testUpdateAsciiStreamIntegerInputStreamInteger() throws Exception { try { delegate.updateAsciiStream(1, (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateAsciiStream(1, (java.io.InputStream) null, 1); } @Test public void testUpdateAsciiStreamIntegerInputStreamLong() throws Exception { try { delegate.updateAsciiStream(1, (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateAsciiStream(1, (java.io.InputStream) null, 1L); } @Test public void testUpdateAsciiStreamStringInputStream() throws Exception { try { delegate.updateAsciiStream("foo", (java.io.InputStream) null); } catch (final SQLException e) { } verify(rs, times(1)).updateAsciiStream("foo", (java.io.InputStream) null); } @Test public void testUpdateAsciiStreamStringInputStreamInteger() throws Exception { try { delegate.updateAsciiStream("foo", (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateAsciiStream("foo", (java.io.InputStream) null, 1); } @Test public void testUpdateAsciiStreamStringInputStreamLong() throws Exception { try { delegate.updateAsciiStream("foo", (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateAsciiStream("foo", (java.io.InputStream) null, 1L); } @Test public void testUpdateBigDecimalIntegerBigDecimal() throws Exception { try { delegate.updateBigDecimal(1, java.math.BigDecimal.valueOf(1.0d)); } catch (final SQLException e) { } verify(rs, times(1)).updateBigDecimal(1, java.math.BigDecimal.valueOf(1.0d)); } @Test public void testUpdateBigDecimalStringBigDecimal() throws Exception { try { delegate.updateBigDecimal("foo", java.math.BigDecimal.valueOf(1.0d)); } catch (final SQLException e) { } verify(rs, times(1)).updateBigDecimal("foo", java.math.BigDecimal.valueOf(1.0d)); } @Test public void testUpdateBinaryStreamIntegerInputStream() throws Exception { try { delegate.updateBinaryStream(1, (java.io.InputStream) null); } catch (final SQLException e) { } verify(rs, times(1)).updateBinaryStream(1, (java.io.InputStream) null); } @Test public void testUpdateBinaryStreamIntegerInputStreamInteger() throws Exception { try { delegate.updateBinaryStream(1, (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateBinaryStream(1, (java.io.InputStream) null, 1); } @Test public void testUpdateBinaryStreamIntegerInputStreamLong() throws Exception { try { delegate.updateBinaryStream(1, (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateBinaryStream(1, (java.io.InputStream) null, 1L); } @Test public void testUpdateBinaryStreamStringInputStream() throws Exception { try { delegate.updateBinaryStream("foo", (java.io.InputStream) null); } catch (final SQLException e) { } verify(rs, times(1)).updateBinaryStream("foo", (java.io.InputStream) null); } @Test public void testUpdateBinaryStreamStringInputStreamInteger() throws Exception { try { delegate.updateBinaryStream("foo", (java.io.InputStream) null, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateBinaryStream("foo", (java.io.InputStream) null, 1); } @Test public void testUpdateBinaryStreamStringInputStreamLong() throws Exception { try { delegate.updateBinaryStream("foo", (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateBinaryStream("foo", (java.io.InputStream) null, 1L); } @Test public void testUpdateBlobIntegerBlob() throws Exception { try { delegate.updateBlob(1, (java.sql.Blob) null); } catch (final SQLException e) { } verify(rs, times(1)).updateBlob(1, (java.sql.Blob) null); } @Test public void testUpdateBlobIntegerInputStream() throws Exception { try { delegate.updateBlob(1, (java.io.InputStream) null); } catch (final SQLException e) { } verify(rs, times(1)).updateBlob(1, (java.io.InputStream) null); } @Test public void testUpdateBlobIntegerInputStreamLong() throws Exception { try { delegate.updateBlob(1, (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateBlob(1, (java.io.InputStream) null, 1L); } @Test public void testUpdateBlobStringBlob() throws Exception { try { delegate.updateBlob("foo", (java.sql.Blob) null); } catch (final SQLException e) { } verify(rs, times(1)).updateBlob("foo", (java.sql.Blob) null); } @Test public void testUpdateBlobStringInputStream() throws Exception { try { delegate.updateBlob("foo", (java.io.InputStream) null); } catch (final SQLException e) { } verify(rs, times(1)).updateBlob("foo", (java.io.InputStream) null); } @Test public void testUpdateBlobStringInputStreamLong() throws Exception { try { delegate.updateBlob("foo", (java.io.InputStream) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateBlob("foo", (java.io.InputStream) null, 1L); } @Test public void testUpdateBooleanIntegerBoolean() throws Exception { try { delegate.updateBoolean(1, Boolean.TRUE); } catch (final SQLException e) { } verify(rs, times(1)).updateBoolean(1, Boolean.TRUE); } @Test public void testUpdateBooleanStringBoolean() throws Exception { try { delegate.updateBoolean("foo", Boolean.TRUE); } catch (final SQLException e) { } verify(rs, times(1)).updateBoolean("foo", Boolean.TRUE); } @Test public void testUpdateByteIntegerByte() throws Exception { try { delegate.updateByte(1, (byte) 1); } catch (final SQLException e) { } verify(rs, times(1)).updateByte(1, (byte) 1); } @Test public void testUpdateBytesIntegerByteArray() throws Exception { try { delegate.updateBytes(1, new byte[] { 1 }); } catch (final SQLException e) { } verify(rs, times(1)).updateBytes(1, new byte[] { 1 }); } @Test public void testUpdateBytesStringByteArray() throws Exception { try { delegate.updateBytes("foo", new byte[] { 1 }); } catch (final SQLException e) { } verify(rs, times(1)).updateBytes("foo", new byte[] { 1 }); } @Test public void testUpdateByteStringByte() throws Exception { try { delegate.updateByte("foo", (byte) 1); } catch (final SQLException e) { } verify(rs, times(1)).updateByte("foo", (byte) 1); } @Test public void testUpdateCharacterStreamIntegerReader() throws Exception { try { delegate.updateCharacterStream(1, (java.io.StringReader) null); } catch (final SQLException e) { } verify(rs, times(1)).updateCharacterStream(1, (java.io.StringReader) null); } @Test public void testUpdateCharacterStreamIntegerReaderInteger() throws Exception { try { delegate.updateCharacterStream(1, (java.io.StringReader) null, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateCharacterStream(1, (java.io.StringReader) null, 1); } @Test public void testUpdateCharacterStreamIntegerReaderLong() throws Exception { try { delegate.updateCharacterStream(1, (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateCharacterStream(1, (java.io.StringReader) null, 1L); } @Test public void testUpdateCharacterStreamStringReader() throws Exception { try { delegate.updateCharacterStream("foo", (java.io.StringReader) null); } catch (final SQLException e) { } verify(rs, times(1)).updateCharacterStream("foo", (java.io.StringReader) null); } @Test public void testUpdateCharacterStreamStringReaderInteger() throws Exception { try { delegate.updateCharacterStream("foo", (java.io.StringReader) null, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateCharacterStream("foo", (java.io.StringReader) null, 1); } @Test public void testUpdateCharacterStreamStringReaderLong() throws Exception { try { delegate.updateCharacterStream("foo", (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateCharacterStream("foo", (java.io.StringReader) null, 1L); } @Test public void testUpdateClobIntegerClob() throws Exception { try { delegate.updateClob(1, (java.sql.Clob) null); } catch (final SQLException e) { } verify(rs, times(1)).updateClob(1, (java.sql.Clob) null); } @Test public void testUpdateClobIntegerReader() throws Exception { try { delegate.updateClob(1, (java.io.StringReader) null); } catch (final SQLException e) { } verify(rs, times(1)).updateClob(1, (java.io.StringReader) null); } @Test public void testUpdateClobIntegerReaderLong() throws Exception { try { delegate.updateClob(1, (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateClob(1, (java.io.StringReader) null, 1L); } @Test public void testUpdateClobStringClob() throws Exception { try { delegate.updateClob("foo", (java.sql.Clob) null); } catch (final SQLException e) { } verify(rs, times(1)).updateClob("foo", (java.sql.Clob) null); } @Test public void testUpdateClobStringReader() throws Exception { try { delegate.updateClob("foo", (java.io.StringReader) null); } catch (final SQLException e) { } verify(rs, times(1)).updateClob("foo", (java.io.StringReader) null); } @Test public void testUpdateClobStringReaderLong() throws Exception { try { delegate.updateClob("foo", (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateClob("foo", (java.io.StringReader) null, 1L); } @Test public void testUpdateDateIntegerSqlDate() throws Exception { try { delegate.updateDate(1, new java.sql.Date(1529827548745L)); } catch (final SQLException e) { } verify(rs, times(1)).updateDate(1, new java.sql.Date(1529827548745L)); } @Test public void testUpdateDateStringSqlDate() throws Exception { try { delegate.updateDate("foo", new java.sql.Date(1529827548745L)); } catch (final SQLException e) { } verify(rs, times(1)).updateDate("foo", new java.sql.Date(1529827548745L)); } @Test public void testUpdateDoubleIntegerDouble() throws Exception { try { delegate.updateDouble(1, 1.0d); } catch (final SQLException e) { } verify(rs, times(1)).updateDouble(1, 1.0d); } @Test public void testUpdateDoubleStringDouble() throws Exception { try { delegate.updateDouble("foo", 1.0d); } catch (final SQLException e) { } verify(rs, times(1)).updateDouble("foo", 1.0d); } @Test public void testUpdateFloatIntegerFloat() throws Exception { try { delegate.updateFloat(1, 1.0f); } catch (final SQLException e) { } verify(rs, times(1)).updateFloat(1, 1.0f); } @Test public void testUpdateFloatStringFloat() throws Exception { try { delegate.updateFloat("foo", 1.0f); } catch (final SQLException e) { } verify(rs, times(1)).updateFloat("foo", 1.0f); } @Test public void testUpdateIntIntegerInteger() throws Exception { try { delegate.updateInt(1, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateInt(1, 1); } @Test public void testUpdateIntStringInteger() throws Exception { try { delegate.updateInt("foo", 1); } catch (final SQLException e) { } verify(rs, times(1)).updateInt("foo", 1); } @Test public void testUpdateLongIntegerLong() throws Exception { try { delegate.updateLong(1, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateLong(1, 1L); } @Test public void testUpdateLongStringLong() throws Exception { try { delegate.updateLong("foo", 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateLong("foo", 1L); } @Test public void testUpdateNCharacterStreamIntegerReader() throws Exception { try { delegate.updateNCharacterStream(1, (java.io.StringReader) null); } catch (final SQLException e) { } verify(rs, times(1)).updateNCharacterStream(1, (java.io.StringReader) null); } @Test public void testUpdateNCharacterStreamIntegerReaderLong() throws Exception { try { delegate.updateNCharacterStream(1, (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateNCharacterStream(1, (java.io.StringReader) null, 1L); } @Test public void testUpdateNCharacterStreamStringReader() throws Exception { try { delegate.updateNCharacterStream("foo", (java.io.StringReader) null); } catch (final SQLException e) { } verify(rs, times(1)).updateNCharacterStream("foo", (java.io.StringReader) null); } @Test public void testUpdateNCharacterStreamStringReaderLong() throws Exception { try { delegate.updateNCharacterStream("foo", (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateNCharacterStream("foo", (java.io.StringReader) null, 1L); } @Test public void testUpdateNClobIntegerNClob() throws Exception { try { delegate.updateNClob(1, (java.sql.NClob) null); } catch (final SQLException e) { } verify(rs, times(1)).updateNClob(1, (java.sql.NClob) null); } @Test public void testUpdateNClobIntegerReader() throws Exception { try { delegate.updateNClob(1, (java.io.StringReader) null); } catch (final SQLException e) { } verify(rs, times(1)).updateNClob(1, (java.io.StringReader) null); } @Test public void testUpdateNClobIntegerReaderLong() throws Exception { try { delegate.updateNClob(1, (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateNClob(1, (java.io.StringReader) null, 1L); } @Test public void testUpdateNClobStringNClob() throws Exception { try { delegate.updateNClob("foo", (java.sql.NClob) null); } catch (final SQLException e) { } verify(rs, times(1)).updateNClob("foo", (java.sql.NClob) null); } @Test public void testUpdateNClobStringReader() throws Exception { try { delegate.updateNClob("foo", (java.io.StringReader) null); } catch (final SQLException e) { } verify(rs, times(1)).updateNClob("foo", (java.io.StringReader) null); } @Test public void testUpdateNClobStringReaderLong() throws Exception { try { delegate.updateNClob("foo", (java.io.StringReader) null, 1L); } catch (final SQLException e) { } verify(rs, times(1)).updateNClob("foo", (java.io.StringReader) null, 1L); } @Test public void testUpdateNStringIntegerString() throws Exception { try { delegate.updateNString(1, "foo"); } catch (final SQLException e) { } verify(rs, times(1)).updateNString(1, "foo"); } @Test public void testUpdateNStringStringString() throws Exception { try { delegate.updateNString("foo", "foo"); } catch (final SQLException e) { } verify(rs, times(1)).updateNString("foo", "foo"); } @Test public void testUpdateNullInteger() throws Exception { try { delegate.updateNull(1); } catch (final SQLException e) { } verify(rs, times(1)).updateNull(1); } @Test public void testUpdateNullString() throws Exception { try { delegate.updateNull("foo"); } catch (final SQLException e) { } verify(rs, times(1)).updateNull("foo"); } @Test public void testUpdateObjectIntegerObject() throws Exception { try { delegate.updateObject(1, System.err); } catch (final SQLException e) { } verify(rs, times(1)).updateObject(1, System.err); } // FIXME: this appears to be a bug @Disabled @Test public void testUpdateObjectIntegerObjectInteger() throws Exception { try { delegate.updateObject(1, System.err, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateObject(1, System.err, 1); } @Test public void testUpdateObjectIntegerObjectSQLType() throws Exception { try { delegate.updateObject(1, System.err, (java.sql.SQLType) null); } catch (final SQLException e) { } verify(rs, times(1)).updateObject(1, System.err, (java.sql.SQLType) null); } @Test public void testUpdateObjectIntegerObjectSQLTypeInteger() throws Exception { try { delegate.updateObject(1, System.err, (java.sql.SQLType) null, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateObject(1, System.err, (java.sql.SQLType) null, 1); } @Test public void testUpdateObjectStringObject() throws Exception { try { delegate.updateObject("foo", System.err); } catch (final SQLException e) { } verify(rs, times(1)).updateObject("foo", System.err); } // FIXME this appears to be a bug @Disabled @Test public void testUpdateObjectStringObjectInteger() throws Exception { try { delegate.updateObject("foo", System.err, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateObject("foo", System.err, 1); } @Test public void testUpdateObjectStringObjectSQLType() throws Exception { try { delegate.updateObject("foo", System.err, (java.sql.SQLType) null); } catch (final SQLException e) { } verify(rs, times(1)).updateObject("foo", System.err, (java.sql.SQLType) null); } @Test public void testUpdateObjectStringObjectSQLTypeInteger() throws Exception { try { delegate.updateObject("foo", System.err, (java.sql.SQLType) null, 1); } catch (final SQLException e) { } verify(rs, times(1)).updateObject("foo", System.err, (java.sql.SQLType) null, 1); } @Test public void testUpdateRefIntegerRef() throws Exception { try { delegate.updateRef(1, (java.sql.Ref) null); } catch (final SQLException e) { } verify(rs, times(1)).updateRef(1, (java.sql.Ref) null); } @Test public void testUpdateRefStringRef() throws Exception { try { delegate.updateRef("foo", (java.sql.Ref) null); } catch (final SQLException e) { } verify(rs, times(1)).updateRef("foo", (java.sql.Ref) null); } @Test public void testUpdateRow() throws Exception { try { delegate.updateRow(); } catch (final SQLException e) { } verify(rs, times(1)).updateRow(); } @Test public void testUpdateRowIdIntegerRowId() throws Exception { try { delegate.updateRowId(1, (java.sql.RowId) null); } catch (final SQLException e) { } verify(rs, times(1)).updateRowId(1, (java.sql.RowId) null); } @Test public void testUpdateRowIdStringRowId() throws Exception { try { delegate.updateRowId("foo", (java.sql.RowId) null); } catch (final SQLException e) { } verify(rs, times(1)).updateRowId("foo", (java.sql.RowId) null); } @Test public void testUpdateShortIntegerShort() throws Exception { try { delegate.updateShort(1, (short) 1); } catch (final SQLException e) { } verify(rs, times(1)).updateShort(1, (short) 1); } @Test public void testUpdateShortStringShort() throws Exception { try { delegate.updateShort("foo", (short) 1); } catch (final SQLException e) { } verify(rs, times(1)).updateShort("foo", (short) 1); } @Test public void testUpdateSQLXMLIntegerSQLXML() throws Exception { try { delegate.updateSQLXML(1, (java.sql.SQLXML) null); } catch (final SQLException e) { } verify(rs, times(1)).updateSQLXML(1, (java.sql.SQLXML) null); } @Test public void testUpdateSQLXMLStringSQLXML() throws Exception { try { delegate.updateSQLXML("foo", (java.sql.SQLXML) null); } catch (final SQLException e) { } verify(rs, times(1)).updateSQLXML("foo", (java.sql.SQLXML) null); } @Test public void testUpdateStringIntegerString() throws Exception { try { delegate.updateString(1, "foo"); } catch (final SQLException e) { } verify(rs, times(1)).updateString(1, "foo"); } @Test public void testUpdateStringStringString() throws Exception { try { delegate.updateString("foo", "foo"); } catch (final SQLException e) { } verify(rs, times(1)).updateString("foo", "foo"); } @Test public void testUpdateTimeIntegerTime() throws Exception { try { delegate.updateTime(1, (java.sql.Time) null); } catch (final SQLException e) { } verify(rs, times(1)).updateTime(1, (java.sql.Time) null); } @Test public void testUpdateTimestampIntegerTimestamp() throws Exception { try { delegate.updateTimestamp(1, (java.sql.Timestamp) null); } catch (final SQLException e) { } verify(rs, times(1)).updateTimestamp(1, (java.sql.Timestamp) null); } @Test public void testUpdateTimestampStringTimestamp() throws Exception { try { delegate.updateTimestamp("foo", (java.sql.Timestamp) null); } catch (final SQLException e) { } verify(rs, times(1)).updateTimestamp("foo", (java.sql.Timestamp) null); } @Test public void testUpdateTimeStringTime() throws Exception { try { delegate.updateTime("foo", (java.sql.Time) null); } catch (final SQLException e) { } verify(rs, times(1)).updateTime("foo", (java.sql.Time) null); } @Test public void testWasNull() throws Exception { try { delegate.wasNull(); } catch (final SQLException e) { } verify(rs, times(1)).wasNull(); } @Test public void testWrap() throws SQLException { final DelegatingResultSet delegate = (DelegatingResultSet) DelegatingResultSet.wrapResultSet(conn, rs); assertEquals(delegate, delegate.unwrap(ResultSet.class)); assertEquals(delegate, delegate.unwrap(DelegatingResultSet.class)); assertEquals(rs, delegate.unwrap(rs.getClass())); assertNull(delegate.unwrap(String.class)); assertTrue(delegate.isWrapperFor(ResultSet.class)); assertTrue(delegate.isWrapperFor(DelegatingResultSet.class)); assertTrue(delegate.isWrapperFor(rs.getClass())); assertFalse(delegate.isWrapperFor(String.class)); } } TestDelegatingStatement.java000066400000000000000000000454701472045345700340620ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class TestDelegatingStatement { private static final class TesterStatementNonWrapping extends TesterStatement { public TesterStatementNonWrapping(final Connection conn) { super(conn); } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } } private DelegatingConnection delegatingConnection; private TesterConnection testerConnection; private Statement mockedStatement; private DelegatingStatement delegatingStatement; private DelegatingStatement delegatingTesterStatement; private TesterResultSet testerResultSet; private TesterStatement testerStatement; @BeforeEach public void setUp() throws Exception { testerConnection = new TesterConnection("test", "test"); delegatingConnection = new DelegatingConnection<>(testerConnection); mockedStatement = mock(Statement.class); testerStatement = new TesterStatement(testerConnection); delegatingStatement = new DelegatingStatement(delegatingConnection, mockedStatement); delegatingTesterStatement = new DelegatingStatement(delegatingConnection, testerStatement); testerResultSet = new TesterResultSet(mockedStatement); } @Test public void testAddBatchString() throws Exception { try { delegatingStatement.addBatch("foo"); } catch (final SQLException e) { } verify(mockedStatement, times(1)).addBatch("foo"); } @Test public void testCancel() throws Exception { try { delegatingStatement.cancel(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).cancel(); } @Test public void testCheckOpen() throws Exception { delegatingStatement.checkOpen(); delegatingStatement.close(); try { delegatingStatement.checkOpen(); fail("Expecting SQLException"); } catch (final SQLException ex) { // expected } } @Test public void testClearBatch() throws Exception { try { delegatingStatement.clearBatch(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).clearBatch(); } @Test public void testClearWarnings() throws Exception { try { delegatingStatement.clearWarnings(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).clearWarnings(); } @Test public void testClose() throws Exception { try { delegatingStatement.close(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).close(); } @Test public void testCloseOnCompletion() throws Exception { try { delegatingStatement.closeOnCompletion(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).closeOnCompletion(); } @Test public void testCloseWithResultSetCloseException() throws Exception { try { testerResultSet.setSqlExceptionOnClose(true); delegatingStatement.addTrace(testerResultSet); delegatingStatement.close(); Assertions.fail("Excpected a SQLExceptionList"); } catch (final SQLException e) { Assertions.assertInstanceOf(SQLExceptionList.class, e); } finally { testerResultSet.setSqlExceptionOnClose(false); } verify(mockedStatement, times(1)).close(); } @Test public void testCloseWithStatementCloseException() throws Exception { try { testerStatement.setSqlExceptionOnClose(true); delegatingTesterStatement.close(); Assertions.fail("Excpected a SQLExceptionList"); } catch (final SQLException e) { Assertions.assertInstanceOf(SQLExceptionList.class, e); } finally { testerStatement.setSqlExceptionOnClose(false); } } @Test public void testExecuteBatch() throws Exception { try { delegatingStatement.executeBatch(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeBatch(); } @Test public void testExecuteLargeBatch() throws Exception { try { delegatingStatement.executeLargeBatch(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeLargeBatch(); } @Test public void testExecuteLargeUpdateString() throws Exception { try { delegatingStatement.executeLargeUpdate("foo"); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeLargeUpdate("foo"); } @Test public void testExecuteLargeUpdateStringInteger() throws Exception { try { delegatingStatement.executeLargeUpdate("foo", 1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeLargeUpdate("foo", 1); } @Test public void testExecuteLargeUpdateStringIntegerArray() throws Exception { try { delegatingStatement.executeLargeUpdate("foo", (int[]) null); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeLargeUpdate("foo", (int[]) null); } @Test public void testExecuteLargeUpdateStringStringArray() throws Exception { try { delegatingStatement.executeLargeUpdate("foo", (String[]) null); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeLargeUpdate("foo", (String[]) null); } @Test public void testExecuteQueryReturnsNull() throws Exception { assertNull(delegatingStatement.executeQuery("null")); } @Test public void testExecuteQueryString() throws Exception { try { delegatingStatement.executeQuery("foo"); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeQuery("foo"); } @Test public void testExecuteString() throws Exception { try { delegatingStatement.execute("foo"); } catch (final SQLException e) { } verify(mockedStatement, times(1)).execute("foo"); } @Test public void testExecuteStringInteger() throws Exception { try { delegatingStatement.execute("foo", 1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).execute("foo", 1); } @Test public void testExecuteStringIntegerArray() throws Exception { try { delegatingStatement.execute("foo", (int[]) null); } catch (final SQLException e) { } verify(mockedStatement, times(1)).execute("foo", (int[]) null); } @Test public void testExecuteStringStringArray() throws Exception { try { delegatingStatement.execute("foo", (String[]) null); } catch (final SQLException e) { } verify(mockedStatement, times(1)).execute("foo", (String[]) null); } @Test public void testExecuteUpdateString() throws Exception { try { delegatingStatement.executeUpdate("foo"); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeUpdate("foo"); } @Test public void testExecuteUpdateStringInteger() throws Exception { try { delegatingStatement.executeUpdate("foo", 1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeUpdate("foo", 1); } @Test public void testExecuteUpdateStringIntegerArray() throws Exception { try { delegatingStatement.executeUpdate("foo", (int[]) null); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeUpdate("foo", (int[]) null); } @Test public void testExecuteUpdateStringStringArray() throws Exception { try { delegatingStatement.executeUpdate("foo", (String[]) null); } catch (final SQLException e) { } verify(mockedStatement, times(1)).executeUpdate("foo", (String[]) null); } /** * This method is a bit special, and return the delegate connection, not the * wrapped statement's connection. * * @throws Exception */ @Test public void testGetConnection() throws Exception { try { delegatingStatement.getConnection(); } catch (final SQLException e) { } verify(mockedStatement, times(0)).getConnection(); } @Test public void testGetDelegate() throws Exception { assertEquals(mockedStatement, delegatingStatement.getDelegate()); } @Test public void testGetFetchDirection() throws Exception { try { delegatingStatement.getFetchDirection(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getFetchDirection(); } @Test public void testGetFetchSize() throws Exception { try { delegatingStatement.getFetchSize(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getFetchSize(); } @Test public void testGetGeneratedKeys() throws Exception { try { delegatingStatement.getGeneratedKeys(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getGeneratedKeys(); } @Test public void testGetLargeMaxRows() throws Exception { try { delegatingStatement.getLargeMaxRows(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getLargeMaxRows(); } @Test public void testGetLargeUpdateCount() throws Exception { try { delegatingStatement.getLargeUpdateCount(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getLargeUpdateCount(); } @Test public void testGetMaxFieldSize() throws Exception { try { delegatingStatement.getMaxFieldSize(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getMaxFieldSize(); } @Test public void testGetMaxRows() throws Exception { try { delegatingStatement.getMaxRows(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getMaxRows(); } @Test public void testGetMoreResults() throws Exception { try { delegatingStatement.getMoreResults(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getMoreResults(); } @Test public void testGetMoreResultsInteger() throws Exception { try { delegatingStatement.getMoreResults(1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getMoreResults(1); } @Test public void testGetQueryTimeout() throws Exception { try { delegatingStatement.getQueryTimeout(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getQueryTimeout(); } @Test public void testGetResultSet() throws Exception { try { delegatingStatement.getResultSet(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getResultSet(); } @Test public void testGetResultSetConcurrency() throws Exception { try { delegatingStatement.getResultSetConcurrency(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getResultSetConcurrency(); } @Test public void testGetResultSetHoldability() throws Exception { try { delegatingStatement.getResultSetHoldability(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getResultSetHoldability(); } @Test public void testGetResultSetType() throws Exception { try { delegatingStatement.getResultSetType(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getResultSetType(); } @Test public void testGetUpdateCount() throws Exception { try { delegatingStatement.getUpdateCount(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getUpdateCount(); } @Test public void testGetWarnings() throws Exception { try { delegatingStatement.getWarnings(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).getWarnings(); } /** * This method is a bit special, and call isClosed in the delegate object * itself, not in the wrapped statement. * * @throws Exception */ @Test public void testIsClosed() throws Exception { try { delegatingStatement.isClosed(); } catch (final SQLException e) { } verify(mockedStatement, times(0)).isClosed(); } @Test public void testIsCloseOnCompletion() throws Exception { try { delegatingStatement.isCloseOnCompletion(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).isCloseOnCompletion(); } @Test public void testIsPoolable() throws Exception { try { delegatingStatement.isPoolable(); } catch (final SQLException e) { } verify(mockedStatement, times(1)).isPoolable(); } @Test public void testIsWrapperFor() throws Exception { final TesterConnection tstConn = new TesterConnection("test", "test"); final TesterStatement tstStmt = new TesterStatementNonWrapping(tstConn); final DelegatingConnection dconn = new DelegatingConnection<>(tstConn); final DelegatingStatement stamt = new DelegatingStatement(dconn, tstStmt); final Class stmtProxyClass = Proxy.getProxyClass( this.getClass().getClassLoader(), Statement.class); assertTrue(stamt.isWrapperFor(DelegatingStatement.class)); assertTrue(stamt.isWrapperFor(TesterStatement.class)); assertFalse(stamt.isWrapperFor(stmtProxyClass)); stamt.close(); } @Test public void testSetCursorNameString() throws Exception { try { delegatingStatement.setCursorName("foo"); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setCursorName("foo"); } @Test public void testSetEscapeProcessingBoolean() throws Exception { try { delegatingStatement.setEscapeProcessing(Boolean.TRUE); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setEscapeProcessing(Boolean.TRUE); } @Test public void testSetFetchDirectionInteger() throws Exception { try { delegatingStatement.setFetchDirection(1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setFetchDirection(1); } @Test public void testSetFetchSizeInteger() throws Exception { try { delegatingStatement.setFetchSize(1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setFetchSize(1); } @Test public void testSetLargeMaxRowsLong() throws Exception { try { delegatingStatement.setLargeMaxRows(1L); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setLargeMaxRows(1L); } @Test public void testSetMaxFieldSizeInteger() throws Exception { try { delegatingStatement.setMaxFieldSize(1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setMaxFieldSize(1); } @Test public void testSetMaxRowsInteger() throws Exception { try { delegatingStatement.setMaxRows(1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setMaxRows(1); } @Test public void testSetPoolableBoolean() throws Exception { try { delegatingStatement.setPoolable(Boolean.TRUE); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setPoolable(Boolean.TRUE); } @Test public void testSetQueryTimeoutInteger() throws Exception { try { delegatingStatement.setQueryTimeout(1); } catch (final SQLException e) { } verify(mockedStatement, times(1)).setQueryTimeout(1); } @Test public void testWrap() throws SQLException { assertEquals(delegatingStatement, delegatingStatement.unwrap(Statement.class)); assertEquals(delegatingStatement, delegatingStatement.unwrap(DelegatingStatement.class)); assertEquals(mockedStatement, delegatingStatement.unwrap(mockedStatement.getClass())); assertNull(delegatingStatement.unwrap(String.class)); assertTrue(delegatingStatement.isWrapperFor(Statement.class)); assertTrue(delegatingStatement.isWrapperFor(DelegatingStatement.class)); assertTrue(delegatingStatement.isWrapperFor(mockedStatement.getClass())); assertFalse(delegatingStatement.isWrapperFor(String.class)); } } TestDriverConnectionFactory.java000066400000000000000000000034571472045345700347340ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.Connection; import java.sql.SQLException; import org.junit.jupiter.api.Test; /** * Tests for DriverConnectionFactory. */ public class TestDriverConnectionFactory { @Test public void testCreateConnection() throws SQLException { final DriverConnectionFactory cf = new DriverConnectionFactory( new TesterDriver(), "jdbc:apache:commons:testdriver", null); final Connection conn = cf.createConnection(); assertEquals(0, conn.getMetaData().getDriverMajorVersion()); } @Test public void testDriverConnectionFactoryToString() { final DriverConnectionFactory cf = new DriverConnectionFactory( new TesterDriver(), "jdbc:apache:commons:testdriver", null); final String toString = cf.toString(); assertTrue(toString.contains("jdbc:apache:commons:testdriver")); } } TestDriverManagerConnectionFactory.java000066400000000000000000000150421472045345700362200ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.junit.jupiter.api.Test; /** * This test *must* execute before all other tests to be effective as it tests * the initialization of DriverManager. * Based on the test case for DBCP-212 written by Marcos Sanz */ public class TestDriverManagerConnectionFactory extends AbstractDriverTest { private static final class ConnectionThread implements Runnable { private final DataSource ds; private volatile boolean result = true; private ConnectionThread(final DataSource ds) { this.ds = ds; } public boolean getResult() { return result; } @Override public void run() { Connection conn = null; try { conn = ds.getConnection(); } catch (final Exception e) { e.printStackTrace(); result = false; } finally { if (conn != null) { try { conn.close(); } catch (final Exception e) { e.printStackTrace(); result = false; } } } } @Override public String toString() { return "ConnectionThread [ds=" + ds + ", result=" + result + "]"; } } @Test public void testDriverManagerCredentialsInUrl() throws SQLException { final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver;user=foo;password=bar", null, (char[]) null); cf.createConnection(); } public void testDriverManagerInit(final boolean withProperties) throws Exception { final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); config.setMaxTotal(10); config.setMaxIdle(0); final Properties properties = new Properties(); // The names "user" and "password" are specified in java.sql.DriverManager.getConnection(String, String, String) properties.setProperty(Constants.KEY_USER, "foo"); properties.setProperty(Constants.KEY_PASSWORD, "bar"); final ConnectionFactory connectionFactory = withProperties ? new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", properties) : new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "foo", "bar"); final PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null); poolableConnectionFactory.setDefaultReadOnly(Boolean.FALSE); poolableConnectionFactory.setDefaultAutoCommit(Boolean.TRUE); final GenericObjectPool connectionPool = new GenericObjectPool<>(poolableConnectionFactory, config); poolableConnectionFactory.setPool(connectionPool); final PoolingDataSource dataSource = new PoolingDataSource<>(connectionPool); final ConnectionThread[] connectionThreads = new ConnectionThread[10]; final Thread[] threads = new Thread[10]; for (int i = 0; i < 10; i++) { connectionThreads[i] = new ConnectionThread(dataSource); threads[i] = new Thread(connectionThreads[i]); } for (int i = 0; i < 10; i++) { threads[i].start(); } for (int i = 0; i < 10; i++) { while (threads[i].isAlive()){//JDK1.5: getState() != Thread.State.TERMINATED) { Thread.sleep(100); } if (!connectionThreads[i].getResult()) { fail("Exception during getConnection(): " + connectionThreads[i]); } } } @Test public void testDriverManagerInitWithCredentials() throws Exception { testDriverManagerInit(false); } @Test public void testDriverManagerInitWithEmptyProperties() throws Exception { final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( "jdbc:apache:commons:testdriver;user=foo;password=bar"); connectionFactory.createConnection(); } @Test public void testDriverManagerInitWithProperties() throws Exception { testDriverManagerInit(true); } @Test public void testDriverManagerWithoutCredentials() { final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", null, (char[]) null); assertThrows(ArrayIndexOutOfBoundsException.class, cf::createConnection); // thrown by TestDriver due to missing user } @Test public void testDriverManagerWithoutPassword() { final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "user", (char[]) null); assertThrows(SQLException.class, cf::createConnection); // thrown by TestDriver due to invalid password } @Test public void testDriverManagerWithoutUser() { final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", null, "pass"); assertThrows(IndexOutOfBoundsException.class, cf::createConnection); // thrown by TestDriver due to missing user } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestJndi.java000066400000000000000000000107661472045345700310750ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.fail; import java.util.Hashtable; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; import org.apache.commons.dbcp2.datasources.PerUserPoolDataSource; import org.apache.commons.dbcp2.datasources.SharedPoolDataSource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests JNID bind and lookup for DataSource implementations. * Demonstrates problem indicated in BZ #38073. */ public class TestJndi { /** * The subcontext where the data source is bound. */ protected static final String JNDI_SUBCONTEXT = "jdbc"; /** * the full JNDI path to the data source. */ protected static final String JNDI_PATH = JNDI_SUBCONTEXT + "/" + "jndiTestDataSource"; /** JNDI context to use in tests **/ protected Context context; /** * Binds a DataSource into JNDI. * * @throws Exception if creation or binding fails. */ protected void bindDataSource(final DataSource dataSource) throws Exception { context.bind(JNDI_PATH, dataSource); } /** * Binds a DataSource to the JNDI and checks that we have successfully * bound it by looking it up again. * * @throws Exception if the bind, lookup or connect fails */ protected void checkBind(final DataSource dataSource) throws Exception { bindDataSource(dataSource); retrieveDataSource(); } /** * Retrieves (or creates if it does not exist) an InitialContext. * * @return the InitialContext. * @throws NamingException if the InitialContext cannot be retrieved * or created. */ protected InitialContext getInitialContext() throws NamingException { final Hashtable environment = new Hashtable<>(); environment.put(Context.INITIAL_CONTEXT_FACTORY, org.apache.naming.java.javaURLContextFactory.class.getName()); return new InitialContext(environment); } /** * Retrieves a DataSource from JNDI. * * @throws Exception if the JNDI lookup fails or no DataSource is bound. */ protected DataSource retrieveDataSource() throws Exception { final Context ctx = getInitialContext(); final DataSource dataSource = (DataSource) ctx.lookup(JNDI_PATH); if (dataSource == null) { fail("DataSource should not be null"); } return dataSource; } @BeforeEach public void setUp() throws Exception { context = getInitialContext(); context.createSubcontext(JNDI_SUBCONTEXT); } @AfterEach public void tearDown() throws Exception { context.unbind(JNDI_PATH); context.destroySubcontext(JNDI_SUBCONTEXT); } /** * Test BasicDatasource bind and lookup * * @throws Exception */ @Test public void testBasicDataSourceBind() throws Exception { final BasicDataSource dataSource = new BasicDataSource(); checkBind(dataSource); } /** * Test PerUserPoolDataSource bind and lookup * * @throws Exception */ @Test public void testPerUserPoolDataSourceBind() throws Exception { final PerUserPoolDataSource dataSource = new PerUserPoolDataSource(); checkBind(dataSource); } /** * Test SharedPoolDataSource bind and lookup * * @throws Exception */ @Test public void testSharedPoolDataSourceBind() throws Exception { final SharedPoolDataSource dataSource = new SharedPoolDataSource(); checkBind(dataSource); } } TestLifetimeExceededException.java000066400000000000000000000027421472045345700351710ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import org.junit.jupiter.api.Test; /** * Tests for LifetimeExceededException. */ public class TestLifetimeExceededException { @Test public void testLifetimeExceededException() { final LifetimeExceededException exception = new LifetimeExceededException("car"); assertEquals("car", exception.getMessage()); } @Test public void testLifetimeExceededExceptionNoMessage() { final LifetimeExceededException exception = new LifetimeExceededException(); assertNull(exception.getMessage()); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestListException.java000066400000000000000000000033531472045345700327750ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.Test; /** * Tests for ListException. */ public class TestListException { @Test public void testExceptionList() { final List exceptions = Arrays.asList(new NullPointerException(), new RuntimeException()); final ListException list = new ListException("Internal Error", exceptions); assertEquals("Internal Error", list.getMessage()); assertArrayEquals(exceptions.toArray(), list.getExceptionList().toArray()); } @Test public void testNulls() { final ListException list = new ListException(null, null); assertNull(list.getMessage()); assertNull(list.getExceptionList()); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java000066400000000000000000000345751472045345700317350ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.ResultSet; import java.sql.Statement; import java.util.Arrays; import org.apache.commons.dbcp2.PoolingConnection.StatementType; import org.junit.jupiter.api.Test; /** * Tests {@link PStmtKey}. */ public class TestPStmtKey { /** * Tests constructors with different catalog. */ @Test public void testCtorDifferentCatalog() { assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog2", "schema1")); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog2", "schema1", 0)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog2", "schema1", 0, 0)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0)); // assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, StatementType.PREPARED_STATEMENT)); // assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog2", "schema1", (int[]) null)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog2", "schema1", new int[1])); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog2", "schema1", (String[]) null)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog2", "schema1", new String[] {"A" })); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", StatementType.PREPARED_STATEMENT)); assertNotEquals( new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE), new PStmtKey("sql", "catalog2", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE)); } /** * Tests constructors with different schemas. */ @Test public void testCtorDifferentSchema() { assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema2")); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog1", "schema2", 0)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog1", "schema2", 0, 0)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0)); // assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0, StatementType.CALLABLE_STATEMENT)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, StatementType.CALLABLE_STATEMENT)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, StatementType.PREPARED_STATEMENT)); // assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog1", "schema2", (int[]) null)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog1", "schema2", new int[1])); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog1", "schema2", (String[]) null)); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog1", "schema2", new String[] {"A" })); assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", StatementType.PREPARED_STATEMENT)); assertNotEquals( new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE), new PStmtKey("sql", "catalog1", "schema2", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE)); } /** * Tests constructors with different catalog. */ @Test public void testCtorEquals() { assertEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema1")); assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog1", "schema1", 0)); assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog1", "schema1", 0, 0)); assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0)); // assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.CALLABLE_STATEMENT)); assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.CALLABLE_STATEMENT)); assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT)); // assertEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog1", "schema1", (int[]) null)); assertEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog1", "schema1", new int[1])); assertEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog1", "schema1", (String[]) null)); assertEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" })); assertEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT)); assertEquals( new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE), new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE)); } /** * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String, int[])}. * * See https://issues.apache.org/jira/browse/DBCP-494 */ @Test public void testCtorStringStringArrayOfInts() { final int[] input = {0, 0}; final PStmtKey pStmtKey = new PStmtKey("", "", "", input); assertArrayEquals(input, pStmtKey.getColumnIndexes()); input[0] = 1; input[1] = 1; assertFalse(Arrays.equals(input, pStmtKey.getColumnIndexes())); } /** * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String, int[])}. * * See https://issues.apache.org/jira/browse/DBCP-494 */ @Test public void testCtorStringStringArrayOfNullInts() { final int[] input = null; final PStmtKey pStmtKey = new PStmtKey("", "", "", input); assertArrayEquals(input, pStmtKey.getColumnIndexes()); } /** * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String, String[])}. * * See https://issues.apache.org/jira/browse/DBCP-494 */ @Test public void testCtorStringStringArrayOfNullStrings() { final String[] input = null; final PStmtKey pStmtKey = new PStmtKey("", "", "", input); assertArrayEquals(input, pStmtKey.getColumnNames()); } /** * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String, String[])}. * * See https://issues.apache.org/jira/browse/DBCP-494 */ @Test public void testCtorStringStringArrayOfStrings() { final String[] input = {"A", "B"}; final PStmtKey pStmtKey = new PStmtKey("", "", "", input); assertArrayEquals(input, pStmtKey.getColumnNames()); input[0] = "C"; input[1] = "D"; assertFalse(Arrays.equals(input, pStmtKey.getColumnNames())); } @Test public void testEquals() { final PStmtKey pStmtKey = new PStmtKey("SELECT 1", "catalog", "public", java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT); assertEquals(pStmtKey, pStmtKey); assertNotEquals(null, pStmtKey); assertNotEquals(pStmtKey, new Object()); assertNotEquals(pStmtKey, new PStmtKey("SELECT 2", "catalog", "public", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT)); assertNotEquals(pStmtKey, new PStmtKey("SELECT 1", "anothercatalog", "public", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT)); assertNotEquals(pStmtKey, new PStmtKey("SELECT 1", "catalog", "private", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT)); assertNotEquals(pStmtKey, new PStmtKey("SELECT 1", "catalog", "public", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT)); assertNotEquals(pStmtKey, new PStmtKey("SELECT 1", "catalog", "public", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE, StatementType.CALLABLE_STATEMENT)); assertNotEquals(pStmtKey, new PStmtKey("SELECT 1", "catalog", "public", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, StatementType.PREPARED_STATEMENT)); assertEquals(pStmtKey, new PStmtKey("SELECT 1", "catalog", "public", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT)); assertEquals(pStmtKey.hashCode(), new PStmtKey("SELECT 1", "catalog", "public", java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY, StatementType.CALLABLE_STATEMENT).hashCode()); } @Test public void testGettersSetters() { final PStmtKey pStmtKey = new PStmtKey("SELECT 1", "catalog", "public"); assertEquals("SELECT 1", pStmtKey.getSql()); assertEquals("public", pStmtKey.getSchema()); assertEquals("catalog", pStmtKey.getCatalog()); assertNull(pStmtKey.getAutoGeneratedKeys()); assertNull(pStmtKey.getResultSetConcurrency()); assertNull(pStmtKey.getResultSetHoldability()); assertNull(pStmtKey.getResultSetType()); assertEquals(StatementType.PREPARED_STATEMENT, pStmtKey.getStmtType()); } @Test public void testToString() { final PStmtKey pStmtKey = new PStmtKey("SELECT 1", "catalog", "public", StatementType.CALLABLE_STATEMENT, Statement.RETURN_GENERATED_KEYS); assertTrue(pStmtKey.toString().contains("sql=SELECT 1")); assertTrue(pStmtKey.toString().contains("schema=public")); assertTrue(pStmtKey.toString().contains("autoGeneratedKeys=1")); assertTrue(pStmtKey.toString().contains("statementType=CALLABLE_STATEMENT")); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestPStmtPooling.java000066400000000000000000000230571472045345700326050ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import javax.management.ObjectName; import javax.sql.DataSource; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * TestSuite for BasicDataSource with prepared statement pooling enabled */ public class TestPStmtPooling { private DataSource createPoolingDataSource() throws Exception { DriverManager.registerDriver(new TesterDriver()); final ConnectionFactory connFactory = new DriverManagerConnectionFactory( "jdbc:apache:commons:testdriver","u1","p1"); final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connFactory, null); pcf.setPoolStatements(true); pcf.setDefaultReadOnly(Boolean.FALSE); pcf.setDefaultAutoCommit(Boolean.TRUE); final ObjectPool connPool = new GenericObjectPool<>(pcf); pcf.setPool(connPool); return new PoolingDataSource<>(connPool); } private PoolablePreparedStatement getPoolablePreparedStatement(Statement s) { while (s != null) { if (s instanceof PoolablePreparedStatement) { return (PoolablePreparedStatement) s; } if (!(s instanceof DelegatingPreparedStatement)) { return null; } s = ((DelegatingPreparedStatement) s).getDelegate(); } return null; } @Test public void testBatchUpdate() throws Exception { DriverManager.registerDriver(new TesterDriver()); final ConnectionFactory connFactory = new DriverManagerConnectionFactory( "jdbc:apache:commons:testdriver","u1","p1"); final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connFactory, null); pcf.setPoolStatements(true); pcf.setDefaultReadOnly(Boolean.FALSE); pcf.setDefaultAutoCommit(Boolean.TRUE); final ObjectPool connPool = new GenericObjectPool<>(pcf); pcf.setPool(connPool); final PoolingDataSource ds = new PoolingDataSource<>(connPool); final Connection conn = ds.getConnection(); final PreparedStatement ps = conn.prepareStatement("select 1 from dual"); final Statement inner = ((DelegatingPreparedStatement) ps).getInnermostDelegate(); // Check DBCP-372 ps.addBatch(); ps.close(); conn.close(); Assertions.assertFalse(inner.isClosed()); ds.close(); } @Test public void testCallableStatementPooling() throws Exception { DriverManager.registerDriver(new TesterDriver()); final ConnectionFactory connFactory = new DriverManagerConnectionFactory( "jdbc:apache:commons:testdriver","u1","p1"); final ObjectName oName = new ObjectName("UnitTests:DataSource=test"); final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connFactory, oName); pcf.setPoolStatements(true); pcf.setDefaultReadOnly(Boolean.FALSE); pcf.setDefaultAutoCommit(Boolean.TRUE); final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); config.setJmxNameBase("UnitTests:DataSource=test,connectionpool=connections"); config.setJmxNamePrefix(""); final ObjectPool connPool = new GenericObjectPool<>(pcf, config); pcf.setPool(connPool); final PoolingDataSource ds = new PoolingDataSource<>(connPool); try (Connection conn = ds.getConnection()) { final Statement stmt1 = conn.prepareStatement("select 1 from dual"); final Statement ustmt1 = ((DelegatingStatement) stmt1).getInnermostDelegate(); final Statement cstmt1 = conn.prepareCall("{call home}"); final Statement ucstmt1 = ((DelegatingStatement) cstmt1).getInnermostDelegate(); stmt1.close(); // Return to pool cstmt1.close(); // "" final Statement stmt2 = conn.prepareStatement("select 1 from dual"); // Check out from pool final Statement ustmt2 = ((DelegatingStatement) stmt2).getInnermostDelegate(); final Statement cstmt2 = conn.prepareCall("{call home}"); final Statement ucstmt2 = ((DelegatingStatement) cstmt2).getInnermostDelegate(); stmt2.close(); // Return to pool cstmt2.close(); // "" assertSame(ustmt1, ustmt2); assertSame(ucstmt1, ucstmt2); // Verify key distinguishes Callable from Prepared Statements in the pool final Statement stmt3 = conn.prepareCall("select 1 from dual"); final Statement ustmt3 = ((DelegatingStatement) stmt3).getInnermostDelegate(); stmt3.close(); assertNotSame(ustmt1, ustmt3); assertNotSame(ustmt3, ucstmt1); } ds.close(); } @Test public void testClosePool() throws Exception { DriverManager.registerDriver(new TesterDriver()); final ConnectionFactory connFactory = new DriverManagerConnectionFactory( "jdbc:apache:commons:testdriver","u1","p1"); final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connFactory, null); pcf.setPoolStatements(true); pcf.setDefaultReadOnly(Boolean.FALSE); pcf.setDefaultAutoCommit(Boolean.TRUE); final ObjectPool connPool = new GenericObjectPool<>(pcf); pcf.setPool(connPool); final PoolingDataSource ds = new PoolingDataSource<>(connPool); ((PoolingDataSource) ds).setAccessToUnderlyingConnectionAllowed(true); final Connection conn = ds.getConnection(); try (Statement s = conn.prepareStatement("select 1 from dual")) {} final Connection poolableConnection = ((DelegatingConnection) conn).getDelegate(); final Connection poolingConnection = ((DelegatingConnection) poolableConnection).getDelegate(); poolingConnection.close(); try (PreparedStatement ps = conn.prepareStatement("select 1 from dual")) { fail("Expecting SQLException"); } catch (final SQLException ex) { assertTrue(ex.getMessage().endsWith("invalid PoolingConnection.")); } ds.close(); } /** * Verifies that executing close() on an already closed DelegatingStatement * that wraps a PoolablePreparedStatement does not "re-close" the PPS * (which could be in use by another client - see DBCP-414). */ @Test public void testMultipleClose() throws Exception { final DataSource ds = createPoolingDataSource(); final Connection conn = ds.getConnection(); final PreparedStatement stmt1 = conn.prepareStatement("select 1 from dual"); final PoolablePreparedStatement pps1 = getPoolablePreparedStatement(stmt1); conn.close(); assertTrue(stmt1.isClosed()); // Closing conn should close stmt stmt1.close(); // Should already be closed - no-op assertTrue(stmt1.isClosed()); final Connection conn2 = ds.getConnection(); final PreparedStatement stmt2 = conn2.prepareStatement("select 1 from dual"); // Confirm stmt2 now wraps the same PPS wrapped by stmt1 Assertions.assertSame(pps1, getPoolablePreparedStatement(stmt2)); stmt1.close(); // close should not cascade to PPS that stmt1 used to wrap assertFalse(stmt2.isClosed()); stmt2.executeQuery(); // wrapped PPS needs to work here - pre DBCP-414 fix this throws conn2.close(); assertTrue(stmt1.isClosed()); assertTrue(stmt2.isClosed()); } @Test public void testStmtPool() throws Exception { final DataSource ds = createPoolingDataSource(); try (Connection conn = ds.getConnection()) { final Statement stmt1 = conn.prepareStatement("select 1 from dual"); final Statement ustmt1 = ((DelegatingStatement) stmt1).getInnermostDelegate(); stmt1.close(); final Statement stmt2 = conn.prepareStatement("select 1 from dual"); final Statement ustmt2 = ((DelegatingStatement) stmt2).getInnermostDelegate(); stmt2.close(); assertSame(ustmt1, ustmt2); } } } TestPStmtPoolingBasicDataSource.java000066400000000000000000000273231472045345700354430ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; import org.apache.commons.pool2.KeyedObjectPool; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * TestSuite for BasicDataSource with prepared statement pooling enabled */ public class TestPStmtPoolingBasicDataSource extends TestBasicDataSource { @Override @BeforeEach public void setUp() throws Exception { super.setUp(); // PoolPreparedStatements enabled, should not affect the basic tests ds.setPoolPreparedStatements(true); ds.setMaxOpenPreparedStatements(2); } /** * Verifies that the prepared statement pool behaves as an LRU cache, * closing least-recently-used statements idle in the pool to make room * for new ones if necessary. */ @Test public void testLRUBehavior() throws Exception { ds.setMaxOpenPreparedStatements(3); final Connection conn = getConnection(); assertNotNull(conn); // Open 3 statements and then close them into the pool final PreparedStatement stmt1 = conn.prepareStatement("select 'a' from dual"); final PreparedStatement inner1 = (PreparedStatement) ((DelegatingPreparedStatement) stmt1).getInnermostDelegate(); final PreparedStatement stmt2 = conn.prepareStatement("select 'b' from dual"); final PreparedStatement inner2 = (PreparedStatement) ((DelegatingPreparedStatement) stmt2).getInnermostDelegate(); final PreparedStatement stmt3 = conn.prepareStatement("select 'c' from dual"); final PreparedStatement inner3 = (PreparedStatement) ((DelegatingPreparedStatement) stmt3).getInnermostDelegate(); stmt1.close(); Thread.sleep(100); // Make sure return timestamps are different stmt2.close(); Thread.sleep(100); stmt3.close(); // Pool now has three idle statements, getting another one will force oldest (stmt1) out final PreparedStatement stmt4 = conn.prepareStatement("select 'd' from dual"); assertNotNull(stmt4); // Verify that inner1 has been closed try { inner1.clearParameters(); fail("expecting SQLExcption - statement should be closed"); } catch (final SQLException ex) { //Expected } // But others are still open inner2.clearParameters(); inner3.clearParameters(); // Now make sure stmt1 does not come back from the dead final PreparedStatement stmt5 = conn.prepareStatement("select 'a' from dual"); final PreparedStatement inner5 = (PreparedStatement) ((DelegatingPreparedStatement) stmt5).getInnermostDelegate(); assertNotSame(inner5, inner1); // inner2 should be closed now try { inner2.clearParameters(); fail("expecting SQLExcption - statement should be closed"); } catch (final SQLException ex) { //Expected } // But inner3 should still be open inner3.clearParameters(); } /** * Tests high-concurrency contention for connections and pooled prepared statements. * DBCP-414 */ @Test public void testMultipleThreads1() throws Exception { ds.setMaxWait(Duration.ofMillis(-1)); ds.setMaxTotal(5); ds.setMaxOpenPreparedStatements(-1); multipleThreads(Duration.ofMillis(5), false, false, Duration.ofMillis(-1), 3, 100, 10000); } @Test public void testPreparedStatementPooling() throws Exception { final Connection conn = getConnection(); assertNotNull(conn); final PreparedStatement stmt1 = conn.prepareStatement("select 'a' from dual"); assertNotNull(stmt1); final PreparedStatement stmt2 = conn.prepareStatement("select 'b' from dual"); assertNotNull(stmt2); assertNotSame(stmt1, stmt2); // go over the maxOpen limit try (PreparedStatement ps = conn.prepareStatement("select 'c' from dual")) { fail("expected SQLException"); } catch (final SQLException e) {} // make idle stmt2.close(); // test cleanup the 'b' statement final PreparedStatement stmt3 = conn.prepareStatement("select 'c' from dual"); assertNotNull(stmt3); assertNotSame(stmt3, stmt1); assertNotSame(stmt3, stmt2); // normal reuse of statement stmt1.close(); try (final PreparedStatement stmt4 = conn.prepareStatement("select 'a' from dual")) { assertNotNull(stmt4); } } // Bugzilla Bug 27246 // PreparedStatement cache should be different depending on the Catalog @Test public void testPStmtCatalog() throws Exception { final Connection conn = getConnection(); conn.setCatalog("catalog1"); final DelegatingPreparedStatement stmt1 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual"); final TesterPreparedStatement inner1 = (TesterPreparedStatement) stmt1.getInnermostDelegate(); assertEquals("catalog1", inner1.getCatalog()); stmt1.close(); conn.setCatalog("catalog2"); final DelegatingPreparedStatement stmt2 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual"); final TesterPreparedStatement inner2 = (TesterPreparedStatement) stmt2.getInnermostDelegate(); assertEquals("catalog2", inner2.getCatalog()); stmt2.close(); conn.setCatalog("catalog1"); final DelegatingPreparedStatement stmt3 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual"); final TesterPreparedStatement inner3 = (TesterPreparedStatement) stmt3.getInnermostDelegate(); assertEquals("catalog1", inner3.getCatalog()); stmt3.close(); assertNotSame(inner1, inner2); assertSame(inner1, inner3); } @Test public void testPStmtPoolingAcrossClose() throws Exception { ds.setMaxTotal(1); // only one connection in pool needed ds.setMaxIdle(1); ds.setAccessToUnderlyingConnectionAllowed(true); final Connection conn1 = getConnection(); assertNotNull(conn1); assertEquals(1, ds.getNumActive()); assertEquals(0, ds.getNumIdle()); final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual"); assertNotNull(stmt1); final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate(); assertNotNull(inner1); stmt1.close(); conn1.close(); assertEquals(0, ds.getNumActive()); assertEquals(1, ds.getNumIdle()); final Connection conn2 = getConnection(); assertNotNull(conn2); assertEquals(1, ds.getNumActive()); assertEquals(0, ds.getNumIdle()); final PreparedStatement stmt2 = conn2.prepareStatement("select 'a' from dual"); assertNotNull(stmt2); final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate(); assertNotNull(inner2); assertSame(inner1, inner2); } /** * Tests clearStatementPoolOnReturn introduced with DBCP-566. * When turned on, the statement pool must be empty after the connection is closed. * * @throws Exception */ @Test public void testPStmtPoolingAcrossCloseWithClearOnReturn() throws Exception { ds.setMaxTotal(1); // only one connection in pool needed ds.setMaxIdle(1); ds.setClearStatementPoolOnReturn(true); ds.setAccessToUnderlyingConnectionAllowed(true); final Connection conn1 = getConnection(); assertNotNull(conn1); assertEquals(1, ds.getNumActive()); assertEquals(0, ds.getNumIdle()); @SuppressWarnings("unchecked") final DelegatingConnection poolableConn = (DelegatingConnection) ((DelegatingConnection) conn1).getDelegateInternal(); final KeyedObjectPool stmtPool = ((PoolingConnection) poolableConn.getDelegateInternal()).getStatementPool(); final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual"); assertNotNull(stmt1); final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate(); assertNotNull(inner1); stmt1.close(); final PreparedStatement stmt2 = conn1.prepareStatement("select 'a' from dual"); assertNotNull(stmt2); final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate(); assertNotNull(inner2); assertSame(inner1, inner2); // from the same connection the statement must be pooled stmt2.close(); conn1.close(); assertTrue(inner1.isClosed()); assertEquals(0, stmtPool.getNumActive()); assertEquals(0, stmtPool.getNumIdle()); assertEquals(0, ds.getNumActive()); assertEquals(1, ds.getNumIdle()); final Connection conn2 = getConnection(); assertNotNull(conn2); assertEquals(1, ds.getNumActive()); assertEquals(0, ds.getNumIdle()); final PreparedStatement stmt3 = conn2.prepareStatement("select 'a' from dual"); assertNotNull(stmt3); final Statement inner3 = ((DelegatingPreparedStatement) stmt3).getInnermostDelegate(); assertNotNull(inner3); assertNotSame(inner1, inner3); // when acquiring the connection the next time, statement must be new conn2.close(); } @Test public void testPStmtPoolingWithNoClose() throws Exception { ds.setMaxTotal(1); // only one connection in pool needed ds.setMaxIdle(1); ds.setAccessToUnderlyingConnectionAllowed(true); final Connection conn1 = getConnection(); assertNotNull(conn1); assertEquals(1, ds.getNumActive()); assertEquals(0, ds.getNumIdle()); final PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual"); assertNotNull(stmt1); final Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate(); assertNotNull(inner1); stmt1.close(); assertNotNull(conn1); assertEquals(1, ds.getNumActive()); assertEquals(0, ds.getNumIdle()); final PreparedStatement stmt2 = conn1.prepareStatement("select 'a' from dual"); assertNotNull(stmt2); final Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate(); assertNotNull(inner2); assertSame(inner1, inner2); } } TestParallelCreationWithNoIdle.java000066400000000000000000000121541472045345700352730ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test if the pooling if no idle objects are used */ public class TestParallelCreationWithNoIdle { final class TestThread extends Thread { final Random random = new Random(); final int iter; final int delay; final int delayAfter; public TestThread(final int iter, final int delay, final int delayAfter) { this.iter = iter; this.delay = delay; this.delayAfter = delayAfter; } @Override public void run() { // System.out.println("Thread started " + Thread.currentThread().toString()); for (int i = 0; i < iter; i++) { sleepMax(delay); try (Connection conn = ds.getConnection(); PreparedStatement stmt = conn.prepareStatement("select 'literal', SYSDATE from dual")) { // System.out.println("Got Connection " + Thread.currentThread().toString()); final ResultSet rset = stmt.executeQuery(); rset.next(); sleepMax(delayAfter); rset.close(); } catch (final Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } // System.out.println("Thread done " + Thread.currentThread().toString()); } private void sleepMax(final int timeMax) { if (timeMax == 0) { return; } try { Thread.sleep(random.nextInt(timeMax)); } catch (final Exception e) { // ignored } } } private static final String CATALOG = "test catalog"; protected BasicDataSource ds; @BeforeEach public void setUp() throws Exception { ds = new BasicDataSource(); ds.setDriverClassName("org.apache.commons.dbcp2.TesterConnectionDelayDriver"); ds.setUrl("jdbc:apache:commons:testerConnectionDelayDriver:50"); ds.setMaxTotal(10); // this one is actually very important. // see DBCP-513 ds.setMaxIdle(0); // wait a minute. Usually the test runs in ~ 1 second // but often it's getting stuck ^^ // you have one second to get a thread dump ;) ds.setMaxWait(Duration.ofMinutes(1)); ds.setDefaultAutoCommit(Boolean.TRUE); ds.setDefaultReadOnly(Boolean.FALSE); ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); ds.setDefaultCatalog(CATALOG); ds.setUsername("userName"); ds.setPassword("password"); ds.setValidationQuery("SELECT DUMMY FROM DUAL"); ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "SELECT 2")); ds.setDriverClassLoader(new TesterClassLoader()); ds.setJmxName("org.apache.commons.dbcp2:name=test"); } /** * Fire up 100 Threads but only have 10 maxActive and forcedBlock. * See * @throws Exception */ @Test public void testMassiveConcurrentInitBorrow() throws Exception { final int numThreads = 200; ds.setDriverClassName("org.apache.commons.dbcp2.TesterConnectionDelayDriver"); ds.setUrl("jdbc:apache:commons:testerConnectionDelayDriver:20"); ds.setInitialSize(8); final List errors = Collections.synchronizedList(new ArrayList<>()); final Thread[] threads = new Thread[numThreads]; for (int i = 0; i < numThreads; i++) { threads[i] = new TestThread(2, 0, 50); threads[i].setUncaughtExceptionHandler((t, e) -> errors.add(e)); } for (int i = 0; i < numThreads; i++) { threads[i].start(); if (i%4 == 0) { Thread.sleep(20); } } for (int i = 0; i < numThreads; i++) { threads[i].join(); } assertEquals(0, errors.size()); ds.close(); } } TestPoolableConnection.java000066400000000000000000000225601472045345700337020ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import javax.management.OperationsException; import org.apache.commons.pool2.impl.GenericObjectPool; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** */ public class TestPoolableConnection { private GenericObjectPool pool; @BeforeEach public void setUp() throws Exception { final PoolableConnectionFactory factory = new PoolableConnectionFactory( new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", null), null); factory.setDefaultAutoCommit(Boolean.TRUE); factory.setDefaultReadOnly(Boolean.TRUE); pool = new GenericObjectPool<>(factory); factory.setPool(pool); } @AfterEach public void tearDown() { pool.close(); } @Test public void testClosingWrappedInDelegate() throws Exception { Assertions.assertEquals(0, pool.getNumActive()); final Connection conn = pool.borrowObject(); final DelegatingConnection outer = new DelegatingConnection<>(conn); Assertions.assertFalse(outer.isClosed()); Assertions.assertFalse(conn.isClosed()); Assertions.assertEquals(1, pool.getNumActive()); outer.close(); Assertions.assertTrue(outer.isClosed()); Assertions.assertTrue(conn.isClosed()); Assertions.assertEquals(0, pool.getNumActive()); Assertions.assertEquals(1, pool.getNumIdle()); } @Test public void testConnectionPool() throws Exception { // Grab a new connection from the pool final Connection c = pool.borrowObject(); assertNotNull(c, "Connection should be created and should not be null"); assertEquals(1, pool.getNumActive(), "There should be exactly one active object in the pool"); // Now return the connection by closing it c.close(); // Can't be null assertEquals(0, pool.getNumActive(), "There should now be zero active objects in the pool"); } @Test public void testDisconnectionIgnoreSqlCodes() throws Exception { pool.setTestOnReturn(true); final PoolableConnectionFactory factory = (PoolableConnectionFactory) pool.getFactory(); factory.setFastFailValidation(true); factory.setDisconnectionIgnoreSqlCodes(Arrays.asList("08S02", "08007")); final PoolableConnection conn = pool.borrowObject(); final TesterConnection nativeConnection = (TesterConnection) conn.getInnermostDelegate(); // set up non-fatal exception nativeConnection.setFailure(new SQLException("Non-fatal connection error.", "08S02")); assertThrows(SQLException.class, conn::createStatement); nativeConnection.setFailure(null); // verify that non-fatal connection is returned to the pool conn.close(); assertEquals(0, pool.getNumActive(), "The pool should have no active connections"); assertEquals(1, pool.getNumIdle(), "The pool should have one idle connection"); } @Test public void testFastFailValidation() throws Exception { pool.setTestOnReturn(true); final PoolableConnectionFactory factory = (PoolableConnectionFactory) pool.getFactory(); factory.setFastFailValidation(true); final PoolableConnection conn = pool.borrowObject(); final TesterConnection nativeConnection = (TesterConnection) conn.getInnermostDelegate(); // Set up non-fatal exception nativeConnection.setFailure(new SQLException("Not fatal error.", "Invalid syntax.")); try { conn.createStatement(); fail("Should throw SQL exception."); } catch (final SQLException ignored) { // cleanup failure nativeConnection.setFailure(null); } // validate should not fail - error was not fatal and condition was cleaned up conn.validate("SELECT 1", 1000); // now set up fatal failure nativeConnection.setFailure(new SQLException("Fatal connection error.", "01002")); try { conn.createStatement(); fail("Should throw SQL exception."); } catch (final SQLException ignored) { // cleanup failure nativeConnection.setFailure(null); } // validate should now fail because of previous fatal error, despite cleanup try { conn.validate("SELECT 1", 1000); fail("Should throw SQL exception on validation."); } catch (final SQLException notValid){ // expected - fatal error && fastFailValidation } // verify that bad connection does not get returned to the pool conn.close(); // testOnReturn triggers validate, which should fail assertEquals(0, pool.getNumActive(), "The pool should have no active connections"); assertEquals(0, pool.getNumIdle(), "The pool should have no idle connections"); } @Test public void testFastFailValidationCustomCodes() throws Exception { pool.setTestOnReturn(true); final PoolableConnectionFactory factory = (PoolableConnectionFactory) pool.getFactory(); factory.setFastFailValidation(true); final ArrayList disconnectionSqlCodes = new ArrayList<>(); disconnectionSqlCodes.add("XXX"); factory.setDisconnectionSqlCodes(disconnectionSqlCodes); final PoolableConnection conn = pool.borrowObject(); final TesterConnection nativeConnection = (TesterConnection) conn.getInnermostDelegate(); // Set up fatal exception nativeConnection.setFailure(new SQLException("Fatal connection error.", "XXX")); assertThrows(SQLException.class, conn::createStatement); // cleanup failure nativeConnection.setFailure(null); // verify that bad connection does not get returned to the pool conn.close(); // testOnReturn triggers validate, which should fail assertEquals(0, pool.getNumActive(), "The pool should have no active connections"); assertEquals(0, pool.getNumIdle(), "The pool should have no idle connections"); } @Test public void testIsDisconnectionSqlExceptionStackOverflow() throws Exception { final int maxDeep = 100_000; final SQLException rootException = new SQLException("Data truncated", "22001"); SQLException parentException = rootException; for (int i = 0; i <= maxDeep; i++) { final SQLException childException = new SQLException("Data truncated: " + i, "22001"); parentException.setNextException(childException); parentException = childException; } final Connection conn = pool.borrowObject(); assertFalse(((PoolableConnection) conn).isDisconnectionSqlException(rootException)); assertFalse(((PoolableConnection) conn).isFatalException(rootException)); } /** * Tests if the {@link PoolableConnectionMXBean} interface is a valid MXBean * interface. */ @Test public void testMXBeanCompliance() throws OperationsException { TestBasicDataSourceMXBean.testMXBeanCompliance(PoolableConnectionMXBean.class); } // Bugzilla Bug 33591: PoolableConnection leaks connections if the // delegated connection closes itself. @Test public void testPoolableConnectionLeak() throws Exception { // 'Borrow' a connection from the pool final Connection conn = pool.borrowObject(); // Now close our innermost delegate, simulating the case where the // underlying connection closes itself ((PoolableConnection)conn).getInnermostDelegate().close(); // At this point, we can close the pooled connection. The // PoolableConnection *should* realize that its underlying // connection is gone and invalidate itself. The pool should have no // active connections. try { conn.close(); } catch (final SQLException e) { // Here we expect 'connection already closed', but the connection // should *NOT* be returned to the pool } assertEquals(0, pool.getNumActive(), "The pool should have no active connections"); } } TestPoolingConnection.java000066400000000000000000000213121472045345700335460ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import java.sql.SQLException; import java.time.Duration; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class TestPoolingConnection { private PoolingConnection connection; @SuppressWarnings("resource") // Resources closed in @AfterEach method. @BeforeEach public void setUp() throws Exception { connection = new PoolingConnection(new TesterConnection("test", "test")); final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotalPerKey(-1); config.setBlockWhenExhausted(false); config.setMaxWait(Duration.ZERO); config.setMaxIdlePerKey(1); config.setMaxTotal(1); connection.setStatementPool(new GenericKeyedObjectPool<>(connection, config)); } @AfterEach public void tearDown() throws Exception { connection.close(); connection = null; } @Test public void testPrepareCall() throws Exception { final String sql = "select 'a' from dual"; try (final DelegatingCallableStatement statement = (DelegatingCallableStatement) connection.prepareCall(sql)) { final TesterCallableStatement testStatement = (TesterCallableStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); } } @Test public void testPrepareCallWithResultSetConcurrency() throws Exception { final String sql = "select 'a' from dual"; final int resultSetType = 0; final int resultSetConcurrency = 0; try (final DelegatingCallableStatement statement = (DelegatingCallableStatement) connection.prepareCall(sql, resultSetType, resultSetConcurrency)) { final TesterCallableStatement testStatement = (TesterCallableStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); assertEquals(resultSetType, testStatement.getResultSetType()); assertEquals(resultSetConcurrency, testStatement.getResultSetConcurrency()); } } @Test public void testPrepareCallWithResultSetHoldability() throws Exception { final String sql = "select 'a' from dual"; final int resultSetType = 0; final int resultSetConcurrency = 0; final int resultSetHoldability = 0; try (final DelegatingCallableStatement statement = (DelegatingCallableStatement) connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability)) { final TesterCallableStatement testStatement = (TesterCallableStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); assertEquals(resultSetType, testStatement.getResultSetType()); assertEquals(resultSetConcurrency, testStatement.getResultSetConcurrency()); assertEquals(resultSetHoldability, testStatement.getResultSetHoldability()); } } @Test public void testPrepareStatement() throws Exception { final String sql = "select 'a' from dual"; try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql)) { final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); } } @Test public void testPrepareStatementWithAutoGeneratedKeys() throws Exception { final String sql = "select 'a' from dual"; final int autoGeneratedKeys = 0; try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, autoGeneratedKeys)) { final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); assertEquals(autoGeneratedKeys, testStatement.getAutoGeneratedKeys()); } } @Test public void testPrepareStatementWithColumnIndexes() throws Exception { final String sql = "select 'a' from dual"; final int[] columnIndexes = {1}; try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, columnIndexes)) { final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); assertArrayEquals(columnIndexes, testStatement.getColumnIndexes()); } } @Test public void testPrepareStatementWithColumnNames() throws Exception { final String sql = "select 'a' from dual"; final String[] columnNames = {"columnName1"}; try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, columnNames)) { final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); assertArrayEquals(columnNames, testStatement.getColumnNames()); } } @Test public void testPrepareStatementWithResultSetConcurrency() throws Exception { final String sql = "select 'a' from dual"; final int resultSetType = 0; final int resultSetConcurrency = 0; try ( final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, resultSetType, resultSetConcurrency)) { final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); assertEquals(resultSetType, testStatement.getResultSetType()); assertEquals(resultSetConcurrency, testStatement.getResultSetConcurrency()); } } @Test public void testPrepareStatementWithResultSetHoldability() throws Exception { final String sql = "select 'a' from dual"; final int resultSetType = 0; final int resultSetConcurrency = 0; final int resultSetHoldability = 0; try (final DelegatingPreparedStatement statement = (DelegatingPreparedStatement) connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability)) { final TesterPreparedStatement testStatement = (TesterPreparedStatement) statement.getInnermostDelegate(); // assert assertEquals(sql, testStatement.getSql()); assertEquals(resultSetType, testStatement.getResultSetType()); assertEquals(resultSetConcurrency, testStatement.getResultSetConcurrency()); assertEquals(resultSetHoldability, testStatement.getResultSetHoldability()); } } /** * Tests DBCP-596 PoolingConnection.toString() causes StackOverflowError. */ @Test public void testToStringStackOverflow() throws SQLException { // Also tests a possible NullPointerException in PoolingConnection.close() try (PoolingConnection conn = new PoolingConnection(null)) { final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); try (GenericKeyedObjectPool stmtPool = new GenericKeyedObjectPool<>(conn, config)) { conn.setStatementPool(stmtPool); } conn.toString(); } } } TestPoolingDataSource.java000066400000000000000000000205071472045345700335060ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import org.apache.commons.pool2.impl.GenericObjectPool; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * TestSuite for PoolingDataSource */ public class TestPoolingDataSource extends TestConnectionPool { protected PoolingDataSource ds; private GenericObjectPool pool; @Override protected Connection getConnection() throws Exception { return ds.getConnection(); } @BeforeEach public void setUp() throws Exception { final Properties properties = new Properties(); properties.setProperty(Constants.KEY_USER, "userName"); properties.setProperty(Constants.KEY_PASSWORD, "password"); final PoolableConnectionFactory factory = new PoolableConnectionFactory( new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", properties), null); factory.setValidationQuery("SELECT DUMMY FROM DUAL"); factory.setDefaultReadOnly(Boolean.TRUE); factory.setDefaultAutoCommit(Boolean.TRUE); pool = new GenericObjectPool<>(factory); factory.setPool(pool); pool.setMaxTotal(getMaxTotal()); pool.setMaxWait(getMaxWaitDuration()); ds = new PoolingDataSource<>(pool); ds.setAccessToUnderlyingConnectionAllowed(true); } @Override @AfterEach public void tearDown() throws Exception { ds.close(); super.tearDown(); } @Test public void testClose() throws Exception { final Properties properties = new Properties(); properties.setProperty(Constants.KEY_USER, "userName"); properties.setProperty(Constants.KEY_PASSWORD, "password"); final PoolableConnectionFactory f = new PoolableConnectionFactory( new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", properties), null); f.setValidationQuery("SELECT DUMMY FROM DUAL"); f.setDefaultReadOnly(Boolean.TRUE); f.setDefaultAutoCommit(Boolean.TRUE); final GenericObjectPool p = new GenericObjectPool<>(f); p.setMaxTotal(getMaxTotal()); p.setMaxWait(getMaxWaitDuration()); try ( PoolingDataSource dataSource = new PoolingDataSource<>(p) ) { final Connection connection = dataSource.getConnection(); assertNotNull(connection); connection.close(); } assertTrue(p.isClosed()); assertEquals(0, p.getNumIdle()); assertEquals(0, p.getNumActive()); } /** * DBCP-412 * Verify that omitting factory.setPool(pool) when setting up PDS does not * result in NPE. */ @Test public void testFixFactoryConfig() throws Exception { final Properties properties = new Properties(); properties.setProperty(Constants.KEY_USER, "userName"); properties.setProperty(Constants.KEY_PASSWORD, "password"); final PoolableConnectionFactory f = new PoolableConnectionFactory( new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", properties), null); f.setValidationQuery("SELECT DUMMY FROM DUAL"); f.setDefaultReadOnly(Boolean.TRUE); f.setDefaultAutoCommit(Boolean.TRUE); final GenericObjectPool p = new GenericObjectPool<>(f); p.setMaxTotal(getMaxTotal()); p.setMaxWait(getMaxWaitDuration()); ds = new PoolingDataSource<>(p); assertEquals(f.getPool(), p); ds.getConnection(); } @Test public void testIsWrapperFor() throws Exception { assertTrue(ds.isWrapperFor(PoolingDataSource.class)); assertTrue(ds.isWrapperFor(AutoCloseable.class)); assertFalse(ds.isWrapperFor(String.class)); assertFalse(ds.isWrapperFor(null)); } @Test public void testPoolGuardConnectionWrapperEqualInnermost() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); final DelegatingConnection con = (DelegatingConnection) ds.getConnection(); final Connection inner = con.getInnermostDelegate(); ds.setAccessToUnderlyingConnectionAllowed(false); final DelegatingConnection con2 = new DelegatingConnection<>(inner); assertNotEquals(con2, con); assertTrue(con.innermostDelegateEquals(con2.getInnermostDelegate())); assertTrue(con2.innermostDelegateEquals(inner)); assertNotEquals(con, con2); } @Test public void testPoolGuardConnectionWrapperEqualsFail() throws Exception { final Connection con1 = ds.getConnection(); final Connection con2 = ds.getConnection(); assertNotEquals(con1, con2); con1.close(); con2.close(); } @Test public void testPoolGuardConnectionWrapperEqualsNull() throws Exception { final Connection con1 = ds.getConnection(); final Connection con2 = null; assertNotEquals(con2, con1); con1.close(); } /* * JIRA: DBCP-198 */ @Test public void testPoolGuardConnectionWrapperEqualsReflexive() throws Exception { final Connection con = ds.getConnection(); final Connection con2 = con; assertEquals(con2, con); assertEquals(con, con2); con.close(); } @Test public void testPoolGuardConnectionWrapperEqualsSameDelegate() throws Exception { // Get a maximal set of connections from the pool final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = newConnection(); } // Close the delegate of one wrapper in the pool ((DelegatingConnection) c[0]).getDelegate().close(); // Grab a new connection - should get c[0]'s closed connection // so should be delegate-equivalent final Connection con = newConnection(); Assertions.assertNotEquals(c[0], con); Assertions.assertEquals( ((DelegatingConnection) c[0]).getInnermostDelegateInternal(), ((DelegatingConnection) con).getInnermostDelegateInternal()); for (final Connection element : c) { element.close(); } } @Test public void testPoolGuardConnectionWrapperEqualsType() throws Exception { final Connection con1 = ds.getConnection(); final Integer con2 = 0; assertNotEquals(con2, con1); con1.close(); } @Test public void testUnwrap() throws Exception { assertSame(ds.unwrap(PoolingDataSource.class), ds); assertSame(ds.unwrap(AutoCloseable.class), ds); assertThrows(SQLException.class, () -> ds.unwrap(String.class)); assertThrows(SQLException.class, () -> ds.unwrap(null)); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestPoolingDriver.java000066400000000000000000000234661472045345700327750ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.time.Duration; import javax.sql.DataSource; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests for a {@link GenericObjectPool} based {@link PoolingDriver}. */ public class TestPoolingDriver extends TestConnectionPool { private PoolingDriver driver; @Override protected Connection getConnection() throws Exception { return DriverManager.getConnection("jdbc:apache:commons:dbcp:test"); } @BeforeEach public void setUp() throws Exception { final DriverConnectionFactory cf = new DriverConnectionFactory(new TesterDriver(),"jdbc:apache:commons:testdriver", null); final PoolableConnectionFactory pcf = new PoolableConnectionFactory(cf, null); pcf.setPoolStatements(true); pcf.setMaxOpenPreparedStatements(10); pcf.setValidationQuery("SELECT COUNT(*) FROM DUAL"); pcf.setDefaultReadOnly(Boolean.FALSE); pcf.setDefaultAutoCommit(Boolean.TRUE); final GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxTotal(getMaxTotal()); poolConfig.setMaxWait(getMaxWaitDuration()); poolConfig.setMinIdle(10); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); poolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(10_000)); poolConfig.setNumTestsPerEvictionRun(5); poolConfig.setMinEvictableIdleTime(Duration.ofMillis(5_000)); final GenericObjectPool pool = new GenericObjectPool<>(pcf, poolConfig); pcf.setPool(pool); assertNotNull(pcf); driver = new PoolingDriver(true); driver.registerPool("test",pool); } @Override @AfterEach public void tearDown() throws Exception { driver.closePool("test"); super.tearDown(); } @Test public void test1() { final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:some:connect:string","userName","password"); final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connectionFactory, null); pcf.setDefaultReadOnly(Boolean.FALSE); pcf.setDefaultAutoCommit(Boolean.TRUE); final GenericObjectPool connectionPool = new GenericObjectPool<>(pcf); pcf.setPool(connectionPool); final DataSource ds = new PoolingDataSource<>(connectionPool); Assertions.assertNotNull(ds); } @Test public void test2() { final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:some:connect:string","userName","password"); final PoolableConnectionFactory pcf = new PoolableConnectionFactory(connectionFactory, null); pcf.setDefaultReadOnly(Boolean.FALSE); pcf.setDefaultAutoCommit(Boolean.TRUE); final GenericObjectPool connectionPool = new GenericObjectPool<>(pcf); final PoolingDriver driver2 = new PoolingDriver(); driver2.registerPool("example", connectionPool); } @Test public void testClosePool() throws Exception { final Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:test"); assertNotNull(conn); conn.close(); final PoolingDriver driver2 = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:"); driver2.closePool("test"); try (Connection c = DriverManager.getConnection("jdbc:apache:commons:dbcp:test")) { fail("expected SQLException"); } catch (final SQLException e) { // OK } } @Test public void testInvalidateConnection() throws Exception { final Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:test"); assertNotNull(conn); final ObjectPool pool = driver.getConnectionPool("test"); assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); final PoolingDriver driver2 = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:"); driver2.invalidateConnection(conn); assertEquals(0, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); assertTrue(conn.isClosed()); } @Test public void testLogWriter() throws Exception { final PrintStream ps = new PrintStream(new ByteArrayOutputStream(), false, StandardCharsets.UTF_8.name()); final PrintWriter pw = new PrintWriter(new OutputStreamWriter(new ByteArrayOutputStream(), StandardCharsets.UTF_8)); System.setErr(new PrintStream(new ByteArrayOutputStream(), false, StandardCharsets.UTF_8.name())); SQLException ex; DriverManager.setLogWriter(pw); ex = new SQLException("A", new Exception("a")); ex.printStackTrace(); ex.printStackTrace(ps); ex.printStackTrace(pw); ex = new SQLException("B"); ex.printStackTrace(); ex.printStackTrace(ps); ex.printStackTrace(pw); ex = new SQLException(null, new Exception("c")); ex.printStackTrace(); ex.printStackTrace(ps); ex.printStackTrace(pw); ex = new SQLException((String)null); ex.printStackTrace(); ex.printStackTrace(ps); ex.printStackTrace(pw); DriverManager.setLogWriter(null); ex = new SQLException("A", new Exception("a")); ex.printStackTrace(); ex.printStackTrace(ps); ex.printStackTrace(pw); ex = new SQLException("B"); ex.printStackTrace(); ex.printStackTrace(ps); ex.printStackTrace(pw); ex = new SQLException(null, new Exception("c")); ex.printStackTrace(); ex.printStackTrace(ps); ex.printStackTrace(pw); ex = new SQLException((String)null); ex.printStackTrace(); ex.printStackTrace(ps); ex.printStackTrace(pw); } /** "https://issues.apache.org/bugzilla/show_bug.cgi?id=12400" */ @Test public void testReportedBug12400() throws Exception { final GenericObjectPoolConfig config = new GenericObjectPoolConfig<>(); config.setMaxTotal(70); config.setMaxWait(Duration.ofMinutes(1)); config.setMaxIdle(10); final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( "jdbc:apache:commons:testdriver", "userName", "password"); final PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null); poolableConnectionFactory.setDefaultReadOnly(Boolean.FALSE); poolableConnectionFactory.setDefaultAutoCommit(Boolean.TRUE); final ObjectPool connectionPool = new GenericObjectPool<>(poolableConnectionFactory, config); poolableConnectionFactory.setPool(connectionPool); assertNotNull(poolableConnectionFactory); final PoolingDriver driver2 = new PoolingDriver(); driver2.registerPool("neusoftim", connectionPool); final Connection[] conn = new Connection[25]; for(int i=0;i<25;i++) { conn[i] = DriverManager.getConnection("jdbc:apache:commons:dbcp:neusoftim"); for(int j=0;j list = Collections.singletonList(cause); final SQLExceptionList sqlExceptionList = new SQLExceptionList(list); Assertions.assertEquals(cause, sqlExceptionList.getCause()); Assertions.assertEquals(list, sqlExceptionList.getCauseList()); sqlExceptionList.printStackTrace(); } @Test public void testNullCause() { final SQLExceptionList sqlExceptionList = new SQLExceptionList(null); Assertions.assertNull(sqlExceptionList.getCause()); Assertions.assertNull(sqlExceptionList.getCauseList()); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TestUtils.java000066400000000000000000000110451472045345700313000ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import org.junit.jupiter.api.Test; public class TestUtils { public static PStmtKey getPStmtKey(final PoolablePreparedStatement poolablePreparedStatement) { return poolablePreparedStatement.getKey(); } @Test public void testCheckForConflictsBothCollectionsNull() { assertDoesNotThrow(() -> Utils.checkSqlCodes(null, null)); } @Test public void testCheckForConflictsEmptyCollections() { final Collection codes1 = Collections.emptySet(); final Collection codes2 = Collections.emptySet(); assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); } @Test public void testCheckForConflictsFirstCollectionNull() { final Collection codes1 = null; final Collection codes2 = new HashSet<>(Arrays.asList("08005", "08007")); assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); } @Test public void testCheckForConflictsNoOverlap() { final Collection codes1 = new HashSet<>(Arrays.asList("08003", "08006")); final Collection codes2 = new HashSet<>(Arrays.asList("08005", "08007")); assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); } @Test public void testCheckForConflictsSecondCollectionNull() { final Collection codes1 = new HashSet<>(Arrays.asList("08003", "08006")); final Collection codes2 = null; assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); } @Test public void testCheckForConflictsWith1Overlap() { final Collection codes1 = new HashSet<>(Arrays.asList("08003", "08006")); final Collection codes2 = new HashSet<>(Arrays.asList("08005", "08006")); final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Utils.checkSqlCodes(codes1, codes2)); assertEquals("[08006] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); } @Test public void testCheckForConflictsWith2Overlap() { final Collection codes1 = new HashSet<>(Arrays.asList("08003", "08006", "08007")); final Collection codes2 = new HashSet<>(Arrays.asList("08005", "08006", "08007")); final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Utils.checkSqlCodes(codes1, codes2)); assertEquals("[08006, 08007] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); } @Test public void testClassLoads() { Utils.closeQuietly((AutoCloseable) null); } @Test public void testIsDisconnectionSqlCode() { assertTrue(Utils.isDisconnectionSqlCode("57P01"), "57P01 should be recognised as a disconnection SQL code."); assertTrue(Utils.isDisconnectionSqlCode("01002"), "01002 should be recognised as a disconnection SQL code."); assertTrue(Utils.isDisconnectionSqlCode("JZ0C0"), "JZ0C0 should be recognised as a disconnection SQL code."); assertFalse(Utils.isDisconnectionSqlCode("INVALID"), "INVALID should not be recognised as a disconnection SQL code."); assertFalse(Utils.isDisconnectionSqlCode("00000"), "00000 should not be recognised as a disconnection SQL code."); } } TesterCallableStatement.java000066400000000000000000000423101472045345700340330ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.Date; import java.sql.NClob; import java.sql.Ref; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLType; import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Map; /** * Trivial implementation of a CallableStatement to avoid null pointer exceptions in tests. */ public class TesterCallableStatement extends TesterPreparedStatement implements CallableStatement { public TesterCallableStatement(final Connection conn) { super(conn); } public TesterCallableStatement(final Connection conn, final String sql) { super(conn, sql); } public TesterCallableStatement(final Connection conn, final String sql, final int resultSetType, final int resultSetConcurrency) { super(conn, sql, resultSetType, resultSetConcurrency); } public TesterCallableStatement(final Connection conn, final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { super(conn, sql, resultSetType, resultSetConcurrency, resultSetHoldability); } @Override public Array getArray(final int i) throws SQLException { return null; } @Override public Array getArray(final String parameterName) throws SQLException { return null; } @Override public BigDecimal getBigDecimal(final int parameterIndex) throws SQLException { return null; } /** * @deprecated See {@link CallableStatement#getBigDecimal(int,int)}. */ @Deprecated @Override public BigDecimal getBigDecimal(final int parameterIndex, final int scale) throws SQLException { return null; } @Override public BigDecimal getBigDecimal(final String parameterName) throws SQLException { return null; } @Override public Blob getBlob(final int i) throws SQLException { return null; } @Override public Blob getBlob(final String parameterName) throws SQLException { return null; } @Override public boolean getBoolean(final int parameterIndex) throws SQLException { return false; } @Override public boolean getBoolean(final String parameterName) throws SQLException { return false; } @Override public byte getByte(final int parameterIndex) throws SQLException { return 0; } @Override public byte getByte(final String parameterName) throws SQLException { return 0; } @Override public byte[] getBytes(final int parameterIndex) throws SQLException { return new byte[0]; } @Override public byte[] getBytes(final String parameterName) throws SQLException { return new byte[0]; } @Override public Reader getCharacterStream(final int parameterIndex) throws SQLException { return null; } @Override public Reader getCharacterStream(final String parameterName) throws SQLException { return null; } @Override public Clob getClob(final int i) throws SQLException { return null; } @Override public Clob getClob(final String parameterName) throws SQLException { return null; } @Override public Date getDate(final int parameterIndex) throws SQLException { return null; } @Override public Date getDate(final int parameterIndex, final Calendar cal) throws SQLException { return null; } @Override public Date getDate(final String parameterName) throws SQLException { return null; } @Override public Date getDate(final String parameterName, final Calendar cal) throws SQLException { return null; } @Override public double getDouble(final int parameterIndex) throws SQLException { return 0; } @Override public double getDouble(final String parameterName) throws SQLException { return 0; } @Override public float getFloat(final int parameterIndex) throws SQLException { return 0; } @Override public float getFloat(final String parameterName) throws SQLException { return 0; } @Override public int getInt(final int parameterIndex) throws SQLException { return 0; } @Override public int getInt(final String parameterName) throws SQLException { return 0; } @Override public long getLong(final int parameterIndex) throws SQLException { return 0; } @Override public long getLong(final String parameterName) throws SQLException { return 0; } @Override public Reader getNCharacterStream(final int parameterIndex) throws SQLException { return null; } @Override public Reader getNCharacterStream(final String parameterName) throws SQLException { return null; } @Override public NClob getNClob(final int parameterIndex) throws SQLException { return null; } @Override public NClob getNClob(final String parameterName) throws SQLException { return null; } @Override public String getNString(final int parameterIndex) throws SQLException { return null; } @Override public String getNString(final String parameterName) throws SQLException { return null; } @Override public Object getObject(final int parameterIndex) throws SQLException { return null; } @Override public T getObject(final int parameterIndex, final Class type) throws SQLException { return null; } @Override public Object getObject(final int i, final Map> map) throws SQLException { return null; } @Override public Object getObject(final String parameterName) throws SQLException { return null; } @Override public T getObject(final String parameterName, final Class type) throws SQLException { return null; } @Override public Object getObject(final String parameterName, final Map> map) throws SQLException { return null; } @Override public Ref getRef(final int i) throws SQLException { return null; } @Override public Ref getRef(final String parameterName) throws SQLException { return null; } @Override public RowId getRowId(final int parameterIndex) throws SQLException { return null; } @Override public RowId getRowId(final String parameterName) throws SQLException { return null; } @Override public short getShort(final int parameterIndex) throws SQLException { return 0; } @Override public short getShort(final String parameterName) throws SQLException { return 0; } @Override public SQLXML getSQLXML(final int parameterIndex) throws SQLException { return null; } @Override public SQLXML getSQLXML(final String parameterName) throws SQLException { return null; } @Override public String getString(final int parameterIndex) throws SQLException { return null; } @Override public String getString(final String parameterName) throws SQLException { return null; } @Override public Time getTime(final int parameterIndex) throws SQLException { return null; } @Override public Time getTime(final int parameterIndex, final Calendar cal) throws SQLException { return null; } @Override public Time getTime(final String parameterName) throws SQLException { return null; } @Override public Time getTime(final String parameterName, final Calendar cal) throws SQLException { return null; } @Override public Timestamp getTimestamp(final int parameterIndex) throws SQLException { return null; } @Override public Timestamp getTimestamp(final int parameterIndex, final Calendar cal) throws SQLException { return null; } @Override public Timestamp getTimestamp(final String parameterName) throws SQLException { return null; } @Override public Timestamp getTimestamp(final String parameterName, final Calendar cal) throws SQLException { return null; } @Override public URL getURL(final int parameterIndex) throws SQLException { return null; } @Override public URL getURL(final String parameterName) throws SQLException { return null; } @Override public void registerOutParameter(final int parameterIndex, final int sqlType) throws SQLException { } @Override public void registerOutParameter(final int parameterIndex, final int sqlType, final int scale) throws SQLException { } @Override public void registerOutParameter(final int paramIndex, final int sqlType, final String typeName) throws SQLException { } @Override public void registerOutParameter(final int parameterIndex, final SQLType sqlType) throws SQLException { // Do nothing } @Override public void registerOutParameter(final int parameterIndex, final SQLType sqlType, final int scale) throws SQLException { // Do nothing } @Override public void registerOutParameter(final int parameterIndex, final SQLType sqlType, final String typeName) throws SQLException { // Do nothing } @Override public void registerOutParameter(final String parameterName, final int sqlType) throws SQLException { } @Override public void registerOutParameter(final String parameterName, final int sqlType, final int scale) throws SQLException { } @Override public void registerOutParameter(final String parameterName, final int sqlType, final String typeName) throws SQLException { } @Override public void registerOutParameter(final String parameterName, final SQLType sqlType) throws SQLException { // Do nothing } @Override public void registerOutParameter(final String parameterName, final SQLType sqlType, final int scale) throws SQLException { // Do nothing } @Override public void registerOutParameter(final String parameterName, final SQLType sqlType, final String typeName) throws SQLException { // Do nothing } @Override public void setAsciiStream(final String parameterName, final InputStream inputStream) throws SQLException { } @Override public void setAsciiStream(final String parameterName, final InputStream x, final int length) throws SQLException { } @Override public void setAsciiStream(final String parameterName, final InputStream inputStream, final long length) throws SQLException { } @Override public void setBigDecimal(final String parameterName, final BigDecimal x) throws SQLException { } @Override public void setBinaryStream(final String parameterName, final InputStream inputStream) throws SQLException { } @Override public void setBinaryStream(final String parameterName, final InputStream x, final int length) throws SQLException { } @Override public void setBinaryStream(final String parameterName, final InputStream inputStream, final long length) throws SQLException { } @Override public void setBlob(final String parameterName, final Blob blob) throws SQLException { } @Override public void setBlob(final String parameterName, final InputStream inputStream) throws SQLException { } @Override public void setBlob(final String parameterName, final InputStream inputStream, final long length) throws SQLException { } @Override public void setBoolean(final String parameterName, final boolean x) throws SQLException { } @Override public void setByte(final String parameterName, final byte x) throws SQLException { } @Override public void setBytes(final String parameterName, final byte[] x) throws SQLException { } @Override public void setCharacterStream(final String parameterName, final Reader reader) throws SQLException { } @Override public void setCharacterStream(final String parameterName, final Reader reader, final int length) throws SQLException { } @Override public void setCharacterStream(final String parameterName, final Reader reader, final long length) throws SQLException { } @Override public void setClob(final String parameterName, final Clob clob) throws SQLException { } @Override public void setClob(final String parameterName, final Reader reader) throws SQLException { } @Override public void setClob(final String parameterName, final Reader reader, final long length) throws SQLException { } @Override public void setDate(final String parameterName, final Date x) throws SQLException { } @Override public void setDate(final String parameterName, final Date x, final Calendar cal) throws SQLException { } @Override public void setDouble(final String parameterName, final double x) throws SQLException { } @Override public void setFloat(final String parameterName, final float x) throws SQLException { } @Override public void setInt(final String parameterName, final int x) throws SQLException { } @Override public void setLong(final String parameterName, final long x) throws SQLException { } @Override public void setNCharacterStream(final String parameterName, final Reader reader) throws SQLException { } @Override public void setNCharacterStream(final String parameterName, final Reader reader, final long length) throws SQLException { } @Override public void setNClob(final String parameterName, final NClob value) throws SQLException { } @Override public void setNClob(final String parameterName, final Reader reader) throws SQLException { } @Override public void setNClob(final String parameterName, final Reader reader, final long length) throws SQLException { } @Override public void setNString(final String parameterName, final String value) throws SQLException { } @Override public void setNull(final String parameterName, final int sqlType) throws SQLException { } @Override public void setNull(final String parameterName, final int sqlType, final String typeName) throws SQLException { } @Override public void setObject(final String parameterName, final Object x) throws SQLException { } @Override public void setObject(final String parameterName, final Object x, final int targetSqlType) throws SQLException { } @Override public void setObject(final String parameterName, final Object x, final int targetSqlType, final int scale) throws SQLException { } @Override public void setObject(final String parameterName, final Object x, final SQLType targetSqlType) throws SQLException { // Do nothing } @Override public void setObject(final String parameterName, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { // Do nothing } @Override public void setRowId(final String parameterName, final RowId value) throws SQLException { } @Override public void setShort(final String parameterName, final short x) throws SQLException { } @Override public void setSQLXML(final String parameterName, final SQLXML value) throws SQLException { } @Override public void setString(final String parameterName, final String x) throws SQLException { } @Override public void setTime(final String parameterName, final Time x) throws SQLException { } @Override public void setTime(final String parameterName, final Time x, final Calendar cal) throws SQLException { } @Override public void setTimestamp(final String parameterName, final Timestamp x) throws SQLException { } @Override public void setTimestamp(final String parameterName, final Timestamp x, final Calendar cal) throws SQLException { } @Override public void setURL(final String parameterName, final URL val) throws SQLException { } @Override public boolean wasNull() throws SQLException { return false; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TesterClassLoader.java000066400000000000000000000026771472045345700327360ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.util.HashSet; import java.util.Set; /** * Simple class loader that just records the classes it was asked to load. */ public class TesterClassLoader extends ClassLoader { private final Set loadedClasses = new HashSet<>(); public boolean didLoad(final String className) { return loadedClasses.contains(className); } @Override protected synchronized Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { final Class clazz = super.loadClass(name, resolve); loadedClasses.add(name); return clazz; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TesterConnection.java000066400000000000000000000307601472045345700326330ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.SQLClientInfoException; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Statement; import java.sql.Struct; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; /** * A dummy {@link Connection}, for testing purposes. */ public class TesterConnection extends AbandonedTrace implements Connection { protected boolean open = true; protected boolean aborted; protected boolean autoCommit = true; protected int transactionIsolation = 1; protected final DatabaseMetaData metaData = new TesterDatabaseMetaData(); protected String catalog; protected String schema; protected Map> typeMap; protected boolean readOnly; protected SQLWarning warnings; protected final String userName; protected Exception failure; protected boolean sqlExceptionOnClose; TesterConnection(final String userName, @SuppressWarnings("unused") final String password) { this.userName = userName; } @Override public void abort(final Executor executor) throws SQLException { checkFailure(); aborted = true; open = false; } protected void checkFailure() throws SQLException { if (failure != null) { if (failure instanceof SQLException) { throw (SQLException) failure; } throw new SQLException("TesterConnection failure", failure); } } protected void checkOpen() throws SQLException { if (!open) { throw new SQLException("Connection is closed."); } checkFailure(); } @Override public void clearWarnings() throws SQLException { checkOpen(); warnings = null; } @Override public void close() throws SQLException { checkFailure(); open = false; } @Override public void commit() throws SQLException { checkOpen(); if (isReadOnly()) { throw new SQLException("Cannot commit a readonly connection"); } } @Override public Array createArrayOf(final String typeName, final Object[] elements) throws SQLException { throw new SQLException("Not implemented."); } @Override public Blob createBlob() throws SQLException { throw new SQLException("Not implemented."); } @Override public Clob createClob() throws SQLException { throw new SQLException("Not implemented."); } @Override public NClob createNClob() throws SQLException { throw new SQLException("Not implemented."); } @Override public SQLXML createSQLXML() throws SQLException { throw new SQLException("Not implemented."); } @Override public Statement createStatement() throws SQLException { checkOpen(); return new TesterStatement(this); } @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); return new TesterStatement(this); } @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { return createStatement(); } @Override public Struct createStruct(final String typeName, final Object[] attributes) throws SQLException { throw new SQLException("Not implemented."); } @Override public boolean getAutoCommit() throws SQLException { checkOpen(); return autoCommit; } @Override public String getCatalog() throws SQLException { checkOpen(); return catalog; } @Override public Properties getClientInfo() throws SQLException { throw new SQLException("Not implemented."); } @Override public String getClientInfo(final String name) throws SQLException { throw new SQLException("Not implemented."); } @Override public int getHoldability() throws SQLException { throw new SQLException("Not implemented."); } @Override public DatabaseMetaData getMetaData() throws SQLException { checkOpen(); return metaData; } @Override public int getNetworkTimeout() throws SQLException { throw new SQLException("Not implemented."); } @Override public String getSchema() throws SQLException { checkOpen(); return schema; } @Override public int getTransactionIsolation() throws SQLException { checkOpen(); return transactionIsolation; } @Override public Map> getTypeMap() throws SQLException { checkOpen(); return typeMap; } public String getUserName() { return this.userName; } @Override public SQLWarning getWarnings() throws SQLException { checkOpen(); return warnings; } public boolean isAborted() throws SQLException { checkFailure(); return aborted; } @Override public boolean isClosed() throws SQLException { checkFailure(); return !open; } @Override public boolean isReadOnly() throws SQLException { checkOpen(); return readOnly; } public boolean isSqlExceptionOnClose() { return sqlExceptionOnClose; } @Override public boolean isValid(final int timeout) throws SQLException { return open; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { throw new SQLException("Not implemented."); } @Override public String nativeSQL(final String sql) throws SQLException { checkOpen(); return sql; } @Override public CallableStatement prepareCall(final String sql) throws SQLException { checkOpen(); if ("warning".equals(sql)) { setWarnings(new SQLWarning("warning in prepareCall")); } return new TesterCallableStatement(this, sql); } @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); return new TesterCallableStatement(this, sql, resultSetType, resultSetConcurrency); } @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); return new TesterCallableStatement(this, sql, resultSetType, resultSetConcurrency, resultSetHoldability); } @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { checkOpen(); switch (sql) { case "null": return null; case "invalid": throw new SQLException("invalid query"); case "broken": throw new SQLException("broken connection"); default: break; } return new TesterPreparedStatement(this, sql); } @Override public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); return new TesterPreparedStatement(this, sql, autoGeneratedKeys); } @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { checkOpen(); return new TesterPreparedStatement(this, sql, resultSetType, resultSetConcurrency); } @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { checkOpen(); return new TesterPreparedStatement(this, sql, resultSetType, resultSetConcurrency, resultSetHoldability); } @Override public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { return new TesterPreparedStatement(this, sql, columnIndexes); } @Override public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { return new TesterPreparedStatement(this, sql, columnNames); } @Override public void releaseSavepoint(final java.sql.Savepoint savepoint) throws SQLException { throw new SQLException("Not implemented."); } @Override public void rollback() throws SQLException { checkOpen(); if (isReadOnly()) { throw new SQLException("Cannot rollback a readonly connection"); } if (getAutoCommit()) { throw new SQLException("Cannot rollback a connection in auto-commit"); } } @Override public void rollback(final java.sql.Savepoint savepoint) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { checkOpen(); this.autoCommit = autoCommit; } @Override public void setCatalog(final String catalog) throws SQLException { checkOpen(); this.catalog = catalog; } @Override public void setClientInfo(final Properties properties) throws SQLClientInfoException { throw new SQLClientInfoException(); } @Override public void setClientInfo(final String name, final String value) throws SQLClientInfoException { throw new SQLClientInfoException(); } public void setFailure(final Exception failure) { this.failure = failure; } @Override public void setHoldability(final int holdability) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setNetworkTimeout(final Executor executor, final int milliseconds) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setReadOnly(final boolean readOnly) throws SQLException { checkOpen(); this.readOnly = readOnly; } @Override public java.sql.Savepoint setSavepoint() throws SQLException { throw new SQLException("Not implemented."); } @Override public java.sql.Savepoint setSavepoint(final String name) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setSchema(final String schema) throws SQLException { checkOpen(); this.schema= schema; } public void setSqlExceptionOnClose(final boolean sqlExceptionOnClose) { this.sqlExceptionOnClose = sqlExceptionOnClose; } @Override public void setTransactionIsolation(final int level) throws SQLException { checkOpen(); this.transactionIsolation = level; } @Override public void setTypeMap(final Map> map) throws SQLException { checkOpen(); this.typeMap = map; } public void setWarnings(final SQLWarning warning) { this.warnings = warning; } @Override public T unwrap(final Class iface) throws SQLException { throw new SQLException("Not implemented."); } } TesterConnectionFactory.java000066400000000000000000000046651472045345700341110ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; import java.util.Properties; /** * Dummy {@link ConnectionFactory} for testing purpose. */ public class TesterConnectionFactory implements ConnectionFactory { private final String connectionString; private final Driver driver; private final Properties properties; /** * Constructs a connection factory for a given Driver. * * @param driver The Driver. * @param connectString The connection string. * @param properties The connection properties. */ public TesterConnectionFactory(final Driver driver, final String connectString, final Properties properties) { this.driver = driver; this.connectionString = connectString; this.properties = properties; } @Override public Connection createConnection() throws SQLException { final Connection conn = driver.connect(connectionString, properties); doSomething(conn); return conn; } private void doSomething(final Connection conn) { // do something } /** * @return The connection String. */ public String getConnectionString() { return connectionString; } /** * @return The Driver. */ public Driver getDriver() { return driver; } /** * @return The Properties. */ public Properties getProperties() { return properties; } @Override public String toString() { return this.getClass().getName() + " [" + driver + ";" + connectionString + ";" + properties + "]"; } } TesterDatabaseMetaData.java000066400000000000000000000543331472045345700335640ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.RowIdLifetime; import java.sql.SQLException; /** * Dummy {@link DatabaseMetaData} for testing purposes. Implements only those * methods required by the test cases. */ public class TesterDatabaseMetaData implements DatabaseMetaData { @Override public boolean allProceduresAreCallable() throws SQLException { return false; } @Override public boolean allTablesAreSelectable() throws SQLException { return false; } @Override public boolean autoCommitFailureClosesAllResultSets() throws SQLException { return false; } @Override public boolean dataDefinitionCausesTransactionCommit() throws SQLException { return false; } @Override public boolean dataDefinitionIgnoredInTransactions() throws SQLException { return false; } @Override public boolean deletesAreDetected(final int type) throws SQLException { return false; } @Override public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { return false; } @Override public boolean generatedKeyAlwaysReturned() throws SQLException { return false; } @Override public ResultSet getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, final String attributeNamePattern) throws SQLException { return null; } @Override public ResultSet getBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, final boolean nullable) throws SQLException { return null; } @Override public ResultSet getCatalogs() throws SQLException { return null; } @Override public String getCatalogSeparator() throws SQLException { return null; } @Override public String getCatalogTerm() throws SQLException { return null; } @Override public ResultSet getClientInfoProperties() throws SQLException { return null; } @Override public ResultSet getColumnPrivileges(final String catalog, final String schema, final String table, final String columnNamePattern) throws SQLException { return null; } @Override public ResultSet getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { return null; } @Override public Connection getConnection() throws SQLException { return null; } @Override public ResultSet getCrossReference(final String parentCatalog, final String parentSchema, final String parentTable, final String foreignCatalog, final String foreignSchema, final String foreignTable) throws SQLException { return null; } @Override public int getDatabaseMajorVersion() throws SQLException { return 0; } @Override public int getDatabaseMinorVersion() throws SQLException { return 0; } @Override public String getDatabaseProductName() throws SQLException { return null; } @Override public String getDatabaseProductVersion() throws SQLException { return null; } @Override public int getDefaultTransactionIsolation() throws SQLException { return 0; } @Override public int getDriverMajorVersion() { return 0; } @Override public int getDriverMinorVersion() { return 0; } @Override public String getDriverName() throws SQLException { return null; } @Override public String getDriverVersion() throws SQLException { return null; } @Override public ResultSet getExportedKeys(final String catalog, final String schema, final String table) throws SQLException { return null; } @Override public String getExtraNameCharacters() throws SQLException { return null; } @Override public ResultSet getFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, final String columnNamePattern) throws SQLException { return null; } @Override public ResultSet getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern) throws SQLException { return null; } @Override public String getIdentifierQuoteString() throws SQLException { return null; } @Override public ResultSet getImportedKeys(final String catalog, final String schema, final String table) throws SQLException { return null; } @Override public ResultSet getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, final boolean approximate) throws SQLException { return null; } @Override public int getJDBCMajorVersion() throws SQLException { return 0; } @Override public int getJDBCMinorVersion() throws SQLException { return 0; } @Override public int getMaxBinaryLiteralLength() throws SQLException { return 0; } @Override public int getMaxCatalogNameLength() throws SQLException { return 0; } @Override public int getMaxCharLiteralLength() throws SQLException { return 0; } @Override public int getMaxColumnNameLength() throws SQLException { return 0; } @Override public int getMaxColumnsInGroupBy() throws SQLException { return 0; } @Override public int getMaxColumnsInIndex() throws SQLException { return 0; } @Override public int getMaxColumnsInOrderBy() throws SQLException { return 0; } @Override public int getMaxColumnsInSelect() throws SQLException { return 0; } @Override public int getMaxColumnsInTable() throws SQLException { return 0; } @Override public int getMaxConnections() throws SQLException { return 0; } @Override public int getMaxCursorNameLength() throws SQLException { return 0; } @Override public int getMaxIndexLength() throws SQLException { return 0; } @Override public int getMaxProcedureNameLength() throws SQLException { return 0; } @Override public int getMaxRowSize() throws SQLException { return 0; } @Override public int getMaxSchemaNameLength() throws SQLException { return 0; } @Override public int getMaxStatementLength() throws SQLException { return 0; } @Override public int getMaxStatements() throws SQLException { return 0; } @Override public int getMaxTableNameLength() throws SQLException { return 0; } @Override public int getMaxTablesInSelect() throws SQLException { return 0; } @Override public int getMaxUserNameLength() throws SQLException { return 0; } @Override public String getNumericFunctions() throws SQLException { return null; } @Override public ResultSet getPrimaryKeys(final String catalog, final String schema, final String table) throws SQLException { return null; } @Override public ResultSet getProcedureColumns(final String catalog, final String schemaPattern, final String procedureNamePattern, final String columnNamePattern) throws SQLException { return null; } @Override public ResultSet getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) throws SQLException { return null; } @Override public String getProcedureTerm() throws SQLException { return null; } @Override public ResultSet getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { return null; } @Override public int getResultSetHoldability() throws SQLException { return 0; } @Override public RowIdLifetime getRowIdLifetime() throws SQLException { return null; } @Override public ResultSet getSchemas() throws SQLException { return new TesterResultSet(null); } @Override public ResultSet getSchemas(final String catalog, final String schemaPattern) throws SQLException { return null; } @Override public String getSchemaTerm() throws SQLException { return null; } @Override public String getSearchStringEscape() throws SQLException { return null; } @Override public String getSQLKeywords() throws SQLException { return null; } @Override public int getSQLStateType() throws SQLException { return 0; } @Override public String getStringFunctions() throws SQLException { return null; } @Override public ResultSet getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { return null; } @Override public ResultSet getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern) throws SQLException { return null; } @Override public String getSystemFunctions() throws SQLException { return null; } @Override public ResultSet getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { return null; } @Override public ResultSet getTables(final String catalog, final String schemaPattern, final String tableNamePattern, final String[] types) throws SQLException { return null; } @Override public ResultSet getTableTypes() throws SQLException { return null; } @Override public String getTimeDateFunctions() throws SQLException { return null; } @Override public ResultSet getTypeInfo() throws SQLException { return null; } @Override public ResultSet getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, final int[] types) throws SQLException { return null; } @Override public String getURL() throws SQLException { return null; } @Override public String getUserName() throws SQLException { return null; } @Override public ResultSet getVersionColumns(final String catalog, final String schema, final String table) throws SQLException { return null; } @Override public boolean insertsAreDetected(final int type) throws SQLException { return false; } @Override public boolean isCatalogAtStart() throws SQLException { return false; } @Override public boolean isReadOnly() throws SQLException { return false; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } @Override public boolean locatorsUpdateCopy() throws SQLException { return false; } @Override public boolean nullPlusNonNullIsNull() throws SQLException { return false; } @Override public boolean nullsAreSortedAtEnd() throws SQLException { return false; } @Override public boolean nullsAreSortedAtStart() throws SQLException { return false; } @Override public boolean nullsAreSortedHigh() throws SQLException { return false; } @Override public boolean nullsAreSortedLow() throws SQLException { return false; } @Override public boolean othersDeletesAreVisible(final int type) throws SQLException { return false; } @Override public boolean othersInsertsAreVisible(final int type) throws SQLException { return false; } @Override public boolean othersUpdatesAreVisible(final int type) throws SQLException { return false; } @Override public boolean ownDeletesAreVisible(final int type) throws SQLException { return false; } @Override public boolean ownInsertsAreVisible(final int type) throws SQLException { return false; } @Override public boolean ownUpdatesAreVisible(final int type) throws SQLException { return false; } @Override public boolean storesLowerCaseIdentifiers() throws SQLException { return false; } @Override public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { return false; } @Override public boolean storesMixedCaseIdentifiers() throws SQLException { return false; } @Override public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { return false; } @Override public boolean storesUpperCaseIdentifiers() throws SQLException { return false; } @Override public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { return false; } @Override public boolean supportsAlterTableWithAddColumn() throws SQLException { return false; } @Override public boolean supportsAlterTableWithDropColumn() throws SQLException { return false; } @Override public boolean supportsANSI92EntryLevelSQL() throws SQLException { return false; } @Override public boolean supportsANSI92FullSQL() throws SQLException { return false; } @Override public boolean supportsANSI92IntermediateSQL() throws SQLException { return false; } @Override public boolean supportsBatchUpdates() throws SQLException { return false; } @Override public boolean supportsCatalogsInDataManipulation() throws SQLException { return false; } @Override public boolean supportsCatalogsInIndexDefinitions() throws SQLException { return false; } @Override public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { return false; } @Override public boolean supportsCatalogsInProcedureCalls() throws SQLException { return false; } @Override public boolean supportsCatalogsInTableDefinitions() throws SQLException { return false; } @Override public boolean supportsColumnAliasing() throws SQLException { return false; } @Override public boolean supportsConvert() throws SQLException { return false; } @Override public boolean supportsConvert(final int fromType, final int toType) throws SQLException { return false; } @Override public boolean supportsCoreSQLGrammar() throws SQLException { return false; } @Override public boolean supportsCorrelatedSubqueries() throws SQLException { return false; } @Override public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { return false; } @Override public boolean supportsDataManipulationTransactionsOnly() throws SQLException { return false; } @Override public boolean supportsDifferentTableCorrelationNames() throws SQLException { return false; } @Override public boolean supportsExpressionsInOrderBy() throws SQLException { return false; } @Override public boolean supportsExtendedSQLGrammar() throws SQLException { return false; } @Override public boolean supportsFullOuterJoins() throws SQLException { return false; } @Override public boolean supportsGetGeneratedKeys() throws SQLException { return false; } @Override public boolean supportsGroupBy() throws SQLException { return false; } @Override public boolean supportsGroupByBeyondSelect() throws SQLException { return false; } @Override public boolean supportsGroupByUnrelated() throws SQLException { return false; } @Override public boolean supportsIntegrityEnhancementFacility() throws SQLException { return false; } @Override public boolean supportsLikeEscapeClause() throws SQLException { return false; } @Override public boolean supportsLimitedOuterJoins() throws SQLException { return false; } @Override public boolean supportsMinimumSQLGrammar() throws SQLException { return false; } @Override public boolean supportsMixedCaseIdentifiers() throws SQLException { return false; } @Override public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { return false; } @Override public boolean supportsMultipleOpenResults() throws SQLException { return false; } @Override public boolean supportsMultipleResultSets() throws SQLException { return false; } @Override public boolean supportsMultipleTransactions() throws SQLException { return false; } @Override public boolean supportsNamedParameters() throws SQLException { return false; } @Override public boolean supportsNonNullableColumns() throws SQLException { return false; } @Override public boolean supportsOpenCursorsAcrossCommit() throws SQLException { return false; } @Override public boolean supportsOpenCursorsAcrossRollback() throws SQLException { return false; } @Override public boolean supportsOpenStatementsAcrossCommit() throws SQLException { return false; } @Override public boolean supportsOpenStatementsAcrossRollback() throws SQLException { return false; } @Override public boolean supportsOrderByUnrelated() throws SQLException { return false; } @Override public boolean supportsOuterJoins() throws SQLException { return false; } @Override public boolean supportsPositionedDelete() throws SQLException { return false; } @Override public boolean supportsPositionedUpdate() throws SQLException { return false; } @Override public boolean supportsResultSetConcurrency(final int type, final int concurrency) throws SQLException { return false; } @Override public boolean supportsResultSetHoldability(final int holdability) throws SQLException { return false; } @Override public boolean supportsResultSetType(final int type) throws SQLException { return false; } @Override public boolean supportsSavepoints() throws SQLException { return false; } @Override public boolean supportsSchemasInDataManipulation() throws SQLException { return false; } @Override public boolean supportsSchemasInIndexDefinitions() throws SQLException { return false; } @Override public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { return false; } @Override public boolean supportsSchemasInProcedureCalls() throws SQLException { return false; } @Override public boolean supportsSchemasInTableDefinitions() throws SQLException { return false; } @Override public boolean supportsSelectForUpdate() throws SQLException { return false; } @Override public boolean supportsStatementPooling() throws SQLException { return false; } @Override public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { return false; } @Override public boolean supportsStoredProcedures() throws SQLException { return false; } @Override public boolean supportsSubqueriesInComparisons() throws SQLException { return false; } @Override public boolean supportsSubqueriesInExists() throws SQLException { return false; } @Override public boolean supportsSubqueriesInIns() throws SQLException { return false; } @Override public boolean supportsSubqueriesInQuantifieds() throws SQLException { return false; } @Override public boolean supportsTableCorrelationNames() throws SQLException { return false; } @Override public boolean supportsTransactionIsolationLevel(final int level) throws SQLException { return false; } @Override public boolean supportsTransactions() throws SQLException { return false; } @Override public boolean supportsUnion() throws SQLException { return false; } @Override public boolean supportsUnionAll() throws SQLException { return false; } @Override public T unwrap(final Class iface) throws SQLException { return null; } @Override public boolean updatesAreDetected(final int type) throws SQLException { return false; } @Override public boolean usesLocalFilePerTable() throws SQLException { return false; } @Override public boolean usesLocalFiles() throws SQLException { return false; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TesterDriver.java000066400000000000000000000115711472045345700317660ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.Properties; import java.util.logging.Logger; /** * Mock object implementing the {@link Driver} interface. * Returns {@code TestConnection}'s from getConnection methods. * Valid user name, password combinations are: * * * * * * * *
userpassword
foobar
u1p1
u2p2
usernamepassword
*/ public class TesterDriver implements Driver { static TesterDriver INSTANCE = new TesterDriver(); private static final Properties validUserPasswords = new Properties(); static { try { DriverManager.registerDriver(new TesterDriver()); } catch (final Exception e) { // ignore } validUserPasswords.put("foo", "bar"); validUserPasswords.put("u1", "p1"); validUserPasswords.put("u2", "p2"); validUserPasswords.put("userName", "password"); } private static final String CONNECT_STRING = "jdbc:apache:commons:testdriver"; // version numbers private static final int MAJOR_VERSION = 1; private static final int MINOR_VERSION = 0; /** * TesterDriver specific method to add users to the list of valid users */ public static void addUser(final String userName, final String password) { synchronized (validUserPasswords) { validUserPasswords.put(userName, password); } } @Override public boolean acceptsURL(final String url) throws SQLException { return url != null && url.startsWith(CONNECT_STRING); } private void assertValidUserPassword(final String userName, final String password) throws SQLException { if (userName == null){ throw new SQLException("user name cannot be null."); } synchronized (validUserPasswords) { final String realPassword = validUserPasswords.getProperty(userName); if (realPassword == null) { throw new SQLException(userName + " is not a valid user name."); } if (!realPassword.equals(password)) { throw new SQLException(password + " is not the correct password for " + userName + ". The correct password is " + realPassword); } } } @Override public Connection connect(final String url, final Properties info) throws SQLException { //return (acceptsURL(url) ? new TesterConnection() : null); Connection conn = null; if (acceptsURL(url)) { String userName = "test"; String password = "test"; if (info != null) { userName = info.getProperty(Constants.KEY_USER); password = info.getProperty(Constants.KEY_PASSWORD); if (userName == null) { final String[] parts = url.split(";"); userName = parts[1]; userName = userName.split("=")[1]; password = parts[2]; password = password.split("=")[1]; } assertValidUserPassword(userName, password); } conn = new TesterConnection(userName, password); } return conn; } @Override public int getMajorVersion() { return MAJOR_VERSION; } @Override public int getMinorVersion() { return MINOR_VERSION; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } @Override public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) { return new DriverPropertyInfo[0]; } @Override public boolean jdbcCompliant() { return true; } } TesterPreparedStatement.java000066400000000000000000000370401472045345700341020ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLType; import java.sql.SQLXML; import java.util.Calendar; /** * A dummy {@link PreparedStatement}, for testing purposes. */ public class TesterPreparedStatement extends TesterStatement implements PreparedStatement { private final ResultSetMetaData resultSetMetaData = null; private String sql; private String catalog; private int autoGeneratedKeys = 1; private int[] columnIndexes; private String[] columnNames; public TesterPreparedStatement(final Connection conn) { super(conn); try { this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql) { super(conn); this.sql = sql; try { this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql, final int autoGeneratedKeys) { super(conn); this.sql = sql; this.autoGeneratedKeys = autoGeneratedKeys; try { this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql, final int resultSetType, final int resultSetConcurrency) { super(conn, resultSetType, resultSetConcurrency); this.sql = sql; try { this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { super(conn, resultSetType, resultSetConcurrency, resultSetHoldability); this.sql = sql; try { this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql, final int[] columnIndexes) { super(conn); this.sql = sql; this.columnIndexes = columnIndexes; try { this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql, final String[] columnNames) { super(conn); this.sql = sql; this.columnNames = columnNames; try { this.catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } @Override public void addBatch() throws SQLException { checkOpen(); } @Override public void clearParameters() throws SQLException { checkOpen(); } @Override public boolean execute() throws SQLException { checkOpen(); return true; } @Override public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); return true; } @Override public boolean execute(final String sl, final int[] columnIndexes) throws SQLException { checkOpen(); return true; } @Override public boolean execute(final String sql, final String[] columnNames) throws SQLException { checkOpen(); return true; } @Override public long executeLargeUpdate() throws SQLException { checkOpen(); return rowsUpdated; } @Override public long executeLargeUpdate(final String sql) throws SQLException { checkOpen(); return rowsUpdated; } @Override public long executeLargeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); return 0; } @Override public long executeLargeUpdate(final String sql, final int[] columnIndexes) throws SQLException { checkOpen(); return 0; } @Override public long executeLargeUpdate(final String sql, final String[] columnNames) throws SQLException { checkOpen(); return 0; } @Override public ResultSet executeQuery() throws SQLException { checkOpen(); if ("null".equals(sql)) { return null; } if (queryTimeout > 0 && queryTimeout < 5) { // Simulate timeout if queryTimout is set to less than 5 seconds throw new SQLException("query timeout"); } return new TesterResultSet(this, resultSetType, resultSetConcurrency); } @Override public ResultSet executeQuery(final String sql) throws SQLException { checkOpen(); if ("null".equals(sql)) { return null; } return new TesterResultSet(this, resultSetType, resultSetConcurrency); } @Override public int executeUpdate() throws SQLException { checkOpen(); return (int) rowsUpdated; } @Override public int executeUpdate(final String sql) throws SQLException { checkOpen(); return (int) rowsUpdated; } @Override public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); return 0; } @Override public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException { checkOpen(); return 0; } @Override public int executeUpdate(final String sql, final String[] columnNames) throws SQLException { checkOpen(); return 0; } public int getAutoGeneratedKeys() { return autoGeneratedKeys; } public String getCatalog() { return catalog; } public int[] getColumnIndexes() { return columnIndexes; } public String[] getColumnNames() { return columnNames; } @Override public ResultSet getGeneratedKeys() throws SQLException { return new TesterResultSet(this, resultSetType, resultSetConcurrency); } @Override public ResultSetMetaData getMetaData() throws SQLException { checkOpen(); return resultSetMetaData; } @Override public boolean getMoreResults(final int current) throws SQLException { throw new SQLException("Not implemented."); } @Override public java.sql.ParameterMetaData getParameterMetaData() throws SQLException { throw new SQLException("Not implemented."); } /** For junit test only */ public String getSql() { return sql; } @Override public void setArray (final int i, final Array x) throws SQLException { checkOpen(); } @Override public void setAsciiStream(final int parameterIndex, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setAsciiStream(final int parameterIndex, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setAsciiStream(final int parameterIndex, final java.io.InputStream x, final int length) throws SQLException { checkOpen(); } @Override public void setBigDecimal(final int parameterIndex, final BigDecimal x) throws SQLException { checkOpen(); } @Override public void setBinaryStream(final int parameterIndex, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setBinaryStream(final int parameterIndex, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setBinaryStream(final int parameterIndex, final java.io.InputStream x, final int length) throws SQLException { checkOpen(); } @Override public void setBlob (final int i, final Blob x) throws SQLException { checkOpen(); } @Override public void setBlob(final int parameterIndex, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setBlob(final int parameterIndex, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setBoolean(final int parameterIndex, final boolean x) throws SQLException { checkOpen(); } @Override public void setByte(final int parameterIndex, final byte x) throws SQLException { checkOpen(); } @Override public void setBytes(final int parameterIndex, final byte[] x) throws SQLException { checkOpen(); } @Override public void setCharacterStream(final int parameterIndex, final java.io.Reader reader, final int length) throws SQLException { checkOpen(); } @Override public void setCharacterStream(final int parameterIndex, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setCharacterStream(final int parameterIndex, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setClob (final int i, final Clob x) throws SQLException { checkOpen(); } @Override public void setClob(final int parameterIndex, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setDate(final int parameterIndex, final java.sql.Date x) throws SQLException { checkOpen(); } @Override public void setDate(final int parameterIndex, final java.sql.Date x, final Calendar cal) throws SQLException { checkOpen(); } @Override public void setDouble(final int parameterIndex, final double x) throws SQLException { checkOpen(); } @Override public void setFloat(final int parameterIndex, final float x) throws SQLException { checkOpen(); } @Override public void setInt(final int parameterIndex, final int x) throws SQLException { checkOpen(); } @Override public void setLong(final int parameterIndex, final long x) throws SQLException { checkOpen(); } @Override public void setNCharacterStream(final int parameterIndex, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setNCharacterStream(final int parameterIndex, final Reader value, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setNClob(final int parameterIndex, final NClob value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setNClob(final int parameterIndex, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setNClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setNString(final int parameterIndex, final String value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setNull(final int parameterIndex, final int sqlType) throws SQLException { checkOpen(); } @Override public void setNull (final int paramIndex, final int sqlType, final String typeName) throws SQLException { checkOpen(); } @Override public void setObject(final int parameterIndex, final Object x) throws SQLException { checkOpen(); } @Override public void setObject(final int parameterIndex, final Object x, final int targetSqlType) throws SQLException { checkOpen(); } @Override public void setObject(final int parameterIndex, final Object x, final int targetSqlType, final int scale) throws SQLException { checkOpen(); } @Override public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType) throws SQLException { checkOpen(); } @Override public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { checkOpen(); } @Override public void setRef (final int i, final Ref x) throws SQLException { checkOpen(); } @Override public void setRowId(final int parameterIndex, final RowId value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setShort(final int parameterIndex, final short x) throws SQLException { checkOpen(); } @Override public void setSQLXML(final int parameterIndex, final SQLXML value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setString(final int parameterIndex, final String x) throws SQLException { checkOpen(); } @Override public void setTime(final int parameterIndex, final java.sql.Time x) throws SQLException { checkOpen(); } @Override public void setTime(final int parameterIndex, final java.sql.Time x, final Calendar cal) throws SQLException { checkOpen(); } @Override public void setTimestamp(final int parameterIndex, final java.sql.Timestamp x) throws SQLException { checkOpen(); } @Override public void setTimestamp(final int parameterIndex, final java.sql.Timestamp x, final Calendar cal) throws SQLException { checkOpen(); } /** @deprecated */ @Deprecated @Override public void setUnicodeStream(final int parameterIndex, final java.io.InputStream x, final int length) throws SQLException { checkOpen(); } @Override public void setURL(final int parameterIndex, final java.net.URL x) throws SQLException { throw new SQLException("Not implemented."); } @Override public String toString() { return sql; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TesterResultSet.java000066400000000000000000001014431472045345700324630ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.NClob; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLType; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Statement; import java.util.Calendar; import java.util.Map; /** * A dummy {@link ResultSet}, for testing purposes. */ public class TesterResultSet extends AbandonedTrace implements ResultSet { protected int _type = ResultSet.TYPE_FORWARD_ONLY; protected int _concurrency = ResultSet.CONCUR_READ_ONLY; protected Object[][] _data; protected int _currentRow = -1; protected Statement _statement; protected int _rowsLeft = 2; protected boolean _open = true; protected boolean _sqlExceptionOnClose; public TesterResultSet(final Statement stmt) { _statement = stmt; } public TesterResultSet(final Statement stmt, final int type, final int concurrency) { _statement = stmt; _data = null; _type = type; _concurrency = concurrency; } public TesterResultSet(final Statement stmt, final Object[][] data) { _statement = stmt; _data = data; } @Override public boolean absolute(final int row) throws SQLException { checkOpen(); return false; } @Override public void afterLast() throws SQLException { checkOpen(); } @Override public void beforeFirst() throws SQLException { checkOpen(); } @Override public void cancelRowUpdates() throws SQLException { checkOpen(); } protected void checkOpen() throws SQLException { if (!_open) { throw new SQLException("ResultSet is closed."); } } @Override public void clearWarnings() throws SQLException { checkOpen(); } @Override public void close() throws SQLException { if (_sqlExceptionOnClose) { throw new SQLException("TestSQLExceptionOnClose"); } if (!_open) { return; } // Not all result sets are generated from statements eg DatabaseMetaData if (_statement != null) { ((TesterStatement) _statement).resultSet = null; } _open = false; } @Override public void deleteRow() throws SQLException { checkOpen(); } @Override public int findColumn(final String columnName) throws SQLException { checkOpen(); return 1; } @Override public boolean first() throws SQLException { checkOpen(); return false; } @Override public Array getArray(final int i) throws SQLException { checkOpen(); return null; } @Override public Array getArray(final String colName) throws SQLException { checkOpen(); return null; } @Override public java.io.InputStream getAsciiStream(final int columnIndex) throws SQLException { checkOpen(); return null; } @Override public java.io.InputStream getAsciiStream(final String columnName) throws SQLException { checkOpen(); return null; } @Override public BigDecimal getBigDecimal(final int columnIndex) throws SQLException { checkOpen(); return new BigDecimal(columnIndex); } /** @deprecated */ @Deprecated @Override public BigDecimal getBigDecimal(final int columnIndex, final int scale) throws SQLException { checkOpen(); return new BigDecimal(columnIndex); } @Override public BigDecimal getBigDecimal(final String columnName) throws SQLException { checkOpen(); return new BigDecimal(columnName.hashCode()); } /** @deprecated */ @Deprecated @Override public BigDecimal getBigDecimal(final String columnName, final int scale) throws SQLException { checkOpen(); return new BigDecimal(columnName.hashCode()); } @Override public java.io.InputStream getBinaryStream(final int columnIndex) throws SQLException { checkOpen(); return null; } @Override public java.io.InputStream getBinaryStream(final String columnName) throws SQLException { checkOpen(); return null; } @Override public Blob getBlob(final int i) throws SQLException { checkOpen(); return null; } @Override public Blob getBlob(final String colName) throws SQLException { checkOpen(); return null; } @Override public boolean getBoolean(final int columnIndex) throws SQLException { checkOpen(); return true; } @Override public boolean getBoolean(final String columnName) throws SQLException { checkOpen(); return true; } @Override public byte getByte(final int columnIndex) throws SQLException { checkOpen(); return (byte) columnIndex; } @Override public byte getByte(final String columnName) throws SQLException { checkOpen(); return (byte) columnName.hashCode(); } @Override public byte[] getBytes(final int columnIndex) throws SQLException { checkOpen(); return new byte[] { (byte) columnIndex }; } @Override public byte[] getBytes(final String columnName) throws SQLException { checkOpen(); return columnName.getBytes(StandardCharsets.UTF_8); } @Override public java.io.Reader getCharacterStream(final int columnIndex) throws SQLException { checkOpen(); return null; } @Override public java.io.Reader getCharacterStream(final String columnName) throws SQLException { checkOpen(); return null; } @Override public Clob getClob(final int i) throws SQLException { checkOpen(); return null; } @Override public Clob getClob(final String colName) throws SQLException { checkOpen(); return null; } @Override public int getConcurrency() throws SQLException { return this._concurrency; } @Override public String getCursorName() throws SQLException { checkOpen(); return null; } @Override public java.sql.Date getDate(final int columnIndex) throws SQLException { checkOpen(); return null; } @Override public java.sql.Date getDate(final int columnIndex, final Calendar cal) throws SQLException { checkOpen(); return null; } @Override public java.sql.Date getDate(final String columnName) throws SQLException { checkOpen(); return null; } @Override public java.sql.Date getDate(final String columnName, final Calendar cal) throws SQLException { checkOpen(); return null; } @Override public double getDouble(final int columnIndex) throws SQLException { checkOpen(); return columnIndex; } @Override public double getDouble(final String columnName) throws SQLException { checkOpen(); return columnName.hashCode(); } @Override public int getFetchDirection() throws SQLException { checkOpen(); return 1; } @Override public int getFetchSize() throws SQLException { checkOpen(); return 2; } @Override public float getFloat(final int columnIndex) throws SQLException { checkOpen(); return columnIndex; } @Override public float getFloat(final String columnName) throws SQLException { checkOpen(); return columnName.hashCode(); } @Override public int getHoldability() throws SQLException { throw new SQLException("Not implemented."); } @Override public int getInt(final int columnIndex) throws SQLException { checkOpen(); return (short) columnIndex; } @Override public int getInt(final String columnName) throws SQLException { checkOpen(); return columnName.hashCode(); } @Override public long getLong(final int columnIndex) throws SQLException { checkOpen(); return columnIndex; } @Override public long getLong(final String columnName) throws SQLException { checkOpen(); return columnName.hashCode(); } @Override public ResultSetMetaData getMetaData() throws SQLException { checkOpen(); return null; } @Override public Reader getNCharacterStream(final int columnIndex) throws SQLException { throw new SQLException("Not implemented."); } @Override public Reader getNCharacterStream(final String columnLabel) throws SQLException { throw new SQLException("Not implemented."); } @Override public NClob getNClob(final int columnIndex) throws SQLException { throw new SQLException("Not implemented."); } @Override public NClob getNClob(final String columnLabel) throws SQLException { throw new SQLException("Not implemented."); } @Override public String getNString(final int columnIndex) throws SQLException { throw new SQLException("Not implemented."); } @Override public String getNString(final String columnLabel) throws SQLException { throw new SQLException("Not implemented."); } @Override public Object getObject(final int columnIndex) throws SQLException { checkOpen(); if (_data != null) { return _data[_currentRow][columnIndex - 1]; } return new Object(); } @Override public T getObject(final int columnIndex, final Class type) throws SQLException { throw new SQLException("Not implemented."); } @Override public Object getObject(final int i, final Map> map) throws SQLException { checkOpen(); return new Object(); } @Override public Object getObject(final String columnName) throws SQLException { checkOpen(); return columnName; } @Override public T getObject(final String columnLabel, final Class type) throws SQLException { throw new SQLException("Not implemented."); } @Override public Object getObject(final String colName, final Map> map) throws SQLException { checkOpen(); return colName; } @Override public Ref getRef(final int i) throws SQLException { checkOpen(); return null; } @Override public Ref getRef(final String colName) throws SQLException { checkOpen(); return null; } @Override public int getRow() throws SQLException { checkOpen(); return 3 - _rowsLeft; } @Override public RowId getRowId(final int columnIndex) throws SQLException { throw new SQLException("Not implemented."); } @Override public RowId getRowId(final String columnLabel) throws SQLException { throw new SQLException("Not implemented."); } @Override public short getShort(final int columnIndex) throws SQLException { checkOpen(); return (short) columnIndex; } @Override public short getShort(final String columnName) throws SQLException { checkOpen(); return (short) columnName.hashCode(); } @Override public SQLXML getSQLXML(final int columnIndex) throws SQLException { throw new SQLException("Not implemented."); } @Override public SQLXML getSQLXML(final String columnLabel) throws SQLException { throw new SQLException("Not implemented."); } @Override public Statement getStatement() throws SQLException { checkOpen(); return _statement; } @Override public String getString(final int columnIndex) throws SQLException { checkOpen(); if (columnIndex == -1) { throw new SQLException("broken connection"); } if (_data != null) { return (String) getObject(columnIndex); } return "String" + columnIndex; } @Override public String getString(final String columnName) throws SQLException { checkOpen(); return columnName; } @Override public java.sql.Time getTime(final int columnIndex) throws SQLException { checkOpen(); return null; } @Override public java.sql.Time getTime(final int columnIndex, final Calendar cal) throws SQLException { checkOpen(); return null; } @Override public java.sql.Time getTime(final String columnName) throws SQLException { checkOpen(); return null; } @Override public java.sql.Time getTime(final String columnName, final Calendar cal) throws SQLException { checkOpen(); return null; } @Override public java.sql.Timestamp getTimestamp(final int columnIndex) throws SQLException { checkOpen(); return null; } @Override public java.sql.Timestamp getTimestamp(final int columnIndex, final Calendar cal) throws SQLException { checkOpen(); return null; } @Override public java.sql.Timestamp getTimestamp(final String columnName) throws SQLException { checkOpen(); return null; } @Override public java.sql.Timestamp getTimestamp(final String columnName, final Calendar cal) throws SQLException { checkOpen(); return null; } @Override public int getType() throws SQLException { return this._type; } /** @deprecated */ @Deprecated @Override public java.io.InputStream getUnicodeStream(final int columnIndex) throws SQLException { checkOpen(); return null; } /** @deprecated */ @Deprecated @Override public java.io.InputStream getUnicodeStream(final String columnName) throws SQLException { checkOpen(); return null; } @Override public java.net.URL getURL(final int columnIndex) throws SQLException { throw new SQLException("Not implemented."); } @Override public java.net.URL getURL(final String columnName) throws SQLException { throw new SQLException("Not implemented."); } @Override public SQLWarning getWarnings() throws SQLException { checkOpen(); return null; } @Override public void insertRow() throws SQLException { checkOpen(); } @Override public boolean isAfterLast() throws SQLException { checkOpen(); return _rowsLeft < 0; } @Override public boolean isBeforeFirst() throws SQLException { checkOpen(); return _rowsLeft == 2; } @Override public boolean isClosed() throws SQLException { return !_open; } @Override public boolean isFirst() throws SQLException { checkOpen(); return _rowsLeft == 1; } @Override public boolean isLast() throws SQLException { checkOpen(); return _rowsLeft == 0; } public boolean isSqlExceptionOnClose() { return _sqlExceptionOnClose; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { throw new SQLException("Not implemented."); } @Override public boolean last() throws SQLException { checkOpen(); return false; } @Override public void moveToCurrentRow() throws SQLException { checkOpen(); } @Override public void moveToInsertRow() throws SQLException { checkOpen(); } @Override public boolean next() throws SQLException { checkOpen(); if (_data != null) { _currentRow++; return _currentRow < _data.length; } return --_rowsLeft > 0; } @Override public boolean previous() throws SQLException { checkOpen(); return false; } @Override public void refreshRow() throws SQLException { checkOpen(); } @Override public boolean relative(final int rows) throws SQLException { checkOpen(); return false; } @Override public boolean rowDeleted() throws SQLException { checkOpen(); return false; } @Override public boolean rowInserted() throws SQLException { checkOpen(); return false; } @Override public boolean rowUpdated() throws SQLException { checkOpen(); return false; } @Override public void setFetchDirection(final int direction) throws SQLException { checkOpen(); } @Override public void setFetchSize(final int rows) throws SQLException { checkOpen(); } public void setSqlExceptionOnClose(final boolean sqlExceptionOnClose) { this._sqlExceptionOnClose = sqlExceptionOnClose; } @Override public T unwrap(final Class iface) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateArray(final int columnIndex, final java.sql.Array x) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateArray(final String columnName, final java.sql.Array x) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateAsciiStream(final int columnIndex, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateAsciiStream(final int columnIndex, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateAsciiStream(final int columnIndex, final java.io.InputStream x, final int length) throws SQLException { checkOpen(); } @Override public void updateAsciiStream(final String columnLabel, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateAsciiStream(final String columnLabel, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateAsciiStream(final String columnName, final java.io.InputStream x, final int length) throws SQLException { checkOpen(); } @Override public void updateBigDecimal(final int columnIndex, final BigDecimal x) throws SQLException { checkOpen(); } @Override public void updateBigDecimal(final String columnName, final BigDecimal x) throws SQLException { checkOpen(); } @Override public void updateBinaryStream(final int columnIndex, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBinaryStream(final int columnIndex, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBinaryStream(final int columnIndex, final java.io.InputStream x, final int length) throws SQLException { checkOpen(); } @Override public void updateBinaryStream(final String columnLabel, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBinaryStream(final String columnLabel, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBinaryStream(final String columnName, final java.io.InputStream x, final int length) throws SQLException { checkOpen(); } @Override public void updateBlob(final int columnIndex, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBlob(final int columnIndex, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBlob(final int columnIndex, final java.sql.Blob x) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBlob(final String columnLabel, final InputStream inputStream) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBlob(final String columnLabel, final InputStream inputStream, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBlob(final String columnName, final java.sql.Blob x) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateBoolean(final int columnIndex, final boolean x) throws SQLException { checkOpen(); } @Override public void updateBoolean(final String columnName, final boolean x) throws SQLException { checkOpen(); } @Override public void updateByte(final int columnIndex, final byte x) throws SQLException { checkOpen(); } @Override public void updateByte(final String columnName, final byte x) throws SQLException { checkOpen(); } @Override public void updateBytes(final int columnIndex, final byte[] x) throws SQLException { checkOpen(); } @Override public void updateBytes(final String columnName, final byte[] x) throws SQLException { checkOpen(); } @Override public void updateCharacterStream(final int columnIndex, final java.io.Reader x, final int length) throws SQLException { checkOpen(); } @Override public void updateCharacterStream(final int columnIndex, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateCharacterStream(final int columnIndex, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateCharacterStream(final String columnName, final java.io.Reader reader, final int length) throws SQLException { checkOpen(); } @Override public void updateCharacterStream(final String columnLabel, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateClob(final int columnIndex, final java.sql.Clob x) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateClob(final int columnIndex, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateClob(final int columnIndex, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateClob(final String columnName, final java.sql.Clob x) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateClob(final String columnLabel, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateClob(final String columnLabel, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateDate(final int columnIndex, final java.sql.Date x) throws SQLException { checkOpen(); } @Override public void updateDate(final String columnName, final java.sql.Date x) throws SQLException { checkOpen(); } @Override public void updateDouble(final int columnIndex, final double x) throws SQLException { checkOpen(); } @Override public void updateDouble(final String columnName, final double x) throws SQLException { checkOpen(); } @Override public void updateFloat(final int columnIndex, final float x) throws SQLException { checkOpen(); } @Override public void updateFloat(final String columnName, final float x) throws SQLException { checkOpen(); } @Override public void updateInt(final int columnIndex, final int x) throws SQLException { checkOpen(); } @Override public void updateInt(final String columnName, final int x) throws SQLException { checkOpen(); } @Override public void updateLong(final int columnIndex, final long x) throws SQLException { checkOpen(); } @Override public void updateLong(final String columnName, final long x) throws SQLException { checkOpen(); } @Override public void updateNCharacterStream(final int columnIndex, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNCharacterStream(final int columnIndex, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNCharacterStream(final String columnLabel, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNClob(final int columnIndex, final NClob value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNClob(final int columnIndex, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNClob(final int columnIndex, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNClob(final String columnLabel, final NClob value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNClob(final String columnLabel, final Reader reader) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNClob(final String columnLabel, final Reader reader, final long length) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNString(final int columnIndex, final String value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNString(final String columnLabel, final String value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateNull(final int columnIndex) throws SQLException { checkOpen(); } @Override public void updateNull(final String columnName) throws SQLException { checkOpen(); } @Override public void updateObject(final int columnIndex, final Object x) throws SQLException { checkOpen(); } @Override public void updateObject(final int columnIndex, final Object x, final int scale) throws SQLException { checkOpen(); } @Override public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType) throws SQLException { checkOpen(); } @Override public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { checkOpen(); } @Override public void updateObject(final String columnName, final Object x) throws SQLException { checkOpen(); } @Override public void updateObject(final String columnName, final Object x, final int scale) throws SQLException { checkOpen(); } @Override public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType) throws SQLException { checkOpen(); } @Override public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { checkOpen(); } @Override public void updateRef(final int columnIndex, final java.sql.Ref x) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateRef(final String columnName, final java.sql.Ref x) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateRow() throws SQLException { checkOpen(); } @Override public void updateRowId(final int columnIndex, final RowId value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateRowId(final String columnLabel, final RowId value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateShort(final int columnIndex, final short x) throws SQLException { checkOpen(); } @Override public void updateShort(final String columnName, final short x) throws SQLException { checkOpen(); } @Override public void updateSQLXML(final int columnIndex, final SQLXML value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateSQLXML(final String columnLabel, final SQLXML value) throws SQLException { throw new SQLException("Not implemented."); } @Override public void updateString(final int columnIndex, final String x) throws SQLException { checkOpen(); } @Override public void updateString(final String columnName, final String x) throws SQLException { checkOpen(); } @Override public void updateTime(final int columnIndex, final java.sql.Time x) throws SQLException { checkOpen(); } @Override public void updateTime(final String columnName, final java.sql.Time x) throws SQLException { checkOpen(); } @Override public void updateTimestamp(final int columnIndex, final java.sql.Timestamp x) throws SQLException { checkOpen(); } @Override public void updateTimestamp(final String columnName, final java.sql.Timestamp x) throws SQLException { checkOpen(); } @Override public boolean wasNull() throws SQLException { checkOpen(); return false; } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TesterStatement.java000066400000000000000000000257351472045345700325060ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; /** * A dummy {@link Statement}, for testing purposes. */ public class TesterStatement extends AbandonedTrace implements Statement { protected final Connection connection; protected boolean open = true; protected final long rowsUpdated = 1; protected final boolean executeResponse = true; protected int maxFieldSize = 1024; protected long maxRows = 1024; protected boolean escapeProcessing; protected int queryTimeout = 1000; protected String cursorName; protected int fetchDirection = 1; protected int fetchSize = 1; protected int resultSetConcurrency = 1; protected int resultSetType = 1; private int resultSetHoldability = 1; protected ResultSet resultSet; protected boolean sqlExceptionOnClose; public TesterStatement(final Connection connection) { this.connection = connection; } public TesterStatement(final Connection connection, final int resultSetType, final int resultSetConcurrency) { this.connection = connection; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; } public TesterStatement(final Connection connection, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { this.connection = connection; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; this.resultSetHoldability = resultSetHoldability; } @Override public void addBatch(final String sql) throws SQLException { checkOpen(); } @Override public void cancel() throws SQLException { checkOpen(); } protected void checkOpen() throws SQLException { if (!open) { throw new SQLException("Connection is closed."); } } @Override public void clearBatch() throws SQLException { checkOpen(); } @Override public void clearWarnings() throws SQLException { checkOpen(); } @Override public void close() throws SQLException { if (sqlExceptionOnClose) { throw new SQLException("TestSQLExceptionOnClose"); } // calling close twice has no effect if (!open) { return; } open = false; if (resultSet != null) { resultSet.close(); resultSet = null; } } @Override public void closeOnCompletion() throws SQLException { throw new SQLException("Not implemented."); } @Override public boolean execute(final String sql) throws SQLException { checkOpen(); if ("invalid".equals(sql)) { throw new SQLException("invalid query"); } return executeResponse; } @Override public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException { throw new SQLException("Not implemented."); } @Override public boolean execute(final String sql, final int[] columnIndexes) throws SQLException { throw new SQLException("Not implemented."); } @Override public boolean execute(final String sql, final String[] columnNames) throws SQLException { throw new SQLException("Not implemented."); } @Override public int[] executeBatch() throws SQLException { checkOpen(); return new int[0]; } @Override public long[] executeLargeBatch() throws SQLException { checkOpen(); return new long[0]; } @Override public long executeLargeUpdate(final String sql) throws SQLException { checkOpen(); return rowsUpdated; } @Override public long executeLargeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { throw new SQLException("Not implemented."); } @Override public long executeLargeUpdate(final String sql, final int[] columnIndexes) throws SQLException { throw new SQLException("Not implemented."); } @Override public long executeLargeUpdate(final String sql, final String[] columnNames) throws SQLException { throw new SQLException("Not implemented."); } @Override public ResultSet executeQuery(final String sql) throws SQLException { checkOpen(); switch (sql) { case "null": return null; case "invalid": throw new SQLException("invalid query"); case "broken": throw new SQLException("broken connection"); case "select username": { final String userName = ((TesterConnection) connection).getUserName(); final Object[][] data = { { userName } }; return new TesterResultSet(this, data); } default: break; } // Simulate timeout if queryTimout is set to less than 5 seconds if (queryTimeout > 0 && queryTimeout < 5) { throw new SQLException("query timeout"); } return new TesterResultSet(this); } @Override public int executeUpdate(final String sql) throws SQLException { checkOpen(); return (int) rowsUpdated; } @Override public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { throw new SQLException("Not implemented."); } @Override public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException { throw new SQLException("Not implemented."); } @Override public int executeUpdate(final String sql, final String[] columnNames) throws SQLException { throw new SQLException("Not implemented."); } @Override public Connection getConnection() throws SQLException { checkOpen(); return connection; } @Override public int getFetchDirection() throws SQLException { checkOpen(); return fetchDirection; } @Override public int getFetchSize() throws SQLException { checkOpen(); return fetchSize; } @Override public ResultSet getGeneratedKeys() throws SQLException { return new TesterResultSet(this); } @Override public long getLargeMaxRows() throws SQLException { checkOpen(); return maxRows; } @Override public long getLargeUpdateCount() throws SQLException { checkOpen(); return rowsUpdated; } @Override public int getMaxFieldSize() throws SQLException { checkOpen(); return maxFieldSize; } @Override public int getMaxRows() throws SQLException { checkOpen(); return (int) maxRows; } @Override public boolean getMoreResults() throws SQLException { checkOpen(); return false; } @Override public boolean getMoreResults(final int current) throws SQLException { throw new SQLException("Not implemented."); } @Override public int getQueryTimeout() throws SQLException { checkOpen(); return queryTimeout; } @Override public ResultSet getResultSet() throws SQLException { checkOpen(); if (resultSet == null) { resultSet = new TesterResultSet(this); } return resultSet; } @Override public int getResultSetConcurrency() throws SQLException { checkOpen(); return resultSetConcurrency; } @Override public int getResultSetHoldability() throws SQLException { checkOpen(); return resultSetHoldability; } @Override public int getResultSetType() throws SQLException { checkOpen(); return resultSetType; } @Override public int getUpdateCount() throws SQLException { checkOpen(); return (int) rowsUpdated; } @Override public SQLWarning getWarnings() throws SQLException { checkOpen(); return null; } @Override public boolean isClosed() throws SQLException { return !open; } @Override public boolean isCloseOnCompletion() throws SQLException { throw new SQLException("Not implemented."); } @Override public boolean isPoolable() throws SQLException { throw new SQLException("Not implemented."); } public boolean isSqlExceptionOnClose() { return sqlExceptionOnClose; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setCursorName(final String name) throws SQLException { checkOpen(); this.cursorName = name; } @Override public void setEscapeProcessing(final boolean enable) throws SQLException { checkOpen(); this.escapeProcessing = enable; } @Override public void setFetchDirection(final int direction) throws SQLException { checkOpen(); this.fetchDirection = direction; } @Override public void setFetchSize(final int rows) throws SQLException { checkOpen(); this.fetchSize = rows; } @Override public void setLargeMaxRows(final long max) throws SQLException { checkOpen(); this.maxRows = max; } @Override public void setMaxFieldSize(final int max) throws SQLException { checkOpen(); this.maxFieldSize = max; } @Override public void setMaxRows(final int max) throws SQLException { checkOpen(); this.maxRows = max; } @Override public void setPoolable(final boolean poolable) throws SQLException { throw new SQLException("Not implemented."); } @Override public void setQueryTimeout(final int seconds) throws SQLException { checkOpen(); this.queryTimeout = seconds; } public void setSqlExceptionOnClose(final boolean _sqlExceptionOnClose) { this.sqlExceptionOnClose = _sqlExceptionOnClose; } @Override public T unwrap(final Class iface) throws SQLException { throw new SQLException("Not implemented."); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/TesterUtils.java000066400000000000000000000026051472045345700316310ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2; import java.lang.reflect.Field; public class TesterUtils { /** * Access a private field. Do it this way rather than increasing the * visibility of the field in the public API. */ public static Object getField(final Object target, final String fieldName) throws Exception { final Class clazz = target.getClass(); final Field f = clazz.getDeclaredField(fieldName); f.setAccessible(true); return f.get(target); } private TesterUtils() { // Utility class - hide default constructor } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/cpdsadapter/000077500000000000000000000000001472045345700307665ustar00rootroot00000000000000TestDriverAdapterCPDS.java000066400000000000000000000407461472045345700356330ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/cpdsadapter/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.cpdsadapter; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.Statement; import java.time.Duration; import java.util.Properties; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.sql.DataSource; import org.apache.commons.dbcp2.Constants; import org.apache.commons.dbcp2.DelegatingPreparedStatement; import org.apache.commons.dbcp2.DelegatingStatement; import org.apache.commons.dbcp2.PStmtKey; import org.apache.commons.dbcp2.PoolablePreparedStatement; import org.apache.commons.dbcp2.TestUtils; import org.apache.commons.dbcp2.datasources.SharedPoolDataSource; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests for DriverAdapterCPDS */ public class TestDriverAdapterCPDS { private static final class ThreadDbcp367 extends Thread { private final DataSource dataSource; private volatile boolean failed; public ThreadDbcp367(final DataSource dataSource) { this.dataSource = dataSource; } public boolean isFailed() { return failed; } @Override public void run() { Connection conn = null; try { for (int j = 0; j < 5000; j++) { conn = dataSource.getConnection(); conn.close(); } } catch (final SQLException sqle) { failed = true; sqle.printStackTrace(); } } } @SuppressWarnings("resource") private static void checkAfterClose(final Connection element, final PStmtKey pStmtKey) throws SQLException { final ConnectionImpl connectionImpl = (ConnectionImpl) element; assertNull(connectionImpl.getInnermostDelegate()); assertNotNull(connectionImpl.getInnermostDelegateInternal()); final PooledConnectionImpl pooledConnectionImpl = connectionImpl.getPooledConnectionImpl(); assertNotNull(pooledConnectionImpl); // Simulate released resources, should not throw NPEs pooledConnectionImpl.destroyObject(pStmtKey, null); pooledConnectionImpl.destroyObject(pStmtKey, new DefaultPooledObject<>(null)); pooledConnectionImpl.destroyObject(pStmtKey, new DefaultPooledObject<>(new DelegatingPreparedStatement(null, null))); } private DriverAdapterCPDS pcds; @BeforeEach public void setUp() throws Exception { pcds = new DriverAdapterCPDS(); pcds.setDriver("org.apache.commons.dbcp2.TesterDriver"); pcds.setUrl("jdbc:apache:commons:testdriver"); pcds.setUser("foo"); pcds.setPassword("bar"); pcds.setPoolPreparedStatements(true); } @Test public void testClose() throws Exception { final Connection[] c = new Connection[10]; for (int i = 0; i < c.length; i++) { c[i] = pcds.getPooledConnection().getConnection(); } // close one of the connections c[0].close(); assertTrue(c[0].isClosed()); // get a new connection c[0] = pcds.getPooledConnection().getConnection(); for (final Connection element : c) { element.close(); checkAfterClose(element, null); } // open all the connections for (int i = 0; i < c.length; i++) { c[i] = pcds.getPooledConnection().getConnection(); } for (final Connection element : c) { element.close(); checkAfterClose(element, null); } } @Test public void testCloseWithUserName() throws Exception { final Connection[] c = new Connection[10]; for (int i = 0; i < c.length; i++) { c[i] = pcds.getPooledConnection("u1", "p1").getConnection(); } // close one of the connections c[0].close(); assertTrue(c[0].isClosed()); // get a new connection c[0] = pcds.getPooledConnection("u1", "p1").getConnection(); for (final Connection element : c) { element.close(); checkAfterClose(element, null); } // open all the connections for (int i = 0; i < c.length; i++) { c[i] = pcds.getPooledConnection("u1", "p1").getConnection(); } for (final Connection element : c) { element.close(); checkAfterClose(element, null); } } // https://issues.apache.org/jira/browse/DBCP-376 @Test public void testDbcp367() throws Exception { final ThreadDbcp367[] threads = new ThreadDbcp367[200]; pcds.setPoolPreparedStatements(true); pcds.setMaxPreparedStatements(-1); pcds.setAccessToUnderlyingConnectionAllowed(true); try (final SharedPoolDataSource spds = new SharedPoolDataSource()) { spds.setConnectionPoolDataSource(pcds); spds.setMaxTotal(threads.length + 10); spds.setDefaultMaxWait(Duration.ofMillis(-1)); spds.setDefaultMaxIdle(10); spds.setDefaultAutoCommit(Boolean.FALSE); spds.setValidationQuery("SELECT 1"); spds.setDefaultDurationBetweenEvictionRuns(Duration.ofSeconds(10)); spds.setDefaultNumTestsPerEvictionRun(-1); spds.setDefaultTestWhileIdle(true); spds.setDefaultTestOnBorrow(true); spds.setDefaultTestOnReturn(false); for (int i = 0; i < threads.length; i++) { threads[i] = new ThreadDbcp367(spds); threads[i].start(); } for (int i = 0; i < threads.length; i++) { threads[i].join(); Assertions.assertFalse(threads[i].isFailed(), "Thread " + i + " has failed"); } } } @SuppressWarnings("deprecation") @Test public void testDeprecatedAccessors() { int i = 0; // i++; pcds.setMinEvictableIdleTimeMillis(i); assertEquals(i, pcds.getMinEvictableIdleTimeMillis()); assertEquals(Duration.ofMillis(i), pcds.getMinEvictableIdleDuration()); // i++; pcds.setTimeBetweenEvictionRunsMillis(i); assertEquals(i, pcds.getTimeBetweenEvictionRunsMillis()); assertEquals(Duration.ofMillis(i), pcds.getDurationBetweenEvictionRuns()); } @Test public void testGetObjectInstance() throws Exception { final Reference ref = pcds.getReference(); final Object o = pcds.getObjectInstance(ref, null, null, null); assertEquals(pcds.getDriver(), ((DriverAdapterCPDS) o).getDriver()); } @Test public void testGetObjectInstanceChangeDescription() throws Exception { final Reference ref = pcds.getReference(); for (int i = 0; i < ref.size(); i++) { if (ref.get(i).getType().equals("description")) { ref.remove(i); break; } } ref.add(new StringRefAddr("description", "anything")); final Object o = pcds.getObjectInstance(ref, null, null, null); assertEquals(pcds.getDescription(), ((DriverAdapterCPDS) o).getDescription()); } @Test public void testGetObjectInstanceNull() throws Exception { final Object o = pcds.getObjectInstance(null, null, null, null); assertNull(o); } @Test public void testGetParentLogger() { assertThrows(SQLFeatureNotSupportedException.class, pcds::getParentLogger); } @Test public void testGetReference() throws NamingException { final Reference ref = pcds.getReference(); assertEquals(pcds.getDriver(), ref.get("driver").getContent()); assertEquals(pcds.getDescription(), ref.get("description").getContent()); } @Test public void testGettersAndSetters() { pcds.setUser("foo"); assertEquals("foo", pcds.getUser()); pcds.setPassword("bar"); assertEquals("bar", pcds.getPassword()); pcds.setPassword(new char[] {'a', 'b'}); assertArrayEquals(new char[] {'a', 'b'}, pcds.getPasswordCharArray()); final PrintWriter pw = new PrintWriter(System.err); pcds.setLogWriter(pw); @SuppressWarnings("resource") final PrintWriter logWriter = pcds.getLogWriter(); assertEquals(pw, logWriter); pcds.setLoginTimeout(10); assertEquals(10, pcds.getLoginTimeout()); pcds.setMaxIdle(100); assertEquals(100, pcds.getMaxIdle()); pcds.setDurationBetweenEvictionRuns(Duration.ofMillis(100)); assertEquals(100, pcds.getDurationBetweenEvictionRuns().toMillis()); pcds.setNumTestsPerEvictionRun(1); assertEquals(1, pcds.getNumTestsPerEvictionRun()); pcds.setMinEvictableIdleDuration(Duration.ofMillis(11)); assertEquals(Duration.ofMillis(11), pcds.getMinEvictableIdleDuration()); pcds.setDescription("jo"); assertEquals("jo", pcds.getDescription()); } /** * JIRA: DBCP-245 */ @Test public void testIncorrectPassword() throws Exception { pcds.getPooledConnection("u2", "p2").close(); // Use bad password assertThrows(SQLException.class, () -> pcds.getPooledConnection("u1", "zlsafjk"), "Able to retrieve connection with incorrect password"); // Use good password final SQLException e = assertThrows(SQLException.class, () -> pcds.getPooledConnection("u1", "x"), "Able to retrieve connection with incorrect password"); assertTrue(e.getMessage().startsWith("x is not the correct password")); // else the exception was expected // Make sure we can still use our good password. pcds.getPooledConnection("u1", "p1").close(); } /** * JIRA: DBCP-442 */ @Test public void testNullValidationQuery() throws Exception { try (final SharedPoolDataSource spds = new SharedPoolDataSource()) { spds.setConnectionPoolDataSource(pcds); spds.setDefaultTestOnBorrow(true); try (final Connection c = spds.getConnection()) { // close right away } } } @Test public void testSetConnectionProperties() throws Exception { // Set user property to bad value pcds.setUser("bad"); // Supply correct value in connection properties // This will overwrite field value final Properties properties = new Properties(); properties.put(Constants.KEY_USER, "foo"); properties.put(Constants.KEY_PASSWORD, pcds.getPassword()); pcds.setConnectionProperties(properties); pcds.getPooledConnection().close(); assertEquals("foo", pcds.getUser()); // Put bad password into properties properties.put("password", "bad"); // This does not change local field assertEquals("bar", pcds.getPassword()); // Supply correct password in getPooledConnection // Call will succeed and overwrite property pcds.getPooledConnection("foo", "bar").close(); assertEquals("bar", pcds.getConnectionProperties().getProperty("password")); } @Test public void testSetConnectionPropertiesConnectionCalled() throws Exception { final Properties properties = new Properties(); // call to the connection pcds.getPooledConnection().close(); assertThrows(IllegalStateException.class, () -> pcds.setConnectionProperties(properties)); } @Test public void testSetConnectionPropertiesNull() throws Exception { pcds.setConnectionProperties(null); } @Test public void testSetPasswordNull() throws Exception { pcds.setPassword("Secret"); assertEquals("Secret", pcds.getPassword()); pcds.setPassword((char[]) null); assertNull(pcds.getPassword()); } @Test public void testSetPasswordNullWithConnectionProperties() throws Exception { pcds.setConnectionProperties(new Properties()); pcds.setPassword("Secret"); assertEquals("Secret", pcds.getPassword()); pcds.setPassword((char[]) null); assertNull(pcds.getPassword()); } @Test public void testSetPasswordThenModCharArray() { final char[] pwd = {'a'}; pcds.setPassword(pwd); assertEquals("a", pcds.getPassword()); pwd[0] = 'b'; assertEquals("a", pcds.getPassword()); } @Test public void testSetUserNull() throws Exception { pcds.setUser("Alice"); assertEquals("Alice", pcds.getUser()); pcds.setUser(null); assertNull(pcds.getUser()); } @Test public void testSetUserNullWithConnectionProperties() throws Exception { pcds.setConnectionProperties(new Properties()); pcds.setUser("Alice"); assertEquals("Alice", pcds.getUser()); pcds.setUser(null); assertNull(pcds.getUser()); } @Test public void testSimple() throws Exception { try (final Connection conn = pcds.getPooledConnection().getConnection()) { assertNotNull(conn); try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (final ResultSet resultSet = stmt.executeQuery()) { assertNotNull(resultSet); assertTrue(resultSet.next()); } } } } @SuppressWarnings("resource") @Test public void testSimpleWithUsername() throws Exception { final Connection connCheck; PStmtKey pStmtKey; try (final Connection conn = pcds.getPooledConnection("u1", "p1").getConnection()) { assertNotNull(conn); connCheck = conn; try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); final DelegatingStatement delegatingStatement = (DelegatingStatement) stmt; final Statement delegateStatement = delegatingStatement.getDelegate(); pStmtKey = TestUtils.getPStmtKey((PoolablePreparedStatement) delegateStatement); assertNotNull(pStmtKey); try (final ResultSet resultSet = stmt.executeQuery()) { assertNotNull(resultSet); assertTrue(resultSet.next()); } } } checkAfterClose(connCheck, pStmtKey); } @Test public void testToStringWithoutConnectionProperties() throws ClassNotFoundException { final DriverAdapterCPDS cleanCpds = new DriverAdapterCPDS(); cleanCpds.setDriver("org.apache.commons.dbcp2.TesterDriver"); cleanCpds.setUrl("jdbc:apache:commons:testdriver"); cleanCpds.setUser("foo"); cleanCpds.setPassword("bar"); cleanCpds.toString(); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/000077500000000000000000000000001472045345700310115ustar00rootroot00000000000000CharArrayTest.java000066400000000000000000000036621472045345700343200ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.junit.jupiter.api.Test; /** * Tests {@link CharArray}. */ public class CharArrayTest { @Test public void testAsString() { assertEquals("foo", new CharArray("foo").asString()); } @Test public void testEquals() { assertEquals(new CharArray("foo"), new CharArray("foo")); assertNotEquals(new CharArray("foo"), new CharArray("bar")); } @Test public void testGet() { assertArrayEquals("foo".toCharArray(), new CharArray("foo").get()); } @Test public void testHashCode() { assertEquals(new CharArray("foo").hashCode(), new CharArray("foo").hashCode()); assertNotEquals(new CharArray("foo").hashCode(), new CharArray("bar").hashCode()); } @Test public void testToString() { assertFalse(new CharArray("foo").toString().contains("foo")); } } ConnectionPoolDataSourceProxy.java000066400000000000000000000057731472045345700375570ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.io.PrintWriter; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import org.apache.commons.dbcp2.Jdbc41Bridge; /** * ConnectionPoolDataSource implementation that proxies another ConnectionPoolDataSource. */ public class ConnectionPoolDataSourceProxy implements ConnectionPoolDataSource { protected ConnectionPoolDataSource delegate; public ConnectionPoolDataSourceProxy(final ConnectionPoolDataSource cpds) { this.delegate = cpds; } public ConnectionPoolDataSource getDelegate() { return delegate; } @Override public int getLoginTimeout() throws SQLException { return delegate.getLoginTimeout(); } @Override public PrintWriter getLogWriter() throws SQLException { return delegate.getLogWriter(); } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return Jdbc41Bridge.getParentLogger(delegate); } /** * Gets a TesterPooledConnection with notifyOnClose turned on */ @Override public PooledConnection getPooledConnection() throws SQLException { return wrapPooledConnection(delegate.getPooledConnection()); } /** * Gets a TesterPooledConnection with notifyOnClose turned on */ @Override public PooledConnection getPooledConnection(final String user, final String password) throws SQLException { return wrapPooledConnection(delegate.getPooledConnection(user, password)); } @Override public void setLoginTimeout(final int seconds) throws SQLException { delegate.setLoginTimeout(seconds); } @Override public void setLogWriter(final PrintWriter out) throws SQLException { delegate.setLogWriter(out); } /** * Creates a TesterPooledConnection with notifyOnClose turned on */ protected PooledConnection wrapPooledConnection(final PooledConnection pc) { final PooledConnectionProxy tpc = new PooledConnectionProxy(pc); tpc.setNotifyOnClose(true); return tpc; } } PooledConnectionProxy.java000066400000000000000000000110631472045345700361020ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EventListener; import java.util.List; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.PooledConnection; import javax.sql.StatementEventListener; /** * PooledConnection implementation that wraps a driver-supplied * PooledConnection and proxies events, allowing behavior to be * modified to simulate behavior of different implementations. */ public class PooledConnectionProxy implements PooledConnection, ConnectionEventListener { protected PooledConnection delegate; /** * ConnectionEventListeners */ private final List eventListeners = Collections.synchronizedList(new ArrayList<>()); /** * True means we will (dubiously) notify listeners with a * ConnectionClosed event when this (i.e. the PooledConnection itself) * is closed */ private boolean notifyOnClose; public PooledConnectionProxy(final PooledConnection pooledConnection) { this.delegate = pooledConnection; pooledConnection.addConnectionEventListener(this); } /** * Add event listeners. */ @Override public void addConnectionEventListener(final ConnectionEventListener listener) { if (!eventListeners.contains(listener)) { eventListeners.add(listener); } } @Override public void addStatementEventListener(final StatementEventListener listener) { if (!eventListeners.contains(listener)) { eventListeners.add(listener); } } /** * If notifyOnClose is on, notify listeners */ @Override public void close() throws SQLException { delegate.close(); if (isNotifyOnClose()) { notifyListeners(); } } /** * Pass closed events on to listeners */ @Override public void connectionClosed(final ConnectionEvent event) { notifyListeners(); } /** * Pass error events on to listeners */ @Override public void connectionErrorOccurred(final ConnectionEvent event) { final Object[] listeners = eventListeners.toArray(); for (final Object listener : listeners) { ((ConnectionEventListener) listener).connectionErrorOccurred(event); } } @Override public Connection getConnection() throws SQLException { return delegate.getConnection(); } /** * Expose listeners */ public Collection getListeners() { return eventListeners; } public boolean isNotifyOnClose() { return notifyOnClose; } /** * sends a connectionClosed event to listeners. */ void notifyListeners() { final ConnectionEvent event = new ConnectionEvent(this); final Object[] listeners = eventListeners.toArray(); for (final Object listener : listeners) { ((ConnectionEventListener) listener).connectionClosed(event); } } /** * Remove event listeners. */ @Override public void removeConnectionEventListener(final ConnectionEventListener listener) { eventListeners.remove(listener); } @Override public void removeStatementEventListener(final StatementEventListener listener) { eventListeners.remove(listener); } public void setNotifyOnClose(final boolean notifyOnClose) { this.notifyOnClose = notifyOnClose; } /** * Generate a connection error event */ public void throwConnectionError() { final ConnectionEvent event = new ConnectionEvent(this); connectionErrorOccurred(event); } } TestCPDSConnectionFactory.java000066400000000000000000000177001472045345700365430ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import javax.sql.PooledConnection; import org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS; import org.apache.commons.pool2.impl.GenericObjectPool; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** */ public class TestCPDSConnectionFactory { protected ConnectionPoolDataSourceProxy cpds; @BeforeEach public void setUp() throws Exception { cpds = new ConnectionPoolDataSourceProxy(new DriverAdapterCPDS()); final DriverAdapterCPDS delegate = (DriverAdapterCPDS) cpds.getDelegate(); delegate.setDriver("org.apache.commons.dbcp2.TesterDriver"); delegate.setUrl("jdbc:apache:commons:testdriver"); delegate.setUser("userName"); delegate.setPassword("password"); } /** * JIRA DBCP-216 * * Verify that pool counters are maintained properly and listeners are * cleaned up when a PooledConnection throws a connectionError event. */ @Test public void testConnectionErrorCleanup() throws Exception { // Setup factory final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, null, Duration.ofMillis(-1), false, "userName", "password"); try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { factory.setPool(pool); // Checkout a pair of connections final PooledConnection pcon1 = pool.borrowObject().getPooledConnection(); try (final Connection con1 = pcon1.getConnection()) { final PooledConnection pcon2 = pool.borrowObject().getPooledConnection(); assertEquals(2, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); // Verify listening final PooledConnectionProxy pc = (PooledConnectionProxy) pcon1; assertTrue(pc.getListeners().contains(factory)); // Throw connectionError event pc.throwConnectionError(); // Active count should be reduced by 1 and no idle increase assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); // Throw another one - should be ignored pc.throwConnectionError(); assertEquals(1, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); // Ask for another connection final PooledConnection pcon3 = pool.borrowObject().getPooledConnection(); assertNotEquals(pcon3, pcon1); // better not get baddie back assertFalse(pc.getListeners().contains(factory)); // verify cleanup assertEquals(2, pool.getNumActive()); assertEquals(0, pool.getNumIdle()); // Return good connections back to pool pcon2.getConnection().close(); pcon3.getConnection().close(); assertEquals(2, pool.getNumIdle()); assertEquals(0, pool.getNumActive()); // Verify pc is closed assertThrows(SQLException.class, pc::getConnection, "Expecting SQLException using closed PooledConnection"); // Back from the dead - ignore the ghost! con1.close(); assertEquals(2, pool.getNumIdle()); assertEquals(0, pool.getNumActive()); // Clear pool pool.clear(); assertEquals(0, pool.getNumIdle()); } } } /** * JIRA: DBCP-442 */ @Test public void testNullValidationQuery() throws Exception { final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, null, Duration.ofMillis(-1), false, "userName", "password"); try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { factory.setPool(pool); pool.setTestOnBorrow(true); final PooledConnection pcon = pool.borrowObject().getPooledConnection(); try (final Connection con = pcon.getConnection()) { } } } /** * JIRA: DBCP-442 */ @Test public void testNullValidationQuery_Deprecated() throws Exception { final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, null, -1, false, "userName", "password"); try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { factory.setPool(pool); pool.setTestOnBorrow(true); final PooledConnection pcon = pool.borrowObject().getPooledConnection(); try (final Connection con = pcon.getConnection()) { } } } @Test public void testSetPasswordThenModCharArray() { final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, null, Duration.ofMillis(-1), false, "userName", "password"); final char[] pwd = {'a'}; factory.setPassword(pwd); assertEquals("a", String.valueOf(factory.getPasswordCharArray())); pwd[0] = 'b'; assertEquals("a", String.valueOf(factory.getPasswordCharArray())); } @Test public void testSetPasswordThenModCharArray_Deprecated() { final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, null, -1, false, "userName", "password"); final char[] pwd = {'a'}; factory.setPassword(pwd); assertEquals("a", String.valueOf(factory.getPasswordCharArray())); pwd[0] = 'b'; assertEquals("a", String.valueOf(factory.getPasswordCharArray())); } /** * JIRA DBCP-216 * * Check PoolableConnection close triggered by destroy is handled * properly. PooledConnectionProxy (dubiously) fires connectionClosed * when PooledConnection itself is closed. */ @Test public void testSharedPoolDSDestroyOnReturn() throws Exception { try (final PerUserPoolDataSource ds = new PerUserPoolDataSource()) { ds.setConnectionPoolDataSource(cpds); ds.setPerUserMaxTotal("userName", 10); ds.setPerUserMaxWait("userName", Duration.ofMillis(50)); ds.setPerUserMaxIdle("userName", 2); final Connection conn1 = ds.getConnection("userName", "password"); final Connection conn2 = ds.getConnection("userName", "password"); final Connection conn3 = ds.getConnection("userName", "password"); assertEquals(3, ds.getNumActive("userName")); conn1.close(); assertEquals(1, ds.getNumIdle("userName")); conn2.close(); assertEquals(2, ds.getNumIdle("userName")); conn3.close(); // Return to pool will trigger destroy -> close sequence assertEquals(2, ds.getNumIdle("userName")); } } } TestFactory.java000066400000000000000000000073221472045345700340500ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.Hashtable; import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Name; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; /** * Tests SharedPoolDataSourceFactory. */ public class TestFactory { /** * Tests Bugzilla Bug 24082: bug in InstanceKeyDataSourceFactory. * * There's a fatal bug in InstanceKeyDataSourceFactory that means you can't instantiate more than one factory. * https://issues.apache.org/bugzilla/show_bug.cgi?id=24082 */ @ParameterizedTest // @formatter:off @CsvSource({ "dataSourceName, java:comp/env/jdbc/bookstoreCPDS", "description, This is a test.", "jndiEnvironment, X", "loginTimeout, 30000", "blockWhenExhausted, false", "evictionPolicyClassName, org.apache.commons.pool2.impl.DefaultEvictionPolicy", "lifo, true", "maxIdlePerKey, 4", "maxTotalPerKey, 4", "maxWaitMillis, 30001", "minEvictableIdleTimeMillis, 30002", "minIdlePerKey, 4", "numTestsPerEvictionRun, 2", "softMinEvictableIdleTimeMillis, 30003", "testOnCreate, true", "testOnBorrow, true", "testOnReturn, true", "testWhileIdle, true", "timeBetweenEvictionRunsMillis, 30004", "validationQuery, select 1", "validationQueryTimeout, 30005", "rollbackAfterValidation, false", "maxConnLifetimeMillis, 60000", "defaultAutoCommit, true", "defaultTransactionIsolation, X", "defaultReadOnly, true" }) // @formatter:on public void testJNDI2Pools(final String string, final String value) throws Exception { final Reference refObj = new Reference(SharedPoolDataSource.class.getName()); refObj.add(new StringRefAddr(string, value)); final Context context = new InitialContext(); final Hashtable env = new Hashtable<>(); final ObjectFactory factory = new SharedPoolDataSourceFactory(); final Name name = new CompositeName("myDB"); final Object obj = factory.getObjectInstance(refObj, name, context, env); assertNotNull(obj); final Name name2 = new CompositeName("myDB2"); final Object obj2 = factory.getObjectInstance(refObj, name2, context, env); assertNotNull(obj2); } } TestInstanceKeyDataSource.java000066400000000000000000000256371472045345700366420ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** */ public class TestInstanceKeyDataSource { private static final class ThrowOnSetupDefaultsDataSource extends SharedPoolDataSource { private static final long serialVersionUID = -448025812063133259L; ThrowOnSetupDefaultsDataSource() { } @Override protected void setupDefaults(final Connection connection, final String userName) throws SQLException { throw new SQLException("bang!"); } } private final static String DRIVER = "org.apache.commons.dbcp2.TesterDriver"; private final static String URL = "jdbc:apache:commons:testdriver"; private final static String USER = "foo"; private final static String PASS = "bar"; private DriverAdapterCPDS pcds; private SharedPoolDataSource spds; @BeforeEach public void setUp() throws ClassNotFoundException { pcds = new DriverAdapterCPDS(); pcds.setDriver(DRIVER); pcds.setUrl(URL); pcds.setUser(USER); pcds.setPassword(PASS); pcds.setPoolPreparedStatements(false); spds = new SharedPoolDataSource(); spds.setConnectionPoolDataSource(pcds); } @AfterEach public void tearDown() throws Exception { spds.close(); } @Test public void testConnection() throws SQLException, ClassNotFoundException { spds = new SharedPoolDataSource(); pcds.setDriver(DRIVER); pcds.setUrl(URL); spds.setConnectionPoolDataSource(pcds); final PooledConnectionAndInfo info = spds.getPooledConnectionAndInfo(null, null); assertNull(info.getUserName()); assertNull(info.getPassword()); try (final Connection conn = spds.getConnection()) { assertNotNull(conn); } } @Test public void testConnectionPoolDataSource() { assertEquals(pcds, spds.getConnectionPoolDataSource()); } @Test public void testConnectionPoolDataSourceAlreadySet() { assertThrows(IllegalStateException.class, () -> spds.setConnectionPoolDataSource(new DriverAdapterCPDS())); } @Test public void testConnectionPoolDataSourceAlreadySetUsingJndi() { spds = new SharedPoolDataSource(); spds.setDataSourceName("anything"); assertThrows(IllegalStateException.class, () -> spds.setConnectionPoolDataSource(new DriverAdapterCPDS())); } @Test public void testDataSourceName() { spds = new SharedPoolDataSource(); assertNull(spds.getDataSourceName()); spds.setDataSourceName("anything"); assertEquals("anything", spds.getDataSourceName()); } @Test public void testDataSourceNameAlreadySet() { assertThrows(IllegalStateException.class, () -> spds.setDataSourceName("anything")); } @Test public void testDataSourceNameAlreadySetUsingJndi() { spds = new SharedPoolDataSource(); spds.setDataSourceName("anything"); assertThrows(IllegalStateException.class, () -> spds.setDataSourceName("anything")); } @Test public void testDefaultBlockWhenExhausted() { spds.setDefaultBlockWhenExhausted(true); assertTrue(spds.getDefaultBlockWhenExhausted()); spds.setDefaultBlockWhenExhausted(false); assertFalse(spds.getDefaultBlockWhenExhausted()); } @Test public void testDefaultEvictionPolicyClassName() { spds.setDefaultEvictionPolicyClassName(Object.class.getName()); assertEquals(Object.class.getName(), spds.getDefaultEvictionPolicyClassName()); } @Test public void testDefaultLifo() { spds.setDefaultLifo(true); assertTrue(spds.getDefaultLifo()); spds.setDefaultLifo(false); assertFalse(spds.getDefaultLifo()); } @Test public void testDefaultMinIdle() { spds.setDefaultMinIdle(10); assertEquals(10, spds.getDefaultMinIdle()); } @Test public void testDefaultReadOnly() { spds.setDefaultReadOnly(true); assertTrue(spds.isDefaultReadOnly()); spds.setDefaultReadOnly(false); assertFalse(spds.isDefaultReadOnly()); } @Test public void testDefaultSoftMinEvictableIdleTimeMillis() { spds.setDefaultSoftMinEvictableIdleTimeMillis(10); assertEquals(10, spds.getDefaultSoftMinEvictableIdleTimeMillis()); } @Test public void testDefaultTestOnCreate() { spds.setDefaultTestOnCreate(false); assertFalse(spds.getDefaultTestOnCreate()); spds.setDefaultTestOnCreate(true); assertTrue(spds.getDefaultTestOnCreate()); } @Test public void testDefaultTransactionIsolation() { assertEquals(InstanceKeyDataSource.UNKNOWN_TRANSACTIONISOLATION, spds.getDefaultTransactionIsolation()); spds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); assertEquals(Connection.TRANSACTION_READ_COMMITTED, spds.getDefaultTransactionIsolation()); } @Test public void testDefaultTransactionIsolationInvalid() { assertEquals(InstanceKeyDataSource.UNKNOWN_TRANSACTIONISOLATION, spds.getDefaultTransactionIsolation()); assertThrows(IllegalArgumentException.class, () -> spds.setDefaultTransactionIsolation(Integer.MAX_VALUE)); } @Test public void testDescription() { spds.setDescription("anything"); assertEquals("anything", spds.getDescription()); } /** * Verify that exception on setupDefaults does not leak PooledConnection * * JIRA: DBCP-237 * @throws Exception */ @Test public void testExceptionOnSetupDefaults() throws Exception { try (final ThrowOnSetupDefaultsDataSource tds = new ThrowOnSetupDefaultsDataSource()) { final int numConnections = tds.getNumActive(); assertThrows(SQLException.class, () -> tds.getConnection(USER, PASS)); assertEquals(numConnections, tds.getNumActive()); } } @Test public void testIsWrapperFor() throws Exception { assertTrue(spds.isWrapperFor(InstanceKeyDataSource.class)); assertTrue(spds.isWrapperFor(AutoCloseable.class)); } @Test public void testJndiEnvironment() { assertNull(spds.getJndiEnvironment("name")); final Properties properties = new Properties(); properties.setProperty("name", "clarke"); spds.setJndiEnvironment(properties); assertEquals("clarke", spds.getJndiEnvironment("name")); spds.setJndiEnvironment("name", "asimov"); assertEquals("asimov", spds.getJndiEnvironment("name")); } @Test public void testJndiNullProperties() { assertThrows(NullPointerException.class, () -> spds.setJndiEnvironment(null)); } @Test public void testJndiPropertiesCleared() { spds.setJndiEnvironment("name", "king"); assertEquals("king", spds.getJndiEnvironment("name")); final Properties properties = new Properties(); properties.setProperty("fish", "kohi"); spds.setJndiEnvironment(properties); assertNull(spds.getJndiEnvironment("name")); } @Test public void testJndiPropertiesNotInitialized() { assertNull(spds.getJndiEnvironment("name")); spds.setJndiEnvironment("name", "king"); assertEquals("king", spds.getJndiEnvironment("name")); } @Test public void testLoginTimeout() { spds.setLoginTimeout(10); assertEquals(10, spds.getLoginTimeout()); } @SuppressWarnings("resource") @Test public void testLogWriter() { spds.setLogWriter(new PrintWriter(System.out)); assertNotNull(spds.getLogWriter()); } @SuppressWarnings("resource") @Test public void testLogWriterAutoInitialized() { assertNotNull(spds.getLogWriter()); } @Test public void testMaxConnLifetimeMillis() { assertEquals(-1, spds.getMaxConnLifetimeMillis()); spds.setMaxConnLifetimeMillis(10); assertEquals(10, spds.getMaxConnLifetimeMillis()); } @Test public void testRollbackAfterValidation() { assertFalse(spds.isRollbackAfterValidation()); spds.setRollbackAfterValidation(true); assertTrue(spds.isRollbackAfterValidation()); } @Test public void testRollbackAfterValidationWithConnectionCalled() throws SQLException { try (Connection connection = spds.getConnection()) { assertFalse(spds.isRollbackAfterValidation()); assertThrows(IllegalStateException.class, () -> spds.setRollbackAfterValidation(true)); } } @SuppressWarnings("resource") @Test public void testUnwrap() throws Exception { assertSame(spds.unwrap(InstanceKeyDataSource.class), spds); assertSame(spds.unwrap(AutoCloseable.class), spds); } @Test public void testValidationQuery() { assertNull(spds.getValidationQuery()); spds.setValidationQuery("anything"); assertEquals("anything", spds.getValidationQuery()); } @Test public void testValidationQueryTimeout() { assertEquals(-1, spds.getValidationQueryTimeout()); spds.setValidationQueryTimeout(10); assertEquals(10, spds.getValidationQueryTimeout()); } @Test public void testValidationQueryWithConnectionCalled() throws SQLException { try (Connection connection = spds.getConnection()) { assertNull(spds.getValidationQuery()); assertThrows(IllegalStateException.class, () -> spds.setValidationQuery("anything")); } } } TestKeyedCPDSConnectionFactory.java000066400000000000000000000153531472045345700375270ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import javax.sql.PooledConnection; import org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS; import org.apache.commons.pool2.KeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests {@link KeyedCPDSConnectionFactory}. */ public class TestKeyedCPDSConnectionFactory { protected ConnectionPoolDataSourceProxy cpds; @BeforeEach public void setUp() throws Exception { cpds = new ConnectionPoolDataSourceProxy(new DriverAdapterCPDS()); final DriverAdapterCPDS delegate = (DriverAdapterCPDS) cpds.getDelegate(); delegate.setDriver("org.apache.commons.dbcp2.TesterDriver"); delegate.setUrl("jdbc:apache:commons:testdriver"); delegate.setUser("userName"); delegate.setPassword("password"); } /** * JIRA DBCP-216 * * Verify that pool counters are maintained properly and listeners are * cleaned up when a PooledConnection throws a connectionError event. */ @Test public void testConnectionErrorCleanup() throws Exception { // Setup factory final UserPassKey key = new UserPassKey("userName", "password"); final KeyedCPDSConnectionFactory factory = new KeyedCPDSConnectionFactory(cpds, null, -1, false); try (final KeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { factory.setPool(pool); // Checkout a pair of connections final PooledConnection pcon1 = pool.borrowObject(key).getPooledConnection(); try (final Connection con1 = pcon1.getConnection()) { final PooledConnection pcon2 = pool.borrowObject(key).getPooledConnection(); assertEquals(2, pool.getNumActive(key)); assertEquals(0, pool.getNumIdle(key)); // Verify listening final PooledConnectionProxy pc = (PooledConnectionProxy) pcon1; assertTrue(pc.getListeners().contains(factory)); // Throw connectionError event pc.throwConnectionError(); // Active count should be reduced by 1 and no idle increase assertEquals(1, pool.getNumActive(key)); assertEquals(0, pool.getNumIdle(key)); // Throw another one - we should be on cleanup list, so ignored pc.throwConnectionError(); assertEquals(1, pool.getNumActive(key)); assertEquals(0, pool.getNumIdle(key)); // Ask for another connection - should trigger makeObject, which causes // cleanup, removing listeners. final PooledConnection pcon3 = pool.borrowObject(key).getPooledConnection(); assertNotEquals(pcon3, pcon1); // better not get baddie back assertFalse(pc.getListeners().contains(factory)); // verify cleanup assertEquals(2, pool.getNumActive(key)); assertEquals(0, pool.getNumIdle(key)); // Return good connections back to pool pcon2.getConnection().close(); pcon3.getConnection().close(); assertEquals(2, pool.getNumIdle(key)); assertEquals(0, pool.getNumActive(key)); // Verify pc is closed assertThrows(SQLException.class, pc::getConnection, "Expecting SQLException using closed PooledConnection"); // Back from the dead - ignore the ghost! } assertEquals(2, pool.getNumIdle(key)); assertEquals(0, pool.getNumActive(key)); // Clear pool pool.clear(); assertEquals(0, pool.getNumIdle(key)); } } /** * JIRA: DBCP-442 */ @Test public void testNullValidationQuery() throws Exception { final UserPassKey key = new UserPassKey("userName", "password"); final KeyedCPDSConnectionFactory factory = new KeyedCPDSConnectionFactory(cpds, null, -1, false); try (final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory)) { factory.setPool(pool); pool.setTestOnBorrow(true); final PooledConnection pcon = pool.borrowObject(key).getPooledConnection(); try (final Connection con = pcon.getConnection()) { } } } /** * JIRA DBCP-216 * * Check PoolableConnection close triggered by destroy is handled * properly. PooledConnectionProxy (dubiously) fires connectionClosed * when PooledConnection itself is closed. */ @Test public void testSharedPoolDSDestroyOnReturn() throws Exception { try (final SharedPoolDataSource ds = new SharedPoolDataSource()) { ds.setConnectionPoolDataSource(cpds); ds.setMaxTotal(10); ds.setDefaultMaxWait(Duration.ofMillis(50)); ds.setDefaultMaxIdle(2); final Connection conn1 = ds.getConnection("userName", "password"); final Connection conn2 = ds.getConnection("userName", "password"); final Connection conn3 = ds.getConnection("userName", "password"); assertEquals(3, ds.getNumActive()); conn1.close(); assertEquals(1, ds.getNumIdle()); conn2.close(); assertEquals(2, ds.getNumIdle()); conn3.close(); // Return to pool will trigger destroy -> close sequence assertEquals(2, ds.getNumIdle()); } } } TestPerUserPoolDataSource.java000066400000000000000000002160271472045345700366370ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; import java.util.HashMap; import java.util.Map; import javax.sql.DataSource; import org.apache.commons.dbcp2.TestConnectionPool; import org.apache.commons.dbcp2.TesterDriver; import org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** */ public class TestPerUserPoolDataSource extends TestConnectionPool { private static final Duration DURATION_1_MILLISECOND = Duration.ofMillis(1); private String user; private DataSource ds; @Override protected Connection getConnection() throws SQLException { return ds.getConnection(user,"bar"); } @BeforeEach public void setUp() throws Exception { user = "foo"; final DriverAdapterCPDS pcds = new DriverAdapterCPDS(); pcds.setDriver("org.apache.commons.dbcp2.TesterDriver"); pcds.setUrl("jdbc:apache:commons:testdriver"); pcds.setUser(user); pcds.setPassword("bar"); pcds.setAccessToUnderlyingConnectionAllowed(true); final PerUserPoolDataSource tds = new PerUserPoolDataSource(); tds.setConnectionPoolDataSource(pcds); tds.setDefaultMaxTotal(getMaxTotal()); tds.setDefaultMaxWait(getMaxWaitDuration()); tds.setPerUserMaxTotal(user, getMaxTotal()); tds.setPerUserMaxWait(user, getMaxWaitDuration()); tds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); tds.setDefaultAutoCommit(Boolean.TRUE); ds = tds; } @Override @AfterEach public void tearDown() throws Exception { super.tearDown(); ((PerUserPoolDataSource) ds).close(); } /** * See DBCP-8 */ @Test public void testChangePassword() throws Exception { assertThrows(SQLException.class, () -> ds.getConnection(user, "bay")); final Connection con1 = ds.getConnection(user, "bar"); final Connection con2 = ds.getConnection(user, "bar"); final Connection con3 = ds.getConnection(user, "bar"); con1.close(); con2.close(); TesterDriver.addUser(user, "bay"); // change the user/password setting try { final Connection con4 = ds.getConnection(user, "bay"); // new password // Idle instances with old password should have been cleared assertEquals(0, ((PerUserPoolDataSource) ds).getNumIdle(user), "Should be no idle connections in the pool"); con4.close(); // Should be one idle instance with new pwd assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user), "Should be one idle connection in the pool"); // old password assertThrows(SQLException.class, () -> ds.getConnection(user, "bar"), "Should have generated SQLException"); try (Connection con5 = ds.getConnection(user, "bay")) { // take the idle one con3.close(); // Return a connection with the old password ds.getConnection(user, "bay").close(); // will try bad returned connection and destroy it assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user), "Should be one idle connection in the pool"); } } finally { TesterDriver.addUser(user, "bar"); } } @Override @Test public void testClosing() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; // open the maximum connections for (int i=0; i ds.getConnection("u1", "zlsafjk")); // Use good password ds.getConnection("u1", "p1").close(); try (Connection c = ds.getConnection("u1", "x")){ fail("Able to retrieve connection with incorrect password"); } catch (final SQLException e) { if (!e.getMessage().startsWith("Given password did not match")) { throw e; } // else the exception was expected } // Make sure we can still use our good password. ds.getConnection("u1", "p1").close(); // Try related users and passwords ds.getConnection(user, "bar").close(); assertThrows(SQLException.class, () -> ds.getConnection("foob", "ar")); assertThrows(SQLException.class, () -> ds.getConnection(user, "baz")); } @Override @Test public void testMaxTotal() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = ds.getConnection(); assertNotNull(c[i]); } try (Connection conn = ds.getConnection()) { fail("Allowed to open more than DefaultMaxTotal connections."); } catch (final java.sql.SQLException e) { // should only be able to open 10 connections, so this test should // throw an exception } for (final Connection element : c) { element.close(); } } /** * Verify that defaultMaxWaitMillis = 0 means immediate failure when * pool is exhausted. */ @Test public void testMaxWaitMillisZero() throws Exception { final PerUserPoolDataSource tds = (PerUserPoolDataSource) ds; tds.setDefaultMaxWait(Duration.ZERO); tds.setPerUserMaxTotal("u1", 1); try (final Connection conn = tds.getConnection("u1", "p1")) { assertThrows(SQLException.class, () -> tds.getConnection("u1", "p1")); } } @Test public void testMultipleThreads1() throws Exception { // Override wait time in order to allow for Thread.sleep(1) sometimes taking a lot longer on // some JVMs, e.g. Windows. final Duration defaultMaxWaitDuration = Duration.ofMillis(430); ((PerUserPoolDataSource) ds).setDefaultMaxWait(defaultMaxWaitDuration); ((PerUserPoolDataSource) ds).setPerUserMaxWait(user, defaultMaxWaitDuration); multipleThreads(Duration.ofMillis(1), false, false, defaultMaxWaitDuration); } @Test public void testMultipleThreads2() throws Exception { final Duration defaultMaxWaitDuration = Duration.ofMillis(500); ((PerUserPoolDataSource) ds).setDefaultMaxWait(defaultMaxWaitDuration); ((PerUserPoolDataSource) ds).setPerUserMaxWait(user, defaultMaxWaitDuration); multipleThreads(defaultMaxWaitDuration.multipliedBy(2), true, true, defaultMaxWaitDuration); } @Override @Test public void testOpening() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; // test that opening new connections is not closing previous for (int i=0; i userDefaultBlockWhenExhausted = new HashMap<>(); userDefaultBlockWhenExhausted.put("key", Boolean.FALSE); ds.setPerUserBlockWhenExhausted(userDefaultBlockWhenExhausted); assertEquals(Boolean.FALSE, ds.getPerUserBlockWhenExhausted("key")); // when the code above is executed, the backing map was initalized // now check if that still works. The backing map is clear'ed. userDefaultBlockWhenExhausted = new HashMap<>(); userDefaultBlockWhenExhausted.put("anonymous", Boolean.FALSE); ds.setPerUserBlockWhenExhausted(userDefaultBlockWhenExhausted); // now the previously entered value was cleared, so it will be back to the // default value of TRUE assertEquals(Boolean.TRUE, ds.getPerUserBlockWhenExhausted("key")); // and our new value exists too assertEquals(Boolean.FALSE, ds.getPerUserBlockWhenExhausted("anonymous")); } /** * Test per user block when exhausted, with the backing map not initialized before. * Instead we pass the map. */ @Test public void testPerUserBlockWhenExhaustedMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map userDefaultBlockWhenExhausted = new HashMap<>(); userDefaultBlockWhenExhausted.put("key", Boolean.TRUE); ds.setPerUserBlockWhenExhausted(userDefaultBlockWhenExhausted); assertEquals(Boolean.TRUE, ds.getPerUserBlockWhenExhausted("key")); } /** * Test per user block when exhausted, with the backing map not initialized before. * Instead, we pass the map. And furthermore, we are now searching for an inexistent * key, which should return the default value. */ @Test public void testPerUserBlockWhenExhaustedMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map userDefaultBlockWhenExhausted = new HashMap<>(); userDefaultBlockWhenExhausted.put("key", Boolean.FALSE); ds.setPerUserBlockWhenExhausted(userDefaultBlockWhenExhausted); assertEquals(ds.getDefaultBlockWhenExhausted(), ds.getPerUserBlockWhenExhausted("missingkey")); } /** * Test per user block when exhausted, with the backing map not initialized before. * Instead we pass the user and value, and hence the map is initialized beforehand. * After that, we pass another user, so both values should still be present. The * PerUserPoolDataSource does not clear the perUserPoolDataSource map, unless you * pass a new map, using another internal/package method. */ @Test public void testPerUserBlockWhenExhaustedWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserBlockWhenExhausted(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserBlockWhenExhausted(user)); // when the code above is executed, the backing map was initalized // now check if that still works. The backing map is NOT clear'ed. ds.setPerUserBlockWhenExhausted("anotheruser", Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserBlockWhenExhausted(user)); assertEquals(Boolean.FALSE, ds.getPerUserBlockWhenExhausted("anotheruser")); } /** * Test per user block when exhausted, with the backing map not initialized before. * Instead we pass the user and value, and hence the map is initialized beforehand. */ @Test public void testPerUserBlockWhenExhaustedWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserBlockWhenExhausted(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserBlockWhenExhausted(user)); } /** * Test per user block when exhausted, with the backing map not initialized before. * Instead we pass the user and value, and hence the map is initialized beforehand. * Furthermore, we are now searching for an inexistent key, which should return the * default value. */ @Test public void testPerUserBlockWhenExhaustedWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserBlockWhenExhausted("whatismyuseragain?", Boolean.FALSE); assertEquals(Boolean.TRUE, ds.getPerUserBlockWhenExhausted("missingkey")); } @Test public void testPerUserDefaultAutoCommitMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserDefaultAutoCommit(values); assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit("key")); values = new HashMap<>(); values.put("anonymous", Boolean.FALSE); ds.setPerUserDefaultAutoCommit(values); assertNull(ds.getPerUserDefaultAutoCommit("key")); assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit("anonymous")); } // getters and setters. Most follow the same pattern. The initial tests contain a more // complete documentation, which can be helpful when write/understanding the other methods. // -- per user block when exhausted @Test public void testPerUserDefaultAutoCommitMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.TRUE); ds.setPerUserDefaultAutoCommit(values); assertEquals(Boolean.TRUE, ds.getPerUserDefaultAutoCommit("key")); } @Test public void testPerUserDefaultAutoCommitMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserDefaultAutoCommit(values); // TODO this is not consistent with the other methods assertNull(ds.getPerUserDefaultAutoCommit("missingkey")); } @Test public void testPerUserDefaultAutoCommitWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultAutoCommit(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit(user)); ds.setPerUserDefaultAutoCommit("anotheruser", Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit(user)); assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit("anotheruser")); } @Test public void testPerUserDefaultAutoCommitWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultAutoCommit(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserDefaultAutoCommit(user)); } @Test public void testPerUserDefaultAutoCommitWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultAutoCommit("whatismyuseragain?", Boolean.FALSE); // TODO this is not consistent with the other methods assertNull(ds.getPerUserDefaultAutoCommit("missingkey")); } @Test public void testPerUserDefaultReadOnlyMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserDefaultReadOnly(values); assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly("key")); values = new HashMap<>(); values.put("anonymous", Boolean.FALSE); ds.setPerUserDefaultReadOnly(values); assertNull(ds.getPerUserDefaultReadOnly("key")); assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly("anonymous")); } // -- per user default auto commit @Test public void testPerUserDefaultReadOnlyMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.TRUE); ds.setPerUserDefaultReadOnly(values); assertEquals(Boolean.TRUE, ds.getPerUserDefaultReadOnly("key")); } @Test public void testPerUserDefaultReadOnlyMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserDefaultReadOnly(values); // TODO this is not consistent with the other methods assertNull(ds.getPerUserDefaultReadOnly("missingkey")); } @Test public void testPerUserDefaultReadOnlyWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultReadOnly(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly(user)); ds.setPerUserDefaultReadOnly("anotheruser", Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly(user)); assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly("anotheruser")); } @Test public void testPerUserDefaultReadOnlyWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultReadOnly(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserDefaultReadOnly(user)); } @Test public void testPerUserDefaultReadOnlyWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultReadOnly("whatismyuseragain?", Boolean.FALSE); // TODO this is not consistent with the other methods assertNull(ds.getPerUserDefaultReadOnly("missingkey")); } @Test public void testPerUserDefaultTransactionIsolationMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserDefaultTransactionIsolation(values); assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation("key")); values = new HashMap<>(); values.put("anonymous", 0); ds.setPerUserDefaultTransactionIsolation(values); // TODO this is not consistent with the other methods assertNull(ds.getPerUserDefaultTransactionIsolation("key")); assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation("anonymous")); } // -- per user default read only @Test public void testPerUserDefaultTransactionIsolationMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1); ds.setPerUserDefaultTransactionIsolation(values); assertEquals((Integer) 1, ds.getPerUserDefaultTransactionIsolation("key")); } @Test public void testPerUserDefaultTransactionIsolationMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserDefaultTransactionIsolation(values); // TODO this is not consistent with the other methods assertNull(ds.getPerUserDefaultTransactionIsolation("missingkey")); } @Test public void testPerUserDefaultTransactionIsolationWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultTransactionIsolation(user, 0); assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation(user)); ds.setPerUserDefaultTransactionIsolation("anotheruser", 0); assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation(user)); assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation("anotheruser")); } @Test public void testPerUserDefaultTransactionIsolationWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultTransactionIsolation(user, 0); assertEquals((Integer) 0, ds.getPerUserDefaultTransactionIsolation(user)); } @Test public void testPerUserDefaultTransactionIsolationWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserDefaultTransactionIsolation("whatismyuseragain?", 0); // TODO this is not consistent with the other methods assertNull(ds.getPerUserDefaultTransactionIsolation("missingkey")); } @Test public void testPerUserDurationBetweenEvictionRunsMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Duration.ZERO); ds.setPerUserDurationBetweenEvictionRuns(values); assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis("key")); assertEquals(Duration.ZERO, ds.getPerUserDurationBetweenEvictionRuns("key")); values = new HashMap<>(); values.put("anonymous", Duration.ZERO); ds.setPerUserDurationBetweenEvictionRuns(values); assertEquals(ds.getDefaultTimeBetweenEvictionRunsMillis(), ds.getPerUserTimeBetweenEvictionRunsMillis("key")); assertEquals(ds.getDefaultDurationBetweenEvictionRuns(), ds.getPerUserDurationBetweenEvictionRuns("key")); assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis("anonymous")); assertEquals(Duration.ZERO, ds.getPerUserDurationBetweenEvictionRuns("anonymous")); } // -- per user default transaction isolation @Test public void testPerUserDurationBetweenEvictionRunsMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", DURATION_1_MILLISECOND); ds.setPerUserDurationBetweenEvictionRuns(values); assertEquals(1L, ds.getPerUserTimeBetweenEvictionRunsMillis("key")); assertEquals(DURATION_1_MILLISECOND, ds.getPerUserDurationBetweenEvictionRuns("key")); } @Test public void testPerUserDurationBetweenEvictionRunsMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Duration.ZERO); ds.setPerUserDurationBetweenEvictionRuns(values); assertEquals(ds.getDefaultTimeBetweenEvictionRunsMillis(), ds.getPerUserTimeBetweenEvictionRunsMillis("missingkey")); assertEquals(ds.getDefaultDurationBetweenEvictionRuns(), ds.getPerUserDurationBetweenEvictionRuns("missingkey")); } @Test public void testPerUserEvictionPolicyClassNameMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", "bar"); ds.setPerUserEvictionPolicyClassName(values); assertEquals("bar", ds.getPerUserEvictionPolicyClassName("key")); values = new HashMap<>(); values.put("anonymous", "bar"); ds.setPerUserEvictionPolicyClassName(values); assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("key")); assertEquals("bar", ds.getPerUserEvictionPolicyClassName("anonymous")); } @Test public void testPerUserEvictionPolicyClassNameMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", "test"); ds.setPerUserEvictionPolicyClassName(values); assertEquals("test", ds.getPerUserEvictionPolicyClassName("key")); } @Test public void testPerUserEvictionPolicyClassNameMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", "bar"); ds.setPerUserEvictionPolicyClassName(values); assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("missingkey")); } @Test public void testPerUserEvictionPolicyClassNameWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserEvictionPolicyClassName(user, "bar"); assertEquals("bar", ds.getPerUserEvictionPolicyClassName(user)); ds.setPerUserEvictionPolicyClassName("anotheruser", "bar"); assertEquals("bar", ds.getPerUserEvictionPolicyClassName(user)); assertEquals("bar", ds.getPerUserEvictionPolicyClassName("anotheruser")); } // -- per user eviction policy class name @Test public void testPerUserEvictionPolicyClassNameWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserEvictionPolicyClassName(user, "bar"); assertEquals("bar", ds.getPerUserEvictionPolicyClassName(user)); } @Test public void testPerUserEvictionPolicyClassNameWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserEvictionPolicyClassName("whatismyuseragain?", "bar"); assertEquals(ds.getDefaultEvictionPolicyClassName(), ds.getPerUserEvictionPolicyClassName("missingkey")); } @Test public void testPerUserLifoMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserLifo(values); assertEquals(Boolean.FALSE, ds.getPerUserLifo("key")); values = new HashMap<>(); values.put("anonymous", Boolean.FALSE); ds.setPerUserLifo(values); assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("key")); assertEquals(Boolean.FALSE, ds.getPerUserLifo("anonymous")); } @Test public void testPerUserLifoMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.TRUE); ds.setPerUserLifo(values); assertEquals(Boolean.TRUE, ds.getPerUserLifo("key")); } @Test public void testPerUserLifoMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserLifo(values); assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("missingkey")); } @Test public void testPerUserLifoWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserLifo(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserLifo(user)); ds.setPerUserLifo("anotheruser", Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserLifo(user)); assertEquals(Boolean.FALSE, ds.getPerUserLifo("anotheruser")); } // -- per user lifo @Test public void testPerUserLifoWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserLifo(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserLifo(user)); } @Test public void testPerUserLifoWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserLifo("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultLifo(), ds.getPerUserLifo("missingkey")); } @Test public void testPerUserMaxIdleMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserMaxIdle(values); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle("key")); values = new HashMap<>(); values.put("anonymous", 0); ds.setPerUserMaxIdle(values); assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("key")); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle("anonymous")); } @Test public void testPerUserMaxIdleMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1); ds.setPerUserMaxIdle(values); assertEquals((Integer) 1, (Integer) ds.getPerUserMaxIdle("key")); } @Test public void testPerUserMaxIdleMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserMaxIdle(values); assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("missingkey")); } @Test public void testPerUserMaxIdleWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxIdle(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle(user)); ds.setPerUserMaxIdle("anotheruser", 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle(user)); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle("anotheruser")); } // -- per user max idle @Test public void testPerUserMaxIdleWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxIdle(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxIdle(user)); } @Test public void testPerUserMaxIdleWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxIdle("whatismyuseragain?", 0); assertEquals((Integer) ds.getDefaultMaxIdle(), (Integer) ds.getPerUserMaxIdle("missingkey")); } @Test public void testPerUserMaxTotalMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserMaxTotal(values); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal("key")); values = new HashMap<>(); values.put("anonymous", 0); ds.setPerUserMaxTotal(values); assertEquals((Integer) ds.getDefaultMaxTotal(), (Integer) ds.getPerUserMaxTotal("key")); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal("anonymous")); } @Test public void testPerUserMaxTotalMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1); ds.setPerUserMaxTotal(values); assertEquals((Integer) 1, (Integer) ds.getPerUserMaxTotal("key")); } @Test public void testPerUserMaxTotalMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserMaxTotal(values); assertEquals((Integer) ds.getDefaultMaxTotal(), (Integer) ds.getPerUserMaxTotal("missingkey")); } @Test public void testPerUserMaxTotalWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxTotal(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal(user)); ds.setPerUserMaxTotal("anotheruser", 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal(user)); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal("anotheruser")); } @Test public void testPerUserMaxTotalWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxTotal(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMaxTotal(user)); } @Test public void testPerUserMaxTotalWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxTotal("whatismyuseragain?", 0); assertEquals((Integer) ds.getDefaultMaxTotal(), (Integer) ds.getPerUserMaxTotal("missingkey")); } @Test public void testPerUserMaxWaitDurationMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Duration.ZERO); ds.setPerUserMaxWaitDuration(values); assertEquals(Duration.ZERO, ds.getPerUserMaxWaitDuration("key")); values = new HashMap<>(); values.put("anonymous", Duration.ZERO); ds.setPerUserMaxWaitDuration(values); assertEquals(ds.getDefaultMaxWait(), ds.getPerUserMaxWaitDuration("key")); assertEquals(Duration.ZERO, ds.getPerUserMaxWaitDuration("anonymous")); } @Test public void testPerUserMaxWaitDurationMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", DURATION_1_MILLISECOND); ds.setPerUserMaxWaitDuration(values); assertEquals(DURATION_1_MILLISECOND, ds.getPerUserMaxWaitDuration("key")); } @Test public void testPerUserMaxWaitDurationMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Duration.ZERO); ds.setPerUserMaxWaitDuration(values); assertEquals(ds.getDefaultMaxWait(), ds.getPerUserMaxWaitDuration("missingkey")); } @Test @SuppressWarnings("deprecation") public void testPerUserMaxWaitMillisWithUserMapInitialized_Deprecated() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxWaitMillis(user, 0L); assertEquals(0L, ds.getPerUserMaxWaitMillis(user)); ds.setPerUserMaxWaitMillis("anotheruser", 0L); assertEquals(0L, ds.getPerUserMaxWaitMillis(user)); assertEquals(0L, ds.getPerUserMaxWaitMillis("anotheruser")); } // -- per user max wait millis @Test @SuppressWarnings("deprecation") public void testPerUserMaxWaitMillisWithUserMapNotInitialized_Deprecated() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxWaitMillis(user, 0L); assertEquals(0L, ds.getPerUserMaxWaitMillis(user)); } @Test @SuppressWarnings("deprecation") public void testPerUserMaxWaitMillisWithUserMapNotInitializedMissingKey_Deprecated() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxWaitMillis("whatismyuseragain?", 0L); assertEquals(ds.getDefaultMaxWaitMillis(), ds.getPerUserMaxWaitMillis("missingkey")); } @Test public void testPerUserMethods() throws Exception { final PerUserPoolDataSource tds = (PerUserPoolDataSource) ds; // you need to set per user maxTotal otherwise there is no accounting tds.setPerUserMaxTotal("u1", 5); tds.setPerUserMaxTotal("u2", 5); assertEquals(0, tds.getNumActive()); assertEquals(0, tds.getNumActive("u1")); assertEquals(0, tds.getNumActive("u2")); assertEquals(0, tds.getNumIdle()); assertEquals(0, tds.getNumIdle("u1")); assertEquals(0, tds.getNumIdle("u2")); try (Connection conn = tds.getConnection()) { assertNotNull(conn); assertEquals(1, tds.getNumActive()); assertEquals(0, tds.getNumActive("u1")); assertEquals(0, tds.getNumActive("u2")); assertEquals(0, tds.getNumIdle()); assertEquals(0, tds.getNumIdle("u1")); assertEquals(0, tds.getNumIdle("u2")); } assertEquals(0, tds.getNumActive()); assertEquals(0, tds.getNumActive("u1")); assertEquals(0, tds.getNumActive("u2")); assertEquals(1, tds.getNumIdle()); assertEquals(0, tds.getNumIdle("u1")); assertEquals(0, tds.getNumIdle("u2")); try (Connection conn = tds.getConnection("u1", "p1")) { assertNotNull(conn); assertEquals(0, tds.getNumActive()); assertEquals(1, tds.getNumActive("u1")); assertEquals(0, tds.getNumActive("u2")); assertEquals(1, tds.getNumIdle()); assertEquals(0, tds.getNumIdle("u1")); assertEquals(0, tds.getNumIdle("u2")); } assertEquals(0, tds.getNumActive()); assertEquals(0, tds.getNumActive("u1")); assertEquals(0, tds.getNumActive("u2")); assertEquals(1, tds.getNumIdle()); assertEquals(1, tds.getNumIdle("u1")); assertEquals(0, tds.getNumIdle("u2")); } @Test public void testPerUserMinEvictableIdleDurationMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Duration.ZERO); ds.setPerUserMinEvictableIdle(values); assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis("key")); assertEquals(Duration.ZERO, ds.getPerUserMinEvictableIdleDuration("key")); values = new HashMap<>(); values.put("anonymous", Duration.ZERO); ds.setPerUserMinEvictableIdle(values); assertEquals(ds.getDefaultMinEvictableIdleTimeMillis(), ds.getPerUserMinEvictableIdleTimeMillis("key")); assertEquals(ds.getDefaultMinEvictableIdleDuration(), ds.getPerUserMinEvictableIdleDuration("key")); assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis("anonymous")); assertEquals(Duration.ZERO, ds.getPerUserMinEvictableIdleDuration("anonymous")); } @Test public void testPerUserMinEvictableIdleDurationMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", DURATION_1_MILLISECOND); ds.setPerUserMinEvictableIdle(values); assertEquals(1L, ds.getPerUserMinEvictableIdleTimeMillis("key")); assertEquals(DURATION_1_MILLISECOND, ds.getPerUserMinEvictableIdleDuration("key")); } @Test public void testPerUserMinEvictableIdleDurationMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Duration.ZERO); ds.setPerUserMinEvictableIdle(values); assertEquals(ds.getDefaultMinEvictableIdleTimeMillis(), ds.getPerUserMinEvictableIdleTimeMillis("missingkey")); assertEquals(ds.getDefaultMinEvictableIdleDuration(), ds.getPerUserMinEvictableIdleDuration("missingkey")); } // -- per user min evictable idle time millis @Test public void testPerUserMinEvictableIdleTimeMillisWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinEvictableIdleTimeMillis(user, 0L); assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis(user)); ds.setPerUserMinEvictableIdleTimeMillis("anotheruser", 0L); assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis(user)); assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis("anotheruser")); } @Test public void testPerUserMinEvictableIdleTimeMillisWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinEvictableIdleTimeMillis(user, 0L); assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis(user)); } @Test public void testPerUserMinEvictableIdleTimeMillisWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinEvictableIdleTimeMillis("whatismyuseragain?", 0L); assertEquals(ds.getDefaultMinEvictableIdleTimeMillis(), ds.getPerUserMinEvictableIdleTimeMillis("missingkey")); } @Test public void testPerUserMinIdleMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserMinIdle(values); assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle("key")); values = new HashMap<>(); values.put("anonymous", 0); ds.setPerUserMinIdle(values); assertEquals((Integer) ds.getDefaultMinIdle(), (Integer) ds.getPerUserMinIdle("key")); assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle("anonymous")); } @Test public void testPerUserMinIdleMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1); ds.setPerUserMinIdle(values); assertEquals((Integer) 1, (Integer) ds.getPerUserMinIdle("key")); } @Test public void testPerUserMinIdleMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserMinIdle(values); assertEquals((Integer) ds.getDefaultMinIdle(), (Integer) ds.getPerUserMinIdle("missingkey")); } // -- per user min idle @Test public void testPerUserMinIdleWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinIdle(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle(user)); ds.setPerUserMinIdle("anotheruser", 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle(user)); assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle("anotheruser")); } @Test public void testPerUserMinIdleWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinIdle(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserMinIdle(user)); } @Test public void testPerUserMinIdleWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMinIdle("whatismyuseragain?", 0); assertEquals((Integer) ds.getDefaultMinIdle(), (Integer) ds.getPerUserMinIdle("missingkey")); } @Test public void testPerUserNumTestsPerEvictionRunMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserNumTestsPerEvictionRun(values); assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun("key")); values = new HashMap<>(); values.put("anonymous", 0); ds.setPerUserNumTestsPerEvictionRun(values); assertEquals((Integer) ds.getDefaultNumTestsPerEvictionRun(), (Integer) ds.getPerUserNumTestsPerEvictionRun("key")); assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun("anonymous")); } @Test public void testPerUserNumTestsPerEvictionRunMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1); ds.setPerUserNumTestsPerEvictionRun(values); assertEquals((Integer) 1, (Integer) ds.getPerUserNumTestsPerEvictionRun("key")); } @Test public void testPerUserNumTestsPerEvictionRunMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0); ds.setPerUserNumTestsPerEvictionRun(values); assertEquals((Integer) ds.getDefaultNumTestsPerEvictionRun(), (Integer) ds.getPerUserNumTestsPerEvictionRun("missingkey")); } // -- per user num tests per eviction run @Test public void testPerUserNumTestsPerEvictionRunWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserNumTestsPerEvictionRun(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun(user)); ds.setPerUserNumTestsPerEvictionRun("anotheruser", 0); assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun(user)); assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun("anotheruser")); } @Test public void testPerUserNumTestsPerEvictionRunWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserNumTestsPerEvictionRun(user, 0); assertEquals((Integer) 0, (Integer) ds.getPerUserNumTestsPerEvictionRun(user)); } @Test public void testPerUserNumTestsPerEvictionRunWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserNumTestsPerEvictionRun("whatismyuseragain?", 0); assertEquals((Integer) ds.getDefaultNumTestsPerEvictionRun(), (Integer) ds.getPerUserNumTestsPerEvictionRun("missingkey")); } @Test public void testPerUserSoftMinEvictableIdleDurationMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Duration.ZERO); ds.setPerUserSoftMinEvictableIdle(values); assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis("key")); assertEquals(Duration.ZERO, ds.getPerUserSoftMinEvictableIdleDuration("key")); values = new HashMap<>(); values.put("anonymous", Duration.ZERO); ds.setPerUserSoftMinEvictableIdle(values); assertEquals(ds.getDefaultSoftMinEvictableIdleTimeMillis(), ds.getPerUserSoftMinEvictableIdleTimeMillis("key")); assertEquals(ds.getDefaultSoftMinEvictableIdleDuration(), ds.getPerUserSoftMinEvictableIdleDuration("key")); assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis("anonymous")); assertEquals(Duration.ZERO, ds.getPerUserSoftMinEvictableIdleDuration("anonymous")); } @Test public void testPerUserSoftMinEvictableIdleDurationMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", DURATION_1_MILLISECOND); ds.setPerUserSoftMinEvictableIdle(values); assertEquals(1L, ds.getPerUserSoftMinEvictableIdleTimeMillis("key")); assertEquals(DURATION_1_MILLISECOND, ds.getPerUserSoftMinEvictableIdleDuration("key")); } @Test public void testPerUserSoftMinEvictableIdleDurationMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Duration.ZERO); ds.setPerUserSoftMinEvictableIdle(values); assertEquals(ds.getDefaultSoftMinEvictableIdleTimeMillis(), ds.getPerUserSoftMinEvictableIdleTimeMillis("missingkey")); assertEquals(ds.getDefaultSoftMinEvictableIdleDuration(), ds.getPerUserSoftMinEvictableIdleDuration("missingkey")); } // -- per user soft min evictable idle time millis @Test public void testPerUserSoftMinEvictableIdleTimeMillisWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserSoftMinEvictableIdleTimeMillis(user, 0L); assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis(user)); ds.setPerUserSoftMinEvictableIdleTimeMillis("anotheruser", 0L); assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis(user)); assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis("anotheruser")); } @Test public void testPerUserSoftMinEvictableIdleTimeMillisWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserSoftMinEvictableIdleTimeMillis(user, 0L); assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis(user)); } @Test public void testPerUserSoftMinEvictableIdleTimeMillisWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserSoftMinEvictableIdleTimeMillis("whatismyuseragain?", 0L); assertEquals(ds.getDefaultSoftMinEvictableIdleTimeMillis(), ds.getPerUserSoftMinEvictableIdleTimeMillis("missingkey")); } @Test public void testPerUserTestOnBorrowMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserTestOnBorrow(values); assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow("key")); values = new HashMap<>(); values.put("anonymous", Boolean.FALSE); ds.setPerUserTestOnBorrow(values); assertEquals(ds.getDefaultTestOnBorrow(), ds.getPerUserTestOnBorrow("key")); assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow("anonymous")); } @Test public void testPerUserTestOnBorrowMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.TRUE); ds.setPerUserTestOnBorrow(values); assertEquals(Boolean.TRUE, ds.getPerUserTestOnBorrow("key")); } @Test public void testPerUserTestOnBorrowMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserTestOnBorrow(values); assertEquals(ds.getDefaultTestOnBorrow(), ds.getPerUserTestOnBorrow("missingkey")); } // -- per user test on borrow @Test public void testPerUserTestOnBorrowWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnBorrow(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow(user)); ds.setPerUserTestOnBorrow("anotheruser", Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow(user)); assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow("anotheruser")); } @Test public void testPerUserTestOnBorrowWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnBorrow(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnBorrow(user)); } @Test public void testPerUserTestOnBorrowWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnBorrow("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultTestOnBorrow(), ds.getPerUserTestOnBorrow("missingkey")); } @Test public void testPerUserTestOnCreateMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserTestOnCreate(values); assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate("key")); values = new HashMap<>(); values.put("anonymous", Boolean.FALSE); ds.setPerUserTestOnCreate(values); assertEquals(ds.getDefaultTestOnCreate(), ds.getPerUserTestOnCreate("key")); assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate("anonymous")); } @Test public void testPerUserTestOnCreateMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.TRUE); ds.setPerUserTestOnCreate(values); assertEquals(Boolean.TRUE, ds.getPerUserTestOnCreate("key")); } @Test public void testPerUserTestOnCreateMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserTestOnCreate(values); assertEquals(ds.getDefaultTestOnCreate(), ds.getPerUserTestOnCreate("missingkey")); } // -- per user test on create @Test public void testPerUserTestOnCreateWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnCreate(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate(user)); ds.setPerUserTestOnCreate("anotheruser", Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate(user)); assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate("anotheruser")); } @Test public void testPerUserTestOnCreateWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnCreate(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnCreate(user)); } @Test public void testPerUserTestOnCreateWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnCreate("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultTestOnCreate(), ds.getPerUserTestOnCreate("missingkey")); } @Test public void testPerUserTestOnReturnMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserTestOnReturn(values); assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn("key")); values = new HashMap<>(); values.put("anonymous", Boolean.FALSE); ds.setPerUserTestOnReturn(values); assertEquals(ds.getDefaultTestOnReturn(), ds.getPerUserTestOnReturn("key")); assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn("anonymous")); } @Test public void testPerUserTestOnReturnMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.TRUE); ds.setPerUserTestOnReturn(values); assertEquals(Boolean.TRUE, ds.getPerUserTestOnReturn("key")); } @Test public void testPerUserTestOnReturnMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserTestOnReturn(values); assertEquals(ds.getDefaultTestOnReturn(), ds.getPerUserTestOnReturn("missingkey")); } // -- per user test on return @Test public void testPerUserTestOnReturnWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnReturn(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn(user)); ds.setPerUserTestOnReturn("anotheruser", Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn(user)); assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn("anotheruser")); } @Test public void testPerUserTestOnReturnWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnReturn(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestOnReturn(user)); } @Test public void testPerUserTestOnReturnWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestOnReturn("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultTestOnReturn(), ds.getPerUserTestOnReturn("missingkey")); } @Test public void testPerUserTestWhileIdleMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserTestWhileIdle(values); assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle("key")); values = new HashMap<>(); values.put("anonymous", Boolean.FALSE); ds.setPerUserTestWhileIdle(values); assertEquals(ds.getDefaultTestWhileIdle(), ds.getPerUserTestWhileIdle("key")); assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle("anonymous")); } @Test public void testPerUserTestWhileIdleMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.TRUE); ds.setPerUserTestWhileIdle(values); assertEquals(Boolean.TRUE, ds.getPerUserTestWhileIdle("key")); } @Test public void testPerUserTestWhileIdleMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", Boolean.FALSE); ds.setPerUserTestWhileIdle(values); assertEquals(ds.getDefaultTestWhileIdle(), ds.getPerUserTestWhileIdle("missingkey")); } @Test public void testPerUserTestWhileIdleWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestWhileIdle(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle(user)); ds.setPerUserTestWhileIdle("anotheruser", Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle(user)); assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle("anotheruser")); } @Test public void testPerUserTestWhileIdleWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestWhileIdle(user, Boolean.FALSE); assertEquals(Boolean.FALSE, ds.getPerUserTestWhileIdle(user)); } @Test public void testPerUserTestWhileIdleWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTestWhileIdle("whatismyuseragain?", Boolean.FALSE); assertEquals(ds.getDefaultTestWhileIdle(), ds.getPerUserTestWhileIdle("missingkey")); } @Test public void testPerUserTimeBetweenEvictionRunsMillisWithUserMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTimeBetweenEvictionRunsMillis(user, 0L); assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis(user)); ds.setPerUserTimeBetweenEvictionRunsMillis("anotheruser", 0L); assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis(user)); assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis("anotheruser")); } @Test public void testPerUserTimeBetweenEvictionRunsMillisWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTimeBetweenEvictionRunsMillis(user, 0L); assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis(user)); } @Test public void testPerUserTimeBetweenEvictionRunsMillisWithUserMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserTimeBetweenEvictionRunsMillis("whatismyuseragain?", 0L); assertEquals(ds.getDefaultTimeBetweenEvictionRunsMillis(), ds.getPerUserTimeBetweenEvictionRunsMillis("missingkey")); } // -- per user time between eviction runs millis @Test public void testSerialization() throws Exception { // make sure the pool has initialized final Connection conn = ds.getConnection(); conn.close(); // serialize final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(ds); out.close(); final byte[] b = baos.toByteArray(); final ByteArrayInputStream bais = new ByteArrayInputStream(b); final ObjectInputStream in = new ObjectInputStream(bais); final Object obj = in.readObject(); in.close(); assertEquals(1, ((PerUserPoolDataSource) obj).getNumIdle()); } @Override @Test public void testSimple() throws Exception { try (final Connection conn = ds.getConnection()) { assertNotNull(conn); try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (final ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } } @Override @Test public void testSimple2() throws Exception { Connection conn = ds.getConnection(); assertNotNull(conn); PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); conn.close(); try (Statement s = conn.createStatement()) { fail("Can't use closed connections"); } catch (final SQLException e) { // expected } conn = ds.getConnection(); assertNotNull(conn); stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); conn.close(); conn = null; } @Test public void testSimpleWithUsername() throws Exception { try (final Connection conn = ds.getConnection("u1", "p1")) { assertNotNull(conn); try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (final ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } } @Test public void testTransactionIsolationBehavior() throws Exception { try (Connection conn = getConnection()) { assertNotNull(conn); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn.getTransactionIsolation()); conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); } final Connection conn2 = getConnection(); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn2.getTransactionIsolation()); final Connection conn3 = getConnection(); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn3.getTransactionIsolation()); conn2.close(); conn3.close(); } // see issue https://issues.apache.org/bugzilla/show_bug.cgi?id=23843 // unregistered user is in the same pool as without user name @Test public void testUnregisteredUser() throws Exception { final PerUserPoolDataSource tds = (PerUserPoolDataSource) ds; assertEquals(0, tds.getNumActive()); assertEquals(0, tds.getNumIdle()); try (Connection conn = tds.getConnection()) { assertNotNull(conn); assertEquals(1, tds.getNumActive()); assertEquals(0, tds.getNumIdle()); } assertEquals(0, tds.getNumActive()); assertEquals(1, tds.getNumIdle()); try (Connection conn = tds.getConnection("u1", "p1")) { assertNotNull(conn); assertEquals(0, tds.getNumActive()); assertEquals(1, tds.getNumIdle()); assertEquals(1, tds.getNumActive("u1")); assertEquals(0, tds.getNumIdle("u1")); } assertEquals(0, tds.getNumActive()); assertEquals(1, tds.getNumIdle()); assertEquals(0, tds.getNumActive("u1")); assertEquals(1, tds.getNumIdle("u1")); } } TestPoolKey.java000066400000000000000000000044251472045345700340240ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests for PoolKey. */ public class TestPoolKey { private PoolKey poolKey; private PoolKey anotherPoolKey; @BeforeEach public void setUp() { poolKey = new PoolKey("ds", "user"); anotherPoolKey = new PoolKey(null, null); } @Test public void testEquals() { assertEquals(poolKey, poolKey); assertNotEquals(poolKey, null); assertNotEquals(poolKey, new Object()); assertNotEquals(new PoolKey(null, "user"), poolKey); assertEquals(new PoolKey(null, "user"), new PoolKey(null, "user")); assertNotEquals(new PoolKey(null, "user"), new PoolKey(null, "foo")); assertNotEquals(new PoolKey("ds", null), new PoolKey("foo", null)); assertNotEquals(new PoolKey("ds", null), poolKey); assertEquals(new PoolKey("ds", null), new PoolKey("ds", null)); } @Test public void testHashcode() { assertEquals(poolKey.hashCode(), new PoolKey("ds", "user").hashCode()); assertNotEquals(poolKey.hashCode(), anotherPoolKey.hashCode()); } @Test public void testToString() { assertEquals(poolKey.toString(), new PoolKey("ds", "user").toString()); assertNotEquals(poolKey.toString(), anotherPoolKey.toString()); } } TestSharedPoolDataSource.java000066400000000000000000000657201472045345700364620ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; import java.util.ArrayList; import javax.sql.DataSource; import org.apache.commons.dbcp2.DelegatingStatement; import org.apache.commons.dbcp2.TestConnectionPool; import org.apache.commons.dbcp2.TesterDriver; import org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** */ public class TestSharedPoolDataSource extends TestConnectionPool { /** * There are 3 different prepareCall statement methods so add a little complexity to reduce what would otherwise be lots * of copy and paste. */ private static abstract class AbstractPrepareCallCallback { protected Connection conn; abstract CallableStatement getCallableStatement() throws SQLException; void setConnection(final Connection conn) { this.conn = conn; } } /** * There are 6 different prepareStatement statement methods so add a little complexity to reduce what would otherwise be * lots of copy and paste. */ private static abstract class AbstractPrepareStatementCallback { protected Connection conn; abstract PreparedStatement prepareStatement() throws SQLException; void setConnection(final Connection conn) { this.conn = conn; } } private static final class CscbString extends AbstractPrepareCallCallback { @Override CallableStatement getCallableStatement() throws SQLException { return conn.prepareCall("{call home()}"); } } private static final class CscbStringIntInt extends AbstractPrepareCallCallback { @Override CallableStatement getCallableStatement() throws SQLException { return conn.prepareCall("{call home()}", 0, 0); } } private static final class CscbStringIntIntInt extends AbstractPrepareCallCallback { @Override CallableStatement getCallableStatement() throws SQLException { return conn.prepareCall("{call home()}", 0, 0, 0); } } private static final class PscbString extends AbstractPrepareStatementCallback { @Override PreparedStatement prepareStatement() throws SQLException { return conn.prepareStatement("select * from dual"); } } private static final class PscbStringInt extends AbstractPrepareStatementCallback { @Override PreparedStatement prepareStatement() throws SQLException { return conn.prepareStatement("select * from dual", 0); } } private static final class PscbStringIntArray extends AbstractPrepareStatementCallback { @Override PreparedStatement prepareStatement() throws SQLException { return conn.prepareStatement("select * from dual", ArrayUtils.EMPTY_INT_ARRAY); } } private static final class PscbStringIntInt extends AbstractPrepareStatementCallback { @Override PreparedStatement prepareStatement() throws SQLException { return conn.prepareStatement("select * from dual", 0, 0); } } private static final class PscbStringIntIntInt extends AbstractPrepareStatementCallback { @Override PreparedStatement prepareStatement() throws SQLException { return conn.prepareStatement("select * from dual", 0, 0, 0); } } private static final class PscbStringStringArray extends AbstractPrepareStatementCallback { @Override PreparedStatement prepareStatement() throws SQLException { return conn.prepareStatement("select * from dual", ArrayUtils.EMPTY_STRING_ARRAY); } } private DriverAdapterCPDS pcds; private DataSource ds; private void doTestPoolCallableStatements(final AbstractPrepareCallCallback callBack) throws Exception { final DriverAdapterCPDS myPcds = new DriverAdapterCPDS(); myPcds.setDriver("org.apache.commons.dbcp2.TesterDriver"); myPcds.setUrl("jdbc:apache:commons:testdriver"); myPcds.setUser("foo"); myPcds.setPassword("bar"); myPcds.setPoolPreparedStatements(true); myPcds.setMaxPreparedStatements(10); try (final SharedPoolDataSource spDs = new SharedPoolDataSource()) { spDs.setConnectionPoolDataSource(myPcds); spDs.setMaxTotal(getMaxTotal()); spDs.setDefaultMaxWait(getMaxWaitDuration()); spDs.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); @SuppressWarnings("resource") final DataSource myDs = spDs; try (Connection conn = ds.getConnection()) { callBack.setConnection(conn); assertNotNull(conn); final long l1HashCode; final long l2HashCode; try (CallableStatement stmt = callBack.getCallableStatement()) { assertNotNull(stmt); l1HashCode = getDelegateHashCode(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } try (CallableStatement stmt = callBack.getCallableStatement()) { assertNotNull(stmt); l2HashCode = getDelegateHashCode(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } // statement pooling is not enabled, we should get different statements assertTrue(l1HashCode != l2HashCode); } try (Connection conn = myDs.getConnection()) { callBack.setConnection(conn); final long l3HashCode; final long l4HashCode; try (CallableStatement stmt = callBack.getCallableStatement()) { assertNotNull(stmt); l3HashCode = getDelegateHashCode(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } try (CallableStatement stmt = callBack.getCallableStatement()) { assertNotNull(stmt); l4HashCode = getDelegateHashCode(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } // prepared statement pooling is working assertEquals(l3HashCode, l4HashCode); } } } private void doTestPoolPreparedStatements(final AbstractPrepareStatementCallback psCallBack) throws Exception { final DriverAdapterCPDS mypcds = new DriverAdapterCPDS(); mypcds.setDriver("org.apache.commons.dbcp2.TesterDriver"); mypcds.setUrl("jdbc:apache:commons:testdriver"); mypcds.setUser("foo"); mypcds.setPassword("bar"); mypcds.setPoolPreparedStatements(true); mypcds.setMaxPreparedStatements(10); try (final SharedPoolDataSource tds = new SharedPoolDataSource()) { tds.setConnectionPoolDataSource(mypcds); tds.setMaxTotal(getMaxTotal()); tds.setDefaultMaxWait(getMaxWaitDuration()); tds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); @SuppressWarnings("resource") final DataSource myDs = tds; try (Connection conn = ds.getConnection()) { final long l1HashCode; final long l2HashCode; assertNotNull(conn); psCallBack.setConnection(conn); try (PreparedStatement stmt = psCallBack.prepareStatement()) { assertNotNull(stmt); l1HashCode = getDelegateHashCode(stmt); try (ResultSet resultSet = stmt.executeQuery()) { assertNotNull(resultSet); assertTrue(resultSet.next()); } } try (PreparedStatement stmt = psCallBack.prepareStatement()) { assertNotNull(stmt); l2HashCode = getDelegateHashCode(stmt); try (ResultSet resultSet = stmt.executeQuery()) { assertNotNull(resultSet); assertTrue(resultSet.next()); } } // statement pooling is not enabled, we should get different statements assertTrue(l1HashCode != l2HashCode); } try (Connection conn = myDs.getConnection()) { final long l3HashCode; final long l4HashCode; assertNotNull(conn); psCallBack.setConnection(conn); try (PreparedStatement stmt = psCallBack.prepareStatement()) { assertNotNull(stmt); l3HashCode = getDelegateHashCode(stmt); try (ResultSet resultSet = stmt.executeQuery()) { assertNotNull(resultSet); assertTrue(resultSet.next()); } } try (PreparedStatement stmt = psCallBack.prepareStatement()) { assertNotNull(stmt); l4HashCode = getDelegateHashCode(stmt); try (ResultSet resultSet = stmt.executeQuery()) { assertNotNull(resultSet); assertTrue(resultSet.next()); } } // prepared statement pooling is working assertEquals(l3HashCode, l4HashCode); } } } @Override protected Connection getConnection() throws Exception { return ds.getConnection("foo","bar"); } @SuppressWarnings("resource") private int getDelegateHashCode(final Statement stmt) { return ((DelegatingStatement) stmt).getDelegate().hashCode(); } @BeforeEach public void setUp() throws Exception { pcds = new DriverAdapterCPDS(); pcds.setDriver("org.apache.commons.dbcp2.TesterDriver"); pcds.setUrl("jdbc:apache:commons:testdriver"); pcds.setUser("foo"); pcds.setPassword("bar"); pcds.setPoolPreparedStatements(false); pcds.setAccessToUnderlyingConnectionAllowed(true); final SharedPoolDataSource tds = new SharedPoolDataSource(); tds.setConnectionPoolDataSource(pcds); tds.setMaxTotal(getMaxTotal()); tds.setDefaultMaxWait(getMaxWaitDuration()); tds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); tds.setDefaultAutoCommit(Boolean.TRUE); ds = tds; } // See DBCP-8 @Test public void testChangePassword() throws Exception { assertThrows(SQLException.class, () -> ds.getConnection("foo", "bay")); final Connection con1 = ds.getConnection("foo", "bar"); final Connection con2 = ds.getConnection("foo", "bar"); final Connection con3 = ds.getConnection("foo", "bar"); con1.close(); con2.close(); TesterDriver.addUser("foo", "bay"); // change the user/password setting try (Connection con4 = ds.getConnection("foo", "bay")) { // new password // Idle instances with old password should have been cleared assertEquals(0, ((SharedPoolDataSource) ds).getNumIdle(), "Should be no idle connections in the pool"); con4.close(); // Should be one idle instance with new pwd assertEquals(1, ((SharedPoolDataSource) ds).getNumIdle(), "Should be one idle connection in the pool"); assertThrows(SQLException.class, () -> ds.getConnection("foo", "bar")); // old password try (final Connection con5 = ds.getConnection("foo", "bay")) { // take the idle one con3.close(); // Return a connection with the old password ds.getConnection("foo", "bay").close(); // will try bad returned connection and destroy it assertEquals(1, ((SharedPoolDataSource) ds).getNumIdle(), "Should be one idle connection in the pool"); } } finally { TesterDriver.addUser("foo", "bar"); } } /** * Tests pool close. Illustrates BZ 37359. * * @throws Exception */ @Test public void testClosePool() throws Exception { ((SharedPoolDataSource) ds).close(); @SuppressWarnings("resource") // closed below final SharedPoolDataSource tds = new SharedPoolDataSource(); // NPE before BZ 37359 fix tds.close(); } @Override @Test public void testClosing() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; // open the maximum connections for (int i = 0; i < c.length; i++) { c[i] = ds.getConnection(); } // close one of the connections c[0].close(); assertTrue(c[0].isClosed()); // get a new connection c[0] = ds.getConnection(); for (final Connection element : c) { element.close(); } } @Test public void testClosingWithUserName() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; // open the maximum connections for (int i = 0; i < c.length; i++) { c[i] = ds.getConnection("u1", "p1"); } // close one of the connections c[0].close(); assertTrue(c[0].isClosed()); // get a new connection c[0] = ds.getConnection("u1", "p1"); for (final Connection element : c) { element.close(); } // open the maximum connections for (int i = 0; i < c.length; i++) { c[i] = ds.getConnection("u1", "p1"); } for (final Connection element : c) { element.close(); } } @Test public void testDbcp369() { final ArrayList dataSources = new ArrayList<>(); for (int j = 0; j < 10000; j++) { dataSources.add(new SharedPoolDataSource()); } final Thread t1 = new Thread(() -> { for (final SharedPoolDataSource dataSource : dataSources) { dataSource.setDataSourceName("a"); } }); final Thread t2 = new Thread(() -> { for (final SharedPoolDataSource dataSource : dataSources) { try { dataSource.close(); } catch (final Exception e) { // Ignore } } }); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (final InterruptedException ie) { // Ignore } } /** * Starting with a successful connection, then incorrect password, * then correct password for same user illustrates * JIRA: DBCP-245 */ @Test public void testIncorrectPassword() throws SQLException { ds.getConnection("u2", "p2").close(); try (Connection c = ds.getConnection("u1", "zlsafjk")){ // Use bad password fail("Able to retrieve connection with incorrect password"); } catch (final SQLException e1) { // should fail } // Use good password ds.getConnection("u1", "p1").close(); try (Connection c = ds.getConnection("u1", "x")) { fail("Able to retrieve connection with incorrect password"); } catch (final SQLException e) { if (!e.getMessage().startsWith("Given password did not match")) { throw e; } // else the exception was expected } // Make sure we can still use our good password. ds.getConnection("u1", "p1").close(); // Try related users and passwords ds.getConnection("foo", "bar").close(); try (Connection c = ds.getConnection("u1", "ar")) { fail("Should have caused an SQLException"); } catch (final SQLException expected) { } try (Connection c = ds.getConnection("u1", "baz")) { fail("Should have generated SQLException"); } catch (final SQLException expected) { } } @Override @Test public void testMaxTotal() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; for (int i=0; i conn.createStatement(), "Can't use closed connections"); } try (Connection conn = ds.getConnection()) { assertNotNull(conn); try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } try (PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } } @Test public void testSimpleWithUsername() throws Exception { try (final Connection conn = ds.getConnection("u1", "p1")) { assertNotNull(conn); try (final PreparedStatement stmt = conn.prepareStatement("select * from dual")) { assertNotNull(stmt); try (final ResultSet rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } } @Test public void testTransactionIsolationBehavior() throws Exception { try (final Connection conn = getConnection()) { assertNotNull(conn); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn.getTransactionIsolation()); conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); } final Connection conn2 = getConnection(); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn2.getTransactionIsolation()); final Connection conn3 = getConnection(); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn3.getTransactionIsolation()); conn2.close(); conn3.close(); } } TestUserPassKey.java000066400000000000000000000057311472045345700346610ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/datasources/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.datasources; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.apache.commons.dbcp2.Utils; import org.apache.commons.lang3.SerializationUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests for UserPassKey. */ public class TestUserPassKey { private UserPassKey userPassKey; private UserPassKey anotherUserPassKey; @BeforeEach public void setUp() { userPassKey = new UserPassKey("user", "pass"); anotherUserPassKey = new UserPassKey((String) null, ""); } @Test public void testEquals() { assertEquals(new UserPassKey("user"), new UserPassKey("user", (char[]) null)); assertEquals(userPassKey, userPassKey); assertNotEquals(userPassKey, null); assertNotEquals(userPassKey, new Object()); assertNotEquals(new UserPassKey(null), userPassKey); assertEquals(new UserPassKey(null), new UserPassKey(null)); assertNotEquals(new UserPassKey("user", "pass"), new UserPassKey("foo", "pass")); } @Test public void testGettersAndSetters() { assertEquals("user", userPassKey.getUserName()); assertEquals("pass", userPassKey.getPassword()); assertArrayEquals(Utils.toCharArray("pass"), userPassKey.getPasswordCharArray()); } @Test public void testHashcode() { assertEquals(userPassKey.hashCode(), new UserPassKey("user", "pass").hashCode()); assertNotEquals(userPassKey.hashCode(), anotherUserPassKey.hashCode()); } @Test public void testSerialization() { assertEquals(userPassKey, SerializationUtils.roundtrip(userPassKey)); assertEquals(anotherUserPassKey, SerializationUtils.roundtrip(anotherUserPassKey)); } @Test public void testToString() { assertEquals(userPassKey.toString(), new UserPassKey("user", "pass").toString()); assertNotEquals(userPassKey.toString(), anotherUserPassKey.toString()); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/000077500000000000000000000000001472045345700300705ustar00rootroot00000000000000TestBasicManagedDataSource.java000066400000000000000000000264561472045345700360020ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.SQLException; import javax.sql.XADataSource; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAException; import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.TestBasicDataSource; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.h2.Driver; import org.h2.jdbcx.JdbcDataSource; import org.junit.jupiter.api.Test; import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple; import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionSynchronizationRegistryImple; /** * TestSuite for BasicManagedDataSource */ public class TestBasicManagedDataSource extends TestBasicDataSource { @Override protected BasicDataSource createDataSource() throws Exception { final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource(); final TransactionManagerImpl transactionManager = new TransactionManagerImpl(); basicManagedDataSource.setTransactionManager(transactionManager); basicManagedDataSource.setTransactionSynchronizationRegistry(transactionManager); return basicManagedDataSource; } @Test public void testCreateXaDataSourceNewInstance() throws SQLException, XAException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setXADataSource(JdbcDataSource.class.getCanonicalName()); basicManagedDataSource.setDriverClassName(Driver.class.getName()); basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); assertNotNull(basicManagedDataSource.createConnectionFactory()); } } @Test public void testCreateXaDataSourceNoInstanceSetAndNoDataSource() throws SQLException, XAException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver"); basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); assertNotNull(basicManagedDataSource.createConnectionFactory()); } } /** * JIRA: DBCP-294 * Verify that PoolableConnections created by BasicManagedDataSource unregister themselves * when reallyClosed. */ @Test public void testReallyClose() throws Exception { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver"); basicManagedDataSource.setUsername("userName"); basicManagedDataSource.setPassword("password"); basicManagedDataSource.setMaxIdle(1); // Create two connections final ManagedConnection conn = (ManagedConnection) basicManagedDataSource.getConnection(); assertNotNull(basicManagedDataSource.getTransactionRegistry().getXAResource(conn)); final ManagedConnection conn2 = (ManagedConnection) basicManagedDataSource.getConnection(); conn2.close(); // Return one connection to the pool conn.close(); // No room at the inn - this will trigger reallyClose(), which should unregister assertThrows(SQLException.class, () -> basicManagedDataSource.getTransactionRegistry().getXAResource(conn), "Expecting SQLException - XAResources orphaned"); conn2.close(); } } @Test public void testRuntimeExceptionsAreRethrown() throws SQLException, XAException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver"); basicManagedDataSource.setUsername("userName"); basicManagedDataSource.setPassword("password"); basicManagedDataSource.setMaxIdle(1); // results in a NPE assertThrows(NullPointerException.class, () -> basicManagedDataSource.createPoolableConnectionFactory(null)); } } @Test public void testSetDriverName() throws SQLException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setDriverClassName("adams"); assertEquals("adams", basicManagedDataSource.getDriverClassName()); basicManagedDataSource.setDriverClassName(null); assertNull(basicManagedDataSource.getDriverClassName()); } } @Test public void testSetNullXaDataSourceInstance() throws SQLException, XAException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver"); basicManagedDataSource.setUsername("userName"); basicManagedDataSource.setPassword("password"); basicManagedDataSource.setMaxIdle(1); basicManagedDataSource.setXaDataSourceInstance(null); assertNull(basicManagedDataSource.getXaDataSourceInstance()); } } /** DBCP-564 */ @Test public void testSetRollbackOnlyBeforeGetConnectionDoesNotLeak() throws Exception { final TransactionManager transactionManager = ((BasicManagedDataSource) ds).getTransactionManager(); final int n = 3; ds.setMaxIdle(n); ds.setMaxTotal(n); for (int i = 0; i <= n; i++) { // loop n+1 times transactionManager.begin(); transactionManager.setRollbackOnly(); try (final Connection conn = getConnection()) { assertNotNull(conn); } transactionManager.rollback(); } assertEquals(0, ds.getNumActive()); assertEquals(1, ds.getNumIdle()); } @Test public void testSetXaDataSourceInstance() throws SQLException, XAException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver"); basicManagedDataSource.setUsername("userName"); basicManagedDataSource.setPassword("password"); basicManagedDataSource.setMaxIdle(1); basicManagedDataSource.setXaDataSourceInstance(new JdbcDataSource()); assertNotNull(basicManagedDataSource.createConnectionFactory()); } } @Test public void testTransactionManagerNotSet() throws SQLException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { assertThrows(SQLException.class, basicManagedDataSource::createConnectionFactory); } } @Test public void testTransactionSynchronizationRegistry() throws Exception { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setTransactionManager(new TransactionManagerImple()); final TransactionSynchronizationRegistry tsr = new TransactionSynchronizationRegistryImple(); basicManagedDataSource.setTransactionSynchronizationRegistry(tsr); final JdbcDataSource xaDataSource = new JdbcDataSource(); xaDataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"); basicManagedDataSource.setXaDataSourceInstance(xaDataSource); basicManagedDataSource.setMaxIdle(1); final TransactionManager tm = basicManagedDataSource.getTransactionManager(); tm.begin(); tsr.registerInterposedSynchronization(new SynchronizationAdapter() { @Override public void beforeCompletion() { Connection connection = null; try { connection = basicManagedDataSource.getConnection(); assertNotNull(connection); } catch (final SQLException e) { fail(e.getMessage()); } finally { if (connection != null) { try { connection.close(); } catch (final SQLException e) { fail(e.getMessage()); } } } } }); tm.commit(); } } @Test public void testXADataSource() throws SQLException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setXADataSource("anything"); assertEquals("anything", basicManagedDataSource.getXADataSource()); } } @Test public void testXaDataSourceInstance() throws SQLException { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { final XADataSource ds = new JdbcDataSource(); basicManagedDataSource.setXaDataSourceInstance(ds); assertEquals(ds, basicManagedDataSource.getXaDataSourceInstance()); } } } TestConnectionWithNarayana.java000066400000000000000000000204571472045345700361320ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.time.Duration; import javax.transaction.RollbackException; import javax.transaction.Status; import org.apache.commons.dbcp2.Utils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple; import com.arjuna.ats.jta.common.jtaPropertyManager; /** * Requires Java 8 or above. */ public class TestConnectionWithNarayana { private static final String CREATE_STMT = "CREATE TABLE TEST_DATA (KEY1 VARCHAR(100), ID BIGINT, VALUE1 DOUBLE PRECISION, INFO TEXT, TS TIMESTAMP)"; private static final String INSERT_STMT = "INSERT INTO TEST_DATA (KEY1, ID, VALUE1, INFO, TS) VALUES (?,?,?,?,?)"; private static final String SELECT_STMT = "SELECT KEY1, ID, VALUE1, INFO, TS FROM TEST_DATA LIMIT 1"; private static final String PAYLOAD; private static final String DROP_STMT = "DROP TABLE TEST_DATA"; static { final StringBuilder sb = new StringBuilder(); sb.append("Start"); sb.append("payload"); for (int i = 0; i < 10000; i++) { sb.append("..."); sb.append(i); } sb.append("End"); sb.append("payload"); PAYLOAD = sb.toString(); } private BasicManagedDataSource mds; @BeforeEach public void setUp() throws Exception { jtaPropertyManager.getJTAEnvironmentBean().setLastResourceOptimisationInterfaceClassName( "org.apache.commons.dbcp2.managed.LocalXAConnectionFactory$LocalXAResource"); mds = new BasicManagedDataSource(); mds.setTransactionManager(new TransactionManagerImple()); mds.setDriverClassName("org.h2.Driver"); mds.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"); mds.setMaxTotal(80); mds.setMinIdle(0); mds.setMaxIdle(80); mds.setMinEvictableIdle(Duration.ofSeconds(10)); mds.setDurationBetweenEvictionRuns(Duration.ofSeconds(10)); mds.setLogAbandoned(true); mds.setMaxWait(Duration.ofSeconds(2)); mds.setRemoveAbandonedOnMaintenance(true); mds.setRemoveAbandonedOnBorrow(true); mds.setRemoveAbandonedTimeout(Duration.ofSeconds(10)); mds.setLogExpiredConnections(true); mds.setLifo(false); try (final Connection conn = mds.getConnection()) { try (final PreparedStatement ps = conn.prepareStatement(CREATE_STMT)) { ps.execute(); } } } @AfterEach public void tearDown() throws Exception { try (final Connection conn = mds.getConnection()) { try (final PreparedStatement ps = conn.prepareStatement(DROP_STMT)) { ps.execute(); } } Utils.closeQuietly(mds); } @Test public void testConnectionCommitAfterTimeout() throws Exception { mds.getTransactionManager().setTransactionTimeout(1); mds.getTransactionManager().begin(); try (Connection conn = mds.getConnection()) { do { Thread.sleep(1000); } while (mds.getTransactionManager().getTransaction().getStatus() != Status.STATUS_ROLLEDBACK); // Let the reaper do it's thing Thread.sleep(1000); try { conn.commit(); fail("Should not work after timeout"); } catch (final SQLException e) { // Expected Assertions.assertEquals("Commit cannot be set while enrolled in a transaction", e.getMessage()); } mds.getTransactionManager().rollback(); } Assertions.assertEquals(0, mds.getNumActive()); } @Test public void testConnectionInTimeout() throws Exception { Connection conn = null; PreparedStatement ps = null; for (int i = 0; i < 5; i++) { try { mds.getTransactionManager().setTransactionTimeout(1); mds.getTransactionManager().begin(); conn = mds.getConnection(); ps = conn.prepareStatement(INSERT_STMT); ps.setString(1, Thread.currentThread().getName()); ps.setLong(2, i); ps.setDouble(3, new java.util.Random().nextDouble()); ps.setString(4, PAYLOAD); ps.setTimestamp(5, new Timestamp(System.currentTimeMillis())); ps.execute(); int n = 0; do { if (mds.getTransactionManager().getTransaction().getStatus() != Status.STATUS_ACTIVE) { n++; } try (Connection c = mds.getConnection(); PreparedStatement ps2 = c.prepareStatement(SELECT_STMT); ResultSet rs = ps2.executeQuery()) { // nothing here, all auto-close. } } while (n < 2); ps.close(); ps = null; conn.close(); conn = null; try { mds.getTransactionManager().commit(); fail("Should not have been able to commit"); } catch (final RollbackException e) { // this is expected if (mds.getTransactionManager().getTransaction() != null) { // Need to pop it off the thread if a background thread rolled the transaction back mds.getTransactionManager().rollback(); } } } catch (final Exception e) { if (mds.getTransactionManager().getTransaction() != null) { // Need to pop it off the thread if a background thread rolled the transaction back mds.getTransactionManager().rollback(); } } finally { if (ps != null) { ps.close(); } if (conn != null) { conn.close(); } } Assertions.assertEquals(0, mds.getNumActive()); } } @Test public void testRepeatedGetConnectionInTimeout() throws Exception { mds.getTransactionManager().setTransactionTimeout(1); mds.getTransactionManager().begin(); try { do { Thread.sleep(1000); } while (mds.getTransactionManager().getTransaction().getStatus() != Status.STATUS_ROLLEDBACK); // Let the reaper do it's thing Thread.sleep(1000); try (Connection conn = mds.getConnection()) { fail("Should not get the connection 1"); } catch (final SQLException e) { if (!e.getCause().getClass().equals(IllegalStateException.class)) { throw e; } try (Connection conn = mds.getConnection()) { fail("Should not get connection 2"); } catch (final SQLException e2) { if (!e2.getCause().getClass().equals(IllegalStateException.class)) { throw e2; } } } } finally { mds.getTransactionManager().rollback(); } Assertions.assertEquals(0, mds.getNumActive()); } }TestDataSourceXAConnectionFactory.java000066400000000000000000000076341472045345700373610ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertEquals; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.SQLException; import java.util.concurrent.atomic.AtomicInteger; import javax.sql.XAConnection; import javax.sql.XADataSource; import org.apache.commons.dbcp2.TestBasicDataSource; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * TestSuite for BasicManagedDataSource when using a * DataSourceXAConnectionFactory (configured from a XADataSource) */ public class TestDataSourceXAConnectionFactory extends TestBasicDataSource { /** * Delegates everything to the BasicDataSource (ds field), except for * getXAConnection which creates a BasicXAConnection. */ public class XADataSourceHandle implements InvocationHandler { protected XAConnection getXAConnection() throws SQLException { return new TesterBasicXAConnection(ds.getConnection(), closeCounter); } @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { final String methodName = method.getName(); switch (methodName) { case "hashCode": return System.identityHashCode(proxy); case "equals": return proxy == args[0]; case "getXAConnection": // both zero and 2-arg signatures return getXAConnection(); default: break; } try { return method.invoke(ds, args); } catch (final InvocationTargetException e) { throw e.getTargetException(); } } } protected BasicManagedDataSource bmds; public final AtomicInteger closeCounter = new AtomicInteger(); @Override @BeforeEach public void setUp() throws Exception { super.setUp(); bmds = new BasicManagedDataSource(); bmds.setTransactionManager(new TransactionManagerImpl()); bmds.setXADataSource("notnull"); final XADataSourceHandle handle = new XADataSourceHandle(); final XADataSource xads = (XADataSource) Proxy.newProxyInstance( XADataSourceHandle.class.getClassLoader(), new Class[] { XADataSource.class }, handle); bmds.setXaDataSourceInstance(xads); } /** * JIRA: DBCP-355 */ @Test public void testPhysicalClose() throws Exception { bmds.setMaxIdle(1); final Connection conn1 = bmds.getConnection(); final Connection conn2 = bmds.getConnection(); closeCounter.set(0); conn1.close(); assertEquals(0, closeCounter.get()); // stays idle in the pool conn2.close(); assertEquals(1, closeCounter.get()); // can't have 2 idle ones bmds.close(); assertEquals(2, closeCounter.get()); } } TestLocalXaResource.java000066400000000000000000000451241472045345700345550ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.SQLClientInfoException; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Savepoint; import java.sql.Statement; import java.sql.Struct; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests for LocalXAConnectionFactory$LocalXAResource */ public class TestLocalXaResource { private static final class TestConnection implements Connection { public boolean throwWhenGetAutoCommit; public boolean throwWhenSetAutoCommit; boolean autoCommit; boolean readOnly; public boolean committed; public boolean rolledback; public boolean closed; @Override public void abort(final Executor executor) throws SQLException { } @Override public void clearWarnings() throws SQLException { } @Override public void close() throws SQLException { closed = true; } @Override public void commit() throws SQLException { committed = true; } @Override public Array createArrayOf(final String typeName, final Object[] elements) throws SQLException { return null; } @Override public Blob createBlob() throws SQLException { return null; } @Override public Clob createClob() throws SQLException { return null; } @Override public NClob createNClob() throws SQLException { return null; } @Override public SQLXML createSQLXML() throws SQLException { return null; } @Override public Statement createStatement() throws SQLException { return null; } @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException { return null; } @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { return null; } @Override public Struct createStruct(final String typeName, final Object[] attributes) throws SQLException { return null; } @Override public boolean getAutoCommit() throws SQLException { if (throwWhenGetAutoCommit) { throw new SQLException(); } return autoCommit; } @Override public String getCatalog() throws SQLException { return null; } @Override public Properties getClientInfo() throws SQLException { return null; } @Override public String getClientInfo(final String name) throws SQLException { return null; } @Override public int getHoldability() throws SQLException { return 0; } @Override public DatabaseMetaData getMetaData() throws SQLException { return null; } @Override public int getNetworkTimeout() throws SQLException { return 0; } @Override public String getSchema() throws SQLException { return null; } @Override public int getTransactionIsolation() throws SQLException { return 0; } @Override public Map> getTypeMap() throws SQLException { return null; } @Override public SQLWarning getWarnings() throws SQLException { return null; } @Override public boolean isClosed() throws SQLException { return closed; } @Override public boolean isReadOnly() throws SQLException { return readOnly; } @Override public boolean isValid(final int timeout) throws SQLException { return false; } @Override public boolean isWrapperFor(final Class iface) throws SQLException { return false; } @Override public String nativeSQL(final String sql) throws SQLException { return null; } @Override public CallableStatement prepareCall(final String sql) throws SQLException { return null; } @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { return null; } @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(final String sql) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { return null; } @Override public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { return null; } @Override public void releaseSavepoint(final Savepoint savepoint) throws SQLException { } @Override public void rollback() throws SQLException { rolledback = true; } @Override public void rollback(final Savepoint savepoint) throws SQLException { } @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { if (throwWhenSetAutoCommit) { throw new SQLException(); } this.autoCommit = autoCommit; } @Override public void setCatalog(final String catalog) throws SQLException { } @Override public void setClientInfo(final Properties properties) throws SQLClientInfoException { } @Override public void setClientInfo(final String name, final String value) throws SQLClientInfoException { } @Override public void setHoldability(final int holdability) throws SQLException { } @Override public void setNetworkTimeout(final Executor executor, final int milliseconds) throws SQLException { } @Override public void setReadOnly(final boolean readOnly) throws SQLException { this.readOnly = readOnly; } @Override public Savepoint setSavepoint() throws SQLException { return null; } @Override public Savepoint setSavepoint(final String name) throws SQLException { return null; } @Override public void setSchema(final String schema) throws SQLException { } @Override public void setTransactionIsolation(final int level) throws SQLException { } @Override public void setTypeMap(final Map> map) throws SQLException { } @Override public T unwrap(final Class iface) throws SQLException { return null; } } private static final class TestXid implements Xid { @Override public byte[] getBranchQualifier() { return null; } @Override public int getFormatId() { return 0; } @Override public byte[] getGlobalTransactionId() { return null; } } private Connection conn; private LocalXAConnectionFactory.LocalXAResource resource; @BeforeEach public void setUp() { conn = new TestConnection(); resource = new LocalXAConnectionFactory.LocalXAResource(conn); } @Test public void testCommit() throws SQLException, XAException { final Xid xid = new TestXid(); ((TestConnection) conn).closed = false; conn.setReadOnly(false); resource.start(xid, XAResource.TMNOFLAGS); resource.commit(xid, false); assertTrue(((TestConnection) conn).committed); } @Test public void testCommitConnectionClosed() throws SQLException, XAException { final Xid xid = new TestXid(); ((TestConnection) conn).closed = true; conn.setReadOnly(false); resource.start(xid, XAResource.TMNOFLAGS); assertThrows(XAException.class, () -> resource.commit(xid, false)); } @Test public void testCommitConnectionNotReadOnly() throws SQLException, XAException { final Xid xid = new TestXid(); ((TestConnection) conn).closed = false; conn.setReadOnly(true); resource.start(xid, XAResource.TMNOFLAGS); resource.commit(xid, false); assertFalse(((TestConnection) conn).committed); } @Test public void testCommitInvalidXid() throws SQLException, XAException { final Xid xid = new TestXid(); ((TestConnection) conn).closed = false; conn.setReadOnly(false); resource.start(xid, XAResource.TMNOFLAGS); assertThrows(XAException.class, () -> resource.commit(new TestXid(), false)); } @Test public void testCommitMissingXid() { assertThrows(NullPointerException.class, () -> resource.commit(null, false)); } @Test public void testCommitNoTransaction() throws SQLException { ((TestConnection) conn).closed = false; conn.setReadOnly(false); assertThrows(XAException.class, () -> resource.commit(new TestXid(), false)); } @Test public void testConstructor() { assertEquals(0, resource.getTransactionTimeout()); assertNull(resource.getXid()); // the current implementation always return false, regardless of the input value assertFalse(resource.setTransactionTimeout(100)); // the current implementation always return an empty/zero'd array, regardless of the input value assertEquals(0, resource.recover(100).length); } @Test public void testForget() throws XAException { final Xid xid = new TestXid(); resource.start(xid, XAResource.TMNOFLAGS); resource.forget(xid); assertNull(resource.getXid()); } @Test public void testForgetDifferentXid() throws XAException { final Xid xid = new TestXid(); resource.start(xid, XAResource.TMNOFLAGS); resource.forget(new TestXid()); assertEquals(xid, resource.getXid()); } @Test public void testForgetMissingXid() throws XAException { final Xid xid = new TestXid(); resource.start(xid, XAResource.TMNOFLAGS); resource.forget(null); assertEquals(xid, resource.getXid()); } @Test public void testIsSame() { assertTrue(resource.isSameRM(resource)); assertFalse(resource.isSameRM(new LocalXAConnectionFactory.LocalXAResource(conn))); } @Test public void testRollback() throws SQLException, XAException { final Xid xid = new TestXid(); ((TestConnection) conn).closed = false; conn.setReadOnly(false); resource.start(xid, XAResource.TMNOFLAGS); resource.rollback(xid); assertTrue(((TestConnection) conn).rolledback); } @Test public void testRollbackInvalidXid() throws SQLException, XAException { final Xid xid = new TestXid(); ((TestConnection) conn).closed = false; conn.setReadOnly(false); resource.start(xid, XAResource.TMNOFLAGS); assertThrows(XAException.class, () -> resource.rollback(new TestXid())); } @Test public void testRollbackMissingXid() { assertThrows(NullPointerException.class, () -> resource.rollback(null)); } /** * When an exception is thrown on the {@link Connection#getAutoCommit()}, then the * value is set to {@code true} by default. * @throws XAException when there are errors with the transaction * @throws SQLException when there are errors with other SQL/DB parts */ @Test public void testStartExceptionOnGetAutoCommit() throws XAException, SQLException { final Xid xid = new TestXid(); ((TestConnection) conn).throwWhenGetAutoCommit = true; conn.setAutoCommit(false); conn.setReadOnly(true); // the start method with no flag will call getAutoCommit, the exception will be thrown, and it will be set // to true resource.start(xid, XAResource.TMNOFLAGS); // and prepare sets the value computed in start in the connection resource.prepare(xid); ((TestConnection) conn).throwWhenGetAutoCommit = false; assertTrue(conn.getAutoCommit()); } @Test public void testStartFailsWhenCannotSetAutoCommit() { final Xid xid = new TestXid(); ((TestConnection) conn).throwWhenSetAutoCommit = true; assertThrows(XAException.class, () -> resource.start(xid, XAResource.TMNOFLAGS)); } @Test public void testStartInvalidFlag() { // currently, valid values are TMNOFLAGS and TMRESUME assertThrows(XAException.class, () -> resource.start(null, XAResource.TMENDRSCAN)); } @Test public void testStartNoFlagButAlreadyEnlisted() throws XAException { resource.start(new TestXid(), XAResource.TMNOFLAGS); assertThrows(XAException.class, () -> resource.start(new TestXid(), XAResource.TMNOFLAGS)); } @Test public void testStartNoFlagResume() throws XAException { final Xid xid = new TestXid(); resource.start(xid, XAResource.TMNOFLAGS); resource.start(xid, XAResource.TMRESUME); assertEquals(xid, resource.getXid()); } @Test public void testStartNoFlagResumeButDifferentXid() throws XAException { resource.start(new TestXid(), XAResource.TMNOFLAGS); assertThrows(XAException.class, () -> resource.start(new TestXid(), XAResource.TMRESUME)); } @Test public void testStartNoFlagResumeEnd() throws XAException { final Xid xid = new TestXid(); resource.start(xid, XAResource.TMNOFLAGS); resource.start(xid, XAResource.TMRESUME); // flag is never used in the end resource.end(xid, 0); assertEquals(xid, resource.getXid()); } @Test public void testStartNoFlagResumeEndDifferentXid() throws XAException { final Xid xid = new TestXid(); resource.start(xid, XAResource.TMNOFLAGS); resource.start(xid, XAResource.TMRESUME); // flag is never used in the end assertThrows(XAException.class, () -> resource.end(new TestXid(), 0)); } @Test public void testStartNoFlagResumeEndMissingXid() throws XAException { final Xid xid = new TestXid(); resource.start(xid, XAResource.TMNOFLAGS); resource.start(xid, XAResource.TMRESUME); // flag is never used in the end assertThrows(NullPointerException.class, () -> resource.end(null, 0)); } /** * When an exception is thrown on the {@link Connection#getAutoCommit()}, then the * value is set to {@code true} by default. However, if the connection is not read-only, * then the value set by the user in the original connection will be kept. * @throws XAException when there are errors with the transaction * @throws SQLException when there are errors with other SQL/DB parts */ @Test public void testStartReadOnlyConnectionExceptionOnGetAutoCommit() throws XAException, SQLException { final Xid xid = new TestXid(); ((TestConnection) conn).throwWhenGetAutoCommit = true; conn.setAutoCommit(false); conn.setReadOnly(false); // the start method with no flag will call getAutoCommit, the exception will be thrown, and it will be set // to true resource.start(xid, XAResource.TMNOFLAGS); // and prepare sets the value computed in start in the connection resource.prepare(xid); ((TestConnection) conn).throwWhenGetAutoCommit = false; assertFalse(conn.getAutoCommit()); } @Test public void testStartReadOnlyConnectionPrepare() throws XAException, SQLException { final Xid xid = new TestXid(); conn.setAutoCommit(false); conn.setReadOnly(true); resource.start(xid, XAResource.TMNOFLAGS); resource.prepare(xid); assertFalse(conn.getAutoCommit()); } } TestManagedConnection.java000066400000000000000000000165621472045345700351020ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import java.util.Properties; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.RollbackException; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.xa.XAResource; import org.apache.commons.dbcp2.ConnectionFactory; import org.apache.commons.dbcp2.Constants; import org.apache.commons.dbcp2.DriverConnectionFactory; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.PoolingDataSource; import org.apache.commons.dbcp2.TesterDriver; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * TestSuite for ManagedConnection. */ public class TestManagedConnection { private final class UncooperativeLocalXAConnectionFactory extends LocalXAConnectionFactory { public UncooperativeLocalXAConnectionFactory(final TransactionManager transactionManager, final ConnectionFactory connectionFactory) { super(transactionManager, connectionFactory); try { // inject our own TransactionRegistry which returns Uncooperative Transactions which always fail to enlist a XAResource final Field field = LocalXAConnectionFactory.class.getDeclaredField("transactionRegistry"); field.setAccessible(true); field.set(this, new UncooperativeTransactionRegistry(transactionManager)); } catch (final Exception e) { e.printStackTrace(); } } } /** * Transaction that always fails enlistResource. */ private static final class UncooperativeTransaction implements Transaction { private final Transaction wrappedTransaction; public UncooperativeTransaction(final Transaction transaction) { this.wrappedTransaction = transaction; } @Override public void commit() throws HeuristicMixedException, HeuristicRollbackException, RollbackException, SecurityException, SystemException { wrappedTransaction.commit(); } @Override public boolean delistResource(final XAResource arg0, final int arg1) throws IllegalStateException, SystemException { return wrappedTransaction.delistResource(arg0, arg1); } @Override public synchronized boolean enlistResource(final XAResource xaRes) { return false; } @Override public int getStatus() throws SystemException { return wrappedTransaction.getStatus(); } @Override public void registerSynchronization(final Synchronization arg0) throws IllegalStateException, RollbackException, SystemException { wrappedTransaction.registerSynchronization(arg0); } @Override public void rollback() throws IllegalStateException, SystemException { wrappedTransaction.rollback(); } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { wrappedTransaction.setRollbackOnly(); } } private final class UncooperativeTransactionRegistry extends TransactionRegistry { public UncooperativeTransactionRegistry(final TransactionManager transactionManager) { super(transactionManager); } @Override public TransactionContext getActiveTransactionContext() throws SQLException { try { return new TransactionContext(this, new UncooperativeTransaction(transactionManager.getTransaction())); } catch (final SystemException e) { return null; } } } protected PoolingDataSource ds; private GenericObjectPool pool; protected TransactionManager transactionManager; public Connection getConnection() throws Exception { return ds.getConnection(); } @BeforeEach public void setUp() throws Exception { // create a GeronimoTransactionManager for testing transactionManager = new TransactionManagerImpl(); // create a driver connection factory final Properties properties = new Properties(); properties.setProperty(Constants.KEY_USER, "userName"); properties.setProperty(Constants.KEY_PASSWORD, "password"); final ConnectionFactory connectionFactory = new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", properties); // wrap it with a LocalXAConnectionFactory final XAConnectionFactory xaConnectionFactory = new UncooperativeLocalXAConnectionFactory(transactionManager, connectionFactory); // create the pool object factory final PoolableConnectionFactory factory = new PoolableConnectionFactory(xaConnectionFactory, null); factory.setValidationQuery("SELECT DUMMY FROM DUAL"); factory.setDefaultReadOnly(Boolean.TRUE); factory.setDefaultAutoCommit(Boolean.TRUE); // create the pool pool = new GenericObjectPool<>(factory); factory.setPool(pool); pool.setMaxTotal(10); pool.setMaxWait(Duration.ofMillis(100)); // finally create the datasource ds = new ManagedDataSource<>(pool, xaConnectionFactory.getTransactionRegistry()); ds.setAccessToUnderlyingConnectionAllowed(true); } @AfterEach public void tearDown() throws Exception { pool.close(); } @Test public void testConnectionReturnOnErrorWhenEnlistingXAResource() throws Exception { // see DBCP-433 transactionManager.begin(); assertThrows(SQLException.class, this::getConnection); transactionManager.commit(); assertEquals(1, pool.getBorrowedCount()); // assertEquals(1, pool.getReturnedCount()); assertEquals(1, pool.getDestroyedCount()); assertEquals(0, pool.getNumActive()); } } TestManagedConnectionCachedState.java000066400000000000000000000114221472045345700371610ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertEquals; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.transaction.TransactionManager; import javax.transaction.xa.XAException; import org.apache.commons.dbcp2.ConnectionFactory; import org.apache.commons.dbcp2.Constants; import org.apache.commons.dbcp2.DriverConnectionFactory; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.PoolingDataSource; import org.apache.commons.dbcp2.TesterDriver; import org.apache.commons.pool2.SwallowedExceptionListener; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test for ManagedConnection cached state. */ public class TestManagedConnectionCachedState { private static final class SwallowedExceptionRecorder implements SwallowedExceptionListener { private final List exceptions = new ArrayList<>(); public List getExceptions() { return exceptions; } @Override public void onSwallowException(final Exception e) { exceptions.add(e); } } private PoolingDataSource ds; private GenericObjectPool pool; private TransactionManager transactionManager; private SwallowedExceptionRecorder swallowedExceptionRecorder; public Connection getConnection() throws SQLException { return ds.getConnection(); } @BeforeEach public void setUp() throws XAException { // create a GeronimoTransactionManager for testing transactionManager = new TransactionManagerImpl(); // create a driver connection factory final Properties properties = new Properties(); properties.setProperty(Constants.KEY_USER, "userName"); properties.setProperty(Constants.KEY_PASSWORD, "password"); final ConnectionFactory connectionFactory = new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", properties); // wrap it with a LocalXAConnectionFactory final XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(transactionManager, connectionFactory); // create the pool object factory // make sure we ask for state caching final PoolableConnectionFactory factory = new PoolableConnectionFactory(xaConnectionFactory, null); factory.setValidationQuery("SELECT DUMMY FROM DUAL"); factory.setCacheState(true); // create the pool pool = new GenericObjectPool<>(factory); factory.setPool(pool); // record swallowed exceptions swallowedExceptionRecorder = new SwallowedExceptionRecorder(); pool.setSwallowedExceptionListener(swallowedExceptionRecorder); // finally create the datasource ds = new ManagedDataSource<>(pool, xaConnectionFactory.getTransactionRegistry()); ds.setAccessToUnderlyingConnectionAllowed(true); } @AfterEach public void tearDown() { pool.close(); } @Test public void testConnectionCachedState() throws Exception { // see DBCP-568 // begin a transaction transactionManager.begin(); // acquire a connection enlisted in the transaction try (final Connection conn = getConnection()) { // check the autocommit status to trigger internal caching conn.getAutoCommit(); // ask the transaction manager to rollback transactionManager.rollback(); } // check that no exceptions about failed rollback during close were logged assertEquals(0, swallowedExceptionRecorder.getExceptions().size()); } } TestManagedDataSource.java000066400000000000000000000257311472045345700350330ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.sql.Connection; import java.util.Properties; import javax.transaction.TransactionManager; import org.apache.commons.dbcp2.ConnectionFactory; import org.apache.commons.dbcp2.Constants; import org.apache.commons.dbcp2.DelegatingConnection; import org.apache.commons.dbcp2.DriverConnectionFactory; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.PoolingDataSource; import org.apache.commons.dbcp2.TestConnectionPool; import org.apache.commons.dbcp2.TesterDriver; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * TestSuite for ManagedDataSource without a transaction in progress. */ public class TestManagedDataSource extends TestConnectionPool { protected PoolingDataSource ds; protected GenericObjectPool pool; protected TransactionManager transactionManager; @Override protected Connection getConnection() throws Exception { return ds.getConnection(); } @BeforeEach public void setUp() throws Exception { // create a GeronimoTransactionManager for testing transactionManager = new TransactionManagerImpl(); // create a driver connection factory final Properties properties = new Properties(); properties.setProperty(Constants.KEY_USER, "userName"); properties.setProperty(Constants.KEY_PASSWORD, "password"); final ConnectionFactory connectionFactory = new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", properties); // wrap it with a LocalXAConnectionFactory final XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(transactionManager, connectionFactory); // create the pool object factory final PoolableConnectionFactory factory = new PoolableConnectionFactory(xaConnectionFactory, null); factory.setValidationQuery("SELECT DUMMY FROM DUAL"); factory.setDefaultReadOnly(Boolean.TRUE); factory.setDefaultAutoCommit(Boolean.TRUE); // create the pool pool = new GenericObjectPool<>(factory); factory.setPool(pool); pool.setMaxTotal(getMaxTotal()); pool.setMaxWait(getMaxWaitDuration()); // finally create the datasource ds = new ManagedDataSource<>(pool, xaConnectionFactory.getTransactionRegistry()); ds.setAccessToUnderlyingConnectionAllowed(true); } @Override @AfterEach public void tearDown() throws Exception { pool.close(); super.tearDown(); } /** * Verify the accessToUnderlyingConnectionAllowed properly limits access to the physical connection. */ @Test public void testAccessToUnderlyingConnectionAllowed() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); try (ManagedConnection connection = (ManagedConnection) newConnection()) { assertTrue(connection.isAccessToUnderlyingConnectionAllowed()); assertNotNull(connection.getDelegate()); assertNotNull(connection.getInnermostDelegate()); } ds.setAccessToUnderlyingConnectionAllowed(false); try (ManagedConnection connection = (ManagedConnection) newConnection()) { assertFalse(connection.isAccessToUnderlyingConnectionAllowed()); assertNull(connection.getDelegate()); assertNull(connection.getInnermostDelegate()); } } @Test public void testConnectionReturnOnCommit() throws Exception { transactionManager.begin(); try (DelegatingConnection connectionA = (DelegatingConnection) newConnection()) { // auto close. } transactionManager.commit(); assertEquals(1, pool.getBorrowedCount()); assertEquals(1, pool.getReturnedCount()); assertEquals(0, pool.getNumActive()); } @Test public void testManagedConnectionEqualInnermost() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); try (DelegatingConnection con = (DelegatingConnection) getConnection()) { @SuppressWarnings("resource") final Connection inner = con.getInnermostDelegate(); ds.setAccessToUnderlyingConnectionAllowed(false); final DelegatingConnection con2 = new DelegatingConnection<>(inner); assertNotEquals(con2, con); assertTrue(con.innermostDelegateEquals(con2.getInnermostDelegate())); assertTrue(con2.innermostDelegateEquals(inner)); assertNotEquals(con, con2); } } @Test public void testManagedConnectionEqualsFail() throws Exception { try (Connection con1 = getConnection(); final Connection con2 = getConnection()) { assertNotEquals(con1, con2); } } @Test public void testManagedConnectionEqualsNull() throws Exception { try (Connection con1 = getConnection()) { final Connection con2 = null; assertNotEquals(con2, con1); } } /* * JIRA: DBCP-198 */ @Test public void testManagedConnectionEqualsReflexive() throws Exception { try (Connection con = getConnection()) { @SuppressWarnings("resource") final Connection con2 = con; assertEquals(con2, con); assertEquals(con, con2); } } @Test public void testManagedConnectionEqualsSameDelegate() throws Exception { // Get a maximal set of connections from the pool final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = newConnection(); } // Close the delegate of one wrapper in the pool ((DelegatingConnection) c[0]).getDelegate().close(); // Grab a new connection - should get c[0]'s closed connection // so should be delegate-equivalent try (Connection con = newConnection()) { Assertions.assertNotEquals(c[0], con); Assertions.assertEquals(((DelegatingConnection) c[0]).getInnermostDelegateInternal(), ((DelegatingConnection) con).getInnermostDelegateInternal()); for (final Connection element : c) { element.close(); } } } @Test public void testManagedConnectionEqualsSameDelegateNoUnderlyingAccess() throws Exception { // Get a maximal set of connections from the pool final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { c[i] = newConnection(); } // Close the delegate of one wrapper in the pool ((DelegatingConnection) c[0]).getDelegate().close(); // Disable access for the new connection ds.setAccessToUnderlyingConnectionAllowed(false); // Grab a new connection - should get c[0]'s closed connection // so should be delegate-equivalent try (Connection con = newConnection()) { Assertions.assertNotEquals(c[0], con); Assertions.assertEquals(((DelegatingConnection) c[0]).getInnermostDelegateInternal(), ((DelegatingConnection) con).getInnermostDelegateInternal()); for (final Connection element : c) { element.close(); } ds.setAccessToUnderlyingConnectionAllowed(true); } } @Test public void testManagedConnectionEqualsType() throws Exception { try (Connection con1 = getConnection()) { final Integer con2 = 0; assertNotEquals(con2, con1); } } @Test public void testNestedConnections() throws Exception { transactionManager.begin(); try (Connection c1 = newConnection(); final Connection c2 = newConnection()) { transactionManager.commit(); } } @Test public void testSetNullTransactionRegistry() throws Exception { try (ManagedDataSource ds = new ManagedDataSource<>(pool, null)) { assertThrows(NullPointerException.class, () -> ds.setTransactionRegistry(null)); } } @Test() public void testSetTransactionRegistry() throws Exception { try (ManagedDataSource ds = new ManagedDataSource<>(pool, null)) { ds.setTransactionRegistry(new TransactionRegistry(transactionManager)); } } @Test public void testSetTransactionRegistryAlreadySet() { final ManagedDataSource managed = (ManagedDataSource) ds; assertThrows(IllegalStateException.class, () -> managed.setTransactionRegistry(null)); } /** * Verify that connection sharing is working (or not working) as expected. */ @Test public void testSharedConnection() throws Exception { try (DelegatingConnection connectionA = (DelegatingConnection) newConnection(); final DelegatingConnection connectionB = (DelegatingConnection) newConnection()) { assertNotEquals(connectionA, connectionB); assertNotEquals(connectionB, connectionA); assertFalse(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertFalse(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); } } @Test public void testTransactionRegistryNotInitialized() throws Exception { try (ManagedDataSource ds = new ManagedDataSource<>(pool, null)) { assertThrows(IllegalStateException.class, ds::getConnection); } } } TestManagedDataSourceInTx.java000066400000000000000000000411721472045345700356330ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.transaction.Synchronization; import javax.transaction.Transaction; import org.apache.commons.dbcp2.DelegatingConnection; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests ManagedDataSource with an active transaction in progress. */ public class TestManagedDataSourceInTx extends TestManagedDataSource { // can't actually test close in a transaction @Override protected void assertBackPointers(final Connection conn, final Statement statement) throws SQLException { assertFalse(conn.isClosed()); assertFalse(isClosed(statement)); assertSame(conn, statement.getConnection(), "statement.getConnection() should return the exact same connection instance that was used to create the statement"); try (ResultSet resultSet = statement.getResultSet()) { assertFalse(isClosed(resultSet)); assertSame(statement, resultSet.getStatement(), "resultSet.getStatement() should return the exact same statement instance that was used to create the result set"); try (ResultSet executeResultSet = statement.executeQuery("select * from dual")) { assertFalse(isClosed(executeResultSet)); assertSame(statement, executeResultSet.getStatement(), "resultSet.getStatement() should return the exact same statement instance that was used to create the result set"); } try (ResultSet keysResultSet = statement.getGeneratedKeys()) { assertFalse(isClosed(keysResultSet)); assertSame(statement, keysResultSet.getStatement(), "resultSet.getStatement() should return the exact same statement instance that was used to create the result set"); } if (statement instanceof PreparedStatement) { final PreparedStatement preparedStatement = (PreparedStatement) statement; try (ResultSet preparedResultSet = preparedStatement.executeQuery()) { assertFalse(isClosed(preparedResultSet)); assertSame(statement, preparedResultSet.getStatement(), "resultSet.getStatement() should return the exact same statement instance that was used to create the result set"); } } resultSet.getStatement().getConnection().close(); } } @Override @BeforeEach public void setUp() throws Exception { super.setUp(); transactionManager.begin(); } @Override @AfterEach public void tearDown() throws Exception { if (transactionManager.getTransaction() != null) { transactionManager.commit(); } super.tearDown(); } @Override @Test public void testAutoCommitBehavior() throws Exception { final Connection connection = newConnection(); // auto commit should be off assertFalse(connection.getAutoCommit(), "Auto-commit should be disabled"); // attempt to set auto commit try { connection.setAutoCommit(true); fail("setAutoCommit method should be disabled while enlisted in a transaction"); } catch (final SQLException e) { // expected } // make sure it is still disabled assertFalse(connection.getAutoCommit(), "Auto-commit should be disabled"); // close connection connection.close(); } @Override @Test public void testClearWarnings() throws Exception { // open a connection Connection connection = newConnection(); assertNotNull(connection); // generate SQLWarning on connection final CallableStatement statement = connection.prepareCall("warning"); assertNotNull(connection.getWarnings()); // create a new shared connection final Connection sharedConnection = newConnection(); // shared connection should see warning assertNotNull(sharedConnection.getWarnings()); // close and allocate a new (original) connection connection.close(); connection = newConnection(); // warnings should not have been cleared by closing the connection assertNotNull(connection.getWarnings()); assertNotNull(sharedConnection.getWarnings()); statement.close(); sharedConnection.close(); connection.close(); } @Test public void testCloseInTransaction() throws Exception { try (DelegatingConnection connectionA = (DelegatingConnection) newConnection(); DelegatingConnection connectionB = (DelegatingConnection) newConnection()) { assertNotEquals(connectionA, connectionB); assertNotEquals(connectionB, connectionA); assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); } final Connection connection = newConnection(); assertFalse(connection.isClosed(), "Connection should be open"); connection.close(); assertTrue(connection.isClosed(), "Connection should be closed"); } @Test public void testCommit() throws Exception { try (Connection connection = newConnection()) { // connection should be open assertFalse(connection.isClosed(), "Connection should be open"); // attempt commit directly try { connection.commit(); fail("commit method should be disabled while enlisted in a transaction"); } catch (final SQLException e) { // expected } // make sure it is still open assertFalse(connection.isClosed(), "Connection should be open"); } } @Override @Test public void testConnectionReturnOnCommit() throws Exception { // override with no-op test } @Override @Test public void testConnectionsAreDistinct() throws Exception { final Connection[] conn = new Connection[getMaxTotal()]; for (int i = 0; i < conn.length; i++) { conn[i] = newConnection(); for (int j = 0; j < i; j++) { // two connections should be distinct instances Assertions.assertNotSame(conn[j], conn[i]); // neither should they should be equivalent even though they are // sharing the same underlying connection Assertions.assertNotEquals(conn[j], conn[i]); // Check underlying connection is the same Assertions.assertEquals(((DelegatingConnection) conn[j]).getInnermostDelegateInternal(), ((DelegatingConnection) conn[i]).getInnermostDelegateInternal()); } } for (final Connection element : conn) { element.close(); } } @Test public void testDoubleReturn() throws Exception { transactionManager.getTransaction().registerSynchronization(new Synchronization() { private ManagedConnection conn; @Override public void afterCompletion(final int i) { final int numActive = pool.getNumActive(); try { conn.checkOpen(); } catch (final Exception e) { // Ignore } assertEquals(numActive, pool.getNumActive()); try { conn.close(); } catch (final Exception e) { fail("Should have been able to close the connection"); } // TODO Requires DBCP-515 assertTrue(numActive -1 == pool.getNumActive()); } @Override public void beforeCompletion() { try { conn = (ManagedConnection) ds.getConnection(); assertNotNull(conn); } catch (final SQLException e) { fail("Could not get connection"); } } }); transactionManager.commit(); } @Test public void testGetConnectionInAfterCompletion() throws Exception { try (DelegatingConnection connection = (DelegatingConnection) newConnection()) { // Don't close so we can check it for warnings in afterCompletion transactionManager.getTransaction().registerSynchronization(new SynchronizationAdapter() { @Override public void afterCompletion(final int i) { try { final Connection connection1 = ds.getConnection(); try { connection1.getWarnings(); fail("Could operate on closed connection"); } catch (final SQLException e) { // This is expected } } catch (final SQLException e) { fail("Should have been able to get connection"); } } }); } transactionManager.commit(); } @Override @Test public void testHashCode() throws Exception { try (Connection conn1 = newConnection()) { assertNotNull(conn1); try (Connection conn2 = newConnection()) { assertNotNull(conn2); // shared connections should not have the same hash code Assertions.assertNotEquals(conn1.hashCode(), conn2.hashCode()); } } } /** * @see #testSharedConnection() */ @Override @Test public void testManagedConnectionEqualsFail() throws Exception { // this test is invalid for managed connections since because // two connections to the same datasource are supposed to share // a single connection } @Override @Test public void testMaxTotal() throws Exception { final Transaction[] transactions = new Transaction[getMaxTotal()]; final Connection[] c = new Connection[getMaxTotal()]; for (int i = 0; i < c.length; i++) { // create a new connection in the current transaction c[i] = newConnection(); assertNotNull(c[i]); // suspend the current transaction and start a new one transactions[i] = transactionManager.suspend(); assertNotNull(transactions[i]); transactionManager.begin(); } try { newConnection(); fail("Allowed to open more than DefaultMaxTotal connections."); } catch (final java.sql.SQLException e) { // should only be able to open 10 connections, so this test should // throw an exception } finally { transactionManager.commit(); for (int i = 0; i < c.length; i++) { transactionManager.resume(transactions[i]); c[i].close(); transactionManager.commit(); } } } @Override @Test public void testNestedConnections() { // Not supported } @Test public void testReadOnly() throws Exception { try (Connection connection = newConnection()) { // NOTE: This test class uses connections that are read-only by default // connection should be read only assertTrue(connection.isReadOnly(), "Connection be read-only"); // attempt to setReadOnly try { connection.setReadOnly(true); fail("setReadOnly method should be disabled while enlisted in a transaction"); } catch (final SQLException e) { // expected } // make sure it is still read-only assertTrue(connection.isReadOnly(), "Connection be read-only"); // attempt to setReadonly try { connection.setReadOnly(false); fail("setReadOnly method should be disabled while enlisted in a transaction"); } catch (final SQLException e) { // expected } // make sure it is still read-only assertTrue(connection.isReadOnly(), "Connection be read-only"); // TwR closes the connection } } @Override @Test public void testSharedConnection() throws Exception { try (DelegatingConnection connectionA = (DelegatingConnection) newConnection(); DelegatingConnection connectionB = (DelegatingConnection) newConnection()) { assertNotEquals(connectionA, connectionB); assertNotEquals(connectionB, connectionA); assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); } } @Test public void testSharedTransactionConversion() throws Exception { try (DelegatingConnection connectionA = (DelegatingConnection) newConnection(); DelegatingConnection connectionB = (DelegatingConnection) newConnection()) { // in a transaction the inner connections should be equal assertNotEquals(connectionA, connectionB); assertNotEquals(connectionB, connectionA); assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); transactionManager.commit(); // use the connection so it adjusts to the completed transaction connectionA.getAutoCommit(); connectionB.getAutoCommit(); // no there is no transaction so inner connections should not be equal assertNotEquals(connectionA, connectionB); assertNotEquals(connectionB, connectionA); assertFalse(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertFalse(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); transactionManager.begin(); // use the connection so it adjusts to the new transaction connectionA.getAutoCommit(); connectionB.getAutoCommit(); // back in a transaction so inner connections should be equal again assertNotEquals(connectionA, connectionB); assertNotEquals(connectionB, connectionA); assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); } } } TestPoolableManagedConnection.java000066400000000000000000000140001472045345700365410ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import java.util.Properties; import javax.transaction.TransactionManager; import org.apache.commons.dbcp2.ConnectionFactory; import org.apache.commons.dbcp2.Constants; import org.apache.commons.dbcp2.DriverConnectionFactory; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.TesterDriver; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Tests for PoolableManagedConnection. */ public class TestPoolableManagedConnection { private TransactionManager transactionManager; private TransactionRegistry transactionRegistry; private GenericObjectPool pool; private Connection conn; private PoolableManagedConnection poolableManagedConnection; @BeforeEach public void setUp() throws Exception { // create a GeronimoTransactionManager for testing transactionManager = new TransactionManagerImpl(); // create a driver connection factory final Properties properties = new Properties(); properties.setProperty(Constants.KEY_USER, "userName"); properties.setProperty(Constants.KEY_PASSWORD, "password"); final ConnectionFactory connectionFactory = new DriverConnectionFactory(new TesterDriver(), "jdbc:apache:commons:testdriver", properties); // wrap it with a LocalXAConnectionFactory final XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(transactionManager, connectionFactory); // create transaction registry transactionRegistry = xaConnectionFactory.getTransactionRegistry(); // create the pool object factory final PoolableConnectionFactory factory = new PoolableConnectionFactory(xaConnectionFactory, null); factory.setValidationQuery("SELECT DUMMY FROM DUAL"); factory.setDefaultReadOnly(Boolean.TRUE); factory.setDefaultAutoCommit(Boolean.TRUE); // create the pool pool = new GenericObjectPool<>(factory); factory.setPool(pool); pool.setMaxTotal(10); pool.setMaxWait(Duration.ofMillis(100)); } @AfterEach public void tearDown() throws SQLException { if (conn != null && !conn.isClosed()) { conn.close(); } if (pool != null && !pool.isClosed()) { pool.close(); } } @Test public void testManagedConnection() throws Exception { assertEquals(0, pool.getNumActive()); // create a connection conn = pool.borrowObject(); assertEquals(1, pool.getNumActive()); // create the poolable managed connection poolableManagedConnection = new PoolableManagedConnection(transactionRegistry, conn, pool); poolableManagedConnection.close(); // closing a poolable managed connection won't close it, but simply return to the pool assertEquals(1, pool.getNumActive()); // but closing the underlying connection really closes it conn.close(); assertEquals(0, pool.getNumActive()); } @Test public void testPoolableConnection() throws Exception { // create a connection // pool uses LocalXAConnectionFactory, which register the connection with the TransactionRegistry conn = pool.borrowObject(); assertNotNull(transactionRegistry.getXAResource(conn)); // create the poolable managed connection poolableManagedConnection = new PoolableManagedConnection(transactionRegistry, conn, pool); poolableManagedConnection.close(); assertNotNull(transactionRegistry.getXAResource(conn)); } @Test public void testReallyClose() throws Exception { assertEquals(0, pool.getNumActive()); // create a connection // pool uses LocalXAConnectionFactory, which register the connection with the TransactionRegistry conn = pool.borrowObject(); assertEquals(1, pool.getNumActive()); assertNotNull(transactionRegistry.getXAResource(conn)); // create the poolable managed connection poolableManagedConnection = new PoolableManagedConnection(transactionRegistry, conn, pool); poolableManagedConnection.close(); assertNotNull(transactionRegistry.getXAResource(conn)); assertEquals(1, pool.getNumActive()); // this must close the managed connection, removing it from the transaction registry poolableManagedConnection.reallyClose(); try { assertNull(transactionRegistry.getXAResource(conn)); fail("Transaction registry was supposed to be empty now"); } catch (final SQLException ignore) { // ignore } assertEquals(0, pool.getNumActive()); } }TestSynchronizationOrder.java000066400000000000000000000231021472045345700357070ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; import javax.sql.XAConnection; import javax.sql.XADataSource; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.xa.XAResource; import org.apache.commons.dbcp2.BasicDataSource; import org.apache.commons.dbcp2.DelegatingConnection; import org.apache.commons.dbcp2.PoolableConnection; import org.apache.commons.dbcp2.PoolableConnectionFactory; import org.apache.commons.dbcp2.TesterClassLoader; import org.apache.commons.dbcp2.transaction.TransactionAdapter; import org.apache.commons.dbcp2.transaction.TransactionManagerAdapter; import org.apache.commons.dbcp2.transaction.TransactionSynchronizationRegistryAdapter; import org.apache.commons.pool2.impl.GenericObjectPool; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class TestSynchronizationOrder { private boolean transactionManagerRegistered; private boolean transactionSynchronizationRegistryRegistered; private TransactionManager transactionManager; private TransactionSynchronizationRegistry transactionSynchronizationRegistry; private XADataSource xads; private BasicManagedDataSource bmds; private BasicDataSource bds; @BeforeEach public void setup() { transactionManager = new TransactionManagerAdapter() { private Transaction transaction; @Override public void begin() throws NotSupportedException, SystemException { transaction = new TransactionAdapter() { @Override public boolean enlistResource(final XAResource xaResource) throws IllegalStateException, RollbackException, SystemException { // Called and used return true; } @Override public void registerSynchronization(final Synchronization synchronization) throws IllegalStateException, RollbackException, SystemException { transactionManagerRegistered = true; } }; } @Override public Transaction getTransaction() throws SystemException { return transaction; } }; transactionSynchronizationRegistry = new TransactionSynchronizationRegistryAdapter() { @Override public void registerInterposedSynchronization(final Synchronization synchronization) { transactionSynchronizationRegistryRegistered = true; } }; bmds = new BasicManagedDataSource(); bmds.setTransactionManager(transactionManager); bmds.setTransactionSynchronizationRegistry(transactionSynchronizationRegistry); bmds.setXADataSource("notnull"); bds = new BasicDataSource(); bds.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); bds.setUrl("jdbc:apache:commons:testdriver"); bds.setMaxTotal(10); bds.setMaxWait(Duration.ofMillis(100)); bds.setDefaultAutoCommit(Boolean.TRUE); bds.setDefaultReadOnly(Boolean.FALSE); bds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); bds.setDefaultCatalog("test catalog"); bds.setUsername("userName"); bds.setPassword("password"); bds.setValidationQuery("SELECT DUMMY FROM DUAL"); bds.setConnectionInitSqls(Arrays.asList("SELECT 1", "SELECT 2")); bds.setDriverClassLoader(new TesterClassLoader()); bds.setJmxName("org.apache.commons.dbcp2:name=test"); final AtomicInteger closeCounter = new AtomicInteger(); final InvocationHandler handle = new InvocationHandler() { @SuppressWarnings("resource") // caller closes protected XAConnection getXAConnection() throws SQLException { return new TesterBasicXAConnection(bds.getConnection(), closeCounter); } @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { final String methodName = method.getName(); switch (methodName) { case "hashCode": return System.identityHashCode(proxy); case "equals": return proxy == args[0]; case "getXAConnection": // both zero and 2-arg signatures return getXAConnection(); default: break; } try { return method.invoke(bds, args); } catch (final InvocationTargetException e) { throw e.getTargetException(); } } }; xads = (XADataSource) Proxy.newProxyInstance( TestSynchronizationOrder.class.getClassLoader(), new Class[]{XADataSource.class}, handle); bmds.setXaDataSourceInstance(xads); } @AfterEach public void tearDown() throws SQLException { bds.close(); bmds.close(); } @Test public void testInterposedSynchronization() throws Exception { final DataSourceXAConnectionFactory xaConnectionFactory = new DataSourceXAConnectionFactory(transactionManager, xads, transactionSynchronizationRegistry); final PoolableConnectionFactory factory = new PoolableConnectionFactory(xaConnectionFactory, null); factory.setValidationQuery("SELECT DUMMY FROM DUAL"); factory.setDefaultReadOnly(Boolean.TRUE); factory.setDefaultAutoCommit(Boolean.TRUE); // create the pool try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { factory.setPool(pool); pool.setMaxTotal(10); pool.setMaxWait(Duration.ofSeconds(1)); // finally create the datasource try (final ManagedDataSource ds = new ManagedDataSource<>(pool, xaConnectionFactory.getTransactionRegistry())) { ds.setAccessToUnderlyingConnectionAllowed(true); transactionManager.begin(); try (final Connection connectionA = ds.getConnection()) { // Check and close right away. assertInstanceOf(DelegatingConnection.class, connectionA); } transactionManager.commit(); assertFalse(transactionManagerRegistered); assertTrue(transactionSynchronizationRegistryRegistered); } } } @Test public void testSessionSynchronization() throws Exception { final DataSourceXAConnectionFactory xaConnectionFactory = new DataSourceXAConnectionFactory(transactionManager, xads); final PoolableConnectionFactory factory = new PoolableConnectionFactory(xaConnectionFactory, null); factory.setValidationQuery("SELECT DUMMY FROM DUAL"); factory.setDefaultReadOnly(Boolean.TRUE); factory.setDefaultAutoCommit(Boolean.TRUE); // create the pool try (final GenericObjectPool pool = new GenericObjectPool<>(factory)) { factory.setPool(pool); pool.setMaxTotal(10); pool.setMaxWait(Duration.ofSeconds(1)); // finally create the datasource try (final ManagedDataSource ds = new ManagedDataSource<>(pool, xaConnectionFactory.getTransactionRegistry())) { ds.setAccessToUnderlyingConnectionAllowed(true); transactionManager.begin(); try (final Connection connectionA = ds.getConnection()) { // Check and close right away. assertInstanceOf(DelegatingConnection.class, connectionA); } transactionManager.commit(); assertTrue(transactionManagerRegistered); assertFalse(transactionSynchronizationRegistryRegistered); } } } } TestTransactionContext.java000066400000000000000000000054761472045345700353620ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; import java.sql.Connection; import java.sql.SQLException; import javax.transaction.xa.XAResource; import org.apache.geronimo.transaction.manager.TransactionImpl; import org.apache.geronimo.transaction.manager.TransactionManagerImpl; import org.junit.jupiter.api.Test; /** * TestSuite for {@link TransactionContext}. */ public class TestTransactionContext { /** * Transaction that always fails enlistResource. */ private static final class UncooperativeTransaction extends TransactionImpl { public UncooperativeTransaction() { super(null, null); } @Override public synchronized boolean enlistResource(final XAResource xaRes) { return false; } } /** * JIRA: DBCP-428 */ @Test public void testSetSharedConnectionEnlistFailure() throws Exception { try (final BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource()) { basicManagedDataSource.setTransactionManager(new TransactionManagerImpl()); basicManagedDataSource.setDriverClassName("org.apache.commons.dbcp2.TesterDriver"); basicManagedDataSource.setUrl("jdbc:apache:commons:testdriver"); basicManagedDataSource.setUsername("userName"); basicManagedDataSource.setPassword("password"); basicManagedDataSource.setMaxIdle(1); try (final Connection conn = basicManagedDataSource.getConnection()) { assertInstanceOf(ManagedConnection.class, conn); final UncooperativeTransaction transaction = new UncooperativeTransaction(); final TransactionContext transactionContext = new TransactionContext(basicManagedDataSource.getTransactionRegistry(), transaction); assertThrows(SQLException.class, () -> transactionContext.setSharedConnection(conn)); } } } } TesterBasicXAConnection.java000066400000000000000000000155571472045345700353520ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/managed/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.apache.commons.dbcp2.managed; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.StatementEventListener; import javax.sql.XAConnection; import javax.transaction.xa.XAResource; /** * Basic XAConnection. getConnection() returns a handle on a physical * Connection. Closing the handle does not close the physical connection, you * have to close the XAConnection for that (PooledConnection behavior). * XA behavior is implemented through a LocalXAResource. */ public class TesterBasicXAConnection implements XAConnection { /** * Delegates everything to a Connection, except for close() which just * notifies the parent XAConnection. */ public static class ConnectionHandle implements InvocationHandler { public Connection conn; public final TesterBasicXAConnection xaconn; public ConnectionHandle(final Connection conn, final TesterBasicXAConnection xaconn) { this.conn = conn; this.xaconn = xaconn; } protected Object close() throws SQLException { if (conn != null) { conn.clearWarnings(); conn = null; xaconn.handle = null; xaconn.notifyConnectionClosed(); } return null; } public void closeHandle() { conn = null; } @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { final String methodName = method.getName(); switch (methodName) { case "hashCode": return System.identityHashCode(proxy); case "equals": return proxy == args[0]; case "isClosed": return conn == null; case "close": return close(); default: break; } if (conn == null) { throw new SQLException("Connection closed"); } try { return method.invoke(conn, args); } catch (final InvocationTargetException e) { final Throwable te = e.getTargetException(); if (te instanceof SQLException) { xaconn.notifyConnectionErrorOccurred((SQLException) te); } throw te; } } } public Connection conn; public ConnectionHandle handle; public final List listeners = new LinkedList<>(); public final AtomicInteger closeCounter; public TesterBasicXAConnection(final Connection conn) { this(conn, null); } public TesterBasicXAConnection(final Connection conn, final AtomicInteger closeCounter) { this.conn = conn; this.closeCounter = closeCounter; } @Override public void addConnectionEventListener( final ConnectionEventListener connectionEventListener) { listeners.add(connectionEventListener); } @Override public void addStatementEventListener(final StatementEventListener listener) { throw new UnsupportedOperationException(); } @Override public void close() throws SQLException { if (handle != null) { closeHandle(); } try { conn.close(); if (closeCounter != null) { closeCounter.incrementAndGet(); } } finally { conn = null; } } protected void closeHandle() throws SQLException { handle.closeHandle(); if (!conn.getAutoCommit()) { try { conn.rollback(); } catch (final SQLException e) { e.printStackTrace(); } } handle = null; } @Override public Connection getConnection() throws SQLException { if (conn == null) { final SQLException e = new SQLException("XAConnection closed"); notifyConnectionErrorOccurred(e); throw e; } try { if (handle != null) { // only one handle at a time on the XAConnection closeHandle(); conn.clearWarnings(); } } catch (final SQLException e) { notifyConnectionErrorOccurred(e); throw e; } handle = new ConnectionHandle(conn, this); return (Connection) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[] { Connection.class }, handle); } @Override public XAResource getXAResource() throws SQLException { return new LocalXAConnectionFactory.LocalXAResource(conn); } protected void notifyConnectionClosed() { final ConnectionEvent event = new ConnectionEvent(this); final List copy = new ArrayList<>( listeners); for (final ConnectionEventListener listener : copy) { listener.connectionClosed(event); } } protected void notifyConnectionErrorOccurred(final SQLException e) { final ConnectionEvent event = new ConnectionEvent(this, e); final List copy = new ArrayList<>( listeners); for (final ConnectionEventListener listener : copy) { listener.connectionErrorOccurred(event); } } @Override public void removeConnectionEventListener( final ConnectionEventListener connectionEventListener) { listeners.remove(connectionEventListener); } @Override public void removeStatementEventListener(final StatementEventListener listener) { throw new UnsupportedOperationException(); } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/transaction/000077500000000000000000000000001472045345700310215ustar00rootroot00000000000000TransactionAdapter.java000066400000000000000000000043421472045345700353760ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/transaction/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.transaction; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.RollbackException; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.xa.XAResource; /** * A Transaction adapter. */ public class TransactionAdapter implements Transaction { @Override public void commit() throws HeuristicMixedException, HeuristicRollbackException, RollbackException, SecurityException, SystemException { // Noop } @Override public boolean delistResource(final XAResource arg0, final int arg1) throws IllegalStateException, SystemException { return false; } @Override public boolean enlistResource(final XAResource arg0) throws IllegalStateException, RollbackException, SystemException { return false; } @Override public int getStatus() throws SystemException { return 0; } @Override public void registerSynchronization(final Synchronization arg0) throws IllegalStateException, RollbackException, SystemException { // Noop } @Override public void rollback() throws IllegalStateException, SystemException { // Noop } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { // Noop } } TransactionManagerAdapter.java000066400000000000000000000046641472045345700367000ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/transaction/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.transaction; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.InvalidTransactionException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; /** * A TransactionManager adapter. */ public class TransactionManagerAdapter implements TransactionManager { @Override public void begin() throws NotSupportedException, SystemException { // Noop } @Override public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException, RollbackException, SecurityException, SystemException { // Noop } @Override public int getStatus() throws SystemException { return 0; } @Override public Transaction getTransaction() throws SystemException { return null; } @Override public void resume(final Transaction arg0) throws IllegalStateException, InvalidTransactionException, SystemException { // Noop } @Override public void rollback() throws IllegalStateException, SecurityException, SystemException { // Noop } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { // Noop } @Override public void setTransactionTimeout(final int arg0) throws SystemException { // Noop } @Override public Transaction suspend() throws SystemException { return null; } } TransactionSynchronizationRegistryAdapter.java000066400000000000000000000033251472045345700422510ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/java/org/apache/commons/dbcp2/transaction/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.dbcp2.transaction; import javax.transaction.Synchronization; import javax.transaction.TransactionSynchronizationRegistry; /** * A TransactionSynchronizationRegistry adapter. */ public class TransactionSynchronizationRegistryAdapter implements TransactionSynchronizationRegistry { @Override public Object getResource(final Object arg0) { return null; } @Override public boolean getRollbackOnly() { return false; } @Override public Object getTransactionKey() { return null; } @Override public int getTransactionStatus() { return 0; } @Override public void putResource(final Object arg0, final Object arg1) { // Noop } @Override public void registerInterposedSynchronization(final Synchronization arg0) { // Noop } @Override public void setRollbackOnly() { // Noop } } commons-dbcp-rel-commons-dbcp-2.13.0/src/test/resources/000077500000000000000000000000001472045345700231105ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.13.0/src/test/resources/commons-logging.properties000066400000000000000000000017711472045345700303330ustar00rootroot00000000000000# # 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. # ## # Forces a concrete implementation of both `LogFactory` and `Log`. org.apache.commons.logging.LogFactory = org.apache.commons.logging.impl.LogFactoryImpl org.apache.commons.logging.Log = org.apache.commons.dbcp2.StackMessageLog