pax_global_header00006660000000000000000000000064141012627660014517gustar00rootroot0000000000000052 comment=2abdb498d0aa7b65d668fc5661795bc83844d8fa commons-dbcp-rel-commons-dbcp-2.9.0/000077500000000000000000000000001410126276600172475ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/.github/000077500000000000000000000000001410126276600206075ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/.github/dependabot.yml000066400000000000000000000017341410126276600234440ustar00rootroot00000000000000# 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: "daily" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" commons-dbcp-rel-commons-dbcp-2.9.0/.github/workflows/000077500000000000000000000000001410126276600226445ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/.github/workflows/maven.yml000066400000000000000000000030501410126276600244730ustar00rootroot00000000000000# 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] jobs: build: runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental }} strategy: matrix: java: [ 8, 11, 16 ] experimental: [false] include: - java: 17-ea experimental: true steps: - uses: actions/checkout@v2.3.4 - uses: actions/cache@v2.1.6 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@v2 with: distribution: 'adopt' java-version: ${{ matrix.java }} - name: Build with Maven run: mvn -V --file pom.xml --no-transfer-progress commons-dbcp-rel-commons-dbcp-2.9.0/.gitignore000066400000000000000000000003771410126276600212460ustar00rootroot00000000000000target/ 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 *.iml .nbproject commons-dbcp-rel-commons-dbcp-2.9.0/.travis.yml000066400000000000000000000016141410126276600213620ustar00rootroot00000000000000# 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. language: java sudo: false cache: directories: - $HOME/.m2 jdk: - openjdk8 - openjdk11 - openjdk16 - openjdk-ea commons-dbcp-rel-commons-dbcp-2.9.0/CODE_OF_CONDUCT.md000066400000000000000000000016411410126276600220500ustar00rootroot00000000000000 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.9.0/CONTRIBUTING.md000066400000000000000000000146011410126276600215020ustar00rootroot00000000000000 Contributing to Apache Commons DBCP ====================== You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to the open source community. Before you dig right into the code there are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. 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). + 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. Making Changes -------------- + Create a _topic branch_ for your isolated work. * Usually you should base your branch on the `master` or `trunk` 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 assure 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) + `#apache-commons` IRC channel on `irc.freenode.net` [cla]:https://www.apache.org/licenses/#clas [jira]:https://issues.apache.org/jira/browse/DBCP commons-dbcp-rel-commons-dbcp-2.9.0/LICENSE.txt000066400000000000000000000261361410126276600211020ustar00rootroot00000000000000 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.9.0/NOTICE.txt000066400000000000000000000002561410126276600207740ustar00rootroot00000000000000Apache Commons DBCP Copyright 2001-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). commons-dbcp-rel-commons-dbcp-2.9.0/README.md000066400000000000000000000130661410126276600205340ustar00rootroot00000000000000 Apache Commons DBCP =================== [![Travis-CI Status](https://travis-ci.org/apache/commons-dbcp.svg)](https://travis-ci.org/apache/commons-dbcp) [![GitHub Actions Status](https://github.com/apache/commons-dbcp/workflows/Java%20CI/badge.svg)](https://github.com/apache/commons-dbcp/actions) [![Coverage Status](https://coveralls.io/repos/apache/commons-dbcp/badge.svg)](https://coveralls.io/r/apache/commons-dbcp) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.commons/commons-dbcp2/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.commons/commons-dbcp2/) [![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-dbcp2/2.9.0.svg)](https://javadoc.io/doc/org.apache.commons/commons-dbcp2/2.9.0) 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][ml]. Where can I get 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.9.0 ``` Contributing ------------ We accept Pull Requests via GitHub. The [developer mailing list][ml] 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 code style. + Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change. + Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running ```mvn clean test```. If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas). You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md). License ------- This code is under the [Apache Licence v2](https://www.apache.org/licenses/LICENSE-2.0). See the `NOTICE.txt` file for required notices and attributions. Donations --------- You like Apache Commons DBCP? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support the development. Additional Resources -------------------- + [Apache Commons Homepage](https://commons.apache.org/) + [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/DBCP) + [Apache Commons Twitter Account](https://twitter.com/ApacheCommons) + `#apache-commons` IRC channel on `irc.freenode.org` [ml]:https://commons.apache.org/mail-lists.html commons-dbcp-rel-commons-dbcp-2.9.0/README.txt000066400000000000000000000010011410126276600207350ustar00rootroot00000000000000Apache Commons DBCP =========================== Welcome to the DBCP component of the Apache Commons project (https://commons.apache.org). DBCP version 2.5.0 requires JDK 1.8. DBCP can be built using either Maven or Ant. When building using Ant, Locations of dependent jars for the Ant build need to be specified in build.properties. There is a build.properties.sample file included in the source distribution. See https://commons.apache.org/dbcp/ for additional and up-to-date information on Commons DBCP. commons-dbcp-rel-commons-dbcp-2.9.0/RELEASE-NOTES.txt000066400000000000000000000644411410126276600217670ustar00rootroot00000000000000 Apache Apache Commons DBCP Version 2.9.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache 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 Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Apache Commons DBCP Version 2.8.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache 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 Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache 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 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 Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Apache Commons DBCP Version 2.6.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache 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 Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download page: https://commons.apache.org/dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Apache Commons DBCP Version 2.5.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache 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 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 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 Apache Commons DBCP Version 2.4.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache 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 Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Apache Commons DBCP Version 2.3.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache 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 Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Apache Commons DBCP Version 2.2.0 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache 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 Apache Commons DBCP website: https://commons.apache.org/dbcp/ Download from https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi ----------------------------------------------------------------------------- Apache Apache Commons DBCP Version 2.1.1 RELEASE NOTES The Apache Commons DBCP team is pleased to announce the release of Apache 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 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.9.0/SECURITY.md000066400000000000000000000016041410126276600210410ustar00rootroot00000000000000 The Apache Commons security page is [https://commons.apache.org/security.html](https://commons.apache.org/security.html). commons-dbcp-rel-commons-dbcp-2.9.0/checkstyle.xml000066400000000000000000000160701410126276600221330ustar00rootroot00000000000000 commons-dbcp-rel-commons-dbcp-2.9.0/dbcp-RC.sh000077500000000000000000000044621410126276600210260ustar00rootroot00000000000000#!/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.9.0/dbcp-pre-RC.sh000077500000000000000000000026201410126276600216040ustar00rootroot00000000000000#!/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.9.0/dbcp-release.sh000077500000000000000000000050721410126276600221400ustar00rootroot00000000000000#!/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.9.0/doc/000077500000000000000000000000001410126276600200145ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/doc/BasicDataSourceExample.java000066400000000000000000000103721410126276600251720ustar00rootroot00000000000000/* * 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.9.0/doc/PoolingDataSourceExample.java000066400000000000000000000140771410126276600255660ustar00rootroot00000000000000/* * 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.9.0/doc/PoolingDriverExample.java000066400000000000000000000163531410126276600247660ustar00rootroot00000000000000/* * 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.9.0/doc/README.txt000066400000000000000000000027071410126276600215200ustar00rootroot00000000000000=================================================================================== 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.9.0/doc/abandon.jsp000066400000000000000000000111201410126276600221270ustar00rootroot00000000000000 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.9.0/doc/static_structure_dia.gif000066400000000000000000000236431410126276600247370ustar00rootroot00000000000000GIF89a#÷ư€€€€€€€€€ÀÀÀÀÜÀ¦Êđ@ ` €   À à @ @@@`@€@ @À@à@` `@```€` `À`à`€ €@€`€€€ €À€à€   @ ` €   À à À À@À`À€À ÀÀÀàÀà à@à`à€à àÀààà@ @@@`@€@ @À@à@ @ @@ @` @€ @  @À @à @@@ @@@@@`@@€@@ @@À@@à@@`@ `@@`@``@€`@ `@À`@à`@€@ €@@€@`€@€€@ €@À€@à€@ @  @@ @` @€ @  @À @à @À@ À@@À@`À@€À@ À@ÀÀ@àÀ@à@ à@@à@`à@€à@ à@Àà@àà@€ €@€`€€€ €À€à€ € €@ €` €€ €  €À €à €@€ @€@@€`@€€@€ @€À@€à@€`€ `€@`€``€€`€ `€À`€à`€€€ €€@€€`€€€€€ €€À€€à€€ €  €@ €` €€ €  €À €à €À€ À€@À€`À€€À€ À€ÀÀ€àÀ€à€ à€@à€`à€€à€ à€Àà€àà€À À@À`À€À ÀÀÀàÀ À À@ À` À€ À  ÀÀ Àà À@À @À@@À`@À€@À @ÀÀ@Àà@À`À `À@`À``À€`À `ÀÀ`Àà`À€À €À@€À`€À€€À €ÀÀ€Àà€À À  À@ À` À€ À  ÀÀ Àà ÀÀÀ ÀÀ@ÀÀ`ÀÀ€ÀÀ ÀÀÿûđ  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ!ùư,#@₫û H° Áƒ*\Ȱ¡Ă‡#JœH±¢Å‹3jÜȱ£Ç CI²¤É“(Sª\ɲ¥Ë—ÆŒ)pæA q>´YRçËŸ@oÄé³bQ„Gwæ:0éE§FûA JµªƠ«X³jƯ:5b×>¿6@V́Ö³ ͪT‹%Û¶păÊK·®̉¦2¥â¥Y–¬^¼5Ë₫mÚ7°ĐÁ< œ·&âÇ};ÖKô1ăĘÿúµ{w0åÉ™gæë82dÂ~IW®|y2ẳ{¥VxóêØymªöü™çmĂœƒ N¼8È®o+î4ụ̀çĐ£KŸN­óêØé^Ïν»÷ïàĂ₫¿O^{ùóèÓ«_v;û÷#ƯĂŸO¿¾}̣̣ï뺿¿ÿÿB—_€"Uà&¨àJ.x`ƒF(á„ưAHá^¨á†vè¡x~(âˆvđω(¦¨â,¶èâ‹0Æ(ăŒ4Öh£Œ!’h̃‚&̃èă@)ä7æ¨ăO=9d’=–…¢“ÿ˜(%”QJeVfùä‰PZ©¤’|MµÙ‘Áy^’_â¨b—d=Ùæ•W¢g•\rùf•Sz '•]¦Y$™ÏÉéç „jèf¨‚‰2$è¡F*韋VjéxkMªé¦œ¶ØèR—†*ê¨m}V§5ÊÙd“uîÙ*«₫pÖ ë¬¨Â¨Ó˜Eꮼöê’© =Zë°Ä. “¯ÈN(l±̀6;#°vmJ’U7íPÎf«-ÉÆµlLƪ§–á®뜲¶º'ånùf»êFfN^{¬rÍY Ӥ‹nœ¬ú+kÀâ ë¿ă+o·p}»íĂÍÚ‹_t¤‰è0Ä×*1ĂwL›t{,̣È$“2I'—¬̣Ê,#˜²H/·,ó̀4³íÅç¼ìóñ\óϼ̃L(»®M+F¿º¦J'mt_M=«—8¿èó{·¶Úl®Ơ¶›×ŸÉ–Zl¦1Q\{V±Ú‹m›`a ôÜ- ­óƯÅ^m3₫Ư|÷ ‘̃Uë7x¶åª®·9vm{U,·Ø†ơ¸ÜY³Fù¼™AÎøæ„q^Ú w=øè h6éøv¦ơ梡›æ²…í:ä—«6ùÛ©áúîO8ï jô;đÄ?è{ñAáụ̈̀§uzêÍG/ưôÉ· =ơØg}ƠxwïçđqïưøÆ–I₫ù‚¯}°6ú›đû ¬îûîÖŸ.Â÷y?ºå,₫“À –̃₫ç¢;)Mj‹×º¢ÆÀ¢ƯxzW¥F5±%ó3X™¤‚IUd ±Ä4§Ah'ä×ú´ƒ¾9.Œá—.)‰xP†8Ä̉ E%¸úđ‡₫@ÄN¾‚HÄ"±8=<¢—ÈD­¨¯‰PŒ"Ÿ(Å*Z{T|P·hÁ+zÑAYü΀¾57Œi«ºŸ´ä&&p₫+ÚˆF;ÅQPmJc ơ·%«}ñ.ëƠ¹HH…ˆ¬Ê!¥•ÈF:r9‹äN$IÉJ‡–̀¤&mXÈNÚJxÂó¤(Y4ÉMzñ†@¢̉MhÆV̉ÉÄ̉[ÉG…ê(ˆ+]FPÙÆpe ƒăû(̀WÚq˜k¢Ú»ôL"•̉”Väå(½7ÆPNóÏ„¦6–Ímzó›Ö '8ÇINe]¥›åL§:­’²AÚ±_í[¼ .zªŒ¶₫êâ:÷I·gJSSÿÜ"»øIP¿…1 ×̀: ÊPư,´¡¨é$JÑ.ªAµ¨F7z₫´æo^¹$FÄ$κqô¤,3KF'‚œÇ¡ô¥¢k¾˜ßœ.4¸q̃LySÓ`ơ6Y{Pt³S¡â4W•ĂL—jĐ×,F—Öăé́<²6†#ƠZ)S·Ê!­êÊ"‰̣*WÇÊ(¤¨g]œYmzÔ°µ5sj£iP DzÚƠ‘b½«^÷j¸°ä”¨±£«eØzVÙơ­¼Ánl*R¾:y},E#+3ÊJö²ªS̀bû¿Fơ0œưë` ÔÖ8N3FµLy$gÚhÉ4¢-₫-be+:Ö¦–±‰½­SH¹Z³ÊåótƠ]*/p¥K Ơ‘FK>’SÜgAëRâ.%‰ .é’̣[¬t׆Ăơ)#µ[Pµ|7hÍ%¯z¹Óơº—3ç¥Y|ß‹̉ùÖ̀¾ôµ(~ï›ß₫³¾₫ 0’`º_ø>°‚!»à "4¡K°É”áQJŒÙá₫Èe¿<³rü—¶Đ––zmôdN §¦A_.pNîs 2EÜ© ó¨Â¢Dñ‰÷…ăNÚ¸Áñáq ©c y-B0Ÿ&.v¹Ñ–«\eg(“ăéÇGN'‡\È"g™Â\梗³#VÏêëWas₫§́)D©Q‚ 3&>ål®4ẨŒz²*À›`ÙªH ï…Ølµ7p]qŒ²‘ÆL)çù˜&tלfNd&«tÿüåQ–Óµ>-êR‘Ô¦Nơí¦i‚Z‘»í\O¤jæ*U¹ª–¤[Ơ¯7O Î.¦'>§bCăÙÍo¦å¡¡L)A*×Èbu«]øjªT®®³mZ̉Ö°i­¸»¶¶ÄéV¨ĐnOï’[Ñă²;Ư§ TdºOw_u<Ø[áêÉøFÛáwgo ï²bzœöÆuÁYUHZ²Ú O©xñˆ[Ó‘­øÅ7Ÿiǰ›’ö¸¤₫hx(N}ïØÿđèëW‘ëײ¼³].sKÙ~²Dô—Ílnơy(tf±‰æJ›ÉOv¥Í“Ys{;éµD% £lbë9á@— ª‚Môî/‚îâzÎëˆl`†Q/=ûÉ ̣µŸ¯ín_ʵYkÛ½¼Ó½»̃×9÷½ûưR}ÿ»àÉøÅ]A­¶â³ëđ›ñ£g¿lĂ`§|b´'’…w‹5·Đ̃ÓÎ>½êÉœúƠ»₫à»2ưëOªv̉Sy—£·½BgºÚ“Q._` Y쟂2~!½ çÚ§,iÅ—¯üÁ­ùêG~‡¦;₫¯ÕÎ÷ºR5w~É̃ûúE¿ú¾₫ölxçw¿ü\=̣—?cñŸ?7æÎsÅY™N̉.øvèt8‡}Kw@ hKP£a3.ú§w‘~÷×}èwù—81øS‚"¸jÎ5‚&4oÁ\EƠZR•[ß¶VăöQÿFXøƒYơ1ˆUƒäV[w‚{‡̀'^9„ï†\*hm>˜„ŸER%ˆ!y§„P¸‰S8ç–6º‘6,(pXˆZ4heU¦Vpåmú@‡Ơ‚Qx†Eˆ†jX2Gx;»a9˜¡8Tn°s9‡SnsmA†³†~d2(‡CWƒØp¬S;₫¡Ă8psˆs8Up£;?•†8‰€F‰̃´]e‰ä…‰‰Ȇ·ñ5[³‚m¶s[§ƠY´U©(WªåH‹YøoçÙ&ƒKhƒ̃‹48Tµø‰ơÁ]8Øo½1/3…%FbWø9³ĂŒƒ•U‚[nu6xx&7USVÖoȸ8c£‡œÓ[_¨Tn¸Sp˜ˆ̃8‡qk¢%‰Â"üä‰ïÈ0U%¹³Çˆu8ă˜Œ‰¥<¸„;q“ˆ´“¹m)ƠƠ;IµYú†öˆ¸‹˜Œ Y;̀׌wè:¹‘¬cVhE[ÖˆVf8Ïf=eˆnƒØ‹:ˆ[‡s,y₫‹3ظȒuu’;¸o¸X2‰ZƠ“º“)p< ƒè¶‚€’1i’°w—è”L©Qb!Áe]Q QT™‰WI`íµ•Ö•^¹c••a9"XÇwe™~í––“%•l –kù– E–—&—ñH{vy—x™—êD—Gâ—|i\ªP³fê9†çp=(!dºuDV©Zº3u)o™6ªÚ©ŸPºª¬:™¥“̉ª²:« ¤£v<¶«÷¶nºÚ«Ǧ¾¬kJqÂZ¬ÊÆj¬7C«̀ʪі¬"m¨ºuÏ ­¸k]:œÄ¹­o y?̉§j2rƠ [o(‘Ûx½‘C ;BYg‘ÑEÓˆ‘)­p¡ÿWœ(ê€'úa*:§™~*~ăʃK9Wùö“ÆÈmäø®‡5ẂÈo/yyi¯éù©^G°¾̉Åj±Ó P{“®,e¿º«¶†\Ÿ¸¬ÍÚ₫²J²=µmûZDYw ×m©³8ÛXu“8‹]j˜q8*•u§(hÊơÊ«C‹wÁă6&q-![pe&hơ–‚_XnV6 Ă‡²ÖµwèŸÓ‘qh­_¥´ñ]#k¶÷j2¢lK!nKwŸ2µ¾Zeâ™q[YĂ:v»·_iµy ¸K°J¸Œ)²Ä¸>è²K¤̀ñ¸’Ë ‘;¹–K i÷±C[c)&×¹¤Z_ñ¤­€ê¥Â®÷ ¦*F©¥›̃5C-Ú¡₫÷¦´Ë}_ºr‡Brß#»Z£“'§µkºtªºÀ麴Wº’Z?̀ù¯’Gy t}Đ;½wÔx₫$¨O §àºyÔ·¢ûê¼Ûû§Ó°ưy7´™+¾ÜËt©1Ü·¾r$° xºáË¢à÷·ƒ&ºÂû­~v¦Ö6rlFO4Z¦Ÿ[CÍ…±¤À .™«¿ k>\§đÁ̀Q—{Á0Z&¼ÁØY¹üÁ¢é~˸$LOXÂ(|†›Â,lRîØÂ0|¶1<ĂÔBĂ6,z7œĂ€¨Ă< ·|Â@= F‹GÁ|6Ä ‚¿Øz¼©{¼³«¼„&>ºëLH¼©¤̉¤d½ü¦zg¨»­]œ¾óÛœøê½Î¼TÅ„^ögÄ©dœj¼Æ±—{nüBqŒzl|Ç¢¦Äé¥ÇYÆÇ₫MëÇÜz‚<Èy\ÈGÈV‰ÈúUÇ»«p`åÈlÇÈ,ɼÉFaÉvLÉuÑ›Æ+tÊ˺>êg Ú|‘,~¶ÛºOÊ·+ÊâÊÉŒâ+BZ}NÓKÑû¼µg' •§\¦Z|y*GKcËœe,¿{úOܘú+À·ä(D8RœÊ° Ë,TÍ Œ{m¬ÍTŒÍq Î…Ǜâjä\ÎZR蜖àsÎëÜ—̃ơÎI‹„ỨÍ+Ï+ô2XlÏŒÏ$èÂÔ<¦0¿p†t̀ôtOvĐ4il̉rÇt€ =¾W—'‘öœî́ÏêœÍñÛ½¶,̀ÚgsK—gÈLÆdÆøÑ:₫P]D“´À=zÑ+í-rá̉ Ó1=Ó7]Å6ÓưµÓưÓîÔB­^D]ÔÚ•GÔc VL­¬%‹)êptx69k‹…ºÅFI”=é‹4y°/ùÔ»™]ư¨ŒÚ‰́ú“#ùº™cHÙ¥́®]Èp¹©·³´dưÏÜ×É æVƠc†‚u‹wØ^Í6Ơ˜”C鳯Ó:£èŒ^K# Øx•’}I^[]›M×É•°îºÖqíocX« ›Ö¦}Ù˜ưHGøÚqkÚmí₫H…â¨YPûTåX‘ˆ8Uä&ûˆ”A‹²ƯP*Z˜³“Ô¸Ø¹ØØ¼₫ˆi5ØÑ­‘a˜Üs©ƯŒ+’M\!âEû\ܽ`Ë-nÑŒ¸Ơ³b¸ƒºÈ̃GỸë5„µÏ},ßF6…SéË:„iX6ßߦßXÙd{Ü©̃“à\ƒ¨qƒß´¾W‹¹Ô®•­Îá¾¼£ ®2.F#9µF R¦bˆ¡¢ßY½lÖ½\ß%(µ'T*ÉÎH¯n×ÍߪUâ‡ăHÖ·•«N„ǘ êizâ£êºÆê*7´_abM̃³F¨|-¸àâkÛ®QíÚ¤Îjè»5p”í“.²x́¨à_ ”5ÉÜǬl#¶ ÛăÏnkéùØ1¹é¾’1“” èœ\k)këmÊÈ.8 “;ë‚î/¼#9I®dƒƒGí̉}Ơ£Ơí·a³3ÛVâ‰ù¾́)¾Î+¬y?®å§ØˆĂ tƳtưăͶ=9œŹøÛ¸ƯÖ¥¨°₫ỏEñSÛv¯Ïçé¶í“®.`2e–XĂë8¶°Ă3®I‚¾ó•2ëÛ$Ø@ô2®x‹\ô¦NăHàJïXùôWơRIT_ơ–2ó„ƒơ€×Ô\Q^ÿơ„gŸb¯#Zïáeoöj™öKOöl­nùöp¿örơq_÷ƒ&–x/·¼÷|¯÷~OÄ}ø‚ø„/džøU¹—/˜Œßø9˜¿ø?ù·*ù–ù›ùûqö{Ăùóèù ¿D¢?ú§fúïXú¨ï`«¿²XOÓø©ú2}cü\>Qûó)û¥!¸ÿºß¦µÏ™í©Á/ü»YüưŒ̣k&·ÈŸJ¢₫ZcÖL¼e¬f°[ư,í Ú¨_Ú½”hù´¥vJŸÅ̀a$̉Œf}¸oăY‚Øï¢áé§ăkulT̉ă¿Ê› Yÿ 0°`A‚ÿ*4È0!‡ "„˜pàEŒ5n䨑`?ú$Y²dH“)U®)’åK˜1eΤYÓæMœ9uîä©ÓeOŸ…ºĐáDŒF+"¸Ô©E‰L¥¥Jô'P¬YµnåÚç̉ªa‡‚ ±lS‰!'…jö"[°bå5‰²îU­x½îåÛ×ï_À1ơn9×°A¸•ªuh–ñZ‹l2VKö1ÜĂ™æÜÙóç•q5Î\V4iÔ₫‡·\ôkرegm øtjÜaoçæí±ölàÁ…î]Üøq̃¿ư*̃Üùsׯw#§^ƯzRèÙµs~Ưû÷ä°™o'_¾üø½ƯÁ¯go½yøñC·§_ôû®øåïçÏ]¼}¬J¿₫ 4đ@›#0/tP£iKpB +´đB 3̀)B¬Ô{đCï8JD K4ñDST‘'YñÅ[ÜIÆk´ñFs”Æ aœ́±£¢êÈ1 }kP9»̣ÓqI&›ṭÉçxüêŧ k«"Ê*{ëGÄÜ:2¥²NJJ2Ë4óL4}úÄ*½<È´ 2Í(©(rP¤0C3M>₫ûôóÏ%¥¼ÉCđ°$ÈÎÆ"S4ÎD%Ô:<“sO@+µôRL Ô¦G?́ÔG«T’tÓ–25ơTTST>ơUÍd•UUkµơVLi•ÉUX{•KWÁpvXb‹% X˜xơuÙP¥3öYh£­Ù—”eöZ¨eI[i»EƠZlĂ}K<¹í̀ÜU×w]÷¼½\v±E·®r1Ä3ÅyOw_Ưܵ^~}Í÷Øzÿ%øÄ‰ xálư­`ß$3²;87:­âeWË“¯„=ëØ+¼>¶M]ê$v/ÛË’ëĐ"³½Nd‡DÎÍË([«æ©{Sg¨̃²-.Y~ù¤Á$E₫˜³Ä!6rË 1Æl1Dz3²w–Sh®¦+æ½¶³ˆĐrël¨á$˪ét;)Œg6ºZ“yÂÖ́™dăˆüQˇԶZå-Ñ3NÛ̃Ź!Á»dÂëD íɶnL©Cƒ|[1Ë%¯.̉™æ₫SïE}–q‹Ó¼lÉƯLËÎÍW¯²ơ¡?uÈđ.0IßÏ÷B†w6÷̃vNuW»ĐçÏù>}yê7C^Óê—‡₫a{A’–ǿéÛ₫údĂ×}|¼3Dÿqó^Ÿ|QÛw¿Û÷¥_₫€ë‡₫ớ¾P€Œ’úx@&P”2Øø@F₫Đtÿ“`-xÁ₫é¯&Ä`=øAM„#$a ¿%B¦P…+,CÇBÆP†+rá®fxCæA5 –}øC ‚A$b&ëˆKdb;Dđáï;ID¡­H?(J‘_Tâ½h,nEQ‹ ¿xF脱7q{ZFÈ‚2 ½±(]j„>WFéƯ‹5Pœ ôöæÇ­˜™Rcn %Dv)pQIYÚ*w%Ÿ -.ˆäY"9Arï`z÷~¢Gïå1”$ؽ> —˜¥*Ơ)]¹ÇMúÑ•©,e-G™ÉA¦©¸9å¥:Eqm ÜYfw±aZ₫QÖÂeúlIÊW.m”·l%+¡IÍW₫æ”±”æUhiÍiR³›¡lf.ù´KÔÈq™‹âœ£ˆù:vÆó—À\§;+ °Å×ÿFË¢‘VµP*çLWk›Úœöµ³ơ…KÛô0ç³Èrl8W=Ü®¶™x n^̃³[†b“–³̀+bGƠÜær³‹ưmqÑØÑÚZwCÛ¤k%ëƯUJ·®Œ].[áê[í^·é)piĐåF® 5́]÷˜Ô² 5«̀Í*zÙÛÄ¿₫—S2Zl̀Ä8YR2°‚û`óNI¦0| a`5¸Â½°€µ¥á ›³ĂÖ]ˆM|#Ά-½%>q‹iXƯ’ºXÆ3¶í¤4IcçØÂÙ₫Ư¡}üc!̣8Æ@&r‘ÓƠGYÉKæ£yÉd(GyÂ4M²”­|eQ¹ÊXær—C7b/‡ù¿kx\Zf–bÍ@2™×œN5¿Vđ·¼Í‚₫\»‚lá™qXç¥Ùih’ûHÉÙ¢ËÉîçmQúîTê¶qJ½÷Áƒlü×WøÀóñü ¿x‹)̣â“üäÙÓx >̣̃ă:óæëCgÏ^̀;ÄüèMod·^ơ«w)₫LYÿzØƱ§}íÏ%dÛç^÷)­éî}ÿû)»øĂ'~{g_|ä'¿¶¥W~óÉ_çG?ú̀—~ơ½H}ëgÁÚç¾̣±ß}đûđûá'ÿ Ç_~ô¯đüég? ×ß~øÇÚ„ưûăï.ûW>ôµ»ÿ†óßùư3µ₫ ±ÿ;¼GC41™tú4Ơđ¹ES@V»³İùÛ´Y‹\ ¶}û¶®I@]»7^3¦ªË’ ÁÊ A ‰7ë™@ äŸ9yAŒÁO3”{[›v³¹g8˜[9’Ó7b£¸€9k[6}ct°ô±@GÁœÊq¶ts8ÏÁAÚ¬Bx¢ºSÁ8₫B$̀  ÀâØ$ôB\)C$ C1,3T04¼›àYC6lCĂ%”Ă¡Ă:tÁ‘A?üC@ DADB,DC<Ä@ÔĂ1³CElÄyĂ¿€DG ?Iä½I¼ÄăCLÜD„aDNüÄwñDPÅ-#ŸJ$Åæ;EBEVüQlEX4Uü£X¬ÅóxE[̀Å/CD^́E_üE` Æ9y¢Fcm̉ªÊTY5A­*mU.¦¼TuVp¥TóÊ&®Ê/z½/­ºq Ïj‰U¾:¬¶₫*VaE’auTJWUJ¬BUXê’©d”V…ª…́WçD²ü¢2)|-Øœ2Ve=×……¥¦ªWQ«ø:Öf Y‹¾ÔR¢,›–¦lÙ¼-½ÙÑWœƯY'ZE²îZ¾à£ÓjU²äYđë-•­%₫YÎÙˆEU¨ƠËZÙ]ZD-¯ŸEÚîSURưÚ™Z›•Za Zè:VyơÙPEÖ£åÚêSUx-(‚úUøbÊWe×`Ư¯M×E¬̃Ê׸ÍÚsuỤ̂Ë?¡0%ÜÁS\ÆM8»z!ô¬èØTë¡ÄmÜ\B®À…&úJ1Oµ©w=+LƯ/¼UÛŒ½%L\̀eE¤øÚX¦eÖÊÚY]Û»µÙS%¯R•ÜƠE¯ơX`=]ÙơØñ‚ƯÁ^{ƠƯ%Å ËÙwL^¯¼\çƠCè̃6Ô\˜mJ©Xû‘Ö¢¥^ƠLÛªuW†}Zá ßáư®‡ÂÚ¦Ơ^ï=Ẫ]Z°åỌ́ XÚ-ß³íƠ¿mßO„[¼,O’Ûºå*´íß>®¾%]f_ưeAÜœ̃Î!~àû‹` †? ¦±€;commons-dbcp-rel-commons-dbcp-2.9.0/findbugs-exclude-filter.xml000066400000000000000000000055141410126276600245110ustar00rootroot00000000000000 commons-dbcp-rel-commons-dbcp-2.9.0/pom.xml000066400000000000000000000466631410126276600206030ustar00rootroot00000000000000 org.apache.commons commons-parent 52 4.0.0 commons-dbcp2 2.9.0 Apache Commons DBCP 2001 Apache Commons DBCP software implements Database Connection Pooling https://commons.apache.org/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 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 org.apache.commons commons-pool2 ${commons.pool.version} commons-logging commons-logging 1.2 org.junit.jupiter junit-jupiter 5.8.0-M1 test org.hamcrest hamcrest 2.2 test org.mockito mockito-core 3.11.2 test org.apache.geronimo.specs geronimo-jta_1.1_spec 1.1.1 true 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 1.7.30 test com.h2database h2 1.4.200 test org.jboss.narayana.jta narayana-jta 5.12.0.Final test org.jboss.spec.javax.transaction jboss-transaction-api_1.2_spec 1.1.1.Final test org.jboss jboss-transaction-spi 7.6.1.Final org.jboss.logging jboss-logging-spi test org.jboss.logging jboss-logging 3.4.2.Final test UTF-8 UTF-8 1.8 1.8 dbcp RC1 org.apache.commons.dbcp2 2.9.0 for JDBC 4.2 on Java 8 sha512 2.4.0 for JDBC 4.1 on Java 7 sha256 commons-dbcp-${commons.release.3.version} 1.4 for JDBC 4 on Java 6 sha256 commons-dbcp-${commons.release.4.version} 1.3 for JDBC 3 on Java 1.4 or 5 sha256 -bin dbcp https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-dbcp site-content DBCP 12310469 3.1.2 8.44 3.3.0 2.10.0 0.15.3 0.8.7 javax.transaction;version="1.1.0",javax.transaction.xa;version="1.1.0";partial=true;mandatory:=partial,* true 4.3.0 4.3.0 2.8.0 true Gary Gregory 86fdc7e2a11262cb false false true true clean package apache-rat:check checkstyle:check japicmp:cmp 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} com.puppycrawl.tools checkstyle ${commons.checkstyle.version} ${basedir}/checkstyle.xml false com.github.spotbugs spotbugs-maven-plugin ${spotbugs.plugin.version} com.github.spotbugs spotbugs ${spotbugs.impl.version} ${basedir}/findbugs-exclude-filter.xml org.apache.maven.plugins maven-surefire-plugin org.apache.commons.dbcp2.StackMessageLog **/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 ${commons.javadoc.version} http://docs.oracle.com/javase/8/docs/api https://commons.apache.org/proper/commons-pool/apidocs http://docs.oracle.com/javaee/7/api/ com.github.siom79.japicmp japicmp-maven-plugin ${commons.japicmp.version} cmp-report true ${commons.japicmp.breakBuildOnBinaryIncompatibleModifications} true true true ${commons.japicmp.ignoreMissingClasses} ${commons.bc.version} org.apache.geronimo.specs geronimo-jta_1.1_spec 1.1.1 com.github.spotbugs spotbugs-maven-plugin org.apache.maven.plugins maven-javadoc-plugin ${commons.javadoc.version} http://docs.oracle.com/javase/8/docs/api https://commons.apache.org/proper/commons-pool/apidocs http://docs.oracle.com/javaee/7/api/ org.apache.maven.plugins maven-changes-plugin ${commons.changes.version} src/changes 12313721,12326766,12328750 org.apache.maven.plugins maven-checkstyle-plugin ${basedir}/checkstyle.xml false org.codehaus.mojo clirr-maven-plugin ${commons.clirr.version} info maven-pmd-plugin 3.14.0 ${maven.compiler.target} pmd cpd commons-dbcp-rel-commons-dbcp-2.9.0/src/000077500000000000000000000000001410126276600200365ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/changes/000077500000000000000000000000001410126276600214465ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/changes/changes.xml000066400000000000000000002154411410126276600236070ustar00rootroot00000000000000 Apache Commons DBCP Release Notes 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 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.9.0/src/changes/release-notes.vm000066400000000000000000000067551410126276600245750ustar00rootroot00000000000000## 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. Apache ${project.name} Version ${version} RELEASE NOTES The ${developmentTeam} is pleased to announce the release of Apache ${project.name} ${version}. $introduction.replaceAll("(? commons-dbcp-rel-commons-dbcp-2.9.0/src/main/000077500000000000000000000000001410126276600207625ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/assembly/000077500000000000000000000000001410126276600226015ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/assembly/bin.xml000066400000000000000000000031371410126276600240770ustar00rootroot00000000000000 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.9.0/src/main/assembly/src-tar-gz.xml000066400000000000000000000053411410126276600253170ustar00rootroot00000000000000 src tar.gz ${project.artifactId}-${project.version}-src build.properties.sample build.xml checkstyle.xml findbugs-exclude-filter.xml LICENSE.txt NOTICE.txt pom.xml README.txt RELEASE-NOTES.txt test-jar.xml lf doc static_structure_dia.gif lf src/site/resources 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.9.0/src/main/assembly/src-zip.xml000066400000000000000000000053531410126276600247200ustar00rootroot00000000000000 src zip ${project.artifactId}-${project.version}-src build.properties.sample build.xml checkstyle.xml findbugs-exclude-filter.xml LICENSE.txt NOTICE.txt pom.xml README.txt RELEASE-NOTES.txt test-jar.xml crlf doc static_structure_dia.gif crlf 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.9.0/src/main/java/000077500000000000000000000000001410126276600217035ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/000077500000000000000000000000001410126276600224725ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/000077500000000000000000000000001410126276600237135ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/000077500000000000000000000000001410126276600253665ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/000077500000000000000000000000001410126276600263605ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/AbandonedTrace.java000066400000000000000000000124041410126276600320560ustar00rootroot00000000000000/* * 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.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; 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 { /** A list of objects created by children of this object. */ private final List> traceList = new ArrayList<>(); /** Last time this connection was used. */ private volatile long lastUsedMillis; /** * 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(); } } /** * Gets the last time this object was used in milliseconds. * * @return long time in milliseconds. */ @Override public long getLastUsed() { return lastUsedMillis; } /** * 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) { if (parent != null) { parent.addTrace(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() { lastUsedMillis = System.currentTimeMillis(); } /** * Sets the time in milliseconds this object was last used. * * @param lastUsedMillis * time in milliseconds. */ protected void setLastUsed(final long lastUsedMillis) { this.lastUsedMillis = lastUsedMillis; } } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java000066400000000000000000002710271410126276600322300ustar00rootroot00000000000000/* * 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.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.logging.Logger; 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 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); } } @SuppressWarnings("resource") protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory) throws Exception { 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 Integer defaultQueryTimeoutSeconds; /** * 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 #timeBetweenEvictionRunsMillis} 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 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 <= 0 to wait indefinitely. */ private long maxWaitMillis = BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS; /** * Prepared statement pooling for this pool. When this property is set to 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 * 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 long timeBetweenEvictionRunsMillis = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; /** * 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 long minEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; /** * 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 #getSoftMinEvictableIdleTimeMillis()}. */ private long softMinEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; 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 URL to be passed to our JDBC driver to establish a connection. */ private String url; /** * 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 int validationQueryTimeoutSeconds = -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 long maxConnLifetimeMillis = -1; private boolean logExpiredConnections = true; private String jmxName; private boolean autoCommitOnReturn = true; private boolean rollbackOnReturn = true; private volatile Set disconnectionSqlCodes; 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 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 {@link #driverClassName} is specified that class is loaded using the * {@link ClassLoader} of this class or, if {@link #driverClassLoader} is set, {@link #driverClassName} is loaded * with the specified {@link ClassLoader}.
  4. *
  5. If {@link #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 {@link #url}. *
*

* 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); final GenericObjectPool gop = createObjectPool(factory, config, abandonedConfig); gop.setMaxTotal(maxTotal); gop.setMaxIdle(maxIdle); gop.setMinIdle(minIdle); gop.setMaxWaitMillis(maxWaitMillis); gop.setTestOnCreate(testOnCreate); gop.setTestOnBorrow(testOnBorrow); gop.setTestOnReturn(testOnReturn); gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun); gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); gop.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis); 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 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 boolean success = false; final PoolableConnectionFactory poolableConnectionFactory; try { poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory); poolableConnectionFactory.setPoolStatements(poolPreparedStatements); poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); success = true; } catch (final SQLException | RuntimeException se) { throw se; } catch (final Exception ex) { throw new SQLException("Error creating connection factory", ex); } if (success) { // create a pool for our connections createConnectionPool(poolableConnectionFactory); } // Create the pooling data source to manage connections DataSource newDataSource; success = false; try { newDataSource = createDataSourceInstance(); newDataSource.setLogWriter(logWriter); success = true; } catch (final SQLException | RuntimeException se) { throw se; } catch (final Exception ex) { throw new SQLException("Error creating datasource", ex); } finally { if (!success) { closeConnectionPool(); } } // If initialSize > 0, preload the pool try { for (int i = 0; i < initialSize; i++) { connectionPool.addObject(); } } catch (final Exception e) { closeConnectionPool(); throw new SQLException("Error preloading the connection pool", e); } // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor // task startPoolMaintenance(); dataSource = newDataSource; 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 { connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, ObjectNameWrapper.unwrap(registeredJmxObjectName)); connectionFactory.setValidationQuery(validationQuery); connectionFactory.setValidationQueryTimeout(validationQueryTimeoutSeconds); 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.setMaxConnLifetimeMillis(maxConnLifetimeMillis); connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn()); connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeout()); connectionFactory.setFastFailValidation(fastFailValidation); connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes); 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 true if usage tracking is enabled */ @Override public boolean getAbandonedUsageTracking() { return abandonedConfig != null && abandonedConfig.getUseUsageTracking(); } /** * Returns 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 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; } /** * Returns 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"); } /** * Returns 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; } /** * Returns 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); } protected GenericObjectPool getConnectionPool() { return connectionPool; } Properties getConnectionProperties() { return connectionProperties; } /** * Returns the default auto-commit property. * * @return true if default auto-commit is enabled */ @Override public Boolean getDefaultAutoCommit() { return defaultAutoCommit; } /** * Returns 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. null means that the driver default will be used. * * @return The default query timeout in seconds. */ public Integer getDefaultQueryTimeout() { return defaultQueryTimeoutSeconds; } /** * Returns the default readOnly property. * * @return true if connections are readOnly by default */ @Override public Boolean getDefaultReadOnly() { return defaultReadOnly; } /** * Returns the default schema. * * @return the default schema. * @since 2.5.0 */ @Override public String getDefaultSchema() { return this.defaultSchema; } /** * Returns 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; } /** * Returns 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); } /** * Returns 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; } /** * Returns the class loader specified for loading the JDBC driver. Returns 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; } /** * Returns 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; } /** * Returns 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 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) * @since 2.1 */ @Override public boolean getFastFailValidation() { return fastFailValidation; } /** * Returns 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; } /** * Returns 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; } /** * Returns 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 #getMaxConnLifetimeMillis()} 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. * *

* Returns 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"); } /** *

* Returns 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(); } /** * Returns the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an * infinite lifetime. */ @Override public long getMaxConnLifetimeMillis() { return maxConnLifetimeMillis; } /** *

* Returns 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 maxOpenPreparedStatements property. * * @return the maximum number of open statements */ @Override public synchronized int getMaxOpenPreparedStatements() { return this.maxOpenPreparedStatements; } /** *

* Returns 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; } /** * Returns 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 */ @Override public synchronized long getMaxWaitMillis() { return this.maxWaitMillis; } /** * Returns the {@link #minEvictableIdleTimeMillis} property. * * @return the value of the {@link #minEvictableIdleTimeMillis} property * @see #minEvictableIdleTimeMillis */ @Override public synchronized long getMinEvictableIdleTimeMillis() { return this.minEvictableIdleTimeMillis; } /** * Returns 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 * {@link #timeBetweenEvictionRunsMillis} 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(); } /** * Returns the value of the {@link #numTestsPerEvictionRun} property. * * @return the number of objects to examine during idle object evictor runs * @see #numTestsPerEvictionRun */ @Override public synchronized int getNumTestsPerEvictionRun() { return this.numTestsPerEvictionRun; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } /** * Returns the password passed to the JDBC driver to establish connections. * * @return the connection password */ @Override public String getPassword() { return this.password; } 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 #getRemoveAbandonedTimeout() 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 #getRemoveAbandonedTimeout() */ @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 #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds. *

* * @see #getRemoveAbandonedTimeout() */ @Override public boolean getRemoveAbandonedOnMaintenance() { return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnMaintenance(); } /** *

* 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. *

*/ @Override public int getRemoveAbandonedTimeout() { return abandonedConfig == null ? 300 : abandonedConfig.getRemoveAbandonedTimeout(); } /** * 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; } /** *

* Returns 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 */ @Override public synchronized long getSoftMinEvictableIdleTimeMillis() { return softMinEvictableIdleTimeMillis; } /** * Returns the {@link #testOnBorrow} property. * * @return true if objects are validated before being borrowed from the pool * * @see #testOnBorrow */ @Override public synchronized boolean getTestOnBorrow() { return this.testOnBorrow; } /** * Returns the {@link #testOnCreate} property. * * @return true if objects are validated immediately after they are created by the pool * @see #testOnCreate */ @Override public synchronized boolean getTestOnCreate() { return this.testOnCreate; } /** * Returns the value of the {@link #testOnReturn} property. * * @return true if objects are validated before being returned to the pool * @see #testOnReturn */ public synchronized boolean getTestOnReturn() { return this.testOnReturn; } /** * Returns the value of the {@link #testWhileIdle} property. * * @return true if objects examined by the idle object evictor are validated * @see #testWhileIdle */ @Override public synchronized boolean getTestWhileIdle() { return this.testWhileIdle; } /** * Returns the value of the {@link #timeBetweenEvictionRunsMillis} property. * * @return the time (in milliseconds) between evictor runs * @see #timeBetweenEvictionRunsMillis */ @Override public synchronized long getTimeBetweenEvictionRunsMillis() { return this.timeBetweenEvictionRunsMillis; } /** * Returns the JDBC connection {@link #url} property. * * @return the {@link #url} passed to the JDBC driver to establish connections */ @Override public synchronized String getUrl() { return this.url; } /** * Returns the JDBC connection {@link #userName} property. * * @return the {@link #userName} passed to the JDBC driver to establish connections */ @Override public String getUsername() { return this.userName; } /** * Returns the validation query used to validate connections before returning them. * * @return the SQL validation query * @see #validationQuery */ @Override public String getValidationQuery() { return this.validationQuery; } /** * Returns the validation query timeout. * * @return the timeout in seconds before connection validation queries fail. */ @Override public int getValidationQueryTimeout() { return validationQueryTimeoutSeconds; } /** * 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); } } /** * Returns 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."); } } protected void log(final String message) { if (logWriter != null) { logWriter.println(message); } } /** * Logs the given throwable. * @param message TODO * @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(); } /** * 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) { if (abandonedConfig == null) { abandonedConfig = new AbandonedConfig(); } abandonedConfig.setLogWriter(logWriter); final GenericObjectPool gop = this.connectionPool; if (gop != null) { gop.setAbandonedConfig(abandonedConfig); } } /** * 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 true will enable the recording of a stack trace on every use of a * pooled connection */ public void setAbandonedUsageTracking(final boolean usageTracking) { if (abandonedConfig == null) { abandonedConfig = new AbandonedConfig(); } abandonedConfig.setUseUsageTracking(usageTracking); final GenericObjectPool gop = this.connectionPool; if (gop != null) { gop.setAbandonedConfig(abandonedConfig); } } /** *

* 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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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 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 list of SQL statements to be executed when a physical connection is first created. *

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

* * @param connectionInitSqls Collection of SQL statements to execute on connection creation */ public void setConnectionInitSqls(final Collection connectionInitSqls) { if (connectionInitSqls != null && !connectionInitSqls.isEmpty()) { ArrayList newVal = null; for (final String s : connectionInitSqls) { if (!isEmpty(s)) { if (newVal == null) { newVal = new ArrayList<>(); } newVal.add(s); } } this.connectionInitSqls = newVal; } else { this.connectionInitSqls = null; } } /** * 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 is null"); final String[] entries = connectionProperties.split(";"); final Properties properties = new Properties(); for (final String entry : entries) { if (!entry.isEmpty()) { 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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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. null means that the driver default will be used. * * @param defaultQueryTimeoutSeconds The default query timeout in seconds. */ public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { this.defaultQueryTimeoutSeconds = defaultQueryTimeoutSeconds; } /** *

* Sets defaultReadonly property. *

*

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

* * @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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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 considered to signal fatal conditions. *

* Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} (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 */ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCodes) { if (disconnectionSqlCodes != null && !disconnectionSqlCodes.isEmpty()) { HashSet newVal = null; for (final String s : disconnectionSqlCodes) { if (!isEmpty(s)) { if (newVal == null) { newVal = new HashSet<>(); } newVal.add(s); } } this.disconnectionSqlCodes = newVal; } else { this.disconnectionSqlCodes = null; } } /** * Sets the JDBC Driver instance to use for this pool. *

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

* * @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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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 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 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) { if (connectionPool != null) { connectionPool.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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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; if (connectionPool != null) { connectionPool.setLifo(lifo); } } /** * @param logAbandoned new logAbandoned property value */ public void setLogAbandoned(final boolean logAbandoned) { if (abandonedConfig == null) { abandonedConfig = new AbandonedConfig(); } abandonedConfig.setLogAbandoned(logAbandoned); final GenericObjectPool gop = this.connectionPool; if (gop != null) { gop.setAbandonedConfig(abandonedConfig); } } /** * When {@link #getMaxConnLifetimeMillis()} 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. * *

* Set 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 in milliseconds. A value of zero or less indicates an * infinite lifetime. *

*

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

* * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds. */ public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { this.maxConnLifetimeMillis = 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; if (connectionPool != null) { connectionPool.setMaxIdle(maxIdle); } } /** *

* Sets the value of the maxOpenPreparedStatements property. *

*

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

* * @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; if (connectionPool != null) { connectionPool.setMaxTotal(maxTotal); } } /** * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely. * * @param maxWaitMillis the new value for MaxWaitMillis * @see #getMaxWaitMillis() */ public synchronized void setMaxWaitMillis(final long maxWaitMillis) { this.maxWaitMillis = maxWaitMillis; if (connectionPool != null) { connectionPool.setMaxWaitMillis(maxWaitMillis); } } // ------------------------------------------------------ Protected Methods /** * Sets the {@link #minEvictableIdleTimeMillis} property. * * @param minEvictableIdleTimeMillis the minimum amount of time an object may sit idle in the pool * @see #minEvictableIdleTimeMillis */ public synchronized void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; if (connectionPool != null) { connectionPool.setMinEvictableIdleTimeMillis(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 * {@link #timeBetweenEvictionRunsMillis} 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; if (connectionPool != null) { connectionPool.setMinIdle(minIdle); } } /** * Sets the value of the {@link #numTestsPerEvictionRun} property. * * @param numTestsPerEvictionRun the new {@link #numTestsPerEvictionRun} value * @see #numTestsPerEvictionRun */ public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { this.numTestsPerEvictionRun = numTestsPerEvictionRun; if (connectionPool != null) { connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun); } } /** *

* Sets the {@link #password}. *

*

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

* * @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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, getLogWriter. *

* * @param poolingStatements pooling on or off */ public synchronized void setPoolPreparedStatements(final boolean poolingStatements) { this.poolPreparedStatements = poolingStatements; } /** * @param removeAbandonedOnBorrow true means abandoned connections may be removed when connections are borrowed from * the pool. * @see #getRemoveAbandonedOnBorrow() */ public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) { if (abandonedConfig == null) { abandonedConfig = new AbandonedConfig(); } abandonedConfig.setRemoveAbandonedOnBorrow(removeAbandonedOnBorrow); final GenericObjectPool gop = this.connectionPool; if (gop != null) { gop.setAbandonedConfig(abandonedConfig); } } /** * @param removeAbandonedOnMaintenance true means abandoned connections may be removed on pool maintenance. * @see #getRemoveAbandonedOnMaintenance() */ public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) { if (abandonedConfig == null) { abandonedConfig = new AbandonedConfig(); } abandonedConfig.setRemoveAbandonedOnMaintenance(removeAbandonedOnMaintenance); final GenericObjectPool gop = this.connectionPool; if (gop != null) { gop.setAbandonedConfig(abandonedConfig); } } /** *

* 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 #getRemoveAbandonedTimeout() * @see #getRemoveAbandonedOnBorrow() * @see #getRemoveAbandonedOnMaintenance() */ public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) { if (abandonedConfig == null) { abandonedConfig = new AbandonedConfig(); } abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout); final GenericObjectPool gop = this.connectionPool; if (gop != null) { gop.setAbandonedConfig(abandonedConfig); } } /** * 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 */ public synchronized void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; if (connectionPool != null) { connectionPool.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis); } } /** * Sets the {@link #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; if (connectionPool != null) { connectionPool.setTestOnBorrow(testOnBorrow); } } /** * Sets the {@link #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; if (connectionPool != null) { connectionPool.setTestOnCreate(testOnCreate); } } /** * Sets the 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; if (connectionPool != null) { connectionPool.setTestOnReturn(testOnReturn); } } /** * Sets the 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; if (connectionPool != null) { connectionPool.setTestWhileIdle(testWhileIdle); } } /** * Sets the {@link #timeBetweenEvictionRunsMillis} property. * * @param timeBetweenEvictionRunsMillis the new time between evictor runs * @see #timeBetweenEvictionRunsMillis */ public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; if (connectionPool != null) { connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); } } /** *

* Sets the {@link #url}. *

*

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

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

* Sets the {@link #userName}. *

*

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

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

* Sets the {@link #validationQuery}. *

*

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

* * @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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, getLogWriter. *

* * @param validationQueryTimeoutSeconds new validation query timeout value in seconds */ public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { this.validationQueryTimeoutSeconds = 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 && timeBetweenEvictionRunsMillis > 0) { connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); } } @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.java000066400000000000000000000646661410126276600335120ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.nio.charset.StandardCharsets; import java.sql.Connection; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; 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 BasicDataSource that has been configured based on the * RefAddr values of the specified Reference, which must match the names and data types of the * BasicDataSource bean properties with the following exceptions: *

*
    *
  • connectionInitSqls must be passed to this factory as a single String using semicolon to delimit the * statements whereas 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 = "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_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"; /* * 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 String[] ALL_PROPERTIES = {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_JMX_NAME, 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_MILLIS + "."); } /** * 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); } // -------------------------------------------------- ObjectFactory Methods /** * 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 Exception * Thrown when an error occurs creating the data source. */ public static BasicDataSource createDataSource(final Properties properties) throws Exception { final BasicDataSource dataSource = new BasicDataSource(); String value = properties.getProperty(PROP_DEFAULT_AUTO_COMMIT); if (value != null) { dataSource.setDefaultAutoCommit(Boolean.valueOf(value)); } value = properties.getProperty(PROP_DEFAULT_READ_ONLY); if (value != null) { dataSource.setDefaultReadOnly(Boolean.valueOf(value)); } value = properties.getProperty(PROP_DEFAULT_TRANSACTION_ISOLATION); if (value != null) { int level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; if ("NONE".equalsIgnoreCase(value)) { level = Connection.TRANSACTION_NONE; } else if ("READ_COMMITTED".equalsIgnoreCase(value)) { level = Connection.TRANSACTION_READ_COMMITTED; } else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) { level = Connection.TRANSACTION_READ_UNCOMMITTED; } else if ("REPEATABLE_READ".equalsIgnoreCase(value)) { level = Connection.TRANSACTION_REPEATABLE_READ; } else if ("SERIALIZABLE".equalsIgnoreCase(value)) { level = Connection.TRANSACTION_SERIALIZABLE; } else { 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; } } dataSource.setDefaultTransactionIsolation(level); } value = properties.getProperty(PROP_DEFAULT_CATALOG); if (value != null) { dataSource.setDefaultCatalog(value); } value = properties.getProperty(PROP_DEFAULT_SCHEMA); if (value != null) { dataSource.setDefaultSchema(value); } value = properties.getProperty(PROP_CACHE_STATE); if (value != null) { dataSource.setCacheState(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_DRIVER_CLASS_NAME); if (value != null) { dataSource.setDriverClassName(value); } value = properties.getProperty(PROP_LIFO); if (value != null) { dataSource.setLifo(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_MAX_TOTAL); if (value != null) { dataSource.setMaxTotal(Integer.parseInt(value)); } value = properties.getProperty(PROP_MAX_IDLE); if (value != null) { dataSource.setMaxIdle(Integer.parseInt(value)); } value = properties.getProperty(PROP_MIN_IDLE); if (value != null) { dataSource.setMinIdle(Integer.parseInt(value)); } value = properties.getProperty(PROP_INITIAL_SIZE); if (value != null) { dataSource.setInitialSize(Integer.parseInt(value)); } value = properties.getProperty(PROP_MAX_WAIT_MILLIS); if (value != null) { dataSource.setMaxWaitMillis(Long.parseLong(value)); } value = properties.getProperty(PROP_TEST_ON_CREATE); if (value != null) { dataSource.setTestOnCreate(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_TEST_ON_BORROW); if (value != null) { dataSource.setTestOnBorrow(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_TEST_ON_RETURN); if (value != null) { dataSource.setTestOnReturn(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_TIME_BETWEEN_EVICTION_RUNS_MILLIS); if (value != null) { dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(value)); } value = properties.getProperty(PROP_NUM_TESTS_PER_EVICTION_RUN); if (value != null) { dataSource.setNumTestsPerEvictionRun(Integer.parseInt(value)); } value = properties.getProperty(PROP_MIN_EVICTABLE_IDLE_TIME_MILLIS); if (value != null) { dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(value)); } value = properties.getProperty(PROP_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS); if (value != null) { dataSource.setSoftMinEvictableIdleTimeMillis(Long.parseLong(value)); } value = properties.getProperty(PROP_EVICTION_POLICY_CLASS_NAME); if (value != null) { dataSource.setEvictionPolicyClassName(value); } value = properties.getProperty(PROP_TEST_WHILE_IDLE); if (value != null) { dataSource.setTestWhileIdle(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_PASSWORD); if (value != null) { dataSource.setPassword(value); } value = properties.getProperty(PROP_URL); if (value != null) { dataSource.setUrl(value); } value = properties.getProperty(PROP_USER_NAME); if (value != null) { dataSource.setUsername(value); } value = properties.getProperty(PROP_VALIDATION_QUERY); if (value != null) { dataSource.setValidationQuery(value); } value = properties.getProperty(PROP_VALIDATION_QUERY_TIMEOUT); if (value != null) { dataSource.setValidationQueryTimeout(Integer.parseInt(value)); } value = properties.getProperty(PROP_ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED); if (value != null) { dataSource.setAccessToUnderlyingConnectionAllowed(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_REMOVE_ABANDONED_ON_BORROW); if (value != null) { dataSource.setRemoveAbandonedOnBorrow(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_REMOVE_ABANDONED_ON_MAINTENANCE); if (value != null) { dataSource.setRemoveAbandonedOnMaintenance(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_REMOVE_ABANDONED_TIMEOUT); if (value != null) { dataSource.setRemoveAbandonedTimeout(Integer.parseInt(value)); } value = properties.getProperty(PROP_LOG_ABANDONED); if (value != null) { dataSource.setLogAbandoned(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_ABANDONED_USAGE_TRACKING); if (value != null) { dataSource.setAbandonedUsageTracking(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_POOL_PREPARED_STATEMENTS); if (value != null) { dataSource.setPoolPreparedStatements(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_CLEAR_STATEMENT_POOL_ON_RETURN); if (value != null) { dataSource.setClearStatementPoolOnReturn(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_MAX_OPEN_PREPARED_STATEMENTS); if (value != null) { dataSource.setMaxOpenPreparedStatements(Integer.parseInt(value)); } value = properties.getProperty(PROP_CONNECTION_INIT_SQLS); if (value != null) { dataSource.setConnectionInitSqls(parseList(value, ';')); } value = properties.getProperty(PROP_CONNECTION_PROPERTIES); if (value != null) { final Properties p = getProperties(value); final Enumeration e = p.propertyNames(); while (e.hasMoreElements()) { final String propertyName = (String) e.nextElement(); dataSource.addConnectionProperty(propertyName, p.getProperty(propertyName)); } } value = properties.getProperty(PROP_MAX_CONN_LIFETIME_MILLIS); if (value != null) { dataSource.setMaxConnLifetimeMillis(Long.parseLong(value)); } value = properties.getProperty(PROP_LOG_EXPIRED_CONNECTIONS); if (value != null) { dataSource.setLogExpiredConnections(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_JMX_NAME); if (value != null) { dataSource.setJmxName(value); } value = properties.getProperty(PROP_ENABLE_AUTO_COMMIT_ON_RETURN); if (value != null) { dataSource.setAutoCommitOnReturn(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_ROLLBACK_ON_RETURN); if (value != null) { dataSource.setRollbackOnReturn(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_DEFAULT_QUERY_TIMEOUT); if (value != null) { dataSource.setDefaultQueryTimeout(Integer.valueOf(value)); } value = properties.getProperty(PROP_FAST_FAIL_VALIDATION); if (value != null) { dataSource.setFastFailValidation(Boolean.parseBoolean(value)); } value = properties.getProperty(PROP_DISCONNECTION_SQL_CODES); if (value != null) { dataSource.setDisconnectionSqlCodes(parseList(value, ',')); } value = properties.getProperty(PROP_CONNECTION_FACTORY_CLASS_NAME); if (value != null) { dataSource.setConnectionFactoryClassName(value); } // DBCP-215 // Trick to make sure that initialSize connections are created if (dataSource.getInitialSize() > 0) { dataSource.getLogWriter(); } // Return the configured DataSource instance return dataSource; } /** *

* Parse properties from the string. Format of the string must be [propertyName=property;]* *

* * @param propText * @return Properties * @throws Exception */ private static Properties getProperties(final String propText) throws Exception { final Properties p = new Properties(); if (propText != null) { p.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes(StandardCharsets.ISO_8859_1))); } return p; } /** * Parse 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 Collection parseList(final String value, final char delimiter) { final StringTokenizer tokenizer = new StringTokenizer(value, Character.toString(delimiter)); final Collection tokens = new ArrayList<>(tokenizer.countTokens()); while (tokenizer.hasMoreTokens()) { tokens.add(tokenizer.nextToken()); } return tokens; } /** *

* Create and return a new BasicDataSource instance. If no instance can be created, return * 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 nameCtx * @param nameCtx * The context relative to which the name parameter is specified, or null if * name is relative to the default initial context * @param environment * The possibly null environment that is used in creating this object * * @throws Exception * if an exception occurs creating the instance */ @Override public Object getObjectInstance(final Object obj, final Name name, final Context nameCtx, final Hashtable environment) throws Exception { // We only know how to deal with javax.naming.References // 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 warnings = new ArrayList<>(); final List infoMessages = new ArrayList<>(); validatePropertyNames(ref, name, warnings, infoMessages); for (final String warning : warnings) { log.warn(warning); } for (final String infoMessage : infoMessages) { log.info(infoMessage); } final Properties properties = new Properties(); for (final String propertyName : ALL_PROPERTIES) { final RefAddr ra = ref.get(propertyName); if (ra != null) { final String propertyValue = ra.getContent().toString(); properties.setProperty(propertyName, propertyValue); } } 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 warnings * container for warning messages * @param infoMessages * container for info messages */ private void validatePropertyNames(final Reference ref, final Name name, final List warnings, final List infoMessages) { final List allPropsAsList = Arrays.asList(ALL_PROPERTIES); final String nameString = name != null ? "Name = " + name.toString() + " " : ""; if (NUPROP_WARNTEXT != null && !NUPROP_WARNTEXT.isEmpty()) { for (final String propertyName : NUPROP_WARNTEXT.keySet()) { final RefAddr ra = ref.get(propertyName); if (ra != null && !allPropsAsList.contains(ra.getType())) { final StringBuilder stringBuilder = new StringBuilder(nameString); final String propertyValue = ra.getContent().toString(); stringBuilder.append(NUPROP_WARNTEXT.get(propertyName)).append(" You have set value of \"") .append(propertyValue).append("\" for \"").append(propertyName) .append("\" property, which is being ignored."); warnings.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 (!(allPropsAsList.contains(propertyName) || NUPROP_WARNTEXT.containsKey(propertyName) || SILENT_PROPERTIES.contains(propertyName))) { final String propertyValue = ra.getContent().toString(); 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.java000066400000000000000000000026431410126276600332000ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 password via JMX is an Information Exposure issue. */ @Deprecated String getPassword(); } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/ConnectionFactory.java000066400000000000000000000025021410126276600326510ustar00rootroot00000000000000/* * 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.java000066400000000000000000000063441410126276600341320ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 */ 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("DBCP DataSource configured without a 'username'"); } final String pwd = basicDataSource.getPassword(); if (pwd != null) { connectionProperties.put("password", pwd); } else { basicDataSource.log("DBCP DataSource configured without a '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.9.0/src/main/java/org/apache/commons/dbcp2/Constants.java000066400000000000000000000032131410126276600311760ustar00rootroot00000000000000/* * 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 { public static final String JMX_CONNECTION_POOL_BASE_EXT = ",connectionpool="; public static final String JMX_CONNECTION_POOL_PREFIX = "connections"; public static final String JMX_CONNECTION_BASE_EXT = JMX_CONNECTION_POOL_BASE_EXT + JMX_CONNECTION_POOL_PREFIX + ",connection="; public static final String JMX_STATEMENT_POOL_BASE_EXT = JMX_CONNECTION_BASE_EXT; 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.java000066400000000000000000000063501410126276600345520ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 userPassword == null ? null : userPassword.clone(); } } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java000066400000000000000000000217171410126276600323200ustar00rootroot00000000000000/* * 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#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()}. */ String 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.java000066400000000000000000001226441410126276600345250ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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; } } } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java000066400000000000000000000764741410126276600333300ustar00rootroot00000000000000/* * 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.ResultSet; 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.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; /** * 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 Integer defaultQueryTimeoutSeconds; /** * Creates a wrapper for the Connection which traces this Connection in the AbandonedObjectPool. * * @param connection the {@link Connection} to delegate all calls to. */ 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); } } protected void activate() { closed = false; setLastUsed(); if (connection instanceof DelegatingConnection) { ((DelegatingConnection) connection).activate(); } } protected void checkOpen() throws SQLException { if (closed) { if (null != connection) { String label = ""; try { label = connection.toString(); } catch (final Exception ex) { // ignore, leave label empty } throw new SQLException("Connection " + label + " is closed."); } throw new SQLException("Connection is null."); } } /** * Can be used to clear cached state when it is known 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 passivate()
  2. *
  3. Call close (or the equivalent appropriate action) on the wrapped connection
  4. *
  5. Set _closed to 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 mutli-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; } } /** * Returns the state caching flag. * * @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. * null means that the driver default will be used. * * @return query timeout limit in seconds; zero means there is no limit. */ public Integer getDefaultQueryTimeout() { return defaultQueryTimeoutSeconds; } /** * 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 (defaultQueryTimeoutSeconds != null && defaultQueryTimeoutSeconds != delegatingStatement.getQueryTimeout()) { delegatingStatement.setQueryTimeout(defaultQueryTimeoutSeconds); } return delegatingStatement; } /** * Compares innermost delegate to the given connection. * * @param c * connection to compare innermost delegate with * @return true if innermost delegate equals 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(); } 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; } } @Override public boolean isValid(final int timeoutSeconds) throws SQLException { if (isClosed()) { return false; } try { return connection.isValid(timeoutSeconds); } 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(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; } } protected void passivate() throws SQLException { // The JDBC specification requires that a Connection close any open // Statement's when it is closed. // DBCP-288. Not all the traced objects will be statements final List traces = getTrace(); if (traces != null && !traces.isEmpty()) { final List thrownList = new ArrayList<>(); for (final Object trace : traces) { if (trace instanceof Statement) { try { ((Statement) trace).close(); } catch (final Exception e) { thrownList.add(e); } } else if (trace instanceof ResultSet) { // DBCP-265: Need to close the result sets that are // generated via DatabaseMetaData try { ((ResultSet) trace).close(); } catch (final Exception e) { thrownList.add(e); } } } clearTrace(); if (!thrownList.isEmpty()) { throw new SQLExceptionList(thrownList); } } setLastUsed(0); } @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 the state caching flag. * * @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); } } 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. * null means that the driver default will be used. * * @param defaultQueryTimeoutSeconds * the new query timeout limit in seconds; zero means there is no limit */ public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { this.defaultQueryTimeoutSeconds = defaultQueryTimeoutSeconds; } /** * Sets my delegate. * * @param connection * my delegate. */ 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 = connection.getSchema(); } } 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 ex) { // 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.java000066400000000000000000001615101410126276600342410ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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; /** *

* 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 = connection; this.databaseMetaData = databaseMetaData; } @Override public boolean allProceduresAreCallable() throws SQLException { try { return databaseMetaData.allProceduresAreCallable(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean allTablesAreSelectable() throws SQLException { try { return databaseMetaData.allTablesAreSelectable(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean autoCommitFailureClosesAllResultSets() throws SQLException { try { return databaseMetaData.autoCommitFailureClosesAllResultSets(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean dataDefinitionCausesTransactionCommit() throws SQLException { try { return databaseMetaData.dataDefinitionCausesTransactionCommit(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean dataDefinitionIgnoredInTransactions() throws SQLException { try { return databaseMetaData.dataDefinitionIgnoredInTransactions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean deletesAreDetected(final int type) throws SQLException { try { return databaseMetaData.deletesAreDetected(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { try { return databaseMetaData.doesMaxRowSizeIncludeBlobs(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean generatedKeyAlwaysReturned() throws SQLException { connection.checkOpen(); try { return Jdbc41Bridge.generatedKeyAlwaysReturned(databaseMetaData); } catch (final SQLException e) { handleException(e); return false; } } @Override public ResultSet getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, final String attributeNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, final boolean nullable) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getBestRowIdentifier(catalog, schema, table, scope, nullable)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getCatalogs() throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getCatalogs()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getCatalogSeparator() throws SQLException { try { return databaseMetaData.getCatalogSeparator(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getCatalogTerm() throws SQLException { try { return databaseMetaData.getCatalogTerm(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getClientInfoProperties() throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getClientInfoProperties()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getColumnPrivileges(final String catalog, final String schema, final String table, final String columnNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getColumnPrivileges(catalog, schema, table, columnNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @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 { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public int getDatabaseMajorVersion() throws SQLException { try { return databaseMetaData.getDatabaseMajorVersion(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getDatabaseMinorVersion() throws SQLException { try { return databaseMetaData.getDatabaseMinorVersion(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public String getDatabaseProductName() throws SQLException { try { return databaseMetaData.getDatabaseProductName(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getDatabaseProductVersion() throws SQLException { try { return databaseMetaData.getDatabaseProductVersion(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public int getDefaultTransactionIsolation() throws SQLException { try { return databaseMetaData.getDefaultTransactionIsolation(); } catch (final SQLException e) { handleException(e); return 0; } } /** * 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 { try { return databaseMetaData.getDriverName(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getDriverVersion() throws SQLException { try { return databaseMetaData.getDriverVersion(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getExportedKeys(final String catalog, final String schema, final String table) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getExportedKeys(catalog, schema, table)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getExtraNameCharacters() throws SQLException { try { return databaseMetaData.getExtraNameCharacters(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, final String columnNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getFunctions(catalog, schemaPattern, functionNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getIdentifierQuoteString() throws SQLException { try { return databaseMetaData.getIdentifierQuoteString(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getImportedKeys(final String catalog, final String schema, final String table) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getImportedKeys(catalog, schema, table)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, final boolean approximate) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getIndexInfo(catalog, schema, table, unique, approximate)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } /** * 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 { try { return databaseMetaData.getJDBCMajorVersion(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getJDBCMinorVersion() throws SQLException { try { return databaseMetaData.getJDBCMinorVersion(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxBinaryLiteralLength() throws SQLException { try { return databaseMetaData.getMaxBinaryLiteralLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxCatalogNameLength() throws SQLException { try { return databaseMetaData.getMaxCatalogNameLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxCharLiteralLength() throws SQLException { try { return databaseMetaData.getMaxCharLiteralLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxColumnNameLength() throws SQLException { try { return databaseMetaData.getMaxColumnNameLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxColumnsInGroupBy() throws SQLException { try { return databaseMetaData.getMaxColumnsInGroupBy(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxColumnsInIndex() throws SQLException { try { return databaseMetaData.getMaxColumnsInIndex(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxColumnsInOrderBy() throws SQLException { try { return databaseMetaData.getMaxColumnsInOrderBy(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxColumnsInSelect() throws SQLException { try { return databaseMetaData.getMaxColumnsInSelect(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxColumnsInTable() throws SQLException { try { return databaseMetaData.getMaxColumnsInTable(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxConnections() throws SQLException { try { return databaseMetaData.getMaxConnections(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxCursorNameLength() throws SQLException { try { return databaseMetaData.getMaxCursorNameLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxIndexLength() throws SQLException { try { return databaseMetaData.getMaxIndexLength(); } catch (final SQLException e) { handleException(e); return 0; } } /** * @since 2.5.0 */ @Override public long getMaxLogicalLobSize() throws SQLException { try { return databaseMetaData.getMaxLogicalLobSize(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxProcedureNameLength() throws SQLException { try { return databaseMetaData.getMaxProcedureNameLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxRowSize() throws SQLException { try { return databaseMetaData.getMaxRowSize(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxSchemaNameLength() throws SQLException { try { return databaseMetaData.getMaxSchemaNameLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxStatementLength() throws SQLException { try { return databaseMetaData.getMaxStatementLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxStatements() throws SQLException { try { return databaseMetaData.getMaxStatements(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxTableNameLength() throws SQLException { try { return databaseMetaData.getMaxTableNameLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxTablesInSelect() throws SQLException { try { return databaseMetaData.getMaxTablesInSelect(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public int getMaxUserNameLength() throws SQLException { try { return databaseMetaData.getMaxUserNameLength(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public String getNumericFunctions() throws SQLException { try { return databaseMetaData.getNumericFunctions(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getPrimaryKeys(final String catalog, final String schema, final String table) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getPrimaryKeys(catalog, schema, table)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getProcedureColumns(final String catalog, final String schemaPattern, final String procedureNamePattern, final String columnNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getProcedures(catalog, schemaPattern, procedureNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getProcedureTerm() throws SQLException { try { return databaseMetaData.getProcedureTerm(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, Jdbc41Bridge.getPseudoColumns(databaseMetaData, catalog, schemaPattern, tableNamePattern, columnNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public int getResultSetHoldability() throws SQLException { try { return databaseMetaData.getResultSetHoldability(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public RowIdLifetime getRowIdLifetime() throws SQLException { try { return databaseMetaData.getRowIdLifetime(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getSchemas() throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getSchemas()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getSchemas(final String catalog, final String schemaPattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getSchemas(catalog, schemaPattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getSchemaTerm() throws SQLException { try { return databaseMetaData.getSchemaTerm(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getSearchStringEscape() throws SQLException { try { return databaseMetaData.getSearchStringEscape(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getSQLKeywords() throws SQLException { try { return databaseMetaData.getSQLKeywords(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public int getSQLStateType() throws SQLException { try { return databaseMetaData.getSQLStateType(); } catch (final SQLException e) { handleException(e); return 0; } } @Override public String getStringFunctions() throws SQLException { try { return databaseMetaData.getStringFunctions(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getSuperTables(catalog, schemaPattern, tableNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getSuperTypes(catalog, schemaPattern, typeNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getSystemFunctions() throws SQLException { try { return databaseMetaData.getSystemFunctions(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getTablePrivileges(catalog, schemaPattern, tableNamePattern)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getTables(final String catalog, final String schemaPattern, final String tableNamePattern, final String[] types) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getTables(catalog, schemaPattern, tableNamePattern, types)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getTableTypes() throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getTableTypes()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getTimeDateFunctions() throws SQLException { try { return databaseMetaData.getTimeDateFunctions(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getTypeInfo() throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getTypeInfo()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, final int[] types) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getUDTs(catalog, schemaPattern, typeNamePattern, types)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getURL() throws SQLException { try { return databaseMetaData.getURL(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public String getUserName() throws SQLException { try { return databaseMetaData.getUserName(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } @Override public ResultSet getVersionColumns(final String catalog, final String schema, final String table) throws SQLException { connection.checkOpen(); try { return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getVersionColumns(catalog, schema, table)); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } 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 { try { return databaseMetaData.insertsAreDetected(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isCatalogAtStart() throws SQLException { try { return databaseMetaData.isCatalogAtStart(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean isReadOnly() throws SQLException { try { return databaseMetaData.isReadOnly(); } 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(databaseMetaData.getClass())) { return true; } return databaseMetaData.isWrapperFor(iface); } @Override public boolean locatorsUpdateCopy() throws SQLException { try { return databaseMetaData.locatorsUpdateCopy(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean nullPlusNonNullIsNull() throws SQLException { try { return databaseMetaData.nullPlusNonNullIsNull(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean nullsAreSortedAtEnd() throws SQLException { try { return databaseMetaData.nullsAreSortedAtEnd(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean nullsAreSortedAtStart() throws SQLException { try { return databaseMetaData.nullsAreSortedAtStart(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean nullsAreSortedHigh() throws SQLException { try { return databaseMetaData.nullsAreSortedHigh(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean nullsAreSortedLow() throws SQLException { try { return databaseMetaData.nullsAreSortedLow(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean othersDeletesAreVisible(final int type) throws SQLException { try { return databaseMetaData.othersDeletesAreVisible(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean othersInsertsAreVisible(final int type) throws SQLException { try { return databaseMetaData.othersInsertsAreVisible(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean othersUpdatesAreVisible(final int type) throws SQLException { try { return databaseMetaData.othersUpdatesAreVisible(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean ownDeletesAreVisible(final int type) throws SQLException { try { return databaseMetaData.ownDeletesAreVisible(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean ownInsertsAreVisible(final int type) throws SQLException { try { return databaseMetaData.ownInsertsAreVisible(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean ownUpdatesAreVisible(final int type) throws SQLException { try { return databaseMetaData.ownUpdatesAreVisible(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean storesLowerCaseIdentifiers() throws SQLException { try { return databaseMetaData.storesLowerCaseIdentifiers(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { try { return databaseMetaData.storesLowerCaseQuotedIdentifiers(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean storesMixedCaseIdentifiers() throws SQLException { try { return databaseMetaData.storesMixedCaseIdentifiers(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { try { return databaseMetaData.storesMixedCaseQuotedIdentifiers(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean storesUpperCaseIdentifiers() throws SQLException { try { return databaseMetaData.storesUpperCaseIdentifiers(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { try { return databaseMetaData.storesUpperCaseQuotedIdentifiers(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsAlterTableWithAddColumn() throws SQLException { try { return databaseMetaData.supportsAlterTableWithAddColumn(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsAlterTableWithDropColumn() throws SQLException { try { return databaseMetaData.supportsAlterTableWithDropColumn(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsANSI92EntryLevelSQL() throws SQLException { try { return databaseMetaData.supportsANSI92EntryLevelSQL(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsANSI92FullSQL() throws SQLException { try { return databaseMetaData.supportsANSI92FullSQL(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsANSI92IntermediateSQL() throws SQLException { try { return databaseMetaData.supportsANSI92IntermediateSQL(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsBatchUpdates() throws SQLException { try { return databaseMetaData.supportsBatchUpdates(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsCatalogsInDataManipulation() throws SQLException { try { return databaseMetaData.supportsCatalogsInDataManipulation(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsCatalogsInIndexDefinitions() throws SQLException { try { return databaseMetaData.supportsCatalogsInIndexDefinitions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { try { return databaseMetaData.supportsCatalogsInPrivilegeDefinitions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsCatalogsInProcedureCalls() throws SQLException { try { return databaseMetaData.supportsCatalogsInProcedureCalls(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsCatalogsInTableDefinitions() throws SQLException { try { return databaseMetaData.supportsCatalogsInTableDefinitions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsColumnAliasing() throws SQLException { try { return databaseMetaData.supportsColumnAliasing(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsConvert() throws SQLException { try { return databaseMetaData.supportsConvert(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsConvert(final int fromType, final int toType) throws SQLException { try { return databaseMetaData.supportsConvert(fromType, toType); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsCoreSQLGrammar() throws SQLException { try { return databaseMetaData.supportsCoreSQLGrammar(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsCorrelatedSubqueries() throws SQLException { try { return databaseMetaData.supportsCorrelatedSubqueries(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { try { return databaseMetaData.supportsDataDefinitionAndDataManipulationTransactions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsDataManipulationTransactionsOnly() throws SQLException { try { return databaseMetaData.supportsDataManipulationTransactionsOnly(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsDifferentTableCorrelationNames() throws SQLException { try { return databaseMetaData.supportsDifferentTableCorrelationNames(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsExpressionsInOrderBy() throws SQLException { try { return databaseMetaData.supportsExpressionsInOrderBy(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsExtendedSQLGrammar() throws SQLException { try { return databaseMetaData.supportsExtendedSQLGrammar(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsFullOuterJoins() throws SQLException { try { return databaseMetaData.supportsFullOuterJoins(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsGetGeneratedKeys() throws SQLException { try { return databaseMetaData.supportsGetGeneratedKeys(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsGroupBy() throws SQLException { try { return databaseMetaData.supportsGroupBy(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsGroupByBeyondSelect() throws SQLException { try { return databaseMetaData.supportsGroupByBeyondSelect(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsGroupByUnrelated() throws SQLException { try { return databaseMetaData.supportsGroupByUnrelated(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsIntegrityEnhancementFacility() throws SQLException { try { return databaseMetaData.supportsIntegrityEnhancementFacility(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsLikeEscapeClause() throws SQLException { try { return databaseMetaData.supportsLikeEscapeClause(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsLimitedOuterJoins() throws SQLException { try { return databaseMetaData.supportsLimitedOuterJoins(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsMinimumSQLGrammar() throws SQLException { try { return databaseMetaData.supportsMinimumSQLGrammar(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsMixedCaseIdentifiers() throws SQLException { try { return databaseMetaData.supportsMixedCaseIdentifiers(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { try { return databaseMetaData.supportsMixedCaseQuotedIdentifiers(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsMultipleOpenResults() throws SQLException { try { return databaseMetaData.supportsMultipleOpenResults(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsMultipleResultSets() throws SQLException { try { return databaseMetaData.supportsMultipleResultSets(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsMultipleTransactions() throws SQLException { try { return databaseMetaData.supportsMultipleTransactions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsNamedParameters() throws SQLException { try { return databaseMetaData.supportsNamedParameters(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsNonNullableColumns() throws SQLException { try { return databaseMetaData.supportsNonNullableColumns(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsOpenCursorsAcrossCommit() throws SQLException { try { return databaseMetaData.supportsOpenCursorsAcrossCommit(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsOpenCursorsAcrossRollback() throws SQLException { try { return databaseMetaData.supportsOpenCursorsAcrossRollback(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsOpenStatementsAcrossCommit() throws SQLException { try { return databaseMetaData.supportsOpenStatementsAcrossCommit(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsOpenStatementsAcrossRollback() throws SQLException { try { return databaseMetaData.supportsOpenStatementsAcrossRollback(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsOrderByUnrelated() throws SQLException { try { return databaseMetaData.supportsOrderByUnrelated(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsOuterJoins() throws SQLException { try { return databaseMetaData.supportsOuterJoins(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsPositionedDelete() throws SQLException { try { return databaseMetaData.supportsPositionedDelete(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsPositionedUpdate() throws SQLException { try { return databaseMetaData.supportsPositionedUpdate(); } catch (final SQLException e) { handleException(e); return false; } } /** * @since 2.5.0 */ @Override public boolean supportsRefCursors() throws SQLException { try { return databaseMetaData.supportsRefCursors(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsResultSetConcurrency(final int type, final int concurrency) throws SQLException { try { return databaseMetaData.supportsResultSetConcurrency(type, concurrency); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsResultSetHoldability(final int holdability) throws SQLException { try { return databaseMetaData.supportsResultSetHoldability(holdability); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsResultSetType(final int type) throws SQLException { try { return databaseMetaData.supportsResultSetType(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSavepoints() throws SQLException { try { return databaseMetaData.supportsSavepoints(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSchemasInDataManipulation() throws SQLException { try { return databaseMetaData.supportsSchemasInDataManipulation(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSchemasInIndexDefinitions() throws SQLException { try { return databaseMetaData.supportsSchemasInIndexDefinitions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { try { return databaseMetaData.supportsSchemasInPrivilegeDefinitions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSchemasInProcedureCalls() throws SQLException { try { return databaseMetaData.supportsSchemasInProcedureCalls(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSchemasInTableDefinitions() throws SQLException { try { return databaseMetaData.supportsSchemasInTableDefinitions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSelectForUpdate() throws SQLException { try { return databaseMetaData.supportsSelectForUpdate(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsStatementPooling() throws SQLException { try { return databaseMetaData.supportsStatementPooling(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { try { return databaseMetaData.supportsStoredFunctionsUsingCallSyntax(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsStoredProcedures() throws SQLException { try { return databaseMetaData.supportsStoredProcedures(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSubqueriesInComparisons() throws SQLException { try { return databaseMetaData.supportsSubqueriesInComparisons(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSubqueriesInExists() throws SQLException { try { return databaseMetaData.supportsSubqueriesInExists(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSubqueriesInIns() throws SQLException { try { return databaseMetaData.supportsSubqueriesInIns(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsSubqueriesInQuantifieds() throws SQLException { try { return databaseMetaData.supportsSubqueriesInQuantifieds(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsTableCorrelationNames() throws SQLException { try { return databaseMetaData.supportsTableCorrelationNames(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsTransactionIsolationLevel(final int level) throws SQLException { try { return databaseMetaData.supportsTransactionIsolationLevel(level); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsTransactions() throws SQLException { try { return databaseMetaData.supportsTransactions(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsUnion() throws SQLException { try { return databaseMetaData.supportsUnion(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean supportsUnionAll() throws SQLException { try { return databaseMetaData.supportsUnionAll(); } catch (final SQLException e) { handleException(e); return false; } } /* JDBC_4_ANT_KEY_END */ @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 { try { return databaseMetaData.updatesAreDetected(type); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean usesLocalFilePerTable() throws SQLException { try { return databaseMetaData.usesLocalFilePerTable(); } catch (final SQLException e) { handleException(e); return false; } } @Override public boolean usesLocalFiles() throws SQLException { try { return databaseMetaData.usesLocalFiles(); } catch (final SQLException e) { handleException(e); return false; } } } DelegatingPreparedStatement.java000066400000000000000000000527101410126276600345640ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.Statement; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; /** * 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(); } } @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() { final Statement statement = getDelegate(); return statement == null ? "NULL" : statement.toString(); } } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/DelegatingResultSet.java000066400000000000000000001636651410126276600331620ustar00rootroot00000000000000/* * 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.9.0/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java000066400000000000000000000557131410126276600331660ustar00rootroot00000000000000/* * 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; /** * 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: \"" + this.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 resultSetList = getTrace(); if (resultSetList != null) { final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY); for (final ResultSet resultSet : resultSets) { if (resultSet != null) { try { resultSet.close(); } catch (final Exception e) { if (connection != null) { // Does not rethrow e. connection.handleExceptionNoThrow(e); } thrownList.add(e); } } } clearTrace(); } if (statement != null) { try { statement.close(); } catch (final Exception 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. * * @see #getDelegate */ @SuppressWarnings("resource") public Statement getInnermostDelegate() { Statement s = statement; while (s instanceof DelegatingStatement) { s = ((DelegatingStatement) s).getDelegate(); if (this == s) { return null; } } return s; } /** * @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 statement == null ? "NULL" : statement.toString(); } @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.java000066400000000000000000000046351410126276600337570ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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); } /** * @return The connection String. * @since 2.6.0 */ public String getConnectionString() { return connectionString; } /** * @return The Driver. * @since 2.6.0 */ public Driver getDriver() { return driver; } /** * @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.9.0/src/main/java/org/apache/commons/dbcp2/DriverFactory.java000066400000000000000000000065421410126276600320150ustar00rootroot00000000000000/* * 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 */ 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.java000066400000000000000000000114561410126276600352510ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 url of the form 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 url of the form 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 url of the form 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 url of the form 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.9.0/src/main/java/org/apache/commons/dbcp2/Jdbc41Bridge.java000066400000000000000000000452341410126276600313570ustar00rootroot00000000000000/* * 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) methods to allow call sites to operate safely (without * {@link AbstractMethodError}) when using a JDBC driver written for JDBC 4.0 (Java 6). *

* 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 e) { // 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 e) { // do nothing } } } LifetimeExceededException.java000066400000000000000000000026411410126276600342130ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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; /** * Exception thrown when a connection's maximum lifetime has been exceeded. * * @since 2.1 */ class LifetimeExceededException extends Exception { private static final long serialVersionUID = -3783783104516492659L; /** * Create a LifetimeExceededException. */ public LifetimeExceededException() { } /** * Create a LifetimeExceededException with the given message. * * @param message * The message with which to create the exception */ public LifetimeExceededException(final String message) { super(message); } } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/ListException.java000066400000000000000000000035101410126276600320140ustar00rootroot00000000000000/* * 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.9.0/src/main/java/org/apache/commons/dbcp2/ObjectNameWrapper.java000066400000000000000000000063601410126276600326000ustar00rootroot00000000000000/* * 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 */ 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.9.0/src/main/java/org/apache/commons/dbcp2/PStmtKey.java000066400000000000000000001072301410126276600307460ustar00rootroot00000000000000/* * 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 org.apache.commons.dbcp2.PoolingConnection.StatementType; /** * A key uniquely identifying {@link java.sql.PreparedStatement PreparedStatement}s. * * @since 2.0 */ public class PStmtKey { /** * Builder for prepareCall(String sql). */ private class PreparedCallSQL implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareCall(sql); } } /** * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency). */ private class PreparedCallWithResultSetConcurrency implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareCall(sql, resultSetType, resultSetConcurrency); } } /** * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). */ private class PreparedCallWithResultSetHoldability implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } } /** * Builder for prepareStatement(String sql). */ private class PreparedStatementSQL implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareStatement(sql); } } /** * Builder for prepareStatement(String sql, int autoGeneratedKeys). */ private class PreparedStatementWithAutoGeneratedKeys implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareStatement(sql, autoGeneratedKeys); } } /** * Builder for prepareStatement(String sql, int[] columnIndexes). */ private class PreparedStatementWithColumnIndexes implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareStatement(sql, columnIndexes); } } /** * Builder for prepareStatement(String sql, String[] columnNames). */ private class PreparedStatementWithColumnNames implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareStatement(sql, columnNames); } } /** * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency). */ private class PreparedStatementWithResultSetConcurrency implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareStatement(sql, resultSetType, resultSetConcurrency); } } /** * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). */ private class PreparedStatementWithResultSetHoldability implements StatementBuilder { @Override public Statement createStatement(final Connection connection) throws SQLException { return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } } /** * Interface for Prepared or Callable Statement. */ private interface StatementBuilder { Statement createStatement(Connection connection) throws SQLException; } /** * SQL defining Prepared or Callable Statement */ private final String sql; /** * Result set type; one of ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, * or ResultSet.TYPE_SCROLL_SENSITIVE. */ private final Integer resultSetType; /** * Result set concurrency. A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. */ private final Integer resultSetConcurrency; /** * Result set holdability. One of the following ResultSet constants: * ResultSet.HOLD_CURSORS_OVER_COMMIT or 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 * Statement.RETURN_GENERATED_KEYS or 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 type, prepared or callable. */ private final StatementType statementType; /** Statement builder */ private transient StatementBuilder builder; /** * 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * 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 * Statement.RETURN_GENERATED_KEYS or 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * @deprecated Use @link {@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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE * @param resultSetHoldability * One of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * @param resultSetHoldability * One of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or 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 = sql; this.catalog = catalog; this.schema = null; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; this.resultSetHoldability = resultSetHoldability; this.statementType = statementType; this.autoGeneratedKeys = null; this.columnIndexes = null; this.columnNames = null; // create builder if (statementType == StatementType.PREPARED_STATEMENT) { this.builder = new PreparedStatementWithResultSetHoldability(); } else if (statementType == StatementType.CALLABLE_STATEMENT) { this.builder = new PreparedCallWithResultSetHoldability(); } } /** * 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * 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 = sql; this.catalog = catalog; this.schema = null; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; this.resultSetHoldability = null; this.statementType = statementType; this.autoGeneratedKeys = null; this.columnIndexes = null; this.columnNames = null; // create builder if (statementType == StatementType.PREPARED_STATEMENT) { this.builder = new PreparedStatementWithResultSetConcurrency(); } else if (statementType == StatementType.CALLABLE_STATEMENT) { this.builder = new PreparedCallWithResultSetConcurrency(); } } /** * 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 = sql; this.catalog = catalog; this.schema = null; this.statementType = StatementType.PREPARED_STATEMENT; this.autoGeneratedKeys = null; this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length); this.columnNames = null; this.resultSetType = null; this.resultSetConcurrency = null; this.resultSetHoldability = null; // create builder this.builder = new PreparedStatementWithColumnIndexes(); } /** * 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 = sql; this.catalog = catalog; this.schema = null; this.statementType = statementType; this.autoGeneratedKeys = null; this.columnIndexes = null; this.columnNames = null; this.resultSetType = null; this.resultSetConcurrency = null; this.resultSetHoldability = null; // create builder if (statementType == StatementType.PREPARED_STATEMENT) { this.builder = new PreparedStatementSQL(); } else if (statementType == StatementType.CALLABLE_STATEMENT) { this.builder = new PreparedCallSQL(); } } /** * 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 * Statement.RETURN_GENERATED_KEYS or 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 = sql; this.catalog = catalog; this.schema = null; this.statementType = statementType; this.autoGeneratedKeys = autoGeneratedKeys; this.columnIndexes = null; this.columnNames = null; this.resultSetType = null; this.resultSetConcurrency = null; this.resultSetHoldability = null; // create builder if (statementType == StatementType.PREPARED_STATEMENT) { this.builder = new PreparedStatementWithAutoGeneratedKeys(); } else if (statementType == StatementType.CALLABLE_STATEMENT) { this.builder = new PreparedCallSQL(); } } /** * 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 * Statement.RETURN_GENERATED_KEYS or 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE * @param resultSetHoldability * One of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * @param resultSetHoldability * One of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or 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 = sql; this.catalog = catalog; this.schema = schema; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; this.resultSetHoldability = resultSetHoldability; this.statementType = statementType; this.autoGeneratedKeys = null; this.columnIndexes = null; this.columnNames = null; // create builder if (statementType == StatementType.PREPARED_STATEMENT) { this.builder = new PreparedStatementWithResultSetHoldability(); } else if (statementType == StatementType.CALLABLE_STATEMENT) { this.builder = new PreparedCallWithResultSetHoldability(); } } /** * 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * 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 = sql; this.catalog = catalog; this.schema = schema; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; this.resultSetHoldability = null; this.statementType = statementType; this.autoGeneratedKeys = null; this.columnIndexes = null; this.columnNames = null; // create builder if (statementType == StatementType.PREPARED_STATEMENT) { this.builder = new PreparedStatementWithResultSetConcurrency(); } else if (statementType == StatementType.CALLABLE_STATEMENT) { this.builder = new PreparedCallWithResultSetConcurrency(); } } /** * 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 = sql; this.catalog = catalog; this.schema = schema; this.statementType = StatementType.PREPARED_STATEMENT; this.autoGeneratedKeys = null; this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length); this.columnNames = null; this.resultSetType = null; this.resultSetConcurrency = null; this.resultSetHoldability = null; // create builder this.builder = new PreparedStatementWithColumnIndexes(); } /** * 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 = sql; this.catalog = catalog; this.schema = schema; this.statementType = statementType; this.autoGeneratedKeys = null; this.columnIndexes = null; this.columnNames = null; this.resultSetType = null; this.resultSetConcurrency = null; this.resultSetHoldability = null; // create builder if (statementType == StatementType.PREPARED_STATEMENT) { this.builder = new PreparedStatementSQL(); } else if (statementType == StatementType.CALLABLE_STATEMENT) { this.builder = new PreparedCallSQL(); } } /** * 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 * Statement.RETURN_GENERATED_KEYS or 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 = sql; this.catalog = catalog; this.schema = schema; this.statementType = statementType; this.autoGeneratedKeys = autoGeneratedKeys; this.columnIndexes = null; this.columnNames = null; this.resultSetType = null; this.resultSetConcurrency = null; this.resultSetHoldability = null; // create builder if (statementType == StatementType.PREPARED_STATEMENT) { this.builder = new PreparedStatementWithAutoGeneratedKeys(); } else if (statementType == StatementType.CALLABLE_STATEMENT) { this.builder = new PreparedCallSQL(); } } /** * 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 = sql; this.catalog = catalog; this.schema = schema; this.statementType = StatementType.PREPARED_STATEMENT; this.autoGeneratedKeys = null; this.columnIndexes = null; this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length); this.resultSetType = null; this.resultSetConcurrency = null; this.resultSetHoldability = null; // create builder builder = new PreparedStatementWithColumnNames(); } /** * 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 = sql; this.catalog = catalog; this.schema = null; this.statementType = StatementType.PREPARED_STATEMENT; this.autoGeneratedKeys = null; this.columnIndexes = null; this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length); this.resultSetType = null; this.resultSetConcurrency = null; this.resultSetHoldability = null; // create builder builder = new PreparedStatementWithColumnNames(); } /** * 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 { if (builder == null) { throw new IllegalStateException("Prepared statement key is invalid."); } return builder.createStatement(connection); } @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 * Statement.RETURN_GENERATED_KEYS or Statement.NO_GENERATED_KEYS. * * @return a flag indicating whether auto-generated keys should be returned. */ public Integer getAutoGeneratedKeys() { return autoGeneratedKeys; } /** * 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 columnIndexes == null ? null : columnIndexes.clone(); } /** * 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 columnNames == null ? null : columnNames.clone(); } /** * Gets the result set concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * * @return The result set concurrency type. */ public Integer getResultSetConcurrency() { return resultSetConcurrency; } /** * Gets the result set holdability, one of the following ResultSet constants: * ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT. * * @return The result set holdability. */ public Integer getResultSetHoldability() { return resultSetHoldability; } /** * Gets the result set type, one of ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * * @return the result set type. */ public Integer getResultSetType() { return resultSetType; } /** * The schema. * * @return The catalog. */ public String getSchema() { return schema; } /** * Gets the SQL statement. * * @return the SQL statement. */ public String getSql() { return sql; } /** * 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.java000066400000000000000000000120731410126276600342110ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; 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; /** * Constructor. * * @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(getConnectionInternal()); } /** * 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); if (getConnectionInternal() != null) { getConnectionInternal().addTrace(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 { 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 resultSetList = getTrace(); if (resultSetList != null) { final List thrownList = new ArrayList<>(); final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY); for (final ResultSet resultSet : resultSets) { if (resultSet != null) { try { resultSet.close(); } catch (final Exception e) { thrownList.add(e); } } } clearTrace(); if (!thrownList.isEmpty()) { throw new SQLExceptionList(thrownList); } } super.passivate(); } } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java000066400000000000000000000320571410126276600330070ustar00rootroot00000000000000/* * 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.util.Collection; import java.util.concurrent.Executor; 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; /** * 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 ex) { // 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#DISCONNECTION_SQL_CODES} (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). */ private final Collection disconnectionSqlCodes; /** Whether or not to fast fail validation after fatal connection errors */ private final boolean fastFailValidation; /** * * @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) { super(conn); this.pool = pool; this.jmxObjectName = ObjectNameWrapper.wrap(jmxObjectName); this.disconnectionSqlCodes = disconnectSqlCodes; this.fastFailValidation = fastFailValidation; if (jmxObjectName != null) { try { MBEAN_SERVER.registerMBean(this, jmxObjectName); } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) { // 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 me to my pool. */ @Override public synchronized void close() throws SQLException { 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 ie) { // 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); } } } /** * @return The disconnection SQL codes. * @since 2.6.0 */ public Collection getDisconnectionSqlCodes() { return disconnectionSqlCodes; } /** * Expose 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 |= isDisconnectionSqlException(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 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#DISCONNECTION_SQL_CODES} 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 */ private boolean isDisconnectionSqlException(final SQLException e) { boolean fatalException = false; final String sqlState = e.getSQLState(); if (sqlState != null) { fatalException = disconnectionSqlCodes == null ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.DISCONNECTION_SQL_CODES.contains(sqlState) : disconnectionSqlCodes.contains(sqlState); if (!fatalException) { final SQLException nextException = e.getNextException(); if (nextException != null && nextException != e) { fatalException = isDisconnectionSqlException(e.getNextException()); } } } return fatalException; } /** * @return Whether to fail-fast. * @since 2.6.0 */ public boolean isFastFailValidation() { return fastFailValidation; } @Override protected void passivate() throws SQLException { super.passivate(); setClosedInternal(true); if (getDelegateInternal() instanceof PoolingConnection) { ((PoolingConnection) getDelegateInternal()).connectionReturnedToPool(); } } /** * Actually close my underlying {@link Connection}. */ @Override public void reallyClose() throws SQLException { if (jmxObjectName != null) { jmxObjectName.unregisterMBean(); } if (validationPreparedStatement != null) { Utils.closeQuietly(validationPreparedStatement); } super.closeInternal(); } /** * 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 */ public void validate(final String sql, int timeoutSeconds) throws SQLException { if (fastFailValidation && fatalSqlExceptionThrown) { throw new SQLException(Utils.getMessage("poolableConnection.validate.fastFail")); } if (sql == null || sql.isEmpty()) { if (timeoutSeconds < 0) { timeoutSeconds = 0; } if (!isValid(timeoutSeconds)) { 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 (timeoutSeconds > 0) { validationPreparedStatement.setQueryTimeout(timeoutSeconds); } try (ResultSet rs = validationPreparedStatement.executeQuery()) { if (!rs.next()) { throw new SQLException("validationQuery didn't return a row"); } } catch (final SQLException sqle) { throw sqle; } } } PoolableConnectionFactory.java000066400000000000000000000542521410126276600342610ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.util.Collection; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; 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 int validationQueryTimeoutSeconds = -1; private Collection connectionInitSqls; private Collection disconnectionSqlCodes; 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 long maxConnLifetimeMillis = -1; private final AtomicLong connectionIndex = new AtomicLong(); private Integer defaultQueryTimeoutSeconds; /** * 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 Exception { 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(defaultQueryTimeoutSeconds); } @Override public void destroyObject(final PooledObject p) throws Exception { p.getObject().reallyClose(); } /** * @since 2.9.0 */ @Override public void destroyObject(final PooledObject p, final DestroyMode mode) throws Exception { if (mode == DestroyMode.ABANDONED) { p.getObject().getInnermostDelegate().abort(Runnable::run); } else { p.getObject().reallyClose(); } } /** * Gets the cache state. * * @return The cache state. * @since Made public in 2.6.0. */ public boolean getCacheState() { return cacheState; } /** * Gets the connection factory. * * @return The connection factory. * @since Made public in 2.6.0. */ public ConnectionFactory getConnectionFactory() { return connectionFactory; } protected AtomicLong getConnectionIndex() { return connectionIndex; } /** * @return The collection of initialization SQL statements. * @since 2.6.0 */ public Collection getConnectionInitSqls() { return connectionInitSqls; } /** * @return The data source JMX ObjectName * @since Made public in 2.6.0. */ public ObjectName getDataSourceJmxName() { return dataSourceJmxObjectName; } /** * @return The data source JMS ObjectName. * @since 2.6.0 */ public ObjectName getDataSourceJmxObjectName() { return dataSourceJmxObjectName; } /** * @return Default auto-commit value. * @since 2.6.0 */ public Boolean getDefaultAutoCommit() { return defaultAutoCommit; } /** * @return Default catalog. * @since 2.6.0 */ public String getDefaultCatalog() { return defaultCatalog; } /** * @return Default query timeout in seconds. */ public Integer getDefaultQueryTimeout() { return defaultQueryTimeoutSeconds; } /** * @return Default query timeout in seconds. * @since 2.6.0 */ public Integer getDefaultQueryTimeoutSeconds() { return defaultQueryTimeoutSeconds; } /** * @return Default read-only-value. * @since 2.6.0 */ public Boolean getDefaultReadOnly() { return defaultReadOnly; } /** * @return Default schema. * @since 2.6.0 */ public String getDefaultSchema() { return defaultSchema; } /** * @return Default transaction isolation. * @since 2.6.0 */ public int getDefaultTransactionIsolation() { return defaultTransactionIsolation; } /** * SQL_STATE codes considered to signal fatal conditions. *

* Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} (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; } /** * @return Maximum connection lifetime in milliseconds. * @since 2.6.0 */ public long getMaxConnLifetimeMillis() { return maxConnLifetimeMillis; } 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; } /** * @return Whether to pool statements. * @since Made public in 2.6.0. */ public boolean getPoolStatements() { return poolStatements; } /** * @return Validation query. * @since 2.6.0 */ public String getValidationQuery() { return validationQuery; } /** * @return Validation query timeout in seconds. * @since 2.6.0 */ public int getValidationQueryTimeoutSeconds() { return validationQueryTimeoutSeconds; } protected void initializeConnection(final Connection conn) throws SQLException { final Collection sqls = connectionInitSqls; if (conn.isClosed()) { throw new SQLException("initializeConnection: connection closed"); } if (null != sqls) { try (Statement stmt = conn.createStatement()) { for (final String sql : sqls) { Objects.requireNonNull(sql, "null connectionInitSqls element"); stmt.execute(sql); } } } } /** * @return Whether to auto-commit on return. * @since 2.6.0 */ public boolean isAutoCommitOnReturn() { return autoCommitOnReturn; } /** * @return Whether to auto-commit on return. * @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; } /** * @return Whether to rollback on return. */ public boolean isRollbackOnReturn() { return rollbackOnReturn; } @Override public PooledObject makeObject() throws Exception { Connection conn = connectionFactory.createConnection(); if (conn == null) { throw new IllegalStateException("Connection factory returned null from createConnection"); } try { initializeConnection(conn); } catch (final SQLException sqle) { // Make sure the connection is closed Utils.closeQuietly(conn); // Rethrow original exception so it is visible to caller throw sqle; } final long connIndex = connectionIndex.getAndIncrement(); if (poolStatements) { conn = new PoolingConnection(conn); final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotalPerKey(-1); config.setBlockWhenExhausted(false); config.setMaxWaitMillis(0); 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 { connJmxName = new ObjectName( dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex); } final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, fastFailValidation); pc.setCacheState(cacheState); return new DefaultPooledObject<>(pc); } @Override public void passivateObject(final PooledObject p) throws Exception { 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(); } public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { this.autoCommitOnReturn = autoCommitOnReturn; } 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; } public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { this.defaultQueryTimeoutSeconds = 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; } /** * @param disconnectionSqlCodes * The disconnection SQL codes. * @see #getDisconnectionSqlCodes() * @since 2.1 */ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCodes) { this.disconnectionSqlCodes = disconnectionSqlCodes; } /** * @param autoCommitOnReturn Whether to auto-commit on return. * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}. */ @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 maxConnLifetimeMillis * The maximum lifetime in milliseconds. */ public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { this.maxConnLifetimeMillis = 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; } public void setPoolStatements(final boolean poolStatements) { this.poolStatements = poolStatements; } 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, 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 */ public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds; } public void validateConnection(final PoolableConnection conn) throws SQLException { if (conn.isClosed()) { throw new SQLException("validateConnection: connection closed"); } conn.validate(validationQuery, validationQueryTimeoutSeconds); } private void validateLifetime(final PooledObject p) throws Exception { if (maxConnLifetimeMillis > 0) { final long lifetimeMillis = System.currentTimeMillis() - p.getCreateTime(); if (lifetimeMillis > maxConnLifetimeMillis) { throw new LifetimeExceededException(Utils.getMessage("connectionFactory.lifetimeExceeded", lifetimeMillis, maxConnLifetimeMillis)); } } } @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.java000066400000000000000000000041351410126276600337570ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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; /** * Defines the attributes and methods that will be exposed via JMX for {@link PoolableConnection} instances. * * @since 2.0 */ public interface PoolableConnectionMXBean { // Methods void clearCachedState(); void clearWarnings() throws SQLException; void close() throws SQLException; // Read-write properties boolean getAutoCommit() throws SQLException; boolean getCacheState(); String getCatalog() throws SQLException; int getHoldability() throws SQLException; String getSchema() throws SQLException; // SQLWarning getWarnings() throws SQLException; String getToString(); int getTransactionIsolation() throws SQLException; // Read-only properties boolean isClosed() throws SQLException; boolean isReadOnly() throws SQLException; void reallyClose() throws SQLException; void setAutoCommit(boolean autoCommit) throws SQLException; void setCacheState(boolean cacheState); void setCatalog(String catalog) throws SQLException; void setHoldability(int holdability) throws SQLException; void setReadOnly(boolean readOnly) throws SQLException; void setSchema(String schema) throws SQLException; void setTransactionIsolation(int level) throws SQLException; } PoolablePreparedStatement.java000066400000000000000000000116201410126276600342510ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; 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; /** * Constructor. * * @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(getConnectionInternal()); } @Override public void activate() throws SQLException { setClosedInternal(false); if (getConnectionInternal() != null) { getConnectionInternal().addTrace(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); } } } @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(); } setClosedInternal(true); removeThisTrace(getConnectionInternal()); // The JDBC spec requires that a statement closes 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 resultSetList = getTrace(); if (resultSetList != null) { final List thrownList = new ArrayList<>(); final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY); for (final ResultSet resultSet : resultSets) { if (resultSet != null) { try { resultSet.close(); } catch (final Exception e) { thrownList.add(e); } } } clearTrace(); if (!thrownList.isEmpty()) { throw new SQLExceptionList(thrownList); } } super.passivate(); } } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java000066400000000000000000000541141410126276600326570ustar00rootroot00000000000000/* * 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.util.NoSuchElementException; 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 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. * * @since 2.0 protected enum. * @since 2.4.0 public enum. */ public enum StatementType { /** * Callable statement. */ CALLABLE_STATEMENT, /** * Prepared statement. */ PREPARED_STATEMENT } /** Pool of {@link PreparedStatement}s. and {@link CallableStatement}s */ private KeyedObjectPool pstmtPool; private boolean clearStatementPoolOnReturn; /** * Constructor. * * @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 Exception { 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 { getDelegateInternal().close(); } finally { setClosedInternal(true); } } } /** * Notification from {@link PoolableConnection} that we returned to the pool. * * @throws SQLException when 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 * Statement.RETURN_GENERATED_KEYS or 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 Exception { pooledObject.getObject().getInnermostDelegate().close(); } private String getCatalogOrNull() { String catalog = null; try { catalog = getCatalog(); } catch (final SQLException e) { // Ignored } return catalog; } private String getSchemaOrNull() { String schema = null; try { schema = getSchema(); } catch (final SQLException e) { // Ignored } return schema; } /** * Returns the prepared statement pool we're using. * * @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 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 Exception { 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 Exception { @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 * Statement.RETURN_GENERATED_KEYS or 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 != null) { return "PoolingConnection: " + pstmtPool.toString(); } return "PoolingConnection: null"; } /** * {@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.9.0/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java000066400000000000000000000206211410126276600326060ustar00rootroot00000000000000/* * 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 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 must not be null."); 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, "PoolableConnectionFactory must not be null."); 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 RuntimeException, SQLException { try { pool.close(); } catch (final RuntimeException rte) { throw new RuntimeException(Utils.getMessage("pool.close.fail"), rte); } 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 uname, final String passwd) throws SQLException { throw new UnsupportedOperationException(); } // --- DataSource methods ----------------------------------------- /** * 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(); } 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); } /* JDBC_4_ANT_KEY_END */ } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java000066400000000000000000000204531410126276600320120ustar00rootroot00000000000000/* * 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 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 e) { // ignore } } /** The map of registered pools. */ protected static final HashMap> pools = new HashMap<>(); /** My URL prefix */ public static final String URL_PREFIX = "jdbc:apache:commons:dbcp:"; protected static final int URL_PREFIX_LEN = URL_PREFIX.length(); // version numbers protected static final int MAJOR_VERSION = 1; protected static final int MINOR_VERSION = 0; /** Controls access to the underlying connection */ private final boolean accessToUnderlyingConnectionAllowed; /** * Constructs a new driver with 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 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 e) { // Ignore. } } /** * 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.9.0/src/main/java/org/apache/commons/dbcp2/SQLExceptionList.java000066400000000000000000000036261410126276600324040ustar00rootroot00000000000000/* * 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.java000066400000000000000000000041471410126276600341320ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.9.0/src/main/java/org/apache/commons/dbcp2/Utils.java000066400000000000000000000153011410126276600303230ustar00rootroot00000000000000/* * 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.util.HashSet; import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; /** * 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)
  • *
*/ 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 } /** * 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 AutoCloseable (which may be null). * * @param autoCloseable an AutoCloseable, may be {@code null} * @since 2.6.0 */ public static void closeQuietly(final AutoCloseable autoCloseable) { if (autoCloseable != null) { try { autoCloseable.close(); } catch (final Exception e) { // ignored } } } /** * 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) { if (connection != null) { try { connection.close(); } catch (final Exception e) { // ignored } } } /** * 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) { if (resultSet != null) { try { resultSet.close(); } catch (final Exception e) { // ignored } } } /** * 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) { if (statement != null) { try { statement.close(); } catch (final Exception e) { // ignored } } } /** * 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(); } 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); } private Utils() { // not instantiable } } commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/cpdsadapter/000077500000000000000000000000001410126276600306525ustar00rootroot00000000000000ConnectionImpl.java000066400000000000000000000310751410126276600343650ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 Connection that will be returned from * PooledConnectionImpl.getConnection(). Most methods are wrappers around the JDBC 1.x * 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 */ class ConnectionImpl extends DelegatingConnection { private final boolean accessToUnderlyingConnectionAllowed; /** The object that instantiated this object */ private final PooledConnectionImpl pooledConnection; /** * Creates a 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(); } } } /** * Get 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; } /** * Get 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; } /** * 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 CallableStatements 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 CallableStatement object containing the pre-compiled SQL statement. * @exception 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 CallableStatements 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 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * a concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * @return a CallableStatement object containing the pre-compiled SQL statement that will produce * 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 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 CallableStatements 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 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 ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * @param resultSetHoldability * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or ResultSet.CLOSE_CURSORS_AT_COMMIT. * @return a new CallableStatement object, containing the pre-compiled SQL statement, that will * generate 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 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 PreparedStatements 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; } } /** * If pooling of PreparedStatements 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; } } // // Methods for accessing the delegate connection // @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.java000066400000000000000000000772011410126276600346530ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.BasicDataSource; 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. ConnectionPoolDataSources are not used * within general applications. They are used by DataSource implementations that pool * Connections, such as {@link org.apache.commons.dbcp2.datasources.SharedPoolDataSource}. A J2EE container * will normally provide some method of initializing the 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 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 DataSource. Jdbc2PoolDataSource can use the * ConnectionPoolDataSource with or without the use of JNDI. *

*

* The DriverAdapterCPDS also provides PreparedStatement pooling which is not generally available in jdbc2 * ConnectionPoolDataSource implementation, but is addressed within the jdbc3 specification. The * 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 catalina and JNDI. The * datasources package documentation shows how to use * DriverAdapterCPDS as a source for Jdbc2PoolDataSource without the use of JNDI. *

* * @since 2.0 */ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceable, Serializable, ObjectFactory { 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; /** Url name */ private String url; /** 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_TIME_BETWEEN_EVICTION_RUNS; private int numTestsPerEvictionRun = -1; private Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME; 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 Exception { // 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("description"); if (isNotEmpty(ra)) { setDescription(getStringContent(ra)); } ra = ref.get("driver"); if (isNotEmpty(ra)) { setDriver(getStringContent(ra)); } ra = ref.get("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("poolPreparedStatements"); if (isNotEmpty(ra)) { setPoolPreparedStatements(getBooleanContentString(ra)); } ra = ref.get("maxIdle"); if (isNotEmpty(ra)) { setMaxIdle(getIntegerStringContent(ra)); } ra = ref.get("timeBetweenEvictionRunsMillis"); if (isNotEmpty(ra)) { setTimeBetweenEvictionRunsMillis(getIntegerStringContent(ra)); } ra = ref.get("numTestsPerEvictionRun"); if (isNotEmpty(ra)) { setNumTestsPerEvictionRun(getIntegerStringContent(ra)); } ra = ref.get("minEvictableIdleTimeMillis"); if (isNotEmpty(ra)) { setMinEvictableIdleTimeMillis(getIntegerStringContent(ra)); } ra = ref.get("maxPreparedStatements"); if (isNotEmpty(ra)) { setMaxPreparedStatements(getIntegerStringContent(ra)); } ra = ref.get("accessToUnderlyingConnectionAllowed"); 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 userPassword == null ? null : userPassword.clone(); } /** * 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; PooledConnectionImpl pooledConnection = null; // Workaround for buggy WebLogic 5.1 class loader - ignore the exception upon first invocation. try { if (connectionProperties != null) { update(connectionProperties, Constants.KEY_USER, pooledUserName); update(connectionProperties, Constants.KEY_PASSWORD, pooledUserPassword); pooledConnection = new PooledConnectionImpl( DriverManager.getConnection(getUrl(), connectionProperties)); } else { pooledConnection = new PooledConnectionImpl( DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword)); } pooledConnection.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); } catch (final ClassCircularityError e) { if (connectionProperties != null) { pooledConnection = new PooledConnectionImpl( DriverManager.getConnection(getUrl(), connectionProperties)); } else { pooledConnection = new PooledConnectionImpl( DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword)); } pooledConnection.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); } KeyedObjectPool stmtPool = null; if (isPoolPreparedStatements()) { final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotalPerKey(Integer.MAX_VALUE); config.setBlockWhenExhausted(false); config.setMaxWaitMillis(0); 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.setMinEvictableIdleTime(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.setMinEvictableIdleTime(Duration.ZERO); } stmtPool = new GenericKeyedObjectPool<>(pooledConnection, config); pooledConnection.setStatementPool(stmtPool); } 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("description", getDescription())); ref.add(new StringRefAddr("driver", getDriver())); ref.add(new StringRefAddr("loginTimeout", String.valueOf(getLoginTimeout()))); ref.add(new StringRefAddr(Constants.KEY_PASSWORD, getPassword())); ref.add(new StringRefAddr(Constants.KEY_USER, getUser())); ref.add(new StringRefAddr("url", getUrl())); ref.add(new StringRefAddr("poolPreparedStatements", String.valueOf(isPoolPreparedStatements()))); ref.add(new StringRefAddr("maxIdle", String.valueOf(getMaxIdle()))); ref.add(new StringRefAddr("numTestsPerEvictionRun", String.valueOf(getNumTestsPerEvictionRun()))); ref.add(new StringRefAddr("maxPreparedStatements", String.valueOf(getMaxPreparedStatements()))); // // Pair of current and deprecated. ref.add(new StringRefAddr("durationBetweenEvictionRuns", String.valueOf(getDurationBetweenEvictionRuns()))); ref.add(new StringRefAddr("timeBetweenEvictionRunsMillis", String.valueOf(getTimeBetweenEvictionRunsMillis()))); // // Pair of current and deprecated. ref.add(new StringRefAddr("minEvictableIdleDuration", String.valueOf(getMinEvictableIdleDuration()))); ref.add(new StringRefAddr("minEvictableIdleTimeMillis", 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 url used to locate the database for this datasource. * * @return value of url. */ public String getUrl() { return url; } /** * 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 PreparedStatements * * @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 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 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) { if (connectionProperties.containsKey(Constants.KEY_USER)) { setUser(connectionProperties.getProperty(Constants.KEY_USER)); } if (connectionProperties.containsKey(Constants.KEY_PASSWORD)) { setPassword(connectionProperties.getProperty(Constants.KEY_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, * 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 PreparedStatements * * @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 #getTimeBetweenEvictionRunsMillis() * @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 datasource. * * @param url Value to assign to url. * @throws IllegalStateException if {@link #getPooledConnection()} has been called */ public void setUrl(final String url) { assertInitializationAllowed(); this.url = url; } /** * 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(", url="); // 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(url); 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.java000066400000000000000000000104561410126276600336360ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 org.apache.commons.dbcp2.PStmtKey; /** * A key uniquely identifying a {@link java.sql.PreparedStatement 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 * Statement.RETURN_GENERATED_KEYS or 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE * @param resultSetHoldability * One of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or 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.java000066400000000000000000000742031410126276600355300ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.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.pool2.KeyedObjectPool; import org.apache.commons.pool2.KeyedPooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; /** * Implementation of PooledConnection that is returned by PooledConnectionDataSource. * * @since 2.0 */ 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 the 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 Exception { 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); } } /* JDBC_4_ANT_KEY_END */ /** * Throws an SQLException, if isClosed is true */ private void assertOpen() throws SQLException { if (closed) { throw new SQLException(CLOSED); } } /** * Closes the physical connection and marks this PooledConnection so that it may not be used to * generate any more logical Connections. * * @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(normalizeSQL(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 * Statement.RETURN_GENERATED_KEYS or 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(normalizeSQL(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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * 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(normalizeSQL(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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE * @param resultSetHoldability * One of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or 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(normalizeSQL(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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * @param resultSetHoldability * One of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or 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(normalizeSQL(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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * A concurrency type; one of ResultSet.CONCUR_READ_ONLY or * 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(normalizeSQL(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(normalizeSQL(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(normalizeSQL(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(normalizeSQL(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 Exception { pooledObject.getObject().getInnermostDelegate().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. try { connection.close(); } catch (final Exception ignored) { // ignore } // 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 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 Exception { 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); } /** * Normalizes the given SQL statement, producing a canonical form that is semantically equivalent to the original. * @param sql * The SQL statement. * @return the normalized SQL statement. */ protected String normalizeSQL(final String sql) { return sql.trim(); } /** * Sends a connectionClosed event. */ void notifyListeners() { final ConnectionEvent event = new ConnectionEvent(this); final Object[] listeners = eventListeners.toArray(); for (final Object listener : listeners) { ((ConnectionEventListener) 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 Exception { @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 CallableStatement object containing the pre-compiled SQL statement. * @exception SQLException * Thrown if a database access error occurs or this method is called on a closed connection. * @since 2.4.0 */ CallableStatement prepareCall(final String sql) throws SQLException { if (pStmtPool == null) { return connection.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 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * a concurrency type; one of ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * @return a CallableStatement object containing the pre-compiled SQL statement that will produce * 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 ResultSet constants indicating type and concurrency. * @since 2.4.0 */ CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { if (pStmtPool == null) { return connection.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 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 ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or * ResultSet.CONCUR_UPDATABLE. * @param resultSetHoldability * one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT * or ResultSet.CLOSE_CURSORS_AT_COMMIT. * @return a new CallableStatement object, containing the pre-compiled SQL statement, that will * generate 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 ResultSet constants indicating type, concurrency, and holdability. * @since 2.4.0 */ CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { if (pStmtPool == null) { return connection.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. */ PreparedStatement prepareStatement(final String sql) throws SQLException { if (pStmtPool == null) { return connection.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 * Statement.RETURN_GENERATED_KEYS or 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) */ PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { if (pStmtPool == null) { return connection.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 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 ResultSet.TYPE_FORWARD_ONLY, * ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE. * @param resultSetConcurrency * a concurrency type; one of ResultSet.CONCUR_READ_ONLY or * 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) */ PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { if (pStmtPool == null) { return connection.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); } } PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { if (pStmtPool == null) { return connection.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); } } PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { if (pStmtPool == null) { return connection.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); } } PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { if (pStmtPool == null) { return connection.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); } /* JDBC_4_ANT_KEY_END */ /** * 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.java000066400000000000000000000060301410126276600337610ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 * ConnectionPoolDataSource (CPDS) implementation that can be used to * adapt older 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.9.0/src/main/java/org/apache/commons/dbcp2/datasources/000077500000000000000000000000001410126276600306755ustar00rootroot00000000000000CPDSConnectionFactory.java000066400000000000000000000413431410126276600355670ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 */ 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 int validationQueryTimeoutSeconds; private final boolean rollbackAfterValidation; private ObjectPool pool; private UserPassKey userPassKey; 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 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 */ 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.validationQueryTimeoutSeconds = 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 */ 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 Exception { 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 Exception { doDestroyObject(p.getObject()); } private void doDestroyObject(final PooledConnectionAndInfo pci) throws Exception { 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); } } // *********************************************************************** // java.sql.ConnectionEventListener implementation // *********************************************************************** @Override public synchronized PooledObject makeObject() { final PooledConnectionAndInfo pci; try { 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); pci = new PooledConnectionAndInfo(pc, userPassKey); pcMap.put(pc, pci); } catch (final SQLException e) { throw new RuntimeException(e.getMessage()); } return new DefaultPooledObject<>(pci); } @Override public void passivateObject(final PooledObject p) throws Exception { validateLifetime(p); } // *********************************************************************** // PooledConnectionManager implementation // *********************************************************************** /** * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, * passivation and validation. * * @param maxConnLifetime * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. * @since 2.9.0 */ public void setMaxConnLifetime(final Duration maxConnLifetime) { this.maxConnLifetime = maxConnLifetime; } /** * 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) { 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(", validationQueryTimeoutSeconds="); builder.append(validationQueryTimeoutSeconds); builder.append(", rollbackAfterValidation="); builder.append(rollbackAfterValidation); builder.append(", pool="); builder.append(pool); builder.append(", maxConnLifetimeMillis="); builder.append(maxConnLifetime); builder.append(", validatingSet="); builder.append(validatingSet); builder.append(", pcMap="); builder.append(pcMap); builder.append("]"); return builder.toString(); } private void validateLifetime(final PooledObject pooledObject) throws Exception { if (maxConnLifetime.compareTo(Duration.ZERO) > 0) { final long lifetimeMillis = System.currentTimeMillis() - pooledObject.getCreateTime(); if (lifetimeMillis > maxConnLifetime.toMillis()) { throw new Exception( Utils.getMessage("connectionFactory.lifetimeExceeded", lifetimeMillis, maxConnLifetime)); } } } @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) { int timeoutSeconds = validationQueryTimeoutSeconds; if (timeoutSeconds < 0) { timeoutSeconds = 0; } try { conn = pconn.getConnection(); valid = conn.isValid(timeoutSeconds); } catch (final SQLException e) { valid = false; } finally { Utils.closeQuietly(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(rset); Utils.closeQuietly(stmt); Utils.closeQuietly(conn); validatingSet.remove(pconn); } } return valid; } } CharArray.java000066400000000000000000000046051410126276600333420ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.util.Arrays; import java.util.Objects; 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 { 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 chars == null ? null : chars.clone(); } @Override public int hashCode() { return Objects.hash(Arrays.hashCode(chars)); } /** * Calls {@code super.toString()} and does not reveal its contents inadvertently. */ @Override public String toString() { return super.toString(); } } InstanceKeyDataSource.java000066400000000000000000001365411410126276600356630ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.pool2.impl.BaseObjectPoolConfig; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; /** *

* The base class for SharedPoolDataSource and 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 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 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 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 DataSource's based on this class with JDBC driver implementations that do not * supply a 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 in seconds */ private int loginTimeout; /** 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 long defaultMinEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; private int defaultMinIdle = GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY; private int defaultNumTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; private long defaultSoftMinEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; 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 long defaultTimeBetweenEvictionRunsMillis = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; // Connection factory properties private String validationQuery; private int validationQueryTimeoutSeconds = -1; private boolean rollbackAfterValidation; private Duration maxConnLifetimeMillis = 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 Exception; 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 * getPooledConnectionAndInfo is compared to the 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 PooledConnectionAndInfo instance retrieved with the old password is * destroyed and the getPooledConnectionAndInfo is repeatedly invoked until a * 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) { try { connection.close(); } catch (final Exception exc) { getLogWriter().println("ignoring exception during close: " + exc); } 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 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#getMaxWaitMillis()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} for each per user pool. * @since 2.9.0 */ public Duration getDefaultMaxWait() { return this.defaultMaxWaitDuration; } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} for each per user pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} for each per user pool. * @deprecated Use {@link #getDefaultMaxWait()}. */ @Deprecated public long getDefaultMaxWaitMillis() { return getDefaultMaxWait().toMillis(); } /** * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleTime()} for each per user * pool. * * @return The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleTime()} for each per * user pool. */ public long getDefaultMinEvictableIdleTimeMillis() { return this.defaultMinEvictableIdleTimeMillis; } /** * 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. */ public long getDefaultSoftMinEvictableIdleTimeMillis() { return this.defaultSoftMinEvictableIdleTimeMillis; } /** * 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 org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTimeBetweenEvictionRunsMillis ()} for each per user pool. * * @return The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTimeBetweenEvictionRunsMillis ()} for each per user pool. */ public long getDefaultTimeBetweenEvictionRunsMillis() { return this.defaultTimeBetweenEvictionRunsMillis; } /** * 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; } 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. */ @Override public int getLoginTimeout() { return loginTimeout; } /** * 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. */ public Duration getMaxConnLifetime() { return maxConnLifetimeMillis; } /** * 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 maxConnLifetimeMillis.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. */ public int getValidationQueryTimeout() { return validationQueryTimeoutSeconds; } /** * 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 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 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 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 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#getMaxWaitMillis()} for each per user pool. * * @param maxWaitMillis * The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} 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#getMinEvictableIdleTime()} for each per user * pool. * * @param minEvictableIdleTimeMillis * The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleTime()} for each * per user pool. */ public void setDefaultMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { assertInitializationAllowed(); this.defaultMinEvictableIdleTimeMillis = 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 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 softMinEvictableIdleTimeMillis * The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. */ public void setDefaultSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { assertInitializationAllowed(); this.defaultSoftMinEvictableIdleTimeMillis = 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 org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTimeBetweenEvictionRunsMillis ()} for each per user pool. * * @param timeBetweenEvictionRunsMillis * The default value for {@link org.apache.commons.pool2.impl.GenericObjectPool * GenericObjectPool#getTimeBetweenEvictionRunsMillis ()} for each per user pool. */ public void setDefaultTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { assertInitializationAllowed(); this.defaultTimeBetweenEvictionRunsMillis = 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. */ @Override public void setLoginTimeout(final int loginTimeout) { this.loginTimeout = 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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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.maxConnLifetimeMillis = 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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, 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 in seconds before the validation query fails. * * @param validationQueryTimeoutSeconds * The new timeout in seconds */ public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { this.validationQueryTimeoutSeconds = 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 e) { // 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(", loginTimeout="); builder.append(loginTimeout); 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(", defaultMaxWait="); builder.append(defaultMaxWaitDuration); builder.append(", defaultMinEvictableIdleTimeMillis="); builder.append(defaultMinEvictableIdleTimeMillis); builder.append(", defaultMinIdle="); builder.append(defaultMinIdle); builder.append(", defaultNumTestsPerEvictionRun="); builder.append(defaultNumTestsPerEvictionRun); builder.append(", defaultSoftMinEvictableIdleTimeMillis="); builder.append(defaultSoftMinEvictableIdleTimeMillis); 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(", defaultTimeBetweenEvictionRunsMillis="); builder.append(defaultTimeBetweenEvictionRunsMillis); builder.append(", validationQuery="); builder.append(validationQuery); builder.append(", validationQueryTimeoutSeconds="); builder.append(validationQueryTimeoutSeconds); builder.append(", rollbackAfterValidation="); builder.append(rollbackAfterValidation); builder.append(", maxConnLifetimeMillis="); builder.append(maxConnLifetimeMillis); 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); } /* JDBC_4_ANT_KEY_END */ } InstanceKeyDataSourceFactory.java000066400000000000000000000321261410126276600372050ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Map.Entry; 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 SharedPoolDataSources or PerUserPoolDataSources * * @since 2.0 */ abstract class InstanceKeyDataSourceFactory implements ObjectFactory { private static final Map INSTANCE_MAP = new ConcurrentHashMap<>(); /** * Closes all pools associated with this class. * * @throws Exception * a {@link ListException} containing all exceptions thrown by {@link InstanceKeyDataSource#close()} * @see InstanceKeyDataSource#close() * @see ListException * @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 Exception { // Get iterator to loop over all instances of this data source. final List exceptionList = new ArrayList<>(INSTANCE_MAP.size()); for (final Entry next : INSTANCE_MAP.entrySet()) { // Bullet-proof to avoid anything else but problems from InstanceKeyDataSource#close(). if (next != null) { @SuppressWarnings("resource") final InstanceKeyDataSource value = next.getValue(); if (value != null) { try { value.close(); } catch (final Exception e) { exceptionList.add(e); } } } } 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 e) { // 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); } } /** * 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 (refAddr != null && refAddr.getContent() != null) { // 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; } /** * @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); private void setCommonProperties(final Reference ref, final InstanceKeyDataSource ikds) throws IOException, ClassNotFoundException { RefAddr refAddr = ref.get("dataSourceName"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDataSourceName(refAddr.getContent().toString()); } refAddr = ref.get("description"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDescription(refAddr.getContent().toString()); } refAddr = ref.get("jndiEnvironment"); if (refAddr != null && refAddr.getContent() != null) { final byte[] serialized = (byte[]) refAddr.getContent(); ikds.setJndiEnvironment((Properties) deserialize(serialized)); } refAddr = ref.get("loginTimeout"); if (refAddr != null && refAddr.getContent() != null) { ikds.setLoginTimeout(Integer.parseInt(refAddr.getContent().toString())); } // Pool properties refAddr = ref.get("blockWhenExhausted"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultBlockWhenExhausted(Boolean.parseBoolean(refAddr.getContent().toString())); } refAddr = ref.get("evictionPolicyClassName"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultEvictionPolicyClassName(refAddr.getContent().toString()); } // Pool properties refAddr = ref.get("lifo"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultLifo(Boolean.parseBoolean(refAddr.getContent().toString())); } refAddr = ref.get("maxIdlePerKey"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultMaxIdle(Integer.parseInt(refAddr.getContent().toString())); } refAddr = ref.get("maxTotalPerKey"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultMaxTotal(Integer.parseInt(refAddr.getContent().toString())); } refAddr = ref.get("maxWaitMillis"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultMaxWaitMillis(Long.parseLong(refAddr.getContent().toString())); } refAddr = ref.get("minEvictableIdleTimeMillis"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultMinEvictableIdleTimeMillis(Long.parseLong(refAddr.getContent().toString())); } refAddr = ref.get("minIdlePerKey"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultMinIdle(Integer.parseInt(refAddr.getContent().toString())); } refAddr = ref.get("numTestsPerEvictionRun"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultNumTestsPerEvictionRun(Integer.parseInt(refAddr.getContent().toString())); } refAddr = ref.get("softMinEvictableIdleTimeMillis"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultSoftMinEvictableIdleTimeMillis(Long.parseLong(refAddr.getContent().toString())); } refAddr = ref.get("testOnCreate"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTestOnCreate(Boolean.parseBoolean(refAddr.getContent().toString())); } refAddr = ref.get("testOnBorrow"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTestOnBorrow(Boolean.parseBoolean(refAddr.getContent().toString())); } refAddr = ref.get("testOnReturn"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTestOnReturn(Boolean.parseBoolean(refAddr.getContent().toString())); } refAddr = ref.get("testWhileIdle"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTestWhileIdle(Boolean.parseBoolean(refAddr.getContent().toString())); } refAddr = ref.get("timeBetweenEvictionRunsMillis"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTimeBetweenEvictionRunsMillis(Long.parseLong(refAddr.getContent().toString())); } // Connection factory properties refAddr = ref.get("validationQuery"); if (refAddr != null && refAddr.getContent() != null) { ikds.setValidationQuery(refAddr.getContent().toString()); } refAddr = ref.get("validationQueryTimeout"); if (refAddr != null && refAddr.getContent() != null) { ikds.setValidationQueryTimeout(Integer.parseInt(refAddr.getContent().toString())); } refAddr = ref.get("rollbackAfterValidation"); if (refAddr != null && refAddr.getContent() != null) { ikds.setRollbackAfterValidation(Boolean.parseBoolean(refAddr.getContent().toString())); } refAddr = ref.get("maxConnLifetimeMillis"); if (refAddr != null && refAddr.getContent() != null) { ikds.setMaxConnLifetimeMillis(Long.parseLong(refAddr.getContent().toString())); } // Connection properties refAddr = ref.get("defaultAutoCommit"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultAutoCommit(Boolean.valueOf(refAddr.getContent().toString())); } refAddr = ref.get("defaultTransactionIsolation"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultTransactionIsolation(Integer.parseInt(refAddr.getContent().toString())); } refAddr = ref.get("defaultReadOnly"); if (refAddr != null && refAddr.getContent() != null) { ikds.setDefaultReadOnly(Boolean.valueOf(refAddr.getContent().toString())); } } } KeyedCPDSConnectionFactory.java000066400000000000000000000347251410126276600365570ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 org.apache.commons.dbcp2.PoolableConnection * PoolableConnection}s. * * @since 2.0 */ 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 int validationQueryTimeoutSeconds; 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<>(); /** * Create 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. */ public KeyedCPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation) { this.cpds = cpds; this.validationQuery = validationQuery; this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds; this.rollbackAfterValidation = rollbackAfterValidation; } @Override public void activateObject(final UserPassKey key, final PooledObject p) throws Exception { 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 Exception { 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); } } // *********************************************************************** // java.sql.ConnectionEventListener implementation // *********************************************************************** /** * 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(java.lang.Object) */ @Override public synchronized PooledObject makeObject(final UserPassKey userPassKey) throws Exception { 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 Exception { validateLifetime(p); } // *********************************************************************** // PooledConnectionManager implementation // *********************************************************************** /** * 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 */ 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) { setMaxConnLifetime(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 p) throws Exception { if (maxConnLifetime.compareTo(Duration.ZERO) > 0) { final long lifetimeMillis = System.currentTimeMillis() - p.getCreateTime(); if (lifetimeMillis > maxConnLifetime.toMillis()) { throw new Exception( Utils.getMessage("connectionFactory.lifetimeExceeded", lifetimeMillis, 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 pconn = pooledObject.getObject().getPooledConnection(); Connection conn = null; validatingSet.add(pconn); if (null == validationQuery) { int timeoutSeconds = validationQueryTimeoutSeconds; if (timeoutSeconds < 0) { timeoutSeconds = 0; } try { conn = pconn.getConnection(); valid = conn.isValid(timeoutSeconds); } catch (final SQLException e) { valid = false; } finally { Utils.closeQuietly(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(rset); Utils.closeQuietly(stmt); Utils.closeQuietly(conn); validatingSet.remove(pconn); } } return valid; } } PerUserPoolDataSource.java000066400000000000000000001231001410126276600356500ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; 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.GenericObjectPool; /** *

* A pooling 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 * getConnection(userName, password) request is processed with a password that is different from those used * to create connections in the pool associated with 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); // Per user pool properties private Map perUserBlockWhenExhausted; private Map perUserEvictionPolicyClassName; private Map perUserLifo; private Map perUserMaxIdle; private Map perUserMaxTotal; private Map perUserMaxWaitMillis; private Map perUserMinEvictableIdleTimeMillis; private Map perUserMinIdle; private Map perUserNumTestsPerEvictionRun; private Map perUserSoftMinEvictableIdleTimeMillis; private Map perUserTestOnCreate; private Map perUserTestOnBorrow; private Map perUserTestOnReturn; private Map perUserTestWhileIdle; private Map perUserTimeBetweenEvictionRunsMillis; // Per user connection properties private Map perUserDefaultAutoCommit; private Map perUserDefaultTransactionIsolation; private Map perUserDefaultReadOnly; /** * Map to keep track of Pools for a given user. */ private transient Map managers = new HashMap<>(); /** * Default no-arg constructor for Serialization. */ public PerUserPoolDataSource() { } /** * Clears pool(s) maintained by this data source. * * @see org.apache.commons.pool2.ObjectPool#clear() * @since 2.3.0 */ public void clear() { for (final PooledConnectionManager manager : managers.values()) { try { getCPDSConnectionFactoryPool(manager).clear(); } catch (final Exception closePoolException) { // ignore and try to close others. } } InstanceKeyDataSourceFactory.removeInstance(getInstanceKey()); } /** * Closes pool(s) maintained by this data source. * * @see org.apache.commons.pool2.ObjectPool#close() */ @SuppressWarnings("resource") @Override public void close() { for (final PooledConnectionManager manager : managers.values()) { Utils.closeQuietly(getCPDSConnectionFactoryPool(manager)); } InstanceKeyDataSourceFactory.removeInstance(getInstanceKey()); } private HashMap createMap() { // Should there be a default size different than what this ctor provides? return new HashMap<>(); } @Override protected PooledConnectionManager getConnectionManager(final UserPassKey upKey) { return managers.get(getPoolKey(upKey.getUserName())); } 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) { Boolean value = null; if (perUserBlockWhenExhausted != null) { value = perUserBlockWhenExhausted.get(userName); } if (value == null) { return getDefaultBlockWhenExhausted(); } return value; } /** * 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) { Boolean value = null; if (perUserDefaultAutoCommit != null) { value = perUserDefaultAutoCommit.get(userName); } return value; } /** * 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) { Boolean value = null; if (perUserDefaultReadOnly != null) { value = perUserDefaultReadOnly.get(userName); } return value; } /** * 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) { Integer value = null; if (perUserDefaultTransactionIsolation != null) { value = perUserDefaultTransactionIsolation.get(userName); } return value; } /** * 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. * * @param userName * The user name key. * @return The user specific value. */ public String getPerUserEvictionPolicyClassName(final String userName) { String value = null; if (perUserEvictionPolicyClassName != null) { value = perUserEvictionPolicyClassName.get(userName); } if (value == null) { return getDefaultEvictionPolicyClassName(); } return value; } /** * 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) { Boolean value = null; if (perUserLifo != null) { value = perUserLifo.get(userName); } if (value == null) { return getDefaultLifo(); } return value; } /** * 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) { Integer value = null; if (perUserMaxIdle != null) { value = perUserMaxIdle.get(userName); } if (value == null) { return getDefaultMaxIdle(); } return value; } /** * 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) { Integer value = null; if (perUserMaxTotal != null) { value = perUserMaxTotal.get(userName); } if (value == null) { return getDefaultMaxTotal(); } return value; } /** * Gets the user specific value for {@link GenericObjectPool#getMaxWaitMillis()} 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 long getPerUserMaxWaitMillis(final String userName) { Long value = null; if (perUserMaxWaitMillis != null) { value = perUserMaxWaitMillis.get(userName); } if (value == null) { return getDefaultMaxWaitMillis(); } return value; } /** * Gets the user specific value for {@link GenericObjectPool#getMinEvictableIdleTime()} 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 long getPerUserMinEvictableIdleTimeMillis(final String userName) { Long value = null; if (perUserMinEvictableIdleTimeMillis != null) { value = perUserMinEvictableIdleTimeMillis.get(userName); } if (value == null) { return getDefaultMinEvictableIdleTimeMillis(); } return value; } /** * 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) { Integer value = null; if (perUserMinIdle != null) { value = perUserMinIdle.get(userName); } if (value == null) { return getDefaultMinIdle(); } return value; } /** * 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) { Integer value = null; if (perUserNumTestsPerEvictionRun != null) { value = perUserNumTestsPerEvictionRun.get(userName); } if (value == null) { return getDefaultNumTestsPerEvictionRun(); } return value; } /** * Gets the user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleTime()} 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 long getPerUserSoftMinEvictableIdleTimeMillis(final String userName) { Long value = null; if (perUserSoftMinEvictableIdleTimeMillis != null) { value = perUserSoftMinEvictableIdleTimeMillis.get(userName); } if (value == null) { return getDefaultSoftMinEvictableIdleTimeMillis(); } return value; } /** * 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) { Boolean value = null; if (perUserTestOnBorrow != null) { value = perUserTestOnBorrow.get(userName); } if (value == null) { return getDefaultTestOnBorrow(); } return value; } /** * 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) { Boolean value = null; if (perUserTestOnCreate != null) { value = perUserTestOnCreate.get(userName); } if (value == null) { return getDefaultTestOnCreate(); } return value; } /** * 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) { Boolean value = null; if (perUserTestOnReturn != null) { value = perUserTestOnReturn.get(userName); } if (value == null) { return getDefaultTestOnReturn(); } return value; } /** * 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) { Boolean value = null; if (perUserTestWhileIdle != null) { value = perUserTestWhileIdle.get(userName); } if (value == null) { return getDefaultTestWhileIdle(); } return value; } /** * Gets the user specific value for {@link GenericObjectPool#getTimeBetweenEvictionRuns()} 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 long getPerUserTimeBetweenEvictionRunsMillis(final String userName) { Long value = null; if (perUserTimeBetweenEvictionRunsMillis != null) { value = perUserTimeBetweenEvictionRunsMillis.get(userName); } if (value == null) { return getDefaultTimeBetweenEvictionRunsMillis(); } return value; } /** * 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(); } @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 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; } /** * Supports Serialization interface. * * @param in * a java.io.ObjectInputStream value * @throws IOException * if an error occurs * @throws ClassNotFoundException * if an error occurs */ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { try { in.defaultReadObject(); final PerUserPoolDataSource oldDS = (PerUserPoolDataSource) new PerUserPoolDataSourceFactory() .getObjectInstance(getReference(), null, null, null); this.managers = oldDS.managers; } 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(), getValidationQueryTimeout(), isRollbackAfterValidation(), userName, password); factory.setMaxConnLifetime(getMaxConnLifetime()); // Create an object pool to contain our PooledConnections 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.setMaxWaitMillis(getPerUserMaxWaitMillis(userName)); pool.setMinEvictableIdleTimeMillis(getPerUserMinEvictableIdleTimeMillis(userName)); pool.setMinIdle(getPerUserMinIdle(userName)); pool.setNumTestsPerEvictionRun(getPerUserNumTestsPerEvictionRun(userName)); pool.setSoftMinEvictableIdleTimeMillis(getPerUserSoftMinEvictableIdleTimeMillis(userName)); pool.setTestOnCreate(getPerUserTestOnCreate(userName)); pool.setTestOnBorrow(getPerUserTestOnBorrow(userName)); pool.setTestOnReturn(getPerUserTestOnReturn(userName)); pool.setTestWhileIdle(getPerUserTestWhileIdle(userName)); pool.setTimeBetweenEvictionRunsMillis(getPerUserTimeBetweenEvictionRunsMillis(userName)); pool.setSwallowedExceptionListener(new SwallowedExceptionLogger(log)); final Object old = managers.put(getPoolKey(userName), factory); if (old != null) { throw new IllegalStateException("Pool already contains an entry for this user/password: " + userName); } } void setPerUserBlockWhenExhausted(final Map userDefaultBlockWhenExhausted) { assertInitializationAllowed(); if (perUserBlockWhenExhausted == null) { perUserBlockWhenExhausted = createMap(); } else { perUserBlockWhenExhausted.clear(); } perUserBlockWhenExhausted.putAll(userDefaultBlockWhenExhausted); } /** * 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(); if (perUserBlockWhenExhausted == null) { perUserBlockWhenExhausted = createMap(); } perUserBlockWhenExhausted.put(userName, value); } void setPerUserDefaultAutoCommit(final Map userDefaultAutoCommit) { assertInitializationAllowed(); if (perUserDefaultAutoCommit == null) { perUserDefaultAutoCommit = createMap(); } else { perUserDefaultAutoCommit.clear(); } perUserDefaultAutoCommit.putAll(userDefaultAutoCommit); } /** * 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(); if (perUserDefaultAutoCommit == null) { perUserDefaultAutoCommit = createMap(); } perUserDefaultAutoCommit.put(userName, value); } void setPerUserDefaultReadOnly(final Map userDefaultReadOnly) { assertInitializationAllowed(); if (perUserDefaultReadOnly == null) { perUserDefaultReadOnly = createMap(); } else { perUserDefaultReadOnly.clear(); } perUserDefaultReadOnly.putAll(userDefaultReadOnly); } /** * 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(); if (perUserDefaultReadOnly == null) { perUserDefaultReadOnly = createMap(); } perUserDefaultReadOnly.put(userName, value); } void setPerUserDefaultTransactionIsolation(final Map userDefaultTransactionIsolation) { assertInitializationAllowed(); if (perUserDefaultTransactionIsolation == null) { perUserDefaultTransactionIsolation = new HashMap<>(); } else { perUserDefaultTransactionIsolation.clear(); } perUserDefaultTransactionIsolation.putAll(userDefaultTransactionIsolation); } /** * 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(); if (perUserDefaultTransactionIsolation == null) { perUserDefaultTransactionIsolation = new HashMap<>(); } perUserDefaultTransactionIsolation.put(userName, value); } void setPerUserEvictionPolicyClassName(final Map userDefaultEvictionPolicyClassName) { assertInitializationAllowed(); if (perUserEvictionPolicyClassName == null) { perUserEvictionPolicyClassName = new HashMap<>(); } else { perUserEvictionPolicyClassName.clear(); } perUserEvictionPolicyClassName.putAll(userDefaultEvictionPolicyClassName); } /** * Sets a user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's * pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserEvictionPolicyClassName(final String userName, final String value) { assertInitializationAllowed(); if (perUserEvictionPolicyClassName == null) { perUserEvictionPolicyClassName = new HashMap<>(); } perUserEvictionPolicyClassName.put(userName, value); } void setPerUserLifo(final Map userDefaultLifo) { assertInitializationAllowed(); if (perUserLifo == null) { perUserLifo = createMap(); } else { perUserLifo.clear(); } perUserLifo.putAll(userDefaultLifo); } /** * 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(); if (perUserLifo == null) { perUserLifo = createMap(); } perUserLifo.put(userName, value); } void setPerUserMaxIdle(final Map userDefaultMaxIdle) { assertInitializationAllowed(); if (perUserMaxIdle == null) { perUserMaxIdle = new HashMap<>(); } else { perUserMaxIdle.clear(); } perUserMaxIdle.putAll(userDefaultMaxIdle); } /** * 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(); if (perUserMaxIdle == null) { perUserMaxIdle = new HashMap<>(); } perUserMaxIdle.put(userName, value); } void setPerUserMaxTotal(final Map userDefaultMaxTotal) { assertInitializationAllowed(); if (perUserMaxTotal == null) { perUserMaxTotal = new HashMap<>(); } else { perUserMaxTotal.clear(); } perUserMaxTotal.putAll(userDefaultMaxTotal); } /** * 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(); if (perUserMaxTotal == null) { perUserMaxTotal = new HashMap<>(); } perUserMaxTotal.put(userName, value); } void setPerUserMaxWaitMillis(final Map userDefaultMaxWaitMillis) { assertInitializationAllowed(); if (perUserMaxWaitMillis == null) { perUserMaxWaitMillis = new HashMap<>(); } else { perUserMaxWaitMillis.clear(); } perUserMaxWaitMillis.putAll(userDefaultMaxWaitMillis); } /** * Sets a user specific value for {@link GenericObjectPool#getMaxWaitMillis()} for the specified user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserMaxWaitMillis(final String userName, final Long value) { assertInitializationAllowed(); if (perUserMaxWaitMillis == null) { perUserMaxWaitMillis = new HashMap<>(); } perUserMaxWaitMillis.put(userName, value); } void setPerUserMinEvictableIdleTimeMillis(final Map userDefaultMinEvictableIdleTimeMillis) { assertInitializationAllowed(); if (perUserMinEvictableIdleTimeMillis == null) { perUserMinEvictableIdleTimeMillis = new HashMap<>(); } else { perUserMinEvictableIdleTimeMillis.clear(); } perUserMinEvictableIdleTimeMillis.putAll(userDefaultMinEvictableIdleTimeMillis); } /** * Sets a user specific value for {@link GenericObjectPool#getMinEvictableIdleTime()} for the specified user's * pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserMinEvictableIdleTimeMillis(final String userName, final Long value) { assertInitializationAllowed(); if (perUserMinEvictableIdleTimeMillis == null) { perUserMinEvictableIdleTimeMillis = new HashMap<>(); } perUserMinEvictableIdleTimeMillis.put(userName, value); } void setPerUserMinIdle(final Map userDefaultMinIdle) { assertInitializationAllowed(); if (perUserMinIdle == null) { perUserMinIdle = new HashMap<>(); } else { perUserMinIdle.clear(); } perUserMinIdle.putAll(userDefaultMinIdle); } /** * 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(); if (perUserMinIdle == null) { perUserMinIdle = new HashMap<>(); } perUserMinIdle.put(userName, value); } void setPerUserNumTestsPerEvictionRun(final Map userDefaultNumTestsPerEvictionRun) { assertInitializationAllowed(); if (perUserNumTestsPerEvictionRun == null) { perUserNumTestsPerEvictionRun = new HashMap<>(); } else { perUserNumTestsPerEvictionRun.clear(); } perUserNumTestsPerEvictionRun.putAll(userDefaultNumTestsPerEvictionRun); } /** * 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(); if (perUserNumTestsPerEvictionRun == null) { perUserNumTestsPerEvictionRun = new HashMap<>(); } perUserNumTestsPerEvictionRun.put(userName, value); } void setPerUserSoftMinEvictableIdleTimeMillis(final Map userDefaultSoftMinEvictableIdleTimeMillis) { assertInitializationAllowed(); if (perUserSoftMinEvictableIdleTimeMillis == null) { perUserSoftMinEvictableIdleTimeMillis = new HashMap<>(); } else { perUserSoftMinEvictableIdleTimeMillis.clear(); } perUserSoftMinEvictableIdleTimeMillis.putAll(userDefaultSoftMinEvictableIdleTimeMillis); } /** * Sets a user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleTime()} for the specified * user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserSoftMinEvictableIdleTimeMillis(final String userName, final Long value) { assertInitializationAllowed(); if (perUserSoftMinEvictableIdleTimeMillis == null) { perUserSoftMinEvictableIdleTimeMillis = new HashMap<>(); } perUserSoftMinEvictableIdleTimeMillis.put(userName, value); } void setPerUserTestOnBorrow(final Map userDefaultTestOnBorrow) { assertInitializationAllowed(); if (perUserTestOnBorrow == null) { perUserTestOnBorrow = createMap(); } else { perUserTestOnBorrow.clear(); } perUserTestOnBorrow.putAll(userDefaultTestOnBorrow); } /** * 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(); if (perUserTestOnBorrow == null) { perUserTestOnBorrow = createMap(); } perUserTestOnBorrow.put(userName, value); } void setPerUserTestOnCreate(final Map userDefaultTestOnCreate) { assertInitializationAllowed(); if (perUserTestOnCreate == null) { perUserTestOnCreate = createMap(); } else { perUserTestOnCreate.clear(); } perUserTestOnCreate.putAll(userDefaultTestOnCreate); } /** * 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(); if (perUserTestOnCreate == null) { perUserTestOnCreate = createMap(); } perUserTestOnCreate.put(userName, value); } void setPerUserTestOnReturn(final Map userDefaultTestOnReturn) { assertInitializationAllowed(); if (perUserTestOnReturn == null) { perUserTestOnReturn = createMap(); } else { perUserTestOnReturn.clear(); } perUserTestOnReturn.putAll(userDefaultTestOnReturn); } /** * 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(); if (perUserTestOnReturn == null) { perUserTestOnReturn = createMap(); } perUserTestOnReturn.put(userName, value); } void setPerUserTestWhileIdle(final Map userDefaultTestWhileIdle) { assertInitializationAllowed(); if (perUserTestWhileIdle == null) { perUserTestWhileIdle = createMap(); } else { perUserTestWhileIdle.clear(); } perUserTestWhileIdle.putAll(userDefaultTestWhileIdle); } /** * 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(); if (perUserTestWhileIdle == null) { perUserTestWhileIdle = createMap(); } perUserTestWhileIdle.put(userName, value); } void setPerUserTimeBetweenEvictionRunsMillis(final Map userDefaultTimeBetweenEvictionRunsMillis) { assertInitializationAllowed(); if (perUserTimeBetweenEvictionRunsMillis == null) { perUserTimeBetweenEvictionRunsMillis = new HashMap<>(); } else { perUserTimeBetweenEvictionRunsMillis.clear(); } perUserTimeBetweenEvictionRunsMillis.putAll(userDefaultTimeBetweenEvictionRunsMillis); } /** * Sets a user specific value for {@link GenericObjectPool#getTimeBetweenEvictionRuns()} for the specified * user's pool. * * @param userName * The user name key. * @param value * The user specific value. */ public void setPerUserTimeBetweenEvictionRunsMillis(final String userName, final Long value) { assertInitializationAllowed(); if (perUserTimeBetweenEvictionRunsMillis == null) { perUserTimeBetweenEvictionRunsMillis = new HashMap<>(); } perUserTimeBetweenEvictionRunsMillis.put(userName, 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); } } } PerUserPoolDataSourceFactory.java000066400000000000000000000074431410126276600372130ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.util.Map; import javax.naming.RefAddr; import javax.naming.Reference; /** * A JNDI ObjectFactory which creates SharedPoolDataSources * * @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 ra = ref.get("defaultMaxTotal"); if (ra != null && ra.getContent() != null) { pupds.setDefaultMaxTotal(Integer.parseInt(ra.getContent().toString())); } ra = ref.get("defaultMaxIdle"); if (ra != null && ra.getContent() != null) { pupds.setDefaultMaxIdle(Integer.parseInt(ra.getContent().toString())); } ra = ref.get("defaultMaxWaitMillis"); if (ra != null && ra.getContent() != null) { pupds.setDefaultMaxWaitMillis(Integer.parseInt(ra.getContent().toString())); } ra = ref.get("perUserDefaultAutoCommit"); if (ra != null && ra.getContent() != null) { final byte[] serialized = (byte[]) ra.getContent(); pupds.setPerUserDefaultAutoCommit((Map) deserialize(serialized)); } ra = ref.get("perUserDefaultTransactionIsolation"); if (ra != null && ra.getContent() != null) { final byte[] serialized = (byte[]) ra.getContent(); pupds.setPerUserDefaultTransactionIsolation((Map) deserialize(serialized)); } ra = ref.get("perUserMaxTotal"); if (ra != null && ra.getContent() != null) { final byte[] serialized = (byte[]) ra.getContent(); pupds.setPerUserMaxTotal((Map) deserialize(serialized)); } ra = ref.get("perUserMaxIdle"); if (ra != null && ra.getContent() != null) { final byte[] serialized = (byte[]) ra.getContent(); pupds.setPerUserMaxIdle((Map) deserialize(serialized)); } ra = ref.get("perUserMaxWaitMillis"); if (ra != null && ra.getContent() != null) { final byte[] serialized = (byte[]) ra.getContent(); pupds.setPerUserMaxWaitMillis((Map) deserialize(serialized)); } ra = ref.get("perUserDefaultReadOnly"); if (ra != null && ra.getContent() != null) { final byte[] serialized = (byte[]) ra.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.9.0/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java000066400000000000000000000040431410126276600331230ustar00rootroot00000000000000/* * 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; /** * @since 2.0 */ 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.java000066400000000000000000000043121410126276600361620ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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; /** * Constructs a new instance. * * @since 2.4.0 */ PooledConnectionAndInfo(final PooledConnection pooledConnection, final char[] userName, final char[] userPassword) { this(pooledConnection, new UserPassKey(userName, userPassword)); } PooledConnectionAndInfo(final PooledConnection pooledConnection, final UserPassKey userPassKey) { this.pooledConnection = pooledConnection; this.userPassKey = userPassKey; } /** * 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.java000066400000000000000000000042221410126276600362160ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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; // /** // * Sets the database password used when creating connections. // * // * @param password password used when authenticating to the database // * @since 3.0.0 // */ // void setPassword(char[] password); /** * 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 */ void setPassword(String password); } SharedPoolDataSource.java000066400000000000000000000212711410126276600354770ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; /** *

* A pooling 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 * getConnection(user name, password) request is processed with a password that is different from those * used to create connections in the pool associated with 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; // Pool properties private int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; private transient KeyedObjectPool pool; 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 Exception { 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; } // ---------------------------------------------------------------------- // Instrumentation Methods /** * 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; } /** * Supports Serialization interface. * * @param in * a java.io.ObjectInputStream value * @throws IOException * if an error occurs * @throws ClassNotFoundException * if an error occurs */ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { try { in.defaultReadObject(); final SharedPoolDataSource oldDS = (SharedPoolDataSource) new SharedPoolDataSourceFactory() .getObjectInstance(getReference(), null, null, null); this.pool = oldDS.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(), getValidationQueryTimeout(), isRollbackAfterValidation()); factory.setMaxConnLifetime(getMaxConnLifetime()); final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setBlockWhenExhausted(getDefaultBlockWhenExhausted()); config.setEvictionPolicyClassName(getDefaultEvictionPolicyClassName()); config.setLifo(getDefaultLifo()); config.setMaxIdlePerKey(getDefaultMaxIdle()); config.setMaxTotal(getMaxTotal()); config.setMaxTotalPerKey(getDefaultMaxTotal()); config.setMaxWaitMillis(getDefaultMaxWait().toMillis()); config.setMinEvictableIdleTimeMillis(getDefaultMinEvictableIdleTimeMillis()); config.setMinIdlePerKey(getDefaultMinIdle()); config.setNumTestsPerEvictionRun(getDefaultNumTestsPerEvictionRun()); config.setSoftMinEvictableIdleTimeMillis(getDefaultSoftMinEvictableIdleTimeMillis()); config.setTestOnCreate(getDefaultTestOnCreate()); config.setTestOnBorrow(getDefaultTestOnBorrow()); config.setTestOnReturn(getDefaultTestOnReturn()); config.setTestWhileIdle(getDefaultTestWhileIdle()); config.setTimeBetweenEvictionRunsMillis(getDefaultTimeBetweenEvictionRunsMillis()); 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.java000066400000000000000000000032431410126276600370260ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 SharedPoolDataSources * * @since 2.0 */ public class SharedPoolDataSourceFactory extends InstanceKeyDataSourceFactory { private static final String SHARED_POOL_CLASSNAME = SharedPoolDataSource.class.getName(); @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.java000066400000000000000000000067011410126276600337030ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 */ class UserPassKey implements Serializable { private static final long serialVersionUID = 5142970911626584817L; private final CharArray name; private final CharArray password; UserPassKey(final char[] userName, final char[] password) { this(new CharArray(userName), new CharArray(password)); } UserPassKey(final CharArray userName, final CharArray userPassword) { this.name = userName; this.password = userPassword; } 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.java000066400000000000000000000132361410126276600340120ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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: PerUserPoolDataSource and * 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 * ConnectionPoolDataSource that is deployed as given in the * cpdsadapter example *

* *

* The 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 DataSource could be maintained, for * multiple getConnection() requests. Or the DataSource can be * looked up in different parts of the application code. * PerUserPoolDataSourceFactory and * 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 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.9.0/src/main/java/org/apache/commons/dbcp2/managed/000077500000000000000000000000001410126276600277545ustar00rootroot00000000000000BasicManagedDataSource.java000066400000000000000000000253201410126276600350130ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 t) { final String message = "Cannot load XA data source class '" + xaDataSource + "'"; throw new SQLException(message, t); } try { xaDataSourceInstance = (XADataSource) xaDataSourceClass.getConstructor().newInstance(); } catch (final Exception t) { final String message = "Cannot create XA data source of class '" + xaDataSource + "'"; throw new SQLException(message, t); } } // 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(getValidationQueryTimeout()); 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.setMaxConnLifetimeMillis(getMaxConnLifetimeMillis()); connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn()); connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeout()); connectionFactory.setFastFailValidation(getFastFailValidation()); connectionFactory.setDisconnectionSqlCodes(getDisconnectionSqlCodes()); 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: getConnection, setLogwriter, * setLoginTimeout, getLoginTimeout, getLogWriter. *

* * @param xaDataSourceInstance * XADataSource instance */ public synchronized void setXaDataSourceInstance(final XADataSource xaDataSourceInstance) { this.xaDataSourceInstance = xaDataSourceInstance; xaDataSource = xaDataSourceInstance == null ? null : xaDataSourceInstance.getClass().getName(); } } DataSourceXAConnectionFactory.java000066400000000000000000000243371410126276600364040ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 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 is null"); Objects.requireNonNull(xaDataSource, "xaDataSource is null"); // 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 = userPassword == null ? null : userPassword.clone(); } /** * 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 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); } }); 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 userPassword == null ? null : userPassword.clone(); } /** * 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 = userPassword == null ? null : userPassword.clone(); } /** * 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.java000066400000000000000000000355751410126276600354120ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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") /** * Construct a new instance for a given connection. * * @param localTransaction A connection. */ public LocalXAResource(final Connection localTransaction) { this.connection = localTransaction; } /** * 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 is null"); if (this.currentXid == null) { throw new XAException("There is no current transaction"); } if (!this.currentXid.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 e) { // ignore } 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 is null"); if (!this.currentXid.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 XAResource.XA_RDONLY; } } catch (final SQLException ignored) { // no big deal } // this is a local (one phase) only connection, so we can't prepare return XAResource.XA_OK; } /** * Always returns a zero length Xid array. The LocalXAConnectionFactory can not 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 is null"); if (!this.currentXid.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 e) { // Ignore. } 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 the 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 == XAResource.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 == XAResource.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 is null"); Objects.requireNonNull(connectionFactory, "connectionFactory is null"); 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; } /** * @return The connection factory. * @since 2.6.0 */ public ConnectionFactory getConnectionFactory() { return connectionFactory; } @Override public TransactionRegistry getTransactionRegistry() { return transactionRegistry; } } ManagedConnection.java000066400000000000000000000312521410126276600341170ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 can not 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; } /** * @return The transaction context. * @since 2.6.0 */ public TransactionContext getTransactionContext() { return transactionContext; } /** * @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; } // // Methods for accessing the delegate connection // @Override public void rollback() throws SQLException { if (transactionContext != null) { throw new SQLException("Commit can not 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 can not 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 can not 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 a 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 can not 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 ignored) { // whatever... try to invalidate the connection try { pool.invalidateObject(connection); } catch (final Exception ignore) { // 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 e1) { // we are try but no luck } throw e; } } } // autoCommit may have been changed directly on the underlying // connection clearCachedState(); } } ManagedDataSource.java000066400000000000000000000071771410126276600340630ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 is null"); this.transactionRegistry = transactionRegistry; } } PoolableManagedConnection.java000066400000000000000000000061531410126276600355770ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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; /** * Create 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); } /** * Create 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) { super(conn, pool, null, disconnectSqlCodes, fastFailValidation); this.transactionRegistry = transactionRegistry; } /** * @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.java000066400000000000000000000114661410126276600371320ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 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(); } /** * @return The transaction registry. * @since 2.6.0 */ public TransactionRegistry getTransactionRegistry() { return transactionRegistry; } /** * Uses the configured XAConnectionFactory to create a {@link PoolableManagedConnection}. Throws * 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. */ @Override public synchronized PooledObject makeObject() throws Exception { 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.setMaxWaitMillis(0); 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(), isFastFailValidation()); pmc.setCacheState(getCacheState()); return new DefaultPooledObject<>(pmc); } } TransactionContext.java000066400000000000000000000212651410126276600344000ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 is null"); Objects.requireNonNull(transaction, "transaction is null"); 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(TransactionContext.this, transaction != null && transaction.getStatus() == Status.STATUS_COMMITTED); return; } final Synchronization s = new Synchronization() { @Override public void afterCompletion(final int status) { listener.afterCompletion(TransactionContext.this, status == Status.STATUS_COMMITTED); } @Override public void beforeCompletion() { // empty } }; if (transactionSynchronizationRegistry != null) { transactionSynchronizationRegistry.registerInterposedSynchronization(s); } else { getTransaction().registerSynchronization(s); } } catch (final RollbackException e) { // 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 e) { // 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.java000066400000000000000000000024321410126276600361010ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 { /** * Occurs after the 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.java000066400000000000000000000144351410126276600345650ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 it's 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) { TransactionContext cache = caches.get(transaction); if (cache == null) { cache = new TransactionContext(this, transaction, transactionSynchronizationRegistry); caches.put(transaction, cache); } return cache; } } 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 is null"); 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 is null"); Objects.requireNonNull(xaResource, "xaResource is null"); 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) { final Connection key = getConnectionKey(connection); xaResources.remove(key); } } XAConnectionFactory.java000066400000000000000000000044421410126276600344240ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 a the ManagedConnection a way to enlist a connection in the transaction. * * @since 2.0 */ public interface XAConnectionFactory extends ConnectionFactory { /** * Create a new {@link java.sql.Connection} in an implementation specific fashion. *

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

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

Commons Database Connection Pooling

commons-dbcp-rel-commons-dbcp-2.9.0/src/main/java/org/apache/commons/dbcp2/package-info.java000066400000000000000000000154471410126276600315620ustar00rootroot00000000000000/* * 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");
 * PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,
 *         connectionPool, null, null, false, true);
 * 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");
 * PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,
 *         connectionPool, null, null, false, true);
 * 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.9.0/src/main/resources/000077500000000000000000000000001410126276600227745ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/resources/org/000077500000000000000000000000001410126276600235635ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/resources/org/apache/000077500000000000000000000000001410126276600250045ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/resources/org/apache/commons/000077500000000000000000000000001410126276600264575ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/main/resources/org/apache/commons/dbcp2/000077500000000000000000000000001410126276600274515ustar00rootroot00000000000000LocalStrings.properties000066400000000000000000000025421410126276600341170ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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}] milliseconds exceeds the maximum permitted value of [{1}] milliseconds 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.9.0/src/media/000077500000000000000000000000001410126276600211155ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/media/dbcp-logo-white.xcf000066400000000000000000000573311410126276600246140ustar00rootroot00000000000000gimp xcf fileæPBB<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) ­ Á Ñ„„„#°öɰ¥-É>ÉöÈ8Âx¡ĐöÈ8€²8wÈöÈ8€PÛÈöÈ8€?ÈúÈ8€₫ÈnDBCPÿ     j%7Ñné Bnư F€€€₫8U UU₫8û8Uqâÿ ÿüƪUU₫ÿ ÿüâ8₫ÿÿüªU8üUâÿÿưâq ₫qÿÿưUüUªÿÿưÆ ₫Æÿÿ₫Uưqâÿÿưâ₫ÿÿưâÿÿưâ ₫ªÿÿ₫Uưâÿÿưâ8ÿưâÿÿ₫â ₫ªÿÿ₫U ₫Æÿÿưâÿ ₫8ÿÿ₫q₫U₫ªÿÿ₫U ưâÿÿ₫Æÿ ₫âÿÿ₫Æ₫â₫ªÿÿ₫U ₫Uÿÿ₫Uÿ ₫ªÿÿưÿ₫ªÿÿ₫U ₫âÿÿ₫Æÿ ₫ªÿÿÿ₫ªÿÿ₫U ₫qÿÿ₫8ÿ ₫Æÿÿ₫âüqÿÿ₫ªÿÿ₫U ₫ÿÿ₫ÿ ₫ÿÿ₫üªÿÿ₫ªÿÿ₫U ÿ₫ªÿ ₫ªÿÿưâÿ₫ªÿÿ₫U ₫ªÿÿÿ₫ªÿÿ₫U₫ÿÿ₫ªÿÿ₫U ₫ªÿÿÿ₫UUưqªÿÿưÆ₫Uÿÿ₫ªÿÿ₫U ₫ªÿÿÿưª₫Uÿÿ₫ªÿÿ₫U ₫ªÿÿÿüUqÆÿÿưÆ8₫Uÿÿ₫ªÿÿ₫U ₫ªÿÿÿư8âÿÿ₫U₫Uÿÿ₫ªÿÿ₫U ₫âÿÿ₫ªÿ ưâÿÿ₫8₫8ÿÿ₫ªÿÿ₫U ÿ₫ÿ ₫8ÿÿ₫Æÿ₫ªÿÿ₫U ₫Uÿÿ₫8ÿ ₫ªÿÿ₫üÆÿÿ₫ªÿÿ₫U ₫Æÿÿ₫âÿ ₫Uÿÿ₫Uüqÿÿ₫ªÿÿ₫U ₫8ÿÿ₫qÿ ₫Uÿÿ₫Uüÿÿ₫ªÿÿ₫U ₫Æÿÿ₫Æÿ ₫qÿÿ₫ưÿ₫ªÿÿ₫U ₫ªÿÿưâÿ ₫Æÿÿ₫âưâ₫ªÿÿ₫U ₫ªÿÿ₫8ÿ ₫Uÿÿ₫U₫U₫ªÿÿ₫Uưªÿÿưâÿ ₫Uÿÿ₫ª ÿ₫qư8ÿÿ₫ ₫Uÿÿ₫ư8ÿÿ₫ª ưªÿÿ₫⪪ÿüÆq ư8âÿÿ₫ƪªÿưÆ8 ₫qª ªU₫ ªUMdddüUªÆÿÿüª8úUU U₫ ₫ÿÿưªqUUñªâÿÆqqÿUUUÆÿ ÿưÆqùUâÿÿ₫qÿÿ₫₫ÆÿÿưÆ8ưUÆÿÿưâUúqÿÿâ8úâÿÿª₫qÿÿ₫ª₫UÿÿûUUÿÿ₫8 ûÿÿª₫Uÿÿ₫ª₫qÿÿư8ÿÿ₫ üqÿª₫Uÿÿ₫ª₫âÿÿúÆÿÿâưâª₫Uÿÿ₫ª₫ªÿÿûÿÿưqâ₫Uÿÿ₫ª₫UÿÿûUÿÿ8₫ÿ₫Uÿÿ₫ª₫UÿÿüUÿÿ₫q₫Uÿÿ₫ª₫UÿÿüUÿª₫Uÿÿ₫ª₫ÿÿüÿª₫Uÿÿ₫ª₫âÿÿûÆÿU₫Uÿÿ₫ª₫ÿÿû8ÿU₫Uÿÿ₫ª₫ÿÿúUÿU₫UÿÿøâªqUUqâÿÿưâUưÿU₫UÿÿüƪªÿÿüâªUưÿU₫Uÿÿ₫ª ưÿU₫Uÿÿ₫ª ưÿª₫Uÿÿ₫ª ưÿÆ₫Uÿÿ₫ª ÿ₫Uÿÿ₫ª ÿ₫q₫Uÿÿ₫ª ÿ₫âưUq₫Uÿÿ₫ª ÿ₫q ưâ₫Uÿÿ₫ª ÿ₫U üâ8₫Uÿÿ₫ª ₫Uÿÿ₫U üâU₫Uÿÿ₫ª ₫UÿÿưªüqÿU₫ªÿÿưÆÿÿưÆUUúqªÿÆ8₫qÿÿưªü8ªâÿÿưª8₫8ª ª₫q₫UU₫7Œ<Drop-Shadow#2̀     c8 øŒ< $“$ŸŒ< ,#g        ùú₫ù  ú  ô      ú÷    ₫ ̣ ü÷ ÷ ₫à   ́è  !! øë !! é  $&()('&$#! ï #&())ö('&%$##""è "&+.010/-+)'&%%ï$#!  #'*-/11û/.,+**₫)ñ !'-2588ù631.,+**+é*)'%#"!"$'*.258998753211ă &-39=?@?<9630/../0122û1/-+))ñ+.15:=@AA@><98778Æ ")18>CEEDA=9631012467898753100148<@DGHGFCA><;<<>?Æ $-5=CHJJHE@<74212469;>??>=;9778;>BGJMNMKHEB@??ACEÛ &/8@GKNMKGB<8411247;>BDEEDB@>>íADHLPRRQOLHECBCEGJÛ (1:CJNQPMHB<730/037;@DHJKKIGEEíGIMQTVWURNJGEDEGKNÆ (2;DKPRQNHB;50-,.15:@FJNPPOMLJJLNRUXZZXUPLIFFGJNRÆ )3FMSWYYXWUTUVY\^__\YTPLIIKNSWÆ  )3=FMQSQMF>6.($#$'-45.'#""&+2:CKRX[\\[YXXY\^`a`]YSNIFEFINS̃  )3=FMQSRMG?70*&%&).5DKOSTTSQPOPRUX[\[YUOJEA@ACHMß (2DIMOOéMKJJLNRUXZYWSNHD@>?AFKÛ (1;CJOQQMHB<62/./15:>CGIJJIGEEíGJNRUWWUQLGB?==@CHÆ &09AHLONLGB<73100369=ACDEDB@?>?AEIMQSSQNJEA><<>AEá %-6>DIKKIFA<74101358:=>>ç<:9879;?DHLNONKGC?<::<>Aâ "*2:@DGGEB>:63100135788æ753101259>BFHIHFC?<9889:=ă  '.5;?ABA>;741/../0122å1/-+*)*,/37;8644568è #)/48:;:8630.,++,+ê)(&$#"#%(,058;<<;864200ư12è $)-02331/-*)'&&æ%$#" "%)-024431/-,+**₫+é "&)*++*(&%#"!  ç"%(*+,+*)'&%$$̣ !##î"! đ "#$##! ñ ä ÷ó đ  ÷ ₫ơ    ù ö  ₫ ơ    ÷    ₫ û   ₫   @*   ₫₫ øø ï ó   ü   ë  ö  øÜ    Đ   ø !""æ!  !  öø !#%')**æ)('&%$"! ('%"÷ !""!"#$Û%&(*,/1233210/.-,*(&#  1/-*'#ø!#%&''ư&%$$Ă%&&'(())*+,.1479;<;;98765421.+'"8763/+&""$')+,,+*)(&&ï'()*+,--.0247;>ACCƯBA?>=<;:963/)$@?>;73.*&$$%&),.011ú/-+)'&&ç'(*+-./01369=ADGIJJIGEDCBBƯ@>;60*#FFEC?:61.++,.03577642/,)'%%è&')+-/02369=AEJMOPONLJIHHçGEB=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*#cgiihfdbaaÂcdda]VMC8-$  !*4?IQY]_^[WRMHDA>;84/)$aehihgecbbdÅb^WND:/%  !*4>HQX\^]ZUOID?;740,'"_cghhgecbbÂcddb^WOE;0&  !*4>HQW\][WRLE?940,($  \aeggfecaa¿bcca]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-$ IMOPPNKHECC¬EGHJJIFB=82-($  &,3:AGKMKHB;2*! EGIIHFC@=;:;CGHGD>7/' ?ABB@>;75322479<>?>=;840,(%"#(.49>ABA>92+# ß9:;:852/,*)*,.146898752/,)%# æ %*/49<=<84.'  3Ç1/-*&$"!"$&),/12321/-*'$"!%*.25542-(" +î*)'$!!$')+,,ô*)'$" è $(+-.-+'# ö$##!ê"$%&&%$"!è!$&&%$! ö÷ơè í ö  ø ó ö ê   ù ó ë  ù ÷  ô øú   ùû  ÷úø₫₫     QĐĐĐk üûûúùù ø ø ø ø ÷ ÷ ÷ ÷ ÷ ÷ ÷ ø ø ø ø ù ùúûûüF#×commonsÿ     %O×%k3»3Ç×%‡)Œ-21€€€ư8qªªüUư8Uªªưq8üq8ưqâÿÿưª ưqâÿÿüâ úUªÿÿUơ8âÿÿ8ªÿÿ₫UôUâÿÿ8qâÿÿ₫Uüqªÿÿ₫UúUÿÿÆ₫Æÿÿ₫U₫qÿÿ₫U₫ªÿÿ₫ªüªªÿÿüUÆûUÿÿâ₫qÿÿ₫â₫Uÿÿ₫U₫ªÿÿ₫ª₫qÿÿùªÿÆ8ÿÿ₫₫ÿÿ₫U₫8ÿÿ₫Æ ₫âÿÿ₫Uÿ₫ªûâÿÿ₫Æÿÿ₫₫Æÿÿ₫U ₫8ÿÿ₫âÿ₫Æ₫qÿÿ₫8úâÿÿU₫8ÿÿ ₫âÿÿ₫qÿ₫ª₫Æÿÿ ₫₫ªÿÿ₫Æ ₫ÿÿ₫Æÿûªÿÿ₫Æÿ₫ª ₫8ÿÿÿûªUÿÿ₫ª₫ÿÿ₫ª ÿ₫8ÿûªÿÿ₫ª₫Uÿÿ₫ª ₫âÿÿ₫Uÿûªªÿÿ₫ª₫Uÿÿ₫ª ₫ªÿÿ₫Uÿûªªÿÿ₫â₫Uÿÿ ₫ªÿÿ₫Uÿûªªÿÿ₫Uÿÿ ₫ªÿÿ₫8ÿûªªÿÿ₫Uÿ₫U ₫ªÿÿÿûªUÿÿ₫Æ ₫8₫âÿÿ₫ ₫ªÿÿ₫Æÿûª8ÿÿ₫8 ưUâ₫ÿÿ₫Æ ÿ₫qÿ₫ª₫âÿÿưâ ü8ÿ8₫8ÿÿ₫8 ₫ÿÿ₫ÿ₫ª₫qÿÿưªü8âÆ₫Æÿÿ₫ ₫qÿÿ₫ÿ₫ª₫âÿÿưâ8ûqÿÿ₫ÿÿ₫ûâÿÿâÿ₫ª₫UÿÿưâUUúâÿÿU₫Uÿÿ₫Æúqÿÿâÿ₫ª₫Uÿ ÿ₫U₫Uÿÿ₫ªúUÿÿâ₫ÿÿ₫ª₫Uÿ ÿưâU ư8âÿÿôâqUÆÿÿÆ₫qÿÿ₫ưÆÿÿư ưqâÿÿưÆ8üUqÆÿÿưâªưUªªưUư8qªªưU ª€€€ù8qªª8ùUªª8 ư8ùUªªqùUª8ÆÿÿưÆưqâÿÿưÆúqÆÿÿưqâÿÿ₫ưÿÿ₫ÿÿ₫Æư8âÿÿ₫âü8ÆÿÿưÆÿÿ₫q₫qÿÿúâUUÿÿùqUÿÿªUUưâÿÿ₫qüƪÆÿÿöUâÿÆqUUÆÿÿùªÿâUU₫8₫ÿÿúâUÿªưâÿÿ₫â₫Æÿÿûªÿ₫qÿÿûªÿq ₫ÿÿ₫ª₫qÿÿ₫8₫Uÿÿ₫U₫âÿÿ₫U ₫8ÿÿ₫Æ₫8ÿÿ₫U₫Uÿÿ₫q₫ÿÿ₫q ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ÿ₫ªÿ₫ª₫Uÿÿ₫U₫Uÿÿ₫U ₫ÿÿ₫âÿ₫Æ₫qÿÿ₫U₫qÿÿ₫ ₫qÿÿ₫U₫qÿÿ₫₫Æÿÿ₫Æ₫ÆÿÿưâøU8qÆÿÿ÷ªU88qÆÿÿ÷âU8UâÿÿüÆUüUâÿÿóâUUª8qª ªûqqª ªưq8ª ª ªü8ª€€€ªưqüUªªưUü88ưqªª₫Uÿ₫ ư8Æÿÿưª8 ơ8âÿÿUÿÿưâUÿ₫ ùÆÿÿÆUưUÆÿÿ₫ªüUªâÿÿûU8âÿÿûUªÿÿ₫ú8âÿÿª₫UÿÿưâªÿUøÿâUUâÿÿ₫â₫Uÿÿ₫úâÿÿª₫Uÿÿưâ₫ªÿÿûâÿª₫Æÿÿ₫U₫Æÿÿ₫â₫âÿÿ₫₫ÿÿ₫ª₫Uÿÿ₫U₫8ÿÿ₫ª₫ÿÿ₫qÿÿ₫ª ₫âÿÿ₫8₫Uÿÿ₫q₫âÿÿ₫â₫Uÿÿ₫U₫âÿÿ₫U ₫ÿÿ₫Æ₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫Uÿÿ₫ ₫8ÿÿ₫₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫ªÿÿ ₫âÿÿ₫U₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫Æÿÿ ₫ªÿÿ₫₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫Uÿ ₫ÿÿ₫ª₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫Uÿ ₫Uÿÿ₫ª₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫Uÿ₫U ₫Uÿÿ₫ª₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫Uÿ₫U ₫Uÿÿ₫₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫ªÿÿ₫ª ₫Uÿÿ₫U₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫ÿÿ₫â ₫Uÿÿ₫₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫8ÿÿ₫ ₫ªÿÿ₫Æ₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫âÿÿ₫ ₫Æÿÿ₫q₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫qÿÿ₫â ₫ÿÿ₫â₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫U₫Æÿÿ₫q₫ÿÿ₫8₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫Uưâÿÿ₫₫ÿÿ₫U₫Uÿÿ₫U₫ªÿÿ₫Uÿÿ₫qưâÿÿưâúâÿÿU₫qÿÿ₫U₫âÿÿûÆÿÿ₫Æưªÿÿơ88ÿÿâU₫âÿÿ₫Æ₫UÿÿüqâÿÿûÆqUư8Æÿÿưâqü8qâÿÿ÷âUUªÿÿ ª₫8ưUªªưq8 ₫qª ª₫8ªªVVV ưUªªúU óÿÿ⪪ÆÿÿªÆÿûÆÿâ8ư8Æÿÿûªÿÿ8üâÿÿû8ÿÿÆü8ÿÿûÿÿªưªÿûªÿÿâưUÿ₫ªÿÿ₫q₫ÿ₫qÿÿ₫q₫8₫ÿÿưÆ8₫ÿÿưÆ ₫ªÿÿư ₫ÿÿưâq ư8âÿÿưâ ₫qÿÿưâU ưÿÿưâ ưªÿÿ₫ưªq₫Uÿÿ₫⪠₫ÿÿưªÿ₫ÿÿüªÿqÿ₫Æûªÿâ₫ÿÿ₫qûªÿÿªûÿÿª₫ªÿÿưÆ8öÿÿªÆqøªÆªªÿÿ⪪ÿưâqª₫8ư8ø8UªªUk 5ơ8 Drop-Shadoẁ     ÿÿÿúÿÿÿú94{ơ84—\̃\êơ84³?I°T‡U  ₫₫₫₫ øúùù ô  í     ù  ̣ ÷ ø ø ×  øî ÷ôøí  !#$%%÷$# ó!"##$%%ù$" Đ  "$&')*+,,+*'%"!#$&'())*+,,ú*(&#!é !$&(*+-.0122ç1.,)&#! !#$'(*+,--./02344ú31.,)×  #'),-/01346787642/,)(''(*,./11223û568:;;û9752ß !&*-/12334679:;<;9742/..è0245677665668:=?ABCB@=:đ "',024566Ù78:<=>>=;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?=:8755ü421Å &-5=DINPRQPMID?:4/*%" !$(,048:;;:875321100/.,+*Ø %,3:?CFHIHEB>94/*%! $(,/133̣10/.-,+*('%$#Ö $*059<>?><:62.)$  #&)+,,̣+*)('&%#" È !&+.134431.*&"!#$%%$$#"! É !$')**)'%" ̣   ơ ö ö Ú   ơ ô é   ö  ö  ÷ ø øù "    ₫ü      ú  ô      ø ø   ë  üø  ÷ ó ûöø  öî !!û"#$$%%û$#"!  !₫"##ø!ö !!đ"#$%!$&'))*û+,-.//ơ.-,*))()*+,,́*(%!"$&())**ú+,-.÷ #&*-/12334ü57899ú8764211ü23455í31-*&" #'*-01233í4567'%%&(+/369;<==<<ó=>@ACCDCB@><::ư;=>>́=:62.)&$$%'+/37:;<=<<ñ=>@/--.037<@CEFF₫EDDûFGIKMM̃KIGECAABCDFGFEC?:51-+*,.27<@CEFFEDDEFH86558;@DILNOOMLKJJLNPSUVVTROMJHGGIJLMNMKGB=841125:?DILNONMKJJKLN@>==?CHLQTVWVTRPOOPRUX[\]\YVSPMLLMOQSTTRNID?:778;@FKPTVVUSQOO€ÅQSHEDDFJNSX[]][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@?ADD€2EHMRW[^^\WQKEA>?BGMSY\]\XRLFA??BGMSY]^][WRNLLMQUY]^]ZUOIC@>@D>=>@CHMSWZZXTNHC?==@EKQVYZXUOJD@>>AEKQVY[ZXTPLJIKNRVY[ZWRLFA>=>B778:>CHNRUUTPKE@=;;>BHMRUVTQLGB><<>CHMRUWVTPLIGGHKOSUVVSOID?<;CHLOPNKGB>:88;>CHLOPPNKHECCDFJMOPPMID?;878;))+.27BFHIHEA=96446:>BFHJIGEB?>>?ADGIIÂGC?:64347"#$'+059=?@?<952/..037;>@A@>:731//147;>@AA@=;9878:=?AAí?<841/./1!$(-1466×41.+)((*,/2578752/,*))*-035788753100134688È630-*)()+!%(+-.-+)'$#""#%(*-./.,*(%$##$&(+-.//.-+*))ü+,.//ú-+)&$""î$!#$%$#! ë #$%&%$" !#$&&ơ%$#"!!"#$%&&ú%#!î óû÷úơ ơûûî ü  û ơ û  ó                ơ ü 9 ₫,  ú   ô û ü₫₫     ù ÷  ₫  ù ÷ ü₫ö ơ ú  é ö  ơ ùơ%%û$#"!  ü!""##ö"   óë !"#//ơ.,+*)(()*+,,ç+)&# !"#$%%ù$#!ô"$')+,,899ơ875321122455Ç42/+'" "$%&'()*+,--,+*(&#"!!"$'*.13566BCDCCA?=;::ü;<=>>å<84/*&" "%')*+,-./012344Ê20.,*))*-037;=?@@JLMMLKIFDBAABCEFGFDA=83.)&%%&(*,.01122Ă34689;<<;975321358=AEGIJJQSUVUTQNLIHGHIKMNNLJE@;61.,,-/2456766è5679<>ABCCB@><::;>AFJNQSSÚVY[\\[XUROMLLMORSTSQMHC>964468:;==<;988‰9;>BEHJKJIGECBCFINRVY[[ZZ]`bba^ZVRPNNPRUWYYWTOJEA><=>@ACCB@>;9889;?CHLOQQPOMKJKMQUY]`aa_[_cefeb^YUQOOQSWZ\]\ZVQLHFDEFGII€ùGD@=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[bgijjhggÂijkkid]TJ@70+)+/5>GPX_ceedcbbdfhiigb\LSY_bb_YSLEA@AELS[afijihffåhijjid^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>CINRTTÂUWZ]addc_ZJQW\__\WQKEA@AEJQX^bcca^[YXYZ\]^]ZUOIC=86569=BGJMNONNĂPRVZ^aba^XIOUZ]]ZVPJDA?@DIPV[_``]ZWTSRSUWXXVSNIC>:878:=@DFHIHHÛJMRV[^_^[WGMRWYYWSMHB?>?BGMSX[\[XUQNLĹNPQRQOLGC?;9889;>@ABBAÂBDHLQVY[ZXSDJOSUUSOJE@=<=@DJOSVWVSOKHEDEFHIKKJGDA>;97789:;<<;::Ê<>BGLPTVVSO@EIMOOMJE@<989<@EIMPPOLHD@><<=?ABCCB@>;976556ư5433’57;@EJMOOMJ;?CGHIGD@;85457;?CFHIGDA=9654568:;<;:9754221100/.-,+,.049>BFHHFC48?@><-14677641.+*))+.13677530,)&%$$%'(*+,,Ú+*)('&%$"!  "&*.256764&)+-./.,)'%##é$&)+-..,*(%" "#$%%â$#"! #&),-.-+!#$%%¢#" !#$%%$" !#$%$#ä ûưú  û î ú û   ₫ù û   đ  ü      ₫  ú ô ü₫   ! ˜ ˜ ˜×*   ₫₫    ù÷÷ ú     öö ù ô ́ ñ ₫#$$%́$" ñ -.Ù-,)&"  678ö753/+'"ø!#$%&&ï%$#! @?ê@AA@?<84/*%" !#%(*,--í,+*(&# ưIHGG₫HIIÙGEA<71,)&%&'*-/1344321/-*'# ưQPNNÖOPPOMJE?94/-,,.1479:;::8641.*&! æWUSRRSTUVVTQLF@;632247;>@AÁ?=;851-(# ü\YVUUÖWYZ[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ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ0ÿ0ÿ0ÿ0ÿ–2K% commons-dbcp-rel-commons-dbcp-2.9.0/src/site/000077500000000000000000000000001410126276600210025ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/000077500000000000000000000000001410126276600230145ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/download_dbcp.cgi000077500000000000000000000002351410126276600263020ustar00rootroot00000000000000#!/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.9.0/src/site/resources/images/000077500000000000000000000000001410126276600242615ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/dbcp-logo-blue.jpg000066400000000000000000000125671410126276600275710ustar00rootroot00000000000000ÿØÿàJFIF``ÿÛC  !"$"$ÿÛCÿÀFÙ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑđ$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰’“”•–—˜™¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂĂÄÅÆÇÈÉỂÓÔƠÖרÙÚáâăäåæçèéêṇ̃óôơö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RđbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰’“”•–—˜™¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂĂÄÅÆÇÈÉỂÓÔƠÖרÙÚâăäåæçèéệóôơö÷øùúÿÚ ?÷-Cö‡øUa{5Æ»p³C#Fále8eb¤p¾ Ôđ̉_ è=wÿ‚ù¿øøƒÆ_̣7ë?ơÿ?₫Œjɯ¢YM·×Èđ^gZû#ï_øi?„¿ôºÿÁ|ßüMđ̉_ è=wÿ‚ù¿øø*Ù4;¿ëä/í:Ư‘÷¯ü4—Â_ú]ÿà¾o₫&øi?„¿ôºÿÁ|ßüM|EÙ4;¿ëäÚu»#ï_øi/„¿ô»ÿÁ|ßüMđ̉_ è=wÿ‚ù¿øø*?²hw×È?´ëvG̃¿đ̉ è=uÿ‚ù¿ø?᤾ÿĐzïÿóñ5đUdĐîÿ¯iÖ́½᤾ÿĐzïÿóñ4ĂIü%ÿ ơ×₫ æÿâkàª(₫É¡Ưÿ_ ₫Ó­ÙzÿĂI|%ÿ ơß₫ æÿâhÿ†“øKÿAë¯üÍÿÄ×ÁTQư“C»₫¾Aư§[²>ơÿ†’øKÿAë¿üÍÿÄÑÿ %đ—₫ƒ×ø/›ÿ‰¯‚¨£û&‡wư|ƒûN·d}ëÿ 'đ—₫ƒ×_ø/›ÿ‰£₫Ká/ư®ÿđ_7ÿ_QGöMïúùönÈû×₫Ká/ư®ÿđ_7ÿGü4ŸÂ_ú]à¾o₫&¾ ¢́ßợí:Ư‘÷¯ü4—Â_ú]ÿà¾o₫&øi/„¿ô»ÿÁ|ßüM|EÙ4;¿ëäÚu»#ï_øi?„¿ôºÿÁ|ßüMđ̉_ è=wÿ‚ù¿øø*?²hw×È?´ëvG̃¿đ̉_ è=wÿ‚ù¿ø?á¤₫ÿĐzëÿóñ5đUdĐîÿ¯iÖ́½í%đ—₫ƒ×Gë§ÍÿÄ×iÿ Â?ôü“ÿ‰¯Ízú¶°­–̉…¬Ù½}Ỹö>hñ—üÚÏư„'ÿÑY5­ă/ùơŸûOÿ£²kÙẸ̀%» (¢˜‚¾…ư>é|qâoê:œ2Ü46Ù´k¹S†‘‹+dnÊă ~CÉÈǃhmÖ³­Xé*­u}q´ Ç»°UưH¯ĐGû;áÀ¹ÖÙ£hzYX‹|‚k‚03…ån¾­^~a^TăS~ógvŒfÜæ´Gj_² „—%´ßÜÛÁÙ.4Ơ™úŸâYtÇođ®GÅß²ŒôÛ_´xYӵ¨KBÊm¥'°]Ä©üYk̀t‹ßô¹Œ¶̃:×dcÚêí®W¡v]Ă¿§§ ¯ ÿfŸºÿ‹<]oàï-¤ó\Âßc¾†/.G•±YùNT ‚¸ÁƯÆU6Œyù”’5ƒÂU—/+MŸ(kZ^£¢ê·V¯e=ơ³l Đ«¡ÆyÔAî5Ø|øc¬üOñ Ún›™í[,c©†uc£FO ¡ˆTåªgªè¿³OĂ éM¨xËV¸ÔR$y®®…²ă9#iGƠÏJ–O‰?³—€îe₫ð̉§½·M¡ô½,K#‚3µg +găǯC…ư²ôßxŸFđÏ„|7¢̃ê—WW̉]¿‘V!eFö<&|ÖÁ$”×9đŸöZ†ÊXuoˆ‰y$:éVmû²Gi$8ƯÛå\r+ÏŒ£:~ÓQëÑ̉Œ¡SÙЂөïß̀m Ç, 2 =0WüÅă?Ù»âW†´™u1›¬C —•tÙÙäE’Û]T·N‹“íOP©ÎånÊÿ˜±²«*|7îíù7EơḈÏđ& ÚüA¶Hï#_>ÆÂçå[5‰¦₫Zw ~çSóp¾# æ‘åP¡*̉å‰çŸ¿g/øÊ(uŸ<Úˆà”VL]Î8ÁTa„SÏ̀Ưp0¤×Đ—>øđÇĂÍu®hÚ 6ă$Í« º–f Ñ›‹ íAë^[ñ§öŸ¸[Éô_‡ …2«̀›‹ẠPđăælç1‚~g×uW^ÔåÔµ­FëP¼”忏»sŒƒƒ\*†'ùªK•vGk­‡Ă®Zk™÷gEăétïüS¿>ĐMµ•ưÊŧX[@œ*®Bq±Û5́ÿe-kP†ßë ¤Fܵ• ÏŒt/÷çĐ=x§Â¿ÜøÆ–¾'³Ó­/ç¶I"¸z•È#pzú;×Ù?²·¼MñĂ:çˆ|Iv’¿öŸÙà†(DqB«1 Ụ̈üä“̉¯Rµ »Ñ.½HÁÓ¥Z~₫­ôèfƯü3ưŸ₫Ú[Ưø#1‚I«N×N7ùXŒºœdzÖ¿Ûözñ¬cá­Á—·ä6‘3°BÉ»£?^+Án-xj?́ôX¥WIÓƠ]Cgl²표—Ë÷ư)ß±§ĂícVñơ·äV¶Ñôƒ&ÙúL­&Äö]Ù'Øù®ƒxmR£½»ưÇJ¬•e+z}ç­|sưŸü¨øKSÖ¼5¦¦‰«ØÚÉqZaaŸ`-±£# 0Æ31_WÜŸµ×Ä‹ øë¶—¾·­ÀĐù#“ ³|²;ۆ够C_ ×^XêºW›ô9sMT´¨QEèœ_V×ÊUơmrâzXn§Í2ÿ‘»Yÿ°„ÿú1«&µ¼eÿ#~³ÿa ÿôcVMtÇdsKvQE1ûûxV=gâ]߈nbI ĐíwG’r'—*‡Ê%ëßwïíÛâÖµÑ4oÛJ›ï\̃̃(a¸F‡l`Œg ÅxÿWßœu?±>„ºgÁ±ª’­&±}4ù ‚¨‡É O~csÿü₫tưªu§ñÇmb+f[”²hôè X’/»yŒăé^ ₫Í:æ¿5¾±ă¤›F̉C'‹«•Æpç’󃟛‚08jôßôO‡ø/À fÚÄpˆÈP`Ó &:/AƠ»+kÄ{_ÜQƠ½ßDg†¡́¿}[D¶ó9/Û‹â¼ígđóN•™à‘o5'I>PpDp'y§È~ẃKáïØø ç^Óơ8ïuAÂj«Ç Fo.=¤ 1=óÆ@¾0»¹¸¼»îîyn.'‘¤–Y\³È́rY‰ä’I$ûsö#̉ZĂàÓß;†₫ÓÔ¦@₫P±cóăYă(¬>‘>¿y¦«¯çk₫·ñĂă‹đĂSƒGŸH½Ôơ;‹OµGn±Ä³*îs’2Qº̉¼Äµ®æa£èú.—\èóÈ®âBÿăµûb_găÅΟg’Mekmdª‹¹¥v` $₫ô.=EGđ¯övñÇ‹®aºÖm%đæ»2MyYƯyá"?6x¶Ñƒ‘»¥0ØjTcRªƠ®¿ä*ØŒEJ®̃Ï¡Ơü øÉñ‹Æ_t½µ85æó/a}>% `A‘·¢RåRÄ‚̀ ç5ô¯Æiđ£®j/qEin_k\LÀ…AßÜ'µy¶£â…³Ç†åÑ4Tÿ^(Öđº½ƠÄ2¦â@?v¿>@#€Çjkæ½k_ñwÇ_zeơ¬·“‹{;xÿÔÙDN\ª’3…˜“–ÛÀ ¾¯MOh£Ẹ̈¹¯·•r9sM₫§~Æ¿ bƠ®ÿá`ø‚Í&²µ“n•œ‰&RCJWÑÂÿµ“ü ̉~ئԵ9₫xvè.ŸjÛuIâs™å˜ƯS×®[6óïơ‹/„ÿnåÑĐBºm’Yi¨NăæG9#v3¸÷ Í~xË$“J̣Êí$ÅØä±=I=Ím„_ZªëÏe¢2Ä¿«RTc»ÜeƠx3áÏȘâ#ç/Á₫#a^q[SÀÊm:îöÙt120º¢­~½KÚ₫¯©ëúÍÖ³¬̃Ë{w!’yå9goä Th¢½$­¢<öîQEơm|¥_V×.'¡Ơ†ê|Ñă/ùơŸûOÿ£²k[Æ_̣7k?öŸÿF5d×LvG4·aESú/đ'N×tÏ„^Óu{kK ˆlĐ*ÄæBŒ‚Ü$ Ă'½rZÆ»đ;á&¡ªÉ%…׉'IîZ]ßÉ3í“̉-Çœ|‹ÏA_ƯxÓÆ7zwöm׋5é́¼¿+́̉j2´[1»Kcn8ÇJÁ¯*9krnrÑôG¥,Á(¥꺳Ü>/~Ñ̃,ñ„ré~WđæÇÈ”ưª`¤ÚÆU}Á, x}W£JŒ)G– Ç J³ªï7p¯Ñ¿D^ø1á« Ê[ùv <åÜa^\Êùlăï9ïüä­kŸx’çDMçÄ´ÚTaBYIy#@¡z;F01Åsă0¯í©¶°̣rµÏµ|[ñÇáƒo¯n´Ùmµ^ä‰'m*̀p柅8 8Üpq̉¾~øûIxûÅ1Me¥¼>Óä8ÛdÄÜÆi>¼¨ZñZ)QÀQ§«W~eUÆƠ©¢Ñy–I&•å•ÚI‹;±Ébz’{ơÏÙ'Ä^đÇÅ‘¨x₫+ w°– {‰¸D™™1¸ôPT8Éặ +ª­5R©ÍNnœÔ—Cô?Æ^$ø/ă é~%ñO„5+ÂQ´A•°@e*á•°Äd`̣k†µ×fË °ÿ„~K…%£–$Ô$__̃aÊơîĂô¯h®e+—Øî–`äïÈ®}—âÚÇÁö+$^đ₫©«H„i™m¡a܃ó7…F}º×Œ|Mư¢¼wă+ô»co i“;̃s§÷ZRrG®Đ¹Œ×Ñ[̉ÀP¦î£¯™…LmjÍè{ẃU¤Á©|kK©—sil÷qóщH³ùJkÜÿm}nÎÇá hïy ^jw‘­ÉËȈÛÙ€ô.ON@î+âÍXƠ´Kß·hº¥ö™u´§ŸipĐÉ´ơ”ƒ7WƠ5=bỗêúæ¡tÀ)êv•Èæ$ÔTÁº˜…U½TñJ$µe:(¢»0¢(¢(¯«kå*ú¶¹q=¬7SɼWđ§ÄSx£U™o4 ¯{3 Ë&p\ŸîVgü*_ÿÏî“ÿdÿâ(¢ª3•‘œ¢®Ă₫/ˆÿç÷Iÿ¿²ñÂ¥ñü₫é?÷öO₫")óÈ\¨?áRø₫tŸûû'ÿGü*_ÿÏî“ÿdÿâ(¢y*øT¾#ÿŸƯ'₫₫ÉÿÄQÿ —Äóû¤ÿßÙ?ø(£Aʃ₫/ˆÿç÷Iÿ¿²ñÂ¥ñü₫é?÷öO₫"(çr ÿ…Kâ?ùửḯŸüEđ©|Gÿ?ºOưư“ÿˆ¢9ä¨?áRø₫tŸûû'ÿGü*_ÿÏî“ÿdÿâ(¢y*øT¾#ÿŸƯ'₫₫ÉÿÄQÿ —Äóû¤ÿßÙ?ø(£Aʃ₫/ˆÿç÷Iÿ¿²ñÂ¥ñü₫é?÷öO₫"(çr ÿ…Kâ?ùửḯŸüEđ©|Gÿ?ºOưư“ÿˆ¢9ä¨?áRø₫tŸûû'ÿGü*_ÿÏî“ÿdÿâ(¢y*đ—Äóû¤ÿßÙ?ø?áRø₫tŸûû'ÿEsÈ9PÂ¥ñü₫é?÷öO₫"øT¾#ÿŸƯ'₫₫ÉÿÄQẸTđ©|Gÿ?ºOưư“ÿˆ¯¥?áƠ¿çâË₫ûo₫&+—7¡Ơ†ÔÿÙcommons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/dbcp-logo-white.png000066400000000000000000000300421410126276600277520ustar00rootroot00000000000000‰PNG  IHDRæP ù ÓsRGB®ÎébKGDÿÿÿ ½§“ pHYs  œtIMEÛ c4H!iTXtCommentCreated with The GIMPm°— IDATxÚí}ypUåùÿç̃\¤3ưC!dư§Ê ¨ÆHÚ2:¶*–Å@ë"P%" %È" Rd â°"°CƠ²© ’Ü{“óûCß3ÏyÎós£ưÍ·bÎ̀Br̃ưÙßgñ†a ư¼‘M-ÇăiôxÿKc¨6¡ÁÛ:µsú[cç*}ÿcæÊ\¥~ùø?ö8pÀ²×ªm|||HóƠ¯ê_í£ÄÇÇ›ă¸̉«½ÉÉÉ1ÏRơ©àH#dgg#''Çu<'âû 999èÑ£‡¹ç?₫8fÍ¥%̃Nÿ76\Ù³gñññÇ7;;Û8₫¼QWW§}ư~¿á÷û@ `ƒA£¾¾̃¨¯¯7fÍ̉ñññFnnn£Ç ƒÆ5kŒœœ³¯5kÖÁ`Іßï7vï̃mtï̃];v÷îƯsçÎ7nܰ½3f̀pœ¿j[[[kiW[[kÔÖÖZæŒÏ>û̀˜5k–‘’’bö¡æªæ;sæLÇ1{́1Ûx7nÜ0Î=k<öØcû¬ÚªW+/=Ë={öXæí3»ví2êêê,ăIç©Ö^TTdŒ?̃²ö·ß~ÛÜ—ÿûßFnn®# ­^½Ú¶/º³Pë›0a‚¥œœ#''DzÖ́́l†B…KµoơơơFCCƒÑĐĐ`†ahsß¾}–ÅO˜0Á(**27àüùóFvv¶má«V­2¾ưö[ÛûƯwß™ &úÖ[oYÆ?~¼±{÷nĂï÷uuuÆùóç—_~Y@·qÎ;g¼ụ̈Ëâo½ơ–97@Uo·nƯŒo¾ùƸ~ưºqưúucÇF\\\HmăââŒo¾ùÆöªy=ö˜–8¨¹?̃‘€Đ7//Ï2ß¼¼¼Ú0Ƨ+?K¿ßo|öÙg MII1Ö¬Yc‹:oiîC† q<Ë7ß|ÓÈÎÎÖ"u–;wî ‰À0V®\iîËơë××§æó̃½ÛB ëêêŒ]»vÙÖuăÆ ă»ï¾3û̉!¿9EÄü׿₫eÙà/¾øÂ2‘ºº:sànƯºÙ½bÅ ă믿6ßk×®YÿƯwß3f̀Đ" í_mÖ!ClădeeiÇ7nœ1dÈcèĐ¡âÁ¬^½Ú8sæŒ9ÿ¸¸8ćرÆo¼a¬X±Â3fŒØîÅ_4jjjŒeË–™¿Ë̀̀4–/_n¬X±Âl+!́‹/¾h|ùå—–÷«¯¾2¾₫úk£[·nÆ!CÄưT½zơj³ßnƯºÓ§O7ḈÚµ«Ø®¬¬̀¨©©1233Íu=Ú2߬¬,m[i®jŸƠYr„ÈÎζÀâºê«tLÅƯuë¢ăP‚(6JÔ¸Ô!"&EÊøøxS„¢ùöÛoo¾ùƸví1}útÛ¢cccêêj£ªªÊ¨®®6ª««sáo¼ñ†mc)…Qư_¿~Ư<¤¯¾úÊ.úfffc¨q¾ụ̈K³S(DïÚµ«±mÛ6ăË/¿4û¨ªª2ªªªŒcljk[²d‰ÀÈÈÈ0JJJŒ«W¯oEE…QYYi=zÔˆµµ¥ß^½zƠ¨¬¬4÷‰"©n¾cÆŒ1?nÔÔÔØæ;mÚ4[»G}ÔÈÈÈ0S§NçZYYi,]ºTl+}_]]mîñ©S§,9tèP‹LÏóÚµkæY._¾\ÜÛcÇÙΓ"ŒD ƠøYYYFii©¹'•••FEE…QQQa$''ÛÚ-Y²Äq}Û·o·HKûIpzíÚ5Ë÷AăHO”#§Åø³oß>ốÙÓTD?ÿüsÄÆÆÂ0 444 ¡¡ÁüYư{áÂtêÔɦ$ççç###Ăb(đx<())AZZù]·nƯ°cÇ‹aƒ¾j,ơvîÜåååâXÔ áơzáơzƠï-Z´hÆç˜™™‰eË–‰kSÏÔ©S‘ŸŸo[_zz:,X`QÚ髿5uêTK»Í›7#))Éü¿£oXX6õŒ‡~Ø6æ²eË0xđ`Û\é|»víjÛX°`̉ÓÓç;xđ`>|Øü&&&´µ¡sMLLÄ¥K—̀oΜ9cAøùÏ“'OÆ¢E‹,ó̀ÈÈ@~~¾e^jLÇ£Ư›¥K—"##Ă«JJJ™™©=C:†Zß”)S°páB@VVV­ZÇcƒQ5&<ôĐC(((@ee¥ÍÀCû¦?óÿ€—"ÄÿøG³£ñăÇ›HY__††Ô××# " "  ** ]ºt±mT§Nà÷û-o Àĉ-ß=úè£fŸô đûư–±€¹Qôy₫ùçá÷ûQWW‡ºº:³­Óï÷‡ñ6ÉÉÉÈÏÏ7¿SméÏuuuèß¿¿m¼Î;cΜ9¨­­Ơ¾uuu"Áúâ‹/,ư«oé¼ëëëmí¦M›†ôôtË|ù\kkk-DO=Ï<ó î¹çqt;w¶´»|ù²¥ºG~¿óçÏ· eVV¢¢¢´ç©^u.Ï=÷bbb,cnÙ²û÷ï·ŒEÛH{3uêT 8Pܵ¶öíÛ#::Ú̉îđáĂâY¨±¨åµ¸¸Ø\ ŵ¶`0¿ßo? ̉~Ô××›xʼnˆ1ç̀™ƒ‹/ZLË ĉ¨^°`eƒçÍ›‡ˆˆÛa8pÀB‘Ơâư©W-–₫®S§N¶Ă¼|ù2/^lCçäọ̈ĂŒ6ÿ®„¤ú¹}ûö6@ˆŒŒtDJƠGBB‚­íÖ­[µÀ^[[«ÈÈÈH‘«C‡¶¶ááá–5©÷Æ–>:v́hk[PP`CÍsñâÅ6n§CD`ê›Aƒ‰ˆFÏÎ1 Ú¾ˆˆ0÷¥1„̣Ê•+¶oèÏ aà̉¥K˜7o6é:Ơºa”ö#¦Â/Iúñ)L}çw,“îÚµ«£9–Ó[µj…¢¢"\ºt ÑÑÑ0 @Àv×ÈE¤¤$ÛFKâ2§&iiiX¾|¹ àï¿ÿ~‹XB_₫444˜™¯‰%Ưe544ØN'ñ§¾¾µµµ–6aaa櫨±ÔÎWÍ™Î×ăñˆmƒÁ jkkm÷†\Œ ¶¶@À2_%ÂnƯº—/_¶|›˜˜¿ßo{j~øèy0K—.µôsäÈüç?ÿ19§4Ç`0ˆºº:s_ø̃ĐsăO]]MÔ C0D§Nđ̃{ï™ßN< 9r¤Ed¦ªaX»v­¹\µRưÓ1Ơ¼¨˜́3 /^´\Ävï̃ƯL-Ta:å¢y"## ṃ·À| r-5ytcé÷ïß߆˜GµGNr©µ©ụĂÔ!¦ßï·ˆ! ëŸùêK!¦n¾:ÄT"×ytˆ©ÆUóUßR€åœ‹î“Ûyv́ØÑÑѸråM̀́ׯŸm®º½QÜT‡˜G”Dè|)bú|>ÜsÏ=x饗,ßO™2˜4iÅ5&$$ XΗ#%wdđz½œñÀ̃½{-ƒÇÅʼnHI‘“Skn¸áœ®¢¢Bp :Å/B¹ ¤¤:t°Ư ÇTỵ̈1CALS/øĂÂẦuk¦Èïơz-ỖcRä¤ÄO©®-Î!t€«Úrà判¸"‚œ£Đóä.:u²ơwäÈôéÓÇr^¯×2\1ỠĐq$IÏB퉒\Z¶l‰x«V­²ÁÙĐ¡Cѹsg̀=‘‘‘–5JF«°°0ÛZ$¼Q8`£êH¨|,)¬¼­úẼO?ưTä1u¯B7/** W¯^µôW^^6mÚØÚ9qL˜t|7®G¥ºêPĂÂÂD@Pmùú|>Ÿù;Wàº: ºV©­RE8!¡@¨ˆƒ®-:ǃ²²2A$é‡jÉeëëÊ•+&̉ĐqC•&(ŒrDàm-F—öAÍ=77W®\Á¶mÛlm9‚{î¹÷ß?î»ï>DFFj­íœ@ĐW›Ï0 ‹ơ‰"¦dđáÀÈÍÚ\çṛ‡¤‡.Éê|SéñÑG9=å :ÎE×É×¥CjhØi¿j¾ÇäWOü÷jïu{E”­æ*ª~pB̉ĐĐ`ê·º¶BK☺«ÎAÔïm\‰̃ĐöN¢,å–tjo$XävI¬œ>}:¢¢¢°zơjqƯo¾ù&¶mÛ†?ưéO6l˜MZ“87g@\̣ôJÛ8&·.q9^̉Yø½ ¶mÛ&öϹ‚$–è<üéµµê]²˜éÆ•$'ă˜è´-¡ùØNˆÉÅo®W¹ÍU×V7_É̃ =ï¿ÿ¾íL'~Sds"ÜU_r9ÁDuÄGRƯ‚Á rss±|ùr‘»@EEæÍ›‡¬¬,\ºtɆ+|’øJ%P¯$^ºtIË1%[²j):,,LËy¤Í—5tˆiăöªH)¹Ä¹.²…̉–s7„æs“ p:Ä¢RÄÍœ€–[ Ơ<¤Gq.é₫ï/‡₫DEEÙ­z¥½ÑJܶøơ çÀ غu+&L˜ í§²²£GÆöíÛµw–¦%XñêØ´i“MÇÔqKÉ́O­Œ>ŸÇÙ¶m›H¥¤ v2È@BB‚ Øu‡IL:H7@•æ*"sDáI§›ràáÆ§˜BiÎ?e¾½zơ²}WXX(J?T ’Œk̉¼Ơ0çdN¢ºtç&iñµñ+;.×××cذaؼy3† ¦EÎ ạ̀åË"ñ… z Ă@vv¶èR'‰XǤ¬²´´>ŸÍ5C³fÍàóùlPZZ*X:cµz̉§cÇ6®@ÅLbJîbn@C•{§oÜAÇ=Ư¨ºb9é4W][ºNJá[¶liûöøñăÚKu®8¥ÛyºéÁÜ0évTÓ@̃oDDÆŒƒµk×"55UDεk×̀†âN¼ơªàUéêáđáĂ6Hư,YN•ØúÁ`́ر!qM…˜üº@Ç=tw¢ưúơE6ƯaJE À⺳ø:M§wKN¡pcé®L>…ºW§đ1Ôü¨OµzªªªL.á¤cñ~?üđC›;gtt´vœÔ‰P9%ñ̉0 äååaưúơưGDDà¹çĂ³Ï>kë{×®]¢$è¦w³{÷îbÄ{nn.ÊËËmH#éBjQGÁèÑ£±xñbbR'jơ”••¡¬¬̀Ñ“‚‹#̉Z¿~ưDêç$.8$åNÈÅÇ Đ)B;qÄPÅäP87÷JrLÎQøßï¼óN„‡‡Û¾ß¸q£¨Ÿétoé<û÷ïo›“äh↘t¾:µH{xâÄ ±_₫¦¦¦"++ËF¨œüd©a»WŒ7N¼K={6._¾¬Ơmø]åèѣѥK$''[LÆaaaHNNÆ]wƯeç“O>Sw§É¹å_₫̣ÄÄĈ¢;L7Q.QVÇ1u‡¬;T ĐB¯Dt„„ÏMcôé{ï½×ö}QQ‘+œp£wÜÑÑÑøóŸÿl#zn¹wœ¤‰Æœvï̃-ˆ´wC† Ѧ$_gQ·\—Œ7NäÛ·oǨQ£PZZª5°|ùräääạ̀åËX´h‘x}âơzñÚk¯ÙÆX»v­éäf54 ĂâƒgyF‹¡j¨ÜE'>:‰³55ö e’˜Ëç­ă(NkJOOGëÖ­-ßWWW£  @DLéN”»V¾úê«"R₫˜b¡î[ÿëÖ­Ïœ;½^¯ÅÁÚ´iăx#á‘ét@âÅ_ỖÑŒ7÷ß?-Z„;w¢°°ü1æ̀™ƒ`ÆŒ€×^{ 111Z ‹¹sçÚ₫ö /ˆú7)¯X±Ât‰‰1ïĂÍàᔄ)Tă'TôS2Ö…2ä“)­÷Çï„ l"ío¼ªª*1–¾W®\± æ¼yóp×]wi×ê¥6º¶̉~HˆYQQ!2œ555–v={ö´YwÄZJ´,d2++ K–,ÑBUU6mÚ„éÓ§ă…^À”)S°fÍÓ5nΜ9HKKs½ 4h^yåËïN<‰¼¼<­¥̉0 |øá‡&ˆ‰‰Áºuë#Ư<¾a¡èWêo<àUéÅ?Q®^½êR3ơx<¨ªªç«p7 $Ưwááá˜>}º 9'M„êêjQ RHyß}÷™ßÏŸ?ƒ u9z–ªO'ä̉!èñăǽ>ea?¾k*N©săÆf›^½zYtN'I’đ̣IeffZ"óCy"##ñ̉K/á÷¿ÿ½H ¤ƒIKKĂªU«,́¿¨¨ÇGAAåP 1bÄ<ơÔS¾T^»v-¢££EăEΰ°0›“¾«ººÚ‘Óy<|̣É'âaºrصk×H"9ô;é5lay:._XXhkûñÇ; ú4ß?₫Ø•(„‡‡#//=zô°ˆ´£GƪU«pæ̀ó,?¹sç"==W¯^Ett4æÎ‹j‘’"ç»ï¾k›ĂæÍ›]Eß;wOÚ/é),,ÄđáĂQZZj™r¢Y¸p¡™ ôî»ïƳÏ>kSx̉'#'ÔƯK¤~öÙg;v,;æ8á́́l 6 ñññ¸å–[pË-·˜÷–<²Cr÷ûưX¹r%Ö¬YăÊ):v́ˆ'Ÿ|]ºt1©•Z ’ؾ};***°k×.œ:uJ́¯U«VhÛ¶-zö́i±2;wgΜÁ={p̣äIí|z÷îßưîwhÙ²%î¸ăÀéÓ§qö́YiÛFFF¢wï̃hƯº5Z¶l‰Ûn» §OŸÆéÓ§±gÏ‘ë@ûöíѶm[´nƯÚ“€ï£ƒÎ=‹Ư»wk÷022©©©hƯº5Z·n-Zø>̀™3gÛ&$$ 55-Z´Àoû[ÜvÛm6WLơ>}Ë–-3‘щ˜?đÀxøá‡MX¡>È4(üèÑ£(++Æ ´{ÓªU+ốÙ­[·6 Duu5Î;‡½{÷¢¨¨H;—öíÛăî»ïFÏ=͵y<̀œ9ƠƠƠˆŒŒ„×ë5‘8**Ê º6 Û·o7×ô‡?üC‡µEbÑk«fÍá–[nÁ¯~ơ+ËKñÇóC ‹åHEr߸qŸ₫9>Œ;v˜Ü)<<­[·Fjj*|>ŸÙYóæÍ-Åó ji<¿ß£G¢´´ÔĐ^¯}úôAbb"n¿ưv â«>¹KŸßïÇäÉ“µac’x•™™‰;ï¼À÷é-Μ9£µ r r›6m0xđ`†‚‚œ>}Úµ­úW!ÊæÍ›EĂ’tb|̣Ism3gÎỖ­J†4ºÖƶÍÈÈÀwÜasúæs­¨¨0 í3!!:uBRR’å,W„›å[o½…ăLJ́âøøăĂ0 œ={[¶lÑúmóơ©}Qăœ={ÑÑш5çzâÄ TVV¢´´Ô¼æ‰ŒŒD‡Đ·o_ñ̃Ÿï•™æÍ››HÙ¼ysóµ &nÅ5oܸa¦ŸPéh̃Tª&N7[QB~pÔ#‡§Ÿà.tÂø|>s̉ªoµÁÜß–R++ÉÛĐM¤›fY“"2œ(_PêE=¨ô@‰Ïc£ÚJ~ÆÔ•Sbêm¥æJÛªuJ¦zµ¿j?Ơz1Uk¥s¥îuôÚˆ{ñ;Y:OÅÔK×IÇä†Ư&%’tn|LµGбèÚÔ8 ö8\sfĂ]*ùí‡Cµß !%Äôé,Méxê ‹,üC€-E&úw*̉J1 عWˆbÄ)=L®¥Ö ÅV̉`VNFä»/>ÙX+°[[åVr Å›E7'·ÿ;Í•[ø%½,/q,̀|’›'…:W ™¤«"§5ó}§ă‡̣è®TŸRxÎK=>[÷Úñù|ZcơG•ăóù,›¦¾áNçbÙS‚ ƯÿÑC­¹Ÿ¬«çüR.¹Êơ m+ƒîÿ4>U µsº*q»Ït"ƯW®Óư’ÄY®&pưY’¶hºI‚ đGϪÄè¾ñ3ă‘/º½å₫ÆœøP À 19‚ªư÷q™s̀f͉47t́D±¹̣̀9ŒS̃*ääJ¦sW¢$ªĐÍƠ ×O©ÁVm85TI„…œDC>WnP ‡LÏ–s7 NÛR)I&t­œ€éBêøY†"I6¥_RØáÄ™ÛJ(ÇTj–î,$;‹Ó\)÷äD‰Â#GLNP}7S”DΠIŸ8פ¢nm”…n„SÖ:ÉGU2̀HîV\o墵19'àăĐÍ×µ•¼Tø¸NÙư§•D;\Ü!‰_´­jÏÇ¥gË×*Inâ,×¥-e˜‘ÆÉĐFû ƒ65H2¶PÄRă„ŸŸ'°\ä•|Ư¤F]2Ê|\·¢̀0 4kÖL n•.P©1@˜Ơ¯¨øª²̀ñü0¡¸`9ù±ª¢™áÔ+Ư7)"#ƯÑv¼­¢ˆ\wàF ]nX§;Åúúzø|>1Ÿ­„ÔHDÏOâĐt­1ô%îĂo’ke¨§ßÑư ë§7̉Yr®Ö'ßW̃̃MOæ6.)H̀Ë„ở0 ›1% ¡ƒ;‰Å-ÄƠ`¯«CâT½‰_:ëb#\Ưx?N™ªb*Ư‚ùƯ‚đûªP¬o¡DλYîtœÏ0 \ºtÉVRNfll,ºtéb¹G+((ÀáÇñî»ïZ:&&#FŒÀ¨Q£φ¿hÑ"L<Ụ̀û×_]»vEll¬ù»̣̣r£  –ï»té‚üü|ÄÆÆj¯Ôt•Ó6n܈§zʬË9v́XŒ=Ú ”ˆy~~>¦L™b™Ă¨Q£̀¢ÂR@å¾]ºtÁ´iÓœœl₫nË–-X´h:d!>S§NÅàÁƒEé‰rNÉqÁÂY Úu=º*Ï¡è n®_º+nˆéå®ÓÜ2b‡â÷ª«F߬®­S|'Ưÿ~ưú¡¸¸ØüÛ̉¥KM€Đ‰ÿ†a ??K–,± hll,̃}÷]ÄÅÅ9º†̣̣rQPÙ ¸(§~W^^AƒÙÆÜ²e‹™ÎF_ùƠƼyóđôÓO›"̣êƠ«ÑµkWÇÔ%t÷̃{¯9‡ŒŒ ¼₫úëâYpDVßr5J½‘#GZö#??ß< ®̉H…§$ÉèköiIDAT—×-"^̣³”®Bx4…î~FgÙ’îđÜÆÔ¹59ơÁóµH}éî_îe¥>t–iƯØns íxÊQ§LëỘ‘GÁ¦M›,ÅĐ:tH[$J!›”J2¤Đđ§ÈÈHØ8ª*Íî$I(éfÆ &RÀêƠ«Ñ­[7­•—¦ÇăÑgbẉÚá˺×Éo4Go‚I¯̣ëRBè"j¤uê¾u{C™¯Û̃I¿Ó=¼Ü‚”W&** DRR’QFŒ .ˆÉ¡œ$ ^ûCJÚ…… ZÚ•——cÑ¢E¶øE>î† đÀ˜íÆg"%p©đ±wLLŒ…̣µẹ́úêB»Ôï†n«r₫üóÏ[T?]æ@ÉeQ[T(ưÍ @uæóP.T÷º]LKZB7„̉!Y¨éÖN×ạ̊ºœµô° %)[¸p¡s9RDh§ÂC<æ“–£§¥́;v́hà-[¶ˆÈLéi2常8äååYJ!rÂÀ ưûˆ#ëzm%!&¦uZ:wîliSRR‚/¾øÂŒ1ÖƠåáiElye‹ nêßc]mL›Æô÷ß7‚đc_§¸I*Ḅ̀´êE؈ˆLœ8ÑP7n´R%¢}êj—¨W`iª¯I“&™†àû„q<ñ¸®đ•. Ư#<‚Ç‹ùw¤jkª ¸êŸ«y«ê×ô)..¶™Ó}” )äô5Æ,ücs{₫ØÇ)4ë¿ÙgcÚ₫˜Ü¯ÿíGÇ-iZ ¸ü‹z¥¥¥!&&ÆL ª Iiii–Eúб¤:œ’Ÿ-}èù•¿ÉÈÈkª̣€i§+¨áÇcÚ´iÚ:0’(«2H uu;U5nfP ó¤^K¾ÿ+ ÿ_y»†ÿë5;•{àÜCçÿË‹©>øàƒ–Ô¡Ÿ~ú)‹‹MîæVE¥VÑ¥Ó í)¾OlÅKÉ«oW®\i+11ÑRiÚ)Û»ÓƠÙsÏ=çx À‰D|x¤D°€%1­Ô±̣¡éùÙ=:=HJ*,ùẠ̈€€´´4 bß¡Ue Ưê±PÑŒëM´mee¥-ëb¿~ưl÷àaaa¶‹₫ôôtË·Ë8ƠE¡Ä„öÿÈ#Ø®TœŒ?’NÇ“²IöéÓÇ$:*"KYƠ¹“=·ß4!æṂè²}óđ.)EˆT%ụ̀åË&p@wBL''ù°aĂ,ƠăÔ8Á`}ô‘M4¤ˆ)9¼èüÔ"îêDôxK…\;v́°´éĐ¡ƒeÿxHÎ…Ơ ²hé›9ù¿ÜTÏï₫`À€–¾hAaj´ b'7₫đ)—™8q¢-ytnn.ZµjeËè÷û-ơôïßßV©ŒœDi³}(5R¤B¶ê?¾-'ï˜1c´…¸ˆWĐûÉ:fÓó¿£c̣ pj ѹºY{©Ñƒ‡zÑgö́ÙHHH°]UTVVâäɓصk—›LŸ>‘‘‘6"¢Æ9r䈨³Q – >̃ÜñÜ©H­›ë³j΋/Ɔ lw˜íÚµcmi`A¦©Tó&2Véü¥>¤ n²ó2üY³fMÈóïÛ·/ƈˆ1¬”ƒSøú$ÏIÏ”ÖË34Hâú±cÇđôÓO£}ûöG}}=®^½ơë×[2ĂGDDà¯ư+RSSµ”hƒA 2̉6Mˆy“qSÉÿ×ÉY—sUuܺ°°ĐÆM ĂÀîƯ»Q]]m)QXXˆÂÂBtèĐăÆC»víDçé¾”ë˜R|(Ej]¾doÏ#¦̉ÁËÊÊlâ¸*³‘>}úX M\’¡º½[©÷&ļɑ“sJɽ2g{ás2ªƒ©6½zơ‚×ëEvv6Μ9ƒüă¦.VVV†Q£FaÊ”)¸ûî»m—́ºûN 19·”®i¤l4»ƒBH‰cFGG#//ÏtÚ ×QTTæb«D #˜¶ÂXM |󋽡¸7̉ªÎêƒëc<¥¨Nד¸@Û¶m1₫|DDDXÚN™2eee6±Y*#/ƠUe–8¦“$D§bĂ:¤ÓG7µ¤ 1!†"C¿zùÅtt´È…uœLºOäÛªU+[\$,Z´È"Ê644˜EèóÉ'ŸˆVQntr’ÜJ€Đ:3Dшün R¨—®«e¾MàûË1éâc·nƯ*^MèréŒDNSư®]»vèÓ§¥ưÉ“'M—~ߦMËw•••E{œRX̉!¨S¹'¨K•B‰(fûoß›Ưñr/“üü|·¼ë®»´‰µtW N‰·è›jëăäÉ“¶>h!\ơS•rJ¡€ºP¼PöƠ)xŸrËPc‰›8æ/Äø —””X̉cÀĂ?́Ê$ÉƠ-;®_ơ]Ï=mßmذÁvWë¶åÙ£ă¤NHéæ+ÍÓẹ@4©ÏÄnáM üË~xô}RR†®Ơ§BƠi QRåêvíÚÙ~ײeKdddX~·iÓ&mZ˜P .êY¿~=^}ơUñÊȉcº!%O M‘R«UuAue-¼^ob₫’ŸG}Ô’t*66Ö–e 1ÀJOعs§¥]«V­!ö‘‘a±ĐVUUaÓ¦M!K̉w/^ÄO<ñăÇ»&os[§S– ÊUá[₫̣̣ 9›KÇ”±cÇÚrà,^¼ØLÿè–V“ëR¡ÔƠôz½ØµkNœ8ai¯²ôIsÇC=dù~Ù²e(**P̉{éß/\¸€̃½{ăí·ß₫I±µN©w$NÙ¬Y3KƠhÅ5iÅqËÛÊ¿,óÊ•+?~<̃{ï= §,))1s…¢¯I"œSFDǃ]»v™)#ƠÓ§OôíÛ×–F…Ơ³gO<ñÄ–v³fÍÂ={BZ¿ZÏŋѷo_̀˜1Ưºu Yÿ …êÇI"¬Ä1¹³Gb₫Lî8Íï!9°–••áŸÿü'̉̉̉đá‡9r$:„¨¨(1ÅOÚ»w¯­ÿGä<}ú4̣óó1mÚ4K»¾}ûbÚ´i ÔÔÓ«W/<ùä“6äœ9s&ªªªÄ̉ ônôµ×^C»ví——‡!C†hËM¨ä_ôyÿư÷µÈ(]ÁH™#‚rưRW Ỳ+Ûôüïr .àïÿ;Ö¯_/~…„„ Àq.11ƒ ÂàÁƒoµºTaUµµµæÏÁ`ÇÇôéÓ-ÛôiÛ¶-Zµjeá<WëĐ¡ÆoΓ‡FÑ»IäƠƠƠ˜1cN:e»}ûöèØ±£‰555(--Åûï¿ääd¼đ èÑ£‡¶ÆJCCæÎ‹gyÆ6ç 77·̃z«jFƯ}>Ÿñ(g”R‘Jå3±7=ÿ›Ï+¯¼‚}ûöY”»±I8”;ù|>$%%áöÛo·PmơHq‘~¿“&M̉êœNzưV‰«ưúơ³Ôåö¤”(lu7O:…7âÔ©SZBiii5jºwïnÑçhÄܹsm–]]¾¶mÛbèĐ¡¦{"5ô<û́³đz½¨ªªBtt4~ưë_#77ûÛß°qăF´hÑ{÷îŤI“PTT¤/#ß„˜??Ư‘'Ưª««Cmm-jkk-é"i…„Í›77Å*Z‘§hTíư~¿%UˆdØ‘b)· ³q>&ÏU¤«¼&]áTVVâÔ©S–‚W;wÆo~óËz%Ää!`@QéA9¯s ‚Çåºä}÷Ư‡-[¶ Y³f8zô(¦Nà‰'Àˆ#PZZC‡iËR4E—ÜdÖX8<>‘»ÈÑï¤$S*,^¼s$Q•·hB*^eÜ)%'7œp«'ơ5U¿£œ-::111¶êHĐBÅ<ªDWÚO*³  ™ă9€U[úû̃½{ăÀ(..Fûöíqö́Y›@×Ü„˜?sd 9uœ—‡Lé,±*˜—>(ª¾x¶87¤Ô•¥ă1•\s* ȯLx&©°-oCR2ú¨Lw:ÿ[ a|đA >DAA¶²[Ǽ‰T²ˆJ%ÔC¹V }̉ïuỤ̀8àÓ`c]¥k)«?Ef©=ç0NÖcÎỹYơ7§B»NW"ºrđ62—̀̀L„‡‡ăÖ[o¹$}ó&à˜RqeÔ‘ªmSÀä?K5)Âpd§µFyÖ9Ï–·nMRØGn)´ŒsjÎÑ©xM¿ Å£I·yé jmåDEơѧOGNiÙdüùy¨Ñ„(h9Ø̀/¿%.¦Ó±8'’CªÂ‘‹z¸đ̣‹N¥ä9'¢º­T ‡#“Ö%94p®I@´æˆ2üP£».‘*̃…B 8æÏØĐĂEKzÁÍs̀H ¸$.ªô/)£, Àêï*©1µâ:U}£b2/€̀Å`)-ˆ®ö‡.{¼ù"éê´â¸”½ăVP*Ù„˜7!‚*ƯĐĐ`1ÔĐ<4Rx“Ó$ɺª¦a¤uG¸̃'UˆÖéuü[eé¤ÜZºÇå§«RJ•9)(\ªÁÂ#I”dà.憜MˆypKe!äH)å\•ÄÉV¿È +”CpÑR‡¡´¸‡ ×Cùå¿SÀ´¤óI’€´vn¨â¢¬”;È 9®ˆi7¬ %­™àx™nƠäN’G‡$¾¥ˆ©8'Ïø.ƯIj̀X%!'×–@ë,×\bĐY›¹±ˆ‹éỘ¬gCMÀơsALÏ/ERï/)95çyL¹øÇ "NVZ'±NÇY•(©–r®Ăé º9H̃ÉY©úµ[ö]Jjq¦k•T©ùá–?'QV!©ñĂ¿ơ¿t.ÊSé`ÊSqQ%¤t»já\…'OÖûuc:q7‰ëđz–Riw§L¶¬t„‡§x₫X~Å$ƯÛ6V¿lº.ù^™đ¥̀t¼t€DbHÈ)qPÉh£KÈ¥‘CƠkƯt4il¾n.NK„­±kä”?H'º7!æ/ 9%ÀÔqL§̉!¯ô}(I·¸…× @Äi]Ù<]½'®­“$ƠAZ£›óS₫˜Ï.æưN;IEND®B`‚commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/000077500000000000000000000000001410126276600250565ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/AbandonedObjectPool.gif000066400000000000000000000540651410126276600314130ustar00rootroot00000000000000GIF89aÄJ÷ÿÿ{{{{{„{„{{„„„{{„{„„„{„„„”)”1œ)œ1œ9½½½½Æ½½ÆÆÆ½½Æ½ÆÆÆ½ÆÆÆ÷ÿÆ÷ÿÎÿÿÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,ÄJ₫;H° Áƒ*\Ȱ¡Ă‡#JœH±¢Å‹3jÜȱ£Ç CI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªƠ«X³jƯʵ«×¯`ĂK¶¬Ù³hÓª]˶­Û·păÊK·®Ư»xóꕸ Aƒ¾€ÿ¼€đßĂ{+^̀˜fƒKL¹²Æ1[̃̀¹³ç‘7j₫Lº´éº£/Ÿ^ͺơÙÔa»M»¶TÙqÛ̃Í»7PƯCûN¼8Mà…_μùHä•;ŸN½:_ÈÖ³kß~ºDéÜĂ₫‹7î="øñèÓÓ.ñ¼ú÷đ?³8?¾ưûzë7Ô¿¿ÿ·ü-ä̃èV€ !hà‚ j¥ B6(á„OEH Q¨á†\àá… „aˆX¢‡%r¨âI¡X‰/(âŒÀXc²¨ă2ÙXă‰¡h#Œ̣hä‘7 Icˆ7^¸d†HF)e’)₫裕OÊ8å–\ºÄ¤j]†)fI_Æ6æ™hff‘l9¦éæ˜öơ朙v˜x̃©g|îégŸ€₫)h „jh¡ˆúgaˆ‰”ca %*©¢“VJ饖fé¦vjèt2ÔÀl`ꩨ¦ªêª¬¦zª₫¥Z°ª¬¦–j*­©âzëºÚJ«­»ªª+© [ë«­&«́²°ÚfBy&-£Ô³Øf«íª{ª·¾~{ª±Í ë«ä«A±©Æ:k¶ »í¼ô.[d¨ ˆ«o­ạ̊»/©ưÚêí¯Ư₫ ¬¬¥jpÀª+đ¾LjÁKÜn¿g .Æ—úlH ”¯¿$k̀ñÉ£̀oÅ_́­Äñ¼q¸¿ºđÊ6—̀«¹$/¼ñÎ₫₫\²Đ&§ltĐü~Œä¨/ëœñ¿N[\j·Ü«ÆMG 3ÅG#ưôĂÆ¾ÜôÓdư­̉u42Ôcg½ªÛ Ç-7̀ú̃\«Ø̀â-ó₫Ź̃½²Uïư-®¿=7ÆQĂÍ7Ä mäÈD›½8Ô‚kp̀‹1̃€#ÍùƯB[pÎd+Nyä7₫[é“;múĐ­· +᛺ØvÇ+đÏ7kÍ:©,ó=µÄ´#₫úï*{Mê½têź‡G]đÊ@K]=Ïá₫꯱oª‡¨vo;ßÓë|üë¼;̉ÚçG<ÛĐ ›ª‡̃’l¯²‚ß́ô1Ëû/ư¤óĐúg´©É®uï{^üJƼ9åKođCÜïæ/›éÏxµûøhE8®Y¥̣à}7Bû™Ï}èó—ú@²…0Ä`ƯH…¢Z/wÁ̉°ôW¸Í} |₫ḄP½&:"°}GŒáĂV¨#ç!1‚¬U₫6 B xPVƯ3 @B+b¬s"¤Û߀gª̣Ñ ”àoÆD´0†j„ă ˆ"d]0a₫³˜¼,èA-bO\ê²b©XŇu.|̣ÛÛçÇ$«obŸÓȸïQq‡§ªá÷6H-¬“R¼jBA†̉CƯó$!¹˜I42̣•‰“X!“ÀZ.’’$ËŸé·Êö2„Bʤ({IĂ`rR•¢ EÄ]’̉”Læ3ÙÈj²b³TÓ˲Y`”®ü&)8EWV±•Ưª"hƠÇ+Ó‹Đ+ŹÉKÚJ„ñ₫̀Ü.9ɲqu¸´e?_'¾fjđ ü2(!ăÉLgô†$!yuATö’‹́tf*YyGô–ÈsX69¹Ê“ƒt%1ó9Nb†0“±b&À”ÙRVjPe¼è=ш°"B‘‘©Fœ×Mu|7•g;—ZC^̉O©¨S¹D‡J´˜Àüd0ïXUêQ³¨&͘P5DÔ£~ơ“5µäKZÓªƠ‹á £[½¸Vs̃M®g cN»ÈMÖÙj¬)k_úƠçññV hb­úÔ¥Fµ±w“&V‹‰PÉJ”—ŸÍèQ³ZÓztÓëYTI3¥ÆŒjR‹ÉÅd¶˜¬•₫©Z“zO¥ú²x\“áO­G*À^„¨¸,íGÈĂf’̣¢e(0O U‰Ö¶ú2UL†ª²p’kayÛÛP h¸Û­wEAơÍo=³æ&/-ÓV₫s˜ a3́úz`u ̃Ï̃·½x”[yƲ.ƒ=›oz§ÇO³¡´ae˜o%$Éđ†Ơ]̃+̣&¶°<>-·¡kđíâk¸ÂB0¨ú5±…W|* P_=M™[†2øROWâ›WgF*ñí¶³,®$À&Ü ṃ·¿3̀q{'bå…‹ŒÎ\ïr:Áôf7¸.3‘“óc¹g?£gƠđV?M{­*œ₫Ơ¥Çryô¾G®¥ơ¶¼ ’~ÎOö\IÂ`5ívËađ |5€¡¹ËºEñO€ çƯ6{­̃H·1ƒødóñ”%m.p­Œ@îë›MW±Đ¦i¿₫½åË íctù2‡cÔ®¦—®ª±:ªÇ‹^¨á—ߟ¼Qx¾²°gÜb́› “·́8[s×X³Û¬:ïBKØÂÍ.Å5LÊæ”¡3œŸM¡™̃_đ§ª^ ¢}b§;9@Z p£óyû¥/öî‹ê­oÀ¼»Ư€8½ñ­Ø{ßvÊ÷½~…#œáư>¸¿o€K\âñxÄû]o=9Üâ78Â₫ yË[NÖFˆ#¬]}åL°Å5wÉ6JU„ ÖƠ¹¯9I ÷Ú'+÷j•Å8únÓEÛvèÄh=ŸúvåÖsÔ+-t¤¹êL¿úƒ†,S£©Â©f¹̀(ˆYèNw¹kêV9ÚĐ0׿bo´•5@g¾0̣›¹.›²5¼í²=ùÓ{Ÿô`ơiÂC:ïËüûèr•c;îp+ŸDcYÊ*öœ¾„j3/ÛЬ{ù³dÖrơ†æOÎ…öû¹>ơ®=ú•¦Õ¨{×g·î²sØï,8̣ªew¦ÚªWeÂÜ SơO\+ÜC¤¤>;º"§/ÀêS¿rn¾á¬₫Ïưëwÿû̃?øÇ/₫̣“üôôú™PỰö+ª7_¦·°âêỢÎäüÖUüåúûôG=·³cØ—:´0´Ó;/6e¸€T7€Úç€ X€X×8€è€ßrê'·|&5©L3åv¤¤I¦ô{Û£‚Ô¥W³÷y@Ơ|úƠ6ÀJp•,Gx²MNfTx{W„”ÓlGȃơb„i¦-àרƒ»Ç*COÂth‰G„2mUè«#>́”ƒ¨̉Z«F‚âT|€Äi¦RÚă+;hæÅg¤#fvS>Æl‘£a‹Çl|¸‡D1(&o¤æwˆ₫ç~i'D蕈ˆˆøˆÑ'3Î÷Ff*O8ˆZÓ+cS}TNF$iơ·3ºSAnµu€ăb¨3hæv–BÎR¯§]"…±6Iˆ„\È„sÄcM¸,=؃¾HŒ†4•è£R0@7FS´\—£v@tW'ˆ‚ƒDnAsN6T[ÚX|´ˆ&8.°he<'mG{Ê—4¸X-„züEjóˆAÁc?€øĺˆnûxB”“Œ ad`*ƠăpuN®uF­ÄS6ôZç¸2çäV°¸ƒSûg€êtd²èhÙÖ‘₫è0ƒ&º¨zíx„ IuüB8$Æ‘' zî#₫POP¦R!t)•YÂtCWe‘»‚‚vd‚:ƒÖ,íD‘è‘Ù¨JeøZ”V…₫Ø~H•­ç1ïH{̣o‡q"—pwo\™q[Éq7-ƒ¡p–dù•ü¶pe¹q —–pÙp —b9—₫Ö bKùjgä“úôV¨ơ7;ÅR˜dIF‰42UJm•Ṽ#6¿2”á‚. •S‚"y•Ñ䲄é™Ư÷™¢9ÛBAÉ%ƠUó³”7%0f‡v|¤?ÖUH ¹7êTQ3µ“9i~ăørºÆ¹Ü„M)2({ÈÙ5ùX9한­wœÊéœĐé*#©À%$0‘±₫Ætkh™³7„ĂpØb=Ôœ+}M¼•gÛé”é…Ty™é–1ƠÉ%%Ơœx·=³̉a=ö.ÍB0Rä2aó.½“‡x¹– 1™B s ‘/å!`SÙ‹ưô›Ix0†"Zh…ÍmĂ¢yRäé ö±MT>«x,¬ÇW[3uäuuˆToØb$x̣I¢‰æ,£[@›’‰BúˆM8†¤H:¤J¤Üg7ơ¹%%)3ø$.#y>Ä?Ôœ4f£(_Ü)_.j™µ( º:àÈ”3Wb¼¸…Nè¡™£…¦¦JئÂXys§uÚ,&Û4=‚UÄǸé6₫œ…4XvTºmº;/çZ S5»I…R)wL·§â7v¨c¶Gí·œP'@&ä©|8›*£Jª§z9¢WœºB€Ú1D‰Te7S-‡ú™$sƒW•)¦ é́æií’G8:¦ÛU‹­È†’êhrç-PXœA·3€€j1¬„¥ó…9ĂO;W;H˜O .:3vœ9ÊëÖ'–7qrw©–q©•øÚ–t9–vùqaÉ'hI¯ri—₫ê•û¯ưz¯nÉ–˰ë°[±±‚Qœ8ÂÙ:¥h›»dNê´VÅTµ%Le¨Ølu%₫¢"xV²ô]D¬¤Y³ơR`Úg³:»³é24ƒEH£…lV<²ö¬₫%g ʦQtb–úN„.ܵ˜í„˜*µ˜EWăM²e´Ü†¨53nƒ0»™¸ÂÉ0Ưµh†¶ƒflY4F¹4u§¨’6C:Zz‡Ă₫ʼqµÊÊ©ÁIM¥¦±³9²;T‘ï¤ZV´S¯b‚+ØcáxS™å-5ª/v?×Dåc̣ÛŸzôbbd3ªJt̀û¥×Ă;D® lJ„æ¬Âë®Íj’ó³R²M*t:6öS<À_/ƒsŒt %<¥8¢÷[@o«¿•ó§¾Ê3ưÛtµÂ«9:L¼©ƒc,ÚE¼)¹½=÷’U¹%QzÀØk2ƒ–A…Æ;º”Àû`/e7‚:…ĂÁ0³ºѺŸ´­tơŸù̃L«À•½ƯîÑxŒ̃H´Ùf}¹Ä‹ 6Zf}Çï¼’¨z¶–t·,»À̉®Ú+\ñ=£Û,bdi=eyźKĐ5[OÛĐ³Å¢h›iZO0³ËƯëͧ³Ækn¼c’Ûˆf¼;‘…;±¸=³<Ç9îÙ`³ÎmHm.^ä™-aë;ñ¤Uđ—‚0Ü%xn­ơÚỚKs•€À;§ ƯD'Ư!Ó«ƠƠ-úG«'·ûÓ¼qÓÈ 88lZï¬Ơ®̣œbÂRß‚á+bdáƯg₫kÖ3k~ÎFT^Úi®Ó2,­G,Ư†¸mäXà9QV(2´ø˜¹ërf£¸ă‡…ă–Æ»:C~$ukGăµåcíßsc•¬ºgyFc ˜›}¦U»|k£+8'̃¸á$t%3Óö[äeưè„+$Rͬ₫»VÖ̀ÜÈ‚…4”†e˜̃¹ä>è¦yºÊGÎèvÎ/x®"£eÈ£[Dàêµ f́#ŒÎóŒ3Ù7çZçÿ½¸,ü‰’.é•Læ¶œ®o}û}ÀF:u|Èx¦gkÑtꨫ̃«>3é*ă~†Ë™|ÈÛ·Ư .y°3<:7wêËx1®K’NEæ<̉ÊLL:₫Fö§ØKi7̀½1ìâƯdđØÎåK·í$•a.¬EÚ½ÈsµÁeÔæ0ît1\C๠5ÿ^á,,^ÜÖN!ŸÓYôÜ*µy¹¡“y˜¥Ÿ0í^·2#ß#ƠR_îËY´ĐÙŒT¯]W3è~“R@ŸẸ́KÑ9Z¦Æ½‘ÎĐ³+™“×>¹#NÏ §TÍÄ/óa/ö,_ÉrÈ|=¬à4µY‡ï÷ô¼çá'Ü{¬Öa÷‹¤ô=zPă§ơçቿºK²H N€ Äó̀˜\ïøÿø/~‹ ¯˜ÅÎTE¯Üí;â§…vĐ”U°Ÿ´öw‚À₫¸¼„Iåé€û#ö, 4}?>ơ÷v.HüÊSúƒÚ*>”ÇU2µ×=ç1ÏûíÏ@Ưa–2ÿœRÿôÿöÏ)Œ́#´ê hà`ƒÀƒ j8˜Đ¡†%„¸¡âC… 5\\hĐ¢Gz¤¸ÁÂÀ j¤ˆ’!Ë•*c¾\I³d͘2K¾\ĐÁçO A…%ZÔhÑ5´Đ0åË“*_2|óæTœ ›ædÈĐăV‘,íjU'L´ioâœÉƠm[¸låª=»–®Íµ { ]`Öïß’UµZƯj³)^°2CÉaqÊÅ›t\3¥\¼#æÜyCƒ£₫¡E‡î»1°È—?&ŒpiDؽ|±imÛ#YËFˆ›7­Rg;;s]äÄß̃½ºwôsèÑ“‚]*Yfê꘾™8xæÂ/¼†)|¢ÅË«Á–]¯ïûå̀ăÊŸk×~̣ø÷m̉Ôïơ¹ö«¯,.0M*¸6Ăʤ«Ü A³Ú =₫Ô©, ó³JÀ´8´‹§èB-)ôœj°Øºà$8¤`”($¯¨M·.’­Å5ïC’́»ñ,øêĂo¾ºtND&›́`º ơ›P<£,+B»̣q;±vºlÁwz)½˜ª’r@ •C̣H#Ơl3M·ḷ/¨¾ˆ₫Ü0¿ ×´Ó<û&›±ø°Z̀Ñ#p£ ṃN=ß[̉I'ë<«ôhlq!k‰$̣"O][Ê«NYlQ"ˆ:UơÔÜ|±K4ß\³Èë…ôÖĐHüˆo©v-c›ND÷¾̉iÊSKôMƯÆ&C|Ê7%\âT”ˆDO¥Ê…(Q"(¹¾.xʘÖB¶-©0ey#™î¥”rI¦z̃2¥̉1¶}Ñr!`CD7‚ud„1j jT³sreˆ¼Qơ¼ç¢Ù„gẃ÷båĂ fˆ¬ÛGÄà6 €c8‡¿,̉5KdevRUA$ ¢l¥(ŸHJßç~¤2 (sÖG?./d₫!E²¦î ~:Ú[Àơ˜"Ôa”_d¦C‡aR&Àôăs ä•¶&5Âáȵr7’ ~{C&‹°£ªsFS#—‘±©G/j²x‹’'ÉơÉ?a‹±Tå@;rPÓ qU?kaÏT©EƒbG&¸¹a¼\¥¾ne[ëÀó ̉® Md6Û[%5˜Ñå‘×b&´ôèË{JƒÅURˆæJ±QáW#jd4JfBt‡*Ô]&mxÚ$>{˜Ï¦jǓ٤j¢v¥˜ˆ¾² Q¬å*³øU,¾̣•3"å*o9VV)QÍÙ¸ÙAœM°£ óT‹îG=Ω­n?ă₫kK(J ‰±#UgS€Ê n4­iLB7̉=µ‘hKØ)^ÖSŸrâ;{e<’̀‰Ơæ>K»:₫ø3¦—äå3“ø@2‘«Å_éhËPÚ¾3†ëÔԨȲµ>o-`Rö•Đ2>($;Z :St©Ơ¸h+*lßrTUá’V»;qK]]•RkˆMĐ˜Ó!mdơóĐ²Đ¥̃ErɈC,TMk_̣urrÛ¥Ï8¼c½­R!˜E¡’5͘l|ÑUÁ§Ê£ŒÅ^<¢·R§¼ *a/R‘)&“_»Đê[_́^’´‹ư®“lzÎÄ §°:¯₫5}¶(án_l’€î–Ƕ¿Cæ¤F²5Ä ·oÁ%Ú̉À$ô@ÉfÎ- ôïz¤`Ó™e\\úçS5à]× ±hÙT™EúQ¢*’‘j‘i؆YÅ)æVÄZ̀$º‰%B̉K•óF¥ÁÄ̃"ZÀøs0c=YuC–ó}#́Ô·‘NüưSCê`¬=¥*ˆfăîE¨ &zxơô‹b7M˜¦u¢̉u ÷ÚˆÜu·5œ¡ßVuP̣̣y'*ḲvéLéæÜ¹IÆ•lâ¸s(_ ÓæU€bÇ¡ëJë}4S³KdH/§BG₫Ÿ¯ 4Ÿ®íŒ~&ă±ƒü”®fáÅ@DcW₫µCí·̀r#vG§&LĂ'`WYëzơU?Û°@̃!Á]; [:Tz¬Ư†©ïKÊ¡₫ö˜{`8bP΅ªé«O!G8JÙj€%xØåXwsV2rÄm$ºÄi%ß9¹µcº•yW-®xŸG§§QøÊS?:̀i¦ ¤Ơ”–Áă½½/+\DßÄMrˆ·‡üÆ4 tĐ¥¸“°só'ר餉̣kgûÚƠ¦Ÿúи/@îpwÀ0÷»ç½îy¿û̃ó¾üưîvŸ»ƯơNø¸óƯî{7<àxÅC~ñˆïûăïwÊ#¾î„o<â9ùɃ>î˜oă₫ÿw©û„ØÍnÔƠîÀc£îi•ÖÛSt˜ĂÙæï5|z«é­y¤¡ÂỪVƯ$Đ́5$ Å#<¤ßä†htưđví¯]íÅKíPŒ+moNöÉêƯÿ].ñC9½ô “U“Ơ₫̃ Ư‹ÊùÄ`'•"ưvpa·xFí »?Năès4›33:àó&ëX+Çr¥†ê­yr!:¥Q%́©+¿*/eB§ë 9|Ú>´9†PŸ’‹¿VÓ™#Q6é~¢A=qßK—•»A— —ú›› râĂº)ÑœĂ I4̉I¾sAĐ̉¿°@ÁSÀ¶ø½¤₫˜”$’¢å8¤7 ’å Ă1ª")’i3¹)\Cñá’Ë CÛ£í5‚{©JËC‹: xS19[Aà³—ÀJ«[ºœr¾ßଘ®Î!¤óx²€+¤Ô¾ c±+̀•JįÚ"0|ÂY‹¡fC£¿Á®°,ADrăc;7|Å—‘“ưº’Ë[ü˜á—[ÜE\äE_́E`üEj;a F`lˆ¤—ûó :©̣3đ,4”BR›¸½5ÊE¥¢Dnt+¼Dï3"PÔX¤ªàB3$, b•åJ4v²"Ó±Æ=́ÆI„ÅÜ‘4: äC¶K#?]₫D€ä\,HHÙ»Eƒü˜ ÁÆ€H„ÔUË(ÊÁ 4×J§Œ8¤Ụ́Àj|‘÷ñ+¬‰ˆè3ë5W<-KG¤Èœ†“àR¢P±¬[³!à"ÉZS¢-: êk5ëó26LÉ6D-`ÁºX è±ÁθˆóŒÜƒAÀPJsˆü‘ü ©\‹dÄVC”‘(>K1³̃˜D’Z$4#3é“Ư‰5̃³Ç)üF–đB«&{sH;\‹}Û’Fq2Id¶G<Á ”B¡D;lÙ/Å`FhÚÉa¢ï!Ëë‰S| Ü™®i Z›8Ù°ƒÂÄ™û@q¶‰́¦₫̉/vD¤¨ÀÖpˆâå:: ‹Fº-²&j2)à1¸Ät•™Kđ‚¥Ḉ+±Élä:py£-qÖ3 ‰{é²ÄÇàÔ§îû’êÀ,k&ó˜¯ Ÿú¿óÈ 3#µ Ô’k3“,B¹>"«‹Ôô#ØyÎí¨ÍûLÇt,Ë 2Zk ½FW›’¥§D́C–C̀ZIâ o*¿>#A èƒ? Éé¡Åø£§2é6_“ĐĂ\Ñ’˜*+&ÚÔ­ƯBPàè"Í®u<¡+¢@¶ ‚ÁŒÀ@üœ*¼̉,- p€Œ€¢XÍÓÎÚQÙø₫0UyïñQÄ«ăD»àÎÈÎ{,”­d¬²@7£Ư1uƾ|¸|ô3̀“¾d7¥B¸ÜNáÚ¶Yô D¾ÖXˆ?•D´Nv„ˆ;ôL««SRdz¢¢º.ÍLbiĐWSÑ`R¢èJ)ÛĐÍ °̣ a˜,ƒ·Ëi é¿ßDIE¬P¡¨¸¤-ë ?K­@OrƠ§)™Ú¡F^Cª´cQítª~bLtG̀̉)GÍ‘½±$¢º®+¨àÊÍàƠ4+ĐA¾ØY)0]›aRM˜rUyÆ!u riÊñKr;¿ḿê“{ºc•9·‚Ơp₫œµ‹L¶ư;3ßZO\u$ú¨ó›s›‚XDDlƠ|½Sád Ơ‚Iâ·F¥M3L³́-èÂQƠèØÛ@¾öÔ)d*CÔÁ‚´Tlr™yÁ£x  X™-×s´ñŒ¿5Ú¡Ô`-8‚´Hʈu6‹ÀÔŒ¦†se¶ÔXC¥*Ü\°|ÆÁKzô½‘Xc Ó3éNœ5/¹ˆ1Ø‚± ÙXă”[[*R(µư›e¢¬)ơÀ´ÈèëËë¢8;ˆq퀛 M \Ÿ\¿Ü–Ü•}Áè)¤a×qCÀ,¬œÆÉ´#|D¹¬Đ2}É>ѽB¡Öt¢JÇb¦₫ÖKݱ£Û]Ûö(ªV„X¯%Z•¨Øik,sX(³¦ŸÜƯ"Ô4Bsb©LÓÁ[‘2»bE’%Y£ \ç5ÜÂƯT‹àC©U÷T/ô£FX1OrsOiÜ£¹ÑZ©üâZXAÚn¤*êSBÂH%ß$:¢Ke#)DyD™‘Å8ÍđÖƠ*ÚÙư"°ƯÇ„\NvĂđ·¢ăÎ́ÔÏDQrJäÄÂ8RƯ“•¾ư[¡x̃èåàÉb"Éø©ưMˆ§8ŸăÉ›Zà˜¹ÁÙ:̣ÖpÎ å#~Eׯ §¢ÀjƠSÜt̉ZSù ÈaÜ8Ơ«Ḷ½\<₫`ûDï´Ÿù[2¡¹ÀÁª N{=«­74ÚÄ:>Ê÷ØOÀ¥ÙŸ@ăÁµÙ&•ÔhF7¦$À)·" ̉Û-œ.I°aº> ÓÛƯ#ămºa Ơ¸±ºK'DÙxʺ©ˆÛÈh…%Ø¥%v$ɪÍZÉœ¯û¢á®ÊSÓÇ›iL@:Z ̣(̉»¬=1qátcU¦K¬"9?!£‰œÓàzÁ]ˆ(> ä¥-1²$¬»̉‘J:r‘)] _¥®¼ßîF ½áđUPüºÎ¹Ñ̀É›¤ẳ-Ô3Ă¿RYÛ%SYÁdf@†â'9ưâ B)[È`=åóĐ3G¿DCó}“'₫ơäkÙO^®´rËÚTKƒVl5ÙØC’ơÔøÈxVEÅ|KLÊ\â¬ËưÙ‚L×’ỗ÷́Ã9®{`œàµø̣dN¾çñIç°M™¤¼1äÀÉk=˜÷²§ĂásØơCQ)Dß[ᬣÖÛ*â±ôBæÂˆ*ÍØ2«­F\³ƒ´çÿ•hüzf~}1Ú:¹÷R­ĂZ´“cúhwµ§m<é›îäóàPFœf Z AOÅƠ«ù±‰c·ÖgP5cûĂYÔÙMÊôÖåÈÚ’1b§%{—bY¨è³î.B¦K\=™^uF"Ü]‰?_zR…}àúDi»6ë₫¡å¶b_eú@JèƯ²Éu¬«ØĐø WÚ…àÅ ¹û‰đÚ7'k¡L‘¢ŒYßCØlºƯ桪5”1ü4̀zÜ#Ëzë­úTNˆ”¯1*Ăj—Œs2‹K¿.6M¼ís.•̃Gø˜«̃ ð(llưe$Ú›¬@–ƯÈ4¿̃k½–»[Ÿñ:ö˜£Àù¾\ÈÛ…×6 ÚiJi7›mÇÆ7lƠc8Z5í³Ø7i:»§É±éóđr4¦{¥Æ )™Ømg´ö‰¸ºXr¦@¡w¬I®Q„ñ²à₫raFÉ .çNs+Á+<¹û₫¼%<Îcr(O<Ï“ƠSf(ÿB`Vƺ© ^đX Î iªà^êä½E“èfIª«–̃CczÍ¿2 ˀ߂åAF3oü¦])´ Úwl#uó)C/ư°L¦¦M.åưÖó•¸íѸ;·́U– ÷(@ă9Ă¹ˆ,=t³u9”6 íä­ ¿pák88cO­!ûn&ău÷‚èĐ‘)6$ë6Ö_ŸUt¸mÖà–¤Rb}Pƒqj%»ƠF¿ơèåô]Vó’µ 1¾ƒÄÎs©St–‹+k¶:spTZÎ-¦ÙŸ¶ÍÉd:(¸Ew"!g‡Vö–Ưsx×6fđÇ₫¹Ø³àVÿ#bÓ,éjëj ÇÓË€ô…cbë ™Ú«.í.ÑTl‹H̀S&;›̣æv1-ơ'ÉBB¤o'³́áæ‹̃ø%¯?¡gGwå’Åôåpiµ2$|‰Ël±Î:¬²?ïó!xèÄ7>; )h¶ Ï$t×x‡ø£µx›¬ºd¹-løưùß‚_|37_œOz×ö¢ÜS;ß̃8u)”«&£ÊaÄĂrSq®§o£3đ´*0á:’8q4´u²Ü“g¸¿Âz[¢¾§5f¤BbcѰùQ9z{Qïz‰îs~IÚh™‹₫ă ²/qy׫>;eË—¿ÀÇÁ”Đùç¨H²ºÂ+Üj.å"ï†×i·óW¾`–jX&i†Üô©ê"qk™l¡º}ØL/zËßú{Û%qÿ̃ÄVpáêµ₫¶̃öíúĺ2èÏCÖÇmeùÊ¿QĂ14j‘_Ơ†Vơ@&·-7ü´h‰¬Poó́àΈ 6@đàÀƒ &D¨`CˆNŒ(ñ¡E+rÜèQaÆAt(qA‡”*;,¸h¡ ƒ^j$HÓ%Cˆv|™PĂ…A5p¸©ĐÂ@Ÿ9eô q¨É L5ü”ÈÔ$ÉX·^̀êb₫ƒ•bÇ’-kÖlKªƒn¸*iÛ¶;yj˜ à%€ˆH¯jl¨ÁÂÔˆkÍøµ&WÄ]‹Ôºx`B”g'S®lYeƒ™yj®8!M½6¥Øt̉‰q{ɲkºª¬£́:Ù"Y0J穹 ₫ÈiE8¶ơe}›eÙ#“¡2‡#§‚%₫‰œ¦i¶«nWRB«^{U×&„«†iÊY8*«è¦«0Åj.œnd›­Uvç׈ú„°uBІ„Ù¬‘Ü%%S®°2́óÇ# ư.zñzˆ¥u¦.7]—âHd« á&dP̀1Ô‡wôÖlºÛ(ºŸLYp/ äggaœ1ŸÜn•¡·~&ûóÜ"{<´~9;ö³sâUmµÄñ…ótF] ®p‘wgü=ô´¶ª 2Ø•÷åë†[4p‹¡}á‘r*]ÓrV—̉Ÿ.°èƠéăéOÛI&Erûûơ×™‹Í7Z›_Gs_ƒº³9ö¹çƯ!kn·̣Í[~ A{₫ó眮WÛÖµ1×I*]3±₫ú´›îË£[œơấ̃&™|æÏÓư~ЉơælÙ9"¬xúy—¹{¢ơ¶vÏΨ̃ħ*ă îà'2éMO,µ*ÍNV†£ä'Ẉ̃Jά̣•º±ïQ”ăạ̀Àµ6Vç²Q¥¨2•LµÊ_r±ÊON§“/)ålâI²"' Q®}>̀Ơ"±-àfqÊùئÄP‰K|"¡˜±%Z­4 ‹"31e±‹NÙ] _¤-µPÊe?ɧ€åÏl‘IºúórGÆ„îë Ă(§´QË ñ!Ü EÇAÂQ-nIνt4$›đ "¤₫±áw¬*0„–T¼Æ¢€³F„ªùä¢tJQÆ\:‹$oF‰-Uṿ#Éc ƒóá¤Bü¸—åpv’ü ẮhG–L³Ê ÜdX•»8 BKáW ë538ºlp¾̉×°̀…09v0ˆñ»#æôJ£ơÆBØA»˜Îuª³NôÈÆØ Å¿ÈÓ:ƒeÓR•́ÈHI=̉× ë̉½îe,?áâ%7YGcs°A1ù¸ë}î_˜J" èÂ/`Ï"’“µ9› uh%ÁyIJv¥Y(CÔ₫ä×ÊR–̉0­œéF²)¿ªM•<ư$>§'¯æX'&¢₫O¦¤–+©¡¯¥ùÊ›×(aöP$ÅŒ(•ªç:­51ơ Æ–ÔÉB½l}zjaBºRo†3¥ó‹—+6Æz̉Ơu]çŸ6g×xî®Q„ˆ°j´mæ¤DZÊf¸Çºz!+UljU¥ªÖ­@T°SBæÎ®2¬?U´*†Scr|̉ƠĂñJc+¤'IƠo²´­(b¼Đ€̀¶¶ pms‹ÛÜæv¶¸µ­o{+\Û₫v¸º5nq‰kÜàw¹´Mîp¡+Ưă2÷¶¼m@s³kƯæB7¸Ïµ¬XêGF`µĐ>UƠZ,äKƒyȵ'…́{W± ‚×N­¦¸+§F²‰œ ₫Ù,bĐO‹“=đcUª`öŒơ}0„Íâà/¨l$=áN¬6P‚†Î…ÄJă0bɦµBÑ£đeHHÍRÈlüƒgÍ̀‘ïŒWDÍq1‰K̀Ú·¦¾A1ƒ\%!Ç©lâÎÄHR®yTy7|½®…Ä6eÇ܈vÁCIÑr”ßRơ›ªôƒŒ×ÿÅ)|{ $ë“ §×Œîå+ßÜÊ6èë €LŸú)©>ơw¢í_ßúÑï}6UËQS±Å6oÉ“*52|êêk₫æăÿj½½== ¤¤Ưv;÷9µ·AÛ)N †a1ß¿ Íi^å@Ê÷=Øôa_ơE XH`÷a_b[đ 3}ÔNüѯÜÄŒÜ_Œæ…Ë₫dÈ]0KÉj´Ù̃Û¡DK€à[D̉b}HƠ€G™ZЉɠ`Ză¹Ç§¤Ùb\Z°‘×7eímô5`D=àöußơAà\D¡œÁ]I¸ Á´Ü‡˜TVQ^dKA2yWÙÍĐxœ`-mUI¦6Ào ˆÄ¸]đüĆtË}ÙŒÍß#ÙÔkđƠ‹MDXE¶à6Ê89!xA¡÷Y`%N ÷ è\Ni"Ô~PÂνe Éáà]\£MÑà$Đ#RRÔÅÙ™H¥azF0ιđ®ƯgqH‡ôÅiƯ2¢̀9æƠ@t₫$êQfŸNcƒDÎ ®¡!*Ä"&”ÑƯÎ'qđ´O3º‹SçÍ!n„–¹ñpÀƯÙ™'á̉щ٪hV D.é!— íG^^#º LưX4&¤Áa  àב)YŸ•'EÎÍáHöÅ₫Ñå%¡ÃQ,FÂƠʸ0wp£M[¬¾1t0MIRïP¶¬?! Ù­¡æÁ–Bö$µaÛ’ÉŸñ×Ôqˆm=Í_aˆ–#:ŸA `A#£å‹àđc7â˜Ö˜\Û¨M Öbú#"̣Ś#–$|-#üEÛkH¥O¶%„1¤M]V$Ù×Ç₫qqlme¬nׯ‚lÉv¬Ể–ÉúÊ~¬†¬Ë¬̀Ö¬Èîvưj…)ˆ´ôµ\…« ,aÍ”ă´Ê#|lK1>Å“µß >¤®:́Ô:j”H,Öf­œh-ï8iĐ ‰E¬êâc0Âd!¡ËùFƠ¾-ĂâêÍQ,×Ö₫­[¢ƯÚm´ølgôQàdÏ;ÍcÄƯÜtÈëlLÖ£?& n¼VmĂÆíkáœ̃Vn¯â­å'íÄơôÓ|b¦ÙEcæG}éEIÖ¬dë¬n×Ü Âm䯮ÜnK̃f®†Ú.É îF¥C ĐĐ]]ú%Ṽ…(ˆ²¨ ñR˜¼¨¢ï¶íÁî́B.Ôîîölơ&^o,ư]ƠVÔ$đ¦ÑúÙKÑ‹Æ$ÈĐ¯ä%j5¥äJoVơjïÎÑïb†ưnízhƠ ơÊƠÔDV¢èđ]Ê’ä!çúN^™JÇFåûBoüRn₫N0ÏE ÏÚ-º¦EJî̃₫Nñ₫Møf\H&h`đ’뀩ê2.̣¹­ûÊiR0 çœ×đYlhÊÜ—M‚Ä(nê7PW‘¦¦j‡¦`̣Á0ü61Ñ\0G±::?Ë rO'!ëi{*[\Z¢aW,°‚E/3ìogïC ư´q“‘)×ñ(u+ѧ÷±ÿ1 ûÔ®@q̣¿1œ©2#/¬·*k{5ëæxL¡:2$?r#G²&c²%GÅG&2­€²Ç (ëp¬©y¼*7†íØNc̉¶ˆR*ϲ,×r*Ṇ̃G¨±(ị̈Á¡E";éqé¬su×v 1s₫r%svuWqAW:Ws=3uAs1+2k—5³2S31w35W—m /³e=³Ç²ăë29¯3;·³;¿3<ë­!ÿrKa^¢HS Ec´IW/GŸ4HR†%’´ºt&ªtå¦4Ó´LÇKcâH¿4OßôLû4P{DK4ötE5#5/ÛôíSI+5TGơCK*G´T_µ2u›tÁi5Vµgz5X[ïXï²XÛïY—uưªu)³µ[7é[Ó₫s\ç/Wæ\ß5^Ûu¤¦u^÷5ñuXSµ_öFö[vA5`öb#v;6dCLdÓo]O¶P ¶eg¶fßî^o¶gcă8WöA6iûsiwíiË3P‹6i7vjËâkO¶kǶ±6mÏÙl—sVnß¶o³so«kX÷oÓ6q;áq_:7sßksOIn=w›&w…aó7_·ug7v_wÍn·v·w‡7xëÖC‹·yƒ7zóÎóy·wz¿·{Ç7|[7CS·‚ U'ç÷&_23'ïw&ÿ·€‡Ù0€©m̉€xëw6±P.8€38„'¸„+¸…ë}ï¨m₫O*vxz8ˆ8w̉Ú†“̣₫¦jˆ§x¬—ˆ«¸‹·8Œw'´J·e0d 3rÚÎ%F…7ÚʾÇïÙ Ñdÿààâ”Ëú1«µ×α’̣]̣øDÀŸ°ïÙ$Y‹é]O ù*}Ë~¹o1÷hG"×x„§yz†j‚ÙQ’WXHg)IÓúÏlˆ B„̉̉Z…Or‰ºfŸ7 …—$l–ÖÑñ±«úë‚‹Oä i¢+ñ«sdE›ă1…'„û噣ùăÍÆøk{ùb́́lǬ T´¹ưÄ’0ÍëbêH̀0n»ÊóÊz ¬O2¬-Ñ ñb{±«\›₫±ơ:¬Ỏ­Ûz€dxVGŸ.!P]¨̣ßă8.ù_~8tTúè ̀} ¯Z™ “«ƒM ,¾]°ßŒ)ö%x£₫ëÈ‘ÁÔzñåc¹ÔB;;{h2,₫^!zKé`¸oXÈå–×Ń€©ăœ p.0[™ùÇ¥»9–Ȧp‹që>ù Ö Âh;è..<·²aü¼=Cû¢B‰é(́(ràê¬^ÍßËê|] ci ×É€" ×'A¡;TY|DúZRjtÉÍsü†¥â4Ù|¶±»Î‹‰è₫¼é9½ù±í^²ˆËGơƒßÙÉꅼӻͯ₫ư›¢És»½₫íü ¥=̃;/”yËŸ‡×}ï=¿0ƯÇ̀VN)ª½ĐĂçÜÇ{Ú#¾)ẩâ‹{ÈÑ…¸W©ÊË&üŒ=TSª¼ÖHëÈ̀ä›àÔÛ{ÈŸúV5~†¾ú>ü"å=Ü›S„X+=3₫°¯dÚO»Î¾äă<â~¶£₫á§ á»ă3~)ºMØ{æ+uÙÛhÿ¬·ß˜ë‹”¾ËÅ,yÇÚO¿ÛcA9Ú}ö.˜:~@Å\ÈøÀËKŒ‹8₫€¾ñ§½£ñ~îĂä/~u,₫ Ư¿n¾ư§ö„6lĐPđ`Bƒ 6døĐaDˆ5XhĐcF9vôø₫dH‘#I–4yrÁI•+Yfl€°`̀…2̉”9Óæ…; î¸á'P‚By₫´ ´'ϤJ}8´é̉¡Du_#«BÙL$1&8MÜ‘B#YS´ĐÛ ¥Ï©>µ¼¿L1Ư@*=ưÔP9:mÎKơ’2 5ô5 aºP.j“Ç,‹mGo=UB9ÉÎ,OWi­ƠơR,yÍ₫U±3EsUĐ²¨­6 ăj ZƒE6Y?Ă5V5D=Ưt̀ÅRåt"3ƯlmUU‘Äq& ´Á/íRDM=6ZƒîTW#v}ØT^饉Ùo™RÈ_e7Îo+đ&!]µ&8×÷]‚•µ”¬ƒ^™E•Y饓nׯưbkôƠW¯ơ¸f0éêU»Û¶™ÛUKSÅ—;Z ˜vº˜~z©›fÚjª¡vÚj¨±úê®§v€ë¨Îúê¨Ç6;́©«†Zj°å.Ûëºă®Ûë¹×®{o¹©ÖÚéªÍv€l·ñ›n»_\l®ßúk¸‡Ụÿ\®₫Ü#Rl’óÍ=Ï ̉gápS1i&éô[ÍBÙíâw“d&Ă™₫W0ÁĐ*N»ZÖđö®öQË>r¡•Ă40Ç$!¸î×C̣đ‡>¼ûˆh¿"ñˆ€P dẮ0}e"aĂ€·'÷lNß₫rW«ø•6ơ«…al×­´h4–ʉ9Tăd:7ƯöâG;ºq!iÖ£4Dâu‘î+Hê°è/ø²5—"ä•’ƒÖñ˜™52₫-GlL^&_&F̣üS #øI¢)P”ƒbâÊœW ZAd–UjŒüÁ%-Q4•‚}ga‰’‰/5³^G !&$§Igê™Ñߨ9MkV›×Ôf6óÆÍm~Ó›áçÜâ66æIç=‰åÙÙÎ/U…!SaæCvi2?á2N\ñ™­¾C{„@!a`hL±p2,[eBŸ¹P††Ê¡£²₫ÉêK­L‘—Æ¬Đ†.êN˜t4£Åé(ûFz40̀ ¹́I­4î±Y#Ÿ—5•pw‹*âC÷ºq ;”Ư ''ÄÛMoÜ2—94P:3ÛF®ä~́ñ Ưƒd Óg^{U[窂6©kƠ* ₫¬‚çólȈuO]‡9̃ºRRímÑb;¥ªÇ1‘L~ÖŒfO?TÍŸ₫O›13²îdZù ¹µÛX̉&„40ĐPóê}¥3W(¬¬¼e‡H¬Ö½¶Øơ>x+"5gbé,ÓüöơZ4ÚÑNØFH-í8Ñy>À.Ê/hKHÀÈ4ÂƯqè½±F·A®Úë ™±‡ÊJ³H?D\*̉œRƒYàh¾S§̃²7=Bb¤l&&“Ùn,Œ=Paêûâ×`¢ñl}HâR ÄYå,I™·³úí₫ˆR‚|i0ƠÀù €ØüæÁùÍ₫’‘ë<çås÷WƯ¤œ.ÙÇz–¡ °åëA ă9ăđ r¥¨£Ç L /T‘ ªlfS,æ.f1a*ó)½Ǘ™3x~m¾sœ¿}#púÎCÓº"mÚP?RĐZíÏIÎÊäGQÇçMëRÑÓø ç{^_§÷ÑöTỤ̂QYåÓƠvŸ]çnßÉçé®v”h镇ÍTY…œg%J9p Ï@*«¨‡ơu¾"«#1Æäù¬Úr}Äy&kjáÖQ· *“.³c•=óÑgèậÆö ËưóA'=±TrA›Ơ[·n–ó}-&‹we·¶<® ,÷›Ÿ ´•­ä‹₫“¿Ÿơ·ÿbGf́n‡4K8Oú=côxîĐ$ª A¢€Â¢”nü¢'ô/ŸN-QüÈ_nØđ©̉R¤C†/¶>ªY†¯øv£G¾(µp"€ï´®„È,°kp]l@ª‹Î £»̃̀ M=ä+« m«ö́ĐdIÎ2-₫&©êËÑŔÏhÂ*üÏ µë…2êÙp4hÑPæ̣Dà zj´Đ½Ầξ«½¨ Ạ̈0ưè Đ²,ÉĐ‹´t/ÉR+²±Ç´̀¼ñÙµ€#†îĐwC₫ȰAÔ0à,1ú01àtª  '₫`¤ÈCÇæ‹+.K 8‹³(‹­₫p®j¾’²+Ä8++èĐ¹†É—L̉ô­½hñ̉>nW kçc2.ê€E¥ ó̀P-˜ñÚLă£v,¶À́ấÀ&-₫ËY Ë́°íL²”,ÛÂËâ+K ´ë¼<,™’»0¬Ñ"{¢§đîÊï‘y’ñ¯r*}B¤p1 lÁN‘oq¥t/­âÏJwk©¼½ËÁl´†L·ÂQË‘ J*´FæÉrBàb~lÂ| OÀPNo ă¬̉(’ 7¬ÄđN–đŒÈb1­0 ÿ¤¨¾‘ ·³̉¬«¾(#£¾₫ÜdçJ¶)́ĂDU’*ư«*D "~đ8 *èåø¦gaæ1‘̃Ïf¯Ûˆ6€mxèCF²-"Vö-b8Äü¤(Ỵ̈i¯²ùr¸üR-²Rí]`p?p-—ä„FMØiÜÎä`­ƠvRHƯrä.±HØpE产DÜd*E-4an4E ¹j±¤æ-}ä1•(́PN8\E…ŒD1Q¥ÙÎäµ^OéDN…øH~œRñ$K ̃ Ï$³$–9§/đ51=à-H>Iøí…Ä-6lç̃¯:$odP(„R£₫1K,ĐK®~Œ3É䨧4—ßS₫¦ø+Øă(HïRÀëXO÷Bfgpă£¸³f₫Ç)).iQÙăÛÂ’,ôó´”J^Ê -å”"©&ä> CÊ9-N™â°Ë o69J<ŸS`~PEm„,,ÔăF̣böéƒølḰªê€(ˆôçC;Tú†tÆĐÉFà> ̣6çÄ.Â1üد<—OzĂÜ"+ù€IưÂ%Âổ8Á.}t‚Y¶†2Ä0ÓåˆôƠÔ4ØôÚÀ˜ËÅ‚)5Í0"ñϦ*((%!°JëtÅî”R‚£¶Ø+B¨ª'¡”ª²½JGठ×J™àư$Σ’ÅHù+S?₫mSù‹w° à0A¿l©~oĂPëËä#Y±ư ÑUs1G¿Ë₫˜,½<¬I1dUH- *Àp()QCÈMc®X›Ç/±m&à/z,L½L²¦ Pû1`$5«ªl±Bo'¹PÁ”¬[°; ̣—đRKO/äë8́k.•&:ơX[b€ú´F_Óf_r₫µ_ó•_öpô&`–`Ö_–aav`Äi$v4‡b]‚i.¶ÔøqR}Â’X»d%’[•ÂFÖ₫̣đư  Q[Ÿ Ÿ˜ ´̃ƒ'?́&!dƠ+…5\èµ^3‰‚4h‡Öˆ₫Lªh‘èh}ˆhÁE9qJ0£Ó³ØíCÈă ¯́YƠÉz;ïđ˲5ÊR„¿Œ»Vkk¢kËÏáT£·*²@ëP^y ú~Ôb0SX^lƒzcGóN,ê³wÄ3ßnéÀU6fˆäRî~úV;)ód2ơS}"ƠƠg4®̃U u©8«Qg˪­r9Dªn)Üni'„¤©:vëBü(­åX%Pư1°*Ñ ZĂgkw¯-<[ˆâtS8!ó˜ uKnOêJ¤+oÜxÆ–ÚDØ=ç 52• }Â%'óo’߈(8UJøÀÂÍODÜ‚Ị́¥4(b~Ư¾D₫6IÉr7¤zw¯è÷#œÇßÈdWÖdK†¢oSÖŸW.˜eyßë₫ê“F9Œgç5y<©ª¶m\ú¨¼V“Ébæaîí…¬ç₫æäM&£6®ñR4ngfn¶iY¦X̣WK\åIÏÍÙÎ Ñêïg̃g0â„v©ÎÙ-Î='ú¶rQ ´­¾̉ü‚ƠvíG)-8yX‰Ưê74†|çÖ^„oÅo'ï-×6V}¦÷4j–́—nUŒÉd Qœ6đ.́°ND£Ươ&bXÙÎcBÊ)éx–`¢ˆ‹fM`ä¢HyÛóPDPm«e !Ăø|«Ăy¡…Ơ₫Iyw₫ÖëºsXɌϘ#&ọ̈Ĉ„l+«À²ütc2,É+3dpCj¯đoÔâtLˆ}#JÛÿ¸ˆ‡&L®U>ØZÀD×VG±D/«Y†m‘ă…ÅE3û¥Ä(…=™'ä6™âĂ«¤á-®˜b‹Đu)µÍ (ÿ,*âC )Eù+9ëÄSbØÄY¬ó‚™D˜..%dZÜoZ“#B[œ¥, ›ûÙ?đơ y„y¥“gjj$c¥i¢Ÿ”-z4ØF¢ḱ¢#¢k¬¢=£7vŸ½¸„B¬ă £ZƠÙ/‚¥%–ezBe/^ú'‚b;Í]ăc¨r#₫Mú ¡/M–N™ư„ïüOmz[úûYA,;ơeŸÖ­‰/p·®—ó…:-yŒ%ö‰́VNüô1`º»–ĂæÙ5c/ÜẨCU0hy ¾®å—:¬×ßđƒwϬ]CE ±ƯC»„H“™/1J¬©Ùl\b°É„œ]Ú1`\9>öb¦¹*)R¾Ôù.¶POé”§£q¶)©—5{́‚ö„èd¨7^w{ˆD˜ŒE™·½¬As¬ …û™²\đ¯Ùz›¿91ØăĔРUq<ÄĐv7¤QIÙ•Ư™9h[»Ç{ˆă×»%›É»₫¶'{½K¦²‹;w@&E¿¥qé-µ`¾¦åؼMH,ôö·/ü¼û„ü<½ ¹]8¥̃¾[¸;¦‡Æ˜ë™2đYmæK£L+¤7J ˜—óeÁ±¼‡›ÁüÄ|ÅÆÉ{¸g|$¼¸†ÆMtḤ'³BRđ:3K•:â¾NqEA=h<¼Ă›Å]¼Å›ÊcÜÁ§¼½ᛦʛ0îg̀ÛKY¨Åè;[bGYïz:S–…9È•ø„i[¶Ÿ\Ê_\½á|ν­ÜŰܙ(¼Ê7¨o_´‘—xe»—|¯N} ]1eưàRÅ7T¡6bîÏ©₫œÎ)ƯΣ¼Î1½¡sœXơ|f̉2Mú0í'½E°c÷̉i¦SX8£!|̉åÜ̉5]Ök½̉û|½m|¬‘TÓgI¥œ}ú’â¶ÑµäC'V™<ÖoÙW=Óă¼ÙaN<½Ÿ]ÆïüÚ¥×ÿ˜Ó%èjØ&pÂmÆƯpü&oÊƯÅ}ܽFÛ»}Ö¡ƯÙßƯÚå}Ó©Hש™Ï…=ÚåØÙÛƯ¹Ưßcb…$jâ;Û—=̃m=á÷}̃o{²ïƯ“»á½¾Ư°gÜ\X‰@@}ÊƯ]áiáé=ä+|a ₫Œ!xáW^ä±}Û1̃äé rƒ]Ùë½åõq~âăƯb₫Pn=^¶K~çãæè băIăç†käA~ä…䟾éÄçU8êY>çc¾è·̃â…cà9û̀́Ë{ưè¡̃́¥ëç=,ª¾^'ƯÉ]Ưăîç₫íë^îíîï^ïóïñ̃ï÷₫ïǽ4JOó¾§ÿñ_ñŸñëÈ"¨]̣¡M—₫GOô¿yL‰ó;ßó?ôCÿó/ é'ßôÿJA/ûäơAOóuÈÿ_öökŸöoßög„íOŸ÷A¢ôZÿú\_ơM#q'mĐn¨ù#Gk–_m₫Ơù£_ù§ú©¿ù­ÿø±?ù«Ÿû¯¿û³ÿû·ßûÇüEºo÷ÏơăNøƒŸư_ưß₫{¿̣Ưnư3?₫ïÿóÿ$Ü_ÿûßÿ¢ƒÀ <ˆ0¡Â… :|1âC$Z¼ˆ1£Æ;zü2¤È‘$K<‰2¥Ê•,[º| 3¦̀™4kÚ¼‰3§Î<{úô;commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/BasicDataSource.gif000066400000000000000000000373111410126276600305460ustar00rootroot00000000000000GIF89aÄ™÷ÿÿ„{{„„„”)”1œ)œ1œ9Æ½ÆÆÆÆ÷ÿÆ÷ÿÎÿÿÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,Ä™₫%H° Áƒ*\Ȱ¡Ă‡#JœH±¢Å‹3jܱÀx)²$É“&S¢\©²%Ë—.cœ)³&Í›6s,P°„Ÿ@@Jt¨Ñ¢H*MÊt©Ó¦PŸJJuªƠªX¯j}p §Q _Á†+T́Ø fÏ₫,+–-Ù´nÑ»®Ư¹wÛæ}‹·¯^°< úÊ nÖĂ[#^¬¸1ăLJH`-]µ{Ọ́Ơü—ófÏuAËYóeÓ¤C“f;Y ÏÑqỬ•ưYơØÙŸcçî|›7íƯ£mÿ>\xm]÷>>tPĐ¡₫éhuéa…F—^Ö­śEÅ₫F[Ư2Ư­Û^Pt;̣빫뜭næ²[Kx}¿vwè…A^Qå=Ͻ€dµ@Y… %Ô ¾gßZè…FØtçq(ßPJØ¡Q*HÔ…X×́©…[gú œ‹fq‡ƯvFáxăx`· ‚8₫8^?]€@¾'Ư’ă ia‘`©ă”;:ùx~ÍhTŒ¶5Qî}¥Ưƒ>ö¨¤…)‚‡%”Ø…È W>ø£™q:Ùä˜CÙäugY'îéÉ[—gqy¡mÑ9§fF¨‰c–µc“̣…ù“uVØg ~g©œùäyUÎ *‘ưiY—^ ₫¥â‰)[‚–h`•V(«œ˜é#–z ™·öI+¯I f“ˆ ¡3¦úa¢fzfû¦k‰Ê,V+êQ86ª)ZŸ:ª•Êv;j«Í>ë¼ÑN¢TcƯkTráá}±é [„sưK°RÓªF„Å%Ÿ´̉Æ^dQ! ÙÅg̀Xć±PúÔÁ¨¥æ¬h§™¬rỀ5¬2¡Æ¹ŒrÈjlóÇ7çŒsUzá̀ê…C™ÎZ%ÖXÆN‰‰VRég@(!à‘ÔM="Q­µƠUg5×[w öØ]‡m6ÙT€µÚd£ƯöÚg—ÍuÛ-…­ö×rË]₫È'} ¾L7¸̉ûmxáÃwÑ‚È⃃¼7† ±\ùË–Ă,óË™e‰yf™— Í1wY\qËzºoÇ­N\–/–Nc¢_Ơü:ŒóªW«K«ºç—Å®ǻơÆÛºç¼#¿ê䆈 ñ¿;+|ôÇK¯üơÆS{ö.ê’JjKíQJä³}€Ik—T>Ơ)¥}¾ùè—¯>ü$¹wü$­?~ưù÷Ï₫ỢÛßÿÄö¾Ú~_›\¿ Đ"Î9đŒ 'HA±vÀ‘ë4˜ÁÔypƒ́ G(B²„Œ: DÑđ¦§=Uơî…Ø³^ «'Ăf^*ĐtvF4ú°‡₫@¤~P±P…«IbjB:ÍLt›C™§ˆ—ŸQÇL 0Ñh¨ĂƯ•Å‹ïª]zèơ0­>kQzîơE§pqA¹QPv0X<ÙaÆ"@í³0¥YFNî’cTÈ ÑfqdÂÊ)²́‹cœXóàØíÔq…ÀK¼”–ï4 ‹½)!ôŸ='(öI€̣È‘C„d`v^t0¶Ô,ŒÂÑ"½\hC/áq_zTd*2‰)Iç“ ¤e‹I“JĐ©¢ !KÎQ.º¼d ¡–_J(˜À̀‘5)ù¤W"R̉)™§º  í$å´cÉ[])¦₫t‹œø¥—#n†Ûœ ơù¼)‘7:%ÓÙ­{+´’§C) ¥ư‡R E¤2=ÇTÈ4äeH79₫¼E6́d(ºÜÙĐx̣œoÑâ+!9Y”`ê¼§Cßó+ETq¥ GÊÍ¢.“ºÑá7ï4L5½É\’ÊS«Ä£r&2Jé¤TÉÀrEéKSd/g‹^´̣Ÿ„­®hÛ¸ P66²dA'³èH[ u”Z£|tỤ̀7¨ăàg«{Cå¸e=údÏ+KYø­t=i½>z›)́yb5LT)<¬ÚØơ¶ñƠKȾ(€ÂàÄ”&¥¤|ÖNz¦U¯%M`‚ʧ₫ËvÉC –º½dƠOđ€ó¯=úNTưÙQ&4Oơ„+OÉÉSxv´£ïúbñ;QnB,“ –¡₫’ ô¼X£:đC»*©oIê¯6Íêx¨œçbZئ@°ˆ̣^Y¦Y¤đ=ôè ‹Đ2uƠƲdÇbQƒÊYËØ<¨NÛN=§?'R$ê|GjM"Z5f ÔËE-p-i,3­”ºúè½4\wºT†+KÏØ¹—Ó+µôD[̀¼’¯¤Ư]Aº[8̣3­Jy#[Rk ]ºŒnno¢·-Ø_Û0ƠÑ1vX˜Iîr›ûÜèN·ºÑ-Wokó̀ÜĂ ±ÍéïÎñ¹†öï{ÄÇHzX¸/XN[b7¸Ü†÷»M](æ8× ›ă{çÙ¯GÚ ë?=̀/ nài©Å₫GÍp…'œwk̃¡Êg• ®o?Œ¹Ë“"±e_n‰8âçnä'̣<ç&kbpb$·‘]$G‡̉—®ô¦'ưéL‡ºÓ£Nơ©[]&RÏzƠµnu®{}ëUçˆØÇÎäứhO»Ú9¢Ÿµ»ưíp»ÜçN÷ºÛưîxÏ»̃÷Î÷¾½í~¼à7böÁ₫đ<âÏøÆ;₫ñ¼ä'OùÊ –Ï|ß1¯ùÎă]ñ½èGOú̉›^îH{êOOùÂKdơ }BdÏúÁ''ơ«Ï=t lG »~đûá÷̃÷Å÷}íñ̃Ü$÷À>ï }å[ÿú̉O₫ơ₫¿ü»sßúƠG₫óy?ǘ_øáÿ}ôißư¹s¿ú´O¿ùÁ~øŸǘo¿÷ç|á£₫âW|Á'~È—ú'w w€ h®·€x ø€8XxØ(¸Ư—€‚"8‚$X‚&Hv x‚—‚*˜yØ‚0ƒ28ƒ4¨,Xƒwƒ8Øx/¸ƒ9(>Hy“¡ƒA(xA„Eèw%‘„•ç¸?ó…P8…ï#…UH…t…Z˜…YˆàĂ…ưc…`(†aˆ…e¸…g>q©¥0Úfdpø†rè†tØXưE‡`‡x¨‡y8‡}h…Ç7ùVA„Xˆå!r₫-Sˆ8A…÷ "s84m‘X‰9Ó2r2ÁÓ9ôXkáĐT $^‡RĂơˆÍ!Í•\ ‘Ub*t›ˆ<˜qT®‡(ÖÃƠq“èqza0=F¦J+rEÆUZ6Ú#lǃ‰Ư†dñâL̉1q åhÄQ±Ø.ÂU~ËáZÁUp*Ô‰&=àŒÏÈ`¼¡'käW‹ăJY52†ñ0„”SÇH"Î…Œ°trÙsÎhd¹xjRU'NRg³‚-úULÆ.Ê‚æ'»b*Uµ_ü¸p¹å8X›!.kâ+±¶(uæ.·#"kẸ́(œb'>̉j̣[ĐX‘¡ñ₫©h~’+T‚)&k ©(Ü‚B½" $©“×ÈQñVr&„TF™bA1?‰&YQÂÂ&ñ(•urD(‰’O‰'‰`êh‘­q²Ø•ªÂ'‚$ÑQ"¥‚#h‰·ẽâTúÅ ­v–̣±–¤2Lh6R©²è_–(Ĩ%&Ơ„æ—ç!Wæ5Ư‘VÁØqæQbÓ5sOñB2:E{Q\¥–ïØn –*¸Qp˜D˜$tªˆ·=ª 'UK˜UKÿ–îƠ^çú²r̀&¸˜`$Ô`Á†$Ç=ff/ơHæ^²AŒ«JÅè†ÍæVûxî3/ˆ‡)™<₫ă_K“œÂH›Üraa™Ô¨rù•û37p#@îI@v“>[ă…îc5W³́Iu´pơ©éó…'ñŸæstx“6̣™Ÿôc7]#kHd‹˜™•¤0–yÊAm¡8ˆ¹@>÷s„‰ĂÅ\ÈW#ê]¿Epgơœm„_¾(Ff1äQë±/¤I £FÏ©Z„ µ‘­r!®…^E®ikÔ‹ÿfsOñ/öÖ!EÊ/ú"σ›³ˆ(29K9̃ȽéT*¤dj5ă˜´È4’¤ÄB1l~qkh傱u¥–Řh°›uq›©!€‰¦₫ų£¯ÓGUʦ¢Ư³† ©Đ@`Ọ́Jʸ-\II÷X²¹§mˆJnERd¦¢{Z[&‚ÚPÔ¨Œ&÷•²•ê†ÅN¬x¥kµ…ehus)°5|ôr6¥²búU`_¹ ‘©”j©P¦^đ2q0uJ¢fh£ÂH§¤\åÉWÁœ*Y*eưBZ§&§–î©P«Ó6cȤg¦”mp„-O8¬ă¤"SM̉D& bQ^u© ƒ*à¬í¤Lîô!"¤9¯&¢®WäDö˜SniJ₫ôRdvâÄ©^fUÖ”SèQ₫D€´VVƠ¯Y¦RÆz®@æ‹Ï%9%5‘JQ&²üZ°>ơQ0Å‘9%²ßJN'ua)µNđ´²@6²Â+N»Qå.’³"UÀº!5{´[5³Wb²`¦B€Ô±:ukrâOGD-#Ög›¶`"iâ‹»RP»S â±ØÔR#k³$%"cH’j˜^´eÍtU Óe‚'hY;à'ă”²-µ±é“K3—£’k®&´µ1­Q^K—³èU¢úè’©œÈX˜…˜Èª!MÊPêk†¶!ªµq$¤Gú_?f»̀Æ£‹(Ó6WÁK¤‰¹'æD4̉]/₫ºCăÅkuœŒvH¼‚¡qhAf÷E¦°ê‰8Œ¨-¡JZ›ú©Ó²|o.ÂV‡Œç5¥Gù®‰•$,S¾¬Ú€«®Ô ˜›ºKê¼€)¦Ÿ¸¾k嘢ôkÚKÏ*©̣:­Ê» \„ R;~Éa©¸½ DhâªSƒ(^üÔJ)́¼bêiÊfª_6ÂF4¤5 ¦¤e±[4T#Ù]ó4eÆúÅ!G )³6¥CK€i!w:µ<Ú»F\¦c!«‡‰ÁóJ¯g¥Eª;ĂÆ8`Ơ´„ăZ¶„Â*‹b5v(Â^‚pÖÔ¼cº‘ưe¥,©ÜM–¼¹üĂù¶'\WóqĂ%†XTL₫"gÄYd–̉a¼C÷̣”®¨§£I:¬ đ¥0}lü¼ă›Æ•Ùn6Zqlœ_K\®{Ô Ü¬YZ<[ZÇQ4¬¸Ûđ«½ÍjÓtÁ˜cZ¥=×3åºă8¹ÅKujNKÁœƒ[g|ÆLl˜oE_0T¾ ̉í¥ºD»ƒö½Ơ‰j*)Ñ:©\,fºYgEm¼Æˆ{•0Ø:äK¾ÀûØÇ¡}û»C0G¬%‡ÅXk±¿q«äƠ_eQ;¼­¸¨mOáeÏS`™4©™Mf;ËÜæn\ØÓ4^̀R÷­öèRJº¢ T¢ÂmeÔk:®d–ª Pî₫œ•Áad¯´FL–¤¯€ü´>…¯±q鲪–µqy`Ÿ+—LƠcṾgæl/9Ưûa$=’É$g½f̀t*Ïêô¨tlVFÊ3J²`«Ö¤O !¶;r´ơÁPƠàíGGû{‹ä̉³¢Æ´Ÿ‚U7‚¶‰¬CE`Û‘m3›̃WÖËñ·ưúMÇ̉RHÛĐ̀ŒgM\Q:]ëX|m`<Ωcûe@rÊä\­RÎ*ά˜ËÊäßÚ—â{›­\ÊíñiÈ}á„›=̉³ăÏG[2’IÄĂ ´(¶TUµ•¢P{6kĄѮVcè¬&#¶”'›^…E5 ®₫„ɇÑ9‰‘Æ›)´" ÜÂt•¥"Ư Kƒ›ÉHÂâÉ0Aʦú®zü©”¼M1]­å8llá#£Yr¾̀ÇqhË¥Í; ’× lÏ®!¾ÅÈ•v}M绢À±Ày é‹c¿x=hBÚ¡ú<ÇFfªTưÅ2Ñ–Ă.,ÀüÆU¬̣h׺Q=Çœ­§r,×V}¨`‘"”¥[‚”Z¼Å­´Đ§U2íxoÓS¶TÝ‘Ü̃¨̉¢ÚW¾£Æí œ\ø6ï¢̃OΉpÙ¡Ă’ÉtƯ² /±mO§ ‚&q#IÖKWßmçz‡A†…³Ơ8¾† £Å»m₫׿”ë³Z få½-ĂÁa#Î9¿ú–B„ʳEđtÔxă±qÇÖM…Ë Ñ4¥Ế-.ƯN7&$Œk¹W%!æÅ:²¯5«b¥jµƠÀ›!“Ö‚ÉR_ÊÿœÊƯ¸£f»jå[¥$âË(K*ù”_ö–cëÄ&O₫_½½ƠÉù"ÏzË·v²® ¸+˯IưMBû'i-œ¢æ)^ä\F‘×Km¿iMåj&g£ú¬Ä̉2ÛâZé³n_ÊJëùs¿i àGûÊt«fĐ¾SŶËz)ơ³pÅ5Ơ³ÁNÄømøv™±Î$N]¯)º—[UsßàZûöăV—¯₫âí4ÑÖ¨uîƯC·ÑP’¡ºEreW}ê»F踸V]̀¶u2]ÂdúØ‹ªK2:Óñ>̣íˆxBˆơl·£qO˜ô ¦ñ  <8° @‚ *d€đàÀ† &ŒXP¡D àøpaF…& 9ñáƒTJ( 2äK—$E~txR ƒ‹5gzÜé’gÍ}.°è±ä@¢#{ŨôÄ 4KÊÔh2©M)W(¸€cNjĹ3*ÔS•vưX–aΦ9ÙwæÑŒRïÖ\óªÈ¾&ưb]r¥„!pÀ˜c€n^t[¶íQ‚–*NJ‘'ܼ₫S‰–́̀´¢ÄˆBj&¬ÖçM‹!¯æ”œ÷¤\†·Jüú52Z tͲ€ycAÉ£umj²véăË÷ÎôÊñ©Ëª4µ+ 9ä׃’¡vm2ëá–7†,^øZ© ”\{§û©§CĂ$8ºyN’3o ¨j¨8ú`đ3„¼³,,…Ü“¬ª'N7•¸ˆ£Æˆ̀¥̃‹ đâCp1ˆê[¨7đī;:1<úJ́m$íÛ €&:ĐºŒń¯D‹“£kBPH°àÓI+•̉CÎÈE:€Ñt$ F7D+‘£oKúvä¯6‰¼J0ºç6ë/·ËăÂ₫¯K4]|̀A4Q̀Ŧ@¹ d ÇÆºtHÂ>I$̉Ιü®Oí\́F²CèEơÖDÈQLẮôRđ,U“T±ÜsTJ%¬³Á×2´€’ jĂM LÆ„TŒÅđCđÔKwŒÙ¦8=ΫëfÓkÑVïrµRhËL2¼/Ëd³L0Ë́̀P®ÜrLº<ˆÂÁrµ¸«ôœ°£+ủMj ºAH‹-ª*¹" Ơ s5ÑFdỈ=€·}UG %à![…º¤/µá^â×'?eí©47 Œm¦ G"Ôµ₫̀öª¿LÆ1%Æk­~çÊ©´ÉjËcµ₫X6 gƒ”ËO&øB Y¡¤*ô °“g‘)œg¥¬(BËË-;㤗9é‚#ưæz9µ +ù)ƒs«ÿ+Z»ÀưÎÆîΧ¥ N5¾m».hˆÂ¾S;’™ås ÷Ib¬9v;kxuÑÆ:lN7Ë̉ˆóÀ¡îU[Íä#ùs³₫r¶®‚4z ë–ư’̃–ăĂ­³AĂ©j÷º§Ë7eñĂ‹\ƒUÁ»u<ĐÓ˜× ¿‰¦zbŸÀsëçÜæ₫Î@̃₫µWø(7Ù'»AZÏĂ*I¦;{+}Çó-´iÏ̃uj©Çø£çĐº9´3ăÉU>Á&؆E9ÆC₫úØW6ô¯+©'yÊ"U¿,e‘$‰(U´HÆ‚°₫hđ`ú#R}̣Ơ"Ú¤KOƒ½€c‘ËQ^U2ÖÂg&4°QÔßè è"dƠæcïÁSªÄ Ñ]đEÊjô8Ơ­'ÖËx0 ^„“¯¤L(PÜX£ À%ZïoEQ–¥¤‰È•ºÆ¢n™±Zo ¢ س³L¤™ÑKÄs­-–+`̣X¥€È:@aˆdRTÇ•'m‰*P¼—eçLkI@d‹R¾²ŒË…œV‹C"PĐSóê yù=ïQí!Y¦JiË^ù+3DJ˜©˜ÄªƯªn₫¼ÛI`g»7Ù„gJ9MD̉”©•ñN)/A¿6A LϳZ…?ê$tÑ…®ô¾W[0[SĐFÁUn@ư¥ªéûÅăX†KƯºW$³YË.¤£âJTO ©°₫6 —*Ü ₫zḰ¥9Å›Ñà‘ŒØ­„1*], ”X¢Öª(€t=àJ¦`9)£çKçB Å^o$8eÚñh¡®¹ ~h=×,­y3ă o ƯÄ?V.ªú>ĂT₫| #̣Ñ̃t‡×ü'*fC“æHŒÄj°JkSó,Ö¹¡kÓɦ^˜Ơø%Zdÿ¥¬C¯Üå½ÅÔl¡đK9ä¼e¶}ÆÏ¨~äb›!CO¶ÏvM¡@nÁJÑ4Û¥p¼²Œ₫^%ËñIou‘ÉÄ¢ùÔTâF5î´W̃x{¢k¥í¢MÎP;ÏT­­Ï· N­"j9ßñ$ ¡`÷b'¼nù©ÛÁô¾âÁƪ[Å}½”gk/ ñ‘W\4R‘üÇúpШøSOÊ…ô£©¡ÑµJz8 ươGƒ•É„*ïR«èTç‹¡áŸl(5̉HE]•ưø³'ª6Wíe]b[YAEEq¾"ZﺡN,&+•({\̀Ư³Üy‘•y3¡¯æÆz‰갌䪾WsLñ¦°¶¼ªÊñ®]Oe²NbjÙf–^ơѨ€Ü$“V´ [‡¬̃ÿV‰cC iëûø¯:₫µXfO<ï; @^ôœb¢´Í¯nYªS^2ÅƠ9|,ëçĂ F1ª'̉̃'‚-Œ`K–±]k™Hè 4Ǥ̃Ëœï9nFN£ùä hÀmk„d­8ôs5?e*Mm_<£üsöS“?S¬LçÔ:»ŒÇ­Ñ*ñºgxÓ4₫)3ü£U#³Ø;Å"+D3ÈÀ‡4©Ω¸G³ˆÆ¹4ßj8®69³2´3³è¨Á=ôÂÔ©Vk™Ù(Ê›”êµ®_³(gÀ¸¢—}â5Ä pῬg µ œÀêƒ*­"™v¢û˜"mª‰cK ¼µ\#₫ ̣'ư‘¨Íâ©îéߘ©ú«„‘®üû‰¼T" ,"œÁ‰'$³ÿ +€¢ aû+ B*tºă sˆaĂ*TŸªqg¡‰'Ô«´à,1¹J¹à#çâ;— ¾P¡ăØ•©ù¥Ú R´Q́1ƒ°`ESDú7éÙÀa?®6é®ôB»²{:q£-Y,C ²Ómé‹á{1êq¶Ú¼\ñ®é̉¤M©AF2+; ¯<̣̣"9󲻫¼ƠƒÆ2\Fư¢¼äK27Z,Ñ=ÜC®ü2-.*Oó¸RÚ* ,ô¨•3¸­₫ƒ¹…Q<ó¡£J¯³Ú¤8:½q0¾ăº I¢Ơ»: ó“( ë¥P‰‘Ö2<áɰ̃{%̣(ÿ›EW”1†d2‡˜kŸë»CUkÂd‰®›»È(Ü5´{\@Ä ™·y œ"(œ ÁH!Œ6a!?1s›ˆ8Ó) ‘£ªlÁȲ­j¬Ë°¿„Ó´E©Øé¹%ô#´¤ "º¾„A¢<;¦ä´³¸ÅüÀ\3ÙhB—9µƠÂŒ<:,¢jDy dS§0ó:ƒ·§Ô1ߺ4è¸ÅKƒâ·₫† 6’¶Íù&¦A8&ëû“'0cL@œ@íë2t”·̃üñ™6ÜŒÂÀÁ‹rËâAÀ¡\ ^BÈ́²– •N«>=sN‹ÅƠ ¬M3¶Ñs¡qÊEóBóÑĂáC₫•ïqăd=Ü/Ñ$Ï"œ›|¾,ÈưëÁâ5PÎÖü)º™Å-°Qr— É$°¨IèÅ‘„E¢º ¥±³’I¼Qr ^*3ĐPº—\ ˆÛ:Ø›°–Ë8ÔK£Ç™´G.9ƠÓˆ‚0¡ + ƒÈ%¹-Jø‹%q»HËH¹Éú™ĂùB•́²–,-´₫ÑäsRn ¸Q &³#úz1‘ĂÓ›̃Áˆ̣̉D¤¼Û¥ Åñh¯¿ë̉_>ô?<Kë₫ú.˺Q0¥¹Œ$`b9ï$8ÄhBÚă—?4Ç£–$[‘RÁ¹ù:ÿ)ÉƠj’ kÀ­U„ÑGEű3®*µI/ºéë§s“{ăŸb•ySJăPŒ±U­µîsÊDCơC¦{œ(Ñr³G¤h°I™Ï ̀k|NĐ O›² ÀqRJ¤›x©§‰Á^MÀ–Jt¶SUK& Kl:¨¸b? è‘;Q[tV+« UƒVĂ1 ¼»B+keªiË XË´@kJ₫²‹²ÙM²ˆ‹t‹ÍL8̃́ÁùAŸ̉œæ\‹¦ù?<³Mă‚å¶—âYƒUk[­ˆ9Ô²äô3>\Ú«ÔÀó --@\I₫û É¿ÁÅ!u¯P{?¸ü4G¥“›µ‰’SÖ«.₫…GO\=%Û£Đ$çJÈÍkÉw,$¶É¤A˜À̀¡©ËûÏíFØúEâZ“ Ë̉ậ04:ɳú‹ÊÚ-;ë°< wb*A²¤ƒRa1;œ¾J-¦|k=€É¢eÆ S¼îµYT±W;PƯPëP½´#ÏY>Ø]Ÿ„2ˆ£Œ«ÈT;{KØè3²J ¡&˔ဨËÑ̀0z³‰̉)­œ>ÁÜ´ưá—iEBtS8|ÛÀ́_g½/ `µÄWÁ³Ă$'Kª»|Ă³ñ6¼Uơ|œmÔW©’ÖÂđÖt#0’ `ó(cÄLƯÊAz³Vl«EÄMŒ1₫¶Æ|à¬t|5?ơé6YÚḈù§ eǾ*alzJ>“Ÿ)üÀă´·đ[b1ưÀ6×ë[ á´¶ÁH¦:¦´q2ˆå©—¢½¯5Ó::„0ÍbÂÑ{ FR¦₫9+1Ư3D8°‰N~ëÆƯ8O¡mXº7übHÛl0ÊÙBÖmc)´ÖÜ1Û¸#†ÀH3°ê§y¿ÇK “+­ ¡±5™üÚ®>É\°"Y©è! M—IäĂƯæ“ůSZ{§¤#¦úeº»9iÏ€Ó,¢”ƒ3’ÈñS“Ô èyÛ@Ú! Z£#G)ZÊD #uC*¶sŒ|a#.µ`́₫-;¼¢ +å:ÔU•1î<‚Œ õ•{2­_ëdZ¬2<ôFAÆQ‰ëÓ7NT̉z± »¨à¼|öäQy(²gÎûƯĐKïÈÙlÆ1CP̣+÷ĐàPÇ u”ƯzĐzăLƯeá{F‹d %KE[[¦1–¥)[ă¢”‡¿B‹ß™Zµsz¡h*B k«¯SJáœÍÆÔ§oå¾è̉«Y6§„X€s¡°>X30;ÛtƠ wÍ&JL©ÿR¶¾}óKCS×wea"ƠÖÂ@CœQ³fZ¸|áÿº´ÚË́©w…Ú¦̣3F,Ú¿~̣(ÜŸ¨93L™Ó€₫}sZöéW(´byª=/MF:„ơ[Ÿ.ø™'ºØG®Av’Mê©4ùË£ +”J{j¦ª¶^•Ÿ½EÙkæßhD‚ðµ‰T3é>E 'Û+mI<­.¬æƒǼƯ«/ÂĐ­ú4‰å©”ÿÍh´ÀB¾U_œ4ͦƯ±fäôj©9’ñ`tµDùZ˜TP¹å½‹®«]>®!«é.‚=MḤ±”\FR-%Ư©c“…́[=.§à"ÑĂ¢ÊËÆqT““Sè_)àÜnXBj&z7€î’ä:½1Éâ]éÁ’© i¹¯ Ù·2=¯²qy´£?].I₫[%7Åo…\Tạ̊5ÁƯ:ê;‹qCÊ+À ̃Ö[±Ó÷çzT¯°íÊgÅ›3jS^è5qjdÜưJ¢hæ‰;@‰ë•䤖{Q_ÊPe¶9 ú#V„ñl™²[œDZºs9ÜÉ&jc¬¼mf¯ß:Œ'›·TL̉æÀâ2¨’a1l÷‹ăAÍ)D§₫V$Æ#µ¼¨Á©`S­aºp×GƒÂ„c¾&́S¿•]Ÿ4ᨌÉêl‰Y´4³̣laFë³éld¾kbƯoº¸¨y–́Ơÿ½Úà­ä³„æ¹tbgîBU%SơƯtåä rç’ ÖÛ$Œú¼?Ơ₫·e'?Û₫mÓÔadM\ti0₫ă1³j”á›́đßÀ í 'ß™´ăöº’¡Í\/Kÿœ¬¾ˆX§¹Ÿ=C:`Øâ´kg{9>/› ä™CAå8i!äeo´Ø°̀ÅH”âÀ–>¸ô„6$̃2è1ËḤ~b›ñKØY£ µí¡/ж'Åj@ 2 aĐ“2QG]Éó%™:ŒN\Đ•sås- —I7…]XTăI\/%¥VØfêiñ’# ÛHf­00q\äUj='»K½1ÂÙ6­ôeÑûå9¸È:ª5 y6̉ÚÉȧcÆ]ÓÑê'4yI¤Ṿ=¯È(Zi‚ñ₫ç]äLßOj«HöÖ!‡hÉÛº«q:ÓùƠH‹Óäºr=¡lH¥Ơs6tQ?-Ư,ưèZlé¶{鯾PE–IÇî°E9÷…¥JÔ z_@Qçv”éSe¬è€ÄÙ|!Ui¶à5–;VơƯ,°¥Å¶j‡*—¢ÑË¢ÅkÆzøsZÄ‚WƠ€~í®̣pG©ˆ XP Ø Ă‚%.œEB„˜°á…CbÔhq Ăƒ!.PˆđdD1#Jœi“ăƒvJ(ĐÑäÉ8_f́øó(N‡72]Y“ Èˆm>(SáT ›ÂhƠé₫S­7“’¥ª“ç‡ °@-Ù¨A ~5ºU¤J• ³üH1́R‘ †íïÆ¨[æm8U(ÊÈH¡–m“§„-pĐ™m€nG̉ư™•``Œ'³L ÁmUˆ°Ơ}úöh™ .ÖÛxeJGÏ–¹:²̃±Ïî< ²m[ш j̀ơvÛ¦£ñngÚ] €äàáª$v-t¸ÅÇ¢n—sø×à9Ó¯Tne£™÷tïÙshëÙfÜLÖWQió­4Ñz¯‡QqgÙ[J!h’P½5Û{SÅ¡p!‰§‰µñçœAly€h?A‡[ ×–B³)8!|é·₫t²9ÔVpñmøp=fƯŒl¡‡ä{·9ènơE9ä‚vÅƠr˜ùÄ[·µØ‘aJéăkÙ9¸–”¹…Ñ]æUè$œV¢YßœÄmUơYienÈø$ŸoNˆfU*ưÙÑƯ[ÖèÙ>ÎÖW#„º)£D/Ê7&Œï9¨àm“¦Ç {̉wcZª«e>µØj×-ºŸ–5‘‡ÚA<Êfj“‚é«“);¦ªn^$騣âØÛ§¦’é ¹ ç„ÅfûÑhÁE*á±Vf‰i·AJ¢¯Éê™d˜–^”v9†W-«–Iä®­¶»ë°º[l¨ª.ûáªS₫©×w‚«`Dü°̉®±ÄÛU©ưô×i›!†_‰̃—iYơ¶›Q%ưF낃ü›kR ˜˜U8œµ%V™_L§ƠT˜Éqi(Ô¢Cf~…Ư¬‘ĨÊuSv]|ÜÆ çZZC̃…tbâơŒØW}¹$ÇKÉT‰…^ơM³–È´Ơæ[Ơö5}b§fvWË@·lr„íÖÄÖ%rÛ;7= Ù¦Í5P:FƯá_Æ“£¯ưhbû&´l’URw̃¦¹ç´j‹(Pç*4pù REż¬é(áí^*KMyDé±£½ ¼ĐÂÍö©çf8.m&˜o;M ₫Ït+äBJ”ñL‘́ƠÇ̀·lƯ#}`‹àæL•ñ̀F‰µu%ÏfÁ­]ưx¸—|)u~q÷â1‰‰}Êp̉(÷|æw½ƒó`t¯(…J):˜̣ê%°PGBüR‹~ä½zA¨IEÂS¾FÀV5ohŒ£Đ@ˆơ| !bz ¥̣×:PU§ûÔñ8e¯‘jMñˆÂ8SÁ‚ưªZ «™³~4?º\'IKû®x&ÏÄéGd¨rƒ&¦(6Ó Ư•Ä‚Hx« ¶†Æ±«Ov3ß O±Néç ĂsÈ$¤“¤K% ÉVñ¬å®ơù°WJT×· dŸăÉçFV₫#]€7%ùh®!V|Ơ/bEÜ‚Q b¤)P6a’PE2Y)S’^ Ü¡+Í05e‡[üråƯØÊi…/Ơ³Û¯ô´jĐ)w<Û U6Øej:›yơü¶,ÛäOlŒeb5j2íJ6{YÓp&̀sZQ̉NĂ·•e’áŒ₫MÉÔ†±=Ó„©dV$ªÈfaé¦UơgøvLôc-=›E%×> =°O&éÖ̃̉:™¥¥7àdOFmÊQ-ùç3’ÛÙ–È΂¢nA êfµ<¿¹(Í)[ÊC}vÈ]U®â ߆VT¾²îqƒJ¢̉ZéÁ3yê´—¼…W¾R*¾k¢Ó¥¼ÂƠª&¢+—ø¥”ô©©N*éØ@ ±LB„¢@›Ê·7¬Ó´D¦7X½æỎú YÛXNJñQ5“f³Â1‚G W(ƠÉ7irJǾNÛA+[íjtÓÖ(]Ùè#́¢¸¬'®K9đ¾È₫5¹B%: ¸‚2_ñVö‚l•đîƒ;23¿|F{­̉jXÙ€íă-”Q̣”½5k~%C¯ÎëtÏåµtÙ rt/”ÓÂZ̀Ëë䈉¹°¡¸¼…YÇ©ÀÀñAºÀ<®n£̉îôûdL$êX“¦m’oå=Äb³ëÀ̃—Ár>p«|êÚ#&|À₫"¿fÎoVQ–2á4’XLÍ=Ç­{«I+¢1µ0íV .ÛÚ.×[·×í4̉B)i¯RzX^6VđliÇe{àD1=¿LæeĂ˜® ḈNÖg‰zßĐăR»Å¸ÜN¥|I›_ªw4SŹbBÊΧ¯Å T¼ö·¼ ¿ù{¹ç§ék‹Ü±êNÉ©„<}Wæ—»\öµ½WRÇ‘ĂŒM0Ga'4Qäđó©#L\Î=îǵƯ™yNz¤ƒWĂí¿̣ËDµj¤‹G`9½á̃ © äqIđ́\„ ZuY]1ÜáUS÷9Ü€Íˈ_©Ÿ•B¥[BùY•Á_₫)̃ÛÚÁÛzy….ưÚ|@‰Íe)ĐÁ̀g mÑ̀B|Ø Å’ĐÅJ–YßL|xÉvüQ´DͨVü܆̉¸—j¡—~\ĐËË]‹»ÖLqOÅqÆÑ>å\¦Ù_å˜ËuÁ‘iyHvY!~ÉQL,FjX‰Å$]ï¨&-ÖÑß{ÙÅ]ë—‹×½ áĐ ²º¤HR&̣±ÔƠ‚9>"?M˜u±¾ˆJÀ·°’²ơ¡1‹QXµÜĐ|XZéÊ´|h‘¢Úáf¹kø̉Fè¡`c±a]I¨Å…áX‡¶ưÄbÄäí¨Ü±=Sû1#ä̀©Ñ@z‹¢…N®C¤Æ¢œÛAÜï”~¤ïơbYD‰½”Ë$¨¥N† @ƯKÍơEÍULÏÛ裲QÄƠíÔöÙ4]û &²Ÿn4ăµDüøÑ>cܬh-₫H¤1âŒÅåÈUäZƠX\¾ôViieÀpˆa‘½ñÖ-r! ƯsŽñ  ¼’ñ".e¢¥é¡ E!d:]%̉Ûph‚ ƒI‹©Ä½1WydÑ ÊÆ5XƯ^¦-₫„ÏI`œ$Ϻ“ÍE&‘""Ưµ×áæ9åX½ĐéWÊ=U ₫urœÀí»éÑrƯM`9WÚ¡aÅĐ-Vˆs¥'¬–óø–wLO·( kQ‰-Ÿ!UÅ+Âpªà'eƯ°X!ư†ÅƯ Ú ñË’̀'EDfƠÑÂ₫•aĐiæoDè¨qŸ§͸ȱ^«₫AÜ¥ư°1Û‹í̃PD]‰† 7jÅÀ–“•ZÔÔhQØ(̃¨¡‡FÍ?Îfĩ è ©‘ú¨ ‘Ä@铺臶èWáŒÜµcR©cZaÅ(Ź¥jàÑ=ZŸ©œÙ%)³"¦a:—6‡Yà¬ÎÁ˜6é́‰©Ú8¶)é­Äif”KF)¢©‘_¢ZH£*jjÙ£NjHœHÀÀ¥nj¦"§zê€j @§^j©bê¨ê¥‚ª¨†êªn*©¦*ª²j¦Ö*§ê©j«â꫺ª¯̣*¨æª¬Ö*«Âê©jê­k§«₫±ö*°ªj°Ê*¨v̉œÎŸ“^+¶²Xj)¶r«¶fk=y+¸fkpÓ@V@Đ”#Q©™CN6)“6!…mÙNµº) .$©]åhr˜©ƠSÁ\H9ZCªÆ[‚`Îă$éE,àgáÚü?.ßƯ5Ô1P#ÈæƠRÈ*ÛÁƯ¥)ôPǼ”ƯÓ ß= Ñ\húY¢™lCB¬âQl™4ÀÎä+†_]|¥4ơÅ‚d…Ødci¡ùà,–lÛ¡¬(ù́êuŒ~Q¥T¢ÀBå!]­;á—ºnRÎ: ÎF›Œâ4€Ï>)Óä‰~&ăÀZë ¾₫ăôe,©tÅÓB­ÔíÉ₫«ÿ´-ê…¾tÉϺdb‘¿%ï8и¢nècHnÔ’,É–ë´-mQ¢˜àZ Å|îÀđË¡„nú̀"@^ÎY.ߺî8ny`§Ó=g´´Í 5gl' Ư‚¤‰ªèÙ–-˜̣́jøsf袡¦´æ̣"&ŹÊó’ ×!lø1ÖënoñRmFù`b†Đ yP( ˇƠ‹zôí-bvù­ñV.Dg‘µ+Ù†í8F)ñm#;^Ï[”ÂRU÷Œ^ñÊ/ë¡́‘£~ÙĐ~« ï£Íít̀ĐÁ.üp ¥m‚¸Æ•Ổ₫nÏFl†ṃªe`W¼ŸömüJB—*^ŰƯƯ•^¹¤ÛṛIƯ [pü–kÏö%‰`pL¯ep•îÄú"ñ^°Ô"0xX-úÈ?2F· l  º)÷Jq„°¦¡¤â¬­à̉å2,ƯQ8Űå’q·°ëB` Eµ´mlí•hØă/ c0C1ĂưVmæ ¡| ßXJy¸˜½é‹qÿđ%“sÉĐXy×Ư,hWÂqKΟ 2*G1›ñ7jæ% ß½ñị̂ ß²ăr Qí¼Rú>î»Üiå­rr.²é.\*¦ä¤i›0^YÙ=³5S*6_³6³Ä= _5/*Óø”~²ZYÛÂö%ÍNG8ÏÅ7³³;;ón¦óDäQÆ«=7±•̃³>ï3?÷³‹Órí뛢©T6_¿ 4¾"ôAó«B74CªO¬n6#êùèøm3FOtFotι|ë>‹k4rëíù³”̣³¸kJw+€–Ôª­Æô­Ê4MÏ´MgêMçô«jjM÷tNû4Pÿ´P5QµQÛ*`†R/5S7µS?5TGµTO5UWµU_5VgµVo5WwµW5Xou@;commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/ConnectionFactory.gif000066400000000000000000000127361410126276600312050ustar00rootroot00000000000000GIF89ab±÷”)”1œ)œ1œ9÷ÿÆ÷ÿÎÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,b±₫H° Áƒ*\Ȱ¡Ă‡#JœH±¢Å‹3jÜȱ£Ç CI²¤É“$ @€¥Ë–0_ÊŒIs¦Í8oêŒé²gË@s µ‰²¨Ñ£H 8  AÓ§N£B*µ*Ơ«V³bƯêTÁÓ¦]đªµ,׳R $]˶íHa¿z—îÜ»uÉ̃µ»W.̃¾~¿ˆ›woáĂ€+à¶±ăÇØ5K­åÊ•å†Ư|¹3fÆC‹-ÀàÂ}Q'̀ZujÖ†É2ƠÛƠulØ·÷ª%Í»÷Z~ ¿æ«7wpăÂÿ/~¯c•Ÿ¾<¹t»}kßNxàºq ₫pN06ó¹Ñk‹]—©óçMÓ@˜©ø®Ë¿́lôÔ}÷hÜhàF̃å¥à_î)ŸƒÖA§œTÏqö| 0%•\NE`c=ס‡ÖEà(¦Q‚× Ø•ˆ_UèàyMÑçà\ïƯeăŒç™—£ø^…?†Øă^Á¨Ùpʨâ“PÄ¢qÓÍcX:Ư…b9ƯÊŸ˜\Θd•cÎÇå‹7’a`‹E)眥Q^kæµ™ä‹9¶$’ô9ä™I‰%™Q I¨ Ö˜ç†Túå$”8e‹ÁÉw¥Ÿd&›‡â˜¥—!†Gf¢jq0Άڂ₫^MZ鬾]*`{ÄơɨsX6×a£ï ºæŒ‡öù\© fh¡c"Iâtwâ%+­Ôfk€·Ê%_x†e¹ŸzÉ~µ!aÖ~Đöµír·N[í»ÙVzw‰÷Wy{Ù‹×–óê5Û–́ÑëƠøJ%đ‡^ÙéU #¼œ»đFœÔµO¹:ÙiüÅ×kqu¡k!ÀÚ‚%Ư·œá+îzyƯ—î_Ḱ2J̣̣•!»—{̣_ă-0.Ç+7­É(çk„-¿lô[Øâg³zNiß’c9MœÓưÎŒWWën´¦Ç4{-&PôÑd{ó^¾̉ˆ0¸µi-–zj›ù´Èý×qơèæ₫ÍƠơkÙ€›D±SÑÑ÷Éuœ­̃‘+6kÆ«„KĐí®¹Hgăh£Ó€¾§¡¢»ü^~ùVîÈl…¥ÛÍ£çy¤co®ûIÓ£5 ɨ™¶7Ë̃êÀO^|±?¶^¨6¼ô“W.]î»gÏPçFê…ºÜ̉/dzO8¯̉¯ú^²ŸW¸˜ÀûJ{‡o­ưư ~a³>Ê~ôÀ“›²0D¬à=zÆû™|ùxç;œÂ‚=üYp Û_Pg¼#AGÍ:Ö́ôö#é1poJtJèÁù<V̉º  ¢?¾ü'Ywj€¶$hñ+6₫çÚÙ´­î †q¡’Á±Í5L¹¬&ÚX dlka¤·h±l‰`4H Á,~ífYcƠ´r3 Uåˆ`« ¤¦H¥¸T0ŒºăÏNvÂá,\p#Â\Ơ´,ơå‡ÏêáqT?ĂÜ«¡¶V/ &¬*®ú–`̣C*®67$‘ÁbC5vÁđ‘\ZR€ÈD€‰,Y2K̀²´ .B\Ậ%»¤%.c L°’–,Ù%/yL[₫’˜ÎT¦f̉Ê›ÀD© £dæÆ$:î1‹dç’ÂùÍMq<$£̀¾‚Êlm›…䦉-7a7½₫[ÍñÙ3v¥¦î|Ỳ…©FÓ†<\dA«¨H…S3:$@*1ÉĐË*a˜] vI'fÔ,dá(fu'‘6e¢…\¶æ*úñSŸ²˜:qc&½6L$`P̉j `gÎAÀˆ"DT@RµÓ]̉¨Ôê4GzXO/¸Mï9H¨Å †¤‘zuGOÅÛVô´F5i…§SU‚`u:?´O%×##ë…IqÛ'qT̀í}Úˆî‚Ö´REäé”PăI>Émv |yj³%ä…Ió’ƯD”(O½eL¤KçRXĂÎ)A»j ÎÔYBmƠK¬U₫̉f̉Ä)? ëQ/<©h–ÏVmQ4­ö+²<%̀F…{m·ÂÔ=¥<°£-‘„Ơ¾éHOc «¼¨¦•V¸PbѰø«25-MQ­k›Z[éÆÖ.Ôí{;/ÅÔ7ÖwÁ«"âHù̃øà÷:fé…„·…-KG¼Ö¢j²|́xÔk—ựE—J¬(q˜å¢<‹J)GIœ ]­:KI¨ ‰k´„½đ漓/ÄIMh2Ó¤)¹°”ƠN,¿ÈÈ:–q~êÏœ ̣M7]ˆ)HŘÓ0ˆÔë› äÀÁS‹S¹aMoÓÿ€ ÅdNó₫Ó÷̉$wY;ơÛ9æ±ëƠ”sÍ›ªTá„tqó›{C1/U5HlrnB)Ïz&ÚÑF¥Î=“8h£¹Ôäå5_ÙL 3&Ÿfæ4—éË^EÔ ¶I¨k¹êdÊD™•Ne2‹’¢ 3Öf‰@}Æđ:!r ®ÓºJ‚üº Œ©5JœDËa»sȶ5 ́^·ÄÙÚ́ơ²1ˆˆQÛ)̉µA¾Íí]'eZä·Ü•nfw[Ûê–¡¬”’h¿ÛØñVâ¤̉=m{ß»4ùÖ·¿K"+~ăÛÜ  wÀ³li{-É>øÂñ~œ-\øÄnñjoüăL´uM₫FmpË;¥%7ùQRN'–«Ü$.WH̀#2ó—“­æ6Ïy¿uÎóg+¼ç¾Áyµ~ôѽè?º̀‘ÎôzËIéM_wË£Nơ@½çW¯ú°³®ơJs}é´Êx×gøơ‹@{́$:Ú×ÎvÓ–½íÂ}»öÎw‰¨;b—ØƯëîS¾û]ŒüæänXÂg[đ‡»áºø‡4ñˬ%2%ïLÊó%—·<æ7¯ùÎ¥ó“}åC_Maƒäñî¤ñ̉́̀z9;tϯGÛ†û {ƒ ${wê"™G[™Ä_ч§œ×)§‹ø©Ơë<=D©́~Ư¹?Đ—¯¬èA>ô¹“Q\×v₫œĐ Œ»ù\hW¿ñ̃Gù=öAåb/ÇֻͪZä|oÓÚ?éÔ¯~9Ơ(®ä÷gfEVơ_s•á·N”æ÷ 8æg€ûÄ7²s2•ơ ˜`;Ă5W3u¶PçgIöszd7'Ó‡g‘‚NëĂûcỊc\m´GÁ'Eư”-úGA ˆÇ„j§öy;؃<øy‘çƒBøƒ6ñJ'̣€4{¤6Êc,©:(ÄB„@t8ô÷QñuHØPµ×z|{}cf åz]H†¬7·ç€~CT=‡Ó„ă†)>Å#;ç@˜‡ơu+…}^•UèU˜„I爀Ø₫‚»ÖPI¨Ïóˆ89iS=ÔAD@r#›e‚ú·~(UƠ/|4~„5œXÀhY0Ñ!|)æ‡}…‡$‹́GO–Di¸ˆXGÓYĂĂ@'4‡ÙÅ@-‡î³@¿È‰køăwƒl#|ÈH Û’CĂ7êÁ/ à‡RăFü$ÓQoc›Qw.GȈà÷*,ǵ,#D:$đC>°³` cËØzŸØ<¥z+ĂbÆe®ØCb|täG3èƯ¸¹2Cƒœ±»6<„9ëâ7l¶ftQødE Ó&ØŒ }2wpÓ(s8bh₫!º¢1¡¤g€‘‚ÄQÎh•.ÿf@†ÆÆ¼(dF ƒdYt/×HW¨‘£…}s‡’Ơ- Wà#O:†+ăÄ8[Ó0¬â: =̉8P¹2ÙE©5íWI"d=3Gbø‚tQlø”{ÈHNÅ8>Ä¢:—8;†ÄBÎa$Lè@øh‡N‡½u˜0‰ăăô8¦µ†„j •gô©U’ưhgèI  3Ev—6ƠTÿ¡¨T})<ô—&$™â3›¯ 9À¸<µ¹,Ų@˜<Îñ@I—i’ù‡T0(eơ‚œá4ªèOJx€{$h¹HV³>…I›@Œ₫“›ØI™T(Äè›'ÔYÿC!üC‡˜H‘^1œóWơ¸EP3!’æ`˜U%èaê5/-©/Vó} {(iu8˜“ƯÓB<̉=´ŒØ)>á)!qÓ— ª6êóA·é›̉Ẹ¹CIƒï\3cHĂ1̣Qgơ(&j¢U9G`9:ôc&sR¸‡{¹„¤ă>€©A˜¨+Rø‘`E˜Œ̣ Đ³£±ăA|"aÈ&h$ư,9J)ô„,ø™¡/ö#ö¸‘%>Z’7#•!vN~…_¢‰0å3Ê b¸} ¢ˆ_>©Ÿœ¤6˜Ă™„Ä'•ø§³¨+›₫S˜@&ä;Ƹ‰¼Éz µ44—̃ä6,ú[`©Q脦7¦ö =éHZCÙûSJj¹‰˜u¡à£xh”i:†@»̣Y•™±é¥T¶1gä.¦Eè’FñÔˆe×—%Ar[ÛµËÄi\ûµb¶dëµeËck¶j‹¶gKri;¶×6•! ejv‚{·cÆ Wá5?F8N1ˆ—» µ†x¸†›QyV%™!ªƒË9ó䜶ñ{yëœFS• f%FOêµù¸LÖ®‰‹¸¤;ºcb**è" ‹i9Ñj­–j5»—¦j:»f»¯KM£6»¼«Kq+ ;¼Ä[¼Æ{¼Èk ˜¼^Ƽ]w³Î½̉;½Ô[½Ö₫ ×[tË›½ï½Üû½à¾â;¾Ö»½äK‚çkr̃›¾ z£÷¾™—K`+¶®äñ»J“×J­TKñ ¿œ'zưÀÿ뿵”½7—ë—”INI¹èẼÔÀ<ÁÜCë‹xà§y¹•ikŸ̃r’›¹UF” iæ[xéç‘+Üơ–øÊ0+̀ÂÓºÁIåO)œVÀaR¥{Zó¬å®#ÓæÛĂ,x¡{·¶ˆ+tkC9ffaµ8¥fPLŰqć™^h‘Ö( ‰§DKdèZ²ơw–è’9¬ª:Yj†[¼‘œR’4ÂÆ˜=°Ê%<\‚Á"Œ±Z‡ø(¦%\”fÀø…å#Å2<¤« 9́•!ÿ}¹›ÚÉCkº|ʺ¬ŒÚ<Èă;µJ«毵¼\U°”´™6̉̀xĐùœ/ÜÀ»NPÖ~‹1Àg°IKĂhƒ×+z¨ÓI¯ ˜|ÉbYDđÇ“½¦HâMüBÑ$ÔATÓNI;Q¤Äù½DUEÉp%€Ö6 ¬®2#ǴỄ!)DoC0:{₫Xüw;œ¸ èÎE’åu·ØÀLƒ1NÆ-DÜàúÆßñíO" â¸-S·êÁ˦J‰ă¦lÀDȃ­¦j¤æ¥æ¶l;L$‡iM.»®Fy;Xj´{ä7Á¾\̃å;commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/Delegating.gif000066400000000000000000001052011410126276600276070ustar00rootroot00000000000000GIF89a­÷ÿÿ”)”1œ)œ1œ9÷ÿÆ÷ÿÎ÷ÿÿÿÿÿÿÿÿÆÿÿÎÿÿÖÿÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,­₫!H° Áƒ*\Ȱ¡Ă‡#JœH±¢Å‹3jÜȱ£Ç C.L Â’HT)eF– X–´“¤̀™8sêÜɳ§ÏŸ@ƒ J´¨Ñ£oŒIs ̉¦Ÿ•)©Ơ«X³jƯʵ«×¯`Ă P`€Ù²hɪMËv­Û¶ÚxKíܲÊÖƯ wmÚ»|÷,Øm̃NÅ*^̀¸±ăÇ#Kf\ A–-c̃|¹3çÏCs¶| 3èÓ¢5§FÍÚ3fƠ«c·-;öe&ë̃Í»·ïßÀƒk:³iăÇ‘wVûµrçÆ¡#‡.ötæË£3¯]ûóíàµ₫çN¾¼ùóèÓ«§Œà2ƒö´ă×Î\Z₫è×öç¿Ç_;¿ÿ₫™!¶̃€hà&XPeÜ}‡ƒ̃1À@}^÷Yi^‡f—aw6v¥`“‚(¦¨â,¶(”ZWũƠh`#̀åÈ£uÉY—£†@θ#‘ƯI÷#¹Uåâ“PF)å”+2h#ˆX.÷†9êh™ Äè†ü‘ÙÀª&¦–Ư0d—]¶iÚœuh…£ye’– H埀*è ºUÆ'’@ªÖ̃rqN8dhxvf§i˜=áÙ¹è}CVªcî=¸ew“&j$‘Lªêª¬¶êªO₫V(–zz¦—pzÉœ_̣êi—¿âÊëeĂâçk`¾©£¯·v:l‰̉êàx¯VkíµØf»`‘FëÜ–ÊöJ́§…{ë¹ç>jîºË ›™º¾Úú¨­·B£̃&G­¶üöëï¿Uf§$¢ à@³Îº‹0ÆÊënÂçîÚ.¯ #«£Äªån¯Ăr»'w¯í đÈ$—l2o†₫ˆïÀB’Ë.ÆơÂ1»èú8¯¸;_§§^ôr"ŸlôÑH'T¬ ²Œ/l¦Û±Æ>J¬Ïï ³Æ w&³×ÇJœp£z:-«f~*­öÚl·íQʬœ™{†©̣¢Ñz)₫›™áY}Đ6Pªà¯áÍ·´B{W´ÛŒ7îøă$PÀ½₫íw…ĩZj‚z܃›çªÅW_Ú§®úê%3hø‡É•*ƯëYÖî­Ê°çûÓÏn»ˆ æ$ëÄo| hf¦|¡j 8€¢ ưôÑÏG½m¨¯ưöܳøq¼g ̣îÀÛ|–½>~…ë‹:ârê(!nƯ×oÿưÂ]úơdÂ7iờ“Đ₫x½†@‚[₫ÈÀBF/z1ŒZƒ—³¨…,s!K2ø— z°ƒá#—Đ„lÉ72 1%F‰¥@Îi’oºó“eA°I‘:>€í₫= °FCÂóŸÅVZè"·\0.H1(ÇІ:”‹ĂDJDJÑÊ&ê\JJü4QŸ’£ ©H­ÅLÜD$éhINz”ô¥0u‘KPR†ó”G¹ibbÊÓ¦ˆª>}JÔ¢®H¨¼ü RÊÔ¦îf©TªS§JỢ@U™^¹jU·ÊƠ¬hƠ"_ƯIX»JÖ²e¬A+NÔjÖ¶º–?akIäúÖºÚ¬q•ê]÷ÊWĐƠ!I`ûJØÂ^3¯Y5¬b‹Ơ Ö#e¬dÉÙ„T6©“ͬfrÙƒt6ª› mh?;O½ö´’%-'M‹ÚÖVµ₫mEdëÚU±¶ÊèZµRÈ+ªTi·ÅíjAâ‚ÅEîq“ËÜå:W¹ĐmntŸ+ƯêR÷ºÓÍ®uµ‹Ưíz·»àå®x¿;̃đ’÷¼ÄÉVH2Đ̣º½ï5¯|ăK_ø®·±Å¯~ Ú€̉¶¨ Ơ/pø«‘ÿ&1À5°€‹B`¼®w{ îi„lU¯4Xii†)́QtÎdĂ¹đÚ@,RyrØZ$fˆˆO–â¶øÄºyñưdLQĂ26î^ºă3¦ÇỤ́?…́ă°¹xGvg’‹Ü•%¯ÎÉƯ„2“½êP)GÓÊS¶ –·åbv9Ë}¬²€¿ f`Y¿d.s₫P̉̀66«̉Íjv́™ñ ç8‹uθ­³‰çÚêyÏî³kÿ è‚ ºµ„.´`ÚD+²è9 \a&Æ&“NÈ¥²b-ùÑr´¥Â’LR*¦NHª+ŒfPSÉѓδ¬sD.AN¡u®ukSóÚÖ·öơ­y#jFÛƠN¬"ë\;»Öiö°§Míg ›ÚËñ§‘¥Dg{Ú̉6³kÍkk{×áÆµ³WămsûI°·¹¡íy§Û̃ç6å·'ś\¾Jư–7¸u½ktÏ[ܾ&ø¯ÙưTwÿ›Ew5 ̣çœQ%•ñNùmÉ@¶” È₫G̣Vü—('¹ÈKî[–«üä/O¹Ëg¾̣Ă<Ÿ]ŸÅi~s›ËÜç1:Ë)t óüç=Oú/{+ŒÜèPWzÑ¥ƨ#ưêSǺ"I¦ª@%&ÖÇqîT‚́K§]E’{Ǘ„‚»b½v‡:]î[ù²LênÇÆ2•xÏ;y&>U§÷&í]áûUn¢øH6'§Rä›9`Sú–LÛ›¾ñÈ0ƯÈ'¿Êçÿø®Ô2†Ïyè#szÅLÁ¥*WRÿ/¾…-¸÷‹îÑ’{̃ï^ƒ¿KđÛ—̃ß÷È?¾̣…Ÿ|æ/ßøÎ₫pŸIö¦.ÿùĂÏ~ó¡₫Ï}í.Ưß¾÷¥?₫đŸ¥,O%¿ø×}ö«ûÊ/¿üƯo₫Ằ:”Çö¯ÿ₫«́ÿs$e#€ü€x€°±/¯×M÷$X€èÈ#̉ƒ€hxÜÂO„Ḉ%8ˆ8‚"h!$%è-ü42Éó4fĂ!›Á!H&c̣9@:t"':89ˆtC2H×A9ñÂ÷̉-zR²€ß>g£!£̉™CaDh7r"x‚†ó7œq)=H…4’„¥±&`87¿£„h£0qjWt'e¨75¨…>ø-è#=ib'I˜†<‚a$8(ˆs˜'ƒ₫L34çĂÉa„ĐR…€Ø·!#_ r@xüá…•ø‰Wxh¡‚x†;ˆƒé-Kâ?áñ7”²9Í>ßa/(=†"~³˜‚8W²d6ÑD-h„­˜)2h6hèCˆ€¤Ó4³Ă2b‹‡c9³Œ˜ˆ@¡?ù‚*WØŸ8#ÉH#̉80¶8„F’Œ´ă‰¥ˆXVÉ£Œø¡R´±?߸‹øÈ7$#VH‰é‚)@lx*iÖ‚}€Ÿáˆºxy8¥(‹”¸9ñH‰‰Œ̉‰!h‘¡?±ˆrs‹7r@s'•(&ư£û₫*™¨%£¨<±h»(‘é’ù" ´g}Qè‚´h9y5)É¢)iŒ́x#S;5é¥b'u2$~s’¦±‚b!J†R”I;`rŒ®¨c2‘é;¡•iB7É&B’°Âg£1¬5X„3ƒ5 Ù,zĂ‹eY‹P£0<9@iv™:PxÈ5Zb'–,Ù2½¢–³È(ṇ̃‹â€~é‘´X„0c6M“¨x¢Ô‚“x5Yâ&sư(„a/Đ‘•ŸÁ5̉c•˱&¶y…q|X™ؘ:roؘ·­£æa`4S5÷=e¡(Î&³®›z+¸Ú¡˜Ú¬E©·ê¢Lj®ÁZÀ9®« ’ȱ«9œ×Z© 6ç‚>Ó1‚*1z§¿é3Ó*5p*₫­ºâ±v ¯'J”Ñ1Bơ5_ö…³:{³<›³=k^ä³BKª94œ!30²Ä³)+« [§ê%̉)‹ÎZ°z¢[™ưÉ#Ot¨×äµh[dFf[`;¶c¶’ăµjA¶Ổ¶c~d… ‹§GëªFXµH‹ªoÊ®æ¢9¢3V«®.£a)¢±8Ñ«JÈ!’ɤV#¬ ›®m*®Zó®S.¶¨°¤–«_ÊŸ8z#¹1B\UƒÊI¢®i«¢`2¤á®±Êª«{©`3¬·ë¡' ™Zk÷xc›¨>ø¸¹B»^z,>Ú®î±${+²K¬Û%°i1 ₫ëºI6¨¸3Á±Cy‰A("Y‰3+> ¸M:¾˜(#IH›D˜˜ؾZ©~”]ä„ a(?H³<2¥í™ J‘@› Ù0ç[„ÙÙ›•8+ ºµzÁxû g”q_[Ñq‰á©“i$Í©à»Áq*¯$ŸH"¾ª;’—kZ'¢x¾Ÿ(»¥Ó‘ Y¢é;Ưú¿J©;Ô῾jíA}[UŒq³!4bŸY9p";Ú>-J“MÙ7ÊI+K<"[Û-˜a¿‘cHœ†x§R*—¸³<“R‘Ă"&ŸÙˆù,e£–Ö(G²7j́¿m82̃Û­·I5L;đk‚₫µˆ– ‘OÙÀr© …< ¹Ă¯‘6å Ṕµ)Yœ)|—”øŒ¶q »HÀAèÇÚ9ƒ¥Ó‹¡¢Æ¡I³"lDŒr¦´w­”z¡4j÷ºz·ơÊ"7 y Ó¹¾„ÇӓQ €æHñ8¾…ă4SÙ'-|/ÜĂÿó1ÔX‘‡Ü,S&ƒI…Ḍùx™5"‹¾K\́E₫zœ´¹Ă7,ǿ؛ÉÈÀ¬H'Á\ʵB‘$&ÍŒẠ̈Í i₫ôÅ™Gi–‡F¼9Ëh9¹l˜ßR̀›)ÅÔÇéŒËÙ1†÷1Ïüø?9x¬¦/¨ƒ\Í¢ˆÂ/Ä́Ëüø\Êj‰½́₫NÚ„Ơ·Hû&Vz(T™í;Íl!'}̀9©Ë‘ûă©̉3ÚÈ,rü¼¯;§i-ưK¬l¬‰‹’‚—f¼ËÓÉÍj2‹’øÇœ$‹̣Ñ́”t‰̀ó=U]@—q†>¶@ÓcÖ¬á©éÖd”˜”+#lâfpzmYjúÀ惀y ¬đs'{Ơzˆ„<¾c©ÂókÊ#Ör­™,)1œ-×­¡‘œă‹ À½sE|?Û;+´¥ ´Â¢-´^ÛqëFq8·j̉6ÛÏÆYŸê×ö¸™¶‚#sº’è<́‹lrÆĐ2–ۣ̓{’ ©¶wÚ7«{ÎmÚ=₫¶#óÈ aœ­7JaƯ7d× !Ûø&p¶Ô‹Ó¢hÜ\®¯;1ØK½]#¹TiAœÜ¨©ø‹ßlÜ(±\`‡e)ÅR ­-(ñ̉–̃GÛ|ÍÈåƯ±ÓÁºZ‹3¡«¬nJ/H™ÛǴǾûỸÔᇕß_7H µ˜×HU±­x­pá=͉̃̃ó‡́꣰û2Fª»v»À ̃ØM#â5Á ÆØ/AyúßèñC¥+ ®D Æ›VÔóT“;®ájÚ¡¨ơb­™*5¡Q1ÖáNÎÎáăDÔÏ@qß?¡æỎuèTCùäæíç%Ns₫æx~çz.ç₫|ç~ç€ç}è{¾Ê« ”û2è‚₫ç[·Ô$" KùÀ“œ“+*˜f:¬8¾·Mü5b~Ụ̂<Á¡è…Nè¦êövŒ~ê‹ê­®ê°NçM%|4 å4àƒÁC®Ôh>OÊ ă+,ÅG(Çđ̀’ï ¬ êËÙ¡NæHbæ?îsDOEÁ¤Ê¼áæ$Á äZ'ñ•OI@l}î¢ñŒæ̃Ù==9˜*Ùât¼~2‰4µÎD5 е¥ÄAĐî³;áđlˆË<đ¹<åcđû3l^ ün£+Á»¡½Äí£%Íí¾î¢“ñ¯ñÖlÑØ̣äL•=w₫Îdñ™Ơ€èùï\7Pü>>(Ä-Ï;åSó0_7 `"÷₫pƯrĐÔÁÁM¨Ơv$ƯñF¯ÖḱñJ=—Á•ØÎLÅL,Íj¥åg$ÔBt‘B.”ơ\_B„¡ơÁ§Bbß`ö0ÔơXïơtB?ï/Ù=R"“FÁQK%` ?Et÷8±ó âqÔ₫N€qAwạÑƠÚ§|ïT4`Ç/©ÜëEÎH‰ÿ`‹•FÏó%“÷’ˆá¬÷ EG¶äùP¢¯¹åèçQ¯ê!úđÄor“¿=ªú-g —i‹UI©¤ä± »OùØ= oX̣”ʯûó~4ßn˜?_ËÄ₫”üÿṬ¥¿_¦ïV½DËTqG …Ãßưàÿưâfaº2₫è₫êŸ₫́ŸÊ½ïMÎô₫ïưuüÄ“BỊqSfÿÄ @H0p ‚dØĐáCˆ%N¤XÑâEŒ5nä8€ăG!E´(äI”)U®dÙ̉%I/eΤYÓæM†2|```Á…8…%Jr§Î¢I•:Œ¹ÔéS¨Qm6•ZƠêƠ¢ hÀU«I¬aÅ®¤:Ö,H°gƠ®e+³l[¸qå2Ü9×îÙºwç¾ƠÛ×/[¾f™°i^‰…UÜ6mcÈ‘o–\Ụ̀C¾_挑qç°₫”A&QtiÔ}ÁæưœÚ5Ó×NǦƯùtmÜboçN]p7o²À…C₫=Ü8ÑâÇ-/L®­sèv›G§®rzuÅ›±‹¼¾Ưûäïá_v_>ölóéq’Wß~ {÷jµÇ¯Ÿ₫ưúøơO´¿ÿjùüËI@¹+°À₫|*Ạ́T>.B ‡BÏ® ú¬.ẹ́Đ Aüđ§9L+DET1E ÑÅalEk ñh 2 _¤ñGƒŒÈ!…l‚ÀˆœÑH™T²É"3hÇÆ̉Ñ¡'³trË" Ë%» sL(Ýñ¾%,è ‡̉́µ²̉$ŒÊ6C₫J(6ă’³N³¬TÈ, ạ́sJ>³ríJ΀ú³Æ» Gé,oϸ5kÍ̃ ’4;FQsT­ 9³T°< ÅêÓ¥6uêLTñZôHSkéÍËT…lGJÏjµ&H Eó=_ íPa—ƒ•´Rƒ}5׿zưëË¿˜ơ.Ù¸¾âj«°µ[m³½¶[p¿—Ûq¯5—\t·U×ÛtÙ]7Üvá}·\wëEWÓD¢W^{÷ơ7̃çxà®¶:—_„î—à…v8[ ´˜…fXă‡ù•¸Û3yă€¯Å//iÇê©–`¹å—pùå™a¦9æeÆyç›{n™₫sg›‹ÖÙç£饕&:館ơ¬œfú馡Îzk¬»¾:曹₫Új²µöºl±mf!Q  ³Í[n´ăN;mºóÆ{o°]ö ÑXƠ o¤~ù€¨8 g–G<æÇsF¼fÊo<éÇÁÎüèÍg¾r+¿ÅŸ6ütÑ©•lpÓQÛơĂaç̀k.}t—sÿ¹rr‡»ñ×§}ø×/Ÿ½g̉³†ºđåa›åîFÉÙñg¼öØw₫üp—áö\xđtá¿ïyso¿å̃^ọ̈m¾xƯe¯?xÆOŸ:SÅXg<­rØ«_÷à4³Eîg₫2c@íÆ§»ÚQN|”_ñx´ơïuÿÛ ₫ ÷ª.€}ë uæ¾̃/făSÛó`†½ÆÙ}/ _øˆB—¡|ëĂƒ7·åĐkRÿX¾ßIp‡´ ¨»ºpf@Ó èâÇ26€t¡»bM˜¸ÖQn®ăzÀÈöºÇ=Ömo¨ÉÙ‡„?<‹{pă#₫hRÎv~w¬đÆĂ7Ó<×µôKønó½hv¿•0‡Ẹ́½ŸQ¡‘¿Ÿ#«iBº±s³¤èE‡Ïbvf“× !Ăÿå)R§©}å ¼´ôó™ơK¦ö«¦÷Û0Öë¤Ùy½Ü˽̃{º´:Ü{ÀØ‹º „@Ø«Y§Ó-S̉›H΅A*¼Ê"ṣ*|Ú&¹z™Mª™vº*4ú! ½‹̉?LâBE|-/¢»7ª"’D* ₫Û£;¡Ǹ£¨AƯ¸A'ü@œ¡ÏñÁëÉB.’ÅåY?œ9Å£jÂOä£B$ &DBPdª&bÆô‰ÅJ+±̉ĂtÔœ“₫bGxrGD-¬̉®¥Ÿ±ƯÚ”w[Hè.?4Çt¢¬(´%́"!d¬F‚")@lŸàB²QD+Gÿ:DđĂÁ×êjt€?dATô¿­ª=̣À̀Ⱥ1ȯÉF¹°?—,È:ât(] El¿eÔ¦†âIôI` q³‰º`H†8¾jF¦´B§é™́e´G¥AG¨?́B%”25£l! ÔFˆK¥`ƒ)‰ñ ®ˆtñK‹—sñnÉËñ–L¼ Lo1~q̀kQLlÑË¯Ø ĂtÈ\LÄÔÉÈ̀Ä´¿äLmé¼$*¹Ê₫‘’¸0½¬—®0—̀T̀½t̀»ü¿Í ÍÚü—ÎÜMÆ|MÍœ̃ŒMÄ„̀̀Ü °̀±̀páMèôéäKoÁJ½°Ë‚1̀׌ÍĐdç¬ÀT®hξÜKvñÎàüΜNÍŒNö\—ïLL½„L‹©ÏoN÷TĐǛ‰¡rŒp¢,É™œ›ưĂÇ]Cñ;Hk̀ħtPÍ)¤đ=4„º©»ºßÓ#$¦¦̀)J-ô¡uÆ|ÄLZK^ZÑFeĐ•”‰•Ă:¦ơ®s§êÑ R|ä¥çJÑ!­¤—¡ËÚàF•1Z̉Sd₫A´äHœÙG*mcû¢íÄ I£­¦hC^̀P u µ̀¥̀É/âI?ºjÑ*£=́À‘RË¢S?¥­)Ä*[¡„uD,.Ư ‘$”ª-³DMÔÙùR@ÅÓ̀jQ„t39DÂD;TÊzÉi‚Ó#ü3íÓr©56—ñˆ…@S̃ÛP Œ@µ­rtÆ%Ơ~̣¦}T_ ™›{LƠ\}"­̉'€"j¹4ȲLPQíIŸü³-4PAƯ©ÊaRܸQ‘¨‹dÑ â?öUoÄÂ["ÇqMWH¬©*ʦÈU×Y¢1Ô=5½W²Ö}₫%W ’ÅDWXyí#ă)ØLBѼ"X†•׆…¢ µŒđ¢S¢"‹tØkJ‚zXŒ}Øê¡Ií×…nÍNĂHŒ >…{É*H@\!äQùb¿¤©*M×é»^Œí[ƒâعb&íÛ?Ô_û%_đ)Y–¨˜Ú]^ë²^}̃¬ơYY÷‘>à×âßúå_d܆™ˆƯ.}5F¥RÙÍ3ë²ÂùÑ´çIZJ̉«\ÖXa×Ñå´ UL¤!₫¡̀ù´?ơYB¼E`ü^¸5ª•‚<´€»"Í₫"ơ•Äø©SÅm¦HÍZ¸Ửó“ÖØŒÍĐʆ •†c cFă¹ÜÇ b„3¨®Ó®áÙU)ˆ̉Ûj + bt,Đ!T­ÇIÚè…cüŸ–¬9m]ÔpR]yQ¼=,ä‚),zª¿‹ăL{¯ºê7ó_5²^çSà÷´7eùÊ%>¦+.¶ùƒ“iŒägÔă ƒ>³[«yk© K`ö­Qö7˜Óă§2®¨4]ií]lư²‘ÆĐ4ăÔ|\‰æeiˆ‰mAX~`J.»½ºdÖÚeMnbY ¸m†1›eƽ¾ö4Z&1ï=éú¹2‚i:¸Å)8öäç-»¸ógYç8~ê²3¼nÇñ ă &G¶ ®d­,›1&iavg¶¾7‡æ"®&/—V§y‹¹ch¸ÆëØIe›-ä©ü טGäạ́Rª«¦¯¹¦c‰êiúëo¦¯½fë¼®ëNé«̃¯ïưR”Ê₫ø dIÊ-–¬Äª0`¿¥ç{ë8ëÍVéè38^†,—¾0úrm-¡ÁçúcIщDÅ =ù%äæ^èßVè¾i¿íJǽ”Ökhçfh¤È!ºVÊN³#Ê^èïÅj̀îjÿ=¬~†hÇo¶&dî†oÍÆƯºl'¤Åc%Ä …$êe&jN·¢-pÀùϹä̉ÉA*¡¹ëÎ}n¦~oûFa7íè°ÑăÜ̃lÆ^\ù®î„¾ïξj".i›Éh̉jä-Ö³µăRf·̃·{³.93*‡¦ïg±½€Ó¹RÖñùî:f 1]Tq±@₫́¢‰à†²̃Lënö¾å»ư´+gJ>r;4^Îá€V»Ơắ_ío›î¸1 Ä8^º`ÍDIs7p¦’­@Ÿ$_vl7>÷óBÖ^\¾/h̉rÈúª-7»N¦3»bôCWè¿Ư&%odän(̃ÉĂ}ÄË¡Ô9~FPmáúqÄ·<¥7Ä®¬~¤¿½?ăÆQ*e#.t(„DO–Đ b+:Rø#Ñă™d×Q\ËóÂ2G¹:l1j­0êbc'vhá d‹‚yvĂv$Iv$Yöj‡vj¿Cv¢’l*ÏuP+%uÈñiT-á«nV2# Ó½Æp,Ø₫MI ‰k÷ÿyÓrlÆá²¤W¼œ%Ö£?F?F‚¢#>½Èm"µ+ø¾º÷«¨é”6H¥~îˆ!Y>.D\‡–¢‘$ÎUdNh¶âTܽ¨ Œ4b¥så¸%öAVÀ…y:¦¡V”-µĐptñtœ¡±iX‚4JY%œ‘N¹ UwúIa—ĩ~lqÇ”¡H5”èC Eôæ’qÎHå£sZy%„uR¥å¥J• 'Z ©ˆ’§Đ¢A5 ©q¶ë‚ÑZ+³¯-Û,X·úP^ êwg¢èbN¸w¬Îø(±ºZl¥Đêø˜µPu«+hƉ׈ÇƠ ï·û+§ªÈ¾:éÀ₫ơ¬ºu9Jd­½Ø.™oSóhZ¸Æ»q²oegÂ!ƒ“¥"Çè·æAu€@©Îµ$§-¦·²¨̃v€¿[øEư¶%.¥«F9+ ÀçGî¶–€̉d¹+áÑ8}ôGL=5ÔîN½tÓI RÔ[WƯu»_'mÀpµ3A`⯩ÉνÅ[Û¼Âu±gǾúĐ‹)s%tÁÂ&3æ%ß…§·ËÙ@\ä dà̀Aá|q>ïÍ^̃—Oå7¬•¬8ê"ơ™:~–HŸ'©­˜ÛûPƯôuVêfí\¹ÁsløA@À.ë¯Á4€h®•·B₫‚g;Ú^yăv“CÀ—.Ÿ÷GwĂå₫KºëE%üL€–ÊÙÄ aV½¶áQü%“›U¦ûëçñ%x ’·ïŒ5́; êh›øèg<>áđ$̉\-‚ëËç¸'¼ q0`“Îê€<Ù/$}áHú$B–À…',Kkœ‡»³¨,}¼ó]ïj½‡9Ê\Cƒˆf¾#)îcDS`X§ÁàÜ$0ƒQE@©º/ÚR—̉R/Ø›z%ÜWú́Ù·—fËüëRÁ³´œr³¦à,¤aMâMÂjó1̉¤)M àÔ3Áu’^-VxVñ\²qaM'úäÄ™ÜÁMXÆèHŸ€ªƠ¼{«¾"WxOƯ›'Üçid;VÔÈICú8}ºS¢W\‹›‰ Ųk‘ÑXAÀ]¡£̣“6,´´êx Z霯Ø8üñ°É0®È]¿l‘βeÁƠƠËx–7G ˜FÄí2uÄØZi!d¹Úá+ưhg/ºÆ+¶’sđ]ª¢Ù•5s–ÓN1zăàâÏ+yWO€D¤$ÉÏ8&Óơ¶Ơ-PÍ’ñ#µẉ…$ iv‚ÖªÿË«Áq$t .¤₫ li‘$-I)ѧM1¦Pnzöô±Y¶-P*_6Ô±ÓäjÉ—@’ÆñAî¼ë y˜ÏÊ­k‘ˆḾ†É („ëîD$E`ÑkWÇ4³;‰ëJjÛ̉ïêÎr¥È!Oß b-rJˆ4hà̉oHŸñ÷üŒă²tÓ«Â< blưăU~b{4\̃¶k{œïƯ•»É"ºaÂ91B{ümÓ—oƠmíÏnÆü]U½1®°xEϹ´(S]¦RWïP….́Œ/Ù(ÓE–oË'ïïÂèâ2 ÏC&vGŒƠÛJøªSMô"å.ƠK¹úÖSí”D-ºç'::snĂ}¿¸¥ÿk÷₫ŒóRªÜÙBïă±”Sl^fÖ;ÁwặIÖë¬n/HÜŸî¬nk°Ø¿b’±4Qá…¯«̀2¬íƠùđ̃­´âk’¸Íă _¸̃ă–¿«Û܇Èñ¹^q¥Í4äëC«å†$ªJ´Y2ÿëïéñ°ê S}¿ï¶pûÜøMvăøTăÀ"+桯y;êí=Ú÷ó:¹­ri—‰P¢>¾236°Đ¾#Ö×qÔ\ĂûùÖYXÑ“ k¢ƒ6Ü¢ö¸¡̃ÖÍÚä‰Îñ–ZdN¼ƯZÓ‘̀mƯÏ₫aK̃%‰¶¤JÍ´´AÛ¡t¶`pa E<ÑæQ|₫¼ßơ‰…Í}’·%Ó"µÅÎ8U†ÑZC)”„­ØnüÙjĐ‘­ß̉1A  ă)ˆÛ¨”’8N•ÙnHĐ-áoíàH_”éÖ“¡__‰T+uŒ˜AôöíĐeaש…ư0á}Ö &Fè8ˆ=ơË̀îQœz•¦ ÄG”ƯƒµÅË •}ÈvE…ú ØËÍA¡aÚí‰` ‚‡ZÜÅ8Àè•\ØÖWĐeƠÁ‘˜Ü„Oä̀Ä]› :Ư¶í¡·DZmHßÈWSí: •嘒 f•aeü 9bÆDÜ!ë@ râ"3Ëè0U₫ûIƠç5â0¶ ‘MÀ9Y)½N'_Vn™8̃ f­ 3>#C±ˆ4Új}†1Ñ0p‰=Öc¥âQ©#:ZTÎvX5ÂÆ½#êX•¥#À¤¢31bí^VäX̃ æhR©"á±! ’̉D-¡1€&.ï°Mg)¤ç¡*B@bœ—äă9¶¤K¾¤EŒ"LÎ$MÖ¤Mj„0äM•ÅF"®cCFă¤å2fÔ0ÊĐÁÅ—a–†`L–å0ÉIÉSañiR¶$d?2äVÂ⽋=™•áăX₫S(–%B%Y®%?zÆb°—N~E µ×âW₫$^₫¥Iêeå¤ZƯ[æ%:åØ^›¸wÈơ˜gĐY]¸Ü"náEƠ-)%Uđd¦3>EÖ‘fRÊg>$!M\–&J c;æ¥Cîåjªæđø%UE]øXHù8‚•È‘ăæµcR;̃%é ÎW Ú ̉DÍrº‹r2'ó@gsFÍs.guR't¢MÔÍt^çt:§tFgw†çx–gv’çy~'s¦kDÓ#fYj̣¥|¶æ|VR¶UăJ>̀Æ ›nKÀÍáÿơR¡ơºˆ³Y`á=aœí%0̉'аâ¶!% l²§…¤â &²¦P̉§‡âDâaÔ₫ÍÙr¡]ë_§¹̀¹a đ¹̃µ| NĐÓX"ƒÙed̉ád’†Zèâ¤×Ó-Ê%HT(ˆÁ熺&q~h’FƠ}#¦q^\T˜ßơ] 9¼M]῭‹ƯƠ%H²’gçƠ"\BË”é'ÅcºFÍ©»@"fΩÖéQä '̃©Ÿö) ₫© *üˆGœé¶@êé\è\É!DÛnÄ™&Ä0 ‹Í“ëô hˆ‡̃h^–cJ¶©q™*ª²D6é‚Ó VH~h#M²¤>•ÖP­‚¦®>ä®*hÖÍ[h„¹R…Øéư½Úë₫‘ß™4EVBCü."©˜†*„¦*† ª¶Æå«2!§¸nçÓ”+w+¹¢«¹¦+»>ÍÑLçvª«¼¶ë¼®«½Ö+¾̉«¾̃ë¾rça]ß½u–0 hµF‘^ùêĐ 6Äßf v‡I,“va·âÉ·^l@®`8+ëp«©Æ"Pü•áXÏHzbX½Ùxé—IáʵÅ~Å’?¥¤ÙQ¶,l¨©Î>iÎ\­dl…XÍb­¥©Ñ˜óTåPÓó`•9Ơo]R0ÍEJkE¾BN¬ÍêsgÏN4…-J¨– mÚ~„ڦ퇀ÄÛ²íÚZ(̣x₫„ÈX<‚,å'µÑÚi"­¥TDÄ %ơ ÷pföb&u¨áñW•èÙÆÆƯF.IÚ¶­Úf®Hh®Ü¶-³°)³¼)ϪƠl$mqÅŸ́lÜsAíœÁÊ‹œYǗPAåc̣ *†jéjQ®ï₫. %Đå­ܲ-æñz.x“̃̃Ç̣ ©æá5¯¦ôô8™láîôg­)İîN8æ…mqÈA2ñ¬+.đ¾oª"Ïđέ̣rṇ̉m»DÆK@aÁï¡.^ŒØéPŒ‘Û˜©q¼‰nhÛÈßœMÆ!9­.)q^Îú/a°NN(J ¯Û₫z®wë³P¯« `.…Ÿá„ª} µ‰¤hÑíÛ§úÊI™dÏzÇé5¥“بîr|@n ÏD˜î#×J —ƺïo‰œ°§ ÜXËo ܾX –Ü!Úº•›J±¬8æ[ké\pŸæ§àĐ¥Kp5q7‹ljÅÔ=²`©] ó9_V®(¨lZ¸íàEÚ% ‹“q×’*ÿî`ÅqèÅèfŸÆÂ±#ïÿFÿ]%=jà™[ÈØè¥̃¢wÜ×qüYO4̉d†)£ä"W2,·Ö\’¯Ç2…œđ3öƯ²°‘XŒ²Ö˜³~àëíߪñÛ₫ ®ërI"²Vº#.G³ï®ª¶>/dI³«ăMđªQÍ–g’\AÚ?nÄ^`qܵ:³p16÷ï;×-ûîÏnÓ<Çslè2pḅÂZâUñ%”$-’ h^ÎD¢̣™àë%Øâ3ÍQ2D³N1²Đ=ă…¼̣D‹…¢¢d6’–́fa9C¡øYD)!wuN:O„.´iÈƠ:×'h>ôD3Môn´-Ơm_4Nç2G&!m9ÅĂN!w¥h‰U"n. ăÙă3Ë´B…FGn#÷ôjÓäb5WŸR~ö~Ơ"Áư"˵$“YÅ /f„{-Qv₫—cµDwơ¥tl×µ];Æ#ˆ`£Üͯ¼îĂqŦQƯ´8ΩHb2SĐ)³ï:¨î5e³OûnUW¶Jôµvpm".*Ă‹­™}ơ¬™™B‹€ÈoLXv%ÅR°åd¶f×6ĐÆ2mÛvI eöîgSiÓßƠ 7Öà÷Y₫ÙƯon­₫ÉdƒÆçî¹s4׳n§Î@ẬVWwJÈ)æ”hǽöv^)&Ùµ™ÏE*²^Çi††Ys?w\Ÿlnë́|kwc8M,ëµ}³ÄˆB© ·Ù™Ê\̃Ơ‰ß±E+K^ÙIz´Q¶\Ñr'UăÚ˜CJ7._ơ~¯₫×r†SHGÿ4ẶJÂEêºÊWbB,ÙÛ@¬¤¦›½6Œ=_S^Î́R8| Mo´~w8÷ø(Q-̣¾̣v\¬“¨m ö]Ù ¹‚a/eCÇôÛ͵gyĺxØÖ÷~c€T~¶R`ăÆèaœ˜0åÏÚ=¥`K9û*ÀXø;s¹–« #C†—ÛwÉ"uÄÎĐ£Y–”'•À"à´ÉX鹬½¤Ùî̉¹}ZlO÷y»u7qvç¹ơ‚¡èÇÎܪÔ&đơ`tù3ÑhhDâ ¾tĤ•sẶØ^ºŸ˜­­w8o³M‘Vuª1utÙà₫‹AöüÅHµ2Fz¬O5Xº¶nz®ƒ…´OûËi¨n!Jøâ ß*HCæw”º¢sb6;×,\O¶µ·;1J²»ÛµơvP[D́¡4U‘ü±p€©L½x:eßâ®:4t %0æx¼/¼J\v—3UT7séÏöă§₫†s¸êówQáª(y{ ’ßqr+v́ïÜC9iÎØ©¯Wyï¶>ñ§qµûxäƒø‚R«ëU>Ơ>åeÔÖ>ûºú=’T·2ƒ¢¾]Ç}ñ;<}¿Ì½˜o†àx"Q‡´FÈäXñ^—´²9yX+§»+cu¦‹ÿ};¾̀e´b > x0Á@ƒ&\˜`¡@† BH8cF9vôø₫dH‘0hp̣¤I“'¬<Đ`%Ê—0Q68°2æË˜&g̉<Ù³AK›5]Mi”ÁL¡0—Ö́³æQ PQRơi4ªU­Q¯Våº3們cÉ–5{-Ʀuûn\¹sç.Ko^½ ƠBàK±£D‚3> <ñ¯^Å‹åđ:”Ÿ[i¶T9”éäª`i^fpsg4Ÿ~îªù¨é£¤½™ơklس±Ön};ơÉ»Œy÷V̀Ö¢oáÉïøpăË™(:ẨŸS( uÔŸg}»àîÍÉû.Đ9¥t’5'åZÙ)̀׫é_ʲ~kö­M Åz¥₫¦öƒÊ¤ưê£̀¶üN[ÁÛpÚ­¼%¼H -¼°0‚(ÄĂ²6ÜÄëD ñ°ĂHQ<† ËnDḾFC €ơĐ j5Fƒm«G£ª?É>ëÏ=”¨«iÀ“øïª˜’LH¢–¤MÁ«”-AWƒ0Æ.½ǜ0ư“L ïÄĂcÑ»ÓTS;ñ´s±̀:“Ëj´m„‰ÉÿtÍ&°f/%Ó.“́>Ÿ„l€=¦ŒjÇ™ZTQ–\”@*¯ÔTKN3]‰K;E•ÔRGúĐT/¹ÏÍ[lE6amQÄSÅĐ1&aª‘Rîª:’&êL;22%• R:%ö₫öV̉WF%vWî’­4S¢2An³´²S¬¼5ƠP%]0ù 5Ư ƒh¢Yç\3¼Y×”SÎëÀk·Ëó~ZW>åóIh£2pà‹=ÊQc^˜RˆŸƯƠØ ÖR#Ă¥ø4+½ÅmăM½•_QÙ-å /R.å +ŒBä02è\†øđ¯ j¹¹®´Đư¦Œ́È<•ÖÈ-.pÙô|-6À)5˜haNï_¬›äªa@Eܰ±—ç0ß-m Ù̉9íÅØnnü}Ï*ö jÊ®2°ÙÏ„@¨©_jT²±<¨bOp)çÛïqºeZZÓ¿¾₫<äO»Â·9ÿôĐE/Ûç«;¦§N–̣kUÿûơ_¯UÖu»£­ZY€uIJâ-Ï\l*ÉøâÓơÜø¹6OsŸEØ+ĂwZÈ” o­©§¬?ô0•ɨÁ¢TÜEµ¯ÜS̃1§Œdæ;w~ÿT‚–§¿́¹-_8´øtƯÑk¨¡O÷Ä0?Í®€¹¡ÏƯô(Ǘ/}üRtƒ¿âÜÏ‚LÎü4è–umÎóƯfôlí„¢©L¶¦²½êáH`»ûSffă'Ú̀P€`CŸuXð€°7»á ?÷ ‰ÆÓ_å®'%*5‘̉•O,3@ô0ÀÙ₫Tÿ–¦((%÷ ̃yx9Đ1‰gù`ñ·F6¾‘x"DPŸÄ5²-{?³T€î•›€Æ3vœ‰Jp²Å­Ù±[ê"çøC8>’ùĐ#YIr•S¨ñ ‰Ö‘YÂL¶²(+Få5œ!ă*{ÈJ¢Ñ’±|ăËdi¿ZÖ)f )ÀvÉËø˜½æ/‡LbÓ˜ÉÜå2‘Ỳa:ó—¾Ü¥”Ù̀cB³ÙÄf/¯9j̣̣›ÏD¦4ÉÍps»¼¥Yjö2œ­ÓT”„$…` O{f¤ÆÉç=Ơ6y†ŸdÚ'!2Đ€®s-ê„‘ƒĂ‘œí¬¡•₫ËZXd¯9í MU•Dÿ©QătLĨ…î÷Đ ¤÷|À]Đd¯XƠÊ£éL9DË[íÆ ËqCP%3 ‰#¨J)B[ú*|¥ÈV4U*q†ºÔGâ´Kđ2‹MçgS§Vô¥²R‘®ÚUă0Ô«å×sJ“ÚŒ§ơ «C륯é́k­å¹ˆU×YÖ¸̉¥©²+o ”V5_0•DĂz½ÓŸw•Đ^-ø!Æ*6~+Ëk^r&8e5«…lGÖ2ÙÍ2§²ö¤ëg+©K„eE…ÓQ±JZ¦Ơµ]úËcc[[~ÅLe¨ú+Wß$XÛzij¿U _‚ÛXáFr´_₫\çu\Đ̀¹Ñe m¥û¹ẩ…¸s‘ju¹Ë¡¹J”ºƯMX‹–×\âUẢ{P̣ª~BärÚÑ$»â /|ăÑẹ̈·]¨íq Û$²gp?úßÑѱçơ§; ÛP UCù噃ßÂaøzxÁ́ qÜ6„`ûG#%NñËLl'ăuÄSqs^Œ¿ưOÅ€ÌNû¢aëX­ä:ëŒQVc"÷¥Á¶ ¨Oï[–›‘¢ í‘Érc*¤½}o-“¯cøUIjüƠ2›ÅÊƯ]éO¯̀#¶¹mư.FºŒÖ:ÓÍ đ–ɳ68ËíÏÅás ₫Å”ăƯrÇ9ØAt[Ưú–‚gÑó̉s‘ =ª3z»'®ô­T›"̃¾ÈMo2Q¨=í[¥yÓ©~$bu:[æ=¹É™ß¡ÙD/®FZ«€%ơ¢ét[/AWƠ²6e[,Ë4—ÊÄ&î©·zÙ̀†ÙÙ¥n-¿́#]^Ú¶,Ăv›m™Æ´uCbƠ 1›Ñúj4´ïƠ¦Ạ̀:„6>çîähzT̃dæ¾ÉÉo÷àÿæ79^páWx¾đ,38-®ªg–Ø ³®9FY·ßÂqé*¸̃ưEWø“Ÿå)WùÊỸr—¿æ'gÀ¸ñËÙă[’-đHÑ₫Ú¶m—;äz‡Û5£:È6¥́̉e>¦'êH—z©¾ô¨S½}7ÇyHä ́ ×\ÓúgÁ=ö´å Œ1W{m¬²v·¿î)g@xaƯdÛ×Ç_óÅŸûó唩€§²ßÍî%5ñéS·ºâ½¦ÊÅW=ñ¿úă)ù«ˆeˆw戭 t$o^ó¦’/® ïñ`'ÀôĂA{¡Ó¡è€¬Ù́˜Öt=®|YÍ ¥ê%΄¬?d É™J/÷YcaBó΋äCIó̃qû¢»ó–Í_'“d¥ Ô ·³…OËE¾ï›áätIr<ÓP‰7"M[FB h~$₫=8ơ½¿í»È× Mùîƒÿüƒd)h.ôĂ9Ä́,4ϯ6̀/h®8ÀÏ‚î ĂoÄ ¢ü‚è4XG:b¢‰XCö ÆP‚FjD0ÿ$‡aâĂ+\gùx$qd/£Y „JP²î8J„¹àÊƯÚ¤Ö$í¢ m¹F- §­T4¸Ä/¢œ0Ạ̈®TÎOv”%v²pÿˆÅZt©E¥å ¹điN‡`ÄZÆZR'wX̀ĐZÄ=’… YG-!l%Ô¼́ÙDƯrÍÙÚ„T }ñeVO₫Øo ái¾pçp Ư0wBh Q2(‘ÿ<₫ñQ¿'ï1 /‘>Í €£@MVp­^ ­ăÄƯF­ñ̀̉bÍ»xNQïö® ï¨ O±-Ñ…—$ Ûư6q31O0+ñCđ(¦1ID1³X˜b%ÆísQËq-⣠ă»J-I…¾0„ÍnÍ|Ÿ‹½¤Py>|¢Q̣ZIJ«eÿ`&!C«%wT¢ƒ‰Æ"å/ }00Td Ó×dq‡pƯÔ-$›Í­j-U:¥â1äTÎV&]¬°&Zä0"µqY,ñ……v±¦'×pvâĐ&91"q$₫Ívä‹°ÑijˆæÆñ QpLêËâxqûî-F\2¶@îC¢‘ÍûO‘\wÆ(?ÔR”,ïLîc¦bpr(€-ÀëÀ%yj´æ È|±¹̉ ÁÎŤ†Œ*…Cƒq́3,#d-Lé"3&S2+“2/Ó2337S3;“3)ó*l÷f.û6bçÎâ0#NèĹú®¯4å‘1m c“»R3FH%oåÚN”ạ̀åx3“̉Næv“8}3ÿ£LbsêÎ#¼.ă „+ƒÊ6a³1¯ÓÅP†¥è-[ic”Ṇ„'‘ÄSñ(/<½3'¼è]Qúø°9·nf̃Æ₫5©s/c„¢h“§$μ̣Ïø3/.ƠÇc2‰-g‘ÚR@ϲ‘nÄ…ˆ¢ư*0)âelE*ë“#CyhIÚ0¢¬’<üSFèqô°ó¤¼/&®ßömx‰™ @E¥iEQ´¨i™–‰FYÔ›p4¤éFeTG{ÔFa4GeHÁIHi4HktH÷­H{ôœøÍE—ôÜ,”3ëù°o¤˜L+;”â SKçK̃S?±Dñâ<$îÖ”MÛÔMeNWèh%`gÜ1픵‹Jđï4Ѭeµ̣”J{>˃9IYÍT Q,ÏQ'ïQÍRRϳ̣ Ơ6ć„ I,ø₫ÂÓ:×±a1TAơÖHUÚNC{LÑ>T|îă„.#…Âè^ñh(kü‡°*F³¥ñ°â5úê#eÅ!V$mEªƠ:*T!<ơZQD!"E¤ƯĐ‘ÍvlgÎåî&‰úĐ ]©Đ1]ÀđóĂàµB8đ+ )í8C•>å´%¸ˆ*©í¾¨{TƒZO₫g_¯ưđăJH³¡\M•\_j"K)ÂSóp?•V¸Ơ·Uï̀ :íQ耬ں²đ´UI"]Ơi(1‘tƠ†¤í₫đ/TCŒɆúƠ€®‚`!Ó₫Á(gù£‚ÊñO—V×F2Pß jÉOñEƯ¨ö)T-lªđk:}qʤ¬L¯́LcŒBÆRô m¥#a¦=„âj²"2B ùfƒzt'~P%7 äh‰̣OW3ĂP¥Qk¢.B‚ê/¬f4.¢ÄÎq¯2LŸSBÛ"¹ÈLû”¬P—cl ,[v"B·1Ü;ÜV8S07æP„Ä3̣DcH)7T‡+†O_–„¥vÂçmeƒfeƒ%?·rUƠ4u­^3+…m#êL]ưy"w0Ûâ×f“t—^›ƒEmƠ¶m×z —@$ñ„tđW6c4x¯_ùG×Ï₫'n‚;AƒPf—q¤o¦W×2zX¦/+zóỢ2>Ưb>3rưwy­r3åơz5{#7½pm@u«d)rQ\·Z°1¥ 5˜w‡̉{8FaÄ0H&ƒaÈọonc§ç‹R‚]̃†K⟣́ 8è·sư×/gÉ́N“t.–ˆƯVM»ZˆcV˜&†Qx"ƒ—fZđFJ´˜bævI6±~o„|4˜`ä¯b„Æ„¡‡JÄ⢽O¡àø]̃x™Væ—́'£‰½x qêá‚Ă—ö¸½y À‰fè˜ 9]Tí'‘áØqê‘ ’ûØ‘•₫ƒ’)Y¯€xز́K—\tÉƠ¶Â*ˆp¦o†Qt‚;GqĐø„]7RVXaˆQÂøøxÂkP™%Æar9I~ƠA?¹~Lw­¢̀d!øko%M‡â‹u!¡$ƒcXÙ`Îø§&X~Y–¡uEW%Å•-æbn9bè—|Âöç‰iê¡×˜7™áB&×–A—Œ;øW§vxr1RkX¹j₫ĂWZâiú1|%‘˜¥ /cg–»¹*àùzçÙ©8º6•yÏ)©è₫tµ‰~O>)Az‚PŒÏz(&J? :NÅswèGvB}«Xn5 %̣9Ø₫"ؘƠ,e àzNP"‰²ưXo¥¶cÂÅ)ÁS?€¶p¶Ÿ™îo+4ú“3­̃<ººÄº,Vï~Óçgÿ•¤•ÏŸĂ÷^eZpSă”Gf™DY3åncZ ¨ÿ¬Çn7„zÓÊ–¬EÂ_æR5cø`„ä:ên'¼eX}µ&ü#ViAQ:÷tZ‡*b‡:$úº«HÀLû,J"=º—m/¸XÂt©–.;ùz'̀7®)gl>›|ÔúF ¦€â$¼tY¶̃Fט»UËRƒ©ĂµohJă¥wïiØ”üh÷Z ­nẃFhE#=YY÷*»>t₫_w‚¹Uo&ce5MR¾L¨‚˜yÆŒd…1âPu™™Ă]KÅTcm½7ºù5aXwar7V9›Aæ”`:ÁƠ/}üÛ Óú•†Œ4R´?B°‰—ç8Äï̀yÛÆB¼]Ó=7rÅô;FTt½Qm-a– ¿»(w¢U8„+Æh†Zvü`zv©f2Ä;©mpÈß°}‘“fÛÛ½A:.H¼Uü4̉¬Ñ̃m¹˜m†˜“‹çа¼ËO2$%BG£ÂtBî`:‘‰ơ÷›¼(Đ¹pÂX  dƒéQ*ÏyûMPc•µf?º5¤œD•YÄP{ ûä₫e/Ñ ©FÇ\ ›8: ³&ư¥6Ổ½\®µÑ `HyŒx›£¥W¸p›å&¤FQ†)¦szg" Mø}tJî†}ÓÉ7œ(JÊ</¬<×ëÖh1dMP' ÇÄØ›ƒÓW %­u\­µ${­C]m,; ×̉‹/ÆIf÷Öë—|qücÏÙwbĐjÚùU*ü\"[‡¢ăư„}ܯó¯{ƒÖ>­cÓ„[ÇƠÔ@§Ú­Ưàñ,Ô₫ÓÿĐÛ7] `3ø9dh½QwZ\=ïoƒw’Yh=¡ }`ôfn]HÚI¤ăơ€¥k¸YÂ3úĂs.̀£?=Í|×₫Ơ;̀œÜ€JĂd¼ĐíÊßçÊçI2B×K/Ï–Àf§hXóo>(v‘b_=»7?9ƒÛY>C7‚W{O€¨VoäßĂ“A‹–¸hH¨…à5>é…Júẓ·ÿl[%`ï}çPæöơ(… º¼Âª®«Q܇ÁkL̀¶ÊĈyÊ\LÓ“Ư"P¿ôc&,;Â^¥{¸ơEw±úXm…¿₫4̣z³w¿RóˆaWƒ;Çs5Ö̃>á> 4y¸à'1`Ÿ“!q¬è Âú?Búí„/`ÖÈ̉÷X₫hG0¸ùĂ²m"‹.\W¿V6qè¦Óÿö́<7éïÿS©Y°"„ ,ˆ0¡Â… :|1¢Ä‰¤ˆq"Aƒ0°bÆ‘$KDxñ¤J• ¦\i’àaÚ¸ …/f¨a‚>&è ƒ&Æ8¤‹- I“†F8¡G66Éd‘Rî8å‘T^ÉàG?²&$QzY¡‘DbùaƒA:å“Næ(f›Uiå5UTTBUTzi9ƠVzI)uT|^©Ÿè¹÷Ôvåå'~ó©·”£₫ àg×Vơ¥µOV :àSá*]¢mI*Dlj©~ú…·ªª́É÷)¬®ÖE+X­úê­¶̉ë­½̣Ö§³ºêk§¢åTj²&í |»ÊÚ,´ÏÂÚ,±µâú¬®¹^Ëë¬Đ₫JmǾ¤,IuNÊ­µ̉në,»Ư 8,¶ƯF«í¼àx`R!0TPÚ‹¿ØJôư4 Kơ—Ư£(̀ÓQ #¼^¦Œ&<}ߥ1U=I<đW ·%0U¯l¤V®²̀¢\_̀2ÏLsÍ6ߌsÎ:ï,s§<ă|`ËBO4À?]_|'ÿ‡tÓN?³_äÑN{Aô¾cÍ5₫Î äËUÚÙ–UéÅŸXưÉ·^ïư¤ƠÇI­íéÙs? •SG|·Văñ iƯ ‚'Äp¿‹ø«AS½¥Ü%5V¥’³Jùä–WùågÎùæw^mä > S¢MÍxêu¶Eúè®KÅ´µ­Ï₫zí´OîÔâ©Sộí¶×.¯ïÂÿ>¹¸.A ïuA>é^„Ư¡êawÀóhKO±ÇÀƠvóvó'WÚxï=Ÿß?ú¨ø•…ißẠ́y2£î₫cï¡̃súo½Wơ÷ÛÊ'óàg,đ»Ïà–Æ•Ç]*fW»Ú˜¸Äñi~ ¹HK^̣’ 2Ä5Ç«`u2È‘…p% ₫!ÈÔ4è’—mOXüG¦¡%vU µ6O>ÿ™–Ṇ̃ăæpf ôOæ7µv!&ÜàKB…ÔF„¡Áañ·¿ÂƠ~¶R¯ỂÂT‚:Ä"ÿȰùDo~r¡Rô±‡]E€‹›Ûº7O‡|gÔ ä¸Ç…áMr¼ăƯ×½±Ç|ư‰óG?R­eÎĂ_%¯H ½́X=s—£*•*öå¥@—üßKIILBEwR„âAă$Îu¤buœhKX’đç_₫W6²e†‹üÓ(ưƒ2l^JËJ3“BLoYR¸Ê[ÊTùF ve¸l₫å-méM™\ä%“̀*3YLQʰ€N!fSL&©]‰́™œ–₫P¹«1 PËóë²·0úđëbđ̀#éÓ¾́­ÑdCׯ(67?od‚‹ØẮ’©¹m¬bÍƠÊ"Y?w™“Ħ*3ÖFt}K>́CƠuÚ¦§W¹ô„YIGjÉû ƒ |ÈqPÇÍ%¤§à¬`PŸÈ–jU&ƯJồYÀEU@Îó Æ :•@±Îlm\Ÿ™0‹r2Xÿl@Ц(£²,‰jơfQ²Ï̉”¤ØTiƠŒ!Ê®`5VẺ¦²'_ø¹*T(,²([6S»̉ÅÇ<å!å₫Ztè³cn²Ñúå*Aú£rÚs®9Åâ9É#°GưóY¢käè×¥^‚Å©ik °#’Đ­»lM-wÔßö6"¯Œ"G‚»«ƯqËDXËêO—jñ-la¨ô<¶C´\µˆ]œªóZÖå"…•±®»iÜó–qm¬x)i°Œ;>ûu— Er5e^”ëMă—/—Æ6+Ñ[Ï»n%(x™gŒỤ̂g~¤{ÙXUSS£­lb‡)aª^óq¶̉&hUc?žײ#~Ậ3±§r¬¡ 軯 ŒRôĹ¿¤µ­{K«V¢"$…Eäîv·Br¥å.XÄÔÈ₫Nœâ‰̀ÉPfq”íÔ°(ẁº[–J‹ŸZ2́Úøµ£J P}[˶9%`Óls AëÆxz/ëPÂüdï|Ù è:'œo«ÏvYÊ’?¤fE 9̣€å™a¥í»fjEpU¥ZƯ‚¬¡5Eéb*ÅĂŒr[Ú1ÓøÏb|©,çûÂS¾;q•å{ă1“:Ö¤üÊGƒŒ̃àr“\Å%îpˆ^à:¤&µ9×›«•j¿Ú¹ÙS—íW„¸PTvu[Úd‹µƠ`%-\æÜ W×F6®2'’8Ô ^qµë¬ÑSĂTÏræXV¿Èä7³®Íl”3­dØZ_®1‚£é₫‹áPUvWâ°0ïĂđL¢ª‡n<)¬ÈÛi›»Âñ¨¯&0LÍ[Ơ2μ*o‹¶ÚƠ²ö³Ëå¬9ăª‰’g]×ÛäOæöS¯Zà•‹Yèw䳓³\̣*#Ö~Í,©}‚qĐ¢uAèÄ-ÿ6oGèÖd{^|åT²;ߟ…+yî4”<Í·*^U.©3|˳(~×™̉…³LEík¨]I+°ïœ¦9L>=Zœ¼ă€×^×ꌬ¹YïyÓßr˜¿\\sb¯–:̣yöv~Ap =é;2zÓ«̃9rƠé=ÏzÓ§>ö±_jƠó7=ŒÍmÛ´Í₫Æ€a,aùơ·ñ“î够œé0¥î5Í8^äyä *=íá:{ëkơ®W}÷1a«¿|ø‹­È!/ă…êơígç½Øi}S¨‹$®6Ề ˆ—0nOÓư b# œïÓ?h@èS>²ơX ‡UçưƠgÑRx†§EƒNĂƒ•?̉¶g•Z]GSVt•û5mă‚Âóm¸%læ n·óÔƠt?×b&Çlưvt5y#‚»çlw6Áç\xöx“̉PÁ£}qn†''ÈÓ.Xh<ˆgaöN%mcevQ|!…Ă$? á8ü$j—J/î×Yê—G|#J₫ˆBMÑBCÎ]ñE 1û’Y…ă6ëÓIeÇ‚Q'X< dˆQ8a‰E[”ˆxÇ9¿¤Kö'o(/”£ˆ—ˆ9—H[vêˆź¥³•ˆơ…OÈ4`›h/‰ƒináhhÑp‹…hº‚hvˆ²cVCˆ±½„*êRˆøX,¯¨háFüÅ\•x‹̀˜FÍ¡ư’v)Å:7x0Z¦^V>Ă<à!ct4c]¸€<'1u¥Qƒ7.P†„RẨwIqkŸxxµBhD3„{tŒkhMñbDœMˆ¢wøHD^s3‰{ĐḌè#Ô‡öè_'å1=aiZÓ*ˆ¦₫LábwΈcua ‘ïu©CKê–yJÂYeUÅä…µèt6ƒ‹„d¢øR?aƯÆHƒÔ6ôä7Hzä7VÅ{VÅ“ƒ´*×s‡´âc7CÙ‡R|®h`kQ‰ÆĂóHO)È•›Ó`©´d>ô|€Ç]]i–¤“;Y™,&Ù:–XCÚRJë$jΤ_ëæ’ ØY¬H(¤è9iÉh%Zgi‰îD–.´BŒeb°((\$˜9v²ª=©Ÿ̀SHÚ˜‡ù1Ç̀âN‹kÿuˆXŒí!–ׂpëÉïw{#J¢³FaÆCK.ƒjZŒöpü·Zö|…]%qêyaÖ1^£¨[)Ê8ÉI}Vb?z˜´2‹ÅD ñÀÑÂĂ/̀c©!n)lĂ7ŒĂøi®•ÉX¡*5Œ¬A¤w-t¢1ÄVÁ˜ƒö`Eq‚zqèN<–╼9¬±À̀ÅC‘ØĂ`Æ!ÆÙĂ₫áÅáÅÆg,ĂX Çq,Ç»Ó^b4C†ÄÁøB°(¶2ÅÇ“æ-0DMv!2ºÊ)÷aˆsWá¬q,[ŒÆZ,ÉgüÅ ÁÅ“ÜÂ/̀Æ“LÉ™LÉ÷:Ç¡,Ê£́iÍb_»™X­ÈT¥XpÆôHZF[iÂ^xy™ç‰y›FÊ ɘ̀ÉmüÂe ̀ÁœÆ™,ÆnœÜËÍ́̀Ïl“6 à~ô‹£¸0¦¦· 8!\‘€Ö¬‹Ơ`p‘Œ{GÈx˜§I1½pL¿|ÉŸ\̀\̀LÏŸü ÉÑÎĐ́ÏÿœĂ;¼0Ôáát¼¡ô›I\´ñ7́ù@œs{ù-ø¤w”¨̣Ôm,*̃‚ ă3NăÎ’—âOJ -IUf±ÄÉ,È›„@>½y1÷}J^ă%QÚMåQ^}üB&‰®"(×¼Ç4ª“€§ÿÁ—Aí]₫¢ê~±jL.åh¶æmîæÅ!ĐîÓm@üO|̣Êb)–>Nđ̉Óîx¸‹‹< ;!Z+ jj₫æàT¹‰Îè® ´2Í1µ©97mY‡̀7/§@léæSĐe•G¾•PŒ˜‘ƈîè)ê«ÎêèÅÓBlâ}‚ÎG=£R6‡ƠƒcÁß+$™gD³I¸'ƒêÇÙkff^ËndỄ́̀.TÎíĐ^t ̉^ÔíÛ®íË₫ä­î©Í+Ó–n‘ÏƠÍÄ(sc€~'Î{́jXV’>×Ă’&ü,Ç₫QĂ¹[\‹,ßî_·q>\ÍU`§]Ø5₫̃ê7ê·,×ÊæeÅÛ†ơ>v?«·ß^·Ïµ Ođ#ƯƯBî§  jØ=(Ø¹ÎØ½Ÿặ 1N·yF{¼<ÁÜø*̣œëñÇïỌC/µöÍv(1: P]¨s  vÔô3=Ó•]¢’~ósy§LHô¡Zk×[ö[Ưư˜épsØÿÉ >³Ûâ½ ›‰†X'Ë1o¼Gó·ö»¼;Ï‚ ö}µq¨¸ÎKO Kÿ1ú=ÖDyÖDXàæôéĂ»ÈWŸIú~œ ¹$—¯¾î‹ùŸù$Ûùôúù›ïùî ú¢úœú£¯ú§¿ú‚~û*ZǹFG₫\u¶ß.’xM°Ô§4ƯaÄ›ơt•ưÂÇ_ÂÈ?Â"L§üÍừ/ư<á´̀ûן•Z­¬1óĂIç†ùå _,Î`;CéA˜Ô褧j¡Ä?§™kl§ºă<¬Ä;ûl«˜ ÍôÇÁ€Aƒ Hp`ƒ$D¨â‚&\ÈÅFLX1$Å‘!+€RåJ–-]¾„SæL5m̃Ä™SçN=}₫TèP¢EeQ"G‘#rÔˆ‘àæ1’Ä:U`S…C"´Ê0iƠ‘TM’ämZ¶kE0W®J¤cí¶-iĐ$س½V₫ {U*ØŒ 7̀ø÷¢W½O—"V¨W$Ȧ‡Rî82đ]´k9¢œZôh̉¥MŸFZơjH™n™já¾?’k°T±¹Ír•|›"Hχ+bî[Rùr̃̀Âeeä̀Ơ6ø‹;qR·ÜE>4̣·u‰|ÅWßƯân’y»î]yçêwOJÇŸ_ÿ~₫ưưÿ©®Â@ؾRèÀƒ8#+¢,L2óPđ½‚ÚkjB§(tîÀ ›cĐ:ÏLÂK!è4­®ëDŒ©Ă2Œ)<ƒ²!S¯»À²Ë­ ÷v«h6wă!ë³+ĐPd²I'Ÿ„2Êè\+©ÀØô₫̉ €¬Ö ©B]́ˆÀ+̣°"-‘ÔÈĂô8\‘ÍđJd‘¼•;QJ£¨“M Å<б=»z Ë´ÄdëB¥”62$°M.ù,3*ïh1³jN—´³SO?5Ô'\ª@-ô/«º̣±̃>´ê@<”HUo#(6̀Ô$‘"^éË3Î`MU(’¤J ̀ ¸¼”û‹Y6%̣Y$k4*‹–Wù’Ö½đÂC6Ó9-6]u×e·]¨äÎJp -ˆ̃\å“Ă+ÅĶ̃\}$³^z+Ư³LH³5·³¼ Ñ\=‘|ËƯTLMJi _B³]–Đ‹ÿDXà₫=†ôÂ|Ơ¸ä‚÷Í—!ijùbfKn9eF[¶¹Đ•¸gŸÚIRG²$Yeơ_‘0ö·iFươUi f“CJ1̣p¶3˵K‡sv´Çê :&<Ă.·̉Îøæ?AÎWíYo₫nßÖ8)µÜï›=6³íyï]tå½»)Ëf¼qÇ/ ^†¢‹RƒÎ,¹!‚¸è̀ª÷uz¢§]vºæ̃tµˆj…(K½̀Ö¾ˆ!w‰bMÓ̉ühÁï½·Ñ~{ѧ¤Ơ¸đ½§¹Ơ4Ỹ¡¼ÿüء䉾Ùäßṽ̃¯Y\œvï¿ü¡'¬UFU­ô€ÉËü₫V¿<"Ïc›µ̃K§­Ÿ+Ï·¼Ç×co˜]̉=ÈkÀ*œß×;̀ñêeHÛ½ç=/péØŒç6è%°x]éÛÚ*t²^•°> `øT¸B²KrÛZạ̀57œá«Kƒ̀BÖ²ÏÙëpRi•ôç#Îi{ cÙ¾g;#&Ieu«ÛÛD63œÑP‡´Ûܦ¨%*He'Ăb£¼R2™]É`t Îøº¶Đo„c“†&‰ˆºQFîÄ9H€MKƯÓ¿¤g} yÚ`—,:±Đ€‹t"%ù!­ˆ’ßb$¬œ%DKË-[’ÏZ„,Cbakt₫Vă¸JV¶25’#Ÿ·7!0ÑçWc1¤]Ô’Øæ!¼ù@¹ÆÂxÀ ™hÂLÚHÖ¢–…&5›ÍĐL<Ê ëd7»øiR½‚â0IUº̉œçDgPƧîÜÈúÑ5É•RB;Úz§o BGI5qœÍD"9 Đ‘K–ÔbL Ăr­€rŸ ÛíbPṂÅ IL4cœDñåLgHE:R˜À2AÍΡz„Æä/Bâ$„(Ññ`h£¨,fM¨Dï-’@JÏ'%åÍ…V²:Ayù=&—8¢Èo`ø85qŸ!iVµºƠ–̀qO§Z₫¢ô¶Ô¤½'ªb­å₫¼6±Uåw²;åín—SŒđ”vÔ©_*NÍ(̀OÁ™ÎFƠó( ¨C",Dmă?â´„ åjd%ËBɵïT¯ dFg‘·Äz0›ÈX7 a‡sʹHû€óÖÀ₫Kœ\›+dו$ l@p«ÛÜ ·º.ns;\øö·(€†‹ÜÜ*¸Î-®sw«\·ºÍ]®t¯›\́7¸ËƠ­s¿û]å.wÑ}®yKÜđ®7¼ïííyƠ\ú—¾÷•/sÇ;Y₫ö7^¥. ØïDy@\ _Ô/‚6”JaÊUW¢¸̉ơH|m₫Ub[$3%fWˆ£°@ V°ae§3{(¿S¥m-¦^́ªg¾®bµ\àaÿöØÇ3)™.›+ƠÑëjW›â(²“~HWhT2«€‡5fRùµô§@3\.×·¼=Ă“¤"£×mÁ6ṢÜ&y UÇ5Óó,ø4a<Û ¨äè†GiöŒ~¼g>ß6”̣*ëûêEµ'7Y"£›UFhov³S+K…—váRÚEv‰Ưu¶™g˜» ›l¾Tåre%¨Ë©[ƠœOqªX¥E§xÜgZ×úS/a©¤F¨yQÊËJé=h×₫ ؾçtVV¹fb¤,'!₫k'êI¢̉tg¢ª%HÀjÛÛÛ>¬3µ‘ŒüÜ)ó¹eju» Ó¶u¼å½ŸñIHoæk2̉ mµù¥i+Ê₫÷=ç—0~/åÈ₫̣“²“¥ÆfW9Ô.v0 *x¡»j5VuwÎ,3w̉’¯3ȉˆc9KŪ"oÎaXWr”ç˜ñ¼e>ó₫˜Tª¾ª!ÉI˜P±×hñ2Œ1ïĐW¾¸…- ±·pxÖ%3og —ê†ZäÆIÜêO#hÔĐÛ0Kùu¸¢UjY‡BàMs¶·].ăḰKơRÏ̀~çÄ¢ö§‚{$Ä™Ư í³:6Äü(=S„ä₫CéLèûö¯ùvWËŒ¦eÖ₫A¾̣SLyÊ>™Ow{êU—fÄ\ê¥%=í5¯ï…$qŒï¼3âzÁb™•ªkLéÀëlâ,Y;”đ+×ĐÁ X¹¢«Áø’ĂÉ̀G\¤M̉aeå u-"©?́ Ñ^üR÷–6‘̀M²É_}üåO“u.6F-º_µeí̀fÆåq€É8µ÷@ä°r,Ás‚8¾•€?'á´É4Ø 2})8$“™₫ɘÜ““0ùÀÀy<ĂÁ—ËÉ–.œ+˜ă`›̃ñ‘ Ô7À`˜°”œ¡ˆœ¿ÔÁ”À5 $₫ Ú¥Û ö@;ă½1“=…b7n7j8Tƒ7d’åc>çK ơ3:Yñ•@#¤£ ¿§¹B68«A2>q©$“̀:2ÜÍ!‘[ Œ¸-)ÜÁ;T½9º˜”ØÛ«u[´ë§æ`¨²Ê> qˆ?"¸¾£Cz¤h@ºˆºåÈd;2|»À/zA²ÀDZÙ5Z´}Ăœ|­ơ»"14­çĂKŒös= L@‰°C<¤Eƒ%!c8Ă8¶À‡–¾b2C;)‹[¹_\¬#ŸTÀ«‰HäÁIl ƒp‚ûœ°_ê’FÛăs4@‚¾ªÁ@TT2ÔF34Z₫™°‹^´€#(Å©Åx”GœS ½ëk§Jê=È8Œ±S´XÊÆ0d,`Lv̀ÚЬeô(8qÆÖ€Æo1 ê÷94c<Ô½¡óDÓ’¡ B™F¥)“́A’ùBúǰ¸¥@q´»YœÇ˜Ü3\«°b Ă02+rAŕ!–VÑ c#œ$:#ó»êhIGTÊ ˜ô*”ºªøFª07y"°ñ°?a¢³UÙ>"ÊơórK)lÁ  sI »'‡Ă*™tËù[§ä髪ùˆ}‰p!®Q-nLX<Ă€;CRd6éI° !2‚ZJô`À¦|H)Ë₫¯Ü Ñă o* ªª¾Ú î+’ ;ƒ#‹”ÚK[â@L ËPCºw„-#bO÷$Ñs¢Ég*£ơ@#Ôñ!"¢“Ñ¢•¹!5á¹`{“Œ•ÉT₫–Í+TSP‰¡[<»?Ĭl̉«7Ë:m B 9ẲAœ]ºѾÑỞU°¿«»àđEËx Í ¹Ê¤äß  œ¡¥‹+>åƯ´ç4¶hS³:¤×#I»‘9‰ lȶ¨^áO¬àÏ7­´XD¡-eT>»ÅµR{r3‰;ăD̀GÈ–5;?R‚ QƠŒE½‰,Í䣿CB‘¦¦ÙøqƠ4E¬HDÊ Â˜Ú .d&DN,Ơ’0ƠFVñ©P{ºC9Èä H¤́¬wrĂÇƯ˜= !¾ä„DÇRƪS&ÛÀtĂÙ›6₫¼7/̣!£ÜÀ`LQ“Ëų¾ŸRºPu`Ö{²¶`G« (ăŒ˺“³?ƒ$́́î›W‡{Ä‚Óv9›„«Cª›C ơ G©Y­ĐQLL­! œÈCrGÀOÅÖDu¶ƠÄוƠ*¯"›49ø?$Ơ?íL*l”ʲxN¨ªKUA¬£WfL(„ÆT“ߤOHùµØp€¢¶ˆˆM‘üKä5dëÆ@Å ¶B$^½V…U:²°W–[ÄCLJ¹¬ï„Z˜‰ÍÛ`<Ú³JaÔyŒ†(̀€T(pLO'LÎçĐÖ9ư¸µP60̀K‘ ¨¨DÎÑÂâØ₫Kœ]Y8,63qÖ–̀C²̉®uÂûÛÎ5Qù°ÇgùNo¡Ô΅ÊüÍjä¸̃¨N¸%Tôt”UL…›[րʪܘ,124äư7‚WQüD¢ó@·1WtÄØAA¾D]X@¼]Ï¥̃P ²S_̃䨢s™́Ư\]²ÛD˜2JWcü“ưU8ưº† 15̉®”%½riÓB,Đ·U±ïk!YĐÓ_D=Ù̃ê5`;0³Å<‚ÜR½L\RÄèûÏëO7ÅܶRF°IXôpßuÊÎà¤kƒ*nÂmz½¶‚3»N±ơܾRÍ>₫àí¨ÄSÄØNÜ5đ}Áª “0$4a ¿lœU¿`Ù ‘VTMO° ̀ÀL팳t+Xóº5yâW.₫Á>ôZyăå°aFăÿ€ÏñóµƒĂÚซƯ6ôaX$2·­ØíQ_øebàpât á˿€1°"åWúe¿WñÎäÇfºÖܶA•MăKv›C5ú@-b₫̃$[ÇM•Ñ̉ädŸ3‰BUØåă2Τ?.(fºĂSó7{῭\@ÄĐd­–Ơ_#ºT¡¥äí9cLFæ)yª¢ A -4cƯBz^Oă£Ï-€=Ưù˜̉%vå/eQ₫ äù́KÏd©j©ơ˜1<’dµWqaÙˆP2æ[Ơ<ædÆgÓ€¹0Û\›3”%†z™m*’<&D7…^nÚ³Ưta胀ñÚ­‰î²®h̃ÂhÎh‹̃èhæèé–¯‹Öè“iVi”^é”̃-ĂËç˜.–k¹¶é›>Ïñ¹=9,ñgœêÀ%Ú¾g™6j®J˜î®>ê¯B[H¹"ë¥̀âY~5Q#æÄi6è@½i¯v#‰{¹ë»®9́’®ú².ój/¾6¯½&.¿Î/Âîë’́₫¿&lĂlé"é¾ŃÁö2Âl/.»î*4N&̀V—·ÆëÏæ{hÈñlw)ê¶‹9Î.˜íÖ¦µ̉† Ụ̂0Øî°• mÓpº8íÑPmºíPém×îÓømy€Íæ Ö®í™(ñf Ỡm·[’à•ÓîëÆîwÁWÙn Û‚ăî́ïñî©Îm‡|nˆ&ïơfoŸ‰îö†ïø–o4ï—˜5£îùÖïưV÷¦9å.<₫đgÿ®µó‰æ&đgđÈñÜ‹æ-ođ ßo ¯µđê:Éo çđöä1»F=®¾ï”đ0Hy í™°đƒi g‰Đ³—₫ñêM€Ç § · Gq÷ÜXœŸñ"ç3— 1Q Yr&O %̣–p̣'gr>¡̣%¿ñ,×rú~đÚzF#ó•µq‡ 2×rGó(?s(Ç̣-Wó3¿r8G¾êE—† ó;—G$/s–Hs9ïs3¿q'7sÿó6t"§5tAt_‰Q'u4't>¯^OơXÿ±ß0•¸íÜ–‰˜+q¸®̃N—ơ_/уé˜K&@ỵ̈ ¸€ơ ïđögŸ7¯^öäv%”øîŸQph×öÈ₫±·vØđÇIv‡̀v)ÑñmGw‰ w¢¸íoï‰Ù^në®mx§w÷{¯÷y·÷|—÷~Ç÷}x}xi{ñxƒ÷w~Gø…Wø|/øt‡øNÁơ(q÷H/î‚/Œ·¯üúëçø/_¯'ù‘7yæ*y”?yïê2¿®”÷x˜y•§ù˜_ù™WlY‹ø÷/˜®øwX‹¦uÆ6#úSdiÅ$ĐÄe£0‰̉Å£‡dÉøy·úç.wÖ¨úà0Û ê¯û°{.1ç±7û³7Û¾úµ÷ĂCîưwI”˜ ½Ï³ûºÇû»×{è̀û¾ßû¿/=;gûÁ¯ö₫Ç”÷£ƯỎè³§Ù›Ê˽fÓ¥V×k ÅÏúiÄdơ4cÂ÷|ÉÚú›È]l ÚE^Âf±:ÜY¶BØ£Bbgy$P[Ø̉—ÅÏÇư–}L…á}ô_×)ḌÔ¬JAZ1X—*Ô‡ú’qăèèÛÏưè©Đ·‰p^ȯ“oÍf.zœ«ƒ¬å©¨A 59ĐR£x¶ư„¶dégÿV¢₫åzöUAËưI^₫µIĂÏ‘ñÉ„!#€ °Ahp° $(ѡĈ^Äx‘âÄ € r$É’&O¢L©r%Ë–._ÂŒ)s&Í6oầ©s'Ï>₫ *thĐD,Đñ£G¦M.ˆÀ¡Ăr„èÁCƒpLxƠ!دÇ‚e€àêW²lÙª-ˆ¶bÙµ­BÔu¯E¨|ơ.5t0á†#N¬x1ăÆ# Y§R¿}/Æœ9ë̉«c"üºđ¡]Đ£½¶mVôh¸eY¿åxp Y¯œogäœy·î¬%O.|8ñâÆ#O®¼&đå,+o~¹wDmW…Ÿ¹?‹1¶jªfÉÄÛpnƠÏq=kô]]ºfêOA:ϯ?ÿ₫₫ÿxÔ$5` ›eÑ-HQBK=ØQ{1´ÖB X—…$₫VzW‰UÖlª¥ÛxeH[F|Ù×à|. Œ3̉X£7â(Ô1CjáFƒPqd‚™A\!ÙÀT™§W\—%_AØ-Å$•ôµøW—Ṭ˜£˜c’Y¦™gærB ˜RZ)ä—̣]IU•U6P”YĐV ʼnŸQÑé× –Éâ‹^Χ&B©¤“RR°à—pœ_̣&Ư¡× ê§”WÆ7ƠJ:éÔ“z69¥¬yN‡‘–¡r)ç¢[:Z©¯¿¬°Ă±™À¥6Đi©ˆê*äQ–ÊÙ§[²ç²F®h–„.eíơåÚ,T½[®¹ç¢₫›îM›&»éîÂÛ®¼ïÎ/½÷Ú›o½ûâ[¯»É0À s+áE†Å${̀m‘  hDÓ«¢̀†Ëh®äªÛ±Çƒr~l+µ£ÜđlÛbØđ¨§†…¢hÔ9Ûj'…µbœ̣·àıÈC]´Ñû8 ¦FUÖ–‰̣|q”~†p“µb7«wï5¨[)yh†‚> ơÏf›ªĐG³Ư¶ÛoĂíc¶GM+E2ß-Đƒ³9¢@rçg#₫-¸\v—àeù½øà n=øÖ ¢]0~pc¹æ›‹ ]¡uŸ-v*:9Ơ“›.9mºuxäoIîøÔ°₫;éVëo¨úg»âÚs`œ¼đĂ?*w徦3w·£{ê{gë¯D{á;Ă{âS=?yäṆ̃Nù¢¿_¾ùç£ïœçt‡N¤…3ÿư<ƠƠḮú‰T­®ûÖûăïüî;ÇOrïÙÅ\T°¾\.} \ ˆăíêx]S؈Üb½ öjßéáèwºf4‚³`ưê-¢Qks [è®yD f ô4ÀTåGKJœ¢s(SƯe`ûÑÓÀ¦Ă:(|JÜØ ›èÄ'º‚́›!Ù’T¨¬ĐbW‹È“&++ơ†;œÛ³§­ … „"ÛèÆÍÅĐgT¼₫ă³0¦Ü†+:á zxFÑe·ø³̃iŒ)+|##éH_Iq·ă*yÀ¿X2>«aŸ*ù9*"’†—J@¦iÊS¢RRq¬b(gøÉK¾R\âÉvÓJX6Ji©Ü%/{y£d ˜› ˜0 Lb²ë_KfÙ̀9Ó™Å\fMhbÓ˜Ê$3IfÍmS˜'9Ư5NpvóœÇܦ6Ă™Íd@ă‰.}iÏ{âó8rĂc&ûéÏ4 (A jP®1Ÿ ](Că#iU¬–±”¨¡*Ú5‹Rô¢Í(G¹Q@2`” )IK)ÎT¡Ôd₫"ÑÈ̉—®4¦*é¢ỉ›â4§JÁV«ÂSđư4¨@ªP‹JÔ£5©H]ªR›zT›æ4ªRUè>Ï¥[Í  Ä¤'ÿ¹ƠeƠ«bƠêX½jLƠsªj]ëH `5µDË£]sˆ‘é©‹y’Ơ‚ت»†%l!d«ú*•q5{yM > µÏy£V‚*[+kÙ6bă‘ëw“Øhé3Ø íÎ~Ø­8à‡-{]@«‘I‡Aêù¨- Vñ}„²—Ư-oØ4-Dœ­ak*Ûü0<zΜdXºå†4¼ \jX]Yẩ¥]̉mo»ë]âA¯_á¬l₫L×Ö]hD¨ƒVëHÈĐÆ‚„;ÑY(ôEÔˆ*p=$n[ .î~7À[œÖC^ôä­<×%Dàc·̉‡=o z‚%åh5sµ‹i-r]Zú÷–â"߀KlbôUF³ªả\a×…¼ÆfÈư₫4ŒàÇ™OsđyÏưB¥4ªeßJm{ÛøÄJ^̣¹b¨'—È6y©đ\|\GXĂf±J« ,g+Ùu[ä́¢±K$f2›Û|´đr̉p^†ñh̃W= J €©aÏẫû½Äm¹.²Ùa¡ª Y#‡Ñ}I²›íhk$;½ø†ÊTJ Q¨–vêO£íå!ầ=—æô¨KM•g¥”^5«+5éL[ [¦¶¬fëJkúÖ¯íÊ“ô*jLÇظ6¬‡}¨cµ:ÙÊ>S¦”uĐgC;Úd=­-¥mí2à¬Pơ²»ím9{¢‘·¸Ë-Yss-Ø=7»×½n®&iư6½ë½œ½zÖ¤̃·¾ûưÇ0JÅßçw§mïƒ#ü(lröµ¿ík×p|:aĂ!^m‰@̃˜wÂ;îqÆü+äÅ9ÉGṇ’£üä*O9ËW>/ar³å2wù̀kNód„Ûß9Ï›¨KÏè=:Ñ‹nôz;commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/PoolingConnection.gif000066400000000000000000001104651410126276600312030ustar00rootroot00000000000000GIF89a™÷÷ÿÿ{{{{„{{„„„{{„{„„„{„„„ŒŒŒ”)”1œ)œ1œ9œœœ¥¥¥­­­µµµ½½½½ÆÆÆ½ÆÆÆÆÎÎÎÖÖÖ̃̃̃çççïïï÷÷÷÷ÿÆ÷ÿÎ÷ÿÿÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,™÷₫IH° Áƒ*\Ȱ¡Ă‡#JœH±¢Å‹?`Ü8ĂEAr‰Q$É“(Sª\ɲ¥Ë—0cÊœ©qfĂqVÔis%Ï@ƒ J´¨Ñ£H?4h°€©Ó¦PŸJJuªƠªM¥^Ưº ëSX¹:¶,Ù³fÓ2]€´­Û·păÊ;³ˆwóâƯ«·/ß¿~Æ+¢đ`Á~ F|¸p^ÆKLy2̃8̉Ừ¹³çÏ W.pLúqéŤQ;Vm¸tëש]›–ớÓ°oç^M»·kÛÀ}fº¸ñăÈ“‡nĐ¡µåÊĐó^¸¹bꪟkÇÎƯ2q‚•₫‹O¾¼y‰vmó–›ưoÙÖûÆv·¹sú°CtØÂ₫ùÿéæz¹Ö@Aá§à‚ 6Úh¹±VÛ{ëívX¡næ§¡…"`8á†~8Ûˆ¢Xâ%èà‹0Æ(£Mé}˜]{$ÂÖ†âƠaiû©fßtˆ¸ZsùaC†˜!›à¬ä‘ˆ„™Ÿá’5ĂÉÎ’3ŒÈyg;çY?y^2ô₫̀'íI~öÄŸú (ä‚ÊÄ MhØê†¾Ä¡ hÇ º²Ä¢ͨ¶0P£ ưŸG 2̉“”4¤1\çØX¨̉œTLăi)JE¨Øt-8íJNoªỌ́ô§; ªO… Ô¡µ¨H%ªR{º–ÊÔ"/åHTỤÔ™Îèˆôœ*F–Ô£rơ«^ +T¼iƠ~ “tU…g˘ֲ:H«‰̣%*i˜Aº•cpéư"×õƠcvư_[!’WE1̣¯ú*,¢ÛĐ*±týó$ &ÊB.–í]f»´ÙË"¥³¤mŒDëY¢6r§}ki÷•Úǵ–A¯]₫íLb›7Ú Q¶Û²­Øt[̃âö¢ùôíx„ûÛfƠ±ÅÅq{¶Üä47¹R .r¡;«çNtºÔe”uñỨ̉Tº Ü®w'"^~•ׯăMÔyÛƯôV¼\¯{"ß¶w¾œ…/ë‹ßê×ư}ïqĂà/ñW¹÷-đ‹\+ÏÅÁ †°¬$ŒYçiä¦̉ÓJT4<¾7E:KVFü”ª\Ă#V€ˆC¼a¨€¸{ ÈiNÜb/¥Æ$îMƯ‡ăÛÅ>&1uü"ôÈ(n±@́áø1@ÈG̃ñø–\bçTÄK‰±S2œă {ÉR®1˜Üc‹2¹ËP®©₫iye27Y~]ÖpŒ›‚e7ç+ n±Q¥Beç™—UÄÖpæ¡B­ĐM3ô hÊ­Gk‹®P¤-éJSú̉8» 7at+LG:рɖ<½¤Ô¸®i×Á€&MhBK©Ô¤¦´E;½ê×ôG‰µ|\5éA“Wy±RN .™u‰«Ô|ƒ—ØhĐÂÖĐ™§́g7ÛÖ¨Pµt—b’AP϶å#j2ơgÛ*JZÀ$¸%;ÛQu´] ‹NNƯ“¯Ÿ­:¤Í›P×Î]Óèt4«¡(ƯwÀ‰–oi·'Ư‚r·Ú¾hSü[în7Æ)l31X)¯îøÁ₫OtnlĂ+K„6̣.fp_œáŒ>¹Ă‹ö{W-uø>8Äk†Ă漩Mœ̃#̣ÔĐÉ ÀKƯŒ‡¦m®rĐ9ÑÓ™̃ràY}8]²Ḳ27jX3‰;w4Üf$±ï1öÙºđf=›©£n¯æª^™ É-I¾¾ƠÖ†˜Ùp©\ àÄgGl̃­³]i6ç'~q·|îÿ₫V€bLúâ>Ôî ió®Kü\y_wơĂ₫̃ù¹ƠÊßU x½@+Ư^‡øÛÄ26\gè÷Ëù·v¼X4Üh—öªf?=5_Ú-³záGô’}$̉.Yƒ*Ÿ-¹F±cl&ÇtsF̣4h#,wç)¾wu€¡&nGu”Qgu“<ù‘,9g³uB0¥j‹€ ȸ³‚Æcs©&(.ƒ£R|H0j'87x€©"1·$ó'y܆’Wj‚!;3Ă#r%ú¡)•̉+¨²)Fƒ_H/•²¢’4û‡2¿²†?’{P(xÍqyç±p›7f¨zG†̀R…F’&cø‡́*dè0Åâ…5Ă'₫\h3†˜…_X‡Oèz?$Ê"}5#3'3ˆâ‡P¢‰–‰Ñ†€‚)Fhˆ)“5ñ’4ô‚lfCƇ~ÿ§‚«§.S*Ø—‡èṚR‹Ê"‹ c0óG1³¸,ơ'2Wbl/̉-ÛG-8* c3³H1Êb‹À(‹Ặ,]H‹ƒo¤¸ƒ™8È·qö!c|U˜‡Ó‹ïr„ ăŒ¼˜ƒˆ3„¸z«b‰ wkfÂ₫#4Ęc3ÁrÛh*·ˆ*§¾èê²̣"¸¨ˆ³sCƒ+ıœVmE—‡)&c.WØ~ÙŒØh‰V1é.)Œ™^s/¤₫‰û¦s26ɇz¹(‘öè2 ’™r¤¢4I]'5ûh|₫ø’«}.hP3 y0»’k2,i1̣Ø¿’Ü’wl̃0N!#üHs=WµX’4™ï²•é”–2/¶‹%ŒƠ1 ·”÷8¨”ê&"j9—Øøp)—·˜˜U©,đÂ4͈*"…É.ø«èGÖÇ”|Y€+€€Øª‚2BɆ±X2;X0:©…g†Wh„̉̉ihÖU´ Vµ)V`…S‚–º'…r3Ù!”ø™sˆŸ˜ˆ”¹?9…)y„™}9–2™™ẩlƹ’+™|+₫yïØ¤¸Y­‰’̀X™æ„3Ù5ÖG%vgta‰‡¦FªmYhn)Rrï;LÂwC·5ŒV4YA#¸W6›†ƒ'¨ÖyFrJÈ'ØÆ~v’h=hx‘×Îøu¦jZ£40Ùpii}2z¯–RC'₫W!å—¿Ç*8“¢ø¹”(Ht/:rèÙ¡™Ivº4.ס£Q3lzH<đ{ê&t«Á5ø!wB!278b‰r0?M±`|Ù—|<ª‡¾f%#:¤7bí9{ñFƒOºliY‘Ó2]Ç5ó)%ú˜8qK:!ˆ5É“i€3ºl꤫‘”ë¥₫"Ă{ó!oÔÇwùGnç-¤/XnG¢(5¼æF£„:|0²pé92èu¸Ó˜„iä–§ưö†Ú'kăl¤j&Iè#‚Ÿ«úṛ̃¡û‰ŒJ<.Gw Ê«æ#wP3mÁö HĂ GN©X<Âs9!ƒ3X­gÓyå*ơIqo¶z„pöñ4bª:b©:Rq̉ÖQz“Ç}cI(³6«}w<`w\G­L87‘₫±Â…ˆ®¡w8ÔvzÙ†°K°ï°¼[}E_Wz|ô7– }t~GjìGŒ̃²©9Âv èˆ+pȶy´ăˆ)Û₫²“dC3Fg¸9³·Y³¶ITUq³4«³6»³>K›NE@C;›A»‰¥!«YÚ)Jgƒ\ †qm¡ö́‰†đI‘)²D3k1ûµ=¶<;¶?K¶bëS<åm!ÅXQ) á<2"·s+qË®¨¦°™3(-¨Æ¢đñz:µÂx¥\{¸¿Aa‰̣lëXƠ¸äq´01´E«•k·˜K´™[´•{l¼É´"˘áœ)’‹¤É º¬«;=¹V5 ·P²—«¹¸Ë¹›[E†‹£3Ă©¯Ñ.訕nI€ës½»·±¡¸_"¹°K½d”₫›5q»º›»»‹™[ë»Ëûo8ˆ4‘Øè‘©™1¾™éQ8!¹Ï¿Î•Iû"¿-1Aq·D[¹Û»½ô»̀ÀĂ›¾ù|* Œ{A¼s‰¸­û½Î+Kø»AÔK?ö{ăD¬Ï:w¨Ø†Á› ”U™€))”ơhvŒê¤`¶ddcÄE:Ñ…Ñ7úêh»VĂü©nózÎJnW#Ÿ…§£'2zJ¬rĂc7ĂrX*|PbôÀ RÁ$u²,;ÅMsµ}̉…§¨:Å^́N Áo4Æ.œPl,dz¸Æ¯8ŒKwk£rTbkj'S÷nœÇl¼}r¸Ä₫èÄN5n'ü¬=¬Å¸q¦†ú¨cgª’jÂÖª:?W&³³ ¶Må˶<̀´L=›FÉ/±Dñ²Èœ°Œ´ÍL6$ơ¬œL®Í{sÍQÍÀŒÍbscaÎÄD¿ä,6Ô|Î2ÑCܬÎ&…Ít̀îÜ3:Ájûmơ S~´Ï®åÏ÷;?² еÂXeñLÉ ÔÎƯO ½ÚD̀¬D5‘ĐƯ[ ÑQ´ÑÍ\ 21?ưÑøD̉ÑH¹Ä₫I&Í^+ms4Đ-­^1íĐ߯Đ3½Í7Ífq¦g8…à à₫àîà®àVQYáná^f»Üá^á.âdÖ=%Ăɘâ߸Ç+̃Æ:́â0®âză–é'!°ßä±8ă2Îâ |ú°’úª¨–ëD́ÈÄ>æ5WYE¬!›'̃-uÙ£²*qGÊ₫Ö$̃xêÇúh¦qJ₫Ă³$ö₫Y¡₫¹^ƒ/¨¤³Èđ#ú…#÷Éí~œZiT‹:\»«8NÏH´Åœ«Mă5HËRÅĐ}#đ½gB0—(€O¦Z̃Ă’̃v'º)ø̃óúN€Yk‡WÇV›œ>băÉúÈí¹¨…;t#?ë |ó"xU~A‰é©&ê Mé yi¡*Ă c7ÇOjÇ Z*̉·|¬±‚:G§ô₫öMQÂ>÷Ơ~œ§xYùª‹•¨{ˆ¬™À4¿œÏIœÄó¥ œî„±ßw_i lÍ’ùï(*YX’†¨ºCZˆXû¦‹)ˆ)Ăé…ä©ûƠ¹]o_oùÊ+•Æ₫Œ½²'{ùüqy¼ÇB—¨Yư{ÿ­ê‰jt»'₫(AkÖ!•ƒùöѯ÷²˜•ÖX;pÛè•ÙXÂÉ$ç¢÷³Â.ÂÊ’<É$$XĐàA„ .BÄC‡!JœH1¢Ä‹)ŃÀÇC9²$Hª́pR¤Ê”;T2¦Í)A¢üØ¡áK-kª\¹̉áÈŸ“jܘ±"Óˆ ü ° ‡„XXÅ*p+U¾¬jµ`ƒ†>!î$J³hQœ;ߺdÛVǹ™l…Ơé̉g]£rRŒ”mÇă=)w±Q¨ ̀N¦\Ụ̀è™5oæ¬á̉§₫¡Av:1Ê |]Âå9ôtј]³úÑmÂD#.¦3v‡Q›'nÑøRÉ•·~e₫‘ H;½…:ơæÎ­\^ùsp  C¶ ›nỹ®ÁÇ^ “¼E·ñ‰¾ƯÚ$đÄøíĂ|,ÑíÍùÂë<’ë́@TpA'cè"§",N´̉„Cê§»VJo.»@̣Ϧ¾T/.5D­¯ưÜzK)¦ZÍ4á’ ¬ç¢ăÎ+m¬± ær¤Çuüq,«Đ’éC¦ä:m1M,ÏI¾<\̉¥úª„̣¨ =<́¥¡¼|’¦*ûP7ˆ lpM6ÛtÓÍï&$MN Y₫O­¥ÔrȃŒÆ›(Æú’¯4<—*­!>S;®Ï/â3¢Û ¤SÎ9UÓªî| R;§ëQÈ=Ư´:‰ôLЇ]o¸̉n REHô'X%r•Ѥ4¸HŸrƠE=%*”Ö?EƠE³hÖWÓ|óYh£•Ö¬]¬ÔÚ:‘-¶Y YÜHÉ['Ä•Øk#Â3Xñ0Â3YYĂ–RIe4«¬R5íÔ^PóưQßPo4U!#÷„1Ơ +ñÈ´¢u¹„ˆY[IK´£ƒûŒ×`;ƯƠè`DÇ%·ÀiCyä5ăÔøÚnOöø)IMwă#-ÖV-=Ă…èNŒ̀uWU¨’í^¥₫²…J¢K-û4»çÎw;́°• ®¨ÅøĐb!ô‰ê›ûuÏX9₫X¦®]Ơëc Đ«₫iÖ«3¢˜©Bv¨h’ë¶ûMù]•‹.̃Cꨩ^ßöƠÛâæ;ª­ưÙp³szr¥û ¨9ËjγR°Ze *mµUr…9©uÅV]àŸ†­¸ôf5t¸³µ]vlYÙêr¼ƒ^d“ù6~ïŒ đÎ5®åv/6eâ¶QƯ­¸ú€§lóéµ üƒĐºHOu"ˆm•~ÑE¥nv́Çèç˜+â{êûTơĐ0ÎRĂ#`¥U•4`₫ t€¨À.0‚ˆ`Ø ^PT ,XÁjp ¬àM &pƒ*ä  G¨B^1„àSøÃP‚2Ä` M耱‚7$"ØBñ<ô$¾.0…œà ©XB!Q†Q !g˜ÂÆœ É(B¶ˆôaKxÆ º0r”c7ˆÆ7æ‚3tbưÈ œÏ[eS̃á$…¿…¹ zÛbÆT†+æKRĂB•p,ÉH́É fjâô -’za£ơ¶wÉB²jt¤*]y;T6r\ë¤'myË‚|ævÛ¤·¨V(JYë₫óe1«÷¸“-¥}‰|Q3“G© ±(Rj™.D/@ê•ë`1{Ơ¸Œá kÍ'Ex†¿A:szê¤H°lÖ.t5@|Ö¤g=ơ¦=ƒ³r´ZŸ̀VÖÏhkŸÉ¬„.F6L  ƯH-ëéF®­•óă& 9K₫!•’óEÿĐ„í3–ˆ{ˆzRzRQ†óx÷̉ḥnm«‚Lmú1—eí’cCfhZ'I ̃T¨A%—²̉"¥¦VEƠÚMû÷Nnt¨CUÊă GÔ©b¨íœhá¦2O¤†ux x'~¦–Ît† mXcfôÖ Ro‘N4”\Öÿv”÷¡Ÿi₫¤6K*Ö̀”ẹH&ßzˆÅm˜u=l_ơJʯéƠ˜’å9[ 2Àfv¬jưÓG@€&Ômô)D©)Aå¿f/OîC-à£-4©ö£ªƯ(Ī©Y«@ñXÀb(?’T2¸ üt&[¸R 5ÆÊhj…–ĐĐ¼–@Ïmq{]â9Ÿ]J††Ú¦²+RZ VV…Ê’L‰—«’äkñêS˜˜W«̣•%f±K™N-ÛZ•9̃Åv¼´Œí¸¤«ù&˜½ˆÁĐH¬`Ă4]î•Tlz_ #Èd>i ¸{µùaö›ˆˆáƺ\­4tmVû@ƒ_/h̀‚ ₫ºÄ Ệ5Ç• <1G „|`%‘‡ä« ™ŸiØv?ô¢)Q‘rUḲ—àXpº!­_WL¥Fl¿GÁHF\¹¦Å­SƯ°Đ«bæÂyn¦ó³·îúi¹¤-ÑxJÜáîvËTq=›#ư}ºËíni‡ιÊ5Ú¯-̣…‡xïçxÛß§ø¦÷æ×æywÙ7'¹Ç›é“wdÿ-#ºsư¦æ÷Íù°œ%9*ơÓó₫Û†ÛđZg8Ä¥›¾û7Ë\¿9«3nvÂC\đ ÿ;ÆW?iO7*Ö½{ñ½ƒÚ¤¸÷QK*±ƒG>Üá ;@Zúµµ­lekG:Ù7Éœ±¿lè r̉ ƠùËŸrâD|e!_çùzʬßóñÇ»{yđn̉°Á8£ÿ k“h—…c>ak¾lk4–0¶CÛ²‘’°³9æ“8L:Óû¾3> ”¶₫ ~̉}Z˜ŸJ:?ñëÙ©¡)/9 —°IœZ›È;?Ê›7øyɈ P¡€ ¢L ´ ¬¦B,8 ,¸"\2DB!<Â%K Á ™Óă¥)d₫›T3­² \wâB³á•ØúQ¿ûp™4•kˆºË@—ƒ9¶‰̉ó´±±¯¡>l*®z0V!@dªÚ‰á®È).¨’Aœ<@©&Qs¿xDĐ‹Äʸ<«đA½ñ+eÑ't‚¤Ç{¼>Y«ËB5Øû²R‚ª̉º²wé(°!¿u)År“ NƒCZ̀›³j§x!1sa”u™˜ÇB˜½‚¦é1¿¥ Æ,FE$§§H?:ó FÛwb)H3½C§`±EL®ÉÂ4aDF¥;%¬ErÄ»³21C Ä~‚$× ©¶áFÊQ:¡QDbÇz4¿DbÆ Xè«<†₫ ÈƠªŸ"0bÂGy»G†¢-bœÇÚÇrŒÈ% ̃ª«¾[³́“Y.ŒG{œÉKF‡TH¬¨93>Ú­„KCD±º3#ü“v[ ÇyÉ„Éă‘Ç€ú‰ŒÈ;󈱵d̀K²”L¾DKEr–µ¬Å;ă“•lIÛÀ¶Á°5çs0<)Ể2©Œ̀₫½Ô¨†,ÉÔH°Êû̉-q"‰j;4> ‰ư2 «K”!ºD,KËŒÁƠäɾ‰Á̀LÍjËT[.t ®ï»¸“;°|1LkM,αÜIá\̀ÄÀL$Œ¡´£Ø8Ö[‹Ô,È4N¿œĹ¬LùôIå„Ă¼‹¸d½r (‘¨å ¦…;È¿tM¨tOùÜFŒÙÜG(̀̃4@œ¾́À3´ü£(́¶ÙâÎøTÍƠδLÎú« ³¬ØA‰üÛ3̉!<\ô=<Ä2€/3Ч°FÙ (<˜Û¥¨¨¨JRøà@t­¼b+3«É¬7eÓÀYF””º¡!ÁÓbG½AÜ©ÉdÁKƒzÉôt)¥)ƠQÀÑC=© ¤ázÈú’±X¢ Dîé)˜VåˆxC¨JơĐ¼À Ô›4óÓµ“‚I›øbÔCHÊ)Ó—CV|UÖ ÑYEÔ³b–[ÁB–Tqe&Î*D®º«¬‘KMơÇkÜ«×́Nź7Eµt¼*Cë•‚₫”©—ÄưùMÑRF~ §5ƒUnUTYưVzJÔr›Kœ DÂÖ‰E5‘Œ, Ơˬ? Öy]̉¥đQ́* #‰I—¬B5¦åkÆQÓu2ÖBD؉¬¥Ñ3TK†…6æ¬Èw‹3^©=–«TD¾½Dת{ŸjÍÔ÷LÖ…E©đL‰Û,Z+d--Z}ºUÄ ¥œÔ³”Ă϶ºØáÜÀ§ÍY[Ẩ„ë«Ñ¹*‹.Æ0Œ I<„±¥uÎRí@¥×¨Z¹NmP_Œ¡̀©ùpë3ĂÆ²9M™Đ2zC;k\µeÚnEN³m¹í°Ó»TÓ{IdÁ¶“ëÈ3₫Ö -lĸ̉,Û;V¾-IY {­9LĐ²K`́/;­<˜ÄÈæ1UÅ¡+,SÜóIʦT¿ùÎËưÑ₫I[0ƯT6.uµÖăÏq‹ÛÄp» ‘?Ó\Ó’ áÓäÑ3¢¥\± ̀{%[S5WÉñơ–Q@bÛ“/=0Ă©‹_÷‹̣KxcHôåIËm̃:Ë»•´½̃ х¾"•®,:YÓ;ˆsà“ÛƯƯĂ`Œ±M}ÁíôXRĐ¿5J/E4"­9=ơ»m»H>Kálà=SáX©ÎŒH<…ÏcU>à-Ă=B“ܲẳưk;ậ¿ 9̣L‘n₫áÆÉ^kÁ¾máL­̉+m[Á±:ˆĂÏ›Ñ`Ăk»!ÆÆcè»H–!DßKØơÖΰ¼K3ÁëUŒScƠÛ¸qS‰[‰N`ĂÏÜ-93»Á©c6`¡³âäơJ¿->’D*Ñ}ØÖÍàU“áÛS—;Ö`=–ÜŒóG íYBmZ,ăëÊ;‚ße‹_›àLµC´ÿƒ´½P4‡ ;aWÖMXƒå°l̉?ÎØ7îIˆƯû̉%@¡²µÍX;´àưüJ]óº[Ó(“ÜPn”ñ fưË6éºOÛÁÛibχ­U&=H9MCºLKM|đoppJp£z?đ†Ú56a-mŒUÆà$̃½´à̃¡>q0ά¬½ËaùvƯ…vÓœ­ï ‡Ä§ƠVâ/âÊ?̣ ¼ˆnboăhéT=†ƒÀ¬»aMÈàÛÛ̉NrG‚₫ñ“’Ä€» Gœq)gË ´ºdiF“/9\v;đzßƯjA ̃åfî×íË¥E'ÏÁ|cĩ5Ÿr*шá=‘د.gáù(M0G;[kOf;ñ Đ9΢®aư>ªknE?ó…’ r$Ÿ̀yº8?ˆ7—sK—́‰:ƠOî̉‹ẶÁđ¯̃üR¹̃8=x5«ƒØ&UrÀeœÈy¢›L¹Œö ’K¿uL/—:O–DJêẳˆ”ÔHæÀü@BaCJƒo3GëXarܵ°.­³"á”í°u\ßö©ŨƯ¦É’Ødª̃4JÈR8KÂqZ¦º]ñ+®g¯3¬ˆ:ƒ₫˜ơ„8{ùnßwiyëÜ)¨¤¥úD»r‘Ų˜²ÊHˆxLJ¤Ú¿^vç±x¿®X¿wj¿÷|Ïx~ßx;£0ưĂy&ö‰h‘÷YªUl6­ÑÁje_ṭsºơ±¸„Àw~¡yÏùÙÙ¾™Öm/Ăî[b$øÄ"¬¹I"ïø̃æVo¥‰¬yâ}¬ơÈRÉöéèïú—Ó®ñ,zI:öÂVZ{ôú ³’À³ë?®Ă93̃DÀÚwùˆ_rÍ_̃¿~\̉_V~+a+§9÷ªà1n½èÍ6ɇØx₫ÊxUîègô4—HµźŸ 럻FcGÁ:=@dmˆDˆX ÁE(4ˆ¡A…%&\8ñ!CŒ/jʱ#ȇ+†”h²‰”*W²lẹ́%̀˜2g̉|¹ &N•ṛ́éó'Đ B‡-jô(RŸ H~ôB €¨ £J-(UbT=PUèu ₫Eª©‚]µªU°W±J̣́ I‘o›2å(w.ƯºzIRD™ô/à•7‡~lø0âÄ3n siS“q=x¥üq2ŧ ºEXV„‡„™Agl(²C[‚nă €µ\‡°íê92/îÛº̃59Ø1đ˜¿ï nü8̣äÊ—«„¼Ñ²Ô"C^}zE¯ C,ûûF¬,ïf‚úÔ»¡Ûæ­¾¶û÷{Ë÷&é—9đáA Çäÿ?€ 8`JÎeRgœ…]iuÆwƠ1èуè=X‘ủ•àjÜi¸Ñ…Í|xÑG[‰}˜”‚­ø"Œ1Ê8# 6X–t|]F₫x£i÷#„>j'¤Q” GCZáẺ&߉yE™‰æÙG#Q-̃§R‹Xzù%˜a₫dcw€àIÂ5Qg̃íEGBdœ ¢×V nQ•RVÙ‰}–盘Aq€R—…*º(£b’ù”™n̉eeZ™¥ÛåÉZei}ôYw›iXĐdsúi•ªbª̣EÆÔ–̉k¢²Úz+®ÈÙˆg₫ùéVM¹ÖYÚÁk¡”¡mqµU¯NäÚˆ«²:%¶î±k®\SqƯ;.¹F=JY¤ ¡¬§¡EÖTWÁ›V´Dº‰ơYUYÆg±SW­«ÙZ₫K° qK®~$ÔZ.ÄK,Ó®ỉ½×e¼¾Qûnz™6t^Dju÷•»ê0’ } 赂Ê|đ¤WFüÁÂ,…;1Ï=CühÈ¥ ¯Vl*²b½;/X¡!k*Çe*-›lB‹æà5CI³Áó6ZÎƯ—èÎ>›}¶­6^ÈuYE×1©p „ÚÆO¯ °©Z}̀±[h¾ưĐÜHÎ}Û…hÂ\"]Ç<×"„-f—…qĐ0Ú•[kÅWkÖPY\í»qZÉzî¶UR³›4ƠûÂu–A£C„¦Ưù¯Ÿ[Û¾¸×ªn‹k­”_₫;đ"^ä‚×)yà"b×Ë‘¡;Z—₫±jƒ zxí‰s=sÂ!ø.kaˆ?>ù_>JiIêÚui_׿"ñ ơWä!X‰ÄîÁØûÏ=îvÇ;•¯€„QÅ\¶ Re¤eÛÍsv"ÖFNZ ˆîw;Üioƒ«E¾×(ß=́€&u¨ ưéLƒ̉«6u¨Ù,k™]Enf¼₫ФƠ©™ª,ɤª2ÅȱÏéK˜£k*=³ˆ,#¶A…£Í́NÛÁ.¢öOLf¡xyÖ̃¶É #…ÊŒ’¬;ÖY&D3—x®đ¡E³”:ámgÍàuG²S² aéSÿβ%Ï]ɳ»íû›àơL\ÂëÍ÷ÖÁ̀p„ùÛk>é2óœëbnêƯœúF0–Û"9•èA­v‘ª]&4èÊw³÷­b…I›liîqÁŒó³„r øÎm¡8ç¶8̉U˜0_SË4PÆM“2yÿ-¯ùØÓ¼(ÏØ̣I”¥'3€æÄl†ê˜kb8C:Ü—₫5Ö©KªĂlhLÑ:—[™íÂuÜèι{ñ‰+sL“áPó_Í<jwL A:@¸{[é DÓc "ºÜinÅÈb'iPj8!Nºé½¡ÈBV´Ơ\ñŒºsÊÓa¾´K₫J$'ØÄy‹ÂƠ¡‘2¹Çơ=p6U[7ư-سëñÊÑĐÅ¥íÚ‡Ọ́PÔe¢÷V$y†¯oGä^+å®–aï³Ol--È–¦F›ä©ŸT¹Ăµ>“*ÿ¨º[¾l>2>”Ö ưÙ qßêE‰̀kÄßq]ĂIŒÊIY…¨ xœFưUJ‘Çá}ˆ^™ØÀ|˜zI÷”ï)^Ù₫µ^©ˆ€´ÈÛÁ²ưe½{iͯÈPé]iPf<̣ !–¡Í¼ˆÏ¡Mô½ 8…Ï8€¡9¡ªEá¡IáPá^!f!jan¡V¡ª%bá~av!r¡!¦a®¡ÆáFq´ÈNæáŒ8€„óu ö¡ ®à™Í1`åâ .¢aœ#¾đŒÍ#NâbÜRué¡ÏRâM߀đG¸l¢¬é‡'r¢)B̃­J:¢´¢+® ø@Ú*¦„¼¢-ÙÑm@\Àù›đâKü" hDđXL@ùhÉ2*â->ă₫¬¤„LÀ@€Ä„X0^Àü"dÀ0ZlÀ€c5j@2’(c2^# ´ă;*ă‰â¸Đ#4̃#Kø1f@¸£Kd@d\€XÀ.bÀ7¤<@d€@5f@:¤@fÀèâ7^d:=Ëo”">†$€ dAÆD:&#$Àè";*c9’@Äă;&€ăKb€t£:¤<–O…$P ”_p£5FœJ¤#N¦DJN£Lv#ÄäIöä`Dr#U^À0eùt$¹€dPâ#€]9Ê„CN@LV£¬d4¤K‚cLnMn$ À¥YÎ¥JBeOj₫â ù‡W~¥-> cf^ÚX8!b_æJ¬$¡_ä́±„D ¦.c₫Î}$¦G6¦fF£Å%3̣L n¦hºÄg&•p¥Ä`æhNbiªUh¢j®&%¶¦@±"$Ŧlê!m–j:`nææn“½Qo₫¦ g@Ib§qêfÜ…Se6'k¢KÔâ#E§tº"rºQ¢0gÏnf'ơmçmZxºy'¦g…™Á)‘rªç=²'w₫äÙ§|B#}&‘{:\~₫§Ù́'|Ϩ Ra§®'b%~^'‚6èMèåô@Å'…r¢…₫N&VœIA܆₫b‡V_"Üy¨ÊH‰Ï®(Œ.’jÙ¦iÆètÎ(Å}—.-¦.b‹ZwFbrhmvWzè)I%©Ï„fÏ“*éa1i¹t "J)–̃ •K n©ÙDi–.éa½hr†é zi®XéÀE ™§ZéV¶i¢) ^⮃Ê)s€ipŒ¶âø°ÏÑ©¸„‹䩾Ÿ6†–¢ ”g.êå¨!œ&jbHêÚ¡D§%Qj¨˜¾¡bª‡~K§iª?Ơ„_,×›ºÄ¥’ªI•Úc.#ÏĐƒÚ©­Âª·á ¦¡ª˜Ưªâis¦®²™g¨§₫„á̀₫‡+–Xá&Z´N«´V+µ^«µf+¶6aµ&´n«¶†+¸«¸–+¹kµ"k®Ö*RÅÊ` ª³æÇpÍ+½Öëơơ–ˆÀ×ẻ₫‰̃†ä«FŒ@ Ú½¬Á,å„˨†™™£>æĂF[ĪuƯÂL¬Ăf,²b́Æj,Äź¬ÊæRèm™É¾‡‰u&=̀đñ –öᆠÖ́É–,Ê¢Qäu ¼:¢ùj¼AƯ««üTªĐ]I\„G{ʇUí̀†1Íím\i*˜jŒ¨"$>Ú-ơlX¡`,ÍW]¬z ỒT’ß]YÎ₫!7Ù«2ªQƧiíÙô¬+J ÙeÙưˆ`Sdˆ́tlu_éux4®ü`ßv”mú…ƠG‰ªºWQ-¬rî-’m•̀4ØùMö4Xt†IỂÖÓ åfÙ­ë¡Ø•RœØ*†ç&F(ç‹•js îê™mn˜FÇP†á»t–ï1SP‡³èÔ¥,Ÿ‚VĂä­®tkb¯·f/÷n¯÷.Z÷‚ï·†¯j¯ø¯§}oú¢¯ù®¯û¶/ü†ïû>á'è:›ôá@đO±é‹Ê vøÚ¯]ê¼1¥E0¡ÿ2ƯêÛ[đ!¢½§¢„Ỗ,ËÚlƯ²JÜÎvđ₫[0{p'ŸD8Àí&]èÊ.,¹Å³Ä'©O߸ ̃ ÄËA^iE «ŒÔ=ٸ唻dµŒÇ^,^ÿˆ@§~€ơ&G°Ơ’ˆñëÀÔ ÆƠl…ápÊø1Ĺ©† 1ñ”èIí¥đà†̉˜\ê~\UùïßÜÍAµÈ-D4uE¨\’₫@-ë5p§†±®qèî­íë6ÎøưÙîMîáªIÛß ¾̉đ1í/₫ªŸˆí/óúZC±TܘœºÔ Ë©'›Ei…ß(®̣Q̣Ep*®¦©©Ơ¬ÙúfåEdm Fµ"ƒ–{m ’(îÚî`#JB@2åƯï ₫rŸ<„₫ë,”±°&Ë ¯̉̃Èñ–ÇdØ$[n•`§ÉªØôÔ!½¬ˆMî‚hà̀Ö +U`k(w$GƯE•që±ư’±=—•TØ‘„Uf|‡hÜÛùÍNº³ô$Oå̃óG\!çÆû1îdñë ̣ ̃ơQOÿå̃`±œ́r6_¡ü&1 ¡6ăÅÔvßÍN–UIx ÂÁ̉lB4Apkæb+ ¯œp('̀¬n^ñtËu !ư™dè…%›WDsÜƯs1ëNe”à̉2 ûR‚×´ Wû3*MĂLí’Ë *gVR»5ẴuRÿ*0á•₫ ëÄơ QÅkHRçÈÓ4’95 ăqTŸ²ưùWË ³,nd,ßQCñ₫vI'Ο†l®Ü¯µWêzÛƯß{J̉đ‹Œ·5½,y’‹È;đĂK[rë ¹q6À÷}đ‘coµ»Ă9ï¡ß¾®__°Î#ÆưVJSƠº­óùÀ3ú•£:ø Óá/z­ƒ?y3y««vû₫e‘?ÿªúª#:Ëu=pb3,O/`„ˆ"èa Á‚ 2\Hp`D…"N´ñaCŒ3>ÜÈ₫äE‘;. qeJ•+Y¶tùfL™$@lØ9æôÙS§Î>„à9èO¤<™ =J4¨SF£₫ä9°)Đ‚9©ZJđ¨VŒP‘è@bV´`ƒblhrf\¹séÖµ{o^˜ 4àû·À~ \˜ïa¾„/8lxpâÁŒ!#öë€̣åÆ+¦,ñcĐ›‹Ùôè¾IclÙsẻzi×»€ăƠ§B·† ëA-W’@ÑfƯ=kT¶lG~tíƠå$}óî°´hÙéÅ‹ ÑucÂpm—7}zº5CTôø~|ùóßI¿¾Gññ÷÷ÿÀ₫ùÈS@¼Ø«(9¢S :¶„#j9†úê§µº¨ˆ¤ËpB +«Ăä¦Ï»̃ ó)!Kp8‰D°Àeœ‘Æ–¸®£‹4Ú1$u I¿…́ÈE ‘?“rÉlJkœr%ÜêC̉>‚F N'R²=’< IB‘³Ex< Jä̀"S¡1 ẬM·Đ$ó̀9÷ÓH8“’Ê@ô¶á ½éĐ:bÓĐ<çdèˉ®+2ÏE4MøÍñ¾2Ë4´Ó E’¿R%”FöîËQ:R?µTP=OÂW[.,ùf…ÏVNßku?NE•Øbµ²¡0á\Ô₫-/“U(Xè„HΆÆÜs£k roT䌵ÖnÁí6\WÅ…ÔaUY_}l/Xs}w^Yç}—\ Ë-UI&§-RƯu=ÜEè+6mUÖ­0]Lh̉‰$¢³_lÓ,rIaƯŨù­—ă‘ ˜`Ûj¢WR&E>7d”?ֵ͕ïÍ/Ôđêä’ũ¹Đ4s·„7Ó}í¼X¢¯®ˆ[‡Vz"¡Zn]ª̃˜eqsæù.ƒg&R$«³Y\£'NÔc—«&Û^œ¹~îByhCóƠK;yTö;©£¶o5Ç’««yĂí´×Ö7q™·[®“Å&H[Å'·₫¼́z½ưó´öqÈE/¹]2é®{8¡œ“Gm¶· )¨Z·”F’·¦S‡¶qµï\fRC}/{W°öăùµ§æ¼ùç1₫“øêE÷:<º•F±7ÛjK»́¤’È(»±Ăß”H¨ŸU¾ùßă¿ú÷á­gỊ̀-ºÿ±—¹EY‚â÷ÈîNÊÔ₫¤D¿È}/́Lg>ă©Qṿ£år[?IZ0(1ôN ;àû8’ĂÍ…Ụ̈‘¶̃/…R§ơLÛEGg¥œ®3¤Ơä<ƒ*¤P–©v¬ÚWè(̣YÊx{Ôpdz+ưp“h¯JḤ’©Ó‰Ö“§¢3ă=ÿGQ¢–ơyE%ëËFT·–̣uÚI#̉´^̃•‘™ªÜĐ â(Ùa j2́(Z¿°B®’ưª₫ÖúÓ6ö¬K:ê[)[".ugÂvé"lô:~ m£Ê¹© B•r;¹V²HÈØzU±=́Î>’¿,€5 P€`ÓÛƠœÆ/¨!Íj₫¢̉8FIL₫r=£à.€€q@r?ó[ÇdF¸Öul¬»ÓÄ&»ÜÅmc*[^¹”.E @]£ŒdÁeIaOÛ!£¥̉Úé¤Z8€ëè QµÆÖ±–›-Ü ÖËVSœh3pÅ’Cº¯ÔÓ)́C̃ÉP dÚ̉È̀Ûá˜À“:ë…"­2Á»UŽLJoRÄ>¨«~ê/H!+TѼت,l~́a~J°`/2-Rya4Ӄ׀ÚzÊU’°\¹äJñmeŸ~©¡Ạ•™Úo–\'.²1²7.,Fü¶¹aLÂ#K¶—^²½sgAû%?ú…̀«ÊR@”₫ m[ßmwé3¢ÏÂA).ƒ Tp éƯÑîh)†mW×LÑ6s­&èÔỮà4á£T‡g»Ø²úÜHW—Ö¯–u¬i=ḳÑ´$xr¡¡|ÇáL —PKâ—yeÊ]¹ƒdj“Í^Â';–'=;=¹O—́Éo&RQ¾5½Q9êÂÙü¦M„<ÎE.™öO¯”Üvóx8׿5ba…MY&¥–æ[´wÉ=đí•*ªå²ü+„©Ùưũ¼u†½×ÍlûcvÏôÁ_ƒíâ"QÚÜç1« ĐùBw®çåVÎZ8dˆB]ʨ½¦öà¬uDÓb1ñ”Sáh®¶ÿ₫^²e\{Öµ¬–MN¥Roºơ_4¬}æ¶úÔ¥₫êô¼ä<3e¼†î÷8Ø,eÚ”ĂÆ̉%¬y3́†ÀÚ´ĂÉÈđb׈ơ KFQoi¿>;°y´Ôá²Ê?Ræh?$°JÇ2€̃ŸÆ™w.̀º‡+™7L-=—ShÂÉF̉˩ʫ÷yî‰Ư‡8d*›ïCGÿ#R:¸øØă-zqö¼g? ø¾È—ÅúÉ̀”i¶‚ÄcoŒ_“Ô·äW© Ơd95Ó6—°ÄP¨zºËËøÆ:ÙjÓ²^IŸVùW^å³SóG[|­äS¸ÑY₫β̣đS:'Iøo,ôREÄL/X®ă¾È-éfܬrxéú0›>Où -"d ô¼ÏĂˆÿˆ…ˆÜÑ*âÊ®CÄâBÚ‚„”íØFư²ˆœ₫̀¿h́û,©­ú²à + Z̀đà àNç¤fZü†é|.-µädÙ:â÷^đ-QEŕ*lØ´lƒ|₫’nă‚æpÆ‚®¢íi°”ƠP¥NçÙö£rĐÎHÚOcü«ư2ÂÅ(đd $p+ÀäZ¦¢ªËÆŒ‰ Íđ”§ØÀÉob'´.‰úư‘'pBvjOâ*í¤íE*ËJ’¯' e₫₫xâ¹D|vC7₫H–”b-´#}®¢ZZPí Ïr®Ó21PpƯnG†Îù Ơ*Z:/£(Z’P i1GbP‘*±ôní°̀Ùï#8(₫Ä$‹è«- 衱ÁéL˜ªó ầ Đ‘vΣlqơªÁTú¥jåR%,ñM‡ccQ A‰ Đqeä²Z‹M$(„Ê'v¸‰æ„–Öî K ‡´̀˪hp̉¤ Ñh¶â¦\p ƒÉkïZ*Sº®½î#̉mª́̀iе¤Å"âÎiŒ̀cRÿ±Ÿ|Íóª±oF„ ·qϯưÂlđ8¨'½l‰ÄiÛëæ₫ÄÀ42ơ$ª#iÄá¬PÆIúd &Qª¥¦4Oñ %K/ 7’l&‹&KÅÉØÖ/¹"'d–̉¢–NÑ-qÅÅLd.A$E$Ä$å¦íƠé)g$ôK®îĐâ 0ȺÍ O<¾Z’§âºÉvåaâ°HôÙ́,™q  $Î#ÊL‹J¥åóoXỄª*yMê±öQk̀«’œ1ñ ‰ )9DŦ*w¨‰©ä+ÿœˆÚ“mf²3I‰O’½°ÅE₫%2ơÆƯ‘YXD›àîP¬¥ă¼‡ùöjÓ̀ǜ«˜¾qï..sI[¶"Û±•øH—Hmñ̃Ó₫-«)ùˆ’³&Oûz̀[ nózÉKFS¦/,Óx,«âÏÆrÁ³  ±³o€†Oªƒ•ª"(”­ưô¯ñDñK^́ù́ÜkÁ\‹,[DBơ³6@̀•VMè^ê5ùEúØ)ƒdA“äÇ0-A[ꋳ3?+«˜æơ¤(pMjE˜hÄ’m—z»lñ́#đ’1́xi2?ê>ăÍEù ½†ÂƒDe[âđ́ˆ­1 C ‹̣́½ÂĂ%÷ ñBˆ6³Ó[~’È"¯´Đ½<4Rs2H"½L̀bĂ~r,-qy3Lƒè²:‘}+m´.₫$µp°TjKíl/Ọ&`Ñô èµîR-©E ä#S&O+h C(đR!ǯđMp‚„³"ïÑ&1…îÔ±̀rRëhLw¢<©@;ˆËî2̉º̉Y“ZZÓN¶óGưLU»50[•@ ̀+ ®:ÂÅ6”Åéædï7‘.§C„ç 20íS…\\“Ơ²°†Ê•<| 1D[,uvo?Ô“?²Ă$SƠ[ḱ¿Ô&_Óc<³F÷ä/3æ¥(чj§|ŒL °R¶JMQÍaíul$U_ïgYms7#MË‚UIư¨Ëm|³„Æâ†°dwV#Ó̀ÚötÎ2O ׯ´₫X« «R¦ªIá“úÎ j)}6áÀ4eéˆì`™âoVé+æ Û.Q)çʇ1«Ở¤¶a–g©&bÑCr|±:'̣$¦lÛ±ƠØP¤ÄÉ ;Â$¡06™’cP¶j‰Çׂ–I|ÎJ;”‘,å.}tù€ẲVm+·g§mÏç²µô¶ªÑ¥h#pµº4ăH2Y°êh3—¢¶^-Wn‹tp)©̃rƒ{à̉AäR• £öqàT[›o Wp)mE&sÍĂŒ–(Io¥‘BëiaîÜîNp®ErèÎ:µV„†t‡ÊXßåxc×%N®Âå’Œô¦:SOđS”₫r/÷a3é{mçøÄBưΤ°94bJ?Å.­¨E.ơWX é*¯ØTxáWf|߉OÙ«$û.‚k…¹̣¥å<óaơ¤Ưu™Ö–xa÷­äĐpYÀËâ%"í+-‰;siđP«/rc„/l~X%*Ïf,/bœó@«W·É‚…îtÔù¦öƒ-·xEØ­ÚÅ~—– Ñ{̃5Ëb„¤CD÷ÈB€ïÖ HsXpyØÍÅI7›tGñ/àÔ!²̉ĨÜ–6ËØ‰CØ!v˜6Hx¡ú•ư´KôH̉vĐưÀ‘ƒ­cLuâ5µ ê¼Tÿ~„Ñ₫øz`êg *d›%:û“ܼMléåPK[-mHqX÷8B÷”$Gù?I0‹̉e/µÙBĐưªPT²D=+™{ŸỊ0™píå0Sׄ$vP­âF:˜î÷açÏdơx•³™ĂÊ‹=ÈN:Wñp£Ùm ·G¥0^±Œ›&2óX•ñT‡¹zÆTï̀Ï ­7¯QÈ’̀Z±Đs—yÈĐôA±Y˜WÙơ¢~m†[ç=HDDWgùö)'M^éâ4ø;YT¹¦’yÅ´âB hW«X™AT`öS´•ÓZEçé óBUúû°zÍ)3¥o?H₫sÖ¦R[K€"å„̉́Kăù£3yc´‚vb´ºˆkßïeỜ y'•Ni*1™ß¹ åו³EelbKè8ÎX‡è¦ƒO8 ¯AÅzθ©‘¯Q’‘%2Z¥zưȹ(/(đºCu¥rUñ\ô8:Oµ“=ºỘV̉3,Ơ´n½9”cX¸ 8Ơ† 1x-lEu›·]™Ms tO8Y’Q`é€{“*É8˜£p[ó{“8“¿¹f9or‡úSBsÊŒ˜ÚbUÀá¸ÁkOÍÛ.Ôl0\¾%¼ÛôhÙ3Ñb̀¬÷ [P?~ÜÁc¯KUjsIûồmûÖÑU25ª0"}[3 Ç÷ơlj—¹%’ªø)iFœÏ•̉ÆÉ₫¨ù·cZ•ñƠɵn©N8c¬¨áΦ²…³*Ăxeo?³Zº\ÄR<©,̀Ïö¾‰˜œ₫';ö,ú÷̀÷ˆ¡ñưHO渨üÎeL7yrÑ3c-®¨ï@ưˆ=7ƠPÉ—ÜÆ9æËébëúTíJLQ]Öˆ QkgI–­ŒéNl—éx›´†¼1g¿G½X*•e?Û"ïæ¬5̀­¼,4˜«‰˜Y@<³å»ÖAdn}.^5¸%¯›ENZđ&₫r¶VopNđǵ-³)BEÚ§dYM¸³×Z₫~\§}†ø¦Ó'páÄ̉Oj>{¼YhUwƒTQEd6L4Üw}/o×MgdăhD¤óz%¾sưß ÄィßƠªo÷èF w=Óá5₫ơ¬PÇ}âÇÅÜ#ç‚­qnS² €í4¹‰±₫ù«T7F©í´[̃ÿ¦LĨPV±Œ»‘Μ:h'́v®}Up‰Îi=ơ†>.°Ç$Ư:e|4A½¹_8+€ÅxÀc f§÷ÂèµÙ£°~]®–fơ9Q§´;4~̃eu¥ăÓç²D°v_Ấ‰¾sÜ~&̃–ƒª¨ư¼Î ],îuöŸ«&#”p>đ‹•å ?<ª…²ºä5ƯOæ}Ø ¾hÏ̃‰.Äaѹư‘4_&^>Æ>÷ôSê3â/Ă1ónĐׄ§ëLË[ÿwüö Ä–ØvC°8¬•Ad«cI₫k¿SƠû́q[…—øÊøc¢˜ÆÔñ%Ơi§Ă)ĂtĐèEö¶ÂC $(P„B….X°¡Ă‰V´Hñ¢Åƒ+\@"¤È‘$K<‰2¥Ê•,[º| 3¦L“ ô0ñ`Äœ<âäÈñbœ6₫4¸(Ä¢":,íP4„Ä t1£VªA¹fớƯ_AÎ<‹6-É!±)Y¦GÇ"œµ¨UŸnø÷êÔ‚Dâ5:0.ÅŸ„Úqë\»”;¶5«6³æÍœ;{.ÉöaÛ…PưÆ…ŒơAȱRt=‘µE¨KÊvˆºiCØ6=́̀₫4²Øà‘µNœ8æÏ̀57°-ú-Ü!r?&®tÏÜårÀz/^¢´+– x2äĂ•“î~´ˆåÍëÛ¿?fÍŒ²k¯v8ÁÖÁÄu%BBÚ……‘Rµ%HÙ@ !'Y{ZHa†dÑ—_‡)…Ô[¿™¶‰! E"A&JÄ"C‰`‹,Öf•iư•˜b1’(zѦXr2Hdeµqèa’J.™YhE 4•RÉ)8€¸…u"]]7 •QơdWy^j„`{e ß{E’L&ù„Yª8M5RÔbUCí£TVúé'C':¶×  AiCªhpàY¨¢M₫gÆ—æ—½‰i¦ª´_[R‰()Smơ—ƯP Î9G…µ¨S‚¨ÂHÑh́yT¶²¹&¥¹ªi—››Ú礫Fui£1&JÚi-N£T{ذFºcŸvÆÚh™|•뤺¢ùѯâËd°†M'ÖwÉ–(ŸQc‰c¢Œ¸TbΩX€Øîê­·âÊo¾’ëYœ{Fhm(ʪӌ.̃e,²Ă ¨c8u䈄-ơ›{…VÚ-ÈE^JpÉ&ÖiT̉áu°¨§—˜°.c;o±Ư½*á´2g„^«"crĐ@\äÀ'7I³¨0úuăL»Øo×–˜â§ »ô‹ŸÆ,₫‰¾áøâCÄjÛ1¯Â t¸G¯Í¶LÁ¶j_7ƒmcC„.*#¡/¾lç‹sŒl»0{t+ÀC₫­álƯöLS鯖ñ%ꃂ÷gåQTYû§VT–¦Ø„+.$Ú–ÙÄxăª³̣F"g³nÂj7̃‘ (Å :møöTF‡Y—³¿C"^ºé‰§¾ºKNFæXRb%øä±)UvvѤÏHuÙ}Uc&Oºñs©Ư|ú« ›DN‰—ơ_»)j÷îS #‚̃ç«á~ Û¸ïJÆ1[âhÀăáyê+ÉF§5m®€yáV$¸ #åeW$Ư¿È—88à ₫,áÑZw=½KB1[Å0¦"Á+w0¬Â|$ ²yïƒTà}¨&Ü ˆÄ$'gJl¢ŸÅ(~i>C¬"Á̃6º̉Ä«YK›£Rä°̃mñ/ö‹Ÿ—X«—UOƒ…C ÍG4!ZQ$ °xº<â„ÚÛcF,èG@₫ñƒÔă$Ç9*eØÛï’B8S¥^\̀Y:kå!-Ư˜ú¥¼₫̀YIäÍ媒B[)ŒĐ‡ÀU^•̃ ‰Ër̉:)êÜår«ƒm²ä#!R«¶9p„¥gJ+6` ˜¦5à€jjsÙ¼₫¦7µÙÍmbSœÜ$§9ĂyMt‚ÓœßTg9ÛÉNqºsœđüf=åyÎun“$̀¥?ïƒÂ}mƒă»‰Ïwê|%!·al´÷ ¾q”?¬T4ÿ‰ÑŒ¤ŸíhgPy»rkBc̉'½t“ëyê'súåCH &S}Ï™e(‡sÑ!r 9ơ¨Oª–Öå]Ñœ¤*Y¯]­’OkŒ*S üf4R[ăDoZShµÓ́iG9ºƠ°®„}t Lm"¸MÍJbªä‹69?üd“ÀLO^\$›̉«|ƯˆWÅꡆä ˜æ`‹ØÄE¨ AØ•lkª¡ºM₫̀n&¥½°†[´£ˆ™¯W’²¯Î_{*€°$8-j_«QT&]Ï Ưäç'Vå-k¢ăÚj—°gm/|äh÷Ü̉º¶áhHđÜå2wºdlYE(Ư–ˆv±ë²jh-}Wg¾Ûnq®Q^5¹ÇUˆt©Ë³È¾ôE-!&/ÚAkrvËív+&Y¬KgÙ}!‘9«4–íƒÍ,-iuỡú¢…£–°…‡ÂÚ &OV™lSœ0)̀‹å…_đ{ fÅGn±‹Ûë̃ g ¬­•±JWÊjt#1m×]ü9MÈ*«Z‰ú¨2?ª÷Ázmq…₫ó6(K£(¬‹Ï(ëT9AJ™Ñ\JQṼˆ|Qjp³f~=yÊ(ëÙ ç$½­]ZÛä¸ô¥È•>o7˜›2hÁ \2{›¼¼8¿éÍnt}¹ ơ’Äa©@{£8AR̉¸ÀLï3á³̃;„ÑM©O­:," @Ë䉦£¢TI†ª®,d0E‹è\‡:9¤FuHzíë`»­r~©SơS˜̣o+¹kÊÔªk"qZL»6“q*l€f{Ûâ2×l?ö«D_§b*ÚP₫i8-uµß½!n7Ø̣®7hô¼2cÊ@)­W«½èj·—Ó„÷µÓ₫Œ!zŸZáönø}¥BTÉj† [íÔS>±×¸¯>´Á=^ʆTä$ÇO@ˤH+c³R¾Æ+gKD²µA~đ—¼I;ï9#ÿg^Đ¹%~»9–³|̣ș٠”<Û™în„»›á¦ºÏ}aè¨P^vÖîíŒtzRP?soơ5Y]Ñk¿z©ï Ỹ‡DFïY¶R%âO·q˜RG;ŒEÙv8̃ílo$¹Y=3:;*sa‘9ŒË₫÷§½=ƒŸrå Ïfok’O¿³ƠJÉÀáÜé“/}äEvy(§óªßcèqs•A®®¥ËưÎà¾ă^̣:gưKVï₫{ƒ´ÙN]æ¿eư%.q‹™9'½éwpà ?øÔg c‹­Ceo‰ÁáAƯüBC?ün”₫…Í_}ø’âfMÍÍ´s/óxß] 6ûÆÉ?₫ä¢_ÂûO?s­›odQFBU„n³¦3×wf–Ï7ưG_èö% ¢×r[³y•n¢âxf¶k È{~'ÔU‚ˆXÖÅ~zBÓBv~̉V%Ç|&‚ºgp'ø(胭µ/â51úe#f+Ôƒ˜€6ˆkzç€:(0?x<(…8Ö%×a/Yb1ău5`]RÈĂ„8ˆ#xTøZhX…•c”Aw₫'?`f”Å ơç„âw‡ xza¡†Ơ‡kHeI<&exçöeŸ%G8zc·€e… ñ‡)ˆƠ7gÁá Bm›W›ÔI­"h‘ö„‹hh¢x“(‘h‹i”ÆTî<9Aÿ•ƒ(ZfHQ¨(Vº˜V¤j´lY& •4Œ›—%?ño—6¡¸w¸W¼¸UĐØ‹&$TỴ̈XO¢qQU!äæ}B'R·h‹b$86˜§yq“*1³'^á)_1‰øU‹¢X“W>•çØ<ŒqD•% ÇoâĈ]]zµ²‡¤˜‡¸È‡½¸ü˜jAhµE^{ñ₫5¶%sh4&v—{ă¸xèŒT”)‘msŕ·a0£[Å+uñ…³ÇFƠŒ 9’Ëxz&™Q:y’'ôC'Ñâcü³5d´.:p5i U$vtvY“¢È“ÿ4•=Y2YG{Cáu?[ƒN‚PăSˆ éw÷ai•;wO5$æ>&%&A1ƒ¡Än7©‡8ÙAU™K€¹–ƯV––C9±F³8;Ă@„èyç3Pf •.&˜ª8˜$§y´FBm·×l9({–4 Hm5™!‰Q™Ơu™"PM%P•ˆ“P¨ÂD×%åVp|yº¶§Ô₫wtˆ…OB$I92®èPA(Éx…Î×—½‰m%œöv}êU‰L¹©G¶yndù Äuw7ÈŒåIJ¿é‹ƠYoëW‘ɉQ[ñ2c¦‰6‘‰°¸„v!åĂ›ư™+èYEª€Ơzº?Z—^jU½Ñ._ˆ= –‡ÑéŸJÊm²#•#s'qØ7¾U-VsY0Â7èÆ+G•Đi¡ø‡¡%£úhس‚́">½Ÿ®sw¶e,E(0É¢ck/&Î8£ê“¤4úsÍyR5Lƒñ¸_æÅ¢yÂ]³ÖZú¢6éˆKÚL*lY§|ö=đC.¨•₫¦2#,ÚE›6+RU¤]jˆ¦ë#¦ÁÖ†ÑKF8qS5`$#’5C!̉-Pú‘^ª¨v§©–§X'ˆªLL¥| U{r±`@nøO韋êajpgHM)†¸Ÿa™JG§©)¢’¤ºp"‰8Ç}‘‰nI$b‰« «ÇA«¬c«o§Œäy^zGvdeŸZ§¡V¬k3­Çú{ŒØ„º÷I›ds“¨Ñ ­”R­'3®Öj}ɪ<’zᙢy{Ăz¤ÿ©–æg)™­¤èg¤¯á ¯iV®WI¯ơ®ºˆä›ÉÙHÁ ®fù¯W°‚‡­.–’₫TïúIà(¬ñJ’¦Ø°;„E›æK#+²%K²'+²ª…0e²-‹²/ë²1 ³3 ;.6ë±tÄ”Rij=Ûy©ä³A+´C«D˜Ac(ˆ³9 ]¥B³M+³O;²1=NKµPkµUKµI»)Zë±ÖäµƠ„NÖ¶`»Mb[¶dûµ 0¶j{¶l›¶î”¶ÔNh‹M̃´¶wÛ¶xû¶yË·{ë·Ơd¶[XÏEJ{cGk¸ˆë\k¸$ XUä\+a’›~ŒÛ¸‹´S¬u¹¸d¹9û¸–I¸üe”K}»¹VÄZ¦[…ª{ºC]$Aº­k2¬+»é£¹5ö±µ¦ºk«˜₫±±Ë»¼bz»!ÑÀ;¼Ư–¼bº¿¶QËk¬Đ«¡ËQ¼̉{BÖ«F{ØK­Ü;˜$D½Æ+º̃ë°ä;˜Çû¼Đe¾Â»¾'‰$Ô¼í«)´+¿‹fOÜT¿¿B¿ù[2ÈË¿±¿ÿ›$$„¾¼µ,‘ñ‹Àå²À©¾&ñ¹ ,LÁËÀŒÁ₫tÁ̀ÁÀÙÁ(øÀœ,›A”XÂ(È œÂÜÂƠç¿/¼X2LĂyzÂƠĂ“Ăˆơ¹;|7\Ă.±S6Á“ÄêĂ%SÄ,ÄiqÄÁY·ñdORLÅSlÅUOX|Å[¬Å]̀Å_́ÅT¬MOŒ2M¼6₫ ^D«Æk̀ÆḿÆN\¸f<»ØqDHw\¤g¢Ç}œÇlH~È_âL¼ºtL®™ôÆ‹Ü Œ́È,md́ˆ\2q’L€ŒÇƒ¬É¯JP™́É{ŒÉ ¼ÉƒÇç(Ƀ™™»2ƒÁ#®±l²‰gỤ%}DËÿÑg̉E "!LÓ2ÆèI EkNT3ø0ïÊwaÈRxÊki¯äYñÓ4蘔#vi5Kăi[q‚ÁEa3,ïg ¢…I—Ö#́±—J“̀?¸̀ViªfÓ0>ú̀¦ÙgsçœËæ&å!S#sg¢J¡R+\gФaƒ›³Î>ØÎ=Ù₫̀†ƒOL†5fd5u'¨ ­ÑÍEDwĐmÑyÓaÍR-~óÏ'¨Ú\TÑĐHKÉWÉ̉ÿâÍo‡'†̉D‡ÑAѹ¼Ó"ư09}Í@}Í;ƯEZƒ"]cĐOóÓFm̀‰i/=í¾›|W7'ưÏEiÔG5Z̉Ơâ§ZƯrcäÓ[ư[oÚ7#êZÔ2’Ï =R½¸1}E3½|÷Öƒ1v3UưÓz̉R%¨ÜcĐCmÔ9ƯÓØ\‰'}}Öj¬:Aוk×äÑ")ÖZ}b ư4&ªÑ'ÆƠÂƠ4N¨]„‘̉L}Ú~Ưx­ ÙÊøÈlÊ—}³¦7A₫–Ûù ´I ´PÔV5}ªœ†D|‡6PAƠAeÛ¿²Âơ|µÏµĐƯ4¤\µßF̉Ư4û •Â˽)¤™?[Üă-̃´Û¶ö*œ ™ËÆÛJdÜFt̃ä“ÜŃƯß͉„¤dsªßr­&ƠSm²ˆßsª«{½7Çơư&hü­ >†Đ9Đ–RBÜÊÊCöW·4ómÊ…ENk ¸ô¸₫µƯâ>â"îáNâtkâ÷Ëâï”ÑTâ/Nă+î¶"₫á6^ă(̃¶^Mµà˜̣½ ÉE%í EiläA[Ü]ºA.ät%ÈŸ<墜ßU>mV®åXÉèsàPî!„ơ“₫Æ™üL>£lg¾™ùư6{Ä̀µ *[ÏîâÊ¢1̀SÄ´L«±¬—“1>Ă`¾$̀©%̃ÉPx!f<”&eA$ũÄÔ9óÉèSDæBÙ@Nèp²/sy+ôlkiÎ̃W áeiÅ*̀WR±]"Έɦ¯NéàQ ê¡̃!u4¡ûYDTƠ|V`¶é}^:Ö̉ƹ®Ârxï’9¾Jiv,à̉V‚>Ü P6́gó̀2Ùad-”Wé ë₫‚’̉*µbtQ¥>*1É¢\$&*ưJ@áä?́ër+ Â.¡—j£Ø’r†Ú₫'8aYؘaé–cùEVº ‰Â,r'¨²;YÆØqM4M̃ëPEaă.Đ‚#₫L,̣œ€1âEH,Ö×ddtlê?g#†ñW£ˆS:;v•b₫Éèưï¾çí¦8äMq ¡̣ăîœ>f/L?#²V[ibH÷…ên^áCvó“]--̃55x9CuÈ]ó¸é"Đô¬÷ôkø@ `đ>pTQF̀Âc\£u¶5Ñû#Öb²èkÿ_¶'¿……:âB²SÑƯŒwr»ÁfAÈ™đs&ÿëí^¢ Úö₫BæƠ?̃ñơ]H/Vê†Â;Jú\úHB₫©™ @[ÙR¡TüSCh;Låù„W÷€ˆ÷/ŸÉ±ú;;»•ïDyѹ5\^3(rxïb¤̉^pˆ'3 øµ$÷%úÍîắ ¬Îèȇta:ÊV<”ø—V›“ö Đ¾!B`ˆEÓLđG‚¬™%Á8áÑrØø,®o‘ʹ'kDUÚÙDă]ïF̉«GØÂ7ÙÉp₫"”Çñ{JyĐø™ø-†uwBj&˜Å-«ƒ°¬Ơë¸ÉÅ‘'f"èg{2’ “&¾pi"M¿ơ¾!„n íĂ8àÉ÷"ÜkÖy ¤À̃ùQ,giMi'Ä,«hIÉöó “­â ë>̃K…¼f™8Ö‰áú»E¦1O[®J+âCƠ l@ ̃í¦Ă˜ÏŒqËÖ62^5›ù$gÆI£ÙĂe7³Ù÷i†'E-ë€Q™'|‹eÄ•ö-ı ,ʶ‰Ù’îjơx̃¹v7¼ßmï‘çÛänN§¬©“ª“¦b]ªŒ›Ïp¯å¡Üä1…ÅBqyçĂí¤Ccq+u—œ EdqíWâ2¯Ö!9Éu=u‘»;×'Çz› ”-l Öluă5ñrMÜ]N;ܰ…8´U²€ÚvO? 9¦¥…íA’̉©Ï}në́ă×u½©>ø¬~%̉ë:°"¶₫ä‰₫4¸S:Í …ª¢°–ɬÎùØÓ¾y¸w8æ ²Ú,™ê²h»Pj‰1øŸs¬³§—„Ø6IÈ ?{“́¤A7±fæË‡bU¤Cß}ÆÔ>,ÚZM_ÇüÍœ›÷XÍpvçl>Ë(kÇú«0pxœ’uÓ̃ûp‹êÜ u´™÷‹›Î nƠ”{%ØMfn)Ở² Ü Ê}™H-@_R%£Åç'§s=˜x½ï3À’  Ó´e)£` í¡Ă“msˆÓI5bú³f3·IÉØY Ú"[r"Y=·i½(Àa;Àđ€êqŸéª yIŸÀa–L₫đKµŒă9² t̀xŸă¥«z ©Ø$l¤¬ Âè‘V!%“2¸1UĂAe"0Âá(&3ÂM± êA ̉ L¢²é»*¤ĂRR!óë°-B ½;,c$₫X#̣£'ÅÁ›Ï›£¬8ú²¦cɨl&™¢©oº) ù ”ºÉ‘<Ê­"Œ̀Ë,ߢªAá=¤¨{9?¡ƒªŒÈk³¨É«¶|ÑœTC©ÄËfr3̀ ̉'’¡­ß;¾øúẸ̈s¤º˜w)»0–vª;ˆëÊ₫̣ƒ£t4ÊdR‹:'ÍĂ/•̀ËÎ̃âJ“`J¿‘|T¡´˜|KS¡E›RaLå’§—Ó½ª8½˜Ă˜¹ô$z¾âKÎồát›ö*e1„›!;°¦È mƒR„Fă á™F>i‹ñXÎ!E‘²'¬Ï«ú"ü̉/e½i‘KC¤D±ÎÛ!ˆđ¡× @)7t²¼ ,ĂJT“ ¨‹.¤+å̉4,GñÁR¢XRX+ˆÓCơÛC~Ă´̉I¥KªLG™,Â!ïx5Ç(´çø·H́L5 TùéÉ̉Nă CEÔỦ”óPa¹ñû¶ kßüE§œ_¦‰?³ 't£[E'¡QO’́›±9bĐúy-3­“₫z eƠikÑmY6°«¾Ä4ÊÙl.Ê)½µLX₫)L}<&¤û©ƠôÎú `­À;)¬Ng¡Öz]‹xX¼Y¤  œdå½Ờ¡$É₫“L 7*Mx©H\¿óƒ8ÊH¼³czÏ1’V{ƠX¼°=[Ÿ€…¥Á¬ÈKêJE-A©%½Y¤+’bŒE)»¶»(·&Ü?g<†ÅY©PƠơÙj•Á—¿çÂȉ<®‹Ó?nrM’u‘—û•N-Ó¡©ƠrÉÈdzM“ܦøÁÊ«Ú ËíÈØŸÛH@,.£̉P- ‚~,°1AYrÑhÜ}âªÚi8èâŒ2‚T$;ÛÀåX¤Á2K¨ê¼å¢ÄB₫ÆEĐ%˯úøSm @m²¢¢¡}BlÓ/M,TÁƯơ¸Â÷ÊÂÛ1eÇ¥#1Í.]$kó¿`G8bRÉ]ÑËÁO ÛÑ^“¸C7=DWbFªE?‹TsÓZ®ú\NS-ëËWºÀÅ¢ÜƯ$ß ̃ï ‰Kœ*LÄj i¤½CÂ|́GB=ÙIÈ&%öÍ&¬O8m¶ÔHÑ~\đơßĂÛE@rỖ=׿xӲțÅÙ ó%#ªøÅíü¥=®C<´tỄ6ñ̃ÿưßnô€o\¥p”,m2±Y-́ UÑA¡ƒˆ }N]1í‚‹ëX™$ä₫A9JQ:Z¸,EƠăàÆ ‚4HXEHÔ¦p’MĐVÉtM®ư˶›“Áù´éóM|¢ƠróH¡êÍv‰• âàuɃI›º¢4§°cJ¦yS̃Ó½ä:Í¡G’µÉ‘=V1––/ó=†²_èèß1&d Jƒ¨)¸Ê ² Ê+Ơcñ[‘X±*±„Ùç{ÁLŸ™e÷Û¹a"7#^Í´P \ ­ˆ;Ă-äV2äâK:"I¡ªn–ÖéÊÀ¼Éæú©₫–Q ¾Æ\­w¾¢#®+BZ̀n¥­¿uåg† Đä?Ñœ,2ơ<.È<8GF‰>Ư₫£’°p’ÇÁ=œËâë$ôc5?<*È X „Jh–g¸ñ!³…S:s^+µN%«Næ |F´àI½nµ ₫ 1Mt[Γêäyæàó©ô¤Úß]¨Ø -[ Ơå¨üª[… [PăOLCé‚FƯ´è—‰µç¡Å[÷M' Æ™̃¾=#í̀\W$UüƠv1›_kĐ·ÔÛ«xh˜₫̃•ÚÍŒïà3ó$ëÛA[C9‚;§́³>vK9‚ŒŒ̃3œ̉đ4/["§fk ̉û ߆îQûPÉ2îí̀úJăÚ¡³]S?ö¬™íè}lOô ₫1nkDE6ƠU¥2u<ó•½ö%¡Ü9w¡' ¼A*9=?Ỡ_.ªñ: ¢ÑøTJ̃ƯÀ¦^lÁUÔ`TNŒGi%6‹Q$…ơ)q&´[ÅOÜă9dfˆœ–\²  Á Ư×fëM)•#â}*ZSbØ|Ú̀éUœå&[QPº;V[²X|cÛ´H{X]Áä™á˜TLĂT…îè̃:lư:ºyÙ̉£¾mÚn†­’iË­Ü=“¢¸‡kcQΘÈL8§»cÖúêÖo§F¼|Ư×¾>^diÔÊ₫k»«g-™“±®̉¬w;₫KoÎS¿¡mÈ~Ï₫pˆîXÿØhÓ6fœ=;¡ävIYÅ”^ă2–¹.>®ÔN*"?0tä™!8ëÂ×ñ›¥ZؤMơ¾‘hËmĬâ\•*ÖôâuqwXtæf³­×­hÖ,¯rh.[Ó=ÛăN[BIù\Ư]G¤ö²²Ñç=Ki…®wl PUVsyF<¢(\¤8ܱd^t´ k®ºÜ6ú0¤\ª~*3u5\Gå₫lè¼XHô*tj-]#;Ư’æ! ‚Å>Î/yy²¾3 ]µMăÑ@oá,袛q$AXuṼÛ;à®ÊQf&éñë ₫cP„‹µ²¢ÎG£Ë° $E´­gweñơḲµ]ÎuŒ jÖ-œ^87Dëù¹`Ñ_He'­#'åŒăÉä#gvc]D ^l p®“®h”ο¹ö®â2¯—f´ŒN[qœ#K¦́l…^k…/da6aÊ|1£YY%‘ÎÜé=ŸǗKC l±ûœcV¢ƯIî9 ̀pOx”è☄¢đæó®œ=Ö$ænqûH,₫b₫W,éfnÆqcơfß „Íä2eRgGz!-c˜dy…RHtưæM,”Ê’{^₫ü«TQÍt ×d-?g\Fˆ¢¹₫ÎÖ V́´ÇËCˆD^äŒă¬Ëcº´́Ñâ‹ùËS¾=Mî¬Ba•[¹ †¡Dpbz°/ØMFđöôRÅÿa¨f™¾¤F0›Ç@—Ä”T̉4&,HđáÉ):4qăÄ/.„¸QdÆ$N¢L©r%Ë–._ÂŒ)s&Í6oầ©s'Ï>₫ *t(Ê @ÄI“6ƯX°áÆE^=x1ëÔ‹ =hMhQ+Ø«%RaÑáÂŒ=b=›lƨu¥r…Ø€(ß¾~ÿ,x0ᆇ6høtÓ­rt‹1ªÆ•³’MÛơr\†tƠnf›W2ÉÎa5›…Ø¡k]Ñ7 Ü{x6íÚ¶oăέ{¶QƒOŸF†\w5CØ­¦¦[Vd[±$Çr6Øœó]É;FtÁ!F —îØsFïÁỄ­~=ûöîßĂßÙ[àrhŒ•aø«ĐOUj“…&kr”–î÷ƠH©%dB–†si¤™…¥₫Ÿ‡‚¢ˆ#îô |vƠ}úM^w’™§–@¿!eUCá1ƠŸ}PMXÚBÀ ÷PhÙçH•µÀW\-d#dåèƠA)Öe‰[rÙ¥—_æ¶ÀUĐÁ}ùíQgÑơCMg™@›1EƠTúƠ™×œÉ9Yj|‚akp9%d„S*8•‚)R‡Ñrr¤%˜“RZ©¥—ÊdÔD +¶p`pçŒPAEåE<&„jª¯†đă›HùV¨~•Z¤®;₫Vè©-™j‘¸‰ë@@’¨¡NA'^ I©´ÓR[m|‰!$@B¬ø ExÎh䮹îZ(qàú₫S±è«}²¶Új@66o¸BªÛª©º.ùë­äÖk¨Y|:p¼ÖU„P‡Ö2ܰĂû%æCÚ:u@ơeT§SÄrœ'ºñ ‰,­Ä†|gRểk¨w ̣°x’\῭¹’ü²À„ºQ®“ûEĐE ±ĐC]´Kb¢Œl2ë ó°ºnŒo„ʲ¢ö¥lÔPCFk¸L»[¯©aü4À_?}ÔcX7ưf¾-l´ÜsÓ=í|¼¦ªƠ|Ç4ߢʬ×y3Ëk­[¥,¯×;kxá{µ¯€âÉ#¸Xớ6Ô{ä´AA׺裋(1®I1fÚdnƠ:UR~ç‘”f₫Qˆèœ©eăGœYgq ¨·QưGßEÊIƠƒ “̃¼óÏß&±âXgf₫6ŒÍ¹ÆÜíÁ>å‘9‹¯cgơ8’ö¥Ư¸U“P:¶£Ú+Z£Ă§7ôûóß?_ó ©CĐ÷,¤&ă!0;æÓ ‘Èg»Ë`iLXÑ]d\ä$»œÆ ÁƒD|‡¾5("̀ó KhB( ;xë%h')ÊOÆ;¤äDCgiÏÂ’#hCđéĐJÅ1 0–¦èpè„J\"W̉›™ ?·̣Vu\×(o=Jˆ]»  Œ³:¶93G$ÍXÖt¯<¹.”agFØÄ7±y ¨₫b·Ä¸Idz izV–v‰„\ ÑÏYơ&«éŒF\#_ún·¸ÁÁKläa#itưÅ1“”›ôècûHñ2?„ĐZ¸(F̀ …jÉJ©¸§ª¥Ë{éº#€’´*¾¡qrzSPŒÆ˜7n2˜Â´VbRxª[w™­̣V/g₫L’•ë•ăđÖiN‰r–KF₫uºfLqù*Sv¦/ûÔŒU]A#;ƒÉaÂ3•z¢P(ÓIù›±l²”M.\ŒŒ½₫鲿µ*$œ;Û²¾ö1ÎÙ¬œmógA½åG5Z2"ï”'G;")€"er 2Áw3 ¥MSh₫¸³.sBÍ]x™JçÅGµ0ô]“ca‘XÚÓÍ)ä7í)ËbV£ÖƠ΂æéÀF=êÔ§¶‡¼[úuP‡+O(›ÚŒ̃B¶c, ètËåÆ Ñăüko‡”iÇΈUwqL+Z3[ăL¨â5¯¶ )3 ùºö³•g `×<²gNơ—8ơ*ú©s¼ễû­s –XØ[+ưij› Äz-ioƒ"¸,†ôQ ÔT¬D°"d9 „—‘ Ơ6Q Ôâ ƒR¶o|Hbë*cœ»–6¹Ê Q’¦”.NUxvâ_¿÷Âe²R¨S¨&⻂{~‚M₫ơä¬ .J+M].{Û‹“búk€Z¬ng¨»à•×gÛ¤¯èEñ¨ñ…zr“~É Ă° ¯—°Q°]ƯëàëDª4̉£ µKñ²o<Ïj­ôĂ·@2’á ¿剤,ëkÈurXƯP­Â21ës&@§—®Ùíf×'̃™¥Œ~"Èđg¾K:³åđ´ëœ3ˆƒçurglåöEÑ©£•Púº} g•±ªB*¼X“&¬̀2 ̃'*¹0ªẦŒNqơÆÛJq¾z¹2ŸûŒ4đ•éÆcôăœHE·±k‘ÅÊpù|̉Ψ52ôÁîW̃vN·vÎh•û₫́éÑjª œJf~́L¯ÁYV‰n™WØ̀ró{÷¢jN9œ ơ{›Đ¦}É[_kÄ1₫4±¡­mm‹Ë¡Bh@Ó"ͱ±h°ƯơdTÙ2Ε’:t1}iü}Û×%)6¹—ÛIÀb»Í˜@Fà´h[nz-få-Êl÷‹lå:¬°̃–6ú†;Ó̃ÖpF‡]îƒóÏ®₫ơÖ ë·}]méÂåBx/¡­e]£¾HÅZ`ƒ›à!×3´nr¼̃M‘û•—â „ê‘•S¿Ï´©Ù€5ÓºŒ«úÆ̃†8ç#‚<èyF ~̣£7Ñtx }ûKƯZºĐ)P )ă₫;[®Ùçæ-nVđ¯‹\èé4̉Ë®ÄN>¥z̉ÙlRt¬FÂïÇ. ï·bk<è³>t±‡}èr1ºÙ ß?¦Ödž ë²~hƠªÄ2l6ˆ³2¾Ö‚¿₫;çÁ~g>ôqLaa£KÜÓĂE{+f`ø̉#×gxw8¢t»yÏüög-ÙEï{̉ѳ+QDS}#̣Z/¶…EÑø>DÙf4Ï´¼î«Ÿû`C¤÷¿ß>Ưæ8:.s®>mB¿•y›5ÊŸ¬qá¬Áoâ~ä×—¿ü/Éưû÷¯“ù¤ í´í  ©ÎuÜ}™û4_ă8D¶’₫ZưQßü¹₫QàóÀ—©±Ó-½\P¥Ăí ̃È üy\I “ôeĐl”UB`çí^ÁUà =ÙæÓí̀ØøS̉ÛÅÁªĐNT>WäT¯ÅŸ ]₫ĐàÊ H‰Ô¨[kyÅbƠøĐË[àÉ¹Ä Û½’}™GÄmÍj­`δàß-! >ààAá„ñ”’¡SXA Ô»d\V]ÜA ¬ Ö .ƒƠIßʽàæèÁa#> _ùËâü•c‘ ®%VÓDÎSÀ aéÓú5Ûæh%}ÆÉ„Æà:â*ë<ÅRx‚YI@Ê£à₫ÆĐưüŒ A^…ỸV袢"^Ÿư±â1JKsMO@W®ơœđE_i8G€56Ư2…ÅûÈ0"7"‰‰á!ă8^‹b ºE:6ZaÄ‚ù‡fŒ™H£5Î]UQ†"2Ü7&"§‘c?‚‰’bdψ!Éœ¼Ø<Ú—9ŸPe,™ơ0J 1‚£8úăEêFi„.~ b Ê"„td‘‰mñ’·ÔNDâăDÆŸ*bäK‚ˆÂ­–•"MbZà"ö’<¤%YråYb%Y:€Y†%ZJ%\Â¥Z‚%Z~e[Úe^eV–%Y²e\Î¥YV¥(@\ ¦^öeUv¥T.ecºGs ¥HâNñ]ÑdZ¦“™Q;’Ÿ£Iæ$.̃<†6G%¹‰X¤c¢¦_h£½VNúƯ n‘Î46¾æk–pÆư6̣bƒ¥fpÜ¢ômZKÜqrœ}›rR*ỄM^çEER çuÅŸ5“ƯPwúœw‚çwg‰Ưuçy†go y2HzÎd8bg|†̉O  ™§yjƯ6âç}Êkđ'w̃#zù'ăÁă~J‡v₫è6JÇiÊçƒÚ„2~ €.'×a¨lâ$†²›æµÚ…f¨m‘J¥Øú]ôŦc8€‰@h‹…̉©…†¡â ¯%^xƯ®¬ŒÀ0䖇˸Y•„ב Û!è“(ZÚ°Ï\}ºh”…Lª T(µàAB#D¤.AäîüÎ •_Pù[ÎQˆUØXCiiWÙ$A 1Jéœ̣ŒRÉ•̣¨̣H°,N5Iϼ; Ë̃Zß„ầ!VË™ŒPy)߬oQMúm„ƒ̉é¥Ré›\)Ä N]ƠW NÙÎA\Nª ¥•ñ• ‰.Ô²R£RV©V›₫<₫aºä¥âjMÀèW( ŸX•Pé[®9\ü*¿±L$Æ•$½ µ!ê¼AÎÈøÍÁ˜ œ2Í)_sÆ…¥æj”Êd6ú ÍPŰbN±¤ÉhŒ¨đÓ›•ÍÅ€`«ªˆœ0V”²̣è¥MªàQ„¶nk‹Ú)AZ×L1–¾q"ß,êX±'‚ » ª!ñˆbqc‰ăp–9̉ Ÿ¢ÖÚÙ*a8Âç¾źKtklẼû±cl©¬yE}è˜U¬ªG™4êÈÓI ,ÙëU0V‡Y(©Îb“UêÇíJ|=ù,N(E²‘íM6 Rô†>-Œ|«yb>̉¾íu*ÜÑf¨h×zí×JEÓm4mÙ"•>q¨-U5‹fmĐJO>'ÍmÏ♈̃mƯ—̃æ-ƯúliÚ-ßfu¾­|ŸƠ#u†í!®tFYâ.îñÔV‚amᢦTBå[rî\.¦Yzî[fèzî]₫¥@eé₫%è²nTn®a’.èîçªî́Âǻ*¦ê®́Â.æb®Ûúnđ ono{p@Oïđîk@;commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/PoolingDataSource.gif000066400000000000000000001325041410126276600311340ustar00rootroot00000000000000GIF89aJÊ÷ÿÿ{{{{„{{„„„{{„{„„„{„„„”)”1œ)œ1œ9½Æ½½ÆÆÆ½ÆÆÆÆ÷ÿÆ÷ÿÎ÷ÿÿÿÿÿÿÿÿÆÿÿÎÿÿÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,JÊ₫5H° Áƒ*\Ȱ¡Ă‡#JœH±¢Å‹3jÜȱ£Ç)€<(̉bÉ'Gn<™R¥Ë—0cÊœI³¦Í›8sêÜÉ“bË?# ÙShÑ£H“*]Ê´©Ó§P£:TÀ€ªƠªX¯jÍÊukÖ[Ăbí*¶,ƒ®hͪMËv­RăÊK·®Ư»xóÈĂ¿€ÿ Lx°a€1^|øoâÆŒ OP ¹rd˘/3`©·³çÏ C‹-ZâÓ‰Q§FíXukʬUĂ–={ơé×´gă®[önÛ¼oÓf a(éăÈ“+_μ¹BÓ™£/F,}0j —#ûÅ₫8{uïà₫ĂuN¾¼ùóèÓ58íß~'_°̃~ơ… ómĂï˜{îư¾Ơç€Gqê%¨à‚ 6H{ö (œ„°…Êfᄽ§Ú†¼áöÚˆ’Øájçà,¶èâ‹rơu¢~®qgá…H`ák₫&ßlØø—Ö I_ñ)¶á7̣§X§a—ß7ŒXf©å–\~$#3:F$7:¶akÖM¦~€%‡±™ß`;*‰#’ô9¦'lz¢Y¥ˆ]Ùå „j(—_z¨†Éä…ó1é×£mJJf“—6ù“fZzˆK6ªi¦8Z &‡¼ z説¶ê*s₫_.jjŸjç­­…z+¨¶^z馽† ,euRZ©¯§{gp²Â¦ê«ĐF+í´P% \³ORZë­¤Úº-¯¿úꨨ’‚Ëm“– ©’î†íkÏR+ï¼ôÖëR¬Rx¦¸êZë¶¿‚;îă"ÛiºÄ–#Àºúµ-¶×¯½WlñÅ YëîŸn†:*¥w›®²‹\+¦Èd»–> åÆNŒñ̀4×-¾aVÉƯµñ_Ÿj¶7dbrvw$`;; [Đ“ơhâŒËlóÔTW½bKĐ…Ù{ ÖƒIiôØ–‘=Ÿß&µƠl·íör-Y+ ³®ữÜg÷₫ÜVé¤ßw£¶öÛ„nxgdvaE/îxa‚5öׂIù¸Ú!xøæœw¾„³æÍ7“wߨă-4éƒ{îúë°Ă”’â“_^;Ø’Û̃~^ë̃@KÇ.üđÄSô•U`_ỤÈ[Ơụ̈e1¯¼Z̉+À|ơƠw•½VÛ'¯=÷χVñä—o~O)â”>LëŸï₫ûđ#%’Á¥qơk¤@₫ñ÷ïÿÿ™ŸZç‘’À…€>!q6À:đ¡Àùç‘ ºÄ€÷£ 7ÈA0'piGR²j°ƒ(LáëR„À\I„yaæTHĂº÷» a"ĂÚđ‡₫@tªZ¨¿‚Q"ªÂa—ÈÄÂ¥h~'¼ˆs¨’!6ñX´Úúˆ+ª$}̀¢Ç(/àMQ ˜I"¨(’$ƒ çHÇW•„~ ,ˆ ”3æp yâ@¸XÇB=³căLâEÈ…ˆ$^‚<¤$'¹"™Á0#$LH#Ÿƒ ’’  ¥gªâ÷¹|FÄŸä§@Dsb“ Mh@ï N…:ô¡}HD’·ZtgC/ÊÑ}f”!ÍcGG:Ïrr‘$M©:MºP™TT¥0•%K2Ó™Æô¦´©AfúRœúô:5âFêÓhªđUIܨÅ¢Z̀¨ *AL*@zAƠ©-bXJùRzµ«`åªX¿:Ö°’ơ¬fMkY×V¶ªµ­p}«\ƯJ׸ºƠ«>¬ Oçj×¾̣ơ¯u¬_ëV¬VLª2=Ÿ¯jØơô)a¬DÏ‡ØÆ6§²å+‰d5“Í.(—–fEÉRÏ&h}¦ ­y YØ4µç‰₫¤j¡5ÚPÖ–U·í2qÛCơV·Ÿù-P) Üi ×ÇTr‹{—å̉ѹ[‚.sç"Ư1VK×nT²‹EîºÈ»Úm x™8̃J†×Uå bz´̃ó®Ç§íư¬{q _âÎ×·ơ5_|ï Âü–o¿ü½ €U8àô8À(å­}Ü¥çtÁ ®Éçà·sÂÅ«°…G¢avØ9̃p9¬_k)Ä DñrTlâo’ø¿-Æ.†‰Çâ¿sÆĂ«±C#ËLđ8¯*̣}Üă cĐ˜Dr‘‡ä$;¹ÉPf²”— dÏÊJỊ̂“§¬å(ç´]æ̣–±ñˆ;Üâ°I£ûrŒ{¼â ¿[È₫/>rƒ÷ óN(ÎB·›1EIƯSj^–£)!Í62¿‡hλ‰miöIZ`ºs yÍo­‘€lC“¨ß$ưI₫æåtγŸGéHB‡úË©345å‡ç½ÉùmZ#§Q¦GP NÊ!ṭ₫`€M”nÄ₫$¬ÇưMzjZ¾ç®́øçéµùûƠùó= ữ0tÿ83 YưM³ùQoà₫·¶_@đa£áµ̃ö¢=F̣câÚÍͦ˜½Á,6(¿+Ñă=̣üSḮvo¨Ëæñc#ư$ù ñhVY;¾ó”¤ÙëÆí±!QăuÛk₫H”»ŸjN›œ[}úÂñYÊ₫³Óû^ú›·wö©³Ê¿†öÀÉú}ºá̃ôc/ưƯ/"¯&²(ÿGtrÇ,ÿÇG3~ygsˆ¡oÂ×3r€Oç5êx'çyS"6h’ñWy]ƒ6t>cp§|¡x‡æ$̃ d·~¸̣v@RzG'€!z!(phĂ'gvCv”‘50#h¢¡1:wg̣{ë÷w;c~}wy£wsÊ·7á7+I€5X$Aƒ}’w"Â7‚ŸÇ!¼“0ă7|E§y´}µ‡'°Ç5^G0˲&„G"¼GÛGPƯ—/Éâ)Í7,QÇ3q2!!Óoÿ7*₫¾Q‚4HtJˆû‚}W1»iÇÁvù¢-Œá&ww¼âṭ1w’̣!‡ ¸z&è3Â{`ÂE{(Ú…:r!‡ lwà‰çg,؇xSˆ'3!¡'$àw|(GTŒGƒả‰1h0’u#ƒG"á²0ä7¥ˆlr&_86×w„“÷j£a„Â0Ö衃ó9h‹W€9*Ü‚*n"‚h6Óg#w’v4†ÉW! {éR†”ñ‡Ăˆ&è…F3$ÊÈ'Ó×…ç².̣ˆ0Aø(?+÷.}x,¤̣v©h)rˆ)’2’ê‚)'S0¹B’,Ó.&Y)Ó₫2¢‹́¨±EE|¾Ñ1 c.í‹,É+ Ă)#s‹EI.=“G™)̉×’3é)‡¬ˆ*”"¤ø‘)ƒ’r’”'É“,y+/Y”æÈ/M]I“‚¨y8Plj"$₫²# 3—é8.ĂR0$c0WI—©—yx ˜óÈ€s/Taäx"ÜX—¶B2æ̉‡˜ )‘Ù/Áyi™¾0pI"₫˜~¡0–)0¼ÂÂÂ/Ø’»².¡é—#%a™•ª¡w~̉–Ơ:Ù‘³©.Ưîè+^¹y)øÁ+;S™Ÿ™.Éé-ñ˜+ƒœKH%₫¢t`?a‰arœµ2fy–Y²É/éR–P眗y#D"”æ‰+1¹œ§é|3̣€á42&ơù˜C‘,yâ·è˜_Ù™Y){å9.I“ƒliŒh˜Œç™“Ñ0Âi› ªßR¡:)èù0Ë©‰áb†°©È‚t´‘l[5X.*X0ZV_¥Uưö›‰¾̣#„)¢ S+ê-;̣)©ŒDº.À›)zÿ’¢x˜ÅˆDhØ—I')$Í˜Ă²¤vY›ÊY¥éx0•Y2dó¡&u"€”‘‘ﳑ|h2́‚ ̣™”É•ÄÉ¥2’}x£!É™e2–)™”·¹/*z‚₫A|Fß•yª‰[¹#ɹ”ZÄÉ£(3*xúæ9Ÿº)2!3’7H7ú¹‹"Ó‹uº•‘©oª £*—Hé¥V ́22¥§‹Mr‡§á›üô–,w„Ư}h§u’i:›ÇB¢y—ê¸ô}¢SxmJ‰†ª·‚Âá4V8IR¡ƒ|„x%؆'⪂QHu6¹«·Kä„§zƯÁ†&z…ß§†‚º:Î÷4‘÷‘θºOÀI7®¡.&¦2zmˆwPÙ| (…¦¨†ëpi'vÆê©œß·–€g4~ˆ§¢'í2€ƒ­¶‡¯J‡|ªÇÇww§₫ˆ’’ˆ‘vø!(CJău‚&đÈ‚C±·ñ¯útŒ˜3 «±æzŒCk‚5H²˜G|ÄØT ¡¥¨(7y¨ §@#+ó*ÛµtÓđ*q³Xc¯ÇZ|ké†íZ‡U2•Oós+†±÷zu;ùG…g£†ÈèŒS²;Íjr"¡C‹±°qƒj"·{{P+ƒÄȰû#f'€’;¯p˜{£ m4 @­RË3.{-_˜·Èê$9»sV‹ŒC›¸äçyÛ1p*»¸ơaö¡ˆŸ«ƒTÛ®OăºEÛwkˆ€­‡¬#˜F?¥«©;yU+"èµc#zxˈ¬W“ÄH†#ys₫2 i¸ “&÷¶́º±‡»²14nëI""&K¾˳½§¾̉ˆ!¥™?h´è{UÇ·̀Â;‹vø”çŒƯ(s€2¶ü¡¦îĂ×{;ßq;?C®ºs ¼·ù80” ÁoVdj6?\6¡AXÂ!œ'¬5̃¿R©®÷è¶ÜqLÁ(l; ,…­´ơ=Z£/JXh•@́ĂD<ÄF<£ÄkÂ72âÄO,Ḿ½EüĂV\ÅX|ÄYW¤4<Ü¢[ÆZ<ÆWXĐs°:ܽJ¼ÁL\ÇR<Çń9Ÿ–ÆÊqÇS‘j3ÑK¬₫́Ät,ÇuÈ…cTz 7À•È…Á ̉T2¡Á†Œ“LÈ–LÇ ÄÈÉ¡Éüµ@TÆ1ÅÈ—\Ç£KœŒÇ̣ók„À7h́@©Œ³̀\WâÊ ¡g¡üÇD<ö6µÜX üB"̀ª|̀ÅĂĩ‹dÈǛ‡„T™³tÎ<ÍĂ5UÔ|Í’TUIv%ÆŒÍ̃¬EÅƯüÍä<5ÎDkÄGå¼Î5D‰Á½́ϲüÎ`Œḳ|Ï4”IÁ„ÏǜA`ÖÏư>Æ/ăĐM_Đ­ÎnVe ưĐåăÎ Ñ}8XÓÁѯƒËƯÑxÁÑ̉—&̉$í9 ]̉(Í₫'̉,}+Ử0ÍP1=Ó6ó̉4Ư=(9Mw´Ó²Ằ7}>­ÓZä CỬG jUE-’ÔA;N½hO=ƠöbÓMƠ²ƠRÍÇXƯƠñH^m8̣æäFÖf]Öh}ÖjÖl½ÖjÑUx6JnƯÖtM==<×x]×z×oÖë¡:€Mæë»«{®Ă ~"ˤ̉øˆ÷¹Ù .²b³~§†Ü1Ù¢ªẫÍâÇœá5ê}]c,5I"ä k*&R Z³`+Á3.ä́] ̃á,çby±!¨+‰£₫Q—0çév~â²2 ¼º)ƯçØ=à ´á’¸“SÊ­IW®yrˆ}Ÿ<*¤ë³‡èZ̃Ú¤°®„̃د!é©a—2;ß;»Ü‰Q¯2ûz+„ ®è6áåùÛ{~œ¦"“ “…(ŸKÙ.˜́°é—;2–ná©qÙƯ4¡ÁÙëÄ₫¦Y*“e’£B¢œb’| –ç ³B́̃̃́+˜x¸.~²h  ưÂ2¢]j†₫ѪÎ.×y)îØ¡”B$•¢/~è¾Åôl•‚ןüï¢B¦5ç——g›{‰.Ø© ª)ÅÊ¥o!?jîÀÍ媬ëß₫,¨ñ¨‰¢[ú/±™›Ư"vY–è"¨ẵßçn“Đ¾UDçGn,(¯¡°ª+ă~¤Ù¡£,JÙñœ —Î̃"Çën¸í ´éëoôô¾ô!Zè!1Ÿ™’JÚO®Qä¸höx"¨Xÿ+ZߣË.ô8̣œ¥Âô³yôËâA¤©¥²ø°HơiḶ́Üë•z#oŸ[9ª©§/«À²/C¹’qºáe/8Ç!Aª«â½øà^2CÉ’‘b́˜2–?/‹>Ÿí'_«‘Iđå(ø°6ơŒ/o₫²Y3ă,\¾¾×… yé­»đ»à—î鳑ó ‘ZwÄóN₫Z9#̃çÈM4ư=Ùk~èÍØuN#D§~C>„é.`¾ë̃}¬ ạ̈é(Ăz;¾gHŒ₫áưè»àl[áç^`“<ơ:æoă .`HĐ Á ,XpCƒ /L@±bŇj”p°"Ä‹ =6¹P”)U®dÙ̉åK˜1eΤYÓæMœ9uîäÙÓçO A…ªT̉(É£ *Ơˆ‘$ĉ)̀bU;¤èq«Ô„ §–Kđ+T‹%Óª]Ë`¨M o5XYÔêHw™~tºaƠ¥Ị̂øµäÖ î „:ø`Y¾xÙ"=ôÂI¹™5oæÜÙógĐ₫¡EÏ,vr̃¼»®Ù²ZÔ{ ›yQ¢DÊ3â6»qơÓ¦§³‰y4]ºC“§dĐĐôd‡ÎU§UØ÷̃ÀS̃HáWÄ”#¼dø¤ÄKỮư{øñåÏoÏà÷DÔ’¡C”€^?kSµÔ¬L²ózĂª6îÔKo+ö@` c¢P¥ SÊp®ºŒ:˰B¯@èB40?ÏÀ£:z.­₫D1¢é³ñFsÔqÇÍ`àG‚ü±̉H$‰D̉H%‘T ',RÈ"“œÈ%‹T²Ê'¹´2Ë/µ¼’I/¹lr̀+‰œ’Ë+×S̀7<“-±₫t̉=äVk¥äúDÉOM)Í6É́Ë2å”rÑC-tJ(ѤS̉'£¬“LD'ÍrÎJ)Ơ´̀GålÓM3½¼´HSUuUV[ű¹ So#̃®³(»Z×¢Ơµ\m‹̀V½¶Ûơ6ay¥Î×kôŒÂ Y Phÿ”V¥æ\LmD] C-¥ûơÖmơ¶»]}åÖ¹ÁήW‰Ü̉`OWă•w^zë•ɾcú­Ä¹ ë?~÷«ÅK̀¯WÿfĐÄ´”]VĐ—¢ TâA^E§Ê.·À.ø@AÙ*u% »…Œ^{[vùe˜ákîVë´ckF}=î¶²TѯŸ₫‰£*8œñX·X¦oÏ 5\n®åÖ@çÊí·há́ùh£¶6úëÚỆ å}yÉƯ˜ÓV{m¶…*Í!Ó“»©ă¦ûî¹óÆ{o½ûæûê’üünƒ¶Qj””†if`¥¼;s› ïñ¿)·¼̣×À…Üq̀/HºmĐC}ô£+€oënØƠ[WƯVØSçœơ½ —;°tg—=ö°>ŸÙ I颜ơဥ]o jΗsÛuwúå§ÇîÜëv³z 'ư{đĂWV&¬u‚^ụ̀ÔW?ưƯQ~ˆPQ*Ô”~ơ¼Mñ—(€̀QÍ@̀‡>i­y₫@^mh–¾Ï}é£`Êöwü±†}› 0@ñ…P„#l]¾cÀóцBÈĐ.ä=ĐE^I³¶ôQd†aa‚D‚­ûµe§Iw"4¯ m/àÛ"¤° ṔaëZÓâæˆ€a¾#J'#;œâxĂE1!₫‘̣HÄ@ŸuÍ$-aÚĦµ¨E b$äcGèD,V@`dHED±Hd7Ck ôeÄ""BÔÈĐĐ¢½ëùk}Œ1ƯFX°h‰k‹ ă,Å’ˆÎŸ2ª’“Bœ é­+"æ,ºá¤C‚I‘,¨/₫"È0?ĂåiZ€̉Đ•éGhFst&I#hËBN¨"ad /©¨Möđ,¦6¿CpÂ1-,¤9ÑGô…1ŒÎ‰ áÀ(0P₫ç H[uÅÀAN’‹Ù$§ÓÙHm4¡êä"8J›Ót̀È< 97í³¬ mËXṿ +Ukw +Sœ"̣¨ƠÙêo{kÙínq°̃ơov¥ÓÙÀÁ51®L@˜8çFXẬ ,WԲŋ1ŒCM,U^‹N‡‚±àäèE!Kf]V¡"Nè6gÙ<«W½MK₫{™è.ÓS•b£PBj9!”mTœÜt¬63RÅorå°qÍŸF_kЇ&¹yuåv̉ÈÁ£]†'p—½́è¶²ŒÅ ¶ø—Ịâ²+Sqܘ/âê/wf® @âæ¥Ạ́biq –DRyb×î¿/fnˆ)[j2̉>9£™¡ÜÙ­H ´çwé„Ë_æt§sØrIà„d>ˆ¨‘bêB¥¥—¬Ơ †¬ºA †¤3ưØXU{b¼Œ33tù D…¹Vd‚D¹FF̀§¬½‚ÁÄmn6A0íilg»„Àq®r†«öeÎ óưHÙ,LL©"ѳ/tͰ₫ñŒë…èz×.¡À¡KáFc3–ˆµv2gßZàëM÷˜ÉB;|^[Û g¸f@½À,²ñ.ä¾¢æă$hˆ›Ës]×ưgêU›Æ!Q8(PokØhl¾øƒ¬ÅTgÑ?$Ù»?̃ñÏrc#¯HÉ₫s óä¥ )«!ZÓ"ú{‹É¢,¯"K©Î˜çưÊU¤~u†È;U½FIŸWßlĐ཈ö₫®úvÇ££vÔ¹†ó:)5s÷Í|t¼ç]&Fáy[(£F?ă¾‚È-[O=ª^Ë•œ ơ»çạ̊•5³ƠͬÈFÙܳ@Éxu·§hñ‰ ¥ñ₫­xkë]ơ«ïÉĐJcù˜·>-Œ ÙÀÉ;½Qçưèåøxß—Dë;jbKâÛBT"o†ª́Èưfi z 1N}đz&0=sd}÷½OmY¾±qû{Ñú¤ÑwÎÓ¹úv›|lÙ¿>Ö##‡åx}ç»J‹œ₫×Z‹ạ́•‡h¹Íé½ø«?ƒ;ÀªÙ¾©ú>ŒÀÉkúOÚªÙc­´/b‹¥ró1¸‚?‘Ă:KÊ–›«¶á#>jQ –»mJ¥t1Ă¼̉)íq§¥C ¿C½ =¡q63û“@"ô²À’.ÁȦæË¬›²¡³";4²)ö 6z:ÁH¢₫5¢?yµ\°‚Âù0SBˆ¦ª(3”Bås῭‹µ—*ĂRĂÂêë B´w›´y0=t0˜Ø´=>äĂDz#D:2DgAD=QDdÄ”đĂ@ÄA|Ä?̉Á#±Rˆó«¬Üâ)º©3văª9Ü,˜sÀR>€IAÉ# ˜Đ¿³ ‰‚²/ü°q£p[%”ѹ!7¸ăA¬ë‘DIq)%cĐƯ“Çÿ,H ÅưÍl´J‚ Ѭ‰°ÜLHơJKËK¥ÊLƯJă£L¶9B0’¢:Œ,§8›³«ˆ 8¶Ù(0,T$íØÇ“Áº¬Ơ©óRÎđµ¸7(*:s·¦‚£Ï›)5¬9$‰a-Ă~™ÏuG \-Bi}ÅJ4äc4+º¢aÚ.Æ(Á!µ3µ•æ;%Œµû| ƠrMUƒSv ¾9 C›ĂÓ$ c‹É¯Su«·\—8₫ô––[czÊĤĂ™Vƒư²”#ñ '5L*r§ßØ0J- j±‹J1!cŸ‰-µÎÊÄ‹Óvw ¥ÉCđ#kj£® ±‰²Å œÍÀ0̣;JdSq#P½h=X壔Ä*3) äÖú©¬IZ,ïâ­ôZ²¢ *¢zÅ8́¸³f Ù ử÷$ \Y؆©tLJ,RÔª«#»²ª0@â@œµÚở²Û¡˜ÔªÚ–Å‚º̣ËÄ4*üz+Ù"«Ùk¤¾U€ívôB·¥±‘%ÙAÁ X¬-ŸK± Û–/}…²¿½•¼Cj[m¶•[i]Ü₫ºe }(±mq2Ú¦Í\³¢¯©m¬ûB¬Mä®[YWùØ 5ƯÑ0:¾¦˜/ $´¤ Û®uºœÂ<Ùu¤»ÅÄĂ\+[ÍÙÄ]̉%BßIX¤84$* @̀:¨PœÁ‹eXË.ñư©tt!’±gƯUœ7•‹Ô.¹u2̃r²)c+ĂSnƠÇÇtJG)ÜKÜT„Ûë]à›đ]—Ú̃?CµƯÇ3Ë̃0ºK*»i³¨@‹6ܪƯƯªEë•¡‰;}¶ni´gƒ6×į² ^RVaV …ßF̃aL= ªÎ©æ¹ÜÁ¼Ù-2+\#âË ₫PêlÄ»»G.´B2È›ȾĽ² A‚̃èT`.c–Z€1² øáâø ù17~YØñ¸XăŸÑPº ßü4+CTÏZIÅÄ9̣¨¹›EÜCåƯơ0cFÖFÑ)K9.W€kbJæ›×bưXI'̃äJ^æTæØc²²ƒ\¶5åƯµ”Ú0Æb¶«F~å®ËÚ´¶‚Ă¾5®Ă;¦c]Đ‘¹bÎåôùä›P“ʼn{D`VJÔ¶u3¨è¼VvÖĐ¥GX~eaîÍ©b«¡¤Næd'–KÊJ1Ưfq^âwå©ù\hÖ>îIä¬CF`ƒ́½jf†‹bz₫é”(iCaLi“: ~~”€₫ç}†‚h„6èB h‡^hˆ~h†̃‰n"¹hkǻ´Ç@UæZ¢÷-eSăh¦12¶g”t6ă•~ àɲá?VvVÛ(iêƠÍzNi–ImiϨ·•îFY¾ E-Í—Hay¶ ưÎ ½‹„™gœn×îi¬₫9…;ê>²HxIjHăäæq^£ö»¢̉CâK.k²nëÙ̀̃¬Û«₫>0̀J®f¢ßổ´:îk÷é6ökÁl–=ëëkïæ»ß·‰’0Á’SùƠ–”Ơ>Fm5±81×¾m0ymܶíÜ̃íÖîm…ÏÎîYĐ&ÂjV©–‚k²næŸâ.Böx&Iµ–Rë}î¯ÜRF%!†lnƒÅîĐvär‰ñn–“ú«=¹näRïnï—ë¸n¾b ‰©oçªSñÁŒs®n÷ïæ6àéCû¶£ùæ#â ¡-|îoÿ]ï–oÄQ§˜êǽù(%Wlp đ†nœ €̣~óæï—ë̃pg•—Và˜†³đ ÏđŸñ­n…<.”Bî¢æî©Y)å¦q —™Ïn/Ăï ?r…qƠĂ₫4 ^qWï®öT$Ỵ̈·0̣¬¾;iô«“pr*ïr/_n L?"æ//ó\rï#-h:q3oóÍạ̀Å₫¾ô–̣ïQs7¿s È^8_=%!+_s<ôÖCóîëc@tDÛ>ŸữqÇNtIỴ̈FŸöÚó­[ôIÿrLçó8nï̉MuÇp† 0M'u ¯ô [ơCơNguZoWo¸Ruñơ˜ÑơZÿo¥æ[ïuGï_?vJ…åa_›Ïöldv¬> iÇ;êäïe‡öiöơ†s n?ơb×öul—ôïé'ƠêËwuŸ&Äö5:fÑÚnj̀Æk₫Ïèuơzs̉‰₫ơ­Á +¼đd“®ja¦»h×HÈQüéÅSä[^>YŒœqú¥,ctºz2G¤hÁ ¤²Ë1Ëœ0Âj+1ÎèæŒ›¾̉"Û±½)U\ϵmq^ó«3ÓÔ<ƯÁ3cƠ²ÔU[ ç®ÀÜôÖ(ÆÖÛÑ SŒ\K¿IëµÇ#ôØsí/ºÚ9ëƠLU«¯RkƯ}û=UÍĩüvºtÖ§Ûq²…]Ñ{¤*²̣¤öÑÎfØơ…NCD+Bÿ=PÁ{oơ¦èŸ›.séjív°;'yñqc¼ä5¡t́§–_́Ÿík₫æ›îyßăŒ Ơúf̣ Û}:ôÑ₫‡;xë„»®åS2¾œ ‚Æ‹Ÿ~EÔ)Ü¿Wïtd‹ ,½f!Œkó1ÏPǘÛoÿx©?¸zá¬̃¤’E2 dÀP+:\É.Ç:óu­@|Èôç2í$¯y< AP¢œƒô ăB nP„¼ ­3›Y¯…çS’†̣%·Œh^}̣“–Ơ¿̣m-} 9^ RÁX°ƒF̀ AxÂ%2ñˆ&dâƒ(Å…ÏRsađà’C¶0Z `´Z™åđ)"UjđĐØ:l5¥FS<á•XB"f„N¤ăåÈA#Öï~́–Ü"E½,^ÏEÚS–Xƒ/÷üÇk^₫Üy¨FÍùpe‘ Ơ¢¨Ä>êñKŒ£'›Çơư±”¦́̀˜ 0  X¥*Y)ËÀR P%.i‰K\²R•º̀å+céË`Ú²˜ à%+o9K\S˜®́å2¡©̀c“¼Tf+¡¹Ëj̣2›Ûüe4·ùMm&S–±¤¥üRÅèek“y¬ă;?IÄ(–P„́ă)ó©ÏÎ0ÀO'̉¡—ø¾G4ËÊ’FDƠ˜| T| ̀^“ Cí”# 8Ó ¡— u&dySÛ'Hm…É©eU¥2cê$ yi/‘Œ|‹"ÏĐ­”¦Ké©cnLÊSÈƯª2̉•bm¼$’Ú®E7{ ,_1đ¤Ûˆ·.ñM`Ñ›P‹ØÖ­s9(xă ØùÊ×"¬¼Q‰7·§ºé´.₫€k®öø¦Ü]WEåŸ̀úvC_] 3W¯ åCí5L‚…›̃––´£åO‡7ö%§dqn€SÜ-«nªàn‰ÓŒ‰¤.öâÙ_TR±viL¼µ#O"ÇvH1Ç5¨q‘œ[•è¾dR1”£̀«ÂƠžmplb1Ä 986Ọ̈±°,Ù.™/]4̣LĂiY•Í“ V,_†]ÔI¹Îu£”Ă–<ٹܘ.2ɱ^¼Û1ÁÈż#áÇ|·gÂTtÆÜ'ÙæXS÷U¬çlçM¯IÓ ªBeBè,kYË%!ÚŸ»́ç¾TŒC“®ỈĂh¡*̉’¼uE₫dIÔærº×¾ÎÊÍ’T“¶Ơ¸Ý}u_È6²ß›vÅés&«çJ¾¶­Ÿ£:Ï”,₫5¸¯›g%ƠđÑd̀á}2̀tûÖS>ë1²Ï̃ö#dÄ5U±Í%ǵÄá₫÷¾½¿ÅGÏÓÿøu8N̉€f„P"vÎ÷(\̣£đÄà"ö'¡JÄà.2ÄpksÆơ=÷ÈăVñù£6tS1k$WŒ )zR32}&ze "ÓZ¥©Ă&Ed D“Œqœs=@9ÑĂ3ô°'ĺÜÜI¸»¬=)ÇJI QH&₫|‘Ï”"†á ©ww½"<ç‘Ù¥ÂëÏ ́†ÿL°A¢ö†CMÅƯ»Ôû¸AƯɶW22E1ï¿Í£́Ú•évpøÑ‹»Ê:|ñâ_:%˜¼üéËZẠ̊®%9¡A(†oÎyH÷}ç̉9­iÎnøÆgđ»yüä/_øÈw>óŸ_|é7úÑ¿>ô¡Oz?‚<Ánוk¬cØñ¹'6Vܽ…¶́zá$ÈY4\„ÛyB6ÍÖxq'êđ‡é¿¼ĐÊÿ₫ơÿ   øtßöŒ‚‡¹zăcaœTœr` ¨„O =RoY˜´©[9²ˆ;NHä’ămẵåâµđ"›â("©†²Œ×*ËCúYAơcnùS`#©[‚£ÎH‹=6êĐEb¤ |íI5¢•ÈÉpÜ›6"‡9"‹(PX¢R̀̃ ÙcE%v¢N2ä³8ÛM¢úÅå³£²¹"J̀₫DîeÙ¸âÜäí›q°²ùà]®M\º…ZJ%£Đ$ ̉Đ@Ô½u‘{Q"T-KfµƠSjƯgUÔLơ– ̉ÔèÊ ÎÆØ`̀Ñ N¦fåèØÙŒjfâ°ÍÚÈÛøƯ$ªéXq|%fî™@zÄb2&Ñ= r¤^‘bJ-Ç¢å^SYÖ[3²¤Gf#¬ñàÉdLHB>R¢È| —Ơ&y&Úmaï ÆMgØÍmDŰDn~Lb^€^öåpŸjJ !FD 'q~œqn̉iàs´ˆ’P`™Yæ© …±,hªhJ̃—4ºÅíá›v.eP%§L\âf{̉&Đ₫4¾đҧŸÑ&û›lúŒ[*ˉ®]†\–%€è¿aXs\†‘e ˆÙ-&¥^\"3ZDøF<éz½̃e‘` }Ư®0@Súqưeµ‘`² ?&Çà%Ø<[Ü…(–¾bÜ)[™¦'}“xŒ–Æzº¢Á‘ŒŸØ ̃U&(Œ™m°nî…‘©nÂâ…Îfn©›—ûI#¬åPJf”jçhæJIa]T‰C‚çPˆÊ"i6R§ ăVB§ÓÑ\v嵕d̉Å‘åx̣ƠæiÀí)[¼́¹áÑǪZB¥ÚÊ›˜Ù'Úï$d™­†Å₫†f•êÊw¦³”̀yPTg>ăÓ%’SA ÍYg.M\àb\)åF̀*­₫J·[ü~Ù`ÆMÄ^„́tL,ÂĆÑk¢”̃Ơˆ¸ïI:æ„\ê¦ %Ûµ$ËaÈf*ÉẪU´ÑIºgáTAƯ"²öÖ­…Á¦«Á€£ǵ Ê©aO´äF„ơª©ƠÛ>X±ƯE©ù…ÅUqF‡xÖ¤î¬ßUiȳæGWFVÓ-TtQ#elG"Jfª©L`PeÚ ¬Ơ¢µ  ƯÖ`’YÈÜåÙäD×"‚íí¨ ¯ä‘Â$ß,[|l‹!Ü66)Zµ₫TH%ùx„ ‘\sD,ÿŇ…g½ª¼œˆ̀9]QÙƠ>×£́¨¶Ư(6cƒÜ[In Uèf ¸vD³¬YŒ™#Ï6«jÀ-„S-YŸ-2åR9]“9é’.E“9Í̉ñÅ®é̉8)ŸëöŔÚnï̉n,Í®/½îéÂ’î“2Í®2Áî*-îƠ˜…Ȇ#ÁmLe>ë"hJdÇF•³…e‚)WªHỒÚaçåµîÀ‘ˆ•ăZ&Jơèru$¾$₫èDUăµ å#]]äº:ï₫ØêWv,̉^|ˆ ơÎ"ü†åbÛe•oèf*ú:ˆʇ 0äÊíÅ%́"%‹₫đK'£v‘J»}åÑbªA2í}%g*WÍÿ"̃ÑƠ]^ÙPfnV°R’́-đ$đ¹ôèºíæTé¶6é»%§¸̃U$±đơÿ¾ˆƯ%PẺ#R^"úÄđ ?Hôʰs¤́Y"`H§ÍVï(’e§ÊŸp ¥JEpÛÆÅœơJ́YºjØÆ‚ïIö]Đœ¸Öo…Y+…µŒoqu%®>ăd₫¦]àÇnȇz)"}1ÂaQorV‘fR’iKºÎĐqѾ¹®W$†ä"OÔUîü"é±"KM{qåXJÚ‰míj*Ḳ‹pu&Ûg†&'k₫G2gè#ïX83@éc̀‹…ÁI¬~,R¡9æÉr„s ăGÖx¤ư&¤&j§2Ï2wı‚|Ÿâà°Ñ„œ¾×ª±bÛȧœ®â#Ëo!—Xn§SUw6îVÙ4›ê~¬ôéíw̉ ²Ú4FÛ…bØ1q¡´³;¯eûØÊ€¨$²¬fÄŸÑë¾úØ5(a,,&ó½1<{N8³3KsÛPLÁ_½½¯,J"éŲf²û6́@QæñF„-.Ö´,‡´Âätv™̉½§Kđ«°ÖTÏkNx—pØ]}L–ÎF²RÓtLïy€ôeD₫+Ç@óB?i+.½زâ½nàÏh´¼É+Ê¢µl^•$>ßåªzÛ ÁµUwG-cÆR {骟֛z-*aÇ` ¬™×fỊ Ïß´¿T*IwJÇÔ5!;R™®ÉÚ„zÍEª_Ỗ¡=´ÀjàfF|&N ï‡Øs„̉ V ù¡r VdçiIKă[’ÍøÈ˜Ø)o™í)₫Ç:îÖ%Óq††·¤º-dŸÅwâ…3ß!RèḱÙÎrßE¼[¶r»ÄƯ!ª»ª36!«!u^«0–”÷sÆds†8!zæ₫…—¥Z×G'.êÓÖcM7¡µ´₫Z¶¹¬^µÅ­´~Ó,½̉¶–Dmë+ÎGâ,˜sꃫçMèu‰Ë́È ™h 8?i$ 5´üî?œKÍ#epe¾öµj̣…íYî¸XôÓå¥7¨¤#‹Ö j̃––ơŸEuÿ̀M¤½Öh6„²¸CAœb૆™Ùấ{å“‹”— É…`Ư$¬©H páp´ ²FăZùß“³uưù!‡¾æ(‚‘5“aÓN®¹ưñ”D1˶½U§yu´ÓØƠn¹*ÔÅ89çƠ×9Z`µI.¯U·ºĂÙç “o§2,x[8A':LúWDk»X́ ßjp₫I_8åă£­²¾|±₫«ÄâÈ£ÔHê Öê³ê?±F“N»çºà5ó,¼Ă 5œM© eă­µµSé# üƒê0Ṇ̃)ÅÛjI5†₫»ê‚±S ±́tômǴxô.<îêâËĂÛHË$e„ª8é^´®8äJ«(A»Á÷ªb°?* z;U+ ˤѢÓ̀ª°È6Ư|ÎÚøê0N¿@üM*2‘.Wz" Ḉ-Åö¾K 3¹ T;!Á ²ÇG® ˆ¬ó¯ÀNRO<ô ›>ä4U¢Ê \OOˆ*ú¯Ôå@…/´ÍnĐYj•ÄàB̉ó£(%JMA 1–Øb¥‰¼˜è¥"üYpC”ºÓ̉[æ÷o»¤₫q¢«ß27£ï¡­[ßH/æ5¯d©@ôà̉"U æ$ú:Œ¾ê>n!î~œÑcđ½ °q(<].ƠÀó¨J=ê!La>g"­ j9üj k:±sÉ(F):Q¡̃"¡±•ˆOñăÚG³đ pq taQ8E+₫D ₫tÖÄè>è”*TVAƠX”Cœ÷-D>K[OdJRÄ+ ΃đ2Ÿk4yµđ8kS¨Q̃“hT73} GDä̉Ôöd¹đpÎ9Öä×ReµE%‹yÄ"Đp”Ÿe(I9JS–•§Te*Y¹JW¶–¯”e,[éÉPÊfNÔ@%h­ 9 *ÎÍ4 ÉsQ̉!KVª‚A—!h…Ѥ£ §‰<^‘7é€zđǨ@Í+*Jsö÷ØhcrLßJg%¸D,p_c̉gvq–;™Ô%ONK0lư':ĐGT U(A•dMăơåVÜ₫"¢FuŸ¥­…Vëy©´'̀X'2ĂÙ“ÔN¬‘°s´c5ϧÏơiV‘ák42ê'TeTƠ}ÄhªEUI8:mĐ;¡#œ]µ¥"îq•Q¡5I¦²/.ƯgN¨%]µ,XƠjV¹ºU¯v¬_kXÉ:V‹YêutÖ½3­b†{?­EÎÂĂêm4W5£̀Ưr¢pbç[ Má`¥¹RöDtöbÉ`¼™¹®³+î\9̉½»ît®aA“e­8îeé>²̉ldH÷«sQd*ZÉ€µ07!©Nơ&0Z˜h¦Ó–!₫Ÿ·¤Ơ­ÎMK\u‹¹ld3úƠ¹uà₫ka+^jí$É)¾´ÔGÍhÉW A*ª9Ơ .;iJéx©iØ !Ö…’K§T¢- NÆ}Ḷ(O?“4¿ ¥–2Ë„Y-–K6E—fÄƠú©…¹Í LÍÇP„‚­r¢éÜ 1÷§k —-{¦±P‚Z-5 &Jă¶E鑯¤ˆ!'ç(·Û̀;0¦,Û Uó’—°,œêĂ4Á ™^i™LËF(ù—¾$0Pû#L%;yKÆ\“‰Ù_fF>±‚ơ˜c?™O‘Jg-7¡®Ǻ»(e•§ ™ÄKâx¹¸¤ ‰Ñ6Q“öJºØ+¨<9\—%~çn'ô– ₫‘ôe8ÛX¥ öˆúÔjHNÁ !ôn?sSă$í2̉• SÁ’²4²UÔ‹RvéÚÆ–€×»a©$븿 Ÿ= V°:íç₫-Q¨I,‘`XeE~¸~øL4ß¶¹©FeÛ! £ef}µa~Ú`\ÎZ0°½9Ç7V!ÑtÉ€iç;aFWK‚5@4‹Kƒ¥Ă9 FmuÂOEsTiEXÀ—M[Ån®lWkJ­ñJØ ß¼7!˜1Ô™N  ôi$úæç±'åđ°^˜‰₫“Z̉ÅpfLu7«Ëma}hm§½ZŒÎr‚«ÆxÛÍ₫ó›¯èưƠ;o~ö“̀é₫Ï« ä“r‰Äw,ṭo„Êt*]Ổx4>IBăª<Ưc‘XW¯¶ZƯÖÊíV3%‚¡`=?U«ï <3‘^ H‘8?˜+ü¸B²*5‡]^Æ=®Ûƒä áÊí£½aMÀĂåêߦ®eŸ6găóƠF'82OL¡!ú>ù=GaÓà[ª$÷HX`ÉâwJ¤Æ—Iă=¦WÔá–G`Ä¿̃^vQäøœ ’ïQYëÑÖ}üXâĂÖÑv7¹¡ºOÉ)ơ8©]Í HsœéH‰syàqí‘©ÿb*aD Ư¹jSj̣yßúå!đÈz÷¯JĐ}ĂBơäDÓQ¹(E \₫wl?+ü­—ÉZ«3ÁJK°øçBKđœ R–/¹ +Û́¯°­øº-Z¶Ig,̀E\ÜjĂÀˆƒ€k§î&O¢fµ®ă@(ÇfŒ+`æ'DĐtK0|₫G.¤ˆÎ¨È'fp6$§ß'~̀e=‚É"$K9øÊœø Ïïpv*ÊP‹§ÆüpB́C(=`#ºTEê>Ï™öKVÇ.¡N®‡/*RÀd–††>,˜¦!¯RÈ(?|ŒP”È‘Æm©ñÄ&Ô kÀĐ̃Bƒ̣åƠ ±GFƒipÅê"‚̉`e´đù꫽¨®ê^eÍp¼X/6ˆ₫Äë,`oÈŒŒ.†˜ˆ`À úœ0ÖÄ0ø„<̀p`J›¸©±æî½*,|œß̀³DÎíQđ6­.bFP–0̣₫*€‚+F1m.¤̣j¨lMhä‰úđPl~®Ú¥oä ̃ưä<6D&9ÆÄV-™0b₫â đGeqëQùø°bijÅàoé,-Ô’°§–*3D ÏÈ$°.TP§8%,KO˜&8ôăæxỌ¢QǯänFÀÏ- û ÏZt-jđƯ°äî̃¼.­̉+®?ä°ôđËàÀƯI%cÑu2'{ƒ_ªˆăάÔL++ÚđS₫ĐÄ3 ¦ ¿°‹Qe|¬LT¦²8pA ²>êÏÊÈ&- ñ'ÎqC¦q#ï"fúïªƯŒ$ü#€tđn₫.$чü8‘ơï(&Ê]̉ñºPzâÓ “ â'!IØË+?ï+Ü1Œ¸DTÖâ,2£{æk¨L-2} ¯f£)i¦¤³–ĐÖ ,yB,•'7LL#eRjEs¸Đ5nû ³ -ñí₫X 1̉%gÓ, HíÈ̀E ‡Íú¥è±' Ó9 ïÔ I¥Ü¾ µâI†̀˜B¯Ô‚‘¿® ËJoó˜d<Ïd²Æ 'óÈä;¿8cbizb₫5›‚,ú†¦Å/¾Q4æîeĂ´±.ÁéPS6Èc>ÑQ;‘øḤoT†.;ßÂpó0w̉0·-1]GS(‚S4§ÜÔ3#Ó‹Œ »“©‚̀éR ê$óD ̉Ó"̉J 3ȸ†%5p”6rô'xC\s@á*8*LÙ)} Ü.g₫H̉í’Ä‚‚t@["5C ¹đ™ofvæ±Ø4Ǹ0ô9™“'«iå4 û…–%>uB!d ø´OáóOuÔxGû´"•Ou4G)ÀGƒ‚yê³7ó>+Ḍ³Z/"ăâ[x₫+Ímäđ%ÅÚ-T_sÙn4dª´j*ÍbÎMûun†đÔBÅ4CëQtXîL‚H¬Ñ¬Ê XUXƒ•X‡uX°Cr´Qm‚Qi‚GŸ>£UPu& µZuZ­uY=Æ&€´,åKœL¢/méäo0æ#ù,"$Q¨Î1Ε!¥N£̀èBñÏ6pơXLĹC·HhaF2ñɬ´VgL¡1k_‡åƠ6ñyđb"v¶+N)¶¶*6¹0VbG$̣'–U[¥udơOE[­uZG,'pPơÂCÓ‚Ó蕺èuf«Đ2lv8:mIÛhô‚°Tx6^;-L₫/ọ́yH±́;ˆôFZ1@"µ^Ç´`y­̣jÿ5ĂØLëN[µ?Çk!ål”u'Pve×VeIVZ±•m«u[™â¥6.Àí\Ûèệö¢\ó¶fÖ§\ev,ö ö.—G:ƯĐÿdN1Xơט Bö̉"¡tj«Vs£³C¶N¦QtR‡Ơ₫}ơ}ă~ç÷â-,ubA¦à¦Q=wÿ|—üXyg–hÑÏU·…TGe"Åêw±Óß¼Ñ@?±uË"»h ơëÎM—/O:¯|©v„IËßd–À”li”@É–\˜bX”€“lé†?É…mX‡k†{ø†s˜„x‡8ˆX†iøˆq¸“>‰ˆGI‰;IˆŸØˆ]XªÔ'̣·{ôC¼́k -É,蜣Sô¦‰4=¬ÑÍÊI0*Ô§×/ª·ÄöG ' $g¿è‚ˆp|)r²„7Îị̂RØCøÍ,biKcu’9’•+Axđ₫×( ù’7ù'`Áx#7Ñ̀ô"?•­cÅÇ.lDAÏÀDù©|}³ƒŸ¯­Â ˜8*³(åât”ñŒÎŸ@™|3—]¦â58É”¢ŸDĐSßmeR0tC7:₫gM¯{a,đ›đ‚­­iÔÎ̃è´_f¹c@†…c¢™O~Áªé÷X; Ẫ¹XÛ2ak9Gí¯ưR¾̉Ô„dÄ_äÑsØ…-¸n‚‹YL¢àVÙfcp0{"Üûd“jñå,Éû1$Û `úÇUuO·Du£M·‚ö‚EÉH¹‘%y’_ú>-6c'y‘+– ́Ÿ%*××›-ZÂ₫hdúPt?)¹éΘ“zbx؈X”“ …£ª§Úª¥««:«¯Z«»•ús_&&eLÆGض†÷ º7RĐÅ–­Âă8ˆgæ”B†˜…¹¯·Z¯»:¯ùz¯û°ÿú…AÉ®‡Ø‘à™[±›±mÔ#ä(r‰“s­ÿpÏún.ă­ÀÊ‚³ *Ṛ¨Y©Í&”9d‹\°³;X5Ncä^Jª3lü’zÆăh&đÊkS‡l!;–E™WI†›z†Ø©‹›°›©‡Û¸ »ˆ›»©—û…›;Û‡¡»‘û¸Ÿ[»Q) ó¹jp;_øH|‡,†³u;₫¬Q¤kV¡w’uMÛuĐYpöu÷T„U³î„TBB±y5*èÚp등Û_À÷ZrNfØI…îÔL¹L¾]ör_®¶‹zeêí#+ü¤ è #O ;|#̀ÙÁu HK³¢) °²jç‚k½Ñºù¦­½‘ú½Ç°-$ûÁÙF½ä/z"°¨|uî=!‰‡̃'7Ă#è )¦<œ%(m",(Uơ³̀yd>FMÙ¥/–‘iú[›Ë'vcI·H)Åc/X¥±(~́»Q^Ûoô¢×èi8/©P€9ˈًkѨ\Cè›Gèf́¦dQöeƒü8zDøäÉ[:;|H?Á ½ƒ… aöjÂ₫;.E“цϷ Ú„ïÓWw‘z|û̀Çq=ˆƯ>Í\ơ¸g nå…?&Å=†‘Tn´£ Çç¬yrµ_Ä1êÆd°¬»×ŸR"á/µ\& ƒÊ†‚ƒŸe]/í ™¬[¬+5±Ö-ù̀7f2¥¿5á¦_Ö>És½ÔÑÜPÜăqoˇryK|²tf-Wmÿ²ÓéúÖ5‚Ôï)đ´Ël öŒÑÁª³LBDL:ƒÖ.í˜́³̀dÖ½B Ó/jEjÈAóS dr/2Ưmµï¥‡Í0[rkœO󳹄æ–gOE6Z¨¬íÖÓ!œơ\…₫G1{e -M1̣˜/êxÙQ3Z#̉Ă…Î ¶7¹ ‹„NĐ“¹xÇÍâdX”WF‹4+5ÚÑ’LV>ÏèM¯<¿b‚=¨‰3Rxrø-µ”Ö«O¼ÉXQÖ4æḶ‡,Ù2,¹´°ÏÁs¢&{ô² ÆN"6•́‹̣U|¢̉g3чy ƒ´jùg₫]6@ö&l÷vư4Q%úƯx e$ÑíĂ<©¤;eÔv-é«5ḳ+̃48ʘ–đÉåCÔ‚qRà>nê6!(èKsû₫_Ê÷ƒZÆô@œºjÆËؾÛußj4ÑÈ„¦—ƒq÷Á₫LXñüÛTóO÷½£sC”‚ês¢dçà[1·'it*¿V…̉´S€À  PđB 2Ä€đ„ƒ ' 4 !Áƒ #B4Hđ¡B/BD˜Ñá…† &t©@ƒ̀™4kÚ¼‰3§Î<{úÄÉÀeB‰*TXH0dR—!_J`xA—§z$8áiÓ–B…NP ’êË­-›"Û̉£P²\™vm+²`̀ŸtsR¨‹7¯^ Ä†Ô ö£Ô®=>M¹p*D‰5Nµˆái\µhU½L6ó[¶œ»vö¼ùm˹{Kë¤`gj «[ËtÍZCßµnË‚¾\ëmÚ’i·́Í₫ơso¥[Éo[4ÜXCmGƒ+Eæ£Ûư%̀¹µ”[Đim_-tÉÙö¤_²Èe—9ÙUA5¡z†¥!yaIˆ’n!%æ›F'D’¥œ mdÛYÈI6Ơ‰p Êß–]ºèe¢<-˜[SO‚ơq₫b:e•¡)Ñ6‰V È…¶Ûˆ –8è¨J2e¨¢ØD“@­®›Í1¥©V¾%AÇ-Y«^%wAP~ø£¦Íú«PÇ¡ơ\”“úv+¤2”ªªÖ¨Ư’U¥ỞDT̉EíAHY}ˆÅ 'juÔƯºƠi–o:v'h½¡Øe zm¿51ể“¹FÉ]`÷₫·^Y’́nc)FÖU¡–:1¡Ÿ•x±ˆ!­èoOüæñ¿»•;à%ugÀ)†É¯Åæ–,­L2\d\K1üƒ 9°³WVÛqĐu9ÖVaÊ.·ï̃·_œG˹.b+åÉ•aíñ¹ôqIuå₫Z$c\1h!]¾2},´¢ă6±‰¢u]Ûa¿=÷©`·ñÊ^ÀqÚt¡–¬t1²z‘ÉTÏ¿ùvU8.¥¸Kƒ¹…£Ă½ ¼82÷ÖtÜl™úyÜÓG¶ß¦×tá¶%t)Fx á÷-b&•ôæœQ³g!Iâº$ UΕa6©ÍÊϲ<¦2g῭s&ìK)ƒ‘DÆÉ]a₫Xb@TÄúhNkj<×Ôæ¿·¨%0J́4ß Å<ÊeåËÖơb¹:U¥}ÄêÑ,9åÄäц^ ñÜ8­K¢¤ç¢–É̀f&s™Œ¨<)>dú¥†=^´sÁ†p®#¹›Ï$›¦® ¯ˆQ£P#‹$D…v®¢}&fÚÑèÍ’I2ÓLáfe¬ ´I.%×?'̣1cLíOBPMÓ¬(ª9}hpô8QxVt«}g̃2:QiN“ª?1¤É”’ÉíNwTi$׌°„àô‹†@¸M®f5£ºN«-¹]Œ-í»ÜAÆÀ–©L:½T¥ä–«Ṣuêá(₫v, زB”¦Å(V)JE~µ«z»€6²ÎÄF?- ×â„'J&‘™2Ï„©ÈJ^„ve:jIµêLÏn毙µpÜä2¹̀m€r“ë\ä· ˆ.s§ Ứ* ¹Ü½.r£»Ưï~÷¹Î ¯tÁ̃çv÷ºÏ]®r½»Ưă^·̃¯{̃ûÊWô5/që¢ÚẩĬ¾́¥ Œà+X$)3e‚¼àCXy’ùoqUgÑ8q\„Nå˜]¹k%Üi­§ÁÇÍn^%íhQ%àûÍE˜•± ¨]±­;N¨ÜJÔÍà3I¡£́ă½UñÆƒă§²₫èJúO±¬ddÜ¢h±ÎSY¢Œ̣\Ú®Éd¾Ö\\æê YÀØÅoz»ûféÊ9Ît†³ç|ç:ăyÏđƠ³Ÿó è=ÿYЦstƒ™æ/±îª<ÊÉ|•¥“́>_̃;ÇøŸf‘€6í,4ưèP'hEơNÈ·fS˸ƪnµlFæ>K3)3t6vJ%6…ƒ%ă©tlY¸gzº™¥vµ©cRlcXÙ¨ku²ÇJMe³¶*̃)‹•²³Z3„f˜ăÜÔÄâ%́NZVơ÷b@Ö”Z̀nwOb±T»{µóv5¼å X|—À"Ó‡é·KvI{ï1w$¯₫„4éHl ^¬º/ú́zǘ4—x»ơ=JP€Ơ6æÆsJ41ñđ1Û–Û•¹nƯŒ¤ôÓ$ƒ–å´¥ø©ƒj-eë™[°}ăøÎ ©́ÙÆzU ́hïP‰"ºmÉ%JÜ%…ĐH¶M’Úe}‰«ßĂƒ;CPÿ|̃äÓùØÏ>Çó% ˜fG»éB뒯i„æ¾4©¤ üeÚ*Î!©e=®9gÁ±»=Ñ×ÀÚ—èÅÛ¤í’ï×](^yó[àO<©nÓÉMà¡ kU½c\ÚÛ­̀nÊè­ë÷Jº̀3̣«5º±)/{aÊdª3Á}îE₫´f)q]₫iÚđơDüưŒ åÅS>[·öRcM–\1ügm̃Gßÿ̃oñöhßl/j̉€û‰*öÉÏ"Y½méYwéǘs–¬÷}>·EÏÓ̀£ü̃yêkf¼˜ÿŸU‡~2–:hs~¦6~h G—€ Ø%Á‡T>-Ú&¶„K$kU“xTGOD%f1F̀V›µP¸jÍf(ˆ‚-˜†r€.Xê·¶d)®„Mƒ2%(Ï‘iưwI ÅEXÆ)ûKâ„sæG1(ƒ,"~5Á{È‚M˜ßW{ThC„ÎĂz¡£c !,8(}UV;#|s–Pa{¯7 ₫Lˆ…¥ñ1m¦^è‡qt†âsxhf"B2J±,_¸S4&HâBx3Eöh`‰£s‡|H‰ÅT‰Ă/Ư…—øv…crçh>R9«„|wU®Ä3̉r2· eˆ¸–ˆX*j!b7·nÈ1‰œ¨Sx{ºˆ‰²¡_Ü•‹¾¸{åVm)çQ'í‚$¹“2°h[¦W&yS.Twj5‚zƠ†0ŒÄˆƯH€̃ø‹âøvX¦>=”HTFWÛ̉Œ̀ˆ'6Cˆ›zÜ2iT¡I-f‹_äØçi¼(9aHD¤MQ“[î8.èaáb;Vá5µS¼#s€3₫‘ßCzÂv}zÓ© MHäx>Ô1’ ©Aˆ‘T“I+Ewg5ƯTđ¢í.¢W̃‚0r÷§Ø§$‰’v1€{X”æ…'™”)yKÁ:Ù/V![&ƠVhRzøØÆ'’Xî(\™LØ”gY…‘‡–»’kÉP‚Fé|Y#‘&W• ÷[VÁ'ظ‘>irß“'”‰G”n …Y‰L¹–ÓöA\(ø÷|yỊ.”Æt°e™¾³a plH–Ñ„˜IÉ{j¦I’†9jÿFAÊb0ö8 æ8³ÔZµ)–‘ó°y›Ä—ÊQPIH–£₫Y4¦Å‰™Ehl¯yrØDI4p¨DmyF"¡I8ÂFcT‘(EfYœ%$’ßiQ(Ơ¡:_Vr·*7"ơœG&%¦a“– âƒC8›·ØYÂY”ÇicäéŸÄÈŸ•˜œƯ‚eÔSC¸/)HÔup¶1A6D›À‰s̃Yß9 |Ø¡|8m%‘ŒÁaºvKVKªèáö#’у·T%÷h¢›ñ5á… ‰s*cH¹¡?Z~Rmú Gµ)T:\·M͹N9BWăCÜ©U:ê>ºx< ¤[ê”o1&=4d¿‰,ñ™ Cn_zk‘@₫Î̉FOJ¥2¤¡\-j)…t `xú‚¹qGq‘·SpÔÖ3ÙrúW™•´ki;f"€c|Ưäk"לê‘zê„–ê©#4¦©¥§S ’sŒKd7ɘ™̉wQY'C5¹R'8¹'¹#ŸKt#–£úi¥₫Ø©™•«²«×ry§3’¿64ÈŒœW–d$pæ™ñç¢:NêÂø# wU§ƒƠ«˜êjhoø•đe®í…®çª®éÊ®ëê®èÚ®ñú®ó:¯̣j¯̀Ơnb½µ;{iDöh•̉ØVR0,…wđâ:Ö餘D1êÆnà Äê₫PB±^ÂG8aƱ;a•æ±ëmê²èIâªjƺØIäAI”9?ÉZ2 ™“‰)$¨V™'~â°^W,”̣̀­¾È€qx±oI(èF'dd‚Ơ´b¡OJë´%YS´´·̉¶?uWœö›Æ¢sn”Ö…MZŸ½D/NF/”zxÜ(±Ør´ùfo«$²%[·w{ƒ${·–DvëKwrZs+**&/ “†¼61­…KAˆÑ5dOh ~iQn8"Cë‹Xzvq«*  KI†"AŸ¢ó´I¶&º£ë…`s ›PÜ¡œ‹±?éZøE³†FèCƠ₫#$sH¸ªPˆ¨„X…¹â(»sD‚;©,ÆirV”%?¬÷iÓëï'½ƯÉël~Èh¨¸S<¥O†ƒÛ&)'¹Ñ+3̀¢±4˜é–Éû¶iF¿ÆÅ¾L 0—™&ÓÀK¶DärXùNw2ùœ_³̣£È­";qÁ‹ è‚ˆŒ²™83ª+c:ªü!e‘Ơ¿l¦8‚7×¶̉q¿x¸¼ô´Â¦aGĂFLă|ơé<1Z2₫TTÓ‰WçœX"¡Q‘‚Xèë(ùA¥W"ÁlÖ¾ ±>æ8|o§ÿ+zH4ʪFU‚mÿįX–µrï€`7§ơû₫2ØÂNÈh_72 ç~$­̣Æ“DmÑàaR9Ë•rdI©Ÿ¡²Äû6Dç8äÆS !³jP–aAù[x%KX3:ÈDÏ‹£)ü ƪèzá²r¼³|œº¬°}LÊSƒaXq¨D,.¥ŒÄû¸=ƒ̀«O†H뤬vü;s5™ṭ²°*•œ9̀“i™ŸYÈ¿•kd¼„fl\áy{kl‚RÀ¯¬Í¯³¨˜³¬DñÊru€c¶´À³ tü˜2l*›¬*I„Ù§åÄ|TÙöLzäŒu9°’p‰Ê;ÈÚÊÆ(üCđœ˜GénŸŒË§Ä₫Ê9ĵ\5A;y&g"Ä}Ḉñ0Éú³ÜÇ>|Đà£Ë€¥¯í™‰R‘T•Wiǰ…N™̣ª¨Ç‘KbĐ¥:Ăƒ)˜7%ÍEÙ¼ß[¦¸ŒXÖª.½³ÜβÇ{<ÑVguàáĂfá îw«̣t̉G—Û*•JĂMz©•MJ$+‘a3‚ơƒiÓ‡ºAK‚B¡ĐẢ ¿asnAa»²OùrǾ5Q 3y %éăTµêÓ_µƠ9…tû$I–¨¿s&$æÔ‡êxÜtR—ÇßBΫ¿¹SµA+¿1×TXÔ<{9v~{`¬íÚÆC;Få`{KÛÖ3‹MG₫'ÏîùA#›KT·F«ºKÂóµUQkµMÛཹ§\Ôµ_ßU]₫¥^rV_ï¯ÍƯÛ­_Ư=g̀µ\ à_̉%̃ÖƯÈU®üƠ^×m®à}̃Ü}Ưé…Ûh'+a꺥;º¤«ßª©ù½ßºH$¥ t«åß;àV{àjz;¬Å<ø—EX¤à=–s hOJu¾DÖki¤k¬†r1ЉF^굨 â9=O\’Z)ËkÊưÚ3̃Ú]$ă7î±4ÔɾªÚ8îăÛ26èKÍiiéóăKà%4X§’´L«S{0(/9(„đâWkŸ‘µ£Ö€‚k$¿ă{Ë·₫´­ö`ÛÚ ±Êö©ào~dúËc‘Æá·áhè&P^ç©»7›{ö¤Á~q¶Q»ät·X)ücc¨ßôébëñx—Ún ßm]—]ö…énÆéü¥é–êÚÍéàƠ_›nêt(h£ê¤₫é^ê«₫ܰ.^ê­êÏ¥j·Û4®ëf.k3ä¾ë$́yä»åÛwMBUP‡æÀíÚqÁˆ)~X…¶³½±3Ô—ånöDí½ ²̀¾í̉®X¼ÍÛ¡ æ̃₫Ă`îéK¤Ưnó•]öơî´ï¤N^ñïô~ïíµép†ïö>hë-ïư~®ù…®ïăuZ;^;ơ₫äÊ‚D^笉ßY¾_9.äàMµù:I>=:ç ~ß UánNå|̣₫]̣>஦đ×”/…ªư)¨ñ>âlÍk8NǽŒ…M±|!o­̀ ¹í@v#óm”̉lù{ô½@‹½JfÍaÙT=½!âñ.o(ËĂä"q+ó§“±Á!Ëtlă‰œ`•‰ă—ÑΑ–KN7í"ă£Á‡©¶2*¼$æØùÉèDÂ"|ñ5ÈŃ›Dø>ĂâëûziZæd Ö÷¢#V̉LccO`B<ÁÓÊäÂw>ŒƠ ªÅÜÇWMúµœRB[³Ăó›ÉÍ­ÏÎ/«́¾·ơïÖß<₫¯öñƒX LîM"eêÛ·¾,/‡Tµ¨¢¡i¢ôtÍü½Ç@ߌÊMÊLÍĂ _Ë®¼¬×ß“äùălÊåá:¯œIh?:Ä•â{^l =kP_ˆ]­tTă{UÄ+üÑnˆµ8qĂ@ Ä0CA 6th°àÁˆhÀ˜QăF=~RäH’%MD™RåJ–-]¾„ÙRÁA0xƒN:w̃Äy(ĐŸ}.ô©3)Î¥?‡u(@O¦8‹̣¼Iu¢T¢< 6½:5'ш5 ^ŒÉmF iƯ¦U01¢‚RŒđ„½14₫Ü*‘lA¡=iR \±đa¤Ö‹”hÁ§Nu*¼»ÓhăCWqí[̉¥MŸÙơjÖ­]‹d€Đ¡B©T%¥ –²ƠÛB‹JưikUGo‡½́QàÊy}ªWË~óZ|­Auö́3+ ØÀ®l¼²!'^H;'ă Ï·nUH¯D³ 5/”9¯Øû¾/dHî¹Æîʬ=ü+Ë ˆ#¨î„0ÂÑ"¤°B ?̣Î<é& Nº¯x›À3¨vă¯²¦–Êm©£D¬®Ăè’KHD®T,Ÿ’1Â&¼°G–0K( .₫¬ûë©ÏÈ q½Æ2Jê6Ëk1É₫zÈ3«úÚ‰K:’.̣˜új³ÅöK<$ecÀG7ß4©­6·ƒ³N;Ư-"ơfË ¢ÀZ2 ›M =aü«ÊƒMT/Úề1 É“+¿Aư:ﺱús O£óN—fªÉ€½0²<ÂJtr/Ă Ê0è̉³ªÖ2¯ămƠY9ăQ³æ«hËû®ÄÊI«0ÛU®\ep!E…ÖÎO£¥¶Z u4ëWJ1ͱf •‹ÑÀøbÉn  ƯH³µOMṭó·¹̀›&Cµv¥<" §!›ụ>+Ûu½½x3Đ²^LP31Ÿ̀ŒD Z·‡ïz5>-®u"ˆ””Áz₫ó%ù5|KFÙÎ<ßE XN£¯assW¿âÛ ¢u÷$÷!™bhsÿk4Í—ñz·¾O{V»”S"U²Ê’Ă9*Mx`‡gíéăÆÄÔ&x aè.XĐ¾ ñ{x'À„}¸³¾ ôzk³‚â«DÊêkđi¿K;ùoÁ/T-êDÑó¶¼ÄkFZq5v<´Æïàü.ÿṿÚ4mäÁ=ÊPa R(oÊ6±³ Ç̉ ́%j[́ÅâfƯ›¥ö)ß Hc̀cQ3ƠeƯ=?Ï?G¤À“g¾µØH§ñ5Ï]üñt«—^̣J5×r̀!ï̃ggiùæ5z₫÷›Ọ̈₫ăµtQLu9¿ù‹Tq—ÜA¥²]dÔó?EeO€²çη@¨†sæc`e¢P‚l@pA 6 ‚Ô -È r!4!C(Â~P…&Dá GXB*`…t¡g8²0…5¼¡øĂ JđA‘¦²ªà!î|ƒL̀X@̀p[ëŒÂU3¾…¬wơ¹Ÿÿ²w¦ÑŒ!ßƠ8Ă9¦r‘ƒcå8G:ÖÑw¤#!ø’=&/tC@û eÀ†E>øáRÿä>Ÿ1LG¬RƠ¶G¨´­-SÀ²b‚¤q‚Sà'Ey’ĐqézÓË₫*U9ÆT²r•§te,ay–Ó„R đ“–¦4ÉùiJr:¸C˜ư•«—‰ ׸&µHÊiˆ6U»"hUÆQ2¯ƠÄfFâÂKNª{k²^ø°÷Kê}“œæ§÷ ²'O¦dNŸd¸"A¦ gÅ̀Ëå›&YgG«ˆ™‰(i˜}úͶ—Ef>Î,is•Í ̉ÎlVÔ¢ƒóC³®v”]ơhHA:R‘–”¤'5iJ€kºs” (ZDRƠÍ*¥M,Đ“bÚó«d6®'hS“{,,ÍwVSƯÀt6)5±"uŒ-/ú·–Nơ–ÍŒßèÍ8n_å*₫½:ΰ*n/R%MUưÖ– fáO£‡Đ…€B›\¿$0J³‹kóZM ¨ǘµx RË„“A=g¯í[ê¼R¼PÔªuràe­º· ŒƠTG‘Kå !—º^₫).ñƯ5=}Ư¤1êÔ>”1¬Í_ׂ%…XV³Y@ ÀHEŒ’|r±¢îuC W"º»²L….@9‡²;5(‰Mx_!™~%Yñc4Eˆ\1€ÖßZKNjmoó‚;[Ï Ë¨w%^‚ iSæ¤×/˜,zlJƠeMÚªhŸöåd+́… ¾à[2\¤ 9ÀL₫a¦«̣ÚJkLí̉®<\<*¡é»nW™»ç¶˜º “Ơy9sLJRR/µ|›cä…Î(ø¬‚̀ÆÛF‰–zC~­/ưé-` R …µA¥«WVª¼‘̀]¢À §́yyëNP>VÅÄ7²jE0³Kļ ±Lâ3ƠP£hɆ¤” Zæ1fÍŒ¦¾2¥™Äk+Û è»“]‘W°»)UÍ[î‘’´%®´hE)[q4E›,ŸfÇ ®–Ny:¤̀k["Đc† ăÇ-‹©Ç‚.o8ŸXs-`ă–Ơ„¨¶íUưÉêz½lfWÈÇ6 2ïX₫]¬ƯuLxÔ₫âµ!¶m°åúl1~£ 6̃ˆÁºƠ.JÖ“nûœSäkŒÚŒx‚\ŸơZÍgÎ)î|=î¿øG6#†5Èú'±é±pÆÏ%­» Èøn­* ›Ư#:uyâÖ .£î‚,Z ÛĂ uÁ¼dæ`WÛF™µ™«í¨“ÏÆl+ç•^²JĐ̀H<-ǸQ€HoÉs[5Ú̀₫Ùsظ‘¨4”jă…-NA3Û½0Ÿê_EơL4§–ͱ₫7w³Ă¨ÛT’v+·˜‹äYó5ñB½r5oÅVm[*¸¿ D_Guiwœ®Ú °Ïí,R¤ơó}¹rªÅçĐˉ₫½MrFk£‰U ÛÁ+{ë¢Êûå£\ ¡+DX:ñ‡d”âG̉o3‡TÏ^ă$o¨·I¤iä!u£MÓg¢T®2Y9Ål(́3«yf‹x™)82ÚB ß R¿Ă¨·¯´Ư礦+†©gP”¤7nëX­k>­l¿¸¬œ{¿Gyr­üø`%ç¶µsÁß_ç§}i†V₫äQ-å;ç̉Ϊ¶1Ê‹ƯĂQ Ö Uc÷s>>Yºôr3ø¨Émq".̉EJ²ëp¿%c$4¿ïû@?¼ë›ƒ¦îQ>Øñºă&뀤s²" ‚¢`Z[kƒ¹:Óx75Z€₫2zZ>Ó?ª¹""´@ô"ĐĐ' l(#ƒ&7{Á§Z&êsŒT“î Á#¿- ?Ơ(¿,„ô;mñ%-+¡a ¬œ ´ïÁ'äÀ-*CæS¨ú“” đÀ˜/Ô1ÙP »Éâ Ê?óX–‘ă¸'; G ªÉÙ8ÛºCƯi1… ˜¹Û)Æ; ,Ă·>ÜD )41«›«Ă@)œˆ7,Ÿ$HAj#ŲDB (XŒŒ< O•/s€«Ñá*B:$aË̉©'™±Âˆ̉$w¡®̃Ñ“%+3¾;G;·²ë3ÆĐÅOÜEñ³ rn$1t•›ø,₫ê‹r!4|ŒT4¦5ñ“ư‰º7\º˜á™é™ÂĂ˜đb¥wŒ BÙF‹'ƒăÊ0»¼q Ă5ˆëÑ!³‹éB4¥i PŸöQµs¹t{ÈYA2+á@p²S?1¥P°R;} r\§4Ù›ưÔÉ^ëµxaP× 1A-•6u{»C]T 5ÓuFL¤ROáF$ %ú;~kS?u#ơËF>‹&Ÿ+¾Sd–L1uT²Ạ¼;”ƠS “µ€ƠX]–LHå«§Èà¹Ḯà1–»»¯… ±àÍ[©F#G¡FF™…ÈSç4£?Ú9‹¾.rÅt<4 Süq< ¤y₫²Âp:ºU-B8ºa"ƠZµƠ+Åú?,}×=m>*¤¬ó°1u%Bbª"J<8Å)rEḍ3›;NpZ0́ĐÁQª°£â`UTlŸ̉V1(†ÑØơ+B%«©›¼™…ơ•Á‹¨Ḅ‹iƠQ´ w­W̉à<ü¯§sBDYóø?Ci¨²X<»3×wdBá8U·Ô*z©¥p¼%y ¬’JyBT(n}¾́ñTWM6>ÛŸ6LU›¼XTeØ7ÖÍyÙ•8™‹x§²=¿ÄÙ¦°•±\&6ƠY#6gÛ- ÈûG=éÙtºº¦~̃‚ƯVèK—Ü@é%Á¹̀–çëX)´ĂÆăËÿAgéÉjj 1äZhuçë/ C¹Ô(_‹̃tƒ¨ë‹K)¼£­ä¿í¤x6K yl˜°kg‹½¬§ă¨X́So…ÆÙrU†ñÖ¸®lö-Ăœ×E«ÔÉÂtYí’A¢qZX£E4±€P¦MÁ~›I¬iƠê)‡zÁˆîư~íƒXîXMnT+_DÂ$qÚ%ăǺUˆ É6E-YÓ?ü3çUUdÔY¢ăØ— <ơÙ™cÄSúo•V'J…Û,aÑJ+ĐƠaµ(Îͧ́ỀÅ₫=₫^oq q[­ÇFïđÖÅ?á®7˜Œ½ºṔ½R̀ 5W“{C’₫ûØ»[hs:ïîƯô[oâÆDMæOC”æ~³d$mÈÆø<‹Æb1ËÔï-'ñ6¼ñXU€:G _`¬‹ ‡[RK̃WlPnÏå)*QN\ªX1¥+ÆăL$ߣ>\¤”8·׿̣7O¦hæÉÈ͵&Å3«gôŒÓ™Ô/q5¡t;…狳óƠÀká2Èăê•`¾û…¯rt°×IVĂ@–ÜơÁ€QSVá̀·b519WZu ÑrL¿ôG¶êÜ[¹LÎIl₫=ă ̀¨2ÙZƯv„xvă>n«%-?ʤ4Ô­ÔônµƯqQs;^ä$9¶sJƒ¹Đœw÷N½c[»8{¸y9ÙZиrQimơÆt£E I›DºƒâI‹̀_­v̀’¬Pö îïÂn–s¯×W‡Í_®Ö‰`Lp̀„Ræ%>ª#UÔJL3! b„‘˜³M‹_OÔ+¹G«¼`GÎÁélvØfïăôé|â¥@qºÛ—&ÚƯ%UGơ°ù—€ÓÈú†X e}%b€v›±3QÔ"“Æâ¶qù‡käE¹^w®·x÷<Ѹ™ó́® ¸lO6+V£†¯zøiƯù¿₫ôc¦0’Ư“×µú‹Ûn±¤ûöÇg^₫«7I:ÙÁnÔˆ­7ù×ÏÿÑ—Ug«ĐËí¯>}ÊÆ½\·¯ ºŸÄàTqÉXQ†Ư‹\³K`&ÇvÊ<½¯K…¿çTWŒÅ]_₫!̃ñö&²&k©³­nV‰²î˦[£¯̀_ÉÂéüĐLj­ο‰Đ̣ψ̣ ïÿ~đGÏÏz̉’w -ư½°>ÁÅe ‡–GBnu@€À Ă‚ œ aA ,(Q Ă‡!J˜ˆ°bD‹ f¼xQ†’&O¢L©r%Ë–._ÂLÉ` H‹ N@h°£Â8₫/J́¹S'†œ; J“ăΦ’&¼àóçG Lk:í¨µ©Íƒ$c‚ +v,Ù²fÏ¢-É€BIܶûVnI pOÂÍK÷®Ü»zặM{–­à†Y*8`1t^`̀øæP…WE2¤IÙcÖ5Ơ8Paç̀Q1Å™¨VÓV•²fpx6í“„MÎT úµî¢E.~H:2€¡Á¥’æ 18E P•û\x!ƒÁ¬yJ§Y¡QÖ̃i~­-~<ụ̀co›të·oúơíÿ₫Ûvñ^Æé囇‰>?ÿ•‰JAqUYGw[udh=eSw;9ÔĐnUÄÑUOÅ`Vßm¨₫”MX”T» %Pxư¡Vn]yÖœd6˜s¡ap€ÅƠô"E3´Øj\·“dé†! ÆH#$z•¢“OB‰–źáG¥|đíE¥{÷öä‰Q:É€uCNÆa‰?”Tr ®Y„)Ø\‰$₫ølÏ…4§k4¾‰àˆ U² å~+‰•Á—ZWA†ˆs¼ù8PEÇUj£ˆCiÈà¤&¸iG<*—&œjÇä—…²Ú*ûƯwå||Ñ÷V­ñÑçW­¶Îê*nÀê«x ÄY਑„XA”ÔŸ,*·æoz2ä(e8­–Ü€†(碿={†˜-”“©®₫*l+2«dD27Ạ¾;¯¼ÄM/¦8Ö‹ï¶̣̉ûnqC¾ë¨dc2ú"c’\/©Đz—®ºSL¡ú±¬I¿«Æ×vqÅâ5ÀÛE Ël9]Aü¾ü©„#̉Ûk&ÏYêByÅoDƠv¶í™rU`P¢aÈ•È#Óv(‹†´o ÷[éBúV=°ÖïJ„µTïK“Ơ3„5Ă%,•ÂÙ(h©:Ì´Üs›7ZwL7°z§ÅV  Pă±Å¡º£Euº²\J™¶Vù,çGDÿIaª8¿\êeâøĐU}’ÖçA®ơi§Ư|§ÅîÛKƯXf‹n]¯ÀT₫¿ëP“åË63̃Nơ¥ÛÂ~ÓÄMÄ\đX£ @ ô¬F?½ơtçV€Ê]g¯¾Éâ;»â]‹Ÿ́c)~ç xoû~$t÷ ¬ï­ ùuÀƠÁèrYÚơ΃D=[ơû´FœfkÛ]ü’AH¥-yÉÓIÛrw²ØY R°ƒà¤̣¡›­ÎD\! [(¹đ$bZHr€ïƒ Đ¢2·œÎqmWK·Ûůs+kXª’%¶!F¦Gó’b|ø­×øđ_›gR½¶Du×ñK$/ØQ0!:̉ñ²Æ…‘fós₫ñp'´˜‰D*5x#Í@%Q ù" iH́í­.‡TÉL¸ ÀgáăÁÜHIHrwC<Ÿ&…¨8űđ«H0£ÅOv²+ó×¿àˆ£+%Z9C™§ơæQåO#@§¥yv:Ûö3ç¡it̉—AZæ"úFD!¤-«‰1k̉†`̀̃́4å¡Sn&‰J\å*CEOªm;çÙæ<'²sB<ç95IÆÍS‹™¡8=£M[Ñy—›ˆ´:FSe‡7âÖ¦đ(H.ÂÉ7[lJºƠ5'&é—Đù'6;Z7Φ–M̀E_$•ëü.5ă]₫ ơÉÆü=å_ÔTĂDóÉå”)yí+Ÿ:s"™’ó¦̣<çù(Rl⢺¼V̉$²9̃¸ 4q`i$Q_ÚÔd ̀ÉGº#‘`‚FÔAa»¼̉³ª†h5‹Z[ÈÍE.:ä̉ªçZ„œkƯD'̓w₫TQ U®¢K‚–fÛ•åi#GĐçÁ&!t’RѤqÆ\1W;3K¥2… 6uCŸÖص.̣´¨]­ #"™´/}2“è\1ZêơfÎ́âd 'ª́`vªËbÙfúd4É6´ª;9ª5“*M‘;– )wéY;aQg{̣ ¶3-(é29Ѭ₫¦*Ö¢7½…ik ÙÂm1¶ßåNŒ¨™Jîpsº Ë>ƒ¦ËZBÊáY#ºáZN+<Ă®FÂÜjª P€PaHøÂư…ĐáTØÂ ö0…IÜa _øÂ±†5̀âĂÄ)îpNâßøÄ ñˆ_¬cĂXĂ=Îqw\ásøÈ.^̣Ơ‹Vö:1«UÀLÉôË:M(5Û-A­ËÁÊ5gVA¡i%qƠqSM•µRXƠ‚‘Ê£óˆpÏ4gå†ÙOœa0™'ë2ra7̀ĂlÍf=È(?Ñdóơà InëÖ@ÇÅ̀íµ®Óú3è₫;OîîÖ40Ë–ñªÔ¥>­½îw[­²–¨´¥̃tS8û#¤èŒÖómuøÂ—ëƒb€Ñ–°×(·đ?zYÊơÊ;r´ÍiV_-~+PëPJW¡–†4{%+°Í^÷fËÓư]jª¶Ü"»^Y hê3»ëíæS¿›EŶ̃€l~o¬£„×́®Üñ'sÚ#=GÍ&NöẽÁ¯d£ZßMN\ơ¥çPz-®X›—D©n®ZriÑP! ·¼t³R>"kY<¢.G9Ígnóăüû¸Üdóo \'đ̃ ‘5i¹ïj½[™C|ªÓùQO'§&µæ₫£@bôéƯ¡WÛɰd¡1jø+«F/0̣CîGÙ¢ơSyƯ.¦fÜm–¶}I4WCï*sµ¯yl ~Ø?·¢ à° J$*¼N¶ÉÆ¡’ˆÉ$ă5Å̀±&¶P4"€|ÈùÈ?$‰··™v.½Û˪ ¬@\C₫Ăîvˆœ÷,qǘơ æûÔQÍưîcÀµ¦ï·ĐÑ&€;î¦l̀×8ó¹I|‚ïéITˆK•Ⱦj…˵@L''ѹ|€m²—eOƠÙUÍMŰ¾29w­^¹¢#u¦)ú4'̉e¡é,̀¯ÿæúÏ?ÿ%2üà`ÅüßܼU%E…\Î@íˆ ä₫©̉*ñÓæ©‘á ÓæÅ–¤Ø ˜>q‘´p`ă©SÈ”´y×ß9ÙLTûT@úaÄhP•fh Dd@ƒø 8ñW™}dH’˜Käèaa® ¡M ` ÜI¬EùL.Ú”áÔûƠà9KÑOĂyR¾ßøÄ¤Ñe^ÀàÏd8ƯÔ¥ơἈ¡<ù’@8!9Í0€ :TNÉÏú4Q¥@JA•! ¥)HÚÛ`åïÅÛn!I0a{ơ^OnèÈ—"&Tyɉo]Ùø¥íÙ£å—}µÜÉeÜ ₫ÉnEVHKuXA<"ß Ê₫Üaºá<½aðáéDA  ̀´×wfå¡̃{ù#ÖÛyrâîưZ#¢ç{®§{VÅŒ‡eºJɼ%é Ø Ô ÔƯÔSîÖØ©’ư3Uø₫üƠ§QíÉpJÚ DJöÙ<c BhWXËlơ' JÈå)â[xbåCy¤}¢N#iÛ₫±hÿ¹¨rÂ^‹Êè‹ºè ’eY´æjÀßhGà̀&á , gâ\’2Y†S"ưpDqÀ*nÛèq×omÅ9VK~›õ³ èĨàJ^Î[© hƯ…DfhY…<‹u±¯ơ#e’(xzÛCt©̃ PaßA•ÊÍLa‘)d@ÅB±˜! áwiÈZ¼¦9®DºDlO÷|ÏêÏø¸Ö̉-Q¦^açQ]Á¡ù¬XQÉMñˆü(ˆ–‰¿đÙ -9çÚ₫åÍ¥Ù)M3yÈ)·ơUíiW^M¦d–(d±Fb{ƧVÖè́¤Sp–pT)`EôÄ….ë"g+¢`£f X8*ZG ]@Ñ9œÁ¬“¸Fü\ ú'æS(}DvṂ¦qᾦ’Ăơ묯Ưh$Óê) 0%TwR—»Ñ*]Bk†²ëoh'(±näN +Qk̃QfÑpQV¹YVe —ˆ®){>£®¥åBøœ·ªD°Ü†{1j5 <D’3R’”Ѻë%eQ-ÆI¤IyP₫Q= ơ ¼jèAeÆÆºJnl(ë}½*₫ wª̀ ¾ßê+sJÛâß/e±ÎéÅg·̣»|,dë~ÁÑ)¼MVèƯ:hÜ®­›Ä̉́›Ơ>I"mơSưtƠ Éç§mơ%,›"ăF^å­Œ9))ç‰!Ó¥„¢Vbg Zöªa†MvÙráÎt¨×Æ’“–"ú-Ʋ­̃ùaeîÖ„`Å ¼=ëth˜‰hiÇÛơîí†bAÖÍË~kK ƠqP*¥TĐ¾T¤Đºnô%eªbá×íø ̀oIơ÷*¨r¯Ñ6Ÿi.«̀yƠˆÖNáưTªù¸“́ ăN5dÏ*]ÙX™œ¤­E₫ âxv$îF̀îÎ-³«€/øB­Cê᪮M%½ZÆ)S­Pj€…Å,̀v£z.¨dËdâ i¥Ê›(P¶Ü$/9Ê[Ø®½¶°\L&†èæ\ ́ á̉väâë9­’záøö/äJdçĐ+ál‹9)îÜƯ“ï&°ŸWyÊiodE™ª½Híøˆ×DNØèËñVÊ‚Y±ÚäD€cI„alnT˜¿l°5 œ¿Àÿ-œ‚FL« MăƠ¼Íª>ªpÔ‘C̉²g/²₫ S5ÿÂèSËäŸy—B4À¢ZôI8Z¦-J¤á)WsH,‚톙ưií ªh³€íj¥Ư(n[3ơQĐ"zƯ₫ÙáY*~ˆQ˜ït¶°çBuSyR$‡O±œ/ïQ_1е#8ïƯ¡z†´DëïvÅ5KPR×Ov6ßégk©R³²‘¶~bE?™¢\ưÂL,ê*‹  ñ M$ ƒ} Nih´ªt°„3&’ỵ¥yEkÊÚ"•Z/h„v*6&QKw·í>COà‘–Eô₫%$1·TÖơº5«ÑhyËdS¸ö ƯlAÜË€ 7›!ܧ®Fä èg₫µÙ¶ØÉ¬í–¶H V`₫uöóY3ï–vn¦%èÀ5eXÇAeù#çđ$ŒDx¯¬ Đ|_í×â8÷Ươ²®|¸\Vkma–jӸ߭-B˜ø% ÑMêÛ(̀[]ñ09•̉µSVÏH×ƯÏëk;[ÙC¶R({¡jƯ’³ °á¸zaXb̀9i›+ªeŸÆ´–ˆ…w–JÇđºi1c¶#÷D-¢ÅÊ9Ê–y•–âµÔo)¬ÅÊ-›CÆX“uYđà ^Ê(<]Ôi2N†‘ ú0€9Ơmêç‰m qßK%`:q\iidžf©§æ©›zª¦₫‘ưÈb¤Ÿw!/ä^ (.­y¼ SƯưâ’¬*[6›kFËo›ÿ:‰Êơ Ω›*¯z“ ˜{÷‰°_fñƠÈñươU§¦í«’đÖ©eúEYơÂß®^ ®<uaAÉ‹#g…ª9±æˆb1r$©!´\Óè"TƯuÂR¥EaÛ\*[hl‚E ẫ‰“å…Ö?uï¶©01S®²;{V~\ksÀο–>zuë×±g×~–̃™H₫kZ]CåÎ}µ–?©zơ㇙-O†˜7këù½o•́²âĂ+“oµ¾À ©§‰hªè@¤, £Ü.#º”{hƯN¨œjz)(×ÊËĂ\Ă §[º0<«RJ¼„ŒÛJÆ—;nÆç ”PÇýÑÇ ‰öd €¤:h5ólô-1øĂ,! ëŒÆ Ơ›ÉḈ£ïJ‡ÚK¨507Û’+„ -ÁJ‹´‹( MN9ƯäqÈ₫|3¨²üÖCh¥To½É¨$¯  ơ Đ”˜jÎÄ« «ñÊÇj¼*Ç 1ÍTÓM9í4£{̀È$;?ÅêO7¾d|₫¢ ­h¡¨>¼ ÑÙn‹¯+VUñªÁ*u¼YŸºÔ¢Ñ̃lNătÓÁ:·#ɤS£-—dƠI]³Ø`—J5¬aĂÔhu·bW̃£‘NZiL§%H@`T—ŸQ'܈ *(†tZhë­ńC¬a o'˜dºMí sSơÄ‹́©ÈÜr›ÛjT-L₫®ăŒ­ó@eăœ³Yf}LM@ă+S¦.9K”!3Ư÷=)ymY>só¤úÆ 9¯:£—]ôÑIw«»„ è€Qw mÚ^C‰́O—7Ü] ÑØs Äïb« ¹ácêMvâJrv²7»ï¯½Ơê»"页ó 1iª ëæ’x×——»¬¯UÇ3½<{Ư\WÍM·}¡#-ổé¯ß₫ûK:é̃œXơ¹›ŒÇ¼¢¨/B ­Ơ"¬}ÈCcƒQWlC”â$pCÁÛML^—+ "Œ=åcU ç1Uäc…¤”í%΃Q^øˆ>Æø7å{€T#0±o>₫#₫Zü†ö¾ªEE4â“Ö4«™-rByéf;§("¹ëÍ``C¥Ùa€a‘Ù¶Á 'xµƒ"m^å;\UzÔ3%d’ñ¨P{ P˜H%ĂXơj™SĂ$*‡T”Ê`ç<‡Hæà‰tä#1e8à…Gsñù‰åf”.±m$ªƠLFDÁƒ90ye£P@´À.ë'+åKƘC ¾­ !< K’¾ÁÑ:&±OS°ÂÊdEZƒ*ïÆ¡ám&"(Ëûđ˜îkßæ$¥ÈùA’›Ưô¦é^Ơ“»àé>;Û’Æ.æ<¶‡q¡˜g̃³%®JAÔÓ₫|Så3rNjÑxÉ7±4å\J5“"¦06¸Û¢iy"¢L¢ÈọK‹… Öô(6©™m~“¤%5éG䈢Pq’…”˜¾ở¶ó0¿˜Îªh-¿l+J6û–yṾ8*]›JyIĐé Ôz—£Ơ.$KƯ ç’ºUƒÙäNú^T¥¯ˆ ơè¤FzRµ®µ›aÀ/‘²̉‰W—ñS˜£˜­L3*ÛYWø”½:̀a‰ÉÀ;Áiqg8u =‡8[z3e÷ô×l`)œ—D%2_<̃یӽˬ¬æh#™„Q*w‚1T"₫Y!¦•­µµ­À5Uù°y0Ơ™d÷”@N@6TPɳ1É5nˆK[Sxº—̀5N¹6¢íS:¥¡NEDßI%'w(Ød²»[û ­Je$³Ê÷´kVù–Ơ*×½í}ñº„Ơ2FBR¹ø9(Èκåd’o‚³Q(µs'áË~\Æ~eéTÏƠÊDŸBTM‰}Sb¨ö¨¡B†Oü¥‘dÚ™*̣#¹.£|́fCI¢anr %14Œ̀ÿBGßôèëô)ă æm„O®¯lCxHeàÔƒ7ämrèäD%¦̀ ~æí8Pÿt°ÖPxÆ)‡­§Xmˆ…[ °)TOÜô©g6‡IÖÉ Z̀ Xh¹–K̀¥ûîÇă| ¶Où4Kú®­ÿ¢¬˜^°64èl¬j(#F„« m¯çˆvpé"PÈj₫5F[~&Lˆåô ë¦„È̀„Àú₫I5P»<¨…Đ©±̉M1°‰Rƒ®¸¨Ø†‡ ± ”.ࢰÎbjH¢΂ÖÏg)²\ ßĐs°Yñ¶N§˜̃ѽ±O\-“ë ÍAM¹ qĐ̣©º¶eÀ‚Œ+"±~´Đ¨æC nÀÆvL¤¼„mEäFl(‰ŒÆ†ÛƒL…́ oï3Zqy×Hí{*§ZRë[Xm»dJºh/>È$Ÿ̀$¨h¿ä́dä[V1‰F¬_ÇÔÚ­*+Ờ„[è ñâà+üRñm0+ú‘-̣›@cô$=đé²Â‘e¬P q#É*+Ä,̃†Ñí,̀µúIXÈíz₫Œª"Fß^J£FfÀŸ:ƒ¨K0P…!Cä! §́æ8b1 eCJ&/²)½ÏFĐ…#5 *g̀܈f®°2*çm+å‹+Oâé§oîP)³*³́é|˜°*Ér"ĂQ5@©œr.Oêû¦̉*í-ăPặ̃¬d+~ܤ@è›Eç˜đ031s1³1ó1!S1™’.)³~|/"a¾ộ ưr/éO"]rîÀ)"»)5-5ăÈXó4U³5Qs5]S6ín©*ó6kË.A337S̃¾‘Æ<³₫v“7G“t’Q-¯²¬ºR9™s+›393:½b2q³:“æ2û2₫0“8yÓ3¹³3³³7‹3,'BÀ< Đó<ÏS=Ùs=áÓ=ă>Û“>íS>ß?ÑS?ß3?ïó?û@ç3@ùS@ư“@íÓ:t­t3û/{<}÷‚s8ooÔI¯4=û³=­4IƠtJ÷sLÍsMדJÙ3M¥4K JëôLÏ“HưôO-p₫í¯¬§6crª%ƠÖíÑ1C̣}:ñQÄ̃qE5S5uA{đ{H-9 Á.ÆdHŸØR!‡¨…Ün-›è*Íh‚:7µVmUÿ¾ï\dp*ïr¹GV‚lÎë$`|t%Á̃íè"3V?/hÁ6lu ;C6Eo#ËÁÎFü”Â’î5`v·föeh•(ṼNQcụ̀+Åöo—­ÈÖ&D¶Ø<)†Îèv¬,É̀Ê.®áh‰¡7&G±Fx+ĐFT305p=÷s¯óÓ’äíDK̀è× NóÔhè¦6`%Ñk“°mvă.Ùf“Ö:ty·w;ep)§ĐR0èF|‡k+W“ .óÔóäx—§̉f38´₫8w×w±7{{xŸC å¶Cd7éj•P÷n®Ơ«™\¥Ú€0vT̀±låE´Æ´L{í÷~áxûÈQ%w Í`°ƒW±FX1çän%¡^uGƯ`ñ7‚%˜,@4@̃ [ïˆU{Ë34 '9ƒ&ˆkT/ë‚§Ơ3¦‡0('4D•u‚]ø…%d‡Q퀣K|zRWøƯ €Ëm*~¦1A5Bózaøˆ‘$dø 'ÏImªÄd‚̉ŒêàµQ¥„Áø [kô;ÏŒ8‰ÅxŒQƒ+¶ xjcXUKŒ7}^NƒEÛ¸FBÛ2BA ‚Éx}—lY₫¢p+†£ ̃føk6êb9C寬]¿ç½¸zotÓøx’)9$d˜ôêB̀£äÑkzåx'PQ©&ŒªĐ Í‘#Ù½8Œ+¹•±—l½¦°Ç™ñÚ®M½Nä‰ (y¼F•\₫–0ÎD鼸˜SÙo]9™+ù’U£êfú(kø‚̣jv×f•0 c)óxf2\ ’ñø˜Åƒ••¹œÿVåŒ2‘yTđÊ&fê`G|ÁK”4GØĐBgîD7ΜùYŒ/s0¤–ù"/ÜŒeÙù‰'‡%Z«¿ê8%°çé(­"ˆm4œéŒûy£a˜™#l˜>©Vx§|éÆDh(₫DºWDÚ“˜"³tR`´-˜,¹X8ú¦%D µTCY¸ªË!N‡ªhu7y[îèƠđ́ Ÿs÷öô§¡úOưx Ơ`ˆqT̉'·‚‰‘LL5ªX(¨˜œù7ˆœ£:­ku‰+è5\gQi÷e+³[kÄuB¹å©Ơú¯;T§-÷åèQƯêƒ[<ȨU 'cÂNX¦(M~™Ú¬!­û²‡T†Ï2°’¨:Iöq ;…ïèx‘ÅØ±‰EÉ&»F¯1;¶)ó’Ăo›ŸĂuÆú: ©‘mCOÄôÊM䉹q~]ûke{¹9öŸe§h)₫›X^Ï`ÊÈúÂ‚Í¨Đø³­‚}\ Ù‘û1,›¹Ñû6÷ë¦VÚ< ±9©1%ưz¹“ă7ú¨Cyö.:¹iï¼Ó»Àr½jµj k§¯Œ &áÈè{ƒ€`Ç™…ưu¼S¹¼%ÙÀA|­E×Rđü¢ÉįUÉ“&úr¢—IIÙ/ÚYø <Äuœ—̉0 Æ‚í”\ĐêÖY{g+¨§– 2Àr‘¼©7£[Û¼w¼Êư”{+í ª•ÂQרˆ'JIüoÆ™ÎüÈ%FüÀ9E/ Ç­<ÎóN+ú¶£d¯Û³₫Đ›÷~©„e#Å9búTĐĂoü1`[Î=Ï*ø® –µ̀rĐL̉ Ơªw¥PLđq‚[fƯp¯7÷8à|ÑI›%ăăĐØ«œL/4 ́Ë’3a“6ËÔ÷¹Ôq}¶Û8«ZNủ|5Ø9“Wơy¯?SGq0×™ưÀÍ}«É QƯØÅ–̀P=Ûk:GœÊ›ưÛÇÑk›Đ„ƒô?zªäơص]œÙ¯k Üå½iº{k}+dƠ<™F¤jb;ŸkƯÖ¹eÔç½à¿ –ÿ¸¸{‚€Xä¤e#I" övCƒƯ]À¹=à™ƒà ~㉙ANÑ.Ç·C₫êB‡mñÉÚÜâ󹨥œRăã2ñ†Ø†Nw…ÚÇĐC¦ÿE×%æ…₫̃œ»‰«¨x:qªr%³R ay:sÅ­†₫â^£‡>ëờ£•˘¾|¿åÙ]5,o…8Ô8*XmăỊ̈åµ₫íăE°›ÈexîăË“µºä—:ƠTV®‹¯~B5î ÿh¦ú‡¹Ç›5«!¦ß%;UU8æĐ̃X§|…?Óí ?ó5…­¥K*C‹O¥©đÈ\;gfø$m<åyô)_óaŸSÛDö }ø]̉[Q5² P_qQaZ¾Ư‰¸¯c¿ø~36;Ôq§’₫$ º́”̣Úi$Ê-?Ù[ÿ_ßøµ{›§¶½Ä§§„¿ ÉÏö³€?Ă›^9ë¹|>øáƯ©·₫%qhƒÉh±¢ óVT"EÆe!‰åơx̃yeâDiä‘H9"Fû%dyéwG̀M“TỶ“~´R†d•Z¹‘e¢̣ø#Î¥@’pÆ)çœ₫tÖYØ’Y2ô¥•$r™¥w…Y~g₫IU®ÇŸ.æ…h¡m®)ibÔ€˜fªé¦œÎ9âwíI‘¨zBêP xeÀשlRÚêHjR 䬭’tæªë®¼öÚØ§ưq´¨Ú×w¤úÇ#¡lª'k­´Né³váêëµØf«í¶5á©U"=™k~JlT°AYƯ´¦í»̉ÆÊ.Forkï½øæ»é’¢›ÜÊơßIß‘¶—‹WîèlÑRëđ¼•Z«ïÄWl1|ÀT¸XVÄŸsj¢GÛ#Âñ.üWĂ³,oTơ^,ó̀4×¼¿̀U6WDZ‰çÜ₫•h©¨,tệ7‘–¿æn¼•6ị́­6G-ơÔT•±ÆdºF—xÑ¡ŒIûef̉J3̀´ËNĂ‹ÀU·íöÛTó›ZHf&èâk½Ñez¢¹ Ê-/øÙj¯̀܈'®øÄ#²úß ™UG&¬&øP¢ë"„×BcN6àe^øË$±½øé¨§¾/º!ó9W©må\1Û:º¤z¥ºvÊI¬úđÄï!“¡ éçéjw'7«¡·›tï„gŸ¦đÆwïư÷Ăñk"£%AjëÑ"̀÷”s×¥°à/c/ºö{q₫ưøç°{;é_ß; ̵3¥ ª|¤{₫ßơà—@ß©Çtú‹ '¨ä!́;Æ ÍÈ¢̣8ÖŒ'y…̣ààæg¶’p„ö£  WÈ™ë[c ơœơ¤Qç53áwX½ßp"l¡‡8ÄŒé,ƒ¬1ÙW¤D*YÆP J¬ÇCR±ôK!·ÈEï5Î S—Éu9êy,%±áÓ™bS´îṃĂâ×Å:Úñ~rĂó^g‘ÍH.vnUç4w‘4*ĐsU<äåø-̃ñ‘Œ›û*Â1Ô4ç4ëË,iÅÑô‹­˜Ḥ”pĂ“râ–?‚eA_ÂdÈW1đ¼e.U‚Ê^ú̉fyd₫‹h,M̃eL¶RÏ ùI\†̣“>tä/§IÍ]åñ$ÛI‘,ù¨MÛ)„uµÔ¥{HJP₫CƠL§:³•Ç&M„Y‰ ñb;̣Ä`Œ4'")·q hđ¤%QUïcÆ2Ù ç:€ñxă,g3mIGZô¢qâßIt@„ÄT»—XµAQ$¡}1ă>ơ™O–F £0)‘4ú̀u¬†É;˜ó2x2:©£¨z§K'ú̀Q2D2MªRă-!đ—Ó\§¹Fí Yû.ËB¶‘¨+%e3ÿ¹Ô²ơ7â;¢µj´BRvg<Ơ&¡„Oai˜+kK₫ÁÔ³úơ¯‚1âÆ:çÁUräk,rIä₫ˆL.acf?÷ ?tö²˜M Î.ă/éheO3â£j˜'9½…GsËi©ÂP‘I”ă„æÓP̉×̀Úö¶<¹ZexÏ03ÓQNgDÓ5àVg@%=î–öYE5”­(n§K]¡´3w3„,÷Ûue&;Ùu+uz¹<-3Ÿz•(m«Ë̃öæv6aèe©‘´}܈_Y’{ÂåK&¢œ\H€q•¢y….yjë̃Ûö)9Ñ.°™ ‰–v± ­Z$\ ̀,("gj-ƒd‹`É₫0$ v°ÿjA -̀ƒaª*X₫ê À"‘ˆúBƠ¢ÉÂ6Áç\Û‡¬b³.¢$ gɸ<óÅ.zI¯sÓK¡ùÊ1mq„?øQ̀1ïË95_Ç|>,ÄÎ3ălçäyËp®‘K°#‹XK<akÑü/̣ºôÏRYăLè¥j™Ë‹2£D•×EJPB3—[?ÉÁ+´¦Yóm·nø…Çyÿ÷Ư>êµD]{ïŇW…ơ]èjæÆ¡yN¡'WˆÙ=¤œP1‰¥ăNQ‡6ư0¶…ʧ]Ưe¨Ÿxưñ#p̉8b%Nˆ¢}~—ßgL¾ø›Œ êÇ•™Há‘X®̃’NWăB,ÖAC1·à|…ÑLmsĐ:ÀAc”bNY_•F̉—¦’\¶éä—„®g¨{eZ‰¦Œîç¢O‚)en‡Â—?뤦 Ú`Tª¢˜jÙâx₫œB^¡ RÊ™W¶Ê"››>êᬒÖ艗&é*CÁ‰q mÆX³Æ…ễH̃wl£½–'댴’Xi¢»+¶°ú:(°" û-±¬»&¹Mj{̃RE»gC©”R¾“HƒơkF*\^AeT[ _†'I©Ơ™–C9û¯u₫V0`̀/¿́/]€…Ḍ¿c:Û»ëƯ»íŸüyë¼çíôïqß®7J0¥äO3ø̉Ïüê.·îGc¹à¤kúéÚ×M¼èÆ{\~ßÁg¯6p@i6×ú̉Ơ@ «4ÿƒúÆdÿ¿ơ¿ÿüu qZ’–ä̀¯q{̉K6₫qÅ"ư“Ÿd&x¿†ÑE~¬ËS₫g¿^Đ‚́_Ă6ˆ¿ êïƒôà-̣µu¬c,?C  G2”ÈO7÷yÏ|íó‚x)Đ:6"CZÊ$#+ËwøÉP}:´¡}¨D#Jщ~¤(/t%DB6E"P&fĂuR̉ ³´¢(µhJWª̉–®Ôi%å(#ŸR…å4ØàÈWđƠO—ú”¥@ư©PƒJÔ¡¾sĐAƒéÑœ=.0ñÀrt̉¡Zµ¨X½ªVƒú¯¢dÇ"µÙéG¶JÖ¬µ¬eÅgóüeª²iPŸÿDëYç*׺¢´¡ÜhGQæđ¯u)È4é'ØÀv°„-l]üôt(,yF;̣:¿–€‡M,b7[XÎfö³ơ¬h;«Ù̉¶f[ ÚÔœ©U7ơù₫4 RRĐz6´¦-au{ÛùñÖ´¸ứm;RhĤÿ²ØÍ ²0¿ú6¸˜í­ps›XèR×¶ÓÍntµ{]ër×°̃Ư®oÓAÙ|’©­uế´5ÉæƠºˆ ïuÅ;_à>÷»ñ½ïoÁ«ßụ́·>Ùá32W†¶騮t÷›_üÚ×ÁØe°‚!ÜàÁ₫%©j0¬Ăwö÷Á₫oˆéKả–x·₫­pq»Ăt#Üè4^Ü iØøÆ̉¨±s̀ăû¸Ç@Öq7†\cÙÆË¨­ [ó hpăÉÑ€F4¦|ă[9ÈX¾²–³̀å-{¹Ë9~q”Ÿ̀bÄÔ¦ư(P₫zj˜ï`xÆđp̣‘¿Lg0×ùÎvÎ3ù m”TƯ ˜mÚà„m‡3Ö³¢÷¼èF3úÑ´»`hL6P†tÚƠ«ÖÅÉF–´¨!MêQ›úÊF`çç 's#“=µ¬KMëY‹:Ç“…s\’O¶ÖÀ¶u°‡-lG£¶Ñƒ X00A Gx6´£Míj[ûÚØ¾6 Xàl&(! Ưf ̀iÄP½É7Èp„̀ Fˆ÷†0ílÛû̃øÎ·¾÷Íï#A F8A´™°Ă“!ä¼›¾Óz@¥C2¬@4 A¿'Nñ[üâG  d°2´xB[œSƒ₫₫±À@uCO¹ÊWỊ̂–ç›&¸ÁXđ•ù ½ _Đœ8ç¯l´cÎv¹Đ‡Nô•Û̉àMÊàî̀ èPºÔ£tkoœ ÆEMZà 2˜@×®úÔÇNv²ƒa,¬a rTăíäG5ÄA÷ºÛưîxÏ»̃é!÷¸Ă}ä°F3t,qrz ®Ñö¸‹#îÖĐ»ä'OùÊ[₫̣˜Ç{5Èqk!¯Ë9ΦÇưp × ‡ă3ÏúÖ»₫ơ°|9®AƒRmiM9̉ D>öÀ¾đ‡O|Ês̃GpXX4-zÄYdQ¼3~_üê[ÿú±·†3h₫~Pë´ƒÎ`¼Û±O₫̣›̣œ¯ưṆ̃Š߯₫üđ¿üñn H##Ú(Ưåñ ₫Ëăỵ̈° »đ 8€x€h€ø È€ È€¹à ̣  ·@ßđ XĂ@å‡7z"a‹Gó&ó ñà€ø€.Ø‚0¨€1È‚2Xƒ4xƒ ˜ƒ/hƒ(¿Àôx3À ü2=ͧ ?#VŸÁ Gyưç 3¨ƒQ¸ƒ8H…RȃV˜…S¸… øß@ÖpÚ –t0a±s¯Ă{, \X…mx…nˆ…o¨…rX‡qx‡p˜‡T(g Jpƒ–PG¨p̀cí°x₫ß0‡h‡z¸ˆxH‡èˆ¸ ßp 'ĐxQé~¿×’‰“‰Œ¤ø‰‹È‡Ơp-æĂ„Ö@,²X£hµx‹¢˜‹p(ö$Ú0âđ +ø PÈ€8€₫€ư§Œ˜Œ^،ˀ»ô0â0 6Œ|g 3àø0»×GĐ â0ŒèƒÏÈŒê˜́èŒîị̈¸ñHđx…(ÖPÚ#₫Rƒ˜'đ¡ FP øƒøhóØ ‘YéY‘IŒß` F -ñ‘&ñ;Gđ ` I‘*‘+9‘,ù’.₫“) “3)“^øxÍ`€x{Ơ3 rs¡âH5Y”Ù’F‰”GI“Ki“Î(ƒ‡‰ áEĐ s×ÑÈ”J¹•ZÙ•Né•IÙ•Ơ`%ơÄÁÜË–M–_ù–n—m9—₫'` A’–(ÈèƒÅØ—tù’ñ  ̣@ ó0¸pÀ`|'×€z™3r¢í`äX€¹˜íÈ•p˜¹•>È€üGF0† â“ÎÇ“· S ¿Đ ŸÉ–œ)—³Ù–¯)c v1V"r1™! G€’ôè™´)›È›Êyœ(Æ “JuP[„ÍaHṛ.@”Å₫Y›Ü™œ̀ù)ÎPùĐ‘Áé0äè‰îØËiœđéàéß0–-6@º )ŸñéưùüY›äp̀àb̉0‘g‚@ü7*ø Ê ú *¡J¡€ÿ A R0 Àđ äĐ '™’ùí—¹ ™‰Œ:¡0ú¢2 ¡3j¡4z£6£ª£1£;J¡( (H₫È1rÔÙ1Qz\§Ơ€è£=Ê£5ú£Sj¥Uz¥Z¥\z£çHC j75cSŒô%©å(¥]J¥lú¦n§X §s*§[J§wª£ñ Ă™ÖUIêúa0₫·’㸗u¨yª¨mʨxÚ¨‹©5 •'Àør‘Ey¸ j§ª:ª JªŸ:§üWµ%N ú÷ƒ¦*©±*ª¥Z«§*«¶:¡â úbª‚”(ƠHœ6¡*¡Çj¬j€Â*À RÓ„ÁöQêCp™Çè©Íˆ¬à €Å¬Æ®Ê:®æz£ç*®ëÚ® zŒ³`˜DJ„ARº*AE±q äÀ—h®é °́ê®K®;°[®+°í ¬ä bjTäEç%'A’¦Äº° ˰䪮‹®²;² ›° {²#{° ú₫œ“q/“³s÷ª$³ûFà ÂX²Û³ ë³)+² ´&+´[´ÿG©×ñ5íP•(y¿`´‹²HK²?kµAë³*;´X ¤â ª³”/¦[{´D{¶]‹¶T«¶+[µY›¬»Ê º F0 ̣0 ³đƒ)Œ*øƒ°ê·ÿ÷·è8¸€K¸è˜ ư'ơ ̉ê ß0 ×đ‡¤ÑS` â`€È·†+¸èè¹…+¸ k¸Ÿ¸¦;º¨kº¥Û¹ªû·Qk©›zB¦3«3ư$'%Y$(€¢Ûº¤º§ë»©ËºÄۻżǻº½{Œóp SÀ đP¯Kê:J%'ú₫œN¼À«¼Èk¼̃Û½à˽⻽äû»æ;¼ß;¾æ» ³ }ËwW»'q!<¢²­lx¾ÂÛ¿ÚË¿ÿ‹¾á[¾¬¾ºPy†4•I”̀jÀ₫›¾Á ÀlÁ|À¼ _knKœ¯ ÁLÁ"|Á|Â$<Á#¼Â|È«ùißÀ¾y ¡đ(¾ÍxĂËû¹PH8 Ơ`ưGƠ` Eˆeđ0˜?¸€ûÄÜ Å¥›ĂÀ+ŰJºSœÅUœÅ\́ ô†S j›1ßH¿[”$£̉ ¯È—ZÅ\ ÅVüÆo¼Ås,Ǭ{Çt ¬Cêæ¶|₫ùz3Ó c! jJÇxlÇ6|ÅŒ\Çp|ÅÍØÈƒ;É’LÉXɘ|É¡ÇüƳđ ï{^Ư7¿f́8BŸ‘U¹Œ‰̀Éx<É‘¼ Ë7LË\ËT¼º±\Ë<º²ÜÉ~ •CUJ°Ä¢©ÈÊüÈ̀¬Çs¬º–ŒÈÀŒÈÎ́ÊZ< wiO…|‰˜ÇÍü͹¼̀á́ÍÑlÉ­<ÍçœÎè·¼‰x5ü ̃‹̃€ºđ…ơ\Ï„)󜌿@˜ €ûü Á(1pưœ²1CsâNËÄIËËz >¸Ï>ˆ•º‹ô@˜ô° ùHÿ§ mÑ^ÜÑ ₫Đ =xÅ1,ÿ×̉#=̉?¨ É\ËË8 ̉à0e\Ê%3Á Oª¡-Ñ?è ̃ê %ƯŒºàÅ¿à Ä8Ó!í ”È?HÑÓ5팈 M˜˜ƠYM0=M̉ölËŒsDQ¿ B]Ô8œÖb-ƠgÑǜŒơÜz}Ăúü®̉ß ×]=ÓkI‰-eí ‹ Öˆư ưWÏ^h̉” Ö=Đzm¼t-|j¿3=íÓ$ñ́ ÊÚÙÙ Đ°ª̉ÿ́ƒmÖ_½ÑRMÛÂ*ƒm£̃0˜ËhÑ—Ư ´½ÙX¸½Ô¨Ñ-ÖưÚRƯÜEí̉ƒ·1₫³ÊªË„)h­ºŒÆ Ùw ÍÿçØ´ «d̉mÛÉø «€̃ƠûL̉¶­̉¹`Ϲđƒ¶pË‹ ̃¼ü âp1å:&¹¿ú]Ư€« óƯªk °˜Ư¹P̃wíÅø̃.ÍØ„)ô° MÑÛ]Ø7lÑ́ ‹R á ñĂÑ[­Ü³lÔ|H A͆QZ̃ ê…_}Üè ơ@óü…ôÿw ø ƒ ß8Œ50 5àÅÀ0c(³8“8MK”ƸĐÿÜÚ Đ…íÅ.ë­à=Đ¿°̉)í×·íƯ÷äYưÚåû¼ÑfnÓºü -Ưßm=V¤}₫Ë—/&Ö° É‚¾àÑ̀-Ö¾̉A,Ö_]̉ íå+ӭѽíå¸-¬Ă!₫Úï-ç¥đỜ=ˬŒç·C'ơ;S%y’¾Ë=Ó=ܸ̃°HÑ”}è}à½Ư„9ߌMÛdư×_xߺ®ècä Ä`=ĐƠMÛ5LÖ ¸ +N¼î XÏ‚ÎêI; EpÊ₫¢\{~]´^S’Ù~Ë›\æ=̉_ü̃ÂZÏo®ÜYÍ Më­ ê _́©z}âÍèár~ °¥h½ %Ưƒý÷ÎÏKÍå<€Áî¶ÜÄܾ›"ðŒÈºêèN˜_Ó­=̉×ưƯl®₫ >ÖkΠXƯŒHÙ~Ụ̈¸î3Ưá"Ö+ƯÔ~́Y>á~îÚÎȤ₫ÓÂ)àïó†k ×=ØQ=1ÜÑe^̣Œ=Ơ)=æÛ óUïƒÑH?ç}́YíîÍ úœØ8˜ÿ7çÅnÏ[}èFÅx̃ÎƠà€·í *ÏÙMçÿW̃đ…„Ỹ€¨½â;ˇ̣€ _ü ¼đ ơ " ˆŒC’â´ĂØâ· ÓO/Ö¥… z=ÏM}ö©` ~íØ{v` ¨ïú® ˜ƠẨ}`xđæḾ'_ÙMÑ'¿½1€ưưßnî t/Ñ îœˆÈJù‚¸ {₫ĐxPÑGưÔ¾PÏ @¥€ú#ƯM˜¥Đ‰0›@©̉ª@ ` đ®ïÿ÷xĐ‹ĐŒ†nÓxÿÚö?ơ­®ụ̈0 ög'ÿ ô7đ_Ađ₫ÁăvDœ<ˆ̣~E¤8Q¢¯ˆ»tÑ‹Ho¢.yAB̀±TB{Jq™ËăDPˆtéúµJâM˜ä°±³i&½™wɳ%/<¿@–’£·Iḿà‘j½oº¼ ̉kHR“v…ÊOIˆ ½¥•·jňáÊ•÷mX~₫ *ä÷¯¯AÀ&\Ø0á‚}̣MW¤ÙCˆtoÂ]åñÇR”èƯg"GP₫“äÂ(Iy%i¥*Đ&9±'ÁºëŒèayuÚ_Á'ŸHo’9vDwüŒ´̣/ !u•j„U·ásµGüÖ́D»ƒÛivÛèöGR¤w O#9–&3-yÊ«̉¶Í-ái“gƠmÖtÉ*"´ä¢Ç›–²d:JnY¯®ëªrCørEºª¢$®f̣ªCỞ12yÄ9¢…n’K2Ñcn¤UJÛăAˆVYë›K!PR¸Bj“B(É;ÔÀ£²\̣0. èq)nó(4yPYPºoX I•6èhC·ḄÅ)Lä+³Ê¡̉Ê¢ơ`”̀Di₫’ q‚ê¡_â9ªK‚®Ê(à³è©g€ ¿É›(× gz¦¹Å—.§FŒvö9́SÁÛ§Çø "óbül¤M -”D¾ñ¤WaÄz衤P²”Ç“[1)„oz¢ç‘B¼Ye’<0¡§‘EVZ$‘åÁ„T*S%Ur]ÅU6iÄ’ÖÙ¨‘²ËHŒ~¡3E¿₫u^zë5¡xíă¶_ÖkD)%©ëJDPq¥”h7ZÊ6Y$KzPYä\WV)äo¬ÉPŒûC«ưJ‘IPÑÅÖ.ô¤UḶÆ\¹PVP̀K.₫'z÷đ’× xđ]Q‡d”́#¤¬-Ä'K¹E]Æ£TYVy,aDêU@Â$P€ dM›ÖJĐ–ÈÅ“] ­‘º>—U6Q™a7Ñä4z¹8¯éqåÜoJ!$d„ ¡ä’<@¥Ha«*$Å_Öå"£VutŹ+¯„̣Ô^Ö[ơè÷í±É₫M¯Măa*sµÜ„aù,©ụ̈o,)rFV¹pƯWär§åj&†/¡¤M~å)UP9×&›†%ü@Áă#Mt‘øe]AdCz6¤HQAÅAi${¶±»"m1¤*D|S;̉ưâ6₫]ÅH¾‘±”Ñ£'mE)”—¡²I>º°Û&đà  pÛˆ*·™bX) öV sM¢œKEÅ6G¬Ux H#–<1‰P@ V–¸̃&¾± A”Mq¥ÀU<‘§mçƠ8‚4àµ4MNZŒÿÖ¢¾di¢H/3™² ±q­Y¨X ! u )U¼µ0ˆåª–À[ă±Bk1cD„%₫p®•x!óu0a-jª» *₫èAgabJ]&rÑÙnDtZH7ÀP =…ä}BƠ‡R㋇̉Eè1©\ơ0$5£G`âºÈ„>éà Ob¥p&è Ođaô|Y=âÑ ;Äâ¡tđF>3Q1KĐ!Ÿø&ưæ‰ ;´Â¨G"> 7DÂyà p <ˆ0Cz8X`Å|…JEáA₫ZC “̉Ñu¥b}ÅVñPĐ¡ ƒ'îЉOÔ¡wø„Åj‰Nü¬¬ *ø€N$¢â€ÔZAW Ó•¨‡0ë‘ÙOĐᢈĂ'ˉăA5 ¨ÈCqƯà VĐwÅ'ø C`⺣PD80A ‚Îjœú¬ĂtÁE¡ªxÙÇ^<ê—Æ·u‰á+cJå?ÉcæJ“EC±"Ö áè„>;¡zTbŸD>]QXỰŸpƒ" Q ~â ó`…p³›‡NŒ“Å…+qKÔ#ø ±q¿\)ÔâPÔ₫k…{‡WŒâ ´EÅ(ôÖPƠ8‰çŒ‰_¸°J#Úª1 ¦7¥kÉăZú¬ ¢p%P‘]IÄ"®`.*î V7<–èRH2qH:´n0³'Zá†È~"©¢°ƒ+zÊ CP‚C¥ḉ—ÜÆr9ĂZ¬'äP1̃]¬¨8ÉRåÜeẩă6qEæ®Á+E&Í’“L‘Û$Be!ñ†ÄäaÓRÚ<íC&ú C„~Âơ0è›+ñ‰E¼ùyøD"Èå n¢YvøỌ̈‰r²¢•åƒcYÑNV,¢ƠD#BqU(Ömđ„4‘80B̃…'₫R±zxBŸ'<¤(₫ ‰Ÿ‚¢ ˜ø!=,J)[„”đ¸S~1¬ôéO³¬ª à6{c# xE8 òĂPE`Ko @,°r!¬¬7«“ï½²~Ü·Ư®+AjÈ•@E‘E ¨p8P‘QܦG+î@Ä¡ ÎUqÅÅ¢X$p•‰FdB´‰pE%áâ«hpœơ³É°²]&BÑ@øñÑ–ç}0øº»¾V¡- R§ñK=±@đA¡Àg#̃ ¸HXb%z(â¢XÄKµ̀̉ ‡́®đFÔç₫ÁÏHü Æ'%°+¡Zö¯ÇĐđ4ÈGâút5h€×¢½7T‹IHÁSºE‹Pù\'CE8,‘ O½Äk1 7âÔhă+!‰°‹ă»XLs̉´‹`E8‘†:" nHĂ¯Q@k u@Ăæ!zĂù„z¨>˜ 7€'q»zXƒpH„5xƒú3V@MªNˆƒ?ȃpX\á·CÀ|2—D¨ ¸ˆ0¼ ¾`9½{AĂ—Ø‘¦ăÛB@ªFÀKú†ùAÀ\q(§?àz8„L>2«©£„J€ëbT¨@ CjX₫¨ü¾²ªrÀH…E †z \€b"ˆSqđ@q„Ûƒ„4ˆƒ4 „Q-LCX7p¶L8„xƒBđ„59Aÿ™ %Sx ó8 Oƒ ëX  x"–VÀxª̣ ‡;‡M|¿¶«O¨@!bù†óM xB(ö„pø„J?₫ƒ„Ë•P$³£ó„yÈD0×˧P€1>X„3ˆ‡D[¤oQ©HXÅX *¸)QR©B¦)µB„‘T‘‡Ë¸ó„7„<¨‡>xo¨JE~*.W¼EºO¸°bûEX4ˆ4»}Ê%C!~₫¬JXQ¸¿™â:úƒ·ª8‹ÁÄDøƒP¨‡M„Kä#M¸.\ <:WP\iG…Ê|¢È«@9¨Äj©F̉)‘**¥SJ%đßø†»¤ [ª\€)H{¨ÀÈ•‡z€zx¤ ¹z˜J ‰Y¨”f(ƒkÀ;ùr¯h:Ú™9í¸ H”È%Ă»0T„NC¸%kƒá̉¶\)6b¹ÇF¨„y¨V¨¾́*«¦T\Hƒ̣́†Lđ2C˜‡Cđ„PœÖ{@¤I‹;¬ˆ¹«"x±J„Á‘Z¡TªA€q —¸ÉÚ¥æÁ„HÀÂJECh₫‚üÇ/k°pđÈ:¬‡X€û´¤^¬CÀA@o -4xFo¨ZÑ…w"?zH„Lа&ó«‹8™ PĂ«¾#ˆÀP&[ˆhh•̀/é(̣†ÂÔ•âºnƒ¡_IM`:̣]À„I˜ŸáTE@È9̃‹](7H¡°w&z@ˆ7@PKȸªJÜ„D¨q˜Ezz°.Oˆ„W@Hx7(+L09zP„Iˆ~Z„üdº#¼*IФO(KhB蕪̀ ¬„¯Ê¬Q—SŒÔá‡Ùù«ÀëˆbÂÉJ„ ³û8đ#]P®è’í±ăQFL@*Ư₫MN÷DĐB¸*oP…}¡Ñ±z/K€„xÓ,Û„?XgÉ•¹¡b›‡u2„ÍH@…îÊ„Q¬¾cjIx–ơ£„a:TñD…ºÄL +¼ ZÉ¡;QKˆÑFÎü—nl³\-o±pˆ‡p¸S̉$Ơl̀æD°Ü$ͱ2‘LÊ’M˜®ppBO0üóÀD‡L„H‡đĐI­OV„¹₫ôI Vh„c'Ñ¢‡sº*! ¶]„yđÀuíMÊ@ÀÈ‘FT•+¸Tâ?£ü†ẳ z€¤¦Â+€q‡°‡Wđ8«{Êz(q™¥…Ú…¨¼†"HƠ;Q¡Á™3Á¦ox\É• Eƒ̀®qL]á@0Xe…7X„5đ„Û«Ѫ„:àŸ“¶tƒ?đ¹HxC¨ƒJx…7P„7ˆ…¾ä:N¨SÔBÛ7:øZá¢á8ÈÄ+¢L½J»#©;ùŒ8% X“é’‰Wbq…oÊPW¨ƒ?ø'`«„cD°/Ó´:HƒOø¦µƒ₫D °5?Ô"[LH]Ÿ«„7H:¨«U7øÏ4x?OA –5X7ˆ‡qÄVÀS̃;>ß>ƒø(|aARCAơoXƒC Ă5H„7¨‡O`´@́<rb 2¬Uœßmz•%7È E¸ƒD¸ƒ%[C“2ëƯ5;P…±̉XE:H„3©Ư°O8ƒHpÀ1”̃¼µOp;7X8Đ,FÍWˆC C ÅZ‡l‹­eAÜ…ƠÙÑgU•Ê@@T7„:Œ·Fà„«@?£*Ûp¸…qŒ -ºëƒWü?dC°<̃ɼÎl aÀ2@Z̉ÊT8„Ö¢VPâz…ß…ƒW$Đ^ƒ =ƒFpƒ =Ư¼3´D<<›7Ø`q-6M…Ep…΄[ @QGĂ…«₫¥ƒpĐÑ ÅCÔL@<4¨‡èúÙáVˆƯ»Ă˜r…*î]đ…@Y\‰8SB¥ƒ«‹ª ôO@ ’m-’éq°‡r8éÖJٕ逗29£đqh#hÁ)½à i¢¦SÙcÆ YÂJ¹¥yhĐÖjJó+ê£JiĐ;ê§j§¦±qÈ•­jª¾%­)§Vé͕ˀ;uÙ(eµ;>a´.)Sú;‘èü 1º­z zÀkr°ë¥1Jiê¬Îjaj¿<¨@a¢‡«‡fnæ£îêÀæê«&‡ýz»Vl»F-¬€P€«‰ø†`®Î₫́T‘‚@ÄhÀ“U‰°¬nmÓk»†mÙÎkÚ̃kØ6ÊÛlÅ̃kËæm»¾êÊÎë´lE‰́¦”́˜úk§¦¦Nƒàn×’lé¾ë£-Ú¦1jå% a»XÁÍé´Öiø">½¯î4’ æÖIœVÜ®1qØëÔ­p ar­ËNjľkzC£Œla‡ún­;́6?́ïúVצ½6Jj¸oúvđ˜zYú†6ÔºX/ˆ>…²óH/º ëÖöê\Âîɾ́t-à¾jAum7Ê—îâ>n˜ºj®Vn®îqGñTGnäö.O½èàđ₫µaÖ,JmU‰’2̣j¿~́[ºkË̃o.¯l-7¿́¢îëi}đÀ¤NệGñ¦~ós£´nÅVlºB/–¬‚Ă=á½É•₫J£´¸Ê\ÙWđÉ”ư8Ÿ́h{€i£ô¸R¸¾é½Ê»‚đxˆ&™ûén¤‹c€`C€BIơ(GOơV_uGwÙXGuYwuY¿uT_u]'9Yÿ¸(CáBT—¡@©k¬ÎđÖôÂơ»UbD#‹R€S×u]—v;tSu^×vXÿu_ÿö]Ÿumou\ÇuVÏvl7ơăʉæ"»R^´¥q̃f₫%q Ao?u—=tjgơ¨v`wôi/”jÿwUÏuG—v^wl†·u†/w‡÷¸YG÷sxCùu[̣ è-‘Ó!ádWë&oA¡µ÷rY`W€û÷_Çv~_yS`oy¿öđvWø u~xS•ŸùŒgykvSö—ö~€¸ö˜7}Ïøă…̣ DÄă×cyĐuYx¯_ønWøY×÷•u€Ïu’;û„¹p·øSu›7x®×ùƒ/”_/ŬÀmÀÅÆ'7µ8ny»øuˆ·øCOx~O{Æo{´‡uµ/üZ—{‚¿øGû·û}Gù™g₫Às( 8‹~Ƀk³̃¨ ¾T”[pν¾ë¬8{øÉ̃₫Épxr§V£äˆUê“K¾t¯QùôF́F+Óâ]Ê¥\)ê2É¥äoßåw~åŸ₫\*jê₫ë)Îè’6Q—ˆ0ë`¾o¹Ëdë'÷´7‘¸Î¾÷öM₫çߥ§Œ1ç̀½~§~åß%y°×öo₫yôº¢gP=]̣.üÅP̃/qG¤ÁûÇß¿₫2r̀XqăFđ¢×đ!D”åé̉ơ-̃BƒeDióáL:sæ´™s̃C˜(…úŒGó(=£̃è-½ÉèL¤LéỰ†đ[J•6V„Ÿ₫¿1b́hö,Ú´jײU»cȱé43yR+ĂU å}£×̃+zâêy 75¦7̃–&¬w5^ßẠ̊êDẸ̀bËô ́Ë4̣Ô„~K¼tii©T –iØ ÉÄ·®¤÷[³"íBrlw¤Ú´…Dm?¬½S`Ô™â Êó8MÏ̀i:îùt™Ø§/O>°ûÑy2 ˃™jxVâ'«éVÑ£ÇnGÄ7!V„ûîT­ZütĐ H€ÿUgCÜe· RÛe÷Ú7áÈÓB ±„—zNô<̉”ôË/»Èă/åđÀPÀ À€*²@0 @₫£Œ:êc|óÍ/%î"Nní´µdZ₫`?íœPD .„Ơ] U(B#–çå<ß„ Sbd~ Lf¦ù’—e¾Ä¦iå½i¦›h2%j‰èŸÖ•Q{ïYT“…zhG¼]Ä¡‡ß”“} ÙRSC̃đùKb %ö Vh~Y¦œihĐbñœ*œŸÉ¦¡–‡éªñübBLm…_Câ°@Ñ?JrD¨F‰ÂÇ¡|vexߤWÚÊW˜W„å³ÖA‹§9["_²Ê³Ë¬ßˆØª§à²ê¥s´˜AmK®«­b…=©5¥…ÇÚ‡ÛWû «/¢ưúË$°ïí3•ö₫lÓiơD¨K=¡}Cïˆ%’ÓAFÉ‹uIu9‰‡‘Ùfµê’iK;eª˜B¦©»1cœ‘ªƯM?„¯’¼ÁÓ]ĐÚ«–‰ờ×@Ö†;â¬íz9-_r&=4¨LǪêÑZ›-–G›)a˜±0S–]g(¯fu8_¤eßDi§X¥íiœh¦ºæ·́²Mîœm>-îÎ&ͦÚQCƯ.ulÆda½ÅƯ*‘4Ä‚Q ˆ»0§=“‚–Đ*KƠó aơÜ‚ĐrK½æ ãtg’A¸h\eùÁóTSổ“KVUkûÍDc•Å[G+IvÉLÄê÷₫?ù¸f¾ă ä|  {÷’ƒÄ &¼C vÔÅ%ĂQĐ6]ùÊë̃C–çqĐ_o¹Ÿ\dWA¯­â{ñ%–¦œÆ3–ă è@W?x¢•p₫@O$0 ûƒxºV4¬(4" ₫đÓ5L&x2ˆ' 7¼á )lMĂºƒF4Q0¦ú c¬² í84£_¯~œ/aÈkgKđ¾Á9̉±2Aˆ^BÆ[N"îI|ȶ3”ä%…+` ˆÈê °'u₫|äø?…”H!©0›JǨ…èY….„_l¬ £‰™jµOÚ*1›‘Ç<2E»#% á>pV0+ñQKªÍJös+äó.‘²®Âw“ª¥́·ẹ̀ب¼øưªy·¼&[Ơ!0î>é9—,d;,u¦wÅü1 'öó$ç|'~(E:eÅ„ZÉ×°‘]UJM‡i,¯“}Ă'2g¦Đd.ÄXñâVHN 1d ă\(F²¹ ]”¡]Ÿ¥éML^)7üà—À°©R€̣¹aSÂ-– ¤„ ‡Pá \xb¨ø* ̉ oƠ¡₫&ÁT|Bô¨‡!‘‰D4ơ@+˜â‰Cè´™D',ñ‡NlƠ™hÄ+4¡O¦đÄ7zÅÖ£>%"*á IŒƠ­DPå¡UX‚9³¡TábJ³ûqH—:#(^ΙQ₫4T„ç}:z%…b6%íü,q¢©%Ä’T=¿`OØê' A°k¾@ø4jv¶(IhmkMbºÓ6íô¥B¼…WÄ!‡,£&§·¸ÆÅ [¢aˆBN¡»>ôBà”Çl «»…8.̃•‡/f©:°¬4Xc‘̉.W’Đh´HV /x!B$"Ñ.¼œ¢}íKßư:¤Dï₫Ÿ¬àûÆ×„–̉Éñ$ “?ù‘yå}pGøe)×Q_T…¶ÛL+SÁ<|Ư ^Ñ÷R#N°{ë‹_ư)ÄæKåcđê‘!́t/ÄA^]DPÿŒ ‡̣Y fOwz‘éŸBôß]XoVKn2dVÂd>ÅĂ¾+NZ‘RbsYÀưq–uá‹ơƯ“Ë–ñˆ¹e%&_È„¤½±ddƒ†0oâr‚‹¤QKt±‰Fà­ôE&×C³ëö£¶4ñ”Ô Å!ĺOzÀÂx³qˆÆûº•–å¥é% 4!B/`̉.êĐ´̉¥²y[Ư³^ï:Øu ­geO/‘H44á;—÷=$– Á₫îÙ½T½îZ§8̃±®wÚƯ¸qv÷́̃«d⺫[ïUHß³Äpcá{–±Íîë–Ççoïn÷Íç=ëƒçü̃ínoĐ_=+F¯îHOz·9ñr¯œ÷AgX“í×ô§Y&Âc¥è1ÅÔ€ Wx£hpC&!9èẬ(„Ô°F,ôÄ* ÊÁÇ&7Èi,ÁL,e7Ư„‘]⨛` J!ơkb–hv),Æ$èBơA($‚<$B(Đ&0*üÁB¬<8Đ́‘Â•Ô øJơJÎøÖå}]àaà ^á₫^ç™àƠùƯꥠ ’ ̃ áơ‰…°Ï„ 4A5u £Ä––ôÖ ₫ êm^ æ çá .ãmWöĐàJ¸̃"?ŒÄCy \ˆÄĂ.·¨Y₫܆ˆB̀TˆØ[Ê}¡¶TƯ.]WˆA>胓`“ăq;́Ă5ˆÁ0ˆµ|aCˆÈL•!!²àÏb¥!ÅÉ,́Â,‰Î’$¢½U"íÈÛ bz—,87ChĂI”äÙƠŒy97̀€Î̉¶4Î+Î ,F"-ú%R¢$^xí/².₫â!ă-"&ú]1‚H.† 4ư˜?4ă₫°°C¯P^º©™¬́I!₫&Æb!Ö"Ú"8~£V/̀B<ÀÂ¥đ¢è­Ù$¶ă0̃b7‚È5Î⟥›6®„êäƒ́Q˜? ”)ªÔF ¢GD LyëÍ&|Ÿà‚7,B'†„ü $P‚L‚(ĐC"x&B=„ƒ'ü9 $à=(ÂöD#dBxB#´‚+‚ÖxƒTÉ%P#T‚7X‚%l‚ ”‚ L…ö̓GjŸ8̀Ă'4B8‚'„ĂMæƠSưA„îĐƒ ÍÜm$Éü¸T>ˆ0`, =Ê"6j¢Yz#0F¢8f#Ÿ„å,Œ}©£;ÎåY†c £ F₫â+Ê_΢8ElƒK)É;tƒ48¨Ù jßqc]ÖcZ̉e0ª˜Ö—<˜ăcƯyct¥0T_¤-°™5Ú£ n,^ă^’å+‚ן́I‰¤Âe .¼fl̃ă<ÊJy’%váºL§ ‚wyR5„â>#äư#Ưá̉U„6¬"9W\V§:^X8‰Ùç}ÅIñïÙ‡K,„+¬ ¸B=¤Á!Ø+„ƒ+ A8„ƒ7ÀÁ!¸A+„˜ß'@•„Ă' "Ä8ˆĂÄB=¼!ØA+L$¤Á+¼ `$,G=´Â@‚̀.¸A#¬A, $LUaÔĂ'¬!¤+¼Bj+¸Á¼‚(؃¥̉©7 épÆÈÔ‡·©N;J?¦Ă ĂñI„̃è₫uh³&è…F+…é+î‰BÄ\/jgu>©‹^'Vë€g’i=ܶ/:ÎDC7ü;œ”4vC4(=đbBb‹Á¦ơ<©³¾f‘"¨¹&é+©=îâ,]|¡\îb~ èzΨ-v+€–ëyJ+Åʪ«8œÀ2ôíÑwYN9„â(r —>ÏfÄ:^;p F|ơDÔB­ÙBÔ„R=E”Ù–­ÛêʉC‡2#)z₫D?ÑäĂ \ƒ8̀F¦<®ünN(­hđ‚Ë̉¯₫ί#QJêÁ28̃9́?œƒă-Ă „í/óïq¨MR¸ÂÀQW°ó„8”Á»Â4Œ@9₫TêVƒC5ˆĂW ûa ‹Ă4­ —09Ă-L9°°Đ–°Û° ăp FW@ «-ƯgEÈ^:€€3Xƒ¯păđ7Øp “p Kq—p Ûđp˜° ‹²  “ q_q £° O± í?1Cñ·±‹p-hƒƠîC?qnin@q° |00Üp³q§q̣«°«± §p‹đ4hq “/´p=Ḍ cñ 3r §0“±#̣';2=C5”ƒ @ĂÖjD~¦oG¬Ăåú±52gr ›1{²§0²-#r.¯±ï² _qÇ₫SMC Wñ£q"Sq&ƒ²0K³Ë152ó2 ĂÍêFF°–†ÅÎ걡\¡ç¤.U^k=Ä*x†‹ÀˆÈÈ À¬ˆ(Àäˆ@Àøs‹äˆ=¯È<ϳ‹4,t‹ôCû3܈¸D¯HC÷È0ĐlÔ‹bYĂù–Åy‰€3l1=81g1#;3-s²(ị̈!ă²Jr5ƒ`´°G²÷̣3S3.csu(CqPó C1/”5ùĂ9ÜĂF¦”/ị́WsQ÷²O¿´!Ă4W¿q$c2QOĂ4€ _q!²¶t¯´Wµ5»₫tW§tVǵ5˜À2p½&6\C9 C34ĂÍZC` v`va#¶b7ƒ1C3\Ă58ö5XeöäV¶`¶5 C5\ƒ3ĂœfyƠ ,·Ă(Ca¶3Ăa'¶kvkÇ6l/¶fS6bOö0 Ă5 ƒc§öl¿6lÿ¶l#¶pw3 ƒ1ƒ3@ƒ1LA4 ëˆ19³EXôC?¨ƒuëKăƠk_Gvp7x7p/¶xǶföyó¶`ïöw¿vx—÷{··|[ƒ0@¶37<·KùĂu[·tgnX4^73È÷|·{#¸y+¸pÓvk/¶coö0Lî„Ûöyw|“·₫kx†—w{[C9Xƒ1€A;€3?̣ñt·NÀd„îQ‰ƯËBxC̀ÑC.E< 1EkMÀ å¸@|AQRÅRWMt‰7˜ ¬ GÉÄR°†­À́iđΖ$>‚ô(bîiN1xc{ø{wø‚“9Ÿ9në¶z£7f›9†+8œsx‚›w0@4đ>èĂ>àq4Hy_8¡Ë9ƒÓ9|wmcöz“Ă0ƒk;8z'zÏyÇyk;¸G7@ƒ°€ ̀€ AÁ Á ©¯:«·:©ÁŒAœ:ªÏ®“:®ŸÀ ªózÜÀ @₫ŒA¨r)̃'yùƒ6€øº©+Á¨º«_;¶gû©o{®‹ª×ú ŒAd;¹—»¹»ºÀº(Á8~ăg÷ [7bDăA Đ€ ˆA œ»¿ÿ»«çú¶“ºˆÁ¬ÓÀÀ¼Âÿû Á è3‚…́郻;ˆ¾³ÀÂo<Ǽ­¯zŒA ̀Ầ¯Ÿ:°w<Ësü @” @qâ§8Ç»¼$cA ˜ÆÔJdÄÚ-<8ĂŒAˆ@Á·<̃+üÉ“<ʧûªïúÇç½à—»»¿ë:àƒ>èĂ?Đ«Tûß³zà~̃s{Ê‹AŒ< ”ÀTûäS>èü Dƒ?°C;œ~>¤C”œ₫駃ë§C;¨>́çĆÇ>́ß>8ƒ(^CëŸ₫êû>ëû~:äC9¤~;Dƒ*ƒ,Ó}Ä:ü4pĂđ??àĂïÓ¾́·ƒơƒńköÏ~í[?ö×₫ơ»~;\íW€6hù¯ø_÷·ûsÿö{?ưƒ.è¦~:ˆâég®„©ÎÄ? „w_B~í₫qk¯¿tí̉Il—¢EŒ'r¼˜₫qâF‹E†¤ø1]G•4œM¼¦¥Æ“%cv”IdÎ’åÚ=lÇí_Ä„ÿÂ+H¿́²Ás˜jÊ(§̉ÄyuäM­&óñĂØ5_ÔtaÓi«@ñÚIYM¶Ưª®G¬nm¶›£¶hD±ưç0?¥G 6|qâ£FÿKØ®H3q̣(ÿ¢|YèºèQ₫&ÏƠ*zºä}#]™ô/]¹*ï’§ë—åΔIÓóơÚƠæ̀º\ÇÎlỤ̀._–a[fùµjß»:ß’×YiÎ̉½És>úù¯oñFWÇ~Y3x̀ßéªTéºÚ¸y K~ιTă_­—¢Ë‰¸i“úÿ-₫«”o@¹¶RI¬|ZŸ}đá‡ñ,‰,́j¾ù¤k*œ6’Ï¿v®‘È0Bâè« -´¯¾›îc1.¶̣ë'xüÙg=‡2Ê1Ç„rL¡ ƒl‡"ú'x†ZÈâÈ}:hÀ»’ †̣gˆÚg}ú¹H…Ê\2È3¡RÍ2{Rˆ2*³M6íLóN3…lP>ưaçŸ~ƈ±<Ñ+‹bèG£ÚcGJ4ơÄ“̉I-•S #‚(‡ú±RL× uÔKKj@³!j¡„”,ʯ‚¬Ô)%×́‘Ô:sÍST]MÅW§Èj!b åơÔd}í₫Ù:Mè§₫yÇŸwˆ"³±DµƯö0(ÿU¢È& ¯2̀»̀é 3·8Ơ‹´ărùÅ—xTëL³x̀•ç6y\nØäa 8ذ›N³_ªă÷¹Ó^Ëw7ắ̃é¦ĂŒÜsÇ+¯"ôSÇ1}D¾ñ×fM̃å¡̃|́#[]VÙ“KN™ÎQïÙ§J¥‚DO0q¼uæ ™MyèIMˆ›nVæ¦e.j ›üIç&ưb̀DzƯ(¤áVCÁÈP7,[n óV)„³1®µ&Hî-‹V¢àÑ¡¬ç₫ÛnÀ¿¼îo½ưmô ,[íÆ±\Í/œrº-'₫ün²‰âÛ¨Îc­óĐ=s!óÖqƒH}ơË[}p̉ƒ§Ô;ÖÜ_ß=ö̃Y÷Ươ¿\e,nwùDưQ² xöIG\ñ̀ÍØ3ŒË¥₫³Ë²¯₫ús{W{s·/í9Ê:ël²óËï>aïƯûéå÷Œc¶clđßơ~ÿ¹Ç̃»oóïúG@₫Ï1hH₫RµCx°«Û¯F¶Ú1N1Ôà‡:LjmKV̉]7÷5ÉQoªk ñ’WüÎ(Z²̉ä8h@É©Gµ  kHB̃.„ëQ ‰˜Á4hqƒÁ`Ú6ÈCv®&¼amÈ;C­ég†₫Q`ÛCEz±la4ˆ4l6vñ(^Tă–’¨@6Xââc¢—1;îËzà#ßxøh½ö}/<ăß=£>ÊLÆ|ăû#øÙ=Ẳ’˜ ¥*UG¶±uC=đ¤î0ÈJ[®qm ôÇ ,)F²EÑoKê²u8ÂG!ÛPèË^¶’˜¹àAt EZBó῭æq—º1ql ˜ÈÔÀmÓ™èÄ& ‰Âr1ñ\ç<µÉ£Á4¨œ½ b éù̀zöSÿ\Pç<7PÚ©`­äâ?êO‡”˜VJ₫ÜN‹¶­¢Îƒd"ÙQHÂÏ‘Ü _¹HÍ r¿‰oVªRF¾Ï‘ßëèóxẸ̀\D€8|¨< QumỏØ)@y:ÔÎ’G ) zµ‚J“¨QíéBQ×¹XwMMèQ¥jT¯úm©ˆT- 'pLXÍ–¡Đ38¶ 3yR̉‡HÖ*ÊnĂ´ç?ºáN»&毆Á ¬ÜøM‹†ÓJ‚Ù‡ñ’Ö»>N[µôÛ_à†wRy= •²Ødº‘­tƠ'`#[Ú²Vơ”đ ăÙ ×Di–0°•Uâ¶è¤Ẵv íH[¸8JS̃¤%}©L‰ Sár¥ÉUn₫rÓ–«¦Đ8n:Üæt§}­i³Wx¼ o¢mœl›Ç-OV̉Ÿ•$¯vEĂT¶MµL  zµ Ùí̃·, kyÙ@Ú₫wy~U [Q%!ÄÀưñ”˜`¦­—wúWÂÖp†s*BâÙZ,cúáÁlÅ)¨a—÷„h¥¿*–1t̀,vn íƒgÜcÿלậúúa…₫ÉI®í’ê âÆ1ÑÄ ‰t;¿é-Ë-%diY™,™aÀùÆ÷ns̉.ồU.$¿áŒ"\Dg Âñç”\ç ®¯Båù̀ạ́B5ÈCtŸ₫},«¹Ẹr MhGÓ–Äk̉’ƒ̉@uÖJ—đ×v O'X¢AY“kăZJl7Ê´¥¿µØÎ²Ó¯ ¡0j¥v\ØƠ7†ơW ˜KóZÖØ¶®}=8{b÷Đëu²)¨~ „׻ε¦=mi÷ZØs>1¯áᄯåÚÀÙÆvµÇƯêrÇZ×2Ôqª×Jé ̃æ¶¹ƒMîzÓ›Øâ®7Ú\­j_ÙŒI&8OŒ-}çÛ̃Ç÷¼ÑÍpyÿEÓ.´í²á¸Ộv\V¦2$9₫e,gÏ2ăë—g<®Ü} ²™ÙvÆC½5w\~Ô}³u+Ư}Đùà·v¼w₫ókËZ×'Ê „:đëüÜçỷ{đˆÛu¯ÿ–º¿ư­tŸ/ữ 7÷ %pD3Á̉ü»Ô­îôŸ+\ëXG»aÜWÑ»G‚’R¥T ¿x—Éd¿äÍcÑ¢s'^‰±Ø˜c=‹y@K|°€ÆX©)¶!Lxñă¿¦Ệ™–Ưâê¥N–âÉ£ Xơx̀#^óO}è¾XÁ´Ă /öl¥-¿úÚ£÷ª§“èºîå;úe|{ăù·7½ÔÚÑ€C₫ñ?ưñ•Ÿüé[ÿđº/ƯéIúm9xE$Ç?J~‘’/{ŸIÿ–Ṣê­₫ÜÛûÏÏ₫₫”où¹¾-3¹.lÎđh¯î…o…îĐơđY"^`/²Èö®¯ú.Đ30û†¯Âª­â,± pùˆ7°/đZ/p¤¢A¾F5g°MP‘m—dqF)ûÏG̣lDâ,èV~my˜ œhÁKg Çäôy¨pîoPLnṃhï° ‡Ï Áđ ßHè Bv¼OmØJ˜”BîzđöÆPÅG GX0pÁpíϰĐÈ₫'v>l€ấQñúñ QI0(œOIÈ„ù¤§ï 7Ñ;₫oyP‰æÔđÉrëo”¤ÀªA¾A^1aQe‘a‘cQw‘b±ÅáÑv‘‹‘ƒ1­Á‘ћџÑoÑg‘k‘«ÿ¤̉B¦î ç0ëp ÅñđÀq _€œG¿‘Ă0ßqáÑâ¸n0ÚªG‘Ư‘åÑăÑ)W¶0ÑèÎú qư±Û12 ÍIŸ* › £zàÅE¯1 ·đÏZH¼"×&2M1sº$‹ˆ#Ỏr¨©o¶­Éœ¬¢LR%q êÏvNlàrG&gr³Œ'·e˜”è'˜œ¡Œ̉(₫²”R)“)—̉)¡̣(‘’*§̉*Ÿ’)£2+)¯*ƒ+¯²)Ç̣)µ̉,¥r,³R*±r)Û̉-Ử”áº(₫P̣g´~̉0N "z`$ưb'ơ¯HMÙBÀü«ÍFêJ0³.+sÓ1‹í¨0%33³»à!ú†÷44M‘v­°<(0C5 #(«¥P¸P€  d“6g³€nó6sS7ys6O@78{S7‹àds7ƒs8“S7ó6ófàN`¦` DàÊ@8‘Ó8‹s9»9ó9m³;ms8eó<Ës<›³8¹s6™€sŒ ₫BÓZŒvÀ3ç35÷óJ>’̉à!l‡?g̉ÂLhÎPë4ô°)0 ô2BEó!8'è"ÔBÇK1yïxöêB;ṕi%“&?J´#NB-zâDS”EWt"PÔEUTFaô#"¢+(â A%,E{ôE[tF_THetHtHi$b"¸áÅ´PÖáV¨ƒB¾âóA=43ÛMkp$¾®K_˯̉) ¿tA1H·ôƯÈTM½,ó%×TMS¾°¦–N³’|M=Ø£=öÄOÿPUP5HÀd!vÀ!Ρ"ˆPƠQƠt¤eÅ 5¯p ?½ôNU₫®X¨\PS7U°ÂtJT™-2"MO•UEOs‚B'­UÉ´K“J5g55Ç&gJŒV*Í™çUX/XYeXĂĐî¼0!ơ Á"t ́P®Y}U ó5[¯P[% ƒUƒ¢s’ÂỜŸt17'Sq55)ÓÄB1Ù5³ÂÔ?ÇT^­ ´ä ˜`‡îƠ_ËnÀ†Bßô_AÓoNS鏴`—­†°•¢/¸É¾Hkvz̉ È oÚaĂZöbCöPʦcodL†Pas5K83? ¶aƠ°S·ä ¢¡dơe…B½e‰nöú©P–gyö÷ e₫ôL#ƒ63₾Åfơi ósrFô”¬E˜<Çj¯k¯æ÷Œ"kmdk¯Ö/¾¶kµvo*„Àvl¹6lµvmÅÖkÙömƯ–¾|mưA=:LAÏty:½–S³ ¸ti·»:Ó!9Ôp?çZцeCuq#t…üÖÆ"×1¶r€÷ÖÍr'‡N,g*—?Û†sz•aỤn«d” ?5ôq§´sÙøœBscw1$u—R_ÖưÁ0÷!l·Uë=¢.«$'…—@b±~7ÇRVyQ_5§Sç­{¯W{³—{·÷zah»W|½w|Ë—|«WJ ́tỎ¢´₫ù‚x£7ô÷/PöÅ W^ÏF+Í‘¶lĐC·ÎAP*L~OƠcÜpAüeï²€OrAå–›ø¢đu–0̉î‘à ƒ78ƒ́p@¸ƒCX‰tà/EXx02…¹n…‡ˆ±Xø…]"áʵ₫6/5P~¾m})¸»rL·v)wñW^µÄo?z¶D’Xn؇/4qœ¢'%o§X á!ס8Ù´8Äzg«ÈPùÆp!'‘‹µ'̣°Íx±úÔxËï8…Đ«+ơ/ª$B ĂzXŒ7+Ô₫Á‹ûa¸˜‚ω·±^…V(!–€ ùK₫¸PŒ‚…-ÄH oƠ-"=Yy&ø©ºîǿX•Ó˜•ëñ¸[ùđŒÛX–i¹K —wPgsnÙßánâÁH%P>fä"¸mØ!x¥¸a uÖáæ "]‰ÙB··D›‹ÈQ„0o¥ù›§Ö[ ,„A’…‹0Í0ï‰×9èHxˆô_µđøYÖù…'™̃™Ÿó²ûvÓÖGè2Ô"¹œQ"’B)â…·(²A‰ÈyqE(xá (¼9¢©t”àaUÜu¤‘§5Y‹(>Ú—Súœ/§­^èƠç×l:@­S‡¦ƒn0nú₫£öèç³tú…€º¨qZgĐ7pzwt¤4¯"ô£ơ(r’ˆ=yǶ¤)Ø)v9s/L:oD·a··(L(4ˆR4ĂGx@ưaUv—­µ¥ÂÔúºZcº®ă¡Ÿw?× (2Gxø:4=gb3€¥]¶¯ŸÚ£bUàx Y¶.O±ÿ5~Å•G¸áÂú±5ó/µÎÔ«G;QZÓ‚÷ dh‚U;¶wÏ4m4›ăfª»1Ÿù`}à/yû±u;ø"q «[ƠMu²so…;'|e›´ô¤ûµ 7e_ÚºÛu,,¼₫B¤!T»˜l¢{»ø‰₫»•·/§º7}«)¹ÏœWơ½é°ºá¤Đ!í¿Ơ´­°F¾¹Wÿ[ïJh¾±Y·T ¸½a7h{¯B3ÁÿÛ® ‚_óÔÂ¥È Mw7œU³Đè̉³*¼éj¹A¼¬ú¸K<Ă=Ü¿oVªS\Å Ô¾Ç{´¿}¨Æák8 oB̉ÂQ|À{Üủ—äËÅ­)Æy—˜6´ÈÜ/Œq¥<¶:<ÇLÜÊÙ×p¢cGlĂ…Á·\rX<^•yUư§ÉËZ´œ̀7Ă¥èĂ·œvöœ çÍÑ0…’1¢”®G›ÈûUÊüjÍ=¡ËúÉ "ÊóÜa©ü¾é|½W₫7Ñ=iƒ(“ƒÂJ²¿<¨´œ”s­Îÿ¡c£í̃§£àưß±kä¹ÅѼ"ßAƯ“â.·áOøab—‚Ú¿ƯđÛ¡ư(À ®}Û¹Ù§½ ăC₫ă¯]Û#)Àư`%™ØaÈ`ˆƯƯÖ~¤₫Tɯ•Çñ=±ÍéµM:)²¿ăÆÔk\nÀÆĐK_bÔƯ.y¤/$6äU>ä‘‘+má%ị̂ë©₫ä‚êÅ})Î₫ë·^ܵ^âM¾ °ê«;PÑ…ˆ:'Ă÷=Ö-œ̃¢>ñBư¦m< .!å`‡œl²Ơ×ܺ ~Œ‚ÔÙZááÙ  dÿEFQ́9PÔêI₫í5~)8ôÓƯ˜}ơ%x́äSŸôûbí·=ơÓ] Z_ôÍ^ăm_ƯûbÛÀ/ _zW]Îû̃ÂåÔPÏ‘_37fhÈwÙ×{|Á₫ç¡^Ô}€ß́•½₫äbăi?÷XîÍ^‚ ôăư)~ô‘^íI?ôÍ^ưÙöëŸ »₫4(€]»ûüd1iđ¼ˆ1£Æ;zü2¤È‘$KܯiÿüÁ;hñ¤̀™4kÚ” O“—ßµ¼ó¦Đ¡D‹=jóe;Đ^úƒˆ4ªÔ©]₫ăoeEª\»zuúó*4ơ;øÅ«@¸p÷đÛw Ä‚ư2.L±ƯÆz î‹™ bÆz ¼Ù`Å}đ¾ •ÚƠ¬[Ït©UlX×´k$kÖà Amû₫ ₫üdL§đ̀tƒ÷CÁ›Kơ§ºbÖăΫ£µö"¼h¹­ŸÎ-1Ăum ÊƠ›=\ÍèÙóåK°szÆ{´œù±úÆØÜcƆ_|Ñ×?ôgE a“ya„&ÁƒÇ-— „JƠǸùÔÛ†"•?ؽ¤–2NaGb‹Y„•ºH£I-‡5¢ƯôuØlñY•c•)`‘q†Ø’}9–—“O>YØg5 $a-Yd“Y¶Pguư3€ÔÍ“1§Flô¦hn&5çub'vî‰çṃùgŸ¹dæKª §Ÿ‰"*'£z i ₫’.)¥“6i½‘µĂVWµ„á¢ú"‹°Q4i¤ V¡®*꛽9ÄMaÂ*UJ&Æ‹ a“ErY]X¼ơël1wl†̀^E,´È:û*Jí  §>₫ô7ÀXc¡Ù? ™꣖bj)›q̣Ô]́Ô_iñ½ï? Ù¥çKøÖO»±‹¯¼ÿl#§]·*Ỡ6÷ûî£óukÀ•+'äÎ̃?ë ¹.£ê^ÚqºK2É úñÄ<}ËÜÅ-”RC‚Úhˆ¸̃<¢‰s9Û¹8oxÎS)¡©óÏ-̣t£h₫hë7y-”¸O馳·Ơ¦ÉQˆ³V5è₫´]kỐ×W»ÄM4đp“À\2“i¯A¤ Ử:E¿Y²ÏtOÚÀEá?ؼ)Đ¾‡ `Á…ÛÛnß[º¦¾R>si µ'Z6/G>?œéÖÁüP:£KqƯ(‚!<ă¶Mqëu3<²È*›<»́'Ûî3¤A!­sÊùj3ÔÂ7W4¡3¯áĐA_̀{¹È{·¢n êÓéÏÏ”Àm1g5œçµ̃Ñ¡zÛ§ÿøD¾H};‘øÅÂSÅÈtĂÖ˜ +×O₫ûl3V6́¬ >ë)ê#/Y¶â$¡Ç2₫@Ç;¢º‚„Kz~Ă’ÖÓ»Àe@̉@f¦'l„É ₫kÇ:,ƒ°‡đD¥ €ö¯VêbÙˆ?6ö´Kɰ#9D Iz@ÑQ̣G₫ª7—Ói–۾榦ëI±5)Ú\\Ä)Ö&Lr“:¾eE-6‡MsĂß:˜(Æ™xëlN;ÛßÇ8Êqt¬£ïˆÇí‘e ^ˆBÈ ¶8í8úÂ[¾•΅)l‹ôZ#5F˜d[-a‡ "̣…†0ÀÆÔĂ}́­I~±á$̣àW{)ˆ\ ` )ưC~qaAÖaIÆœĂJ¿‚Ë˜ÆæHF¢ÎjëèÇ/‰5d*ó‘Ëd¤3ƒ Íd2sÏLĐ}Ơ±­LÎL₫£7¹R5ƒố›Í1!óôuzd;Ë _7¢H{vCúäç>éÇO ÿü§@ zЄԠ (CªĐ‚:t eF°Đ….Xa W`3¢±ŒhHƒŸ̀çq¸1,d%m¥?a©K[ ӗƧ!1P̉<9ɽ<åw8€?vÙ’U>å)Bä>&yÉ[V–6=jK&ùœF.®Œ¥?€K¨:ħ{©d]^ Ö˜fˆ\iGÆú¡»„u­be«[Û ×·Ê5®t«LQ7¼–'/́¦<ÿµÅfˆ€ Op9—̣„…°…ÊÜÚ¥3n(¶±B C₫P 2ô@LĐtZĐ~¶³L`‚ HkZÔ–³©eíjKËY¼€´²¥ílc Û°·º%mo9û[ئ–¶¥}-q™à„.xA ZШ®P$„a¸aÈ, È §¡®¥2MXa ^ï¨ü‰r”óª>ơFçYG&·JKŸö…–[ư‰c|ºË T‚vß§‚j´\¥{+€mhcIpC ßđkÂÑïbû÷cFë»®đX?,a‡Ä&1…M,âxÅNb‚Ι †´ñ"áÚeo,«̀eœéÄñQF¨7îĐÇÏͲ‡H"kg*‚‡6₫ÆBH­t=™ciËöÂƯN ª N‡r‰ø Å¬$è`—[™àÛFé@EÇ ?üåĐ´xÆ3¬Đ[’“ăûxæ^qGÓÛt(ôY^LJ'¡³êôđ ÷ñ{ÏüO?A½›^4Wÿ6OTEÁ²̉;î‹ü¹WN₫9Öù}ô®oÉ­̣¾rƠYܰ¿˜àe í6dƯĐÜø]ô©ûé…rÊ÷´/¤ÍÅG¿Qü=—ê3=+ÇK²¥H³²Ư_T;Ú±–)qéQÔZ4ÿÏjOƠÔLĐdç 1ü05̉D€Ó´zÅ̉fW-½æ#í’^içÀ€ü×€¸È€HMè]“N@?ÚE)à8-“Eæ‡c#ÔÁƒĂ¶XXô~78%˜.Ü`}FÇ~Ù!~g„5w„:—„9'=ÏĐm;Æä‚0Ùc*¢{¦g(1× ñ È… ¡€ï°….1†ª#5fø…½"†j8,Ñ₫½bƒ!7 *a8.ü †:ó†n¸+Đч 8Tts¿2T-ˆq!.>1†ux#~Ȉa7”*}8,Ê1.á2.ʈRƒxd  ç#3&̉h¨…l(. (5]˜^s¬˜‡vx†e(‹©(_xy(¸ˆ\è`¨…~ø¿8c¸†ihŒÂ¸‹dH!Jq6W QĐ% "µ f€fËqqÙǃ\‡5đÀa†‰Ù8Ë¡ƒQ%a3â—A¨lCH3¼SXm¨B+1Lß’=^k”DW¦VÆ m´VÖMá-₫øtÔùFù8aPOz„ ‘)‘TÖ Y eY ₫QđÆ ađr£X›R1(k°o:s|!IIÓ /p!(¹lè,cÁ[GŃhL='^d¥“;É“=é“? ”A)”>iÚ0:-1„U“Ó PĐe8À·Z¨UZUi•W‰•Y©•[9[QYZ]ù)`fpZ]¹•g‰–[9]—åd§•–q™•bI–^)—iÉYNàȵ[àdLfy—…i˜‡‰˜‰©˜‡¹—N Uà_À^àiQÀ’¿óE/V~.)F-s"áñ†Ỹ7/…/HY3'Ø! ê(lIy“ư,Ci›·‰›¹)”.ÆxMĂU”@₫×Qơ4R₫ÔOʼnœÉ©œËɜ͙œû4RĐPÈ oÎi×ÙœËPœÚ‰Ư¹œûDƠéÎ)#eÉ RѨăÉíéï ŸñIÏ) ‘Y™}Ù—É`c".˜;«  ̉r1c£F“y1Ưà© búå,Ë1“B¸ /‘?@NL¸sº„ºj–¸SsQ¡f vkG‰"ø¨.Ö¢/º¢.£0:Gf•,:£9*£; £I t:Ú£Cº¢y£DÊ£9ª̃âeđÀ?Ûa5H*¥BJ¥Ij¥Sz¥U¥[J¥¨ç-íĐ QàÏåe"Å -hơ₫׈~ªE§£aIÔ/»¢zˆ§…₫é¦/Rư™Ư±k²)LJ¨Hh¨Jˆ„ä¢-A¶ Ư@Vnă/`6r§&a—Úb™j©Âß35~膖 ‚Hˆ›jªûàú•R)•©¤Êª®^ Vª¦©´ª3 ú¶̣*µÚ«¦J«Àú«ÁJ¬Ăj¬'†¬)fb˜jª1iKQ& /P‹êHº§±bMeơ-£™­¥"k¨ÙHظÎC, ¨ºÆL;¨ïª¡·;±A«́8-Øú­¯±D9@a”¯!e+£#F’ÿêM¢(“/¡n 62Øu0I®Ê>¢è₫̉@¨ô ’øú3ĂÑ3Ù#ÇĂ™ Ë.GoȱÿJA(‚±$»#̀Ă Ưà?•³:;wü³dôbc„);Éè­‹̣²ÏĂ~5gă4²B{³!q£;đ Gû´öâ!ÀÙ'T[µ¡ă ñO‹43Ø=[«vÀ̉m:²ZÑi<ëM+£#¾&²4c¶¹’D®yw;OeFwv|»*~êDZ™äh°SN[çH3÷”®J6„˜ç²76D,öJ›u*¸?´Œăȸ{Ú!b7ˆÛ¹5¢ L0f+sd»[Ë>7j›lÛ¦nû¶P¸ K·²₫¢µ§['©£·À›5¸H'9²Ä»#DH„CU»«pç~¡ ƒÍÂ=Ûa+B8¼­ó»8ă±g̉WLk·Ô{º ûi J¾ ¦,ë:¸«¼9ăr¡nwKBđÀ¯D¿J{ƯV}é 5öû#Pdº̉¦»=ç6›¼ïKupr¿§¨À@AZG.¥÷À«]7È ³̀ÖÀi»J6Z'„gÓït5₫K#ß‹¹p̣kµÙ™E‘>](s3³/‹“Añ¼‘%Á—ĂQ2<œĂ˜Sy5Ä6ü’J™1rÓ½ÿºl¡æPu·[Á.̣°(l~?EB‡$b|{#N±¨̣·~VW8Àß·₫3’¤!¾₫J“‘Ă¾#èñĂ7 /̣CP1ḈÇ$Ä „BslAt~¼Àx…cA°Á§Àß’?hCe<Å‚+Én:Ṕs4ĂÆ=ûa64Æî'lOF=7”Lø«N*lÀ¢ÑÂúÂE‘Q‚ ~́Ævl TA7LË•GĂ˜£ÇrÇwÜĂÀœA tËG|1’•¦ú0Ésa”Ť]kÅÍL>g!Ó¬}»!7ÿSºÄ!ÉN“?gd”a¼47 dœû™qK4Œ‡Àv‹ÆLÇC,̀¾üA6[Ë{¬³̀Ä|ÇǜÇÄŒ€L.ó-́°¨E ¼NaLä‘ÀØL₫ÍQƒ,eA~³í§+̉ÉU«3¦g"ÑÜy±iVä¢EØX¡’´0ÉÊu+À]‡Ÿ9plĐu,ÏÁ<ǾsÇËx\ÇqŒÏýÆ4Ät‚:ª]K£Á ưN³46èí"ØÑÊî»§H³rf½X\,E+mñÍ×ă-Ùp" l¹–,,ï¼ÑRa$-ÔŸQÓEÏ”óĂ~Ñû„l³óLÔw9ñ×7ásfưÊ|‹m„åÑÖRíU·cgrÉnêØ@s;Ȱ4H¦Î\—_ËDƯóØiÔk×¼ÊWÄ̉R|ëyœơ!>-Đø"×₫â7;]Ă?½8둳¬$È4¡.Ú- ]calkJÚ,Ù̃!Ù½¸;4’cñ}ŸMçz"htf<°~ü1eëƒe¯¼Û3纡1”́ $“a„±9ŸV2×wA9øA^R—Jˆaưư$JBØF Ó6AüVÁAW¨w©Ó]ƠM¯đ ³“ơtQ÷ŸÿÅrjNƒ̀mÁX¤§”¥c—ËfÖí©Ë‘!Ạ̈- ²]y’‘híÚâ±9~ä2¾%ïq‹‘‘T ­FW¾Í¼¾²Ô¾NÀâ. aƒ£́Wcœ¸µ+ă#&n~&Mk₫°™±,Ú”µ̃aQ!‘“®₫¼ÿpàn¬$‡ñ%§•ñÖ|¡ă˜áII¢ºƯUqà…})ΜÜÓƠR¾bgCyQ»Á̀¨ùç äß40SƠ§+ÙC»e.+Û—/¨ƯÎưé*£Ù̉ ë@Q«‰ñáÓ–DhqBA±$j—q膿¤K °-]TæL’û́}ñJ 6X€!˜ôÇ*]íÛ>‚ÖÎí±îíƯ₫í6d›̣̀4à>îá®îâîîíïä.ḯ>ï ̀^̀ÖÔ/¡z.á ¢}£]1ă¸Đ>¸‘Kd,,&æj₫°¡̃ư‡aN”0Aßxß¡ßûḿzQ«Ä% a‰>K ẃÿ{ƒ ‡>×°`K¨T8”Œ\v?$³WÙj#?o@Ÿ’B¯yễ vCôK¯ôM߃D/T;vỉ‡sdÛƒ^ܰfăU»°ÖM¼£NkïclêpÛäÍØg=yâö2¤/_DÄAfo›£8H&́à9“¯C–/ùp¯ù‚ùẹ̀䬗&̃¶ù”ßù•?ú—ú™Ïù©ßø¬oú‹bƒf¦@[ë₫€Ç¡`c8ÖƠđu[¾?¡kkæ ¯̃jíÎ₫saô:íËs´gzvöxƒ&?|qÿcyÖd'Ü' :ª-È+lwÖíĐ7:~%w3sk"Â÷jmjôßü¦s;Jhÿ·ÿ°óèñO ?ÿàDx¡Á„ *t("Ç )JŒXp"F9fœ¸ñbG’K iQdÊ“&MB„)°;x5•íđ­[7m5¹qƒçÏß:ư„ZDTéR¦M>…UêB‚ÿÚÔÑMäT®]½~ö_Ơ±áIc²ÚZ¶lá1ÑJµí\ºS *|÷bMxN¤i₫½:¶èѺJÙY<ü/ñá}±!\¬X̣;‡K~\Y²dË—?¶¼Yôå‚¡KEÇpñçÂđ²YXölÚ_ưµë¦"?‚wkÿ\8؃[áíö¢Ê(Uvî<¨OẢĂ­_‡Zµ¸ij±ï6Yƒh½‡GŸômw¹ ɧ‡/‘ {ƒdqûƠʦ~₫ưưÿvøê (2°¦j@́BŸô“B / „Á₫¸YđA ùÂ0@Ä/ĂWd±E_„1F_́F'fÄ1Gwä±GäoÁ¢‘‰-¼Èb‹+ªÀïŸ~úÙ‡¦ó⣲®ª®₫r¾*·ü,²3K1 ï ~ "ï½1…Ă .¼ÆJ¬$ª`B˜ÀóN<÷ä³O?ÿ4PA%TOB÷́¡OCùLÔÏEmôPI'µ³NœØb‹ÈH! 24TQG%µTSOơÓ *¶hA2ö\ôNPQ¥µV[oÅ5×R+µs‡pÀá‡=ç¼âH-́¢ (ÈàÆ}njMiỤ̂§M­Ôœ6[·ÊªêLxºIK[øÖÛÈ·²Ä\‰zóǹX毤ù‹^zkÄ·̃|÷Ơ·_~ÿơ7`€¸`‚68a„V¸a|kÜâ˜z¥ÑÉa‹Æøb3æxc‡óMæ z₫•y¸F;Fùd•Sfye—[ø9™»‰†Èx—Y5 /’‚ f¢‡2›]£Ñ, ~²,úh§“J“#x¢ ÷éëÔ=s „°µz-kßôghrAóóÏ ưÔæ‹íÜ.nm₫à¦{n»ß¾»í¼ñ–»o½ưæ;pÁ ¯oSèÎ@†?<̣Ä!Ÿñ½%¿¼r̀ßœ̣̀ƒTđ8iÂàÆ Ù~¼sË9×¼ơÏYƯsØg—½öƠmW=w¸¿ơænœ°BI$tâ&7­²ˆ¨®—G¨1ù®e>z¥êM ¥¿­ZúÚÔƯ"®µÿû Â&*Ë̉92Wk¤×W¿ư₫sƯư÷ç₫î察₫ûíÇưû ÿ Bi´£Z©©^ÿ'À60ô(ARđg!ƒ#¶ưYĐƒáCXÁ:°„a I˜B¼=î* úÖ¥˜ñ—ƒ hƯ8ŸĐ¾£UëKăNÓx(®øá…jBbW°¦À$råkPÚ¡  ¥1b ›€Lg•*­&KẲUÄÅëq‹cPµ¨E4zÑ‹aä"¿¸F1vQplăÏhÇ9â‘oܣɯ?‘‚P"á‘ ©Mm†¬£ !Ç4ö1•d$19É;?d>蓈º¼”>æA¸)†^ ¢¯£¦ƒDFÑ}Ï{ÙÆĂÆô£·–Ó„ø̉˜Í9̣úæ‰ ä1j¼èÁGm¦I]ơM¹Jf4 ù¹¿>Ñe Lf ÁÍ/8À!F\ïjßXüÖZB·íQ­ Ÿ/âÊ‹Ư}@j-zúTư’ḳĂçë#äçVñA«+̉}°wÅrÙ7l|“ÛÖ)ẓM-© d¹i†ŒaàÍt̉€[4đö¿ÿÛ ‹ ¨#0üÀÑÀưK@É 6Áû½VC@̣‹B'Ú£@ K x êq $‰»¾ĐÁÉ ‰Üp8ŒK·Ú{3ă7¶C>}³¶óŒ́?Îè $ªgØÆC₫«ƒ8Åh´ BlH³Lw#°LÀĐ8Œ̀¸Œ%|BÎX@ɸ(Ø8Œv ƒ¸̃»> 6–(Áû½¸`oC™8í[‰1L àƯ(;zÚ3C6ZÓ t²¼øË<áXB)\ˆô?Ö`:&< Ó¨A¼Á?¨+Eü¿w‹B¢Ä0x8°«€Û¨³4¬ªnP=,ÔóÄsRŸvđ*®Ŕ:fă¾ Ä–x: 9Ü9:LŸÔ5ñ!‹¸âĂ‚vĐÓ Ö€b4€g@+w; D*lBcLDÉ€‡sÂÊXưsBÆF D0€b FlD tÄ Ù‡w₫H x ÙDBcEơH^»\|GR9 l+Å£Hè©Gsyj™́‰7u1‘ GP#7(̉ˆ¶“?/|eÜF¤Dft7`@DÄŒü Œ|Œ‰tÆÊ¨«2C Ш Œü?Kü Ç@0'd€Ä•<8vƒeHiëÄz|ˆ09H™óIº¶»¨ m²RŒ¸»xÊsG7̀°5”Zl¿Zë;=7¿Ă‹œZ^$ů`Ff¤ÂpTÆÉp ư\FŘÈbLŒ´ü™̀F³lIpL°o”É‚(F„°Kp„KÅøÆ̀øÆ ¹\ oÔŒ¾ôF´lK³4Ë}X‡₫¾†p’ÆèÉ¡”ixñ¹ÅùÓ̀§Q£'Ç5Đ́>+ú‡ßqJ¤ùJ¬û̀ä; ‚T7rŒyDMH[ȡ۷rIHÙ˼䌼\ Œ|Km ǼDKwCKädËËæd‡æÄåÔÆç,Æt̀¸¼Îé̀ÅÀè4 ²´Nº4ˆv Æ…ËÉĐ¡­ ͇ˆÇÛ”<̣€È÷¼†x£¡pÏä íhJËs3X„.Èú,*Û<ÈùCPé±Í¡ëÊôÅßX̀½äÈÄ,΋¬ édLo\Ëî„·m4NëôNÇœNp\FÓ N½ÎíIäÜFŒI½lѺ‹`¬²₫̀ƒ̀L͜͠XĐhPû´÷0ë9ÚG Đ*ƒÊ‰È©»`§ª|0}b¿;ºËsÈ> ÔhIÉ K½|7íôÎe\Ñ…ËƯNåüĐætÑÓS³´ŒíN7 Ç̀XN9åK0­Ñ́ ³2m²̀¡ ̉„8´ˆ"牉B-4…†$%Áë; ‹xzMØŒ +ªó¸Ô§4F ¶â[; óJë°ŒmTBáÜĐoFE܉l@7È ƒRV WÁ₫đ ª,HzR̉~êÔ!ÚM=' ưMúGkdBDDÂa„7•ô $D\@$äWz­vÌÈ O™¨ àƒ‡°§ú³Ï0ñØ ĂÖuÁh¨ ú@tJm`₫ç7½Uo,Oz-Ä0ÑNÎç”U³dƠĂK…h§̃ÎBę܋te”djfüH!é`₫ˆ­¶‰"’»ÖLû§,mŸ—u;™†Œ́ZÓµ4BW¶P=N̉ˆÓ¶h§¶Óđ„7XÆN@m™üHĐ–ŒÆ(íî́h5ÅN…Xê¡đ¹h!T¨#}@ĂÇÎë*‰śÔ‹uh : |Gí;‚€¡â³S<ù+êQˆRöÍï€U µÈ:̃åÅüP($K]NS ÎÍæj¬æåcƠ^ƯUo •ÄđŒX}a­î]U>Q ™4JdLäwl qîîEî0Ẃæî£gÂ3đÁ%O”ƯÔ}<ƒ°đz Uá g¬¤́‡GäY„xŒú5XĂMí à ̀×—dDÄ€₫I*„U¤É‰ä]Œx‡`,.Ï‹m0[F­‰ đ¶Æ[îOđH뺢Ëi Ô¢̀È€èXk¶½(U<¹ƒ‡ƯKA >Ÿ}rµ{Á£Đ́¤xÛ¥clF—Ôăn­Wàaä­ÁX6 Ă…ƠaÔHxđqË'…màø̣ê# é^r§Ù…4t5Ù†à:àẢ)féê "6ß VrHó!2!ă}0 xxÜ·Q'²È;`û«²pTguTwơUO¬;+ơQ¬´RŸp̉X‡ơ°â–Ââu¦u®”1_ÿuZG]Çuœú!Nsu©’&âRà<;ö\§vU¯öV×ơkum₫Ïvk÷vlçöpÿöm÷n÷o—,Ü¿ ×Û\çÊwg.xw¬x§÷y·÷·º÷`×wyÇ÷~ß÷z÷w~ÿ÷|ø‚øøƒ7x‚Wx梈ưd½2¼r÷s·xr¿xsÇø×ø¯ø˜Ó¹ö4ˆüđ9.Z¿ú°±æ6‹&ÛraH,ó±;°êCđ́xGƒ0ESDăùöùÉûùr¢8®A´,aa…8é­ z¥Àù›wzDúC‹úîù–P´»̉g¥z¦hz¨÷z©ÿz®ŸúÛ {²û³ß² 'äÆ@±/{¦{¸{¨‰{ G¶çÈÉ08„Ü}Ry¬”ˆ±¥R₫—§ºÈ&ă«@)3@†Êơ¢i:ÈĂè.ɧ Êw¦h‚¦ È|!Ăè¿eŒ!Œ&ë ̀ï¬Îê+¤ÿÛ¡ ư’+Íÿ[Ó«UˆÉÿ!ÊØǜ×Û2}ÊøµÚ/ˆRgưÜÿ}S§.â¢0P†.2\ÈÚºÙRµz~₫j«p«­ª~@m~it₫ï₫ïÏ₫đ2í7çï~è÷₫ôñÇ~îwÿ­«₫»xÛ©1ƒ)Xzü,ä«¡2 ’ë€øç¯Ư@í₫±û‡pá„ÿ|8ĐŸÄˆ œx° Ă„B¤²¢ÈŒ5dèQáJ’.GŒiR%M‡0'¾4©săÁ>₫†„ÇO(ưú”Uog?ûOÛu4Td¡…[$æ‚4Å¥m¼A¡„rœd–ÁÓjrØ₫áh¾­v¡‡#zøàS³Ç6ÿtƒDdà ƒL¼0£42‘ăŒ92±£<ö¤Ạ8¤‘B"Yd’?*Ù$“O å‘NFYå”R.ie–GÊØ¥ŒLlq>„0æ—XRy¥–inÙ&›o¢çrªY'L:qÅ)à@:ü™ĂŒ:Ä8¨›t:§¢v¹h¢Œ"Ú(¤Jú¨¥EzÉDf¤đç”F*¨£NZê¥<¾ÀÄ:öđ§UXÑ…³Z±EN¨·Ơe”‘Ø«¯¾&ÔS©…ø«±‚XÛSÛ,lÉ>E‘pa0Mc2¶ØbƯdË­·Ư‚û­¸á’;®¹å¢₫{®ºé²»®»íÂû®º×̉+ÍÉXë­µṇ̃+o¿ÿú0À ̀m2W0;×2VoÁCü°ÄS<±Åÿ»m½Ñ0Ă˜wÚ^2Æ"“Ln¶Ú6 ·̀l±E]dqEHHÓm§9›³Î¤™ˆÛ°î4k²Ưl™ÏB#mô²'̃:₫°¢~¼*ןƠWc_7a0æ6Yƒ¶}†4́Q–œØk³ƯvÛËfˆvQ_»]÷~p?Å ·Pla…[Í ŒmäÏÑI#óV>ĂClâk­̉·A8´Ú†å4?K_ƠÙA§9UáçÑnöyd¡?„a鮫fª₫+ÄúèO••êf“B7WåÇë ¼4:Às»C)"½ô–;Øyñ=MŸ}g>P†ÜUÑñqfoưÛm̉jŸ>o¦ï¸úA'{ºˆó¿ß!p(f¸áGéđ†ÿëpỒ3s¸Ë€JÛ̃eÖ‘§8¤6Iàf(¨,*đ§IƠ0èÁ ‚ áIȬ…%L¡ éwBú#Cê`eơBâp…:¼á]èC ̣0ˆ?a…Ä!ªĐˆD́a₫ôG”m°„IDb hÅ%*q´Úමu#)ÉáÜëgÆZđˆĐÎØ,É1ksnô₫Đå87&øoK›#gz'lp„% Y‘CÉ́P¹)¢¸¯u8³¡#+éÈÍE?Ù#-™´ÎyqFëœ~ĸ4ư•Ñ“éÓ•`†"CJªBñ[a*c›ÓàoY‚Ñ"/¸_î*˜ÄÙ0E ̀b“˜ÊÜc2—6Hß%dtØ`$;Vô?S˜Ël&7µ™Í⯆̃́&2ÇiÎr¢s›çTg:³ÙNr²ó!Ëg1ăéN{Âóú̀'?×¹Oöó¨@ËICxx`|íĐÏíO‚>´ è?ux>Ṭ)b<Ÿ-Ưˆ›`=…°́hnà(9’ô5uÄ₫ä‚SK>Ê4¼Đ^hrÈôµ£Ñ æKSú¾W¶Rƒ=ơ)Q‘xø ÿÈF=‹ ¬V£±M̀'D§"/†/T]$±ú¬^ʪ^Íư&¡h(‚éGçPéÖ·Â5®r+]ëj׺®ĂMÑSü±śO†[Ç:öw×Ă"–®‘CуëØÇB6²’́c¢!Ù¥q5”Ư,g;ëÙÏ‚6´qµL;pp¶ư9P´ª]­j ˆÊâ=;(ÚHÇ4±êrm´mkLÚ3̃Ʀ—ºÄĐà6JÖ"W®}µër›RØÂêºLî`“ëX"E)‘Œu»ëƯïµvqDàw₫Ëk̃ó¢W±‚ ă}°uqé/k‡ÊÑ%Mîô0W»¢\–¿½+-Ü\î·sü»™`¬'ÑRÔ¡ͧC xÈÊD!Đ‹0D!,JË ~°„KÜa“øÄÂl±ÎêA8ƆñŒUœâËXÂ\¤̀ ”áRçÈ5Æñ‰YiáæÈu‡~;hà¬jp=èä“=#[÷¢±Ê¬ăkM) 9̀4N&6—¹4x i¾æSÖ,ä1ûó)M®Ëï2g"ß9Èx2€w »Ï™¨Îoô ­çC‹™Đ9¦Œ"W¢<'ÚĐ‘±“Ûzf2RÄE›Œ–!₫g~Ä0Œµí4†¸!ïÙñ”¤ÆˆUư—́†”ft¤`kÀ{Ÿcª-ĂvÀÖiNˆ…£¹½°cÂLȰ—Å4/̣Saˆ°}‡»=v̉ÂByǯ2m„8í˜J±•¾*gtzͰ MkHĂÛƯ!re;œbÍT£ôĂñ–ô¾ƯïwË®7ưp~¼ƯRˆ^¢Ÿê5uƠ¾úq₫ëáH<4é(óưdFÿ¦±¬ÎcF?,´]»Ù×—i‰eÜœrkF×-¿ 6رf·„PkÇw`Úk®fo₫C¶7+‰ù³}½qˬè½KEˆá›₫ñ虦sLeGǯzơ¯sæ¸H¡Í¨Á.¡ƒV§4\ÙÍÎ%K²V7¹Ù³àÛë&Zs‚CüxP¶d.Hƒ[E 7¯ŸƯ€”àñ,Ù9³%ÂË<Í+®-c˜[f¸zämỰj/ơ—·ơăMŸk…Tj‘À’v‡»Ưr[‡Zyûß»¶2ư£'đ94ºçúÅ“uñ)¤Y¶ë€S›™ŸG¤>40—14üÚ¸8q§ëHÊ[nøÔƒ{ͯÿǰ5Ï₫ËûḉwÈÎç?ù^åØÈ¿ư_ÿlf+Ä₫ÁG;,̃̀`Óµ×åZó₫ À6øSPYó½†PQ đÉßÑ]̣F;P— •öVªô=HL™]ó˜PŒNø WùÎ4Xˆ‘\àUÎƯ­D®̃L­\é‘^êñZ˜ß?P̃́¥ü9^µ)àÑ-Dư!̃û1!ÿµŸŒ̃†›çÉâùC(G4ˆVµ F?`œáe–̃™¡–9˜Iµ¡nTÆ:xÏĂÑTJHǵ×QD{X_QTŸ« b§ußi|yÍZĐ²ñZÊm!˽R!Náë ÛÿIâQ̃çAáä¡_&Âß²Ÿ5iâ?<Ăe Îy„æƠßû5Tˆ¡̀ Äâ¡ó¹₫†DÄÿÄ`-zUÇqĐöñbh¼ BÀÆÙY0êÆYY6ŒÑï1ÙqLl‘–Í V]ˆ ÆÚ.ËZp̃ĐÑ\+RÛO[G`a³­çuûu#K4®¥#³ÙZ9!"6³¸\ä%DçY!Ô­Y;8@ Z-"ăÛÁĂ@ÅP’6&$Iu¬1QD.ÜçX“EL•¡Eb‰X4đ@G~(Å$±!=H!jÔ æø¥„`̀T!EÑ!ͤÊƯT̀Ñ\fàÑ” Ơ¤MñdN%Ë=OGx¦½ ‘¤G~€ø€6Â9¥€ËØ)UJV¥µÅP;ü€16₫eUZc°€Ú?èM„%]™8¥¥mñÈÁ…oAänÜdPÚT]öäÊ5ÄP¥OêeMDQ_ª̃ơ¤N²F4=œ Ï«©àV–”¨T[:¦-¡rl”@¼ÎdØI™ä1j¦ÆmdE†_ÄYåÈơ÷¹d×ưÊ3aƒüæLF6Rüưd`îåPêŸv¢næÊå\aæ¦gx±‘1Î4ˆˆd~f†0ÏægÚViÑ;8tnÆFâ¦agT»ăsf/¹˜́\£%ÏÉ¥³€BÜ›_nÚep₫¥mÖ\Mf|̃çMƯÛ̉Ư%Ọfoe>ÄTE  ₫hw>’c¬¡y2(VaRRqAdf„.<¨@Vzƒ¦R 5Ÿ_²8Ø 1'I]NÖ­gvH€Ê…mîÖ$mjÆúåf¼g{æ¦èMÊ\{>SP¾§g€̃Ư9H;Á2¬…? À‚bh…8¨Y">)eD AˆD•B<<„réw.çI‰Ôˆö[‰Ri’W\bÉË­™^ÎÙ¦#FÑ~æåB]â-]mb†B]7ÎéÑù ѕ߽Ơ&àf°Ü±E‘9È4RDù…i…8RÍ\Vjer˜_pé´9…—†Ü¦¾P¬)Dcˆ§3*’Úñ¦ÈG₫ƒÈjªéˆ4Ûm₫é%ú%’<fQêeq §B`âi°"ë̉Ñi^êfM8D?lü†–Ú¨©F4¼€|íQ ak%E[ƠÅ-‹~¦Úq–1 ¬Öb em”éx†¦NÎ×±i Å›â௬_¸™^ễ¿¢^Ó¥™&Z!ycM®ă³™̃æ•̃*̃Úª„£°Íi*aÁ*¡̀-(6´̃±ª#€>üƒH@X(¥~+†8¨?`*JèÊÂϲôĂËêG÷˜«c‚ÚY ˜²k»VÛ5În¹ˆ¸́­Ré̃µj›Öj6&í„X,NªŸ¯åߪŸúà^€¢º₫¢z­9&à$Îă'B̃*²#B¤ăÔ‚ÆĐQ̃9n(ÊẾĐn–ỲʬĐÜNÍ_ü,/:©ÎOeF¨·6¼í ¶*º½¶Úæä«­6‹F-=‚â×¢Ÿ̉D¿R-°fí9fmÿ%æ=á=̉cû±ăè₫g*`;&ÄP¨Ü®CÂêj˜®óHUÎîí îÙüÅÓjfçä+Ù­+—z+ç0…Ư®S‘èÑè­'­¤p¥QÓ‚ŸđFH «›µ-*ÎÜÆJ!û}O!fØh;Â_Í!6äÚæ‰¢Ùf-'zmææêœæœíºÜå!¬BÈîÙSđŸ÷~+Pí ₫5oïêM68+† ílI#0b§fU{L™™ú¨™«e.¥ÑßQY¸Æ£:£̉¤íÚCÜgµí_:¶°Úê\Íåj?Îcª#́uëÎïLñ_æÉéƠŸƯ9Ô^5%1¸±î¦Úíâxæ#°ÎX́BXh•̃Fñ6c˜jŸÑŒjW­"5“VJ(.•jơR$"̣®„ôàỎ§MÚ¤ÿ¹§çÁçŸâ1 __̉' ¾çL­Ù¯n¬ù«¯MIéỘ·FÍeG™™ñgˆ&<(_$;eC]fôâááüX€,.ØđpÆƯë…€°ÓK|r,¡Úe₫’ûâñÆ6^°"åO₫1²̃f£â¤̀=Ó́B!)'Pê7́€1₫D|êĐf¥ÉU¯$›)™Vd́!î ;Y•&ﲸ’3®ù -»eÓÂeKª2'Ë”.ïdCÈ&o"Ö§`¾̣ÊñŒö2Ó©=è13>²rø4bñơƯ.îrƒjX³I±4O\µWQ8iwFĐZ–±‡fÙEæ)ÅΩ$«¥g\^ªmcB ƒ´±?ª-r£2]ë$ ̃iëBá?ó²m)nâåB(j·™FÔèWO¸ØO`«sZH±D³C¿ˆêđ¢c“aï¹ú^è=₫…h:£~½dC«’¬̉àz•4köÊç8lvâo.ë=Ïf>cî, ¨°¦Ỵ̈%Qºt×₫i0ÏïÉÆ Y i¥fZêOïx5SKR‹‘±UªơP5&[ơ(Å7 åˆ£@̀’Z°xđ5®1œ₫î|Ûø%l®œr³~íåÖå'γLû$L%f­ú%@P¹S,o^(6×é•̉Œ³b¯’)©sú`ÈÍîëcsÚ{QÄøü¡ËZv&ö%¡qj̃Q/wh¼q<ƒÑåéû­È±¯Må²%"«’7ÂwZÓ¤;¿̣-S›=Û6;?ÔtO†Q<₫×3aCEÍĂB.r«å°d„&„^q‘Y·–ʈRà×À—_•˜&‚y÷䪲±¬Dzs:v^Ô¢j·â>zcÿ0́¸̀^ÔêœưæÆ¶0N¾§{ë –b »x#"€?@7@Ào^0›jB˜Ú9\8ê|±‚kåR¥nDaErºU3Oø:ỐôiÅ{ù­‰Bn/çX7…ÄTÂă÷>›û†­êb₫6Ư₫%á̉­Ỷ%à$ {³¶^ÖŸåj¡«"M.z÷À6pCÄ:€a×̉-a [­Ă 2–«ˆ†9O&;X\ŕî₫¦‚RB:¤àh¶7èϯuè“™È ºˆ_ï*CƯ a(ª¢×J¡j2 «m û«ÀúZ7"Ú’mLûÄÿ »ø^¬æf­Ÿ÷pA͘e¨%†Û`öÍ®ÉÂÖv‹:…@•†lº;£ƒ¬ƒS(…¥ÅywƠvN…‚©(¢2F·Ä"87‰{[+ZáæúßJ¬ʲ&`ù™£°»âN"*p³ûä¿Rû$2ÛæIlÂCla78@ph/}¯̀fi¾üºWNÖYæ»WéÉDf'«û¢ƒØƯ6‹ŕơQ¨WYy~v+…v̀ ÿ«Œ_<Ÿ;₫¬êđ°ó*Úª̃8 %>ưâ>4öcLăÇ–£ê¢.æ­­ûµZ&ÀÙ„ËƯĂC(ÄÏsT‚ËüăĐ*ÓL)¼mëXSÅ…†wó%®2RßSˆ¤ơéW 6#à¯)ơ^Á§3‰Ïvl«5+ϳ‹&kl %_kËßsZ—₫púàTBSƯ5+ŸẾQpĂW ¨KvàËü…¾r©>„ctN6w¥›B 4~GƯ†₫Yă)+½đ=‰æ|¥Z÷æDr°êå3~¢­ kù«Nú3÷Û7cµ±kơCú¾§ñÔ[n)6Ç—Ơí©₫f5@è€÷`Aƒ&T¸aC‡!&„ÇDÚ@ƒ₫Ä‘cG?N¬˜ñßF"-ô·1%Èünc÷Ừ4qæü‡M'Ι jĐ&B>‰5ÈóçÑ¢ EhóéÍŸC£ Jóh;5º;–lY³áuS1&ÁnÏÆ•;—n]»Y–ü§c亙-ïxIx|V¼8đÛ·áEc’˜qå²(¾µ¼ï?°LºƠûßá‘5+Èn#ºï^Ơ){ỉ­R¡âd*µ*̉ÙZŸîTJó*íÛ²£₫|6<(6x(ư•†Ë™zu±i'_,IÙzwïß₫ă¦ö×ÎG7n+÷q¿₫ñĂ¡ÙÇ÷£fx̉²Ë×?¾v‹©ơă 3ÏF;é«̣̀R¬-v²¢Ê*¡œ’ꨪé'C…"dÇ€à†6¥ (›6Œm«}Â}¶Éˆ"’F ĐFË̉z¡%~4đÆP/BÛg¥Ú RÉÜClÉ'Ër¬ ȸÉJÔîÊÁ0ú¬¿°H3 °#-Ăj& ډ¹­†º)!¦¨ú€â,ÄÆÅ n*ª=D̉ä*§à†r‘ 4O4.Í™ª< ̀-!)-HS‰À#ÍTÓ‡LzlJJoSM›Ơ8Û14ôĂ 4§?ÓÔ° 7D‘&–/$HϨS‚Ơí¦U/ơ‘襫ûïÈ笋chDÆđđR‘Q[‡ºé°Ov1I₫pu9ÜI¥dWaPn6²=ÏDgZ–ï.6=™= ĂF'&­–‰h'È .„(¹ưIq#£›Ê' ™F́H̉ UD% ¦₫Ê É)MàFI^¤HIF ï)Ư&çâ?‚”&€‘$ Á†FÅ,= k `øa-¥lh9Ặ‰,­²7Å k&t”MœˆÂ¬àx« Éêe³HDœX«MlâƯ3À•-Œü”ª1ZJf²¿jú%đàÁsĐñ´m†§-°±6Ç)–Çl§k’ŒâS)º*zæ§D§₫\déåiåñÊH›¸—L‹ZÅ<‘RèH,©ÈM#¡>æÀÎoCÜPA7´APùă* Jg{X•qƯó£¦H;p ¸©¤d9I˜Ø̉¹¼´F̉Ñ¡)mW@x¶‰©?—6-(Q¼̣‰ƠÅ+ˆÚ²¡ùTA‘yĐÙ”ˆ—Åqàˆ4ÍÎÁƒ #IRI`2”©Éô,đhÇ5w¨%²¶o'1Ch̃AÄ ®!Ñ¡g4¥H×±lÍ Nœ«Iä:Hoª«=Ë$ÑA¥7ĂÇ> UeâÆªLUSo,T›ư†²ĂCJµŒZÈç1zÊxôZVG’d°©Í™₫ (ˆ t-§FÙÊÛ…_ó̀M „†‰]ÚcVY#Ữî•‚±–.uÂǪ8t[efO°b,ƯH´6”=v”@ÉÆđÀA‘Lk×wxl·9kRRµµwr°ƯÎWf"*úB$,ø2à~Á–™̀Àƒ=øª)/ÉQÙ7̣œQ̉R»,’‰1mzK¯Ç¬[̉í‚}›lñ<ÛǽYØ¡QeÜ4́@Ưµí[HJ <\³Áá$ À1ë1™ûß·K±qw{uÁ$¥¯¬Xâ}¬„@^Ư4Â`# 2_1Øc~Ê`Ås¼oû́‡ÀÂÆ`9nʈg₫S8ÎVKª4άp&ÈäL¶Ë}óè:üYc¯qÅÚqBÚr$P±&AS₫s¦Èt’Ÿ:UỊæ’&NF#¤¶.^‰>úa[%f´‘̣ÆÚ#–:ÇËăÄNfÁÂ¥pN<‹Û%&¸‘u‘äU;P2›AïbˆjÜŸđØƯ­˜:yˆJ²@w_äÖ¤3£påÓЦW¥ï…0kä«xÆ3: Fám¿¶¬éÇ:>J‹°c^Ùœdƒ1×Ó{Mx¾wa‡krÖ¼:ª°¡zÛàóÄÜCŒªjÓó™-Xw–÷¬Ç¸ënÛ¬«ù ˜rṆQÁ3Nv­Eüâ™wá\î Ô;¡a¸wS>Ç£¦‘¡ơ%ïåu1®y ăÄ{íeÄƯÀù„đœM̃yŸ< %¦-̀—Pà3^ñă{u´ĆÈ₫ˆ³UvÜéi²HÅ÷nÄ÷ƯF†Ơî×úU­6Y"¼ï&»8ưñàæ •̣óªÊÓô¤®̀M G₫9Å yv*Ỵ÷}˜¡[ !•ékc{0x¼c¡Æziđ}^¨©K¿÷ûül` HÀcÍOy6¯ºh́Đă‚'¸øxO>́KLâîĐ’ä(4à9ÊÇînë\,â( á›Üé¼jn]Fs Fñ²¬̃́&`£|‹¥úm©xC»j‰[ ¿ DÆH²n°Z*©h#lÈ3rP“vŒÀ|@đˆ¬¯p\Ă“"pÇ„I|€ø(mÜzË·üº¾Üi¸Dª¹p\®,·|Ă©’jC̀ϰ*Á¬Œ¦âª *» —´‹£~¥à °(…sP_ÎÅ3 ₫0THNV̀ ÅĐølkR6 kæ ѹE¹NPÓÀƒägÚB~ü)DZÙl±< X¦˜Øp7–ª1,'˜¢ä/üK‹Q!&e ¬¦%(ñdWc¬Æ-÷²-1z±¤ ‘ §„(§FÂ=ü0]ª,rFí mdjĂ)Ÿ¨êŒ‰BØ ̀ë—¨i‘ Ăʱ9„"Ï<ƯDË|1#ºAGF2¢1¿CVJ£<¸A³ }*_F°Æ|D¥¡ƒëQ©¨VÈ<Âñ²RlxĂ— -r7Œ+P†Ÿ¨©²JŒw¬$¼âïÀ*çH ññJ₫†H̀%åîH摸•Äă9ÚÉ¢’!í¯ÀDaèÍF:è|Í8ˆ'ª áh£CÎdˆc½,YÔlíBI €L̉Ă P2"1¤̣¬̣%q<%£Ø‘俥K^`úÈ’Ñ ²̣™:V.-ɦÊÅ$<"ơ².èïˤj é°ÄÆ+¼v)¢‚cQND2 ʇÂ{¦i<ÄR-ûJt̉R"(=óI€(ùáöú‰4' =₫¡IJF’Ú̉1º¸”::s4ë2sˆ2aïçØĂ´₫8([z₫a9'ưüHû†eZÍ&BdühyG₫C̣Èê¨SÑDè¢S¾SÎ₫Aüéà¡ ˜>$M-ËEÉqUJsIÖ(ƒèVâ/¶GXb.·#úZS!6‡'Ÿh欬3±0Q: o@L‚57ñ¦†văOÚDâ îBû¬éî(¢ná)eZÈo~iqL4ÿØ«à-¸! ¢…ÍACAçs1₫5=e~ ôĐDs. .R²Ú“-qÓˆ ĂH́£7ăíÁÆæ]̃@Ù6ÎĂ¢‡ŒK#/7©lôFq5NTÊ}Ô$£ ɰ₫P¾̣,Üö¡ôạ́ Ùêj’K%ôA5Ñ;®Bá:ơدBc/Ö ®ó˜ ×è…B́[.ˆO*Hßcȱ<=ÓjtJó9®isRăNñt‰V⬺aˆ$‹6·Ă¿x Ù‘Đ̃¥­¶¡̀úu$h•FÄ…°BmÁBÅ“d@«[Ơj}̣ªµäD …M *ægg´Ój€f´åfâåbª~†nØôEàUÖ¨]+fVT›q@Nl<Ù´̣jb#Xh̀ª…Ó[Ăơ[%*\-–b5vb96c;cO¢kØSæøêc/öd7ÖcUc₫YeM6e[f]veg6¢äæçey–feög{6fƒ¶fåå°ˆ•Ü€Ög‡6i…Vi¶i›6(`#|₫£‘ t ¿‚ëd¤"®l@³Œçx‹I‚P~‚a%T)üé&@‡Ư‰8ôĐ-bɲá-+^¨t+x(¿Ö°ßä© ƒoËC<Î]´µ-ŒËĐ—l=bq×%Êå?(ƒ·3÷r-7s9¢r7÷: <€pÊ©`Ws#‚sO·t÷u!Âuq sƯK%ĐÀ”ơ>UW¥1k(Uvju~³>$l]àÎQ}×x•ñx•—  6¢Â£d¢ ï*Iâ₫«"D~¤¼–Ăjˆ“-ˆBi"圡b„B,“@zi&b$¬\o… æ$Ơ'yå÷Ư–—~ç·R)#‹yí·ñwë÷k2,âÀô—8€€ïwØø€#˜ư‚X‚/XyŸfúI¶ƒ+„8ƒX„-8„)˜Àâ]6~Ix‚K8…Ox„Q8†mØwùá]ĂƯ‚¡ ‚I³‡TSSUX H‰WÜŒµÖ›Ø~ ø)|ë5fâ«xÑ5¨´â®8|e#I¶Ø'Z"IºX8¾J~Ô78pÏ:­(Đæt"%ˆs¿¥Ó £wщå7÷ø~ù₫ø•₫8¡yŸØû8U°ăK8WơØ~ yy y¹‘9’/™’3Y'ù‘;Y»äàT?›Ë““!9€?Y•OY“S“± W™“ •3Ù”+™•s•'™–Ÿ£ #4 ×p¥¡ tWkq·Ö|KÛô6óăVÂ>ä)7'â*¬>«±|£$ùI• J˜H£ƯÀKXQ» bä=*5ÇSâÀvÑ^Ă¼:˜IU2·rÀ™å.›¶Đ €@º^Ăj¡uæú™ñụ̈/óY6 ÚS”¢-ú¢1:£5z£3Z‡)ºÉ´Á¢=ÚSF:¤áÁ¤₫INCúöH¥Ûî¥u8Y ́¥Ÿ¥oïöF§Ÿƒ¥uú¤5:¦-ú¦³v¤9º¨ú¨‘:©•z©™º©=¥ŒN_Ó©©ºª­úª±:«µz«Ú3¸á ºÉ\«Éº¬Íª)NÏz­Ùº­;Ú»! ºà ªÀ ^´¢!s“ÀJæà阷¤™E£]œ•–ª¥Aî:±_” ¥¯»Á±!{²%›²#»±'»² Z³;³-³-»±›´7Û±1µ/;´O[´K{²#;±![µ£!¶?{´C»³s¯A;±C›³?›¶-{¸¥Á°uµ9{µoû¸O·][¹“Û₫³£û·{»¹™{¹¡»º±[ºµ{ºŸ›»Ûº/›˜ª{±Û··›ºĂ{½¿›½¯Û»Å¼ă»»í»½å۽羳¿ï»¾ư;À|Àm› ˜!j[±ù›¾û{ÀüÁ<Â|Âß»Â÷Û¼³›¼k›¸)üÂA\¿E<¿Iü¿!üĂGÜÄÁ›´»À ´À º ´` &:éQ1"÷xT>¢A ̀ t€ ˜àŒÜ œ€ ¼É™üÉ<Ê¡|Ê¥¼Ê©üÊ­<˱|˵¼Ë¹ü˽<̀ÁË›\̀¼È« Â@p`tÉÅ<ÎÇ\Îé|Îí¼ÎñüÎ₫\ÍQÀv`t@˜¼È¼ĐóüĐơÑ=Ñ}ѽÑíÜĐ‹Ü ¶à ÂÀ R€ T€ ưÑ=½ÓAƯÑ}ÈÍ«`ĐÏ<ÔUưÓY}ƠÇü^À ưª@ ¾àÖ_ÆÉ@@)¤1Í„QäûI›µ6§Q„94ÔZ­ƯºÙưÙ—:#vÚ<ÀÚ­ưÚËøº)¶°½Û½ưÛ½Ư3º!̀ƒ¥‰ÜÑưÙ‰†đZÓưƯ±ỷ n= *ư Z`Ø¥‘>~ƯńԼ¶ÈöÁ̃#gi—6៶fi^áÁµ>ÈdïÖA5Đ>ă!₫á^ă;cb€2ï₫ØEä>₫ä¡–ăS̃ăW~ăY^å+–%ÊĂ\\¾æQæ_>ăÙAå\OqUÀl¾åo>çƒ₫b£,Ó¢a ´`®«@ÁknÇÑ…æ6Ç¢°¾ÈIƯBå¸ àÏƠ®bn]’$́ d́;©́¯F:N*íÅíÑ́×î]LîÍ~«̃₫́ăïç^ïë^í÷̃îóđÿ̃ïû2́^Ú¡Á€ÛîƯ>đ ¿ññụ̀ ÿî¿̣_̣/Ỵ̈9ŸñĂjôlG‘$¶ßó'ßô7ơKÿôY?ơ[ơ]?öaö5Ÿö-ßö3ÿö‰7î'âEuøÔ÷#_÷‰?÷øó‘ù•¿₫ù¯Ǽÿb¦Që¤H¿ö­¿ø™¿ó_ÿú“_ûeŸûŸ5,₫$` ¤A<º.Iß”đÏr•êăf_LâM^}°‰̃-~ơ ₫ „7° A‚ÿ&<(p¡C…#6”èđ¡A‹)BdÈq#FŒCrëÆíŸ¿víR9‘#Ë-?jŒ¹r&̀›/sÚÔéÙư ´!ÎH{*•¹´fÓ‹I™Ju:êÓŒW=RƯj"¼0Ñ LI³,Öªg¹¦µV+[µn×MXT`»nÑŒ.ŒË×lߣYư Üv0Oưú́¶,!Áú~*ÔK¹²å˘3k̃̀™3¼₫yáeó‰ĐŸ¿Î¨S«^úô^&Ư$º₫׉2‚₫öÜwr÷?¡₫ø?­{ŸIáÂÿ?>\9<ăĂ“/Nü9séÖ©;‡¼:÷æÓ»o¿îüxíáÁgŸûw÷&Ûưkw¾¿ĐL®K(Ÿû;éÊ÷q7`€₫˜ "( ‚2¡ƒBX¡„RÈÏÆ5Øá„f˜’=3Á˜Æo¡‹ÂØ"{Êø¡5̉h;êø?úäB ^Gö˜dKÙ$)n×±ư&P ƒ•[¥yÆyy¤˜’I ™¢&˜\~Ù%›f*„Íi₫À#œụ1ù¢‘{>égŸ€ÆÈ§ èŒÁÁ“¢?Ù8öÏ3̣ơ3“±f饘^úIùÔĐi³e*ꨤÂĂ„4+Í ¨êånj̉¬²ÖJë­¶æë®ºöÊ믾 ́°ÂḰ®ŸÆú•Qæy¬±Đ>+m´ÔNkmµ²ơC;ÿù$Ÿià„íµäkn¹è«nº́‚ ±·î¼íÖKï¹yÆÎ%¹ê½ö đÀ·”"<̣­Ă§I£C¥¤F,1¦ïVYQ¨g¬±e₫D›lZ©i—ḷÉ(W†[Å“aœ̣Ë0£ O78L«²1ç¬óÎ<_–m₫B§é€ª»=m´Q¡²|ổL'»ÆđHĂÄMWÈ®ä²Ơ<›ÚêÓé†5̉¯rmöÙzÑÖh·]̣̀/´pÁn×m7ÏeÏ*ôcBQ}÷ߘ·×̃€>j̉ E3µá]í4ă&Ÿæ±Å7'D8Ùg¾³Jck©ùç©ÍüpÖ¥núéY7¤›$­è7êu—­4́¨K>kWR¿N»¨¦Zœlé»ó̃ùíbưĩÁ'¿Zï +:Ür+˶óÔ· +±ñV_ơmË~9÷“\<ë~g^|~k}¬ơDßÇ:ưúƠs₫uåô.ºúÀçïÿήÑO¶¡œư¯i®‘₫Ï»ŒwÀ³Ùjµ1_)“>̉ál‚*^+ˆ¹`Pỳ{ßƯ½̀íg#La©ö*²øăy‡ uæ=ßÍ]I\$˜Â"í†Ê\ó,Ç@qqwöâ™¶? ̃n‰P̀LiLĂOÙÇB‰âɧ’øi1fÔKÔ÷Å«ÑvOœ!oV¼‘!¯ŒŒó!₫ਲ਼0t¤#nHæ“*Ê˃y<Üø¼H”‰o/åƒcç–ÆùùOˆ™MÇ'?̀l¨!Ỳ"6®ÄÉ,r“ Œ’IR̉“˜$e(­ÄÊß ”ªüä?6)K¡dq”¥le)CÉQ6Ä—¯D₫íÚ¡ÁBæ¬Dă¿ŒE•ˆ+Qÿ `ñÈ̀KI®sd51eÀ'.lŒ<!wA5Ó„ tăE(_̉’–Ÿl§Ü™É] Ä¢ÔË*¯4ÏvÂS“¬ <­$ÏO²Ă–LåA[¹IỎ̉—¦4èBO|z¢Á ÚṆ¸m œ©Ô¦GÅI²!L4QÊèH…ù©q®4c²7ÈøÅEvT¤ëƒ$Đ‚HI#^†¸¤ B úKXÎ̉”ª&•ú|6ơ¨ú„hChi€‡ 5¡VzåD[ù`~²¡©„*'™E§fj8}é¥î2µ²-S­=¼ <<Đ/v¬ ®ª¹ǽ₫đ)e6¤ -£KgƠ?s̃ïvUô¢ø¨T®ºóJ XhPÛ™UÊ Ä—¸À<9ÙÏ®br²˜m§/7;K©R”´ÿÀ¥S ÚM– ¬ ¨Yo €Èº̉²¢´mj£ÊƠÎØ›̉°K9ùZªÜ…ô‡ÄU#3q]ca§Y’IqŸ›™ÆÊØÜKZ1s3XÓ¼®óŒíơ¢àPR–¶Wr²¨û›Yy¢̣µJV2z;;₫寢{¶ °,¹ởØ®¢6µRưv}Ó›ĂáJÎSIkǺ±Î]‡®9Pt nđà­Ù$énĂ Y,ĐÉUŸÓ¸Ñú(2O}« 7«çv³zÂF¼Oú#¨û(Χ~Aà|Ù[áJ‰?ôÑ»ÄË„)I „¢@£æ¤)jT%[löäññ4”„6qÏE„±°íy¸>LS8ä"¿!ZÁån°ÊîwgŸÏ8ÆøÀă[_™aÛü\6ùÆÿæéŸµ’à"Ÿß“Od,́ª₫’ÀC,ßnoñÎùF-*ﬧø:FHƒÛîá")¾Gá"fï ‡b6°(˘`œz^ƒx*GcdÜN»QŒ•.)ê›P†ôñcö=7æăhI>Ö¿äöO’(̃¡öœùƠÿ-ùÇưœô8Ùë³~ú´ŸK€ÏeF…̣Vö?ÙF1Pb'Dû! W V°cp ±…û°ÇwlÿàzÄ·v…{Ó{/©bpyBˆWpƠ2¯’"ư°¢H(‚*5B³±F·N +G*Áƒ>øƒ@„B8„DxRbW„H˜„Jè@á-Dv>!Kˆ0D1„₫t> Vđ_ YĐN%qeÇxæL¿ñ-ȃ‚fˆ@hÔSf×ø\È{>¥†{ÇrpÔuaWDÉ×b́Đ(ƯĐU@8 :À/°ˆaøL‰‹‰L0‰’H‰•ˆ‰–˜‰”¸‰¨‰ h(`d ‘˜ŸØ‰ ¨¬x‰­È‰®‹•hP‘¨f a`ºH) ‹©Èd“È‹X‰9ˆLaha°^À…^ €W` ‡‰á.Hm(E1Q•3GƯÈ8½†5rÇWü<ç8l-ôzÜ@‚åÚP:ËÔ 4mC̀ Ưđ₫Ñ Ư )9y ™ ¹ÙyË‘ùY‘éé9‘‰y‘ ¹‘xqÿø3# Ë ƒ) V \0]°U ảç)ăh|¨“ ñr©³“äØMăĆ#•/¿!*Ăz¯²G£á“~±I³Gfâ¤6`C‘!2b÷Sø•`IMX…M–f‰„)TÈ„>X–Jè–dá)=HŒ±[`TP$É ;°ƒ&”Q'Gå7F ˜ä=¨R‡¶&´D"v̉ox—]P ̀¥HÍV‡ô3ø<6*£+G6…iBƯÔ}™’E₫ôM\3ѤKÏ¡;ƯÇQ•xO”'wá5én /Ưx†I> ˆ¿i85È2™fHÙ>Đw¹kÈæ97 §H;˜ˆöû!\$mÁƠb*BbV¡˜[ăHåéxA‰\éù‡vFfç‰]‹gyê9Ÿëă …-á è€ÙDÿVœ ³fÈY† W:đ@%Á™ơÙ : G Dîg3x@Iô@î2ËEÄG̣(¡j^5QEy <ᙄwª¨ªªºª¬Úª®úª°«²:«­Z¤¢é(-Ek¥¥Æ•“l—¨vs¨‰Â„Ódv2 đ§„e¦t;QS£5…5Ö&Ï =G„VŸ76₫²­´Ú­̃ú­à®âʪK™kÓz<đƒZ‚5q“»·{Àj=±«Møt£Ç₫©9øD2j‡z<‰“©K´©&uz½÷¨äyW—³­M ¥;±J*±K±Lz±›±û¤NC5nä.a° {´¡; =«ˆ3¯făLÙXZG|nZMÂñ*ÊÚMV£3­gæg"ăƒđí° *£(¨MÓƒSæ©”ç¢ cm?úë±Kµk±W;µXkµNBBª{†&â2³!N[7cd˲S9é),̉vàâ7ûCiḤ ±˜¶ơs*%¹‹;đ$] eúwʲP0÷‚3 %¥LV´ ±¸Öº=³2Qeú#’kDsF†«( Geèê₫ª‚€Tµ[›ºZ»º¨ËºYÛº­Ë’Óû¹X€YE¹3¥ ª¶Dmäăú£3§4öhṿ*.¼5”R· ”§M`K@ÑP>)v „x'å-v'º}cw؇‘¡½Â9Ñ•y’½Fø§Ư+ß{%¤…!Ph)Á› ç¥«5ÇË»gØl»Á¼Đ埗k|üÛ»’3ÙKÆkR¡Û2xçÀcK£z‹|aP̀€€H°¥>q?À%Á €× ĐĐÁ03%Œ5Î`LP3´÷ëØđ(p§÷!<3Ê Ă€…*<Â%̀'LÂ? Â>ÑÂ/ÜE2¬%₫5|ĂQ¨Ă5Ó =́?¬ŸèÙđ*Pº5Kx.å9PYÀ¤ŸUÀ×¹³®Íú¯dl4|„y‘†¼k¥‘XX8ÁÛTƒ®bUSN° fĐ9è’’ ñ#…¸È́+™=)é*Ü¥7äÓ„H(93?áȦ‘üIÉ aɘ<3<½>QzLÑÏ*¡µg²o<>J㸆93Sƒ¦IŸ»|4ÓÊ:đ`‚í©œđƒŸz̀LkjDxA°×§+× °ˆ ́p½)Av!¿"–³R–)̃|RE¸caEB¾ü¡*á ¸§aÎ…·₫½F¨”́|"íw`!ºÏD{_cªÅÜocñú̀Đ¥Æ°a«`SĐL“@†í0¡%v¬x,—f 1#öÇ~f­‚0xÁ¨â‚J 2¨¢NWÑ(âÇŸ"‡)2Q¼¤/›w̉ë̉Ûùr,ư.+0E |P4™́0S‰ pv±©ÆL:7 WAxL Ñèă¬d€…]f©ºøéĐwöV^ §H=3§à;́‹ÀA7¿1'ÍïpQrª%¯¦Ú7pm+¤D×Ïôúđ#xmª%…E|ĐiˆC­)ÿ&©ƠZºÁuƠèx£³¿âhÙ₫¤ŸVhp›₫»»c {>×D‚•pyf}ÎZu¹H+û qÄ'+)b­QbÛ»-›•[¬t̉¸×ú¯Ç-=· ¯„"ư½wR*=m¼]á¿u ˜Spà› Ư4yÆ2à ·„…ỨiƯÇÓ1ÜPGH-ºUYRÈ̉)b6]¢¸¢+ŸWß°rß-ßÉÇQ!‡0=Đ›_¼¼[Rô(sø›€Å ¼aȆ¨ß3’“Đ•Jww¡ủĂDs¶ÿ°ƒ…$Ï¡<(߀G¶ăƯ¬ø-ÑÉ¡ôm%*¬a ú@£qúăƒ«»<^q p̉×Ơ¬ç)‰¡•₫r]á›Ó—Ơt$₫Ÿ‰ưÀư‡P<ơØ7ö‘2¾ºoäS:Æ…¤±±J]ĐˆươXY¥üPëĐê IûËäî„–³%ö-)}zK-èeæÚ™.8§z¤%û¡%\7¨Pz±ơ}éYMœ–îĐІ†Èéu$Î [=†b]̀`́)́|Fnåºù²²~2ËTU’œe–êÓZ¥Ơm· ¢†{¾Œ¤EC .v•ÜêâKj3Q!± ÇÑî»âÑ(°°Œ/@?À8à+Đæk—Aus¬ {²@±uÛy¿±7Èbv+ë`₫$!ßnkïH2j¹ë¦CçPª¹4):È^p›®–~đ6Èt’ÉĐp’'°>Ú$÷Ị̂Ñ„-¤èí₫2ÑYgüE.¤*ư‚߇¥:É(oîg}©%0Ä˰2^êɧ·,Ñ̉Hºṿ³LÆ’k’ÂÊs̃ *ÇDá‡c»̀,k²§&AK[₫R>A"<¾̣€ưñ‘ó±ñ3̣×ʘQ'Ọ̈:;ØTÚ(§Çzt*Ü€¥T ÁvfóézÔ=,7h|ÊçBî+ qË'E¾Üà¡ù”7“ñ¼Û2(êqe÷Ë—ˆwơX_2.B\Ọ ÁœÎ‰à!6áåë₫ơχ˜Ï´đ¹…)y¢úá—áù‘É<}.¢ zđ“ÏäÙ5I_Üvè´ƯXk*ûè8óÙƯ ¯QDXïJt²D=€öø²₫>„£¬¿D$*;‰8yûûđ®ôÿ#ÖïübDhÂo†À́À8 ₫Yo«Ó:Ô†̃]ô¢GƯL?:ưwƒ1›«ûè₫‡5ûÆđº©€÷ß?„₫&\ØĐáCˆ%N¤XÑâEŒ5näØÑ#‚ 9tƒ·ÏŸÂvU®dÙr¥ÂáéVĐåMœ9uR<¹P&7&6w%J’a2,Ú4gÈ¥ ™ÔtZƠêU«QJ¹0₫*V°ao ÚP¡?¡bƠ®e»ö¬Axq·ư3™¶í]±0SΤ×ï_…!“Vöïá‡[íFÜö«¿ƒ6ùÚm\Ù2KÅ ¿^æ\U Aƒ^Ív&]¬̀=c¶ y±iØaÊÔ‘4öm–ZcFëA·Ờ£Eÿ*XëTßÄ•³=Î5&ÓåÑ/’M{6¹t́Øm„÷_»ë²+ß×ụxô©Ÿ%l8ưΣ¶E_ñqdµé×çï2¸à₫Æû¬ ƒ S/@/Û.0xøG!“Kđ²Ùb¢i¿ ;Sí9x¢q/Ă2sĐÀÍ@ŒÈ¸…XCÎD1̉+>lñ6ê4;pFĂ₫’‰»î₫™‹®·rÄ+0‘zPH ·[(²n>D²¢à†“ñIáØñÉH*³DkÅơ²́¬Â„J)ª½4“#¨b‚‡µlØQÈÊ3ÁZj˾âL=É<ÄĐK‡3J‰Œ̉Î —Rѹ”n$Ô¯ö́̉ÏE#HI<à&5vʃS̉¢ƠÓ¼$\ÊÁA‰Ëù₫Ô¡M5µ?:%SôƠ°ÚiR(+ˤ•ÖÙàá!.tzÚsW CèP•Ø̃ÊÓÉHû$ñ̀@c*R>f±3F¸–Ͷ©F+$ó[Z jhBbgSr_ñÂv‰B ºĂ|ƠƠ×t¦V•7ºX»̉÷_—îlu/Wá6s©à1ƒ¤wÜ”PáŒ}[H)ñ±¡]TZEn±Ú1Ö86ÆDTƠ“[ Wà„[̃·×˜TP&͉e®&áƠY¥9À^Sá٤׼=¥„ŒÆögÓàÉ[‘¡ÎÖpeÙjé…¬ÜgØŸgCëèê¸ÖhÊ‚¸é¼{ÉæÔ»ƠæL&¹í.o½Gö·o( 3¾Ÿ,`J󠪟ԠÆ7ñ¿Èí>\r G¼—ậ ÇÜÏ9:ÜóĐßÛ*µÄKGnƠ¡¾ü_̉[¿éuÙ-²‰öÚ'ç2ơÏëÎƯ"vÓ ;commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/getConnection.gif000066400000000000000000002406221410126276600303520ustar00rootroot00000000000000GIF89a¸¤÷- 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†)‚/~9†9”) 6˜6¦9=!%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=qoIZ††ZˆŒ\‘‘`i””k™™g–™s¢ o¥¥s¢ }ªª|­­„µ­„±²†µµŒµµ”µ½½·‰Æ½Œ½µ”½½”ÆÆŒÆ½”½½œÆ½œ½Æ”½ÆœÆÆ”ÆÆœÆÆ¥ÆÎœ̀ËŸÖ̉œ̉̉©ÖÖ­Ö̃¥̃̃¥Öε̃Ö­Ö̃­ÚØ·̃̃­̃̃µ̃̃½̃çµç̃­çç­ç̃¹û̃Îççµïçµ̃ç½çç½ïç½ççÆïçÆçïµëï¹ïï½çïÆïïÆïû½ï÷ÆïïÎï÷ÎïÿÎ÷ï½÷ïÆ÷ïÎ÷÷½÷÷Æ÷÷Î÷ÿ½÷ÿÆ÷ÿÎÿçÆÿçÎÿïÆÿ÷Æÿÿ½ÿÿÆÿĐáÿ̃ÖÿçÖÿ̃âÿç̃ïççÿççÿïÎïïÖ÷ïÖÿïÖ÷ï̃ÿï̃ÿïççïïÿ÷Îïïï÷çï÷ïïÿÎïÿÖïÿ̃ïÿçïÿïï÷ï÷ÿÖ÷ÿ̃÷ÿç÷ÿï÷ÿ̃ÿÿçÿÿïÿ÷÷Öÿ÷Ö÷÷̃ÿ÷̃ÿ÷çç÷ïï÷ï÷÷ïÿ÷ïç÷÷ï÷÷÷÷÷ÿ÷÷ï÷ÿ÷÷ÿÿ÷ÿÿÿÎ÷ÿÖÿÿÖ÷ÿ̃ÿÿ̃ÿÿçïÿïÿÿïçÿ÷ïÿ÷÷ÿ÷ÿÿ÷çÿÿïÿÿ÷ÿÿÿÿÿ,¸¤₫÷í[÷ÏƯ»ƒÿüùû×OaÂ…#Bœø°¢Ä‡ư₫û·Ïá¿wÜ6²ó×pá»}ÿô©dÇ̣äHcœi‘¦̀8oê´¹£Ë}́*®{÷oÊH“*åØÑdBv'–̀É“ªƠW«bƯª•"; ,Ù©Ô·‘(É~KÓn”Z娰.¹f+·nWºwíâEêOŸB…D ¼ö¯¿ùô©Ó·Ïï^½óJ~<9rMĂ=¾s—2èG¥_ÛkÜ·²iʨ-«î¹µĂwboØ‘ Ñ©O¯ÎÍ{uঀÍ—Ù­?ÂÄöæéº¹îçËç₫üÔ!ç û>hØqáè»Ă₫WøU¥Iî₫l#,¬±bÆÅƒ‡.ÿ&ăÆcƯøḾáưpöÎBú ¸ßqdÔÑ€ûp–’gG)¥7Ô~FyDT…æüAhÖH Dg.ÔàS ¹ƒ‚=˜Đ'ºUâ‚-x˜ƒ)U‰ Øc„ÔƠgë`§VZ(½¸Ögçô¥g;>•Đ;dÁÈ •+ú˜eT[Îá• º(a—C^‰›™ ̃ă‚dƠHfŒÎÈÙ@aưcÏaŸ™åÑ’I½ö™_~¸Qi·¦Ù‰¸ˆfâ¤$Fê"BØ"nXbª"••¾Ø)f­è‰Âx'— Î©e•₫A‰å—_aƒ”g=At(Aew⤦†:'©v²øÑ—¿¬«†Y¥—jÉå˜0ùl¢?²yX¦ndé‚ơU`vPaxÔRåís·ĂÊXå©&¶«l«0¾:ïF¦ æ»Bk-ÔfË(·û•(iRºs`ñy&Ͷør”̃G¾Ê˪•ơ6˯ƒù~Éè´ƯV«-À!7#¡Üc°›¶[绨:•¯ m§§ 6n„Â~%)¢±‘ ,¨›¶˜%¼^ s˪ºẸ̈±{*³d9ÛeÇÑ2¸PhÔ©ăgîR(ngP¯*uuúV½qÄ,fÈ₫ËcÀ‹I0₫ˆåuœ‡^·¡ŸÊJ“öjˤ₫ ¯ÁB¯L´‚.—:yÛ1̃;uÆnßëccFæ§Ï9ät_“ÿöÛgAƠº‡¬·؆)Ơ mi¶ai z-{êÇîºđ°’ê"ơ™ñË¿₫úđĂ3<́Ñ·ÆRFª”@™m= Yë€H˜óÄ/<óÄ“ưù́/Oưûêûú̉ÿ~BꈤP‚º®½RáKÏ6â»ú„~Đ+^û¦¿ø™ï«K`·ÀäI°|ÈkEr@Ôe*9c”™ %€\í7Á®Pƒ)œŸƯ×Â÷½đ$ß )Ö$Ú°D]₫÷¹HYĐ„ÄP‡<ßübxĂ.Q†I¤a?ÓÄà]Đ̣SàQv#‚@j6STa¥xD*щ5̀Ư[÷Bô•QŒI¹ÍCNÈ’ •…#àûLÕĂ5Æ…mùÇÆAÖÏ.<#uh½p‰D]û°ÇJ°Ç”ă)Q‘|£!+ˆHb%̀ƯQ¤R¿ /H 6t·¡4q‡¡¤à ;ùº*f’–w$Œ~ö‘˜u16ù!¹€ ÅjfÄüJ1ëØ’cj&?)ÍİC˜™C"%2ìăm“\Ǽ&7™é’dzÈHÀœ™2‹¸Ípjsœådg<«Ó†ÍVù₫û …₫FÜTÄtă‹U<“9̀o.Ó™äJèAÅéN²œ̀tè;ÏÑ́ Ó íl&8I’+”#—Ÿá'?b–r裧2gD½©Đqj³¡*gFáÉN‰4¢1-¢Na£N–&s>Ư&AÚ’–S833­Œ¢I¢nœá+‰ T—æT›¥éD{ºSœr™EkKjTØ Ơ¥AÍ*C½ÊÓ¯¥Ha‚t…[±«*u¦U{:SwÊÔ¦]ƠêM¹zV²£ *`ƠQÏè{,ʆ¼¨S±æơ¦c­lZÍØ•–­±‹1-Qµnu±̃ä*¹úv¥à]óoMr₫Ê?̣wƠ6s«†Ư&XµzÎÍ¢ơ³‰Ư«LMkSrjvµ~}I=¥¤/Φ1æPIQzu¼́§›-M,pW*܇µ¸¨E®q [T,¡ô„JŸ(DW‚|ƒ¤œÍ«_kzƠÁΗ¼äÍl~ÚY„5¸$…X̃‘*Ư±„̣ …̀à;%J‚°[ˆCœ8/\íđ‡:Ô‘¦,¸Á ~°ˆÁÁ{ØÄ=±|R0̉#D)T8väE=ñwâóøÇ=N±}ÜĂ³l8=¢]dÿw¸bXĂFË.uLd [¹ÊX¾²–³ä;ú/b ‘®“tµ™>÷Ă[N3₫—Ờæ5»ÙÁ/V g2bP¦²O|³Û̀ç=ûyĨó‹a¼æ |ÍNt›Q|b3ÚÏ»́‹:rwd¨„₫ É­ôIâ>{ZÑ æñ˜)ùbHê#dSK‚©êVzÁq vúƯ}̉Ơ ffơ«]Ík ̉‘ Y¥f¸•©j¦ØÅ6k|…£ld3[Ùñ%öàÖ±¿s-d•ÿøF5ŸÍmm>ÛÙÍîv¸ĂíífrÖÛâ†6ºÁ îƒh;,,‘j1`§ƒ±0B±‰Íîoû›Ùưw»×ưï€/›Ưåæi|“đdăÙ„Ii ÿ·?[ÿÛÚÆsº^đs\à'8È₫Çưñ†‹Ûä#/¹±Y)Ơƒ<ŒONª«î¤}́¼ă)9Ê>r”«¼ç5ßyÈSîî[Û‚QÔR8c Í ]Ư8ç¹ĐI®ó¨ƯêTzεnr¸Xú/œY%PĐÁs¨g}êçúĐ»~î…£Û́RǺԭ8ó¡0ëˆ;hđµËưä‡:Ú¯vÁăüTơ~8Ü@cØ+¿ëĐÏø¸̣̃ƒλaĂ}¿ëH̀c®3Ưa#Ùfÿ¹Ï«®uƠơ«Ÿ*„Íú mxăÇ=7¾áƯoăöÀç½đƒOüá¿øßH¾7–¿üäó^Ú¦óRoXƒÛ°Æ6₫Ïưâ{¿ûàÿ¾øĂO₫ñŸùÛHÿ6®Ñý°C#´·­C½ăxïæ/¿₫óÏÿưû¿ÿ̃Ç Ơ° Ø'€RUR¡üäù €đU ˜}Û€ÿWx˜H|çÇ|ÂÇ ÖĐÚ°§;Ú·o»§*¸+Ø‚,¸Üp{Û·{4ø|·0QÖ××ç‚>ø‚?„/‚!ø^Óa ׀ׄN(„Pø„·ç|Sè|ÛÇ{̃Đ 7*B̉ƒÍ†Q8†RH†è§~́×yM—+qß@€;ƒX(†eX‡dØ}̃ ~Ø~ÖÀ’#q”„¸w)h‡†x‡₫¸|Ø~Û· ^à G0bPG@˜x‰˜¸‰œØ‰ø‰(J°‰U°T€e@°Wđ^…gÜpfGpGP ˜‹º¸‹¼Ø‹¾ø‹˜XUSPŒG`e€fÀ~)q.̣;QKph KŒØ˜Ú¸Üg0p˜x€»Óa"EJwÄßpg U`‹Ụ̈8ôX ¨‰e0K0j° ±dq f I`B`×h ¹ ©—¨‰Ó8”(‘^ HgñÛ`J B ’"9’½8T`‘AQ6)&  I’0₫“ñxK C`bàfĐ­Xje±!̉Àf2Y”F ÂHŒÆˆŒT`Ü sÛ C Lɉ¸x”Zé‹Sp^ù•GfЇ`YDa j`‘xD¹•nÉUà•R0SP3°è@ÄÀ ăÊáÀ ~ ˜„Y˜†y˜ˆ™˜Ï €© © ̣° ă  Ä èc^¶weĐ Í0|™˜ ¢9Ï¥i¨‰§9¬‰˜}Ù—á0²i eP.g"ơTeÁT` ÍĐÀœÂ9œ€Y§iœÅ™Ă© ăÀ™T€cö$Ï8>Ü œé™Ä™Ú₫¹ÜÙÂɘ€Ù—Éœă@ G@lKÂb` ²àéđỴ̈9Ÿ ù—âY˜Ä` –ù<`´ܰ™íIŸ: :œă@bĐánÿÉ—Z Ǚȩœôù «I˜‹ỲÀ Fp ç ÆK` ‚¡(¢Àùá9›µiA GĐ¡÷ ›î©¢8Jœ̣0;˜̀@Æ@è¹K¡Æ@<£JJŸ,ÚœÆ ÷€R á½đđ Y¥Ïđ ^ú ¸đ¥aê¥c ¦bz¦dú¥¿@ ¿² ̣À ¼p¥pº P÷Đ'ç´2Ê—̣` XÚ i:¨₫fJ¨ez¨hZ¨z¨đ`¨‰¨©‹ú¥¹P©¹ •ÍIÏñá!U°—U ©“*©¦ªºª¨Êª§úªª¦V¥;Ê RÀ væ…268t 3Ê£€j¥­:¬°êª±Z¬Äz¬Êj¬̀ª¸€ ¹€¥[ª¥~)Öà$q¦÷`Äà̉¬Í¬âº¬àZ®ă®ÊÚ¨Zª¥[ú ¥) FcëáX|J‚™¥è¯æJ®çº¯ú¬a:¦›¦¸;*ÄV:¸WéÏÀ¯û¯ë¯Û¯^z¥îú ‚ê¥YA€™‡̣“3›Íđ°˪[¨k¦k₫±-û²”j©˜ j µÉ«r Rđ—\Ê®đ ϲ ³C{²^Z©°´ñ±é™B@^6ÚÊ­̃Ú¨E{µ.k´Y˱?¹ ̀@ 2 ä0¥Z*«? ¦+­>»¥l+­nË¥pë³¸Đ ̣đ§áP̣°˜¯vFÉà«÷º±q[¸m{¸s›¸o»¸r ·ë¸ˆË¸†«¸Û¦Ï¥¹ÄPDtöV£́0ÆÀ³;¹’¹§«º¨»º”Ûº¯›º¯Ë®ë®y8ö·ÏR@!¸UÚ¥mʺÂ;»Ä+»ÆëºÇ »Ă›¼Ë‹¼¸p h ­đ  R¢₫øx9  ÏĐ W¼à«¼Å¾Í+¾̀;¾æK¾û¬mZ©Ê¾Ï R@M±/ÂÖÜ+¨åÛ¿èë¿çÀê+Àé·~)¤́pqÜ Çp À<Á,¹ü¿ßÚ¾pû @Ë´ă`u$zdLzY¥,ÁŒÂ*ŒÁrË®.œ¸–»¶™»¹;Â:k@½·Â,|Â=̀Ă’k¹mÚ±ôÀ çÙ©Ê180¦½ûû½@́Ă²ûÂ+|Á竱îK™c;ºÂĐ¥c­i{¹>»®ûÂ-<Æ̉Z ˜°P D@˜̀`Íø;ă ¥cê¶dLÆÓjÆq+Æ₫zü¸|Æ‹»Ç‚Ȉ́¶d°3<_!(Ÿë`1ºƯúLj<È—|ȆlÉ›LÈ\ÈŒKÈ™lɾÀ±Ï0S€cK2–#Ö`Çxü¥Ÿ̀É~́ɵü¶³ÜÇ£¬Ë›̀Ë~́ˉ Ƚ,̀đ€ ¥̀Áø*½Ô» RD¡è Áp ̃ë®·̀£lË»L̀ØœËÜŒÉ̃œÍ¸|Í} ´2lµ́{ Ä0è0!±uÛ ¿]ê Û,Îe\ÏáœÏäüͼÏờ¼Ï  U@l~RĐ¥jÏÀ Î₫¬Ïøüˉ¼ĐưüϘû³&ܨ•ê™K;4æ'@qÆ`×̀ĐØÀìĐüL₫ËÈb¼É‹ ¦üÈ‚ăŸTP¥ü½/-Ñ*}̉ÍÓ ưÓjª±´:Gwv(ä0Ó\ͳL̉>mÏÄÜÓ¿œ̉ÚLÆ‚z¹á 2đU0 ÊШ\º·{[̀kÁf ¹XZ°°đ ô  Âǰ §L K€+º’ûà«ă൭ÇeƯ¶§û×eØg=؆MØ€Öh­¶AÓMA¤ 8N&3SĐ­kk؉ر[ؽلưهقַ€ ° ©¸»AW2Œ¡×j̀¾¢­Ø³=Ú¶]Û´ÛƒƯÙ¼Ú…ëÙ¿-­•ê®Zº´›¹̀#GtÚfÚ™₫-Ư¸ Üœ]Ư· Ü}Ư»=Ø‹¡{[ª« ĂP¥ædư ‘ú ´¾àźƯÜ}ؽƯƯÔMßđữˆ-ÜíÅÑễL»¸ª’tÜ`k°Ø ÚÛ­à ®Ư¾ưàÓ-߂͵̣°¥W͘ÍpJÆ?—]}Ñö]ØËß?»ß-áơ}ßÁß+âŒư¬ưá Y@ ̣P©́gëß-¾à=̃àñÍ✦YÚªüe»£­ÚË).â?âN>ß*ä̉zƠѪ¹2p]ưƠdÍ´c Ö"¾Ư‰ ´´Pá~\PÇ@ă eĐ&¸A|z{´aêÅC<åbâ₫ æCܦÎçS>·ŒÍÁXîh›€âúQ[óÜ̉;è-îä+îă{¥èØM¦iLÔ¸…3qü4fư0çu wçPnƯ—.ä ]é¾ưêÖë Ø¥y·x­Ä Ü½;ùàÜÄđ æœ ¬îă±́²̃äømé‚Né´₫¶ß½˜c ´]̃F¸¢‘U0æ¼³î î́ă.î­>éÊ^â'î̃$TĐæq̃ 0íÅä~î÷~ßù®é~Îïœ₫́éN©đ¬À[°áĐ UàʱGDÑ+QÙ\ë”Îîú]Ñû.éÑ®ïüNß…>Ă2€èŸñ†5₫³ÑJ₫í"mîđè>é·̣½¦`M³áÊ$ÂÜÁ€Âæ æé¾̣¯)¯ç(ÿ¶^´Ó+¶é]Ùx¦.\¨³ Ö8 ôÁûç]ªég ơđ@±¹ j₫ Çp ´éÔôÛ0éµkÍXïçU¯®`=ơVOơoơ³éûöêé¨üơU÷yoơR¥á0 Y€§&ê9xŃ¡Åđ ™₫÷‚ètߦ~Ÿénoùươ¿ù`ơ¿÷–o÷ù¡ß÷ßz¥¸9ÛPóÔÊ'ag§Rögóœ?Ä{Ö”ßö¨ïû“Oơr¯ù¢¿ñwú€¿û|è¿₫èŸüÖlüªŸúÎ?Ä¥‰àu ­Ç0Mg–7ÏS0 îíÂ_ưp_ü ¿öé_ùëßûQ¿üÀơ¼₫qï₫Ëÿ₫ư₫üöÿ¾^ ÏàÁ{ö ®_áˆMyçÏá¾ûö½ûçï·ăâ庅k`/x¿>)² É“!G„R¥I–%²“`É›$[ê ™̣×L•;Uº¤¦JŸ=ƒÖä‰ÓhPxʪxc'ñß»õ¦<ó˜Ë(ĐŸO‰æ<úèN›'ËÛ3&Ø‘fqÊœ«6§Y±:íÎüe0—×}=†kFeÅúü]¥ØÏŸ>tUˆ[ú¯Í±vŸÚ|‰̣²Î̀₫NĂỀ‹§Ï¤hơ¾íǜµÓpĂ² Ó—¯ß¿ï¬ey– W+‘¹Â…›¹×æè•Ic^mZ'rƠÎ× }ËÚ©KUÆ 7Å:܈Ăă~̀nʰpđ|WÚܺRæ̉•+mÿơ}ÑÖƠy2¥îiHXráúÙ§`¸Âå–n2è8¨‚+»Î‰–d¡çe Gᆡ‚Ü&¨"v¶YyäÉ©ŸN›K5äØú́.¡Üꌮí²±=uüÑ5ú”!†Ú[ 7&›t’¼!‚È¡̀\r‰Q>‹ª«Á¤¶́´åêl,́kÍ5›M iqœ₫ƒˆ"ˆH|rO&I<ÑŸWlñÅÊx”Hù\¢Ï¤8Ï4³Á̀,û²>œ`L*Í}́/ͱØz&=¯~a\ñ®¢ˆÆ#/2ôä©å9!cƠ4´ḉÂtÂJÉœ4V₫Æ¥\ơ 6¹ sÍ̃JÂ…‚ˆ9‚‡ü± ¢Ü¼©‚™<ôÇa¡‹ËWíÏ×́XJ)Ѽ %6\c£Ăt³Î™ê}Øy+­ŃW₫ø«°Ñ1ưëO;‚%ØËÏèêËM6Ư2Ö€É-I°¿B é xÂa† oÛgÉ«₫Qlt¦ &c}œàđ_‚W&M;Fµ£Đ\÷е™f Q̉¶ ~₫m.n #‘TL±Ü¶Ùê Œ+,7ºvûuaumíŒFM-¤™,`ư°¸›b=ém1"#Fy´Ü/]ve…ƠêIk:WQFÍm0oơ‚*è] úk@59-{axj‘g Wµs<W!oœ+x'Øñy‘G™"”.œ`¦`GŸÏ̃¦q¼:«)7 ©–½Ÿ¡=óäé08‡\_z¾rjyơÜ 7‰WyơBË)•­O#ia…ª¨<ùôZB˜préÂđaü¯Å%üq€™ Ëóđw“Wµik₫1È8ªp˜%QË{”àUV×:‚¼ },;̃GrÑAË(•«ó4œÈÑ¢Aă\ït<[`Ç#²À]-f¢»è9îy$$ˆ<¨§;À¤‚„"±Kt8[4‡cÉă\¢%áL IU÷êu„“ Ä|<ß/|ø¸à$‰ícÙ’^¼JB¢ôlW¡æÏr‹\ï´#XT±•˜¿=₫n‡;©œHn'½µ)8 1´·$Ưé"THϹ»W%p ÔS"#GĂ1 åi₫s£ù̃ÈNfPrºëà94fzÙ‰#" ¹°_¸í’[SÇÄs¯mPRƒè₫[¡ăz RF/‡5”#½˜Æ¶9N”s‰C²p• ăg̣>ă}Tˆ<w7@Mb)¯ü₫‰BdP/É$‹q^ŒñtxM‚Nt¢.‚™«÷ !Jïƒ;áEÂaYyè‚Ghª¬B‘I–o'û‚ƠKfT‹ŒV·se¥ÿuÖZ$Ñ£cåRqVàaÉ%ÈŒËIĐßr†asÖöèƠ½ >©‚å_zx̣Ü¿ÁăZ*<–*¹4C?Ê!HÖˆ]Yär'6ôâm5GË–àQ›œ́ßư6Îóy¥&á€g”’»'?æò#¨ÿèĂ| q…oÙÈצ:Å«|̀èÀb₫zœ¡“ èl_‡gJ0ö$§ưh&«YƯù¥1ƒ<^_¸¹¢4/s…ßYÑÛăÍịM›HE¢g1I‚¹×7Zú_o C´cª•ˆƯf¦×ˆđ¸©{›AÍ ¹ L%¥„“ø*~t~-z&ü2—ƉÆE¬ÑÛŸucz0H‡„¾ß;Øá2¤çf‘†ôăV9JÓ)ØmÅ3H\QÿiÎ~‡•̃5M]Hí°±ÍÊ£.Tè¼L¶Èq´`ê₫ØH=^çƠ±}ơss´sæ’¾{’E"B/tP!‹9₫oZ=-ä#:¯“jvo!́Û¦¦&Đx¢ÜPjZ6Ù%¶`­Kh¸¾M:1“Öåáă*—ûåđElªJxûŸg,̉}Ri # Ẁ"BX²¸úOj\…-@0Pf¢ínQN{(ºc<ƒÁĐ:"¨_3#.x\½§K*Lè!qˆ,¸‹L G™âzPD2áĐă­"…`ácåa:ÄA†\s£Ùܾ"¾R¸üÑDv_>é÷!G ß0»₫:Ür*yÄ"‹!y„U$˜&Pü˱®b=0!nÜ¥bºvƠA!‡>€›ÄØÍ¤@páZY‚úôóẲ¤ÅSAĐÇÓó,•{Ñ ]p2­M?$(îˆ<ˆ'»Æ!~‘ Z°‘qđx„̃`‡À7¡ơSb[A¡ˆó‚Gˆ;¸ƒZ=§<ˆ5K»H€‡L8¿ôĂ!“…$ZP„Pªơp‘« e(f£–Åđv¨1-?èjƠË>à³&+P„PƒHp„¢½̀Y°Hˆ¼;@…p’œ…¹<@úûÁIˆPpn‚ă‰Nxƒ7ˆƒIp₫2Ç…H°!As& ¥DR5!.ía’Hˆ‹È4ïÓ Ó»18²Yȃ>˜LxJEà¦(ŒÊ‘‡J°¿<Ȱ„Ó¤këªÈH¨…QÑ–‘ …<ȃ;¨7+ÉÈ@l«4T„V˜ÉÆqI8 ƒ=4/6 ‰;ÆM‚PhÜ›D(̀ºE«»©,̣Iœà›û1ˆ=8(»pœÀÅD³ÿ‰p€Ạ̈â‡c,€–Ôé“€CœÑzH Ê=RÂÊLˆyP„A‚r@è:₫ÇÉ=ÀH(„Ç¡Ó\„A HhMy€@°DD€‡º­ÿ3/Çá„W…T KèPÀÀEȯJŸrS)0®Ë>'Y®zj.NC3ƒxL8ËZèJ­xÀ„A@…W©„Ư<@>TpE€Y@…Ü„DZƒHÚ[x„À„Q˜ƒÇY„GØÏT°Ạ̈\„J`(LPH€„;ú¬…H ÏLØÅg°P„÷‰„ø$&h1©̣ ú‚±ˆ 1{9K³T̀GxL ú‹OLàOú´M@€‡APÓ\=Lp„g Ï\đ„]”S:x#£=T PX„ÀkÑÍT@€„Ç™ÓG°„;È„5ºO¦ú?'LFU1̉tN[À$u„<¨CRèă ‡Z€„Ü‹­T*Óâ²ùé áX=I•Ô)³%@™6|Ní°ô8±çdSTH…Â=DÑâÔB;¦Ÿ̀@˜¨E|WÁĂD„ú₫ÜÑ„̀ƒ1¢7"y@I¤Wq½TûÄ»Aˆbư½L„Ÿ¬DNxÀ¹LÅJ* Å*a‡¸ÑP̀GàRh„bŽA˜D@@ÏH¸ƒQPXó¬…U¨ÏÇ…>H…\ ×Sèó‘@øô,Ï?ˆIˆFÜSÎ̀ALÀ„:Ơâ1̉"Äd(|}Óß“SGÀW]QÇÑÂZ¢•„ßQK1¤Ö‘ 5C<6iÔ%#܀ĭˆP€H7v³®ñ3Xy(€¿ø+§´œ€(;ÄÔÇ’#¸¢¨’̀tă2΀V7ù”~‹± Ù3ª£jĂ₫$­PaÅA>¨D>°Äg°Ó$¥Ïƒ}TPƠK>¨뢃s³ÄNP„܃À­½JGĐAÜ+®…>˜G°ƒ]…g˜SK¬OX¸C´đ àa”pP91›CABÇHû…:¼¥öS]Ük]W¡×å¤OLMÔGHIHˆÏLp„ß9¦LƯEWIU| [€‰MÉE„HĐßK·NÈY‡ÚTI(«§ƒ >"†©³'¹¬³ºÆÁºm‘ SxÜ÷¡€¨ƒrÊ¡‡ÇƯ=ˆJ7fĐvXÜĐưÂ4Ñê/7„©àƒ$ơ¸Hƒ?MU€„Qˆƒx€„EØGÀ₫ÙHàƒQøSøƒƒº̉QˆÙ8°…EȃLX…H8LxƒE([`ÍH¨ƒYÈ?PF…K˜H`MP<À: … â ́!†Î µN1c’†̉ƒÛï“Çуt[aPÍMFđ>¸„:X…QÀƒLÀUÈß6½8Đ;ĐU°UĐäQH„pˆ‡Q¨Í9ÈM=È„WˆY8V8 ÓUÈ„<Ø„9…Tèy„LÀ„8ˆ„HPDđ„<ßs¢T¼Pe¶Ë$d1Û>æ/́eC–É»Y>Đ<(P€ƒ9^M¨ƒÛÔ„LHSˆF¸=(,]ăRÀS₫…A°…p°[Sh(z‡A¸yzy^ăU(7håKÈd_₫…„ädM­̉ƒ9Đ9¸<€Whpˆ„>çR`ÍJàHĐƒH¨„áËAO€Ù: ̃;¸:Pøƒ9xĐ–H"]9=±¢„9đ›>éCA0¡yĐr…„C¸hW†„Q¾åLX„]c•Hé7µ/îß>°ƠŸ…RĐƒVÆdsé+éK¸gK˜gqÖFk9îƒKÈM˜ƒRØ8(…QÖ7đƒE°WÈ1–‡„®UU¸ƒM¸äHˆGX„D́ûAœpλV₫í¸3Ѹơ0íØE‚zŸQ(„V ‡M†9ˆMèx^=Mđâ:(…+u„̃d([È…QàKƒVˆ„9ˆ<ˆh9…ç¦gÂÖMpi€•â6ÀL¸ä2NfP€å>fÅ‹„7pl;ĐçH°ƒïöb:H…Jë@¼f†5Ơ ëë“KË´wăf‚1GĐd΃”–ƒMæƒRhyp<øṇ̀l,>ïd¾̉YCđhÄ₫6ê–WÀí6 kRØmM¸W¨8ˆ„C€zÀƒ®3¨BPÇñçÿNhz ‡ê¦„qNg—çR¨Wđ8¨¬mf̣̀ŸƯJoŒÎGY₫z¡:çâï@h[@hW ‡„—z¨̣osázHè@†¿̣yØ̣/o„¦2\Î 4!ó¸Ø*\.‡¨r.¨oÛhʇƒJè:§‡tû6o+:H«~›HÏCĐzßưÎyàƒÛ(Oøt^nåänM(>đ’öçDÀ9ˆc…^MXz0„¹îp0[åb77À‰)“NêD.ëÄN+yṛ=yˆ~îg.¿9đ<?0h&V{z€FȵçE‡­îƒR‡̉dbp‡{ÆíDh₫[hS†ªE@pyPGĐƒ: æpÈ_QØgb{WÀÔ\ ‡>p8x-:¦ \¸oû²fyäéYe ’£A¦à5¼g(Q₫j /^.x¿T‹ ·wÿ₫íóçïŸNè 'óèÊ_+Y.µ%/œ̣f­c\$H®đÈĂ³JÏ8m"]²8h”c‰#̃©Tp½À0Q́ĂÎEå̉è5­T€<1ÉSK°¬¥Û ¹Qñ0O°Ç@8ijW.½d /Äœq P<₫5·Ó;ÿ è«#ůJ¼ñN-ƒ’7U•²J"ô4x ”‰d¶©ß$}ˆ’"ap É<ƒ8ơÊS̃ H £àƒ<̃2²ADâ[ôƒză°~)¥8TXô–“µ r0kÓOöqa…_L1̉Jºă4̃`¢´“Z‘>l€DxÜx€Å ôY€U3>h¯qQ”<²•‰°Æ üÈfÄsŸúÈcƒá%²—UpçH(‰‰è~qS1§ƒfä >”!Ñu'DáJA@[ụ̈È\$₫P “€Â›(`XĂHÜq‹ˆ! @äâ´₫[ÊĂ q‡½¨"#‘à–%ü§>ôôxÜa ¼¢¯ÈH“ =²d¶€ƒ+äFY  ~àñŸ' a h9Ⳉ„#ü@À’U7:aK¤"²B́%uÈâw¼(X™<“9́°^vê*Ö`•g¥àÑPôBđ¨T8F%z¬Â$s„ .bb˜øƒ÷‘‰Z V©̣ˆJ0ô«-ú@Lب›ÖÙ#h— 8"ârEÈ‘ˋë/#ÅÛ!æ8»̃v ›(éŨl”̀1ª9₫JÀر5•’·Wå‡80y˜ë”ñ(€Sè€Y«¯ǯ̉qôêv ˆ₫|Ơ€yäÊÓ¡]`ôÂZ<£ •zÁ±»z˜×\â ÀDPPùkV®È®jE§I)*a]‰Q êd9ϱ‚tÆ•àB‚aC‰ ê×賑xÅ ádCH”â>}8̀Á##ïuÆ]æl<ăYÓÉÆ[ḿ¹n§nGÉ(ä₫08¼̉qh"3ˆM3ˆEh‹̣ô!‘ẴđŒQ‚iµˆƒ÷¹—’bC̀Ă1YdëxĐÄmbˆU¼árx…LɵÁrĐf‰ù:ŒBå¦7̃wˆ§Đăé‡,ä.‡ÅŸÄ‹¿ÔdRr”Ü$'ÔŒ35‡̉ªlëô·+ Lß`1i@± Xºüú¼́¤ †‹₫8dØ® €E…<́‡¹8€±@RRŸñB®Äku†Œ‚,îÉ̃D²¢ĐĂ(´^´BÆĐ-p]ÊưåÂÈlÈ Â-½RæỠüA×a^’"ÄB FEØö\‡Jđ$›®i‘œ&´X£5ª¦lT =¬×mªÏ8観́&ñ|‹f`Më¸Ô©‘ }Đ;„Đ•É-L×/ĐT\ç·d§¸Œƒ{ñZ†Mé¯ôÚ¶!SĂgq¬rLtü‚ŒéK’v‘<Ä’S~Ö¨k¶æ|Úg}̉çœ>Å>µâfn¾©ƒ(¥&íõNºpg8\ç–v‡¤ÂJ0`21Ÿ›Eô©5•Pqívȃ,ä́–JmvFi¶>Kj “‚èñtjo:₫h¥‚©<˜)„’‹oJª{¨ƯâfÔŹ^DĐç¬DN=ƒ«N¬qfuÚHXƠ‚y‹=)«°Đ 2ŒĂ¨O±ñ|.µĐJ­ŒC=ƒ @7][JLEÏL%Ç^‚eo\ăÜ ¾Û®́.àKïKîJ˺è®đöî4›´¸#° ‹´Ëï K°-¯¬Ho‚ÙX‰ÍDqX?é€ èNøCÇMÁǹa*ÈCùÂĂº ïPï°đ.̣./ñ﮼ËüBoñ&/̣Năñæn₫₫nüÂïí̃n-j“µ¨¼JO÷]fÆ¡ơ´Q»juàoóîS°?ïñJËú oû^.₫₫₫oṇ̃nîîïư®ËóÀéj0î./ûúî Ÿ®®ä‹ñ!_»̉„Mà„œ}í/̉™¼QÊ ß®ó 1ơ~î_đ¯̣Fođö/¿¯Û/đv°O1'qëî­̀ÊíÎ=zQNµkŸ’`Ơ”QM¥`v­`[ăKúNïcđọ́ïÿ̉±K°ïº°ÿ*ñÓ1 óîî²/ß =x“³‰̀!É­ pođínûÊ _n{0&1›0?̣@ “r(c̣°Ḥ»P̣­̣ú̀J ‡²°Ä0¾́Eù¯§ôK#±Ä.•Ê©|o E0B'₫Â₫^@°Û)›¹K=`˜€ Dµ€-$‹—Ă+Ô ± 8Đ/·n ÊB±˜«@Ø}mă¬t®¹ÀK½t£´PXxl¯ƒdLoR=Ă¿\ÜO¼XŒ)L3}Ếp&² đ°üú¯%ă‹;/ƒpĂoĂñîâ²ụ̀èt ›Á¡ƠôD‘î0’₫d 9…Ä.¾H/{0Ïqë±qgđg´ÿjtÛÊ(cXv𨠉é¼Zê8.wZ‹)GË́:çǽƠ¦Q‚¶åơ]ïµØË è…ª¾µ]÷íÅ]ϵf§¨ Ê$ -_ÍjÙ vêÄs¬‚j¾âµk;6c3vÆölÇvp¸5n—*]ïớä© e6fçgf?LƠ¶¼~“ ©0VØ¢D’ú0ÜH7¤¶Áµ\Ă5p3`păơc{7d¿¶÷0à^“·x·ơ¥¾Dz“ Å’ºµơéŸ.§À j¡6̣ yOq_x÷7o|wáf·ÈơRÔ-f_f6'xv»ơf¯· ~ölK÷Qöf&†çÈ́₫÷ÔÂ*Pl|¥¨U(ÓS$ê,ä99E.H^+8…ä±̀x„æS¼Q°íÈí¤ˆ{Ïvœm[cíRÛBv‰ëØ^”Ü×ef×»V0{4^ ¾±¡©8(K–Ë(´R 80fƒÜƒo"9” c̣+ zQË–«¹—RX2xkƒS´í¤œ©Øö¨bëÙºúRäv6ǿº¨çˆú¯×Zo.₫ÏeuĐ„]¾|@¢,X2đr±1.ï<²)̣̣ê ñú&X-$îê’qfBSwæ+–áFPLlG#­;<€ĂK([o»7½·;[·»ë°{Mäû7Å.ø;¿ÓXw6±@ƒöÆ 65e øz•» í|)öJ¨Ú7a¿7R¹ûº÷˜S´BU@ ¼Ë‰¾ƒ|¿ÇÈ7Ó¼ÿ»Ës7^ƒMQ‹]€RSi+'ÚeÍf®Î́BpÖ~ÓÇû»’¯ü¾»NÊçÔvxMvT‡Ót¼À#}Ô³üÔư괂Ӵ±u]~vôÆT́·ÆóKöÔ¤ ·™óñ„÷äQ˜₫…ûÖăö{Ö–\̀S½ë;Ô³ü¿[ư¿ÀgWÊs‡Ê{üÑ|Ơ~̃‹=¢Yb} ¨ ÇÆ” Lj¯Y­Q8wL׆3₫7-¿¼̃oÇЇ¾Ô“>Ơ›>ßç}á§~é=M”-c†£Đră¤"Ï!~_G¦ä”ÓüÔPͲ₫å.7kÈNḾ¶Ơ’Ø>•­cKh¶µ-èl8jWóçY÷4L¦\‹>±´Lr» Ç’Ê£Ê0ÿ"«³k0G§²2o±1úÊôjqûC̣ kr”²°1&Ṣô®3(P àÁ  XÄJ4HĐ`yđ8Âûå₫̃3¿H Ǵ»}ÿ̃íóÇ̉•p¿p}ÜØ+W®åơ‚'¯ÖF‘¹D…g N¢J&MúŒ)R¶jÙÚ(ơè/¥P“₫ºÔéW®¸ÉăZT̃ÔZđÖjưIR¤É%ß̃ưû·¯¥¿—vï¢;B,Ç#Av́¹1(G®u2æ(*W¤§’ÅE—بNÁNå̀ƠóÖ¨Am!…'«#ax¸:ú|F,Ê>vSç"Ù‹uăŸđèÙZe¨m₫XxÛµ©wotß~ơƯÙ×ïWqu³úEÊÏ₫¼₫ó<*é$*Tbé}øZÁị́%½ö9B˜ÀT T8ªå¼÷ü«O¿<„ï'ù>d?ûR1ÄùB¢ ¨ Km<¡›ºtÇơY©®w¼)#œu»CĂ₫û©,R|’½÷TtïD­DñJáØḰÊúdA¬ºL*^Î;‹ º₫aÇ®½dç¯ÀVKrF *«–₫8 ́ĂUô³Ëêøü¯Oûâbq>¡äƒrÊêªnLâjŒ¤Nª‚Í»{GH1Âñ‰N$Ïüi-yP[‘'BS5©>@»4ôUúbMQ®4¤ À\;²Gïb'&9SC²Î£62Å‘ậ₫äk¶·g[Ŭ̃lD[ yc<äѤâJÓC✣֖p̣LÖ;úÀă'«Â±EÚtåeRæcGH“'°yåñ$³V¡'[-ËÊE¸ơØâHĂÂt"‰(yàº1ÇẈGG•àl×ú.ê—´x§ơNí-ĂRùh-[¼z̀ئ¬*‘J¶RÁ¾ƒ¥mV¸̃fqΕå2Œw¿›EÜȸW„³ÎJyæ¤2¬KAđ¬˜©&¡æä(½µ84+Ö²A ªT%åD´Đ)•”¯–ơ"₫ˆá’Dº‘._]zIGÙ¤9̉ÔZyxl=¥4ûU@í̉Ơ@©M,Æ/ô)abc₫§ m+)©̉J.¸\â₫ɳ›­¢Và«H£GV`̃©(íØ| Â5ƒe¼t·r#bïK­ñ.w/lxàÿ½U /”Ú$b¤¸Ú¥¥¿kAô™­ÂaScT&SÅlä½ßMOeL-=#°xXíó/đ8̣ Œơ®}z¾êªX™pwJTºÚ“aƠaÉOV²̣Ú¢RsÀÅ!xª‰©¢§ Œi}u‚QÚóŸÄc$F1 ¸Ñ7½ ¨/qẸ́ø˜ pEKkĂÍSĂ ²/ḶVøØĂù4i€äƒŸ#8™­T’[acQ©\œd ™JwX™PL{Y₫LMÜz¢ñ™o€9œO‹ØCűˆÅ ­ôº0+€6J“¯ØÁđ0!+‘-2qyÀaô˜Å(‘ ß̀âKÔ„"FYl¢yÈÄ(́z,¢«èC" ö M烤-<чQ,B™đÄ"䑉>ȃ}Hë<ñSÄ£}đÄ Pg Gˆ”‹€$đ źu£À&D’ ‡uÏ#›˜[B¢û5h/lÚ:¨¸‚„CÛÉzVA‹‡‡C¿…Å~qª…m<ÑĐ{Äf–Á¹'ê©”p̣ŒxPZ¬sÎĐ#¶¤ïáW¹,#A1%Đă₫[°Vc“©ådœlé]ytEF2®Pœ ưø̣cÀ&ï‹>Œ\EăŹªé.yqS AöµbƠÓ#D9)ù7£5ΨJ_| {*?üÔ"}Ú»Ṕ.§ÂœGiÁAêùÖ2¸ZLl-æ”Ñz,7†­đè…ײó¼½tGC*̉/È“«ƯÁL¤l«%5?»ÊƠ'SHnă3ùµ¯rƠ«X%E×Áê•5oéÔFQiùs„̃!! YH€ë]NGª•’xEwM¬+¨̣*ZPt@M̀«Ò—À₫¯tÍ+aK{NÛú®F¿À›̃$Ë£!Èkm+àHX–´,I₫^][Øà¢µ4qmc`+Úömm]+X́d³•j IdV’pjtlZ<âA”3Ùf·kj“ÆØñ79q/t2çz´ÂפD—­Rpkçª×î®ö®¦µëq›kàĂ*X¶Îå®v»k`ÿ*u±ŒuÊ€,E M/Rû¾9²‡AŃ›;®h¹+Ú¹¶Â¬îfkàSØÁ20` œƯỜ–,ºĂjÚ¢̃¨ÁCsäKƠªS=yl˜„i PØuÅ"0!;¬T¦)6!É;`b•pÊ@Áæ;8"n¨E™1QLŒ"àƒ#̣°L@ÔÂx„₫@A‡T`B˜ Ó,‡E bj‘àDl1;àË|ÈD%-‡U`bh!ేNÈc¿đ”`ủ^eŒ³‹Ḉûd[—Œ4ưl]“¬±D­âs¸¨§iV¡€Y˜„Ÿ³x”-œg$Æ;#Œ,¾Zà$¨Û*“̉Æ_[@ÔQïêÄ×J5ÏjÍZ°¤ë5î¦#c '[³ăíVJÇÙ¥«9“HW–¶Ëm°u›ˆ»üO¤đ Å3S·‘¾”SÜ9aß>†Ù½Æ;̃p‰mD[oœTjÀf^ƒüàĐ̉øäÎ5¹sö ùή•‹Âh³VÜ1l=¬)•9q₫!l…×û©:wXbÓ™”VpÏœF©Üó´£Yß±sR¬`Ç»ÂÏ̉pêSÏpb?›a©}́oƠúƒdçH½ƠßÚt½ËÚ¤ª¾ºîÂ.v¯÷êÖá/̃Ç>÷»¤à¤{àçäm#S-Q»¦Ô?9Ño±‘ü¹»^ùº_î—ç0æ)ïw»_º$© -2w¾«f¿l¼èÄÖKµ2Àz¾Xû:jnzÀë.«·ç{éGnû¿çưó̉Í<ç'?y«K~÷V-[ŒÏ9ºq—5Pd‡‚đ÷nÈù€7§¯±|àgßûĹçßù¾K>¡ƠưÔăK;`é>ù­S-@Ñ₫†6`â'ƒxĂÜ y¼Á́@øl¡2A2*₫o₫àDa₫Hú`ÿÜ@ú Ëàø@0!úààËd2 äa—Ψ¸(¨ˆŒl6"'¾¸±ĂÉ ¹)ú¸ŒÅv 5¨₫fP̀AA`Jídc̃¡nơª ˜l$9iF•a‡•Wù]Ùy-¾d¬̃È‘û8—9Z)Y— 9.°Â*è¡j̣&©g¦Ô²`ơó˜ö8$Ù!92xY–Eb’‡‚¥YƒÙa§?¾$…Kå—c¹(z¹•!yŒw"›™Œay‰"…¿D‡QñÔr/~xµ8ˆl»]Ùœ Ù¨¸ßù‹U[íÄÙ•wY–×›W9uù Ù™¢%º)ØX¡q9”A%³%̣ôÖá®A Æ9̣¹Í™›Ưv.Z£µù&ăÙÂgP₫ù¢'Z ·Ù¢₫¯Ùɰ"Œ!ă)´øôADYH¤€Smí¦:‡½\Á9C wt˜Ä«×0DsTq³úªÁÁ ~´7 E ÍZ̀%~±Ú9×8~«Ÿă­‹CHŸ…hœƒ9Zuè%‹H±±"tj¨wG̣¹;*Nªço=h!æ¡t4 ÅÁCçAâPê!ëA~ç€ÁCÁÁ `œâ¡Z[³ƠpèáµÅ¡4 ÀZÔCÅÄ¡8[³‡#éáb[~›EµË%¶†-´*Tđ­j$ê6¯VŒº¥!ºº›Û¸bà®âxaUvêœ#úŸeÚ₫§·;.`ÚX‡™aŒA%°Á!Ùü¢úùĬ¨ư» 9’)º‘où :§9À3º Å锈d£Œ¡B,)ÂĂ!”A8Ä/9Ä¥µĂ1¹Ăá8<ÅUüĂAÜĂ;Ʀr¬ØD’™È>¡ÅIœÄE¼ÇG\ȃÄœjˆÜÅá9vá>\Z=ÜÈ…œĂ•!Ê‹ÜÅI¼Å;¼ºăXĐáÆÿÁ¾s̉.n<”±Á.JĂWœĂ±¼Ê×üÊ¥Üͧ¼ÍĂaÅ?¼ÎŸaèÉEÜÊû¼ÄáœÏÿÜÏÊC©?À\/*S`+tÉtœÇă₫<Đ+ưÈ)Ửa<Ó­É3ÈÆwĂu¡HQ|Đ«ÔO}Ê7=ÎSÓŸü’_<ÉÍQÈa ¬A"óù‡Ù0ÜĐ_]Ê]}Ó…ƠYÏ<ËW\,‰ÎíĐÙüÙß\Ơå<Ú©=Ä_üĂ?\Æ…ÆmœGØÁ4€”a–ƒĐçÚ§]ĐƯÚưTÚÔU:ÛSœÊ;}ÎƠÜØñữ«ƯÍwª „^¢„:…átë›ex  ! áÏ÷|b*á ăçW2b~¾ă₫á äă"â/>ă#"â#"ă/¾:>æ~~/̃E« ©éX »₫÷§%¸I{¥ºCp¦µÁaD[³â|9»µ=”³ "dÄPà±kTH‰T³ÅA´§¾‘Aµ)"v³å·[»4"ˆÔ9ØWjæA}‡´Y hnâÖèC# ²øÆB”aÆAè}Ơ ]ß=ñư¼đC|ÅăÆ7¼ĐUœßé¼̣ÿĂ›ÆÇÁß©€nY¢nù&O¤×3ÜĐ‹ƯW=ơ#ÈK|̃K=ÅWŸØƒƯØa]ZŸAÉɬÁˆ €ÁA„&œ“Ÿ˜ßù—Ÿ‚!Ÿ„¡ù•¿ø“¿øO™NyÂ…AÁ€¡¸a₫v®.Øa´ø!ú­ÿù¯?₫çßøåŸ₫íù¡?ù…aú±?û‚1f3h° Âƒ $6̀1‰ÆŒ ;ĂnŸ9ÿ̃ưû2¤H₫Jú{çñ4vT†‘#×P`L†4g:¤y3!A™…Û‰s¦Í¡A‹ l¢ÅÜØưÛ÷Î$Ç‘T?úÓ7ơ»wÜVD”L˜Q¢9É[èÎfb™ùdÖ́lY´së’MÛ́ °fäŒUÙÆÛƠ©(ß±ăÖذfHé.” ÙqPµ‹%ÖṾÙÈvÇÂW 0eÍŒ«ÑÔ_?~ưú•üwƯ¶Íj́Œ›³nƒÂà2 ›₫p AÉÁsç‰<¸Lfä‚á#JṽÊ<Ă/»ö́¿¶sÏ ”!Éf |đƠUcMtÜVË wµÙR¯ !pQ® çzKµÛ‚Óưvá Ë{-¶ôAÅ6(Ù́/ÎÖ̀Đ LÅÔ†>øÜ3l÷ÊƠ ±q&œ‘“üùæ­w₫-̉Ø"M¯½øZUkª½ÆÎa±¶œÿ:ñp]îÓ`1·C ơÊÅO<Ä+‹.üÏ×sŒ†{äÎtƠ]Çèv8~§]-"gË+̣ÀO.ăW^.µ”×<«d÷á‡â§¾ ¨#2ú Ô ü¤b<ưkP+̀ă@ưƠ"¶€Ÿ<̣§Áç}đ©ül•Ƚ₫ˆT4’“<åû@h”(ïœï;ÂÏ,àÁ¤RüéO(Œ¤$ Ú8ÀÎħ(qó‡+8€)5I€’AyX U"bŸÎDDˆ>¬GèÁ%z˜"‰?¬Ç8ê€üĐ̣08ĐCó=D"Æ&å¨ü‹ K —†‚Ùừx®›˜º8Ö1ÓìÈBǰê5²‘#ÁµN .1ˆa Öèˆ;J‚•Èydr•»\æ§IØm[¡SÚ&…§E dc¤,¦[@X úѬm ÷ Ç=Đ£̃±ắ@G5¯iÍlb³ è₫f3ª™ÍV³…Ñ́] ›ù̀Ăè«OÙ×T̀yg¦S›ôĦ=ë‰Ï{êÓ×°€7Á9Îpæs û,(ŒöAMj6åù6ÈVTJçîèH`˜YP‚j4£g6¹ak¾́Ư¨IKÊLf^#³âˆÙúÑôË$”ê]JçỶœt§ûô¨=¯1v\CƠ©QyÔeZ“̉\&SÙ±—Äùø‡5¶Đfu«H5jB:Tkj€¤]-+W9ZÎs:ÓÛÀ]EqÆÂv’´©>5«]ÏÍo¢ĂKè2ñ Xó«„&Q¿ñ¨£#(ñàx́Ñ|å«…₫‡̀s!ơ<ĂÙÙ#¢æ—£÷iG´%|Ÿh‹₫Ø1n¬4Mf2“ăºä"·%êàÈLKâ¨êc̀ù0²•Ïœå4;YÍUFs•“’ÂÈ0Jns–Ư\ç<Ÿù̀TÍG?Œ̀¯̃Iă*‘YL§Úb*Ö0ßø±ÙŒçG¯ÙΔΈSà;‡… "]ÂƠ8̉…1ô…_†c˜Gaˆwch†^H†bh†h˜(₫ixs8̣!Åơ!$b"AÇ"âń]5²…ww>g#̣æÁYĂÅ?̃!?î¡îaw!4¨đđëîŒÈˆ̣ƒ–8?˜‰ØZñ1Ybˆqr‡‘H0ÓN“Rxl7h‹³˜~Kè Ưg„·Ø‹!±\áqç{'q¾è„¹xü—|˘ŒMÈŒ+fŒAŒEøO€Bµr¾~S!HÍ÷Á‡‹)$Ê8…ßĐ´X|Óx‚Çç€́G‹fÓ€à˜óˆÊŒÛ×}́ø€¿(.X¿—ªÆ~`Sh€ÓH…Vиïø₫‹ÍEéj¼ÇŒ̉‘€ó÷Đx‘À¨ƒ‘ă(Ô‰‘Ë’HÆy.V)y’I’-ùÂè OP“Bˆ%ù‚Ư}&®AUh[uwK©†3”tMé†p¸†S ‡Pi•gȆnø†[y> –(œåsI™ xø{C×B}È”X؆Ûá?"Ôs₫Y¹pYđpG†˜ˆwÙ–xiˆó³>uhBˆ˜r‰–yi~X"—’˜|HùÆ\Ø€> ”ç—‹íH…¼(’•‘Kx4命’3c‘8éưø¦Ù’4(Ó—Â(”₫b(D´(.&_&„¨J˜9›²₫éÂ9”éç VX·y„ÁÉœĂ)嘖yh_öHœ>yÙÉœ H…ë¸b1XœÎ)áéÆ÷’0É~׿Ùă‰ÍIïé₫G…WX̣ŸÚ9Ÿđé“ă8Q/²›ÂÙ¹ŸŸü9…”ÙW ’øé úy ZxYaïGf£Bñø ü ¡*&ØXWÀJ¢úŒÜˆ¢̣h©¤T¨W˜…̉U•ZÙ†Yy•4Z†9j£T©£=ê£Ig#b[Æ%ÈE–ÎÇjÏ]Kyq]˜˜ªB“5{„!¤”Ú!ˆYzsÛ!ˆWº¥É¥a:ZgØ¥‰©wé66₫ª¦ƒ`Æ¡oêÉG+̃ ¢Ú¡j~í™B9 zj¢JœÜÙy§pZ¢̉'yˆ¨ôè/ ÚR¸8‹ZƠḉàƒå˜#qdÓX“º¹~qzh~:¡ä©œÊ"ü"‰©ư9ªT1Œé§j›Úª¶Zµ¢›»Úª½g©£ ½}«†« ù‰‚Âêª1U¬°6¾©H:›³¬™Ú¬z«0ø~'Ñ j­Ùú­(6z€ĐG«ư€©Âz­¹™­sê©Ô¸¬é¹®đY“5éjF6…̃đ¢8R¦åĂ£Q‰•gÈ£;J° °8:£2…="©h (B|Ÿ‰d-ô₫Bá¤7â¤ë?­[b:]Á•°qHYR™£Lj>3dq‰ÉGÉåGiï$»£¬ë:QĂxt:¯́®Ơ·‘̀¨j0%›ª®à‹â˜̃Y«Ê­̣ÚăZ€ă꟫*µ%ñWà82 ªy(6)ÓçîçS+¶cK¶e{³úIË€h¶m»ª₫›Rتڪ·µn‹·yû¶z³̃Y®z ¸eûŒñxª4£›PQ)è ©Ë¸ ù̃đ-帕¸Y}ˆûÎÊ®–ë¹z‹|'ø*̣¹¥k¶HúăhÍw®1kº¯Ëª H…“ ­÷»x»¶[»¶ÔxJ₫Ö¢úª N鯋#%Ô…Yˆbw+Yß¡¥Xʼ%½Óë¥ÍK½Éû±_Ù(uh¤)²ƒ›«ih¹…Âûs%k#V•ké•]ù¤;£P°í»–cX¦&²²ö˜lûd¿W«·{(ˆ®Èê¿y‹¡¹ºBœû‘ܶacƒ*… ¼À'/ơ¬ùÖ"ƒ¡W±bXñµù¶çeǘ‡•²»†×³ïôÁUų.ơ\À̀y/ÜÂ1¼Á3\ÔA‘ ­á~°èÂ5,U¨ÄùV˜~4µ"J¬†7UEÜÂ6¬Á,ÄQ̀bP,ĂS‡È¤è̀Ü‘”Ë Í‚¼Xú̀W*ÍÙl½̉œ̉ÛÍÛáÍ6§áÜ¥Ö ˆw9BzGAÇ ùñ‡hy±_ªÎ Ë÷ŒÏd˜½̣›–»¾hÈ`º•Ê˾}Ôw”b€ư€¸ HSNÊ¿<₫Ä0UÀ¹œ'± ̀¤üĐÉEf^fîæŸM ̀¦|ÈmÈÌy[üÁ¨æÅ·̀Ñ0]Ë=ËBʇ¯¹̀É@xe•·B́`c{/W|P,qï1zú;ÍÄ[yIfxRíÔQưd̃€|,Ô–gÁOMƠ+ÄÓP=Ơ­¦ÄF Ë…K3@¬a­<LüÖ¡×±èƠdÍbỵ̈NQfm Öuí×Vư×c=̉U x ‰Ö3ƒ›ágLÍ{ûëÖOÍ×r ÙsíØp=Ù—Ư"Uµ \¬ÁU-Ø€ ÚŸ-Ú]ƠX†Đâ–‚Yae®QÀMÚ}Ú¯-Ö²ÍB¼×Ö¢+₫à –ÊÖ”ÙtưØÁmÙÂ½Ó (…Vf ø(±O´Ö_=Û°=ÚÔíÙ–ZU²ñU<“̉íƯÑ ̃®mƯƠ?xx.ª Ø–1*Љ’”å[½Ïß̀+ßælßơßôÍ!)Û! ˽â½̉çĐ aiâÛ̀K½ö½¥^‰àó­Ï_J² ^£èÓ•~¦ŒÉ²T0ga­QoLµ1‚ÙĂMâ½Ơÿ°ØÿB‘áÛă=Ư/®iÖØyÆ ÉX‘JàXƯ/₫Ưâ ƠŒÔñÇûPØ<¾ă-®ă±™¡FÔ×÷RodqơÖ> Ô€§¹lÂÔƯđ­AÍ»Û×q å‚ æ₫•­¹`NTĐ̉KÚONæaîÔc^Ä¼Ă½êyưéælÙn₫åbÎçvm6Ô‘ƠB~â-ƠñWèÔmè’-Ö†Ư\ăέ µ_ xº;æỹæ—né™^é•NÔµ½~üÁ] Ơx>ê¥mê°Mê©~eíDƠP9TÑèN<±À}è‹è·në¹₫Ơ-Zåƒ!媾çõçÁŃẽç|}í‘‚¶èzƯ¸^ëÑ®è̉NëÓÎƠ8̀Û.BÁ‰^́zńÂî.₫ỢxPÑÉáp"êîëîîéïí~"ó¾î́ï÷ïù®ïñ~"Ê`ïÿ¾ï/đßî_ïÏPïÏ U°₫ÛàÈáÉÆàïïnïOđï đóîÇđÿÎñ!¯ï!Oïê~đ́ÎñüṆëÎ ÆpĐî"Î.ƠâÇí›>́ßnÂ=^ÑØËxnóáóÆ.ØÏÚØæ×‘“̃×>ó̃Îô—îăZƠZê@ßô>́_¼ä ë2Å©?=+Èè{ưSœÖ‡mJ;ªJøg˜³h¯}mO€n/÷%}(¡„<÷y·y¯Äyï÷l¼÷gÛ}c÷Oç"Ifoøh›&˜P±‹/ùcÏơ‡Ö|”/ù~¯Áÿ¢™<œù3ë¬RÑ/,d ß`¶1·!ªÏú·Ñú«ßú®/û³Oûµ₫ya Áû¶Ïû½Ïû1û°¿û«¿ú‹gà8ç·XđÇ V` »ïûÄoûĐïû©_ưaÁ` ©üĂ/ûÔïú̉/ư±oưÖ/ü1a TĐ;µư²Z}…ÿªSÀư½ŸOö˜¯}úøđÿñOàÀï¾9y÷OŸ?‚ >„QâD ¾ṣ-¡?†ÿ:₫KèÑâH’%Kd±‘áGY„SæLßl¢²æN=}₫¸̣"ȃ7ETiĐ–;&l¢1äRªU­dha©WyräXđÚ;nb– 9S…Ê*kÛ¶e ÷íܸqßÚ›Wï^¾eŒ”₫!¢‹†2T¤v;…ïbÆ{Ùâ• ×.d*g̀  rMd×°ÿ¾´âöñèµ#S¾Ûرj*eʈ)¢Ë ª!£N-:̣n·§á*®œJ•%J¸±Û÷n¡×‰]]fơ†ùtê6qê¬^ưo —$ø2ûOƒ-° ä<^ưU®×®‡Ÿ¤ó‚ÑC—Ÿ_?øÉ3Ư/@ư²ÚF:ú„hŸ¦Đc§Av®¹¦vĐ¡pB ѱĂ 7̀Ă ?1D?ÜCk2+QCGd±Å -́°Â=„‘cd§¡̀ÉÇv¸yg›ăYĐm†¹¥uhè“Y6:h¢Mv9i¦WƦ ‡ÈúYhz‰n¹Y°Ç–́››F:9•>[ ĩIC#xK ;ç¡q>:Ǽ™¾»æoW[¡qb©jwÜùơ0…”MN+fî_ộ̃‚4-Uc‘îíÔ 6ßéèèđê´|q£"-=uô éû@ç\ơN;{Ï̀e'øÜPo\À̀W2‡#}̣ÑG`É᥹¥ä§=¤æzéW‰œ¬oùE©?·̃Cq6~éđÁÿ7¤ª=îêâ­ö8ú₫́¡_têø£wßæ÷ÁWü¦+¶9}nă½—Úô²%@æ¬)ÂS–?̃q5SÁç#éÈ7́ƒ»́(pr̉¡ ₫ó›®a¨{`2¹‹(pNAÜswÀ‚́Î)±S¡^Â}`Dn1dYèÔ;8 ê9añÇƠÔ¡9"ˆ>F´XuôÄ‘¥(;b¥ˆµ%VÑîˆâËäá™kñ£"ÅX¹ÊëO LjD+†Qs™Kß:†V5F1+.Ä!{<‚Æđc¹>́h0̀#P^rBA&’`&́éÈ7u„#ïˆ º(Y©â$’́ ÿ±Î¤p ¦d₫"AP™—„%le²T9ËSÚä3Nà†+]r1¢ç•¼”e-™̣(_ê)AœÇBxl‘P°¬“&û8̀X‚ä× 0¥™J² QaSA2³É¯m®²—Öç.[w» ÏwÏ 7>¹I¤˜ “°ó#<2®ºƒ%9̣GÙN äj hC:Jt  ¨A#*QJjÍ́)º3z*E”dIH™:Ê(¡œjY!mäHí´‘â53ƒT)‚\êÄ ´´Q e-¹9æÔ§=êO…ÔÖ¤•¡jR‰ªT¦.•tÇă©S›:U©V=dÊĂªJU®jNYûđ‡₫ă#Í≔YƠŒéLV̉nạ̈"UáMôQ®­ĂemŸ@çPA£ í+E%PôjlD[PÂ6´z₫HG]A§Qô‰.­j=êÁØÁ‘|Lô²û!—J̣q“°üơ³ña¥JÂÊëiơ´ùÙ¬đZ·9B‘¦çˆ‚âC̃æÖ·é­@Ü߸Çà?Q—Ơ†7¬Å ®q¥ËÛ₫ŒÄ‡¢ôŸL‹Üèv7·Ơåîo-hCç`—ƒÓ…nz‰»[ơb \\í°̣³’Iơ£Gúz-L,–›H³•ợÑq‰ ¾cˆ×êX‚¶S°Ơk@!:Å:x‡ƠëD₫%ü¼Ăf<<éåW»/T ơØ¡M̉ÄVWVT’pCê0í‹ƠS*~úƒG Ñó³Åu|Ă´u±|º"V¦ hjà“WF² Ey€P¦2–¡Vå¿YÏqP¶²•¤e)yËd¾̣”Ï|*¦Å̀̀º sk¿–-Mhi6s™Å̀å5ç9ÍQ>ú&(4YÍzỊ̂¡ñ¼g¾`“µCÎ ¸êx‡f„\’µ†EÅ,N©ên’ôèbâ¼¶w ÖÁ¹p†€L8±‰£¨â*\Đ½8¡ơ+A°‘ ñè a7ÍiÚ¥®Ë^?K₫åûNj”<„vRR;¦ s¤jÔÎvv”9S|‡T ¼̣Q‰«åDûÙĐîæ3¢û¼g‹~£M{.Ï<ïvï¹ĐUV^À©œÓ́Ú/€4ĂÙ˜ŸïE÷Ûák¶øW³éªùạ́ÆxĂ³Å°¸xk,Ç.9ÜyX̣́ ̃ä(ơ?¢.°ªÂ ©°ˆb½à¯u(¬={PÔÖ¸–°~´̣áZÙ5đÉ'̣0}®®Ø–ºOhgMÖ*̀9ÎúRĐÔ™¯KJ£ag;¾#$ ’Ñ_My³º ^Ưw¸Ô5® ¶;÷ăÖư·Ă]Ö¼»„ĐÀ¥»ǴÎ₫]ö®wO‡‡³xÜ„ñ¾·{ÈƯøọ́]¬™º¡9xÏûóÂí»H8ÿ\Ʊ3;é©)—%:T¢=(̃ÙƠ[´/$ùñÍ` –ø#₫¬×¡ó‚Îz ³.:ô#JëXÿcø>'₫ñ™ï|ÍçqRëĂớ¶#QêNôSå%“̣YÚ&‘̉z@J̣üa‚®·mëJ¾ˆ¸û)Ú)‰áꛪd=ƠÛ©ƯÚ)œ³o˜'~á% \À:i@K¼C½*Öc²Ú” DÁ AĂ;ÀX²)ÔÀÁ͉¸Đ$¡€3 $@8S¼Ü₫@l%À£"Éù?«x ©€üB¿ôÈ …)öĂw ¿LKẹˆuđ9ë ¾.ôÂ_óÂ14Åñµ.ä¹ø>_c¾ÄĂ0üÂîûBU%xk”¹?ëăÄÊ?!Ko¸P·̉?Gqᆠw°¬DT$₫‰€Â$}’D¤0 ÉĂ1ˆ³›j¥1E|1ˆ'p“"\Öy&˜êL’Tô 62Aơh¶0 kđD5:¹ôaˆo‚„0‹j¹¨`‡—›˜”å8;ó éû‡x>‰J0ilF:ôŸËÆâ1}˜5è=6ÔÄ9/ +0₫¼Ă;¤ĂC±oø™Ê‰pÔÀMĂ:ÜjẁX̀Ä“x.npÇ\Ä}́ ­êk¸‚o@D́ ™ O4>‰»̉Ç ST"ø@ŵ”@,—ÖÁª/Ú±øáHT¤hâIqÈD”¦^Lƒ£8 z2 Â–đ˜!B¶°XˆpD6?Tˆ[˜nlÆQ€°ÊBsdF7¥\‰$fDÊ·€äƨ¶¢®á6´‰5 :ÀK [IJ|° {5°T¶êƒ0†º[ë S1)å{«bâ[€«ñ>®d¾ä«çóˆp €u,ºgœÊQ’M…p‡gCëcF}(Êu0F«́>nĐ5˜¬-\‡Àóyµ!",h軲@¼»É´ÜÂÂ%êÔ‡½2ºâÎ…R&:? C+“@—ƒq„ùÉP[̀ù€§‹P—‡lÏ&ạ́Ëù<1_JÏÈÏÜO Dǜ¼»ÂÈT7₫¤'>áøÜK”¸“l”wø₫é‹j£I1́á 1©„¸J«†i¨Ù,ĂáWË0r¨!".œtË«ùîÖ2ôÈ”R‚º=±Ë1eTÔ;;u{úùÔV÷Œ%ï€Óo₫u˜9ETr=*ƒ¸ÓêÓ°ƒ39¨kWJ*)ô8WtĐ™×VÔ”QYReMyhø̀v"›Ẩu ̉­%cMj%Ä*G}«sÀvø†+XođĐ—½i³¾L-:>$€EvØQ¨Ôáă[ kÓMô˜5cDĂ —cÓ9¬ĐÍè°ØXƯ ‰-:vZ“Éh0Æ£ùTÉÅ\'-ÅOJœœ6aStµVÚ¥y1Ûr5{[ưëˆ!Z:ÚW©Kµ₫:;^ªÛ¸’<ÇÙGEÍV$¤-àA3 f±(•KÜ₫ ₫ëé¯h@Æ\º ÄEUIa–Æ5\Åu¹Äu\Ç]ĐØĐ\Z ñÅơWu˜Í©c̀YØ\ÊÙņèƠÆz‡ß́=và9hØĐđk€€ÁCb‰ßäƯ:|‡HtˆYå¨ZM5-ç°GÂ3“뜵“÷¬6ÙÛ¿Ô&…Wï!º¬StM°Öá-< ñ…¶cÄé_»&¢X_|ư†”ĐW™œnĐ†ÏØo؆5Ù6`o°†Eà.` Z“–`Và &à5` ^` â>àjà`– ̃mđm°đèøjèÙ₫ÙjY„ôC°æ”­uèÍàG˜«Êkß íɤüB†°F7„9%.-së#¥̃kFÅ9JsRsÜ• %˜bC›"¸%¢ơQ?:\ôu¥¼ŒÏ²ecˆ@Û=RÛ8N_PÙßo ëù¼d‘ßMSĐœơ!fZ6dqă<¶̀E-ÏÔy‡¸-à5p°'p‚-°+ d+¸‚dJ₫€+ÈäN®dPƒMæä¸d'e'hNÎäQNåJneM¾dMVƒNåX®ä-øNÖ‚¨ÀøèØx'°‚x/+Pƒ-@6A6uẹÆNóI₫ÀÉF[¾F{MÈɤ¬bsnMªÄBøJg†(“§snMs¶gw°Đ(ÂñĂ%­Ö¨̉˜îơ%»$ :Q@;N“9Η?VẸ̀­¡:FhJÛϵåw²6x9SüÇ|D”}ʶĜ›m¸‚·Ơ±|†̃<ù&Íeé–vé—†é˜^'—– `aÀ¨mdÔ\ r‚ÅM£Íó‚Ơôˆ5(p èK(Ö\^Uâ2äB¨b—p¾Ù\>_…̃}ĂđØ‡¢S&±B“R™ lÈ(.’=c}›':?¬¨ªÛ56 eS¨¨C6Ôˆn¥7…h¾.k¿µÀ8e-ûm öÜK₫¡đ9ÊßóĐ1BE”!éCF•̣Ú®üíœo@°è†î5È¥~¨“¡¡À·:XdÄNaûJ*ÇJ%ÀcḲiå—€¨ c¬îôÎ9$ˆ)>¶âqµÌÍJ‹*-¬>:.H•”áÔ'•*eV ` ›Û‰ÀúílƠÈ…Ï6B¾₫ßZ’˜É₫˲¾Wr RuîûEÓ‡ô=Åh”NX̉ëíߕɄñV0‚ £è7pă†0 ƒn«w˜†Чe •„¼JökHÜjø±&”M¨† ³D†ÆN¡Ú¶¬,ƯnËÂĂ}P0ës]·Á₫kʨclđQ́ùŒ”È%.* w°9ïæ «‰́ºR}0ĐâV@±oD–‡̣́ưmr!C¬›„ï6eÎw@i"äpç‹́†Vdº¦u‚VauøÈQÓøŒøùv₫,’u„¦ơ‰ö̃Æ<M ¡8%t+àŸñVù BÛ¼Äø}̀×cwù¿.¯Jé‘|ø‡ ·±¾̃#o˜+pØ‚-pæ'pf5à+å_fe+p}pO–ä+0åPf d\ÎdJ¾‚%øØ·}QÆ}ä÷dJVƒS¦~~'Xƒ]Ve5°5 ₫J¶ư5èưà×å%h' ₫äÿåL&~ge÷·-¨dKîåđ́böœ¶/¨i6€p̣ 'j®x±̣îÆ6\ÇP"Ä/Nt¸"Æ)‚Œèq$É’ưù{øÎ›Â)MÂŒ)s&Í6-¦\ÈPß;+̃₫t̃ *t(Ñ¢/¾ÛÖ²áË¢NŸB­I‘›7ïºü4*×®^²c¨îoÜ6Ưúu-Û”9®\Êv.]ï¾9AÊk]ºïÆ|{·ÏáÛ¾7Q¦dÇm¡¿~ÿª.”xÔ_̉̃¾}«vyó7mß.oûü9tèÍ·q.-z[iĐ EõLÚjƠµ½Ñ~í÷7ÔœeĂöîϸ#7Z›6zô°¡cÚϘ÷̃Öí…Z’2–́®µâ° ¿;¯¾"úu:ѧ'/âú“{UªDÉTë·&â¦e˜€̉D™ñE ‚ ’´OJxưÇ „†ùCƠǗwÔ„¶å₫̉;-üD\ăqXâ~'̃·&²Ó[w5Á;-Fơ4(IÄXC:̉XV(Å¥“[ăÅØ;G"™¤’K2Ù¤“O*©•“R.I%”W6i%“¡]ñÂ@¼yó‚‘LzÓÂ;î­3íưĂN A£|‘e¤;”µ –`ñ­Ö:k@çwa…E€>́Đ9¢y!-´Ï;è™g̃wƯQJ_|;Z!b^ú’~–?íé)¦0qÔQªÿp´ªI«¶*R1æ«m̃™Ơ¬»®¥NJ‹ ©Oa¼[’[Aˆg±ËdO!̃Ç)³ u§°ná´ÔjøÎ₫¨³­MˆIô-§ ¶₫È_A'²â–xäbL¤QMoG²¤nCúhÅ’5çI$·f´4{5gÁ‰ºÇĐ¢ Y'CL4é?è)œ'‰ FÑ; °3ăxƒÊ¸èÅ#â—̣¥§¢lŸ~/̃‡²[‰y(Ö?S4$‘¯‚çªF·nD°Đ0)œjÆà-»P?ưđ$£KüµI¢ú#,\úJ-5bI)Ä£~ÚfƯă×-Ëa…˜Æ₫ä£,ÚbTƠ8jüöE}–s”ƒç{Ơºùêúâ7rÙ=W¶m̃Å fH}cæNă唯DàêÀ÷™€}q{ßQüzPÖwq~rçH´æèüă>₫KC‘ëë°f"ŸÜ3\đ}ؙ⇔^j“¸é:lßœÔ G¬rIû,4D±}³ơ%áü‘ÏbؘKµ‡ º…£½ü¨₫HÔ×è룀&-ü-ªưĐfu₫ưAmå(gBÉX®ñ?égÉ$˜GL¦]wL~ÍÈ?́ßÉnésd™ÜÜ%9ÇiÎrR ‹˜̉ P`‰(ƒíïXc'¹ÇÆ‡Ä VR#%Ø7—تṽú+w妬pQѲdAÙr¤m\aOLVC(%²¹¯¢5c(AÉ iô)<H×1EAzË[%Ë"₫)'$¤¿)¤]\eHgBA«¥Ä·åHÂ’ƒQ³›Å\ŸúPDJX ½ï@ă; €;’¸¾¸ˆU‹&p¹<¬ɘÅt‰ù™•êRœ¦̉[¹éÖ¶¦2|›z_‰t#aqY™â9êÙŘTÉ'=I’ÀÎ*@UË¢SS^¹¯}eóëc„¨ÁM6Œ•UĐ‘È–¼ÍΤZ{ÁădÚĂŒ¨l¾z“ßAk,d U'±,ÈỸG• =m'É®ozƒ\l&gMóÜ,‰:qéĐ³5½çV§;Oóz26y>¸Óœy–ø¨5IWs6̣܈₫¦«~ȹ+ëäáÎÖ̃06%ư@̀|“·´¥Ẹ.@8“>fÅ8!×k%Ù1‡ö3 ÙŸv£ê€¼¤ÑÍ=L˜-oă'†Xc Ÿ¥l…¹‚/Âé¬Ă†Ó_`Dl’‘†åà|‡5Ȱ£–XxGÀ…YëÉ$¼£¤”…1ƒ^ª’|µ+Åô‹q³\’’¼QQ~wiÉ“r…’¹Öµ.reE/”Ï¡4ö¦wôu!C.|̀ă-‘• ,NƒÔ–Oö^ö®÷͇“ï\éŒ$#ß×ṼúrƠ?ʵŒḈ10DrÇ&́>ذQäg¢  ñ\ƒ ß 0‘ ÈP~c í¬ôZ.₫›N×e!x)1v{Ú#AMquxTâZ7UÍÔâúKˆLKÁ:.῭-hÊjµ+=…4a¿Z̉(v₫c0vR¦u*eßÇÙ-{z9öÙ÷8Ú/‘6\Ă»̃¹CR1eL«u.̣#‘£^à2’0ƯŒi[s¼},ÍGú†¨ư’œ‘WËi¢ö²'GÛ…„Á2®t‘–đ7f»@ôgĂ¼«·8 0[¡ø\ >4Ĥ{3Iöj”n¬Zz¿J¨ú#ë•ÏQMøF•a₫W1îÓ6O¦GªÇ (+ƯV®÷m&¨ukÈ0G ­tÍäđi…ƒ\IĐÍ₫̉ŒP¶1û÷D^Rƪk½‹`?‘^H„¡±TÀ öZœ‘ÈMÄ[¢J"âmº”lä¹›Ă!›VÈÉó=Ÿˆ>xÉ»‘83¼¢ÓÜ xa¡%₫À»b ‰»s#º°c“K8¡e‚½Ẫ­ä˧Wö½"ï<´Œ½‹¦Aú˜\ÅQˆ:PÍoNäJéZç¯Càn¿ÿ= Ă4‡ü¦̀²)Üđ5¨C¼2¤ {¢ÅöÛ̃fä'άú‹ƠNå—ư—¥ĐúÜ7²°¾…S3f•Œ×O¡óÜN·„«z:´¯ưđo¿ưY9÷Ñ’Áèºé7|AtÜ tĂ6,ÆåưĂ5₫đ¨|Q8ƒ0Á…ÂÔG̀ΙÜ¢¡NïLÜM×FœN^-îü]Å0đtOåt‹èÓP@\íy…:TGĐ‘P( è©J«¸ëƯÄJè̃Ëí홆¥ ñ¡¥¸Ö7ƠÎË¡re@H!Rđ]äÀK®M̉¥–̉­\° ;ír͘`Iºá†J½¥"ÉG% ¢(êá”$ÉbpĂ6àøtä€X°¬ÄÔ!ÍÙ¸sQM„Kê¤ÎtYyYà%Wï'Ú¢ƯJêD„v}„yqø *]xœÈƯÏ´ÑXzeÄE₫Í4áFMĐ; Ạ́¼Y.–Dơ‰ ß뉇³ 0æÇc´„;0aÔp¡¾i³`Í)=Đi7D”2V × ±­Ä X´À8–#9c:¢ă:c;ă;Âc<Êă<ÎăXÁlAXÁ°=úc9~€¨ÁŒ# ¬ô£?*äB2ä9:A ˆă đc´€ütüĐ€̀@ XÁ8ÁxAB<ä(‘¨VI„uư«ˆ`AC%̀u5›8̃É@qâ¢1 AÜ­b¢ !gùß"mÜ)®EH́àPzH åƯ°JǼà EäÄTË(#LŒJ›8–qQVb₫cPD` ÔưZhaRèXfE™ø\k•…ßèÙW‹ñ ›Bˆ!‘aª!]£$EY`Ç`fl€Éa"Gb*æb2fbjĂ`>fc2¦ohFbRĂqø†djæf.&qđjàÀ Ú€ Ü@ tĂ tĂn¬m\°`ß0‘ÈÂA^YbáU¢DDUáµÎÙÎPDêä&|0q-QÉJyœ£AOø+Ä%ç>ùàH$çau…"qĐ3²å^„‹¼X ²iawbJ„cùÊö¥UZa¥9†[váÏÅ%ÛÑ4Z£€)ó%N]ôiV‘<‰–ÜY–üè₫!èFÉ]%Ô*h„2èƒÉ]…P.¨„fh‚rèÖaïí€ØÀlƒ¼”…5,cñÇ̀Æ̃ Y^IƒÉpÁE„>I^Đà¨H<Øéé5XÁH¯(‹ø€ÈÆ=[<Ü­¸â>I¢Á‡JSºHïYØ‘çIèj‘Û\éE¤RÍ1Ú×́åî]|Ú'đ5g|1E é°đT^BrÚ{É”7|†œĐÓù_² IŸ꟮•Ùđ_ÿôi»„éY­Ÿ¡Iøñ‹:ˆ¡[LN[½•Ù°¢²Đ‹]ËËäĂ;¼j–¨ø8A‰–C´{HÍ=M˜êD’Îâ«Z\C,i₫oÆêÏøÓ%Z†ZÙef5„³IsFܨ ï¹Wœ­}W™Œœ!+VÎɳ.™9^•9kưœÍ²'Óu)F zy ¾e·:ĵ„Đ-V(Dµ'‘¥K|öm¡°:ÔT£Óég6nc·zcˆ±'¹z«}ÜÅdQ†‘˜Ÿ̀ Ç̀ˆ×mŸîG^aŸ>Ăn)ºÆ®ÓI¬®„ßƬ¡’¬[Œ¬É’,’\ ä´ÍÛ‘d ×Û±€ª²ƒé¸„BQFXp’ŸŒ™µÙ•eÄ”Km îÔl³êƠA©³-D_Y›Qkp›`XL¢X­_¡e§ä₫Ñ2Oj[¼—lưHĤưU»¾¹üƒÚ^̉ ­å&ŒÜëejkÁ)fÉéôu+âÖ~xcÙb’V+¶¾ẰrCùYÀZúävÄù´Ôå’­Ḳ¼E|½ƒ ̀€”å‰Aà;äNÀǘƒSÁEŸd1U"TêÜç$Ñb[Ÿü â5Dîp›ä&Á0̃Å/6LWîxÁ® æU€ưäÄÁ`åÖª[®åÈ|QÏ: ‚̀—›n–Ú À®E|K>´ fPZªëơUá•î1¦éưp¡Ơ,!ß₫Ø5¾Ẹ̀©m¥ñ”¿nùÊDŃz₫‰hCỳR(Ա텴)Ù¯̣Î>L°BđKđ3¬Hhđ|°ǜ_ ÿP4ÍN đ ï «0\଒Ư?|ƒàÀ”¦gt寤Á7À–¨\Ë́ 6KWÍ Û4¸|+(•?,€¯ổµ¨Ă€K †QéJñú ‹ûƒL 0P e±0!0m̉{ñq ±ë9 «?”ƒ×ÙoÊ‘ˆÅVæï7ÖWÙ•¯?Đñ>®[„¯ŒEˆmÿÔï]_oĐéî1ü>‚¯[ÍÊƯÖ’đ•b!“1]á2²V".ÿè èđ₫Âr,Ẹ̈,Ó2– bR䀸ô€xÁe¤”Vp@hÈKÙø}Ê+ù±1Réƒ:@¬É €•¯0ñ3/¬qSs£„RMq?³@ªoj{q8g±>3£„ùXñ®±5ß1ïñÎ ̃Tó¼L\E!§2S¸ŸÙ ê‘2iÅIfYºRá^rêܵ/ư6§D#₫¶“pÅUík—ö+6₫k@ â’ÚDI è€D8Á8¼´ÄtL¿£M#NË4<êtOóôOß4Pç´PïtPơP5C*µRÛôKĂ´x8ö£ä2üÀÄ₫@iÖ€D*K«ä”£ À,MŤTînå ơĂŒÎ¢EEđ„N¾CœIáĐ¢±; Ç6=^ĂỊµ A܃¡YôΨGÈW!—]>8†º́©dS#WϦœH?Ô87¤Á6•˜›¶SR8NV*¬¥$÷H̃n°AV|âëß¾ )ó”ØEƯCkvn%®ô}Ă dChôf÷ewpür+wr3÷r;wsC÷sKwtS÷tÇqwd‡ ¢à€ XF ¤¦q?¦p´À78@ÀNÛœÑ:Rl¯ñ¾56́fỨ„Û4̃œ«’® ơÆ^₫O ”0/_û¦Jä€Đ2D±ƒè}OJç€YeÙµ6vjăÑ·ôIû3qt·Ö,Œt*cí¨6­hWض̀g̀m.*Ë]ÄxkyV Åw"-Y¾æ˜n«'™’O¹H…gaë7”Ťs-;ù“Cy-[ ¾ś€¼0WĂXG-“K7à‘̉ÊCĐÑsn^EđèDH„¹Å̉œ9²¹œ»äfgDœCª°µIo›Ä q£áú–‰t(N¿Ơ•H›Èú₫ø&7Ô8_WŒÄÎ&kœlëø‚€r¾Đv™¢vÇçdïv‘©¢ô½Ă₫xô*[£°›&%Pø™E¯ÛriỈ²0X躙Ûũӱ}Ă ÔÀâ˜`†(5-Ê¡­J5 ơêóăDÄ´ MưeºÚL”z\Jĉ?„ÅII'ÈúNbpCˆ ̃'̃5ºøû¸‡±‡l,Ă÷­1²̣}Ăí©ï"’÷D»oÏ%_ô‡ơmá;Ëz§{º¸JƯFk#k›ØGwî(û»—¦ºf ´ Ûˆ[©»O®}|ä†üÈ›|©<]¦í¦ưÑƠ³³‘%Đ… Í{r”ưúxđzºÉ[%AÛØÚ^X°ÓGĐỎë|˜Ù­oÙ× É×̀€tĐ₫€eø0c\kE½´éQ<0vV‰}ư%á»°¤§kZ›™j–-¢§ĂO !C¶iK̉à'¾ÊÆw§àúœ©g¼—®̣z₫}²mŒ!g%,-º̉ü‡̀<ưO°a:EyäK₫ä3Éâ”Ç7À€Eâ@txÁ½ ɘ ½H~¥‹₫ElÊ7_4½}MÍŒ/UNB•~Ư)µ~vöíàîo‘£o)̃÷=€l|%÷v²ÂÙ±*ơJḳ3ỵ̈;ô_ëóOt]Í₫Qˆ”}¥Ä6¬Á´@xA9’¿LÓtM“cM—cL'äCÚt?Æt ¨ÿN·¿L¯¿ưÓNËAâ¿û₫§?@XqbÅ -,x0!AƒNBØb ĆV´‚ÑbE'N^„Ø„̀‹<|øøÑF[”Œ1xÅɇ'V”<¹öî_OŸ?:”hQ£G‘&Uº”è»wßœđd:•jU«W±&uêä›Ô¬_Á†eÊ“§¿f{ªëçOƯ»k?Ñ•;—.P³kÿ½c§W]>që¶Z6Ÿ:}yÏL·¬âw̃¬¼C‹–,d¯‹1gÎêïiäÄ>Í¾ÛæYsiÓ§Ïæµâị́çw«yîƯ³5jÛ¨'ö‡×©×¿¯½uí99ï†ñ'üÛ·åΡ?—útëƠ±_»vîƯ₫Á_o¼ysm9~àèĂÆ—n3º•÷¶ù7mj„ßÖ¿¿éÓ¨vù PÀŸzăÊ«ËrPÁ¡Êêi³̣Á‡3Ĭp³¿hsêŸ~ôyĐÂÀœ’f ơ.Á…’̀1ËRK,nHCQÆÁ,3+4YœQGÛ8ƒÍ®Đ|„‹6¸₫*̉È#‘LRÉ%™l̉É'¡Œ2I jÓ²}úùÇ ÖtJvÖЦ+vöÊ«·3ơ:s¯̃ÖtªÍ4ÙTSÎ8étÍ;á´Ï=ù́ÓO?óÊolÀá XÛf/¼ônÎæ›+ ƯÑ̉¬œúfŒ*/í«½ êDOm“ÊÆ¼Øyđ/nØñ‰₫SR?,̣ŸJ×Q‡2X­‚tDTMƠR ]}ªɆ̣±q%•³o†m±XÑMVZª€ä’HƠ¸”­XQ¥́ÖÛoÁ 7Ê!]%ĐÈ!Íj¢«¸z3ËÖ ±̣0ŸæN[É´=+_Zµ´|ƯÙWà öwÛVăÚ'á…}R¸a†{r8b_…úKŸ¿ÖZö ‚KƠ©Xăæ§·²vÚ“{Ú *Qn9¨wBƠeƒơ  gVåĐx²•äœz‡ kxÂ&/‘?;ƠS©üÆ3â^Œh …ezÛc_ºåжlÄ g«í²± ,»Ü³ÉM›BµÉF{í·ÛfÛl¹Ư»)¸†₫™K¥wûç…nxrçÜ·-°Ă…œMñm7<ñÆ_ÜqÉ#‡üñkăfá<äæmzûÇV¶₫ù擵^ZÓ¬SïÔ¬½Ôe½ơÀH́M¼¬ĂíÙ5Û¬o€àÉœ4y'0‰GSÆ™oXͰƃóʱx—}:®ĐF“}zO{Dư3§³¥đÆ熻|»Ñ?_ưº×§Û}óƯf÷eÄnÎ7#™¸Ư)®|rºă¿¯(Fb₫ Zæơº°¡êhÿ8̀;ó¹oôäbÎøË:˜ºíéhYÿ‘ÜgĘåGqÚaR”æ&T­î„½sÖï̉Àuü£U&lÙỷ/™-ÍDMk₫Ộâ4¶1Ï»Qh¤GDæaËkỢƒ¨Ô>ø½/}́³"¥XÅ÷‘o(h©à¶Ơ=©°L|å+ăơ$?ø±qh#N‹u£¸±ñjóK͉öw c¥Mọlú¨D™EĐ"V 'H₫ø£ co¥H¬ÈÏ?C”ä`‚èÁmÏ~2U²Hä*Ë$ĐXI¼äb–ơC!̣”ÜëäµÀ›®•·©_×¤êÆ“F¡ØƯ|™HM¥JOD¡V‚F›˜ơkŒ`¬åiTÈQÆQmÏ4>ÜQÈƠơ@â2E°‘cóî˜Đ7FñSZ:ÇH¢‘;ƠCÅaf”2`” cPͨ̃¸ÂÿD™½C ̃†SJ¾Œæ3¦_©d9i…ü|e¡¤=I(SÖÔ*ƠkLزGÔA¾4¿óÑ:yªTÚË™± º8B±|ơjD©‰Æ†î,ieÅhB§E…~5…2 T«*Ơ:̀)Ø•\1“Àu°C]ÿđ:ñªFâ)€)ç9ۘΧ––®[ÑÓu´+x“°®Ễ©V:ÔÊj†Ÿ×bjb7+æ… vy‡ö–Qv6¥ˆĂ₫.ÖíĐre+XgûÏÖ5¶µÖ÷á°…¶¨~åW¥Î¦ZâVÅ$sÊ_ï·Ù{(©ËEÊM£Z¼Ï²¶Sî$Đ4[T™yZWTUs+ÉËÙíb(–ÿÈ*wÓ«”[zo8À™ #ÁÙ±I4¢±eí₫̀¨¶̃ö´̃€ ́ßå1f3S Hߥ4×L¬R#B%œ”Ă4÷Q<."å*Ö@ 1Ă ú†9×öK—½F8Á­-óÆDUºèhă-qƠGÍ–x€Êỗ×~̀ăIæe &§Æ@QgSî§H=rÊÀYD›”ËEeĐByln=̉@é+ä.¾îùZ2†Å₫ÜE?è^ôSñ3ư'^ÊƠ°+ĂéôÖ[Me=‚ulÏ̉™£>«º€Kg›ZºÅF¾†NYJK%\â÷‘̀PÙèx=.ymM6S—6­é,3yÔ—V¨“¹ÇL›‰+‰¹˜„kdGÇñg²qGrÑă2½-U´©á·Ù¸îˬ›y©—ºw©n•È)€’¼‡´f2ó̃)ËwÊöưn#àˆ¸»i3¯­4ç¯)+] 4Øm¸̉Ă˜N·Æº₫ẃ5¼n±Æ‡^@c—ÛSËóœăªUγNå& }meÛß[4­ë[ÊC[ĐO ù¯S™£âq¹+Ü<´‘§Âzö:*̃¢§¿-êF{…9uơ¬£eë—麀&”aăÈÈk¸Ăœ¼^,Æ?¼N®\OÛ,*ÓÔơ₫fkNˆ–³±}“Óđ½øRͦ <#+OºăÇ/ŒÎw̃Emûsµ™˜«ÄGéÑ]Oâ…¡•CV¢óë÷áhĂa¼t3"hPö®µê_ÿZ×Ă¾÷´çåíMÔ\́>ö²ƠïûüSÙø³gäñÿû₫"é÷ΧtéÖ:’ïCîÎÍAz0¸—Ô{×ơ Eœ;^®Óµ,æ­Ẹ̈ ḉå'ói#ƒæ.ọ¤Ê¨>{đÏóÂf¸|nñ€Nđ̉l¾8… ¬†C/.È̃ÎBU®Ïơ,¦̉̀áH.¦ö6́àb÷d›XFäa+d“æ®1D[¯¯ïEpÏÍAĂó¢„ăœ:G 2nçú®tÈ ëèG÷íxü*~6˰PÈê ÅÏ~¦t„₫̣)<‡¥Úh ‰Pë‹̀˜Ôp•¬˜œ†Ü¢ªÁ  HØ!?,mÉî-›d‡¤"ß h|"₫Iè'qpÍâL…®êÚÑ'±ơñØqqȽtÈ,¸a &È󼸡 ́&󼢨 ¸Áhô‹¸”¦†v,ĂôO¦ÿ¦åÿfÎÏf1Ănî¼ í ƒióÚë½l ©¾å*`s¶Ô`5ºâb‚Í)¬Á¯DN4H¤!‡üêƯœb'öJOÜägeV¸á7°1bº[…ä΄×äM¼‘'D†Ùñ²±¹‘Mä1IÏ-FîƠEF/®ª7Xe!ßA dMăD*zMÉvn߬t N˜bÊ©$ïÄkÿV¬ ;oFẠ̀  FÈP©₫pL¬ OƠ,<‹ ịóÀ­Jö¢¥f ¾‚̣8̃Á–Q4'8 È)¨aLÊ£+„²»b¢’ưñ»â)à$(%ƒ•’ăR/r¥R4ªrMˆF4²rL2Rľ’)²<È2(§̣,±+3N6‡º¡ƒ>ʃ¨a ÂL×:ÇPà"qç\¬-Pk»)´ªí ­7è@±‰^2 dNˆp&±PĐPØ̉P ŨŸq–‘dž®˜̃¡f€jR̃! DÀ r( Fä@ X@t4³ÔR4… ’À.Ç€ ̉º‚$LR ÆÀ6­₫ Är zó7›` ¢b†ÆÀ8‘s ”“9:“ ¦óªó:";·³;9ă;ĂóÆó8ŸÂ<—S(›ó9£“=;́=±s ´sÍÓ ~²Èà®®@ Hâ 0®3)³¤¶iÊB «AR“±8´xüÇ,¶Á "pÄ 'n­…̃á¥À.Ư‚mG¬æ₫6IÆP×̀đˆ,3'yó-Ïxt´l2(¾aº<ƠE(³r 5$¸B'CØèœ°lM8m:MC8®ÉTJ%‡üÈ|2-t²ô@p†K§ôKɆKÍd/̉6CçI3Ö¼A ̃aE{(D ÑR¨ Ư ¿Äí— XÈ₫â‘H‡ˆ¶†Z/FwDí)vĐ~qTG5 ÊA5“±JDnæR`S¬‘› †)̀Á¦¢#I[lq`¦-¨($¦̀8đb.Í=ONIc2bL E¨´*³₫x©_üÁ/đ´•,üÔï@h¯X6VPïº ÄïÙlô4‰«̣đ©ƒÔGï'»̃âª'¸Q %*™ DŒ+b2Q)₫ÈN—"ö¬($.5̀LỖÊ› è“8å^ ÈUZpDnGQANW=Íư„ ä“Zó’Èè¹₫¢-̃ o¥U Ă/X”‚¤±L²B52U4]“4s̀4u4-UÑ0ơÎ₫ruS…âfŒ.+Ư¤_pO¦P¿´a…̀&Ơ5Đ·¯ Đ‹x¢0>­¾|ñ̉T„‘̉ÏDÄE¦\tÖ3ßÉZÅ%qÔˆPd)ƠERHsRH# 4®a 4N$m¡ƯX%ñN¶CM a…ƠPÇ  jÙVC%l₫̉ѯfè„̉¤_Ü¡ṢCVdy[«Đ¼$U$».ˆ% ¶Û^SíÚÎDægj¥c/35¾ÑÓLă2%2dji‡¶!î,ØgîµîŒ¥g^”“†¦gÈ•¶¸ç3ǵZßvœb²„¸•&¶ŸÀVx‰l'+†¥Ö%û|₫ú̀ó¤"ư₫!wXV₫ "‰lç&Sz·uâ¢L̉ÏÉÀULW¤zcPI9éx¦i —j¨u÷G·² °d{öqŸ%eW“ÑÊvelëë8’́.Æ An=8ơ zÍÄη@"́‰l:‡…nŒJ„&U©{D3orÛ ĂÂ0̣HlÚ´6³êW 7¯x…Ql'’‰ÎÊ#ÉË+¤÷2Â÷ØHæÈà3/_Ä̉ơ—†€“ÜØă2ɃOi?q.3ujºRW*S†%4ƒ7½"u•W{½$·åæ6€Ó~̃qJ2¾fyÓví̀åA®‚…ñÖ‚Ke6¡w_Aňu« í(z<₫èđzÂ΄vv:ÉV£˜ÙH˜ÄÄp…;´Q-k»öC\Ăöx‡”J Ê”¸…̉X;÷₫ª*i3̣h4³ƠđÖ„æn‡‚ #ƒŬƒœÂ•» ÉnÅ–y„Ϭ˜‘CŒdñi‹·‹/U–ü÷ +· X£Œ÷ ĐxßÀNw^±-_ß ~³ltY®̣e¯„øo—ëIä³Ơ,XDp×G0–₫¦•„ỶF¥­Ø.ë uˆ×đǺ˜RÅvŒ°ä„́¯ ¡â¤nc‡CễA-lư®Ŕv›ù¸êº¢́8×j-‚̣gù¼aÆ@è´–ù×Dø Ư9w“¿‰q₫µØ—«Ù[Đ˜™]¶¼‚ÄŲZíĐíècM:¥HÇ)¸ÁÅ¡¥ê€¤Rl%½¨y,K6zĐ2µ$că·ñâ·„[R¥Ë°Qe’œaú’]ƒ’W\'RŒäGø₫9}§ĐC@Ymíc 6„&Ip/¢iöYåû²•êÆY«é qúăO22†¿zúĐt÷yëÇ«˜‘ʯm.rW6¤m.¦_&“÷Eµ‰‹ª³çu³1…³?û*@( ñN{£«<;tA»µøµG•][´¯¬zí"K Ơ×PÑ₫‚JI™ÎôŒD†í° U£uÊ·Ó™K0ö†û Å0₫/su’ĂơkÅú…-Y€i#“Ñ¥µ›ÙÊ`[­È¥U ´¦_HÆÅF†Böü°á^dĂëtè¼iŒ¢Ø¡´—̀¿ó"̃á²GM·(‘ÈÁ)JÁJÏ<¼á&t64öđw¢ḰP©ĂêŒeE40‹_æ„Xn]n̉Œ²-äc;œŒ[‰²ø±_|qù÷‹9Ü5©*†É8%!ÜÁÂu `c¥â0œ0¾Áq`ưÍh̉Øïá|ÂhÀC|¿³VÜ–²'üCĂ *ùQ™̀=Û̀Å;À¼̀M2N„dv"©µ9W‹•†Coù4‘Æ₫9Äy,SJœ¨e¤sCÅ=–ÏZ„wqÔ‘·² ˜YĐ)s»ùy™ÿÉ„,‰u.ËkÖÈ{B´1mÏÛ¿ àüû¼)ÄÔ±!BˇœËưÊÜÎû¯À¿û;jßÁ¿£.ĂÁ¬¾ê±̃¯ àú>w₫H⥴g(Ô 5B½¹J;ßÏ¢ÖkƯVÉ>ß!â#₫œíï(ß4̃3@7ëÿê?đ đ ¿đm¤°“@ ¡U.Z]u¥ư¡¸! ¶!ïöا 磮·YOÛ1çK#PM¶dô¹±¦—E{b<çV_©$¹‡ú÷¥5•Ưs)ÈàHÁĐjyxŸvŸèJ¡øĐÛF>ïưaë£Ỏ₫à£OàG$„á§Ü,Ễ·¥ÎùÿAỄ,Àû“†ß=äï̃>ˤ5øu¡Ôø}¿÷¿ưåÿưƯ?₫é?ø­¼üª3Î/'÷ œl{ÇîŸÁ₫*\Ȱ¡Ă‡#JœHqbBƒïf4øm›“CI²¤Iƒ₫6¾ûöñ¤Ë—.ß9ù–QŸĂŒaê´˜óß»•Vp¢ôé“[ĐH“*=¹²Å;9/¾óvt©Ơ«X‘Juâ $Ê„ï¬t]Ø3«Ù³húÜ瓫׃)­ĐLxªƯ…^ójÜ{Po_¾íË€ÿÖÄöÏ@âë̃˜œx€;¶̉Ø`â₫wë+>Œø_i•¦ü'²âĐ—ö¹:á5Nˆ¾ø¯ï̃Ày ÷œøpÁÆ“#_₫7£_¨DëăæÅƺĐÓjß~̉[‚ßÈl[-¼,÷ó.ÍËr7ú÷fq®lbĐ|ôïÆĐDØSưư8•5UP6©¥Uîư§àR)}sTvj½³MU Vh!Y>‰ơtÅÖP×](bZRµµCqycàWÙí¦ÜoÇÁøbqÿ°¥Xbÿ°£;«´;öÄce¤X‘±áÈZ`EÚ¸Ö?Œå(£l IçNÜŒ’y.2Gă”`~)fŒcÎH&™oưôÓ]ëI¨Æ6ü±è߈₫tîDĐL Ö©§p_¥å€BTÖ7ôA¨N?]ƒ:`ÑuèM†ú4¡PuEf*aP 5 ¦™†Ú]Xc)©ªêH`}çVC₫°³EWçøä܇}gĐO"ô®5‚U#F̃ ¶ÏS‘÷N¹Ö7,Qû¤ÔÛ¯¨A ̉±(6 ̉¯aû¤Jºb¤+·Đ–¥Jêäƒ7ßđ§tÅn¤(‘›«´5^çm¾)Ë́°Èî»}yk_lIî¼a›Đ¾́H…k¼#›ïA C•O?₫¼ûúpƒĐ»9ÆêÍ í*™Đ:₫­\¯ù̀2—T3ÍJâ Ñ7Só₫®@´ă?,}#rª«Â·%\Œ₫ĂÍO '-"v¾~œQÓR“´f?H¨#^' ‚uöiÖ™6èÔNöÛ¥!Y uØ,ˆCÁu‰2•Ê7tUÔ|æm8\(ª8†Œñœ‚.øä—d^IFæO9+ïá ³Ư_â‹Nºä¦—^9嬯º]°§ô‚ ̃|cÍF́,+áßH£}QĂ6Cëü,47Ÿ¤I¼Êlü®7.ïô8?_%Ơß8¸@„ë}W)æ×)íưvtµHÆJÿ7́”ÓÇ8Bh₫ÔÂbôÍÚe;gÔưîĂÏ₫Ÿ (€¬₫×ÜL%7¿….iû÷5lCd‘¶îÅŸhu^Ñ¢‹M 3„”đ$3aúBˆz^#YœRøBª¥c7Œ!m¨Bw¼+Z>œá a˜Ă8í!7̣‡:"Ă#œ̀ 4ô T\¨Ă*ÎPˆ̀âAHD^‘„"éBÅ"‚Q-)Dámơ›|ă =° ¾°oäî)+ù¥x„HUÉ&<I ›Ÿ¯}>ƒĐ°´Aú¬f×sˆ#ÿ!=%aƒjØÏ̉ ˆ•=LSÇ;Ơ:N%!ô#ẢåGNâ$ê°I€’6K-oÎ9 )Ô pSÜ%₫ ¸¡ºÍíC•0GÄ·W1$w-¨*ƠDÍjZóØ̀¦6·ÉÍnzó›àôfî®ñ´Ÿ4q%4Z8×ÉÎvºóëLçJlÀà`4@™6¾q  ØQ•ß  ;Ôñd"r"=K̀!ƒ¶J ̉ •l"­‡#ä’ 9¤ñYHJú„':Ư2M²-d|øÖµF6©éưĐEøi° ,µÜ2¶áícb)~n),°èR¨IKQ13ä@e"ujlª­¶18ái¸‚œà„1pƠ V«XÇJÖ²ơ¬hMkZ[V¶ZÁ­pm«ZçÖ¸¾U®wÍkY₫·đ»ªáj`«à„xÁ[ưêVéÊØÆ:ö±́cÁúÖlơ=øÁ́ÙƒĐ ZHĂV°+< dpÂfƠ½…(Æ¢6s­Đ4*´̀…äH…¤Îf4Ẻvg9{Ⱥ§¦ÇW9º)””eܬÜåi‰ÁZ0³ö4–ÑFlR3ÔOX¶µ¹§l ¥@ä6đFUt#Ú1"ó*¨™!U;¾Qƒnt¥#Ío~½Áß₫ú÷¿°€LࣿF°‚ ̀`'¸v₫}đƒ¼ ₫RĂ¿u<°6º±ßO¸Á ±ˆGLâ3¸Ăü=pfqĐ|ê 5ĐÆ6*₫¼Ï°ëd̃€.pa{[Eºf¶‰bfS¼›ÍF¡ù­G hù  ­: ;2Wuî[_@Öf&à‹ĐƠüQ¤e¾ƒ ·ƒRQúä(ME (”P§ûå’ˆBR9jëgÂ…˜X̃3zZƠ©&p̃è'7mÅhu:çц´£#MéI[úÑØ´•5+-éNOÓœÛÔt5# êr~úÖhO69ÍêK·ºÓ¯µ«g kZËÓ¢'@+Mkđ&FCÀ„Í?ú0Œ‚,dÓàVfˆ‰ ‘IRØà0Đk@GMÓÛŒ*D3OYH8RàFnG₫gA3#5ơ‰5Æ#w‹$/uBF̀¡J3'ácẸ́œtỀüä–&5àwí­“^Ö²m g8/Ñûn»=+™—¸V̀æg¸Øä 4!hî¦5”î¶¹l&xÉóṿ•«<åR –ZbF̉ü†1Wy ëâÁ£äæ1$è¼F®˜m!bÖJÊ—Îr·ü†MgúË£Nơ©[åUǺαơ -Ô +OË”‘‚ ,pê`3äyÉ'2Æ“‚V̉h/Lƒ2SÜè4ÑăM^†|¤Ḯđ0̉{b2m(’ uû58©„6ßøåG2̃º¥a Rj÷ªd²₫̣ZOØƠÈUî‰~ó ùT§"¤gØĂĐï¦x)mB“̃=)yáxŸ•Ö·„øH5FäR­Đä ̃(Èg”tƒHßRj¤4€ø½û>1̀ôÎ÷ƒ€úL0B™ƠL¦4’ôu~¶æe†)sg€t†Û¹S~”±wă—#pƒ2Ef‹Àn—qö–”¢í|œç¸f¶@́5yĂ”? ·,¸4‚h9âe:Àt‚ï¡TéeqÈ”?È‚Z¦§2:‚Aƒ–Ó)Q^<˜¨R"¦á˜4đµ’™a†QwN(}N˜#₫uw.|gnBăFÂw›Ñ„‰ñ¥Aeܶ+’1…̃·Ø€mø+ pZÈ:âlNh…W €‡‰Á5Q†Ë#> *Rf h{m–K„±÷ ÖÁ3˜5èƒÅ(©×Ô?E±ˆŒØˆNÑf´Ç‰˜¸÷gL…4£ØpQ• CxqD˜$Á7®‹`æá}ü;ÉÆ(ú . À(à ₫Pñ~˜ls€₫p€æà‹ïÂ2ܸŒÀƯXÀ(JÔ1ŘŒË  D ƯØ1Ææ “Ñ1ÑÊúĐZ₫Œ ˜„Lr]ĐHĂ³‚´Øˆ-Ñ^»'‘Ù%‚âU |S{ p'ä%™º×'0øN’‘cƒñ…ƒ]¡ƒơ†’Á7Ûp)0©5̀÷HPọèvç¨ à‹Ê¨àÈEÉù;ĐØ“Dù.v±Đ¸”L¹Kù.ù”åø.SÙ”Í,̣8•ú•9‰ê²KéÜvyÿpvC“¹Ă +̣z{–ˆ&X“øˆ›dJ“89ă*o–‰?Å 4É—1)³gT ©˜Z6’q"™‘™¾wƒ}‘ƒ®ˆIAø˜¹|~“û( xâë₫§[Ù·+û7†®9d®Ávgh¢1›ç‚n“Q‡ÜfQï'—½y¼rm@0²ù„¬iÅà„üwP“!3Øöè¦ÿ€ÛâæÈ1ªÁ œS•é^DØSxÉ{+ñ‡x>”)5—ˆ‚‘f£‘!©6ƒ @&á‚·^xs’öÙLR%:ă„2 ¡©{8Œ¤̣—Q$Cc$Gâ« ăªfÖ4ï ’ç„7’±¢@̣l‘$Øpëà~54¥f% ơËÉQ ª”;ă—}4>₫Xô3­Dy4É—+á—»GS7i0•x(§̉₫«§‰sÖ™wV¤gcŸ=XhK•Z—¹’™Ù’›9|Z*g³ø¥ÂåN”R°…QH\ís#2ƠH‘´dJ ±[,Kf)13à û¤&•fĂ&Úúʈ¢jüù¯¦*‚«¥úă«ªˆ«q̣©‚ơ¹±‘C™Æä!&i¯¡Êqbʫŕ´ÈW Z„¿÷! ï³FOf{¶h›¶›å´ 7°0  K å´‹K¤½! M’ü ‰Â°©ó({6k xg+â˜]‹’Û'ë´â*ÿy#˜+g;«¦­Ø!ăƯaa¡;º¢₫[º¤{º¦›º¨»ºªÛº¬ûº®»)&`¶<°9Đb6p +2§:²®J„YZ“åÙ¯?‹A{·B´ŸI‚¿;¼5ùªx&)†±´'%¹ŸTK‹₫Y±dÚ:‹‹ˆf³· ‹^9ÑPD£5@„%V”Vï»Xî;Vñ[¿ô{¿ó›¿đ‹¿û«¿̣Û¿ü¿l¿₫KÀVđnuÀ/°À(p#Đœ…>ø´íbp'(ƒxA¾£Hh¼Ç«7€Û«2¸†Y)¬Hʘ•¢¸kP{§'¬aê½c¹Ö«±/,‘©̉eZĐ ¦¦¶B<ÄDœṂdMß Á>Đb40₫5đu"ª—ákJ i@ÇG¼£z̃“S|J9@G»°Ñ›‚£ª/“2œŸR«½—Ëq“»¹JĂă[½)™,Ăok@ íb§Îë­$È0äB} ­\Ó:Èă*ÈĐÊÇâÇ6ȇÜÈ„üȆ̀È@“ÈlÉ—wSC§ß qD´#³5P º½Y†/zKÇ,Ø·Yªk¸Û'¶äS(ü?VÊ]X¹gÜgMu*ÉÛË«x‹Ă ‹¹¬L¼¶;́8`#ĐLÑl̉\Í;RÁ2øđcÀö#Đ¢d¨l^̣¼<Å+¤f¦ÅÔÅfÁ¼pÆĐ “̉û₫K|Æ´Q{7·Ă*iĂU f${đ,\ÍyY6Æ¡}²/©’¹1q1h4îÙs/ôs9CĐzí"=]̉m !̉½̉3Çs.1* ̉¼(¤)P‡Z  ƒĂ"!lo™aϺA(ÏÊRï PQf-¢ÅÂSlËrf°VÊÂE%Æú,±üœÆ₫«—ùŸ‘ß;.; ¼¾&xñv }Ö/i&im²;8#Fb:oNeÖhĐơÖĐg¢×Ă Ño}×ñÑÄA»(™°́…]«8BK|ˆFÈ×4¸Ôë£DOe;âRL}!̣̀]%XÏŒ₫KÆcÆWM1œ½ÿ|̀nœ Üp¬<)r¹$¥9’‹OÑMÍKZÛ!/:¸&ˆÛ÷yÍxƯ×Ö +c\b¾¦r,IẴñ{$Üw#‡}Ø|Ùq)L+Ê9â²Ô=½ & ƠºË‰¸¿”Î{½ÀüËú\Ă7qäñ9Œ u£Ü+×]P:̣ß÷­¸àư½ßÈưt̃7µr*<5à¢à èøm:ú}á^¤•§á8^à.áèU ²«¿z*~–á”fÑ¢DJ´XKí Kæ(Ṭ2£á)*Í)ŸÍ̃xḮ•ÏWƯ¸Øk« Đ₫ºúŸ±RÜFB₫$ZÇß̃áØ:(á.·á#̃å©Ăå å®å7̉åwÜb^å^Î:-·å•S@q:u>9ü=æw>ç]ÎÜ Çj:E‹½r@Ùá»hÎh(azAN×~§…₫G->´q—ăm!…ĩ₫“̀­LTÚ¥!Yư¸NÛƠ»ذ]±#Ô„CƯÊ +%b?!ÜnçÔAp¶«¸Î<‚ذÓI7³®º®5¼NëÇö£́¡scâ¢₫½\m+x̣ÊÄ7ƯAéÜà»3né¾»i>R9Zơ}ÛaC˘èăÏ ä<+ÚCÎé~₫ÚHÎÎJn"À÷€¬ï:`pƯÂó$ø̉1ר¿Âs´ ÑFư.xQ­3§/ư!ƒ$cÈ̉Â\Ẳå"|“É"ƒµ!¶Ï!­ £æĐjëC8-·RÖƯBƒáÑëx­̣5{d”pư°_!K;×̣Ă'ØcÑÇ‚â¿#_k̀9ë9"éBÅ7cfˆ‰fW#×"ơ(Í?‡)ïx¥‚éîªÍ¥éEêm<±»W@c3 M ï ‚×sĂCFÿATóg ̀áÎ &ƯAv‹÷üR0ÈeâC-FØ1ñyŸ'©ÿ0ooDS6'ø4Ÿ,9Ạ́0₫?÷€̉E„ù»ø•ë+røÅbù‰³jÔ/›/-ÅÂ6%>ÚÏ]¾I¸918ƒjdàƒ|KQ8âôïñÿîĂWέî́ÉîưbƠ¡=‹ÓKÚ¡>íK…ÚĂ.Ç68¹ˆé .PÙÀa$X¶Ÿf+ƒSk•₫R;­&~đ–//Ơo³v,Î1ríÊ₫P¾̣/Eÿ?Áÿœû̃ư{÷N`Á́,èÏCƒ $Ènà;nßœP„øo¡E† /&œè°ăC‹SLÉĐ%B‘,¼ØP"B}÷AŒYó¥H—-/|grâ?”Iœéó›ozD*ĐITªYµnåÚƠ₫ëW°aÅ%[6lR'ß8j]kÖí[¸qÅNe[ÔcÆ1måîåÛ×/Ơ¶ɰ[çOŸ̃¿‰ÿ¾ƒuçB¤%ƒ-J×ă;oV¤z”Hđ)âÉ¡E‹Æ¬ùag‰™AfƯÚ5Xï ¶5:[«å×¹uK–¸ó]ZÄë̃m™Ñ†Ü‚IĂaâèj'!ĂíƯ7&d’`ü& ™m›D/8†Cu9lañOăjÂ3&?½úớÛ3z_ü·1”@O½->p>ùüCº1¨³;í¸ăo¾ñ,ï¼ỗY¯½÷ƈo‚ÆÛèoZX"Œ̃ÉN‰w #»¡³1 C,đ@·₫°¾¼Bưºûn>ƠPÀ ×3°ĂdĐAü"ÜoH'¯ p@ od2A„Q­_À®Ód‹ ·ỬT¬ÇHjâ…Ö”37 ̉hµ9ó ÍÊÍôÜM6µNƒ,2?á2 °ëZx''B/R­PHG‹íE 匠m4‹tSN#3“¶‡rŒªÎ,íôÔЦºè*иÙB›føBµ,Úæ›k J‘›Œ¬Kq›SüÆ‚ÂÛ‘×o2ñŸŒ¼ó°oª‰duí•»ƒ5’رå#o–mÎI¥}‡Úc¯ưUÛë¸5ÖÚd¿—Äg¯3ƯoÔâ&›5ÂƠ5ßdt£ë₫¾Uö®mœe§Üi« ˜»`Ù¶Xo} ÷.z¶·át«]·àm)̃ƠâyføÜj1RW-`¯s F/ưMTk̃Ë"‹̉ZØf9Ó«Noœèyh¶¶ºn£F‰æëÓô)ƠT¥ :°Ïí #M£Ö:«Dí"“ G·»¯Øl˪6¬Î{í³̣U® ÁÙŒœ ĂëpélF:÷o‚¤!É"Ág²n¡sÿ® kÿ[9Äw đwṇ̀—¿H¡Åßi\8‹¼©ËsĂưæ|¢Ï÷(Wå„óFǘL¿›̀UG8‚Zư²vÜüï,ÿ»đ‹4¯ÈqÆÿ}ô₫JÇürä R>ñÎ}÷ü2ëgJiok®Ï̉2Íf{í˜ "ăÁi>͵̣́ é÷Q•êèÜ©¿,¦íś©]F5ŒRز¶¿MJSS“H¦đ„ÀúIÄ|œ •mÚT*÷A°güZ¸"œ-„G8ù"Câ<’“ôœ02‚zŒ;³‡¤Đ0‚̉_Ó¦æ´ÎÈ0'‚zÈcLCÅqÆi‘©!©bÄèp…‘ñá ID¤ ñ!E¼¡QHåiPª2–)LÓ¨CĐ!A" ³ÄzÄ…^¼‰(Fº”Q‰al"#ăÆ)ÂñˆVœ#ùbËøC ³É m¶v4a ê0ä₫nv›‚„­‘zHf¾”B’iùÀ`&í‡I¶ådˆ¼đ5\A W¨@đǧû¸́#™ï¹€RL_ÀÛÜ̃́È¿È7*Ö₫Ñ~‰CC4×èơú"ÿ,\ï>W§/₫Ă;zÀ¹ÛÑoµÂÀ¸±LèÅ“m˜úïw Fïđ†¿s–p“ă?Øè" S‹¼;¬k¼:?Ö«‰;±»Ÿú×Ó¾Ü˪§»Ï+%û»;Eó…₫¸D@¯À¸èS=÷CAøË%{›»3‰4đsAë/™;AƯ+jÙ)˜•°<l³pnHƒmƠ{»>«̀¨¼‰ù‰Ÿƒƒ S› ü“½«/A ¿!ô-Ê®²ÓÁ/$ơ+ ’4¨)C®ˆ?£;µ±@6́ØP4##ĂÚ{k¸ơÊ'v臡›Ă'ûđ±%tº´»b‰¼÷‹ @cÄ*³”[C ;Y ”@ñÛ¯¯ñBA4”˰©› JüÄ6s=«‹Ù[=<”¼ø©Àx3EÀà‘°>N3¨ĂÈ6YÜ l`‡'à•Ú볜B¼ë³6¯b   ,œ“̣₫ĂÁ.,½/<4ƒ‹ÀVBL=öSĂfÔ=µR0¶€ĂC¼FĂSnÈ‹]¤¹Œ0%pêƒÂ™t”‚»xëÆÿB4Œ@Ç(ÔcÂWjÍ’A©º…ª†K‡cĂ\%ÓÄx„$RD›{ÈS|ù 9V<¤ô¨0{² €';@‘̀ÛH-ƒ"-K!½*Iœ1Ų·‰!’̀ 1”D¿n"¿Êس-ÜÅyô r䮬#•÷’₫S¨Øh5ă¾¢è‡‚̣!¤JÖp¶©’ª8Ô*1A$‹l|´4l»RüD7”A™s;©Ü ‘¨Iß ¢Éº„K»¤ ₫½JÉ»L¼dËÜÈÔ “4£oÂv0€—Zˆ’„¹´É(#-êĂn²Ç ŒAÇ£LîB ¤pÇ:T1œ©À¦›¼%Z,Î ¢©IKIéÀ0Lœ8Đ›Ă8|Đ¹ˆPËtô8Q̀´œ=ùTK-;Rs¬¿ ¢¿tË*˜QdL­øPæ„Q%Q¸4ΕQHMRưK…§I‹€ô€ôÂpQHuL₫ÛŒ°©̉bÆ Œ₫H³›­û>a][Ûä]cUP”Ûơ ˺uÖ€Eœ;­7H–ưÓPñ•à̃_”À`¾aÀt, Â8L Ïp—Ó2Fú+nànb~b)&Ùé:đă4‰ẫb'æb-îb0>¢E1“Jz›b0₫b5†â".f‘—‚°œŒh‚ÛEÁë`‘hAeáêÍƯCSû6½Ñû^™‰È¯Ô㇠YÄđnPƒ¨Hi˜‰`Ê@ưi!,ÇàäËĐ)©édPöäP₫dQ>e ë 4ƒ1‰àÈ ă4r›8Ñ̀È0Äl=¢c²Re%Kn˜Os›X;`’̀d\₫KeVNæ]Væ#SegfæU^finfh~æifj¾fkÎfjÆRÖº‚΅2G̀°„ ‹Yΰ|"KgSgwngxFuçw–çzfg{g|̃gzÖç~nC‚X^%嘤ˆ¨¡ƒî²USh„^èHkhˆfh‰~è‰Nh¾h‹Îh‡Ö舦æt¾ Z‚°†óưBüùà~«½]›­ ´+&áFlÛ=VD>9e֮иK̃‚Po‰j¢.j£>j¤Nj¥^j¦fœ¦~j¤jkX‰¦oІTjnȪ†j°k±k²ko¨¡.kµ^k¶nk·ê₫V3‚ykº®k»Ö•‚°oظè—[‘éM ,³Ûưa=5́ëmƠ¦—Ô.íƠNíÖí×ví̉¦•mH˜„™mÖÖmÙ̃íÀ̃†jàíÙí|Ámoè nÑÖí„)@Ó̃mÚîíç–îáîè¾ńnë†íí®îâ&mè€iíî¦îë6oÙFoïVoèfoíÎnƠNoỚnÀñ&mávïøîn×Öïöæï÷VïѶmÙ†ÈÀÈĐn¨KÚGªÁc•O®º?₫ ¾ÊAf<­$;½iœVä€âă G¼åĐP2h2p'h‚&˜qw+°'h×qçq·̣ïqÇq ïñ!7r ÷q$?̣_̣/̣)ÿq(̣¿>+P*÷ñ!ó*ßq'·‚$¯̣!¿‚p5°0ó+—r'çñWh+°‚¿ñ>Ỵ̈&̣âSs5r%'̣&Çñ0sD7r,/s,grG_ô —ó/Wô1̣FGóLt@ŸôNg'¸‚%0s/5—ñˆ̣¯t"×ñU‡̣3÷ô9/óY·tX·uFwt2—ơ]óX·rW₫çơ`̣avH/̣ÿ--°s7souJ?tIçtH·ôDô_‡uPÏöMsp¿vqgôØà5Øèđđ·ˆđ!Léu^i²jì^My4áûÊ`óâDVl ÅË®́~/G¤Ç­à/І¹n ˆ¸k‹kZ¬•‹·–‰jáñ/ĐjŸˆ¯̃x“?ù§fˆ´&êGy—yº^ù£€y¿xmĐààĐ膘›U¼ă<^xùºp÷‹…ÛpK3xäcPC¶iWx ¥ÁNḃ½Ă`@9²Ơ@Œ¯÷°ŸD²¯ĐÅWn¼₫IŒoû®(ª ¼ÂQ{KµWØ~{³/û–ë{Àÿ{Ág¹³‘à°‹øÏâûÁgûÀ'|ÈwüÆ?]Ê·a»@³Ă2]Ö]ÉüÎÿüÊß{¸÷ûÈ·À$" @pØúNHD@|Gß=¦Û>æÎÇÁ²EȤJ‰C áñ¨$qăEVÍ»Ùħh"Æ]=¦çW~îMâèo~è_~ô‰°±{æ¯~Ù~ë§₫ïï^îÿéÿZ>ưC4ï/ÿơß₫öï₫ñ7öÿ÷?ÿ?µ4Đtúßÿđ¯ùˆÿùh° AƒëªăvåÅ·ˆï&~ṣ.!ÆŒ7ŕ₫èñ#È"5¾ûÆââE‚#W²lùño)œẹ́&N₫j,Ùâ>Qz³b3'̉¤J—ôy¡ĐwÛŒ2­jơ*Ö„5cƯùï×ûh₫K 5+Ú´jU–-ëäÛQ0e"4»ö.^¬(ß9d—2ñÀ‚Eî›X́ƯB”m½ń˜#ß‹̉ÚN,Ëø1æư•Zy§?¾3“F[rồ³¥­Î½8V(ÙƠͪ~WôiԲܨÊî½Ôéf²¶yû.9t؃[ej5îHà„Rh`…úÆÍ;H|ó~)&!†%’xâ…(Ƨ̉;́DĂA^Ơ÷/ ẻˆªƠèRkͶ£N<ƯhTvu•uIjXOAUÓT?*9¥KËuUX̀½Æ"lTz¹‘‘ÓU§Ukª÷%Ö¥iº9_ßßvR¾©dbïŒ1ÑB”Ư™—?}6cgH₫)ÛY§ÈÖ¡$…µåYm:G[BĂáÆ%_WØÙhfRn–r:êA=*WVr±‘úetnÁ•Ñu@5‡hµÚz+®¹êº+¯½úú+°Ạ́ÚÔOѤ°É*₫»,³Í:»“:;±³Í1 µÙ³Ùj»-·Á:ĂÎܰs¦WƯ{n³1úÓ>ưpx©T®*[}Ñ)騦 —¦Œ=}óS‘u:oiL₫Ä(‹Qܨ•Zaùè¾/́\˜Ô«‘£»1Çï_Oû¤Ç%›¼±>ùœ6®J Ñt2̀17mAWlÓ²ËÈʼ³³ÿ,”O?AÆ¢7/l:1V‰â¨¾öéAJRÊ’´R¶ÛÑH¯Ü“C ¬55Ý0ªcv 6­yqk[^jbq[8w†pÓmwƯ%}ZÖ–w«X÷ßx ø‰}răÍïtààrîxă~CaYë₫À´âQWFøäK₫ùă>/d97ơ%qh¦(zM;=Æ«ÊeM±e50e_«¨̃N §đî¬êäWç&qđ™U;FúÚƠ<ôœƒyèƠS_©JÜØÇ–ởwïù÷ÓŸxø¥o&ö̃_¯>ûàÿç;/xb¥­ï~ûâÇÍàSAÛ¾}̣®R›o4aQ®;Ô;¤±“ÄX«uR»̀Pf5”8dvü ›¸TƯ]0me»̉µÓADñÍ-făW ̉·Ú¥ç<ú_J¢ XNPÔ¸èD§ú¬'ûpˆ"(¾ÍÄrBÏè8₫ˆpºaŒ&B'hi,}ê₫bzDø¼0|^¼ßô6c-\i&q9Êó—Füyn'Ă³Á¸Æ.Ê‘QËGA8d')P;ü̉¢·! 42̀Ùó’Ô¯ưÄj¹K]“æ•x‘LÛ½’%×D́€—̀JÅNØ“F‹¥y:’8uô©3ÿ@Đ*•h`C çÔè®8DÑad!°„¥B”XV™:”h!?Wä%+•øÉ¤ˆñ6—Zä4ñ‘lEÙ\BèÔ}„Æ›ßĉbB´́ ḿ(G]öÁ˜D̉hj=©ZnøÉs&8ŒÚà>ùyœ*“ŒỤ́̃£2‰%6L-₫mùJiúr•ÏLˆ øØKiÂ2—±æ. âL%ºóÑÊG2ÛÂJyT‹= éA5ƯÍ3¦ tcª‚´(›î‹ë€Ö;®ÁS¤“•?…àÂR¢h†;ÂfïI”€U$L¢ÊeP÷Đª 0“ÓR'¹*À:-# U• I“u£Á´h0/J̉¹NTASw9Ä‚ ¯C9‡µi– `ƒî́ ˜LA´æ©[œ›UeŒùú‘̀ÍäX’UÓ­²TO₫) © ~₫ˆ¼´ƠŸ˜ÂÚgWb)Pª±MA_–Û³ƯV) åPH 5s–fˆ‹í!H)₫j€—&V•¹Ôe,]Ú̉èºt£Ñơ©ËđĂ ‚¤4±>[ßÚÛˆª ăE©I\‚ʧÙ3ßyV«>±#¢ëu_èä‘•²FöôÚ̃¸w$ÛÆW.ÿ"¤V ¯¬Ç#­‚ƠD…:.ưMkf†Ø's¢‡+±£âUå‡ÿ1bđÆ2‰•æEÈIËʰØVdY.—kƯ'ˆ¦æqưrºZfn(÷†ˆ̉·̃:©¦µ,ƯVÑô2Xă˜/ZƠ³…'úŒ̣g¹æP9'u)«n Zæ–üv¡Âu¨s< ¯ĂĂI4ñw“bG³OxÆå?  ₫ʶ†x‚®.GF  ,ÄïĂd´XK ¶xE1)’:Ú®$As–¹β̣̀Ö CO~|P4¾™Œ‘ö$À¨‡̉\äQ—·ÓMiRF`_¤a§ÚdCLl„̉ÍÎ2˜×â²Xˆ‡Öâ÷Œm „ÄÔfñCwÅ dpÙ"ù4ó˜̀YưƒߨS„4”’̀©t ”ớÔ¶«ùö²g«A]ûÛ VsÇ™]Âéœ&g…s’ °ârĂƠÎÜ–f‡óụ̈ w›æ/ß³º¿Ûí₫ç[ÅÚ–8ƒ€ƒ³CÜ;¿9Ïơ­`¿x£€!ÿÈ–ü̉„oxö³:2#ëlíl&Ù^Q­•Ö`Nù©‰r uQO2R•öÓ9blƯ"j{³+\d̃®=/£3ÀŸƒit-æ\Ư+ïö¹³Ư/¤LE:ŸÍaA÷\Ư‹ÈHïọÜ–«‚-§ja8îqGa¤Nơô©ëTë÷xíå΋«ăDêªz$ăÔ|Iq´øká_v­×¦/öÇ…Üz_·V'oê”Öáx–×Uæùfëà_.:£ÏYt‡Îeˆ¡ár£_¯:~¹X9ô4°CúxÇr¯/îÑ₫iÑ æĐØy߇fÊïˆF–-ß¡Q]TDJüĐyÖÍ”Qøîå^XÔ”LÅ\˜]•ïD…%Ÿf́–µÔ]Xy ô‘œ³íÄô^¨œ@˜˜Ë¹TµM̃DáÜáùœâ}¾Ùà*­Üß1ŸmX̀•…8À?@[ ±̉ù/Y2 KxL`@‘\ˆ) —?˜Ăí©Œ7‘ïI‡¬…µ:Æ̃đyYù›§dOp! "Ỵ̈ÍoƯ!‹H¨™)•’ útE—*µ”/9×D…”‰=“¶ơáMâfyðC?ŒÜiíĐEb₫vÆ5ÄØñx JƒüT¥¬ápH…} `́•N­°CÑg%•ĐźŒ‡*6†ïUÊm¤Ç›Á ØÛ â²éa—”]ÇåY"ß%ÉXđ•ÉUŸ¹ØKéƠ="Ea0í™76â}DbxC 4Đ:DZ^„}! 5#Jôblq†_pˆ) =¢M\ȈkÅ̃7TĂ«ưƒjÁ‡ƒÈZ.̃‘<`=Ơ¼áƠßy‰YSa ªÉÚ Èedº ÛH#ôáI,EL%—K”Ÿ1×ăÙ•Gi£6̉UJ$7DI>€BØ˼F1—‚¹L‹¤–ÉƯá™L70₫FCUẃD¡đ,̃Ö;¨ÀhC5|CéĐ¢Ñ¬ L™œN×l¥Ù©Ú• F₫dï[‚y$³1˜bKÄÈÍHœQúÈG°¢)…N\FªldF|ƒüˆ`¦`&a¦a&bJ‘` RP¦ ½Kd(¦`Bæ IfeFc ̉=^f`²Ă»dfIÔ¢ˆ„"ev& qfb¦¦j®&k¶¦k¦¦ IÄkÎ&mÖ¦m̃æjj&_ÀE`Ún₫&p'k~Ặ¦p'rç7è́€x6DD7ѺŒØôH¾IØ5]¼d\Ơá0ª¥c}\ 0Ghu‰éåÙ¸¦ \ú₫ÄQz¸'Z-ÊNÙ„,l¨VwÈ'g” ”\y tƒ7lĂzƒ7|Ă6'q6è‚zĂá8(„ç„.h…Jh„2¨ƒj(…vè…rh„†h†–(qF¨‡*è‡Fh†’h‡bè‰èá h‡Öhn訂V¥‚*h àèŒÂ(B(nh‹)ˆ"éˆ*©…2ih“®h” é”Bé“©”^éFÄ‚rè7hC7Dç*(–R©–.i–º(©Vi™Zi›©›&i:iˆÚ(ƒzC6hƒ‚^¨œ₫iœªj*›ê¡J©UF(5th7üh¢F*œ"ê¤j¥Jê›f*₫Jê‹ö€|*Ø€Ü@7̀\CæËØ %ýă]l‘%EöV1R̉’gGÄ G§kØJ}Îe …Ä|¬ˆ|¶„\ë„üذZ†ŒPXó°€ÀÀ8ÁX´€8A¶Z«µj+·zk·rë¶~«¸‚븆+¹¦+º®ë¹¶«¹¾k¹Æ«ºº«¼²+¼Î+¼n\¨ÁxÁ ¼@·:¶b+¾Ö+½¬ÂÚ+Ẫ+Ă.lÂ>¬ÄFlÄRk\ˆÀ|@µj«¹R¬Ă‚lĂ,Ƭɒ́ÄlÉÆ«µ~ÀÔÀx+ͫȮ,Φ,Ễ¬Î*¬Çf+Ájëx₫ÁHÀ|@ ̀ÀΪlÏ6-Ï>-ÓB­¼Î€§̣|ª 䀘êQö<…]XÈëM R‰Ê鯬2ÙIm!#1‚ Œä~[—Q’°-̃Ɔ#µI²¶̀~¶çßNc~₫áêÄû½C 0Y¬7¨æ4HrF®äNnbz&íƠ‡qR®ænnä2¦7°@ir®èîmâ‡T€L®ênn‚pĂ»\Qdîêήr̉€ô€s̃À¸@7¼‡HĂMºêsp“9±íC–m0ʪÛ”¢å1âªÜ±%Ä`]Ưº¥ơ®Ö°º ¶Çơrïỡ¥|á ÷Z‹÷’o ²§ºˆ¯ß–“&₫¥ ¥\Á©2ZºƒŒœ¼đ îÄ9đ%®~¡ØÀcñT̃"DJÙị̈öÑ;| lí D§7hĂP]¤ 0§´Æ;đ$¬mí´]>Å!xîxôjN~бªáú¯~Ú-άo÷v¯ù®ªŒ¯ Çđ ·0}̃°[îD$®ừä?PÇ¡D5º†bF[(1/q?±GqO±X@13qKq_±o±c1wq·…9:¼ƒ6 J„ÈN˜a¥ư¼q9Â1zı×1Ó±Ï1˱ßñÿq÷1 ̣ c‘œ̀ÄûÁÉ r ²#̣#72$W2₫%_̣$g²$„4¼CÄPfđvЉ½Œ²)·)oQ)£̣)¯²+«2,§²,·r,Ọ́,·…+‰_q60è1e˜¡(31œ1ó1 ³23332?ó2;s4's3Å |RƯpXCåØ_îÍzFđfÅvê0’p™ƠªÛƯj ;ß ÷HƠÑS ¯° Ó³8_˜zé­=׳™̀Jà–?ïó=ïe™J̀7ä²°zCÛˆCÏFCCôCw„ï ñ́DRtDkôDCÆF{tG“d¹W”ÍJ´H‡4I¨tKs,}ƒ`K´MsôMƒtN¯´Y1Ë|₫éEïôK uO³tQ5úö‚Zee`ƒ5ܯ{……éßwŒ3tœ°í—ÉáÚ.:—đ™U–ØT‡} .]’…¤Ü¢Ÿ˜G…4IÄQ8[›\·jP ›yø7LpæäAüÓ3₫-̣:AÑ"“wY¸7P˜÷$¢÷©7r÷P{ËJ|—÷ZÍ·wá7{¸x¿·~g‡_PX³waö‚ĂOƒ§–c+N„öX ê-ø…[x…3ø`ăG‡w–ÖQ¸„Û†ox†öƒ§ø‡‹¸ˆ[¶)º6âwgw¶h‡ö`ă$ËäBj6j‡7Ûøjăøç8?¶‘Q¹ăx’ơÉàJ†́l§Uo Ư³̣&ăYfƠó¶³¼37T&J”y°¾ôˆ([›ù²¢¹X–5} G›µ}¹ñ%/¾Ă<Z‹\]‚i: úŸºÜ!KI Ü…9–¡ç*¡û9¤;z₫£:£ó–• O:£G:¥sú¦KºŸ×7<Áêù³§/É£ƒºªwúªoú6ÜÑdú©o°¦£z­Ó:8 ShpĂœ·ǸD•?D‹e8c=•­}đwÛ̉–z9™¼³$~Đ z(ñP† Q Ñ—rB"ñ·Ë¹Û•ă·ưLÄXŒ{—û_œûHáñº²»ƒˆư¤^*û̀éyÉE‘Œ¯«K¹Xoù< #<ù2¼Â?¼ĂG|ĂO<ÄS¼ÄW<ÆïNàQd¨‹Ø^¼Å/|ÈgüÈ_¼É—<Ê“¼ÊËp‚ÀzĂ¯|ÊŸ<̀ϼ̀×|̀߼ʅ³₫¼ö:<ÎÛ<Íÿ¼Đç¼Á‹Ö°ï„m†Œ=Ó½ÓưÓC<Ø „U2D•OâôĐ¼†MI®iœ€}uzđï¤m₫Â-–T@DĐI>¤ƒÖ3%üø;…*–ù:*2¯```å#¢!úLo{|Fđ½9R×₫ƯkQ̃ Ñ̃–ï•ĂD < ‘H–KŸ´@Û³ß ỗ®đçtèïèw¾Ơ˜>¹t~ŸüçAxåóp~=Ÿ¾êW¯ç§>í_Ëíë₫êă₫́û¾íƒ₫Âi ÷>ï‹>đă¾đÛ¾ñ/̣ë¾ó¿̣“~à\W0đÿ>ö×₫î?ÿêw¿ôŸ¾çC$ƒ₫¼ư=×₫óo?ôS¿úç¾öƒôïóé4Đ m|‹€¸”CĐ S°%đZ„?ÿ̃ư3øî[‹‚ÿ ,ø›•‚)V´xcF9vôødH„ 2lHĐ›Ä+Y¶tùfL‹₫̃Yñ6‘¢@‚V¶½{Ç›Árơù[GP ÀuFơ5„öO]RƒO£6”ªîß:}‡EêïéѤI—ju Uê?ª%¯fƯú¯ëAa­-Û,ZjÑÖˆU+W£ró=˜o ·+=OdXó¦Av+âÄI™âeÍ•9gî|đ3fĐI6-ơæ̉©C«>ưđ×uï¤9Öé“ơj×¹_·ö₫­ûwoàĂ…çưó7'ƒóv¾zóèÄŸK·NỰ;'‘'^6>ưûơđØÅWŸèĐ';Qk_|üñóáÓ?ï˜âÑ|êă–ùÀÚ¯©…L A ´(9‰z %•œÂ ;¢é•ö:ém$´ÄEtÉ!›¼»m1Ÿ‚è v̀1J½¹,jª¡¥Ú‡¨¢ú)Êgû¯¬Ă‹±x|ª"J GôÑ‘GM ̉+'*²¡#gt̀F|̉Ÿ’’"*‡¼̉0iÂæ¾9±¡wZˆ,7Ë>³Ó4<‹Ó“Ïàú̀ÓÏ̉₫ÜSPØyÈ«‡ˆ"¨»@}”₫PHơ<®PH)•T><»KÎ æ.­oĐI] 5ÓJEÔù²ÛÎSÔN5UXKÅTUY-=ˆ›‚ÖA ³T_%Î×XiƠVbG;,v¾‘Yi³‘ É¬jvÂw6<(¥…đ{("ï¨ưÜŒ´–C³ Ưt¤ÉÄ™J"o¼ù€Œ\'êg/¯Å¬ÊØ"Ë £º“–&ï´Ơ×Ó~ṣk0!v̀?ÏB˜_ü«a[„Ø`ŸRv :s*ñ¦ö±£¾He‹g¨åư…™f–k~Ùæœq̃ù"­â†¿2™è›gÖùhWVÚå¤^ú馡†Ú'nxçd©£–₫yj­¹öºh¤»₫́°™.ÛhŸœxg³·v{l¸Á6:nº›6é'ÿÁf_¯Ñ{nÀÿ>[îÁß.¡CÄ*bu›Íu©hÏ‹Ùñ®ơ)!r{èÜÊ=C…dvÈCo??uÛơw o–đf›o>ØÂMØYü7ˆTLï§"ß¹FÅÉÖ™Œ[ÿ ú†v°²FŦ€fÎ̃à{Ÿ øô²" {qE^ù˜÷Éù\)‹÷ä©₫zÊtïî—o₫ ÷=tD²iQ¦́ÁÆúïÿ$,‰Åè?€,àÿ(@>ĐlàGæi ?&q  (ÁRa₫I˜Ap„(,!¸„Œá>£ƒà Y¨BÖ‡ ¼¡s8ĂöĐƒ¤ÉÚp²Â îЇFL"DʬKḷÉ@”ÄḌ‹Ktâ³ØÄ.Ź2­ó `\•º½ƒ ̀Û[öPV@3jÄZ*Cˆ†¶•½½0IW6®<₫1]a•»̉‚nè°#H́z’|c¹âÆ¡tg¯ï)ëßZ&Û'Éöu9̃¨øâ   $v¬Úú.™IM¶O“„È'{r(Q’̣¦ä*eù¼Jú¤•œ„e'gù¦Z&g”ïØJ.OéØíÎßxwfrшl€Ô¦₫̣¢wTƒ qâß6É)“ªÁ°œé PÁˆ¨N<:dK₫(AÀi:w¾“©@AÖrO—¼# ,ú%o˜ÎË €Äëœ?Ơ‰! ip‘wdèDYÂ.‘¡́^  t …o… VhÂ;đÅ/ÀđPaC•²4WL CŒI†0Œ´}c˜iƠÔÀ‚1@åMØÂH2Ó0Äï*ei‡^ª;™̉´C6Åé7t:Rˆôô§X*Q×aT¤*Ơ'ÛhjLgZÓ›¯ª<ơ)P·j­®6¦ÿ¸©.j kÆ̀ehQâ—¹ceS¯êtá7–ƒ³¼¶œ‚dÛÑ‹ØuÆI‰ñ«cO₫· ƒ|C Ü8 ´(»í°MZ‚ûăää×₫=$CílåZ.‡,tµ±%Ù‰Z·‚n¼À WxÓ›î£"ĐФW)Ⱦ`è^¹C3?˜ …û+æ׸¹;r+£Ü814­jÔp™“;O½ƒº™±.Múöv]‹&ÓäcvcëOuH¢íU'¹üÁlẠḾl椋F¿ºV„T`!,đåbkÍ—ÅĐ·ÉL¶ª¨>ØØq¡ÓÖÂà[` 'ÖÁ¬{äºáJ'Œô· ̃ÈÉ’µ•8ÄÅ 1 ^̣–R„Æ.±1‚?k )½C½Óê.`?ü¹/µENgSfC₫azXÉà̉‡;¶bÿº ÊQÖˆÊ D`-£+Áư°ƒ]Œ¬ùîoÂt,Dâûåfíѯm³›·9[B¾c̃ˆæ;¢yTƲk*WÖºü‘¬¹Ç!A4»’},ú1î¤#½¹ƒ ½@¾‰̃L#h:Së½₫ôéS_o¨aCµç¢†oDẰ«æ¦½,k%¸UFlM á‰Jø² ©0çælëuÍѲ*±ÉiQÚ>̉ 7Q–o/’ef ˜ ƒ àB€Ü“´¤øÚè‚'D®`ípOˆÅqúƼr¶s[(ƯĂ£)Pßm9Ă^¶Øơ₫'a\d2÷‘ȰO›½₫rë»Z¥ ¶üˆpÔÙYÄŸßO‚"G‡ƒbṣÏc\h¢±̣âή¨C.̣‰qº.9‰æ1̉ĐzåH‘Y‡c₫\‹Fåz ñØÊIÚÊ8Ù̉ ¯yK4,C=;GÙ;”À¶bñWH_Mæô æ „¸ç ¥₫Ÿ#$É]¯Đ`ªf̀ X́-ÁËlÄ×nŸÇ¢#ÏwÚ+Ăï³ûÛ lĂn¬#œ_°‹®àl6w×áw¡Ó=DÑöÈR/e¤6G<7§Uu‚4I}¥iæ!–­ ?"qaÆ₫/ dbH/+đ„üư„äˆ! Ë×́ßîæ̀b[Ôlܺ¥ á,đ ‰Ng ùÎŒ²0a FH.Q +‘d[k >À Öà^ \À Æ Â@|úÆ9±÷JđûÄ'À ̉l‰0̃ 6́́rÑØè«2ĐĐi/×n wđ€ ́$âcÏ‘-…OßĐø0®'¿`u˜Ïÿ£{†#"0]fcäå¨Át ´Á”d f£BƠ‡qâÈ }Q/ te5€ÑÖ`/énöøPû:ëe(6OÿêˆÜª1æ₫₫ϵ1 ÷–.ÈÆ ߌ ¿Q Ơ¢ùâDx$c•ââq}\²e,2í̃+7̉"ÖѸA¬vc#Kïœ̉`Ú#4†N3#'·ïynµtĐ«3ç’÷ÈèR'SæŸmç ¨Q'Ï@ÈQ6v I2@b'j ̃„ !Qêp#i+ïr6 {~Ä&Å.Q4ÏÆ’̣âøØ₫̉áö°ß± ́*ñH" " ± ¯̣²+lñ0ê¼FÏƯé@‹\F̣đ¥9ñ$́î?‹Đvs ‚æÉº²$äûœ¯0C kûđæb´Œ6”‚º,$Álà–mÿ̃O1äL:Ëï­Â'4ïÀº̃aà<[’2¤…cƒ¹ ư₫áuF±U Â, RZ KfƒU³",X5´ÖHZ̃!̃.bsÑàcR0ă6̃W6ĂNI‹ rú"ë |Œ;´t6Œ̣6ˆè> îNp@”Qö8”Gœ´È†g(óîœ"ó\öï:Å! 'Ơf¼óƒôÁÔá ư!῭`Qˆ5+"ĐH3#€U₫ÀHYƠ¨°²Âêk Ô®´Wy´ «ô´Wö(´  HyTd->½DfŸ‚Bvdy®,+L5%ÿE*„–-hSEÖ!h‚‚qÂhó;cC),¨ˆĐ·âÂöâDWN*´O›đÜö”2lD8¯áù,+6Ơ?:ÔŸ&â Û-Qª*Œ4rB¥1Ơ¶“_S¦‚ˆôA€*a "V¼Â=ŸPH·JÏOÎs VöJûÇq·q¯Tc„=3×r—s/V°Á(Xµ)ÜGÎJ ¦¬B!a‚=PJEs1Fˆ¦c åđ"₫L!ä[uR¹Ö#[)›¶u\ÂHm'=/O×ïg—q(kGí1&ÇI¶t̀¤Á0‚WbơçQ}(sDï+#÷5o9¬#“P "ÉdcƒG¥%u BJ+J¢b·Fbdbc«T6¶(@öà$*vró×oÁbS÷uÿa€]Ö`#g)VN·!,8€₫6aOWJ9˜U—‚`«´,ˆ1";̀” ÖAhS,¨Mç7r$£o4MĂªÜb́wïQmxë1—Ó„~Â0€¦lư©€¤P• 9r5´ èUnƒ3•R«IRÏb̉W'¸"ĂEÆ BÜ₫S W-°"×! UØ*8rγqߨÔÁq­„sSö)¶G*(7ƒ¨rK¢‚ä$đøg™}„ƒÏĐ¸Ô³Œ6Ÿêâ<„(J_ 83ïă‚Œ'o%µwRx1±scB&P2» "*„4ÓH–]S´‰:Mk2ï•đƠđªx[/-[g}[”b…Äd”=7ë K$#ae”"$öH¶dV-`t€)£27d±&J1•!:6fßá€"*Öp”x€ôKƯácXvf6JÅ .v ˜ƠA«­W°öP¶â‹­‹½2èă‚̉ ̀ ¬á§₫bhzkÎ'`ë„•'ω‡¡ù,œäÂ)}¢ÿ¡±×ÀAiù₫̃H5'qèöù²ón‰P‹«‰‹lDU¤/1-‡U­” u%Q†5G9w¬{Øưúrú’”]ŸË3úFŨA£%×XoâÙ=è“fđ†Ú¤†BÆnc>™FrÔ8s¦)ƒ° ‰ñơñú*­Q¯cÈ H¬$¢ÍèÆ ₫Älmw|QË—ư|KÔ¥gÚÙî́fs¨È H×Z\Èd…ơn‘Ñ,»;¬ïIIăêà•d-1±K(s":Öù®¬Eg×rđT¢â­¥£g_l—4₫²ÓU’W©Ê[öúâ¬ï'*¸ÓîPh*X»®&³K@‹Åx{¾»\ôÊ*eX˜̣9,‹Ï7Eoƒ4 ›Rj ѼIiâ°1°ÉÓÊ9̉"Åb–"‡æ$Ü’`;bG“"đÅÁ Ớºô“Ś$4‡™”aˆ¼q²‘cm’Ûk¿ ±Á̉ ́\ư°]øªZçkà’̀^‹›Ụ̀•Ă²Ûxkú‘Ô`”êëØĐ!xº("gÆÙ‚ÆnÄÆsÜ*0O#ËFx䯽D'ô8 µÔ¨(ÇKbí¨p§…¯JâE–"H°¢p‘ü$<̉œz0f!¨€vt₫ vl4~\1^ĐgÔgxI¼ä’Ă ŒĂFY~«¹ÑĐè"O•÷D9ØœzÙ̉SP'<{®cñQE\_»;o¿Û!^@gw&̉+Ử/Ó3]Ó'Ư^‚fÓ)˜ÇÓ/’Ă'¢á%?}̉Ù!W2ij xàx€¶ ’́Evi¸].iüÜ'z}áĐƒ#ÇN é\L̃n™îLgZĂîûÈ%%–Å.ÛËÁ¢ƠiçU'rÍøï®|Q¼N½ój`Z *À ÔÀ œÀ ¬ ¬ÀƯß̃ëỮïßë=̃áưƯ÷}ßóàí½Dñ ´àÖ€îƯß₫û̃· ÖÀ Z` øßă]Ư·@ >à Ô€v¬` X ă~̃)¾ @ ¬`fÀÜ}À~v€j ¼`Z@ ¼À <À XÀ Ö€‚¦U BLäÚÓ°uRBœ&u0X Ç@æM"§{SMb.|BÿÁC³‘úÛÖ+Íë¹»°ơÑщ²Ár)ß>—̃îåÅîïïó^ïñ~îë~ïÿđí¾¿ïû₫ív?đµ!·ñå%î÷>—2Iߑ䥲!zÀz€£f h奿’¨a J臾¢QÈ7<>z–₫en#Ý(ħ*,ÅéhsëO/½Û·]Û·]2»=하/sùăœkÁ’®¾AÈg̉£«¸¼ û·ß»(ô¤GûĂ6’ÇÔ«'û5}’xçüÓĂ^J½Ô'6ºw¶’j€nÀ &Ÿ^àú‡; ·uÿÔư{çÏß¿ƒï:|1¢Ä‰+Z¼ˆ1£Æ₫û¶Í ‡9<‰2¥Ê• *d÷Ư¿’₫²¼‰3§ÎŒ¾{ÇÍŸ¾’;‹ƠiÓæ̀„½‰< 5êN¢ ½µhÈTªVï¬xCØ/ë̀±J·ædªôƯ·«úZ.løÎiY³tẹ̈TûT¬Ïsí₫úưk´ëWˆh?|“éö_Ûƒÿö¹¥:Ó1Ó¶‡.Ư§P!f‡˜!Óô'9̣XĐb f&=¶óÂĐ¡-%xyôCÊB.(ûñ[‡BrĂëEÛ·†ß¾}@˜0,ÁŸÛXÈL.cÀÔ«SƯT$QëÜ»#oû“ØƯÛ»›¯;ÔL¬»Ï»Çè±/ÚmWú¾¿²ª•oËăGêUCùø÷ŸEXmW^nÁÅM}>˜̉;|eƘOrAˆ¡_5H˜Oûñ×Ö:ï¬ă’B°åS…ñ¥Sy).ER{E­ăt ư””\™…ÅX\/ G”}yR|̃8‘TbD.¹‘?ưèóÓo₫ Éd•₫$%DĐ6ܰhå{̉ñ6’]BXZM8&Jï81XV%ÙDàƒh9„×;‹­˜ •i₫WÓŹñv_{z̉ƒ]yĂH•eÿœ(£A&QM`J7^¤B–gYÁYæC›Æ8‘¥h‚Ú^Bæåd>Ùr„Îê7Hê9k•L±SÍ7'vëåó;Åm,`4"—˜Éâ÷Ó7gÖø,E‚5䨨J™i,ºÊÍSƠ₫§ÖU.xá¸ănx(˜5ñÍ5X­³;ëä±j }Ú̉‹ÑM„«¤J¹Zc_üVTªÓ͉®¸ÉưûªKÚr©.·Ùú“i₫Ỏ÷±• ©ă:ï\ĐqÉZ L̃^âºL\̉₫Ió[ (°î¡)ª\wîæmÎÖơÉ* «lô†Î…ÖÅÉô)PŒÆÉôÀ‰Á™ª¿ûZ›\ćuÙZW„0Ëîå`C<"´´Å]7}_ĂjƯê1Ưïy$â7d QÖzoe¢OJ éà,½QME+®\w§eôµï8–÷¶CB|ŸßöØ àç7Yd¥;ú’́BíS ½₫3 ?欳åo™GzñE”³xpà¾o4WïÂM°î¹ ¬vv-‹5¹Ü=’:`im#f’ÑsGbLÛL{ữ ĂMÛHSj÷đi”„W™₫˜ÍÎâñÓ6B }@Ó)ôÖʳUŸëC¶4₫aH~ˆúÆ ´'(‰Cܹ†8&kXÙGđÇw81‚ĂÖn"ˆÁ‡@p~±àX¿̀Ň/ÏLe§s‰N€GÑàäHHC»Œèn€óY³˜5m#&¤úa¥̣V–oi†Fl\R¾ñ¾¦­i8)÷¤:}A3kâMÊ%«­¡Î‹ÜñP»vxă[27~#/̀}NE¤_K&Ȱ#n¦|™CHª=Q> ỲíĐV›<µ̀…ja}¸FF³e _¤V`Ăop ’ơ³$N0‡)Ê„– Y₫8æI“`ÅL Ñ ¥v¿Nf(–ÊZƘJ í~2cb.wB@w½c Úâõ†0t K0¢Œ’(D“±X†B˜;—昒™ĐèÆ3ÍĘ5ÉV7US7=ƒ‘B ™›k.Ed·º\Z$T½#₫)0¤/ç ¼d’ ÈÂ'Tl8Å{ Đ>hù%ư‰6ˆHk&è¤ÙO®1”ưK–³́– z:!T#¥K‘…º¸Ñ—]«CaÓ6¼1$P2< ÉẻÓ›u’È%Ciz`z›<‰BCÑ—;nJSsÎ4!5¥)Q]’ÓJ3_­*Q…Z¢¢µ7̀ôˆRÏÉÔüÔ%̉ç7’₫€#‡@ (̃¸Âo£+†mÙË$¢Öʘ,®ísIéIHbF¢Çä̀Z{’™(L­¹ú‰“̣ÑqZIĂŸvô÷8ºV Œ̃ H%6±î ^™ Ö¸6.­"z‹ñ"6pƒIqà(Ř~¾6µîl cRËAÀ¡5& ™ml7xÛ·Ôµ¦-îBvëÚà6D¶ÅzÔX©ÇơØîÅẢ½EX̀ç©Ë4'fUÉ( ô»Úú‰]­·Q¾Í¤jfOŸ25q‹n9úÁ#Ó0NW£,F¹8̃T‚Ñ 0y¯3̉jÁ=ÀA Öh +Xá ÑHC ” ₫k¤! gzG5È0&üÆ M ä74Œ&dxĂ6†ZĐ„Q:Á bª0Îtb«¥±ZÆPâ§xÅ₫‰‹a,c7ÄÆ8Öp‘¿Áă0ø˜Ä&F±s\äw9Æ%Ụ?lLkü„ d@ÁÔ8á dhˆ/à„[¡Ù%/Êü±›³Î†‰xüÅ€Ê3’_":đ«2ˆJ£oƒ ;Ô;)Î$êpa¦–DË’³2D&0qơ½b‚s̃¾ÖÑ;ô9\€î±èOù͇®ó—äç0o ”ô‰£å¼ă‹¢.®9J‹knäÑÙ®B¬±%hœí~v‚Çø|`óR±qT-Ư~×b¶[‡DY­ß₫¨µ̉x¢e.Èẩá₫QÙÎ’`¢ñk¨FÓ?Œ­Ê¨Ă ô²CJç²é£ô¥o®m`“Ú’°ƒ^x^̀‰P"¥¬ ­\ëc¿AÚ¯Ăö§7MîÅÊzØøöo‘}½fZÚ†HĂjcÇQÿA>7- ó₫RÈôq†x̀Gë Ü?ŸÏKת9î…+§È2Øåä́anÍ‘…MB«[ßPé€âqß5`Ñ´?åW$œEjh¡(¯ơÆ7ë$ôâL™{­WôB_r÷(Ă'©×8‚¯'‚ç"¨kG‚±‚`âBLà@°ÇL<²vÜVæp₫Ö0åe€1bAe`ÆđR„уQ5±äó>h6Ơ0 ñ @ĐæÀ[óVÈr]ç‚wƠñx Ç"£4y¦EzaYI8rWOd0D ±oêqz½Á{ÏÄ{•qzúA&̉!uXHy¸U¸qowø‡¶¡‡›‘8̀t"†4|hƒø(xhˆ{[Wâ‡Udˆ¡Ç‡ŒÁdÀ@“2 ƒQX~ªe,äç/jˆO}E_8xzgGª˜32¤s§(‹×ƒ3T˜Ö\·h?è‡BEä4h$*ó_€˜rU€A¨K &L"ŒÎÈG¼apä¤Aè>¾ˆPçT:ÄÈ$ï°r$C₫Náè2ŒsC€¶ä1̉¨49˜!œ“'¶eøÆhy‚BaF›Ơ ø0ưèD¶UrÉDĂizP’?¹d¤‡PâæÈ%ù,Û¡ø(YTI®ˆi"Giĸq[´1ÉØ‘~B`ÍÈh›̣èŒ\³"Ij/)O6£’˜Ç‡êQV•Ớñjà ̉@’óäoAÓ“!uCä2]±wP™&ôè'öè’€öihxy:Y>1 #ư·wñ˜Üg)’–^I)œ†‘©D!?q‹÷’wR/đR‰~·^YéWŒ$)%’~~ªƒ rŒ@¡Q×Q’•jI`₫‰3Y–â·-Ø’– Yư×–â‰@w1ßT~©veƒod4A²́øgTù1™&WK’×”!å?àj˜I)I…’ù" ù^Œ–’‰›¼“†:©ư]ûUG"Rx^³œ?D€=¢™ù ~Ù;Q¹D•¾©,ư¥ÿ.›‰‹,I€{‰›>¡Y&Ç›^™ÿ‚“äI›DS/™p—„Ñ™oo [ DKM””li„t²4ù,®~̉-‰'¹hgM]9œ-¡›±¹i x–/$œéI4¢Ù\Ê©Ÿ¢¦‡®×0-ѹ´XḄ 9éz“9(#5’Ó8@₫&ù†¹ “˜ù¶˜D ¢ö‰€›5LÚ .׮LJ¬÷—x{%ئw—QZ‰'⦥T:¥ÅW¥.˜‰“¥̀§¥81˜îp™˜‰'©éé¥p˜ŸmúK""ơBœÿiDÜ”©™wJ£5Ú0:#àɲ)¨S›•%¡zÂd#[~¨AçÀ"°‘¥•8¦ÿ¥À{úœzz¡ª©¢ê©Oú¤­§¥™:ª qª—z—§Z¦h·'qj‚—aA"§ç*|JÁÅĐrŸÙ«Ƈ5¸;%*@-Cê”×ù‘€97—Ăˆqûs˜ă¹†,É%"7¡ Â₫›Tø_qªØ€!3]j¥˜ê‚xªë «¼¯á¤a¯ôR¯ü*ª°«\J²ú¯Ú¯ŸÚªÛª·º‹Å¡9©¦©8FÇ:OYú``[…F±©Dzï€8›–t¢¬è§K.º'V)X‰fX\Y²jZ¡E¹ 0¯3ëºê ¬z—ÿ¯‘¥›Jª뇮áóJ°ơº~&ˆªK»—J°A [0¥°j´Wj¦Ÿá*˜Åé•rhPÁ8QÔ˜Z`u—ï7§å­mK Øy­ñ˜Û‚²P›̃²­?*jAz:³¬EJRùœj‘³¶Qµ®₫ꪰ¡¯!«°©ùÊ{”û©úµĐđ¸Œkz  –û¸‹µ¥‡¹—ºK¥üÊ´Ÿû(–{z£‹ª-̣0iê˜kÚEwëI¥Å Û€ JpJQ È 4w6m+¬i²ñô§{â‡Ú"„j'†Jp‰ @3[»5 9«à³¨ @¥²¯ä˹Wû(M‹ºëP«S‹´ä‹º ¹îû©—8¯°Ñ¾ó+¯é«©'ª«ô& q-¸û›÷¸l‡g<4sGp©eCÔP¾Û¬ L'ÖKW2ú­Y·BI$yË£â™ÀRh‚ù¶ưëY@ÙË|ê`ï©~踻©₫¬»¿̣»í{¹@¬¯úùú¹ñK¯»¾ä«¯æ©U 7ܹÛ¸8L¥’ûz9A5‘'´;¶©È¦‰Ĩ€#A–Aˆ*£­6ÎK+¦ƒ¼Êx²óK‚Æ$-+½¾ ¡JƒÁÆ)¸̀¿¡½ +— +Mÿ § †¯Đ‰üç œ[¾-aÈ Áƒ`"[§ªæ»€ˆ‚LPª†\‡¢\¿„¬°È ¨³Sºi:%É%2q^Kø;zŒJjéÜà [ĐO2DµrlËI^  A=ZIMĐJzCq̀4¬9@åà·́8!!·Æ×;®Á₫ß0ùj₫pÄ“g†Lô¸C!¯…œÊ­œG<̣ú¸ áÎä ¢œœ%ưlÉ:k₫Äó Đc¡¯´¡É"ơlº’ [©7É=Ø8Çy\Z—ŒV%BT\ǤA‹J Â3fùB¸¤*(́8đ̀p›@éa;¤èO#_H7HU,—¡øa•‘w§'Ü•‡Ç#́Œÿhr—D=ªrÈ7DaH#½–!¢³‰ i<ø8ÍÊàË|xèw‰¸°qˆØ¥xfWíªmá¡U›±”%s½ÓYm/a0 4J˜!úe0ñC)1ÅÙ₫„-w̉>©‹‚!Ư%ƒùâ°™0đÉLf›1ơRñ¡œ£Ùª·= €’]9̃¡BÂ5ë_ÆxÅ:{­5:'"IúËqCtÈơ<.g/œ8¹]¬…›Ø€ËMsLGt·ư 0}½h\ 1à„2±®;„}( Ư¹½ß']ñÙ²us“Ôx5$2Ư›‡ÂY96!ªí¦I* ˜‰æp+"”ÖU’¦ª”vغhÂơ/DăQYqdQÅîHà…YÍ ƒàJ©#Úü²4ÛÍƠ½-N­1ÏSj©n1ÖYzI ‚„ˆN9Ơc DKê ÈÔ¯́ÖÿÀƒ±̀ƒÆ7rYé?‰£áßG7Đ:Ô@l—Yíå`N³7Ñe“X=̀Rœ£¡UÙ=C6ùw­̃O|‘úd8=²­U=´é䢣ʳi ë%C½ûØæ¡¹Çî̉ox#¼ơ₫₫ÖpØƠg}ÑÀ[֗ר%7Çt0G}ྱ]Ç”s®F}ge}â₫à“só.9î^î‚îÔwïÿ̃ïư¾n5Đ<đ¡>Đf,‹"] ("Ë̉́ƒƒŸ Q̉6ÁÙ5Y'œbÀy%h̉̀¢Æå¿¿Ù#ñGÁ³Bb&ˆ½ë÷ñÓÇæß%,FÑ̉lÈßP7đq¶fNÀjp[đW 3fôÀpN j f,°jÀW`ÀôPOơkö[oô?¯àô,`G¿fZïpôMÿôXôMo`ôrơrÏE?càkàôgôNđV₫ĐôEô@pôWÿó4Æ÷4¦ö3&ù4Fc>g@Nq¶[°_@=à8à9`4đö©ßóc0AÏO‘]“”܃?I2?8ru»ËË×(…³|\m d@'¯882î;æ­¹…¦GPœ́bx¼q₫^w¼ nŸNƯ0ok´Fïæ k$´¶j̃@₫JÄjÅáự†₫éæư ±₫đ/ỵ̈f₫´₫Jdÿ ánđŸn'å₫±íÛ6oß ü¦Í À‚ ~K8ĐB… 'l˜£A!r[èÍ[7=pôĐ‘²Û ‘- zôfå»ÿüù«‰gM₫=}₫TèP¢EEtè;›ÿ¸½Ă´¦T¥U­^ÅU+Đwï¾9¡ºÚX²e±2ưú-́Îa;…;¶«¾ £ÆÅ›×¬Û®dØ­ó§Ï­^ÂE¡zcºojÎÂxßƯôù.&Ó8™z•ÙXóf«’eêlÛÔó`Î¥M—µl±OÈï´́[ölÚµm߯[÷ñ½q·ơû©W‚/tбxlŲ¿q›Ó2đЧ­_7úÛƯÈØ½oËN{̉àÍcßäÍó퓲å)ợ×̣îí+ơz₫ư·ï¬¨ªưø ²ø¼jẠm4¬Ê)ëɲm2ƒ0CÍ$₫TÍ­ÖœP1ƪӰğ.[lºº²æ bGD*¯œX H#‰&ñ¾‰JÅ#Ÿ4̀Ÿ}fzDö*„̣ºÁ„ô&º,!”>ëụ̂ÄÿÑgº|l?̀(­-n0,3Ă Ac̀Á:÷*µƠ*ôÓ¦-»‹¯§°54ÑB-²QE”QHu4̉J)%±2›nRQ;íÂ'n¼™A-4on jl >ụ̀̀m¼|V ;e‡É×´ƠÄËÈøF{mŒ-K%£•Xđ$¤ï1e…̣o5á|̣Ơ©&[p§Ë&{¶=f3{ƠB:»Ư“Ă?₫yjíLă,‹Lh;ƒ·*wƒZ Đ4›âæ)nl*GBoTP‹²ÿ1è…®†Ew@rï³ YAÖή̀Rˆí[đŸuØ!ïu.Ö‹´›ºúf\7s–[w~6Z¦̣QÓZ_7Œ[M/ăæyOùBg§³Œ[«mëL@‹>wDR¸i¦Ÿ₫É騡fj,§Æºj­k}găógQ·`GÂË̃i΃o264–‡ö§¬`n÷Â₫‡§–êm»Q¶ÉIµKÔï¿ ‹LÛYw>\,œ¼Iaˆ]Ʀ~4œÀ6k–)ÛÅôl¼0f#wµ-ŸC7Ñ\å₫/1¯¶i₫MÑåIöœl¯‰®2F'Û}oU±̉Ñ>vÆ<§'Ï3–rö5qo^yyGQc°v¦Ö¶a¡)ñÜ–líi3E;)»Ú±üï(û¸+nîơÑYơK^ŽƠÉ|₫¥X ÚdưǺä(“?>Qî10«̀"&ÎÁ©GsbÜÿ:ó…ëZ₫“àw´å„¤Ñ̀e’Ẩ•̣V:©&"¤×?D$¿)¥…5i¡ï¨².B©°o/´!QJØöà),ú Ü £uxæ—Ó‰đÂצ¶Ñ,ƒ›Ù‰A>»'ê…my›É°$TÅbåI;!`}$₫E‹[kx1—ù£TÓ₫Z *HimÚ·̣­̉NVÔ£iü´:‚umƠóăñ¬fB)M]¤ñ\bfÇ»äµÅsĐkN%oGy°Róü3ÎŒ¡ĤF÷ÙX¦>Êfy’“2—ÙŸH4yÜ&gT‡̀9ÁˆJÜ  Uô›@£&*%pO¼ùĂÖkËMV¸ËÚ„.î0Ç;EZSíh>©Đ$å÷„çíäiĐzBt•‹¹{ú3f2L› »ô7nq|áDÍT₫‡9”Å‚ñ”ẦØR¦tû £uEY%‹¦¼Ê7:¦ÀnUIZÎëæÔÎƯt?íÓ„zg:@BƠ,ƒDf´Ă¢4€2ư©NÔ±~ 0gµ;ç ™±–o4̀Ç„Å)Șƒ¬<1kØđ¦"µ'vuë:M)×MÍcw­I^ÑÊצ|́”ˆ}₫×̀ơ&êṼ¼ñØx,IÚéRÙ.×ÖʪJ± tvÚ=&©ß`$k±";ä#o¡i1†¬™.“dCÍ)5ÏMEWƒnºfœ´SUÙ̃I‹xd®l÷øA@Í„ƒCÈàí¤3¢剓"₫£ÂS1ªä {>^ÿ́‰x›B^‡âd`éḾT̉)˜¶¼÷èMèxÙ¸Ü=J½úmoñÙ5=ÅkÿÀ†œbâ±ö1ÑQ̉EJÚ¢Ó[ #”YM([‡¯Âüñ«Ei³½è̉t>CåÙUL;ăZ§ñÁ–SÁ)b>®Q\qŸFÈ’y£,Q 7¢N]FªEd£‹2O¯øÅÑ’á̃¡„₫Áµ´‰B_‹Qz61]¸¨†\¡Ơ4´Ô¶Ôq  Ê}ÛÍ8•Ó.¥nÂö‚’ô ÛđF`…}ưƒWƒZ¬‘†1$ûƠ C¢¢–&ŒA=ÚIƒ´½²́f+{ ˆJWœ°…&́‹làÀ´¹ílhk›ÚÖNr¶ƠÍlg[ăÛ᮹ÍîywûÙÑö;ª}mnÈ{Ûôö6¸c3îr;…ßÛhËœà´À l¸‚ j°…t+á ™Æe®xk¢piæ&yxEµ ( rFÁ·q 4rÆ>›¬Å¨¦!Y¬¨Dä̉j|_Đc‚®Îs9:j‰æt.¿ VÆ /₫d9pZ0́DĂ O D<åíh́Ïy °Ï®ñˆd=$ûL¸{e8I6»Öó%+’y…í’1§ßƹ‡]ï}§{̃÷®v­ÿƯíâü•ç₫ƒ¤%ß Æ7fĐ ‘X̃TSÙÜĐ1Œ³“£Üå ₫Ê•DÏZNÅ ÀFá/«øéC´Ă[lµOÙ"¦P²P«?µH.l.Wé¹¼[´µc¨#Å2@Gæ7^Àyµ$áq—]ä›Ùu0%Â'Ä"M˜ÂÎJcü̃Ço÷4“í ”Á04shÈOócÂéï~Ûo½÷ÛP<âÏ'¡¿ó»?đS?ù¿ÖØ»ñ₫º'›;!Z£æ[ma’H“Àđª‹oà€H¾Ÿ‘-‘bK1Ó¢íĐ½Ó¢ ¯h‚06r¶́@‹À¤CmµŸê1 ú£ă#¹q:v0$ó¸&¶&4 ¶¹¢Ư!œ]Ú¸‘éˆÂTÂ#ü U·ÏÛ©–ê£üàA ‚® ‚:™® 9ÀŸ|’½ÙC9›É¦EÔ£ô&[Ä£:]“¾s!¦9¢·a4¢Ÿ‘ <©)«xÅZ₫”Ũ©1[\±]t›N DbV<½À‘8QÄ"ÛCF®¨SñÄ¿IªÜ¡DQa‚ªÊĐ ;ó¬{Œê‡Qz˜éä"¤{*“ª̉ÙÁeD’\c —9ºî˜)w’d©¤ Çß“) BœưY±}–E+0lÁ‘«! ¤'^ú™[¼@’9ÁQ<̃»°´›†r#˜A1Ó '˜–^²-Zt*‡)¤'Zµ8JÇ⃠[s.åK:vtÅ!Ë*‰,’³áÇ||—]ÉL9H́ÉKÓÈ<ÔÈúh %DlÈ•w°¬M1H“l>ü B£a$9*)5˜<5·ux£₫"¢9MÊ­#Ú (S˜¡HL´‰|P‡¡JÍ™Áј|ÆÙ{£ªº 2Ô5¨0jô9ôIIÁÉŸ́ÉAqJ”;LSCcQB¯ñ¿2JÙÓË\J§~h2¦$.AtÈË„ª…3Ä×1&8§|À‡-MÔŃÁ$—®ĂÊ"{ÄÄYJ®ºÁŸ’ËZ{I¬,™Ü-̃‹ÅÖÆÂ$̀5̀Å\Π4Lä¡̣ ̓TLĐK †ÿóJ£d™ƠÄ̀#¼©VIΔs>äG ,DïŒ&ư vº tZLOƒŒ½Y‡JtN[q°öG(>ç2GæĂ0¦›ªuÎqG)₫²¹h•bêNÔÊI ÏÁ=é|P*ÂÇd %ù¢7²LvF!|5ơ¬¥%I–´´ªf\Ô–+a3éáͬ"1¼Qóx2°ô£Ă©¼D₫ÈD:">åZILK¾ä9ÇèÛ­3™§ñ¥Åä‘Ư•·YNR‚̉œˆ Å’‰̣G^)J}îc}y%v™Q`ºŒ€zkƒD)ÓO¬Àm˜kĂAöä²́QÓø,MC‘ ` s 6J‚…<ö<ÏéO\Ú Ù)R鲌’‘§Ă ªPÄÊ O§<¾úĐÔ¬à.$ÅĂwx‘!jBmĐà¬$ĂÁ½´Đçª9ÂH¨qI!₫35Ë‘ƒá†Aă†&ÅÊ˧è6DÁ¸Ê*M9³ÑÊcZº1É"C3ÏuÉoHvøœ‰Œ½BåQ2WăHKÄ¥F‚„%™¯°*©KÀÁlNL¥N蜗êdLÂ\ẀAÑ’Pu£ÁÖæ)é̉ÜkÓZ̉ V*G'Ø Œwho1B½O.j› ²ùđ’¦;µ™#aµÑȖʸKIó 9±ˆ‹‘„E®PU¬±dÙ~ÏáĐå * ¡É k`ËẈIØ'Fđ1#…Ç PvTj*ñŒØFÓw ƠxØ€LÖ£ưÍư₫@$€åQuÑ$¯ mÅ1âă¹ •´p­i=kỶUd̉©ZƠ'Ở'[ÜœϺuÚªÁÛV¥ÛW›/u•‘9­OÄH§5ZstT¬Vº¹íĂToơ­¾ÍZ£Ø¡ÍÖ¹Ç,éØ:¢£ƒÎĐ’]®a'Ú|GˆMY,\ ¥̉¼eUÏu[vÑ]çØßƯ]Ô»M˜zUÙqB   $¸}¤¢}\§z:dô¡w¸€ ZÆlÙơÀ'˜¦&ZÔ9¥#®%Ÿ…ù u)%±r¤–ƒ‘mJ[ŸiÁo"×€†ƒ̣[Ô#­Ô§ÅẠ̊mºÆ$Åư½₫GÆ1£Ù‰’̣®SEb%Ï;ÚzÜR Yv|«½™@æ±&Ë¿FyË úMÜÍQÑÍX,e²5ºÔe ½ÖåJt¦€3₫I¢ÿ‚¿ù Æô]ØĐÈ´±Ä È ÆaèQ(Œjt¿©đ=ÚQTB¯F²ŒZä¯̃‹æ’1t-%ơà₫-VkäËèưÏn4h2nÉư”@Ưé>úœ@ơí–XmÈ×­íÚÉ!ƯâÜÔAIn]”¤ƯWDü¨µ‰Pùk0 ÄE'Zƒ#̀Đ¥âÉ_Ư!DßÂ=ŸMI5æ¹ÛGV>Ú:Fid\Kf LÎ?₫1©ç[a^‚͆5D2¦`´]FÈB‘¦ÔĂQ¡Ï±Í'â\º Đm-=9vƠ-#ÁͦµṆ̃̃küMד$k‚-P—(39¤³Àp.A`Tûë2{¥ñ£A=$à(g+fx÷]gv¶Iwn‹zgïY­ïIg›´ç®P€çÜĂàe‰Å(Ç5Z va~%0vn"`N¹¨í§Hq#cÂ=7Ùø]<î' ₫’ó [qTá—lDœøèÈÊùe=ŸYɘlĐnÖ»o¸Q÷»´#»Ä;¿³Cî"Ÿ•‘04»ó¤6Ÿ ¼Ó—Ă[åĐ˜£6ê₫¢Nê­j¾sễ* ^»¡¶j¤%ÄHJ­NJE&OÉ•m¨nåx-‰A¤¥e4á1^ ^’æ±aễÀüàd¦4¯¡àbVØ,­Aî°Đä‚̃ºáØ?Nä”’+U‚MÖûÖä†H X€$H°K‚& µ`í¯`‚0DÖæ€4È@'˜ %ø€-îb‚f£»ÖNƒư†$n²km2¨¯¶1îHwz°¸©h‚̃†®¶Ù~ẫîăNnÖÖ®æ>nÙîÚ¾íÜ̃í̃₫íïnÖ‚Ó†í&Tí -¨5h2à€đ₫'p‚+Đè’Đ]G4qh#…h3Ù*†Äfæ"gY'ªGÄ6f_Öéé<áaæR”Ëk*Jă»+\aÔÑ – y xÑi{…³?çÀ́¬¼a³óÛq÷Íñ™°2ÄgÿçÇ¢0»g×›vF‘q¶W©Đ²Î‚¼Ợ(w êX‡)‰»Û†ĐiPÊ ÆCÏä̉‡Sđ{* ¤{ê 0æÄes.2«w@‚öMéZ áøèëÆ.áÇ̃gö_9Ư¦}•ÑØ̀í~áqñ́đˆođẹ»:pû:%Û±«O›JT‡}Pü¢w‚ iøO· ÇZ‡P₫W‘T?¥¦Èt1œF1uP¯Q/uxBuUט{q¬xơM¿ôOŒZÇ RW!\· »²ß¦`K9Ñp™~‡kÈ—đ¥̉]ÜCsàäkY`’Ø»ëæ[¿@í̃—åh6hOÛṾñ–ÛŸ™7Û©–ö0[èØü(ut¦™ˆ°íĐ²™Â]J“&DÂ$4‡ibJKª-I¥M1}()tBƒ/ÂdWxJ´”FUº‰ˆŸx¦T'иøIÏøÖØx‡÷Ÿt῭B¨´-éo¸vZ­"ơgö̀œÍv¬|ps¿Àîs –›W–ä‰b`@Œ°›ƯH¿t?Ñ?÷ë₫X‰́S*Ê>º%Å#-ø»|‰mH¨ưY+öá<¼¯³¿O´— ´O¡±ä²·Ïṕ̣+(¶|P¥½q#|臶¤ø¦€†±BÂJ\yS7û\øÀ_ZJÜwđôI¨,TüÁ× ÇW‘ĂW>Șü4q¬Â eïVœØüX÷|_Gü+ưÎ'0spüp††/dÁ)s@JùBØ©—®él“‡IÆưǗí¾Ô+óAï°ơ;ÙxÄÓÄöđ>½¯f[1ixWKyw̃ËØ† ;22đ hY¨úû°‡û¡I¶YµÈ¢Xă·ñOºù{°X¿4Ḳ Á*”§ï›₫ë¡V€ø÷N ´ÿÖ­3˜ĐàÀ„́ Bø®àAl ^|8ăD…  <øï!Ä+^ )RcD‚SbÔçïŸ?l ßy³̣NæL>wúë¹±gÉ¢F"Mªt)Ó¦NŸBu:´¤¿wV¼mŒªu+×®^¿n*p›Nª`Ï¢M«êBñP¼#ús-Ưºv½’T÷N‹7nD‰f½+xpÓ™37â,Kx1c¯ï¾9‘hPnăÊ%ßù˜fUËtƒªøM§¾É&q¾ø6† ·oß¶q“,[à@ï²̃F¼/÷ÈÜïvߦ-¼¶pvÁK Î0ø>Úȃ?œöîÓƠÇ­ü9b²₫Ê1vbĐ"náûÜ‘dxưáCw- ²3~™ä»‡7/ç‘¥ưĐYăVCư˜x#…Dà{#É} bDRtÍtDÜpsE\₫”¶ÎL e‘XbR›™Ơ„f&²Ø"Zû̀.̉X£?nmÁ D†X£•öN X™ẻG"%—’ÿl#’Ovu˜hM䔂MÔ}!NuåQơw>…øÏk/\áÄk̃´° ïÄcÄöNc„‘ÛJqSjpđNBL8¡Fc¬æfI°öd$§wÖyg·íÙ§@º,¤qh¢́¨Æhkï<iœ”̃₫f©|ú ¨ ÿ4Q(yM´ EnÜ´%Ú3~,~… •°Omv¬QÊÆQ^ez-‰…¨ƒ̉bëY\₫ƒrJ™­¸Z™ÓfA1;®ºTUe‘¦‰µ®‚{c̣^É¥@́e-¾_åCƒ7¢´ áöM qq&%j̃8AÆƠlăÍ6ƯvÍmÛa.>ÙÔf>îA£¾ø ́4Y!,¶₫́fnQúê/_~{™H—ÀÄ~z¹†K¤¯‡äCˆkà{΢‚ơmoÑIOÄ‚“$í1Ü ƒq>Ô’ô¼#ÍQÉR¯€Íd…= qhRˆ d…VIJ₫^H0¤†–~DŸÇTă Jhœà„+\Á Zđ‚ tEÁ¯Íˆ$ ááÇ·#}°ăm1bñ…6øë8ÿ¸a¡Ts!0}mt mœ@@…oIAI"(œÉäQP‰›@v¾µÉo")`7.h Är‘YbcùPHmC49̉†¸ø%ùPˆ?úÑ2¬“‡“‰>Ôñ!¸²‡Q¥(ÏÆ¯Ặ ¥́‡ iBKV̉o°œ¡i₫AËÕR”¤4åMŒƒ1£¤z:$øip‘4̉ mf+Œ=ÁÆ7÷NmLC+Ô"Ï ¤:blGîŒÊT₫FŸ`hiÉF¦¹Q0v$A< -Í…É\›‹dd“h́¡6Lˆ+é~9£DQG?(ÇCZË¢3±Vüæ!s¤ơ+œ?2ºÑ !ÿ°–µ`(Q“ú¥Â¤èJ/ÚRíù€)I^;8•rˆrÔgæ$' @2µE=aÓ¢ %É̀ä~Û±ª‰œ‰7³-•«|ÇßTV±N@4ñ–rÖ‰ÖArd m§ø̃A†¥ÍÔ Ó,RƯ4¨0~:Œ‘‘Fˆœá“CªD­"˜§&}ĐÏ$,YˆMtÏĐl‘&‘Ûa û@ˆÜD¦ˆ1dKÆ·m–3‰¬³4Â₫1HĐ %}«&‰ n ¡>A¥í¼äi‘A‰Œ·4ÚJÿa1˜UpÂ]ËmüÇ×å̃å6e….Rø‰ w 4zdˆÈY©›› ÈV$PÅ×;Tu‘u×E½ŒB‹­q¤b‹Đc4—ß\V%÷|ªx#²…&ŒÄ©¡I ›́w²₫ùoƒÜX₫´ä7’[ *‘ol·פ®:!ˆĂê-æ?®A8‰¸D Ñ+fÊ“bº832FIï‹™2ȬèKÂ5ØmnØ_Ơ¸ºa²«8ơ1̃a†H+́y!ɹF¾!ÑhMË#Íf+£­ryf“e­pyAX3…LÙÁ₫Lj§]G̣>§´f6s¥‘|‡̃ ç®<Èź³VĂ¼o4ÁÎ|>qT”Ao¾ƒ₫’j¬Û@«h•´ª·°– ÍL³r«LfŒüÊÈ–i³¼$ yÏà鲑hbf“@,.’Y4a¨éêĐú.#: Ysœë^F°ÊươRfBƠFg“ØM‰ËnŒ£¦C“x¹(ÊNdĹHyØs×@Ô†?$;y4yË´`¿“ÜPĂË‘Ñ^7PƯnQ‡Ơ“fwßmï"½û¹øỤ̀i"heÛ˜3YÀ×"iyù*ÿ.øÿêb†»m_ªYÖº!¾o2|£ 4Ö§œTí…₫‹µ*2bع­ÚlüHN6¦Ó*n·Û0÷.ÁÖ«ÊÄ\µöNÁPNă×Û±…́9ă†CëqĐâi‰ ÍÅ/u+=*r–¹ơ(Ñ&'₫¾ºă†Ư‹ëk-;× £·]âV6Ăüç”{Íä´¹ºI¦U ÜxÂĂuN¦ÿ%=ïQ؃>s ¾̉¤FdÎA3åÀ+Éa—ù ³µ-öb¿GẴxĂà~u¦sÆÈ|!ùåÉe&­›³ôbc‡Èl u‹Sh!áVKñăïÅc#¦^ºe Ù¯%‡¢Aá¶)Üo ›@F₫0Ä_ĂP"MFĂ|-L¡ĂÀ‘J#ÑAÄn ‰U.Z²$¤JBœ¿ŒÑá 97¤Á60P¾•EbÄk˜$ŸaeTZ›Z̉ YI߉´ˆ$̣åƯ™eT%)råä‘àÇỬc²Ó·™ÜḅeDpƒÙ&×Å Ycù­˜@8ÇX£SOÇH;æZc"eÉ•±!2âĐÚ}âX́%Ûy U e^ÙœIX¶"ÎÁÎtùfTr¦¶Å7ˆ”ăxôÚ^¥ØGR[¹]›¿₫ñæ?XI@eÆ0¢f­-!C ænææ!–o çq>•đÄq¢;±âw̉Úa¼frÏ`˜tÖ`gH—¯Qß‹]d£µæäÚ&TͼâŒ[Ü9Ù˜Üf!Úç9Éœ¿±DúæÁÙP¦ç5ÆEièÉ'0Z œ(âdxèüd„X̃d1™LÄRk”„[½X ÍTˆ"Ém”̉A™œ’y)5É\Ü$d¦…WJ^ÀXN mh ̃̉Ç„ê(Z%‡ubrL!‚ôh»hb Ư’êÏÇ”ƒ™GxéYÜ#Œ˜†D¡²éLX’U©•₫p”R:ŒL+%[7J†FùR> „3lé¹’À„Îß=ê[ÅØœJ[¯aêà`•#qTDÖ¥%Nç?(êÈÔ‡ŸVêpÑD=_ªª…HzG7”§rIpœ̉¡¶¢¢b•‚¢ ́@©‘úÔĪ>æÛ|(ằ#¦¨4æ†q~›wÎÛä>đ篮"đ)̉EEà¸DăƯI¢WÖª­̣iCà¦V¤‘êÙ܆9èêpbß,åíÁd}ˆ"l]RBœÇ9“[̉¡P§]̉`¤[A„lèÿ΅\í¬eØ^‘Ç49^2„ln, !Ç’Öf!*ưƒåÔ—Ă‘ dĂ}ĂĐDüÄ́ÍEBpxLh†e₫̀§4Apqepd×qí[8úe´î'‹Æ$‡ñÑmDߦpHŒÁ@˜ƒÄÆc M©¼…lV^Ѩ’0eO´œ[MƯV6ÇÛñ!Æ[!F3N,¢ưÅc¤;X K¨'iƯH~,”A\äăcÖ©ü –Ÿ‘½¦«†iúÚVdZ=đ6í¶9RŒ¼ń₫̣+ß¼ĂpŒx}ŒdđÄndÚL¸Cq¥MØi ™–¤mJlÈ’Îd¯6 LƠ9¤ÎîXL^Ø_¢́7‚Ú£ÙÑ0 „4p ¤±ÉƠ,­.Y‹ÆƠ½‚DHƠOBHÔ‡€¼®p {È ûDBh”4°ƒ™id<„ÚPÊ₫é~Ă›́₫¡-0eî™\ËRQ*§g̃]̃û$œ7Dpî.¯å)ÊñM"±ÓÚ‘Å|ƒ¨ ˜ŒĐ@M¤Ú™ñØv–ÄGÖ¾LÆÛŒ®ËÄ₫ÛPíû܈5¼É%åMüđf‹Ö$Ç"¢Öé£)₫<±̀ê]¹^ư(đ¨$Ÿµ©7–Đm,JñµÁW#×Ơ'Ï€ Äß4ô͘¦%‡Î ÏäÆCXR…‡!SO-ÇN.³Ơ-›*ơ˜j}$„ÍüÎ[C0s³ÎZ_;çcVÚÀÙ́AFk·M2Lz±%÷dÜ\€½Î¦I°)Ỡå{”2^†47±ú¼ƒ̀€tƒ7TĂlÁ¯œD đlÁ@#YmÁƯ pÀ¯„N fT¤ 4AÉe ´5(twZĂ?´ ´Î°Á6<»ó¼ƠỚµk€ĐëHʬtË~ÀÎ}\VBPDhmD³ñ×e=ÄưôÆkĂGl'ˆFœđÅ\÷pÍ:Vg”M£3†kT₫.̀N °ˆl3PK­†68y+êúœrÏ‘X$ÄVÂ#Zmad ơ¨F™ŒEµâ¼Ă|u¸L  ˆL¹FUÇ« µg{ÂĐÔ®·ÀA°Ä«‰hĐo»–Æư ̉70áèM z7ä́æa“ö5V3vO8oe³0%¯³êQ6qLƯçÚû„ؽ”RE’rU>µ4§Ç†G× tC·I|¯¾„Í¥œëx6Zñß~‡ ú·;„ûî=6·¼J̣‡s3GèăMĂ »*i*xÊ„±«‰k·Y„‹S¹zKy`Æ_\!çŒ\sÀeáR{àxû‡ï!Ç”ªŒóM…‹1₫eVó_!í½N{”¥›wv;0|ƒoŒ? ÉGc%:‹¯[ˆÓÚcXø˜³M¯™/QzgẬ¤ôi['–aö …4ÏXcä‘[z >·hHâtg…c z>wQIƯ|m«q9­…Ô;ä–®.‡7u”›²˜/ù¥w§™₫D–‚ °Œ §w ~¶<ª³ ENºhTú±çß$ä́F ÿtbCùỹC¨†5®¹Å-Dyæöi„I6›M̉h§úØ@¡ j¢³wz§ƒºzÑeÛ *2;§·1q¸% {⟇;†º(³;ÏlƒÏzeE1°k¬Î™ bàh₫ļ#sÓú-eç´SÀë´S¼J~›²£Œ}l¿ø¶ŸS9;Æeî¶ë{le¿ˆó₫ôsŒÜ>ZÙéơk|† öËÿ&2?á*[ôwÑçº%ơw#®±ÿŒåvN¿ùË¢xææ®›;T7ñ™Ÿ™'@ü8`Aƒ&T¸aĂ‚î₫íÑaE‹1”˜‘cGAvô’dI“'Q¦T¹’eËï$t9“fÍŒ́dÚÔ¹óä»oṼôç/(O£G|gÅ[ÑCÿ9E:u¥>ªW]JŪ0 ;commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/images/uml/prepareStatement.gif000066400000000000000000001363231410126276600311000ustar00rootroot00000000000000GIF89aît÷!)!11!9%B!JDJ!B)R R!J!NZ!ZZZ!J)N)R)R1Z)Z)Z)Z1e g!f )q&c1p 1{+s)ˆ!†+ƒ13”)5–3Ÿ6R!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{!1„9?H)R)!1))R))B)1J)1R)1J)9Z) R)9Z!9c!9e) m)/k!9y!>H1*V-9]1 f15N5BZ5Bc)9m,@rnIˆ^’`ŒŒk—˜k ¢q£¤{«®‚µ±µµ„­µŒ½½„µµŒµµ”º·½½Œ½½”½½œ½Æ”½ÆœÆÁÈĂ™ËË™ÎΜƽ¥ÆÊ¥ÎÎ¥̉̉©ÖÖ­ÖÖµ̃ÖµÖ̃­̃̃­ç̃­̃̃µç̃µ̃̃½ç̃½̃ç­̃çµçç­ççµïçµïïµçç½çï½ïç½ïï½ççÆçïÆïçÆïïÆïïÎÿâÎ÷ï½÷ïÊÿïÎï÷½÷÷½ÿ÷½ï÷Æ÷÷Æÿ÷Æï÷Î÷÷Îïÿ½÷ÿ½ÿÿ½÷ÿÆÿÿÆïÿÎ÷ÿÎÿÎ̃ÿ̉âÿ̃Úÿ̃çÿçÖÿç̃ÿççïçïïïÖ÷ïÖÿïÖÿï̃ÿïççïïïïïÿ÷Î÷çï÷ïïÿÖïÿ̃ïÿçïÿïï÷ï÷ÿÖ÷ÿ̃÷ÿç÷ÿï÷÷ïÿÿÖÿÿ̃ÿÿçÿÿïÿï÷Ö÷÷Öÿ÷Ö÷÷̃ÿ÷̃÷÷çÿ÷çï÷ï÷÷ïÿ÷ïç÷÷ï÷÷÷÷÷ÿ÷÷ï÷ÿ÷÷ÿÿ÷ÿÿÿÎïÿÖ÷ÿÖÿÿÖ÷ÿ̃ÿÿ̃ÿÿçÿÿïçÿ÷ïÿ÷÷ÿ÷ÿÿ÷ïÿÿ÷ÿÿÿÿÿ,ît₫ùµû÷¼ƒ₫üưKØOaÂ…#Bœø°¢D…đ₫ÁK¸#¼oơåkH?~ÿPj„×®åÀ‹0)Æ´(³&Í›3sÚÔ‰Óæ>}₫ÎÜw°ƯÁ£{*åÉt§Ó¥O›Beẉ$»}UYf|µ+Ô¯RĂz v!Áị́Û¨A·G3®Ó˜” Ư±xËêUxr`ÆŒ÷ưó[̣ß»“ưÿ|2/ÙÇ#ï•,Ơî¾ÀăúḱöŸ6x—ÿuôÇôBÓ\‰̣åê¯Âç§₫;đ̣e J~ $xØßF~\Eo,x¸aàÇ—«f₫ü5tå §»®₫Ü0vå ·₫×(û;̣đÖc{' qߺ„n%h­wÆÖÖó–¾\¼sسewŸ•7Ưyøugœ÷!¸i z‡ ƒê‡R;W¡„nvƠW’€m©WƯqÉMç–…úmÆ_ˆÜ·ˆƒå×]€à%8jæ±æŸz³-ä Bi i†Q…̉AumØFµơ'#€ß±g£s8¨czö¸Yj̣§‘?—¡c×;ÉưÍhtÁÚ‰F¢É±)oªb„#nI‰Í¥¸ˆËm´WÉ*¢‹z~ÇæĐÙ©(qŒDƠm¸•ƯIB 6PUÑẻ_kEa¤̉ªIŒ Ơ‘sí`•Α₫¾m–Ь)ä驸‚:ꮕªQ®¿öVj¯¼¦걿;́`%û©¨ufY\©ó>!û́³̀ëm·Æ+.ªß.;иÀ‚k®©ÚâZ,\'̣ă–Aoqåë¶é®û­³î–«l³í ûï¾'믿µ>”°]̣¢ƒƠ9û@Œ̉h²ú¶¾Èª;p¸¬ñ· 54«Bú¼‡R4†e„2pú•0Ièf¬/¸üêz°Æ1‹ îb̉ƠsÎÜÎLXÍûµÖo¿ÙuƠOû¸ƠW«¥µQ-i:˜IT¯…ÖÖW ÄZj©eÛeë\X͹IÏ*r?l÷“KVåơÜ_ÇơƯZË-7₫KZk÷̃oÎ÷à\·ôiàZÇMµâ]gä_!-¤ObÙ=7àz̃7܆Î8Ơ…ÿ}xæ› ~¹æ„xƠ†'̃Û]Î(4—`g‰^8Zw{Î:î^³.z̃–“₫5̃ªkuzé~#ÎùÖ¨ëε?"ƒù`s9̉Ø)ư†YBÍŸûïÅ;ͯ.wÛ#W4oJo1‘Ú ơn>ù·7₫ưñ„^ºâË{¯<àW\ÿHG5đư/|ü[]Q r!xˆ©#l#”­̀bß°/i¼ 3¨ZƯ¥.¯ËÈo’”ômƒÜ  SȺ°…0|¡ [9x¼C!î€̃9 ¤Íđ‡₫1 "‡(Ä ÂÊn™KB̃0•mƒE$¢£HÅ)Z±ƒfaŸÏ|óªÀüĂûª|HÆ+‘ƒX̀â?¬1LQ…üØa;¦e ¦ŒÙăg˜G=ú1{…ù` ̣£´ăF‰‹"µ¢•D6²(dd"¹’£€$ñû6c—E*̉‘’Œä$EiÈPr”Œ|ä)I™Ê®̣•ªåg>“Éöƒ Ơ`%,]‰Ê^F2–¬ô%$…ÌRÓ”‹œd{–¸–_¾̣˜À|æ/yL]RS­Ä¦0S —À#—ÇX V†dœƒĐ̣#èÄä4ăâÈk³ÚÔåAÔ©m¤LÀ₫áGG:£ P¢“ëD¦;«™ÍwZs—¥ (( *Đx¦̉“ …4>‚ o|ăÚĐF¿‘‹fĂ¢ ưFHG*̉’’ô¤̃èhG½Á̉”^Ô¹áJld#£7µéIMÊÓú´§@ư©PƒJÔ¡µ¤Ơh6¦±̀%đĐhQ§zÔªRơªVÍjI³A›ftˆŒ–S=óR¬U«h=«ZÓ:R–ÚÔ¦ƠHj66µO’|d£Úh©^ÙºÖ¾¶ơ­6•ë7ªQ…CƠà¨\ßZQ¿:–¯}¬d… R––£å¨G×à†#a GĂF̉ö´¨M­jW‹Z+¸¶µ¯₫‚ âÀÔÚÊ(S°‚¢)ÄÀ ¬ ®p‡KÜâ÷¸ÈEíĐ`#Ø ó±Fp–ÜêZ÷ºØMîØ…#La Sø T»µ&d÷¼èM¯zUk…Ä@ đ‚h§`‡jXƒú¸giT03̀7·ë 0qÛûÛ÷F¼Lø ;–Ø&E*oáë̃Ø øÂÎpv;…̉N! L`¦!(câHqÉ¡ »øÅ0±ŒUÜbrˆĂËX†2rœă(Äơ\fŒ± rÅ3N²’—̀ä&;ùÉKVÆ‘1†·ÑT¤S@2”·̀å.{ÙÉö9̀a1ô³†̃ ‚₫–¿̀æ6»ùÍ.6²L*ϧ0iIÇNlcÓC†³ eLg1™ ¾Ï'Ơ)ÙÆ…´¤'Mé/ÇăÅ,s­@ |àƒÅÇ3âa‹xÄcÔ£G/VƯ ^°ÚƠ«†u«_MëX³ÚÔµ¨…=æñgX<ăôPŒ‘;;ä$G@1=~ñ q˜ÚÖĐu´eMíZKûÚƠ¶µ³ím{[Ûàă(¼¦ñÆÄnn»ûÛƯn7¼ß-ïzÇ»¿à³éaä0ô³™Q7»ïMo‚Ïûàö.¸Ânđhÿ"̀GÄë<…s•ó$éH‡Bư‹QÇÚ¼yÂ₫¾đ‘¯úáOù<È1†lܧ0/*̀1”ÿbguĂw^r“üç&÷yĐ]Í‹¢óÂÔ§&ơ¥—j́E Æ3^ô_´úèHOµ©µô¬#½ë[Çu<èa‹gÀB¿̃72ª,ú#h(,]j­sưî_Ç»×÷v¾ƒưïzï»àŸ÷Âû]ï¶(µ8ˆ†.̉ê¢ë>¼áxÂK₫̣”Ÿ¼å3ù®¯º́bö1ayΛ~󨯼ê5¿úη₫ôZwÑÅ=qĂ ¯â`ø¡qbˆĂê¶`ơ.\ {ÖßơÇǘă±̣(|"öÉL6¢@œ_=ù©Ç₫ë³₫üîßûÜßz«uQk}ÇCØNo‡|Otq?ßEï{ªçïuúwƯîñpơ¯í„WaỘ0a€›ÂIÑ{°kÁẉ×€agö—t(x¨æ€ø7`W ˜·jÏ lépvơ S@H)ÈxX/ø€1(3¨£F~³piâàcbꆂ-ƒ+HƒChƒH„ˆ„Gh„¨„MÈ„±Ft—V R™‘¼gb¿÷y:× A(ƒE¸‚.†vwu­ö ä .Çh%¤Ù ä`uF'n1èb(„IÈ„vø…DÈ{·‡5x‡`h¼° ±Fj₫gLG ÆĂ jtlÎ6jX÷u~§yG§Ào­@X@ ÊläàodƒR7‡–ˆ‰—¸\ǃ·‹³è²X‹ƒWtÇx#èAđ p·ø­‹¶(‹ÂHŒ–xŒ¸¸ŒĂv¼@~—FhP ätK&èlÆŒÚx‹È¸ŒÊØŒÊøƯÜ8uW§‹¶W…C¢h­aÅ@̣đ~¥F‡ÙXÅXÛx«x¼P{jø Á,̉‡ùftÜHŒâHö˜ÉÈyâèéù&n£†sÏÀlâ° Y0 ÆaH‰¦ælζj×qφ ø¸úö â  DP₫X 7FSàrŸb' SG ñ§ÍØu*i‘·ˆ’§V‰̀ØA‘Ç(ŒW×lË`näDX†K¹ ‘XI‹Ăøv÷~Êht¥Ö|Ú@NÆqÉ”+¹–\©–@9y©j^™–_g†øf{1Đ‹·ôríàäà ×wé–Y¹•a×q‘H—_gtưH1ĐQ qAĐ£؇ópJ©”„Ù–Y˜–(ntSwt^H†É™o©j§lô@‰W 70 ·¡¦I|ÄS'—â6J§»i‘¡µĐö@lĐ ¿ögQ€“Qí ˜¾ttXjª‰º₫©›ÙÉ›̃)—ªYJ'à)ªÙÀ Ïæqåij¾ù›ê¹›áÉ¿9…RP–¤ß%ɹܩđ9 ăéÏ–ê…çù jĂ©ºóÙ›ƯùŸªvt’¸ œ†*%‘ V  ñ¹ê  ¡Áyj"º çùŸJ¡ *Ú ¾é›̣I¢¿& ÊP 1Đ*“£4¼'☷{(¡*z%z 'z£Á¹›ï ¡º%I{âđ˜ß=ø„lcØâp™‘˜j Ú2¤-z£:œOú N* gʤ̃I£3¦.Ê¢#ª§J ê’§j₫>ù Ê ²É'P ÏĐ~ô(mJ§Öy§ßYµ  ô A e§ˆj(Ûáê'w÷pfZ§|§¥9£'§5£DI§ê雀J©S:¡+ÚªGn>zgfÑÀ8«¹ Äj’ê)¢) ´z¢”§*Ÿơ™¬vº¬̃ùªñ œ.IV°†£â¡Ê`§ÈÚj HÇʬs ª¦7®uɦáj’åy¢· ®â*—¿F®xéx¶‚q̉I"·€‚笗¦Ë¢¦|DÙ¦¸Ê¢ùúu ?×3+5(x§®*­ vñ: Îʰ+£Ë…ÍÚ±&[₫©¶º¢,{¦u‡tE— ‡¨­¡…rH‡yµ j¿` ô`j¿€ ô`´Cù³ñ€ âF¼ uJ+´¥ ` j§f“̃Zd½—I ôy©dGœîYœJ» tµd[ ¥¦´Ä9´f+x?û«đumK²n«¶ñp äk½p©çY—§f{Q µ0— ¥'‹¦©j²À¸¥F|Nj·oË·Hw·b¡l«jq;·‹tôà ª¶ŸKœ½ ·T·¸ÀijÊ0 q¸‰û¦ë´s»lJ›·&ù³?k‘´đ¶Jç¶DÈ´¦f¸`´µ ’¹º¸¼Ûjdû·ĐKf«´Ÿû¸C₫K´Đ[®ûX°S(•uÁjƒj’Ç©¦ö´‰©’P‹t»+vJ«’ŒÛ´Fû¸{œL‹¼ÈkjN µ×{˜â`0ÅIi,ÀH´|7œ·f¬ŒKœ$Kœ£¶ p{½?;´ kCk ·{jÅÙ È[œe{½BK¶$‹Á̉û»bwj² ½ºKj»ÛÀœk ƒù³#ŒtÂ[· ¼÷H‰®ö¿̃0:+¯̀7¨¸–ÁÄYœ̉kǬ´›½ÀVœ¶Pµ`€jä@YÛ)w‘Q° ©Ă볦ö¸¦ë·. ¸+Œt)ŒÁ(Z›+ºc÷³®ÀÆ%\¦ ¼2|¸&°j<Äô@‡íûÅ₫4ë…„{nuÔhV©º§«Æ¶’kœ[Ä϶Ân+ÆÉ‹ˆ¾k¹¤F}<´PëÁî{¹›’ôøÇô¸›÷ LđºvqH‰k®Œt± ‰CÛ»?ûpH{‹kC ¿œkLjÇÏÛ ·`œÎk¹½ qØ™̀’L¿u|»ô[º¹¼O붪»ÀƯ‹~qlÿ Å¡ÖǪÉl£v½4ÊÀG loK²¥ËÏûu»k6´ºp©HÁŸ›¼µ°‰dÎÏ&SSâ‹k!pôø~‚+§v* ?›Â4Z ÀÖ G«‰Œy›Çc· BkÁÀKÇm»¶JºKû¨ ¼ÏñàÆq\Áî;₫·́ë G7¶g¬̉k‹¾‚»uùv³&V́çÀ=»Ï±€k½+½¿@̀¸¿©»\įlûk;ªˆT€H[˵q—S׳¦IĽÈâ €đ}ÆK̉ô@ Œđu« àÁ§o«´˜Àz¡0Ê ¸âÆ·+ü· ’Đ ¡€ ª¿!œÁÎ́uøv~Åà½wQS± È0ûuC ·¤đ¯ ½â׌ 0Öc§Ï”ÀyĐ£ ½}©J‹”º+nđ¡đÙ§0 |«Âư»·b¬º*—®[Am•몽¦6 Æú“?K ΫÖk Å9ÎôP·₫ —êʽ@¿µ`u{Ưä· ªÉ ²@h;v «Ïk+n²Àj£đlbljA]Ë_ ­çI¸øĐvÇ6ª€¶ÀâÜ|¾[·lÈËÁđ;Á–k¹̀Ư†˜¼× ÄMkÁt\à w¼àÏM ă¬̀nU— -§åL|^mÙE|½ă¬’¦_‡ ¡`¦ ƒÀàô |~@¡G¸¾y ½̃uü¼·{˜À }Đ|À§Àư¶£0 Ÿ̀¾‹̀¾[œµÍ jĐÀk8ƯĂíđĂôˆsYjW - `@ÇiÅÉæOÜ¿Ù́‹ »v½°@Á—ƠcôA₫ZÜbàiuŸ)vtŒ bû·¡p½0 g àÜñ€  ²íâˆp¡@˜ˆ@ µ  k † ñ  |tukÖ¢^ ¤Đ„›đà´›À„N€“đ  Ïp ªéG ˆ€ ²<Üu)ÈÅp„ÜIˆ{È^x´Đ”0vF+œë’ë™₫ ¦F Bîꇼ¦Đ—P·˜p¤¤Öcçܤ`©­î’pÖÏ Œà­y ¬Ư”Đ @́¢`ëpéªNë7üá։ʪÜ+híM²@Ë*™æđ´=›Ùjñl0”í­»ÓL₫¶ 0Ëä× º  ±àă®6Á@Pœ\¼BK ×{Ûzm̃ѹ† 0ËGëÂY7œÙ̀YTb¾‡çøÖqª­»#¿´oĐíĐ»¬ËúûÆµđ¸ ­Âñ0|+¼¼ô`%ñư 혽`ᨪCĐ~¬]®¶à |î¤  ÀF è̃釀 `Œ đïô è3ÎđèŸÍøµ} ™€îÄy đÙôĐŒ é{ µê—₫èŒĐ¡đg-½đ„. –₫ à‚}è˜@œ̃ ¦`éæ~Óîê’àäˆN^‹^Èl6½Ă9Ưå;­8‡ÖÅ₫ù¸´P 0vôÄœ̣–ÑÑ®ÚôÔô¼–ÉÏ|ͦç*qQƠG²×\à­‰«@çÅK ˆ@’°@”à«À “ø°ºÔè)M{è‘ÊCêÏ$M„8 ̉äU£JöVÙ£7‘SV 9ñ©Dj¦>•*V²¨é¥C”øJeˆ”ŸK39é1Åg½S½â *ôÙ/¡ñ”CÓß?¨ï₫ÁÓ6EÑ¢X³Åï=D¤páâÈɽI‘(I䃶O§?¨4!┈̉P|(9¬ ‘$zópÑ«H ¤¦<,9%DŇ“CK~H•ú£©‘@R”"U$5“”Ï₫¡ñª…5i<£¨ŸMù*TxÙ¬j=M4éX{öXå€̃¸pö‚¦ǴX¼!°¢gÏwđæd› oN/=׋÷Zx­®µŒ¸Ë@ñâöpÍS_]¸đ{È̃“ ¬}lwôDŸi-jT\±(đáǵüùgŸ̉‘¢˜«²úå—ưè)–¡Äûå¼Áˆ¼xæñz¾Z¥´_̀»À¤c8z’³ÇÂâVùÊ8z¹Å+­Fg o₫* ü§ÚùƪÓ~ɪ¶¡öÓ/zYe0ơH)„I"AÅ"‹>ñ%\,KE†~‘‰’?$ÑÄ.?*éC®DpI«’“n₫̉„UPÍHHQ©-Nöh„’BdZ̀N₫è15ç‘äËUâCNB4ñ²"NvjLNđ°§’?8ñ£“‘&éC“Iü0…¬œ$ê^œÜ—^Ä¡¢Çv¢`©$qŒ‡zhéê+‹Ư ˜§Å à  X\€jq²¡lmÍŸ§^ƒ*(”‘•Ôl{²«x1nY*úăq ©$œ´ ÑÄK$™$zü@aeA:Y¤<̣À£’B8.œD&A+’ºđ­¤DÂá$Ḍ؈HáHIX¡BPùÔRÁ…’GĐ+Í´¡hç¿(̉ ÷µØ₫fÛJ]¬~±…UñJ 1ḶøƒVÑKY„{(Id•ˆ#©$ÎJ²œ$©ÑD;°\®«.´©+̉DvX’BÄ",’O !„z¶,J&÷K­—g˜h ¶!l0]œ±âÈ9Ç0à¦%–§ràüáÎË­óårc‚Îs›ÇrÔÑ+¦Do½‚ËÍ[́![{3 ôpƇs @uœĂ.7ó0wµIœ»Ÿ}’Ÿ\$<]^~¹ªÅ¡hÅ¥Äâ0—ôóèY‚Î[ź̀¯c…óăaçx˜°æ! `₫ôÔóª¢́Èđx ‘‚›yChCQRR„¤v¥F_ÑN8>±‡B"ûT#ÂB˜ED„}Øtu”Nâ„î"‰Ø¥¤O EŒ¸D<$A CP•À"(B¶O!Â’₫„C(QÂñX4&µ b!•¡& ]"+’Đ;‰B±b)±ŸZÜ rEQ̉Rzö³íqC#,âA+Y|p¡PD/bCüDX„@!–@̀e‹ză=Ü&*ơG•À…¿0q\Ä28œ"Å{”ó`!Â3»°"KkÂE( ÁªÈå,„ˆc `#›y®“h‰̃n‚CƠ©'É ÇPĂÁ¹zÜcÑ«G8Ú7;uv×±‡paÔâl]ç̉†¼€q8çZ÷`Å%Ă{\r0¼Ụ̈–ºº4W$zjÄŸm …g̣₫^À· q°[^=ÄWV}%Œ(N—tnÎs¡¢àιDz:DÔƠâ˜GônÑ€¦&§¬œLʬ$HÁ©HHD2’ ˆ>I„;CÑàjñ MÂ~ñpÄ$*: Cp¢¢‘x"ôBàâcô°Ä#(¡³Ç/û‹Ç$qÜp &"3s„¾R!KT"‹ „±H‹'x°̉z5!"¢ ˆ¸Ws>aˆ_{ˆGAµĂ aÎÅœ…iơó Ă¡ë}  ;áQ‘Q ؃,áUÎa°=p¨Î› 8n”JPR\±₫ˆÑ O"…N¢´j¡‡Ot…U+3äg ¡\¬b<\b"èT<̀x çˆpä!_¢Çøđ‡<œ"yYbö@°8*!ÁjEgÏøOœ2cyMѨ¡ºx¡OÜŒE—™÷2{”"<œ&‚ú5{đÁô]á¦óЉyäÁHa ™‘B¯ĐC•+Á<ó{ƠÖ.måN¼”†À“îX+ƠÔ”qµ}œ±µB–¡Rv¨Â›vq̀ÊÙ̃cơh@é&µÎÎÚơôăƠ }å}]ƯÜQ₫‘a€°ÕdU–q¢·TyG/Å Gï1m\¶U´IÊ^»$%èê*ßUÄ¡ÁÔâ:É‘ÏUƠĂTÔƒ€l={T|t̉úv£Xx‡ăœyê6IÛîŒG°µ ( £Wƒơ ~Xơs(å^qסUè{ÀÅ-Ú̀?Û¥Íy8) ‘‡_ ›zøC8Ëá¢Ơ¯ø2¢>¡ê=̀ƒy DĐü"9ă‰!„ ™$.½‡IÔ™N‚È+ê>‚@ÅKÍ6àxàú_Z0*¤´‡@äÔUw„öhe+\ư1¶(Q̀Uá &zºAm2₫[Ù¡†ơßäXñ[97zD(»à–2¨Đ×À3Ah(*ŸÑs­ˆ(êyGHKÚæŒ”#䨤8<Îä3ØăÖ±Ç<èVëWŸÁi÷)Ö°Ú#¬̀ÆÅoô£ÿ:ÁY¿aáÓëFg<óÙküª̀ÆÙüñƯp0Iî¿̣«ñ 1đËđ[¿U?`…ë -ås> ô8 ¬́ +ô£ë)„¾z°âx ‰©ĂIœÅœ¢ ₫¸ ¡ª¬ª²‡¦"€÷`*κœz0‡z€7œ‡g ,\ˆ\hº ăˆ̣@a‘«»̣8LBËa$̣¸¥R₫ª~«Ÿ̃ÈóĐ̃¸tÑù‘ñ«v,<̣¤̣ÙC›Ô +Ó{Cr€í£,Œ»Áó(-Ô ÙÙ6@·ÓY*¥ÚœÊâ ™’ ñÙêœëÜZ§£(W0÷ë@¤Ó>ë[; O< ơ»ó³¾M¤¤îûóKáaæ#@TÔ8ó?óC@; À‡2¬S,¿„A¤6{ÁÀz V©££h­{ầó£]áñ “Ó öKæ¿pp ªÎ)¥2n„Ak) [ø=f¼Ø j;—¡I  h̀Éi‘l!|ÜG}41~|₫¼G€ÔÇÎÈ|;#H41€,È~¼‚E.-̉ï̀Q²ÂsÀ‡Ás¸s`¿rPÔï|pR/U½àp<ª•ĐŒ­ GÜ < CÓHŸ;=ÑÁa•ơϬʪSƯO!ë¼üøPUQ(Q¬UP[¥UĂ²D4Å™ßËT=2 ê|Æ$¡I;XI€„•̀7Í‘ÉĐ¡h€k €g°…slÒƒ-RúS"†c ƒœư@§®{ZWt%Aañy5w•×xWw5 T₫̉W–;ê×tu×tơwD SA¬ÈH …§ûKA­̉¨´‰=6¤¸Ø€}×y%:%A—Á(‘ˆ«×‚í¼X)‘;ÚX}أ٣XYÁu¡T×  ôH& }́6‡TVieV̀ÉÇ •É€ Ú Úh­I†DÚ{DH°Ö•œËü™Öæ‘ 5ÚeHÀE+¸íù‘Ñô‘ « € €«ƠÇzD€dH·ENÊTÎü IhÅŸhEÛÔ¤…ؤ i•PÚÔĂ œ³Ó́ %Ù­ )›ÁXŒu4‹EÙ~¥\–”½'u-ßÚØ’M·Ñ¨×ÏU’÷qÙ₫̉åAuăØ]×zU¥yU'È1 s°é̀Ư´#Œz…Z°wI;|˜:Nº#q°‚op§’q‰‚ù´£P¥©cCViMS¼zỢƠ-¯=ßy¶¤©Â醂dœÄĐÅƯ¡¨…öÜßUĆqßßơ5_~U@ëª̉¾¬0œƠøÉ©€X¡\§›áQ¬RØ(±̀`àơà$[MÇ]AF( ^ŸƠ ,Eb$Ăº]lÑ ñĐI¯b•đÚ`»¢ÉÛ9¸28%-¢x]c9ŸS€Ùb4̃± *‘₫\8^äíØ­Y¹VÁ[ˆb >ŸôP˜"×ÚT×èÔvøT»­ÔL WÁtĐë‰cơ5ß:B_øûU­(`¬Đcóàô­Ë®xØ]ÜÚ)¶ÛuF K ̉ư…7²ÆUî QØîA¥ÑI¡°%™…‚̃Û£^vܽ̃S’çÄÙ 1Ơ¡èôu°ï%dQJ9nå4eQÍ-\f\ü]W‘PúûéHûd’tB Ùí9ÚÏë©t¡SXöăZ†åÓè¹̉ÀîÈ庌QŸ´©ÆÙ ûư u"­r—¢[`—ÉO®°…b& ØuäâÀ#˜µ­ªç Ñf₫Æ…’ Ëâ`gg6U¡8… >á[aÙ]àÅeÓ¾z½¼›9 ©‘ÄSE9hø3mA`~2zÈ'‹fưƯ…x‘ ‰Æă…Ưđ0„¾§×ÍN½¹Gǜ\–Ç&k̃cóEæ­Hæh8C>gÿ%ß9>UlFÆ¢F^˜ÆûM ÎK—auOEæ•ç<è"–UÖ_¯Â£* {2æx°§’Z ^0ƠEq0måK̃ƒÇ˜B7±î[ Snù=k₫=~ÅkøÍë¼æÁlÀ.äÜSƠ€Fń¼Æë=źÇńưlgN`g¶O ûeqy‡ UX¡, ₫ś$£y^Ë~lẤÔÎßÊńƠ~lt|̃ÅN—Óníö̀k 9°.œ́½¶mçß×kÔ.́×>kW@MÜJMÂzÎß“°[Ù‡ C Z¹ÎZ₫pt³'^ eÔ±·§,'ë^ …'ë)óa § á~ˆbÈ«f¾eÑ Yißßÿ 7Ÿs:¿mø­séDaŒ2¯̀CĐ3ôÄ#=bf2’ÄØ¤"e‰Ë[j’˜¹<æ1#ÉÉ`´A" ú†5àñ +r˜ÖD&1™Mk"2‘‰t¥'‰Á Xj“œ×¦9aIGcYđ†̃²̉›k{Û[O­pq¯pùc9”3@€d™2RC›qà£ZÈßr2Ó~ñó:ÑBŸø’1>ƒÁ‹ƠJ¸83ƒá¢ZÑJ`2B#h`ä¸À+p¸Ä¥=‘ÑI|æ#¬\Ñh‡‚J[ậœÛT₫ä"éHH R’éǾ‚å댴îëÔæ;¸Öhîñ,7©“ƠVPxZá³ÇL5XS›‚d@ ¡}đó>ưƒzV0‚Jk̃ÉZA ¼e.d ̃0¡G˜CqÛᦷ·R˜‚‹°̃(Œá w£±VưqÊÁcT˜Âd¡PZÿ¸ÉfF/dÁ»ØÅF³æ=‚J{æ9oẁ¥́gUËZ×ö£WDL>̀tŒHu3KG;h|´£ˆfF¢‡1…Dócщn£ ­ètpºĐª«ô UÇ? ?₫˜g}̀hLSÚ̉n5«_éJĂzÖ®¦µ¢₫hG·Ăc¸t®smëXÓ:Óľµ«­́t8Đîª?ô‘}œ##ʶ¬k}éas{Û̃6ö¦{=‚DkCØÚÎ6²—]́s;‚FÇ̀ă]É3{©/¾á̉ z|&c ‡8œ%/³"£Ộè=äE¦Î <¡¾ÁE푌ílï RsVX¼3˜ù·Å“QƒE«3¥áN á’‰Qªi¾)“SúÄXǼت+miF«.ƯÆÆv¬/] Ơu TÁ¾¶·ÑkL'ƒf4?®ª7RùƒT‰¦êîô$*zƯ¯VzºÁ®nŸ'}Ưà¾tÑyÍiv'»Û_÷:Ü»₫Nö¯'Ó6ô¡C­~´„æÇ~,̣û$qđI,|¡/3̃đ?üágVx½íg?ƠĐÕ²2ï>'QZơ<â!ïøĐ?^ô‘éSŸDÉHf˜ÙêN?zÔ—¾ö¤¿=íqø­²®V¡EĐaøÑϾø²?¾êq_üFĂĂ ‡a}î£oüäKùûЇçµlø«Ɇö¸gOD0?̀o›ÚTX€Ôa?üÍG€÷߆ӹÍû©ƒ€úŸ¯}˜²üŸùœßù¨û½ß&àh$ L-ä„°D/¼G°„Äh̃;øC>œZ;̃áưIîMŸíYD¨¬^;₫Ä6@Ÿ*̣ơƒ>ôƒV¯Ê>,Ñơ^ ¾àVà Vơơ ŸêÄÁƯŒ"ß₫ ² é±¯́Q…U„âÉV©•Z‰dá7<Á}xŸæñ”Œ ̃êx_ÄXD́ RÄ®ÀCy!O¹!¦¡¾á~!̣”ë ̉–ˆÚ¡†áÆá"²!E˜Ú!–Záâ ¢# "#¢léÍÆS$>bbb#ºá¦áføƠ“}-̀ZK™d̀)>BÔd¬b<῭3¬¢pdŒr°bœ῭+– ™(‡÷¼â.‚oĐb™(G0̣ÆGÔb0Çäâ˜dĐÜ₫ĂàÔSÀ̃ÈWQáàqƠ!B¢&b!*eáĐØ%r£ ^áºáZ„9c&’ă;Æă&öa<ÁC8‚v£>Âă<öăH–¡R„ë^>FLÄ|ăƒ7¤ABê#;&b‰ˆO$đ%¤%Ê£;ú#&"¤4©AF ?n$IäJ$:ä>j¤>z#CRëT#Gª$MÎ ¯$â÷…ß(b)J dÍ˜Ä _˜Ä^ÔN¬¢,º"B åÆˆ .ڢʈ S¦‰LñÆÆ\¥-Ú"RÉcøäOnWZ`.ä#nc>ª£#̉c*Æ=¥[Îd&^áXÖe©y!ZÖ₫$\îåÖå=<=d#®$_f ²!"öáá¤z¡`^Ï!2$HÚe*⼑aEZá)¥cfÚ$:b¤$Ræg†&=.¤7L¦$‚¦hªfe²æhöTBbfV¤kÖ&i¾fkb¾ä7à¦oÚæj’f=Æ&¯Ø[̃N­…4̃¶X{4çSØ“tJ WÊI@'4FgvnçÊÀǰ@çyĐ̀픩•§5æcn'zêMdR<©gzÆ' æ6F¦Öămg|₫f~ö§cj<¨A`Â'¨~¨!Z…$F¤ZdZ̃!{^ăi &zÖe÷9¦El¦Læ£A¢c…Væ‡V(…₫~(̃H(Läm†¨‚èN"‹h‹¦hŒz¨FLbxLÂèŒädL̉èExƒNÆÜd|rKu>'s§‘"锢sRç±GuJ£O^©“&©“:§w6ŒNŘ÷i# †éƒf…^cO]¤€ê販G†a}b¦}öT_ö¨ŒÆ(›i&†{æ¡èŸi‹bÄ…âa†)WY¤˜¢!„j̃â(<˜£¤J**]&c¢él_Nª§~*¨†ê¤¦ă®A¤ú¡¨¦ªªª*"rƠf̉i§®ª¬Îª#F*WyCœê¬îª¬Úå©Z!ö0(Ö—}ñ„wöä“*§²*k₫–NéM!«u:k‘fé´b©µ*é”"çv)5èê,©̣j¦NâeÂCŸkªRæ¯$J¢d¬¢+¼Âk­â ¼§6Æ+¾îêàEª‚Vd‚̣Ô))ª«¢¡àå v_;@ª«â)QDĂêG‰zŸˆ¬>hjh̉~pfĂj™ŒmƠÀ:lÇ2¬©=¬ÇêÇÈv¬æmCæêÂ&êɶ¬É‚,̀n,ɬ̀b̃½ăfvh„ŕ̀¾,ÎÆ¬Ï-͆́Ç2êàơ®¢̀mÉíÏ̃́Ó-ï¡çœ–Êçv¾EOJé²~­³2+•Bi´f+•Vë´n©W^'Úr©ÙçÆ—Ơ¦¬ĂF₫­ÓV¤÷­Î¨Á ¹ÂÔ-ƠÚ́Đ̉!̃œ’!̃áJ¤ë<­àÖ́Ç:mă­Đ:î䢬ËÎfŸU)ÍläÚ-å₫íÔJmçâGâ6(¦̉à‰H5RÄă™́)-fÅ&,LR¤ể®Ä´Ă!FŸïyhˆèGêæní́¾Ú.á oñ̉.b"oíF[FxĂt`EœăñḷR/ñVođ*¯đ^j6"]J/!EoøoF˜/ùÈŸœ¡´eC@¯öƯơ/ö/ư l6j¨EHÓ‘ntz’«–RkÙ~åµÚTOb§øq'±̣dd€'ÛN©|ÁN¹́¾**•̃üÊ/b₫˜aFDÛ©Q`]¯ ߯ù‚)fl]r̀́½ÉÇz°ửđôfoçpđ́đö?hîÄ̀°×đß0ă0¯å.Á&Ñîfèöz_À¡ơºà©áh́aÄñ"fgă¦ÎL6ư_^ÆîG̃ίør1¯qđ¦±ún•́âVñđgọ̃±çq G ¸ª/¥–oŸo³±ưº± Gị̣̈®Î â± 2!¯!§±æ%*đƠ\©˜Á2¨'WM'Øpˆ(C…(‡²){2*£2)—²'¯2ØÎ*³²*·̣,GÏ'ßr+C …².Û²8 RÀyz/'²!á₫$çpÀĺ’°r2r‡&âú~èê”, q4C²4s³7Kr$›́ñp ›lw38£ó3ó:§óùn[Ä rï‡v(&;êEhÉv¦́Œvh tˆ–h>sá\ 4BÏ(™¢eB 4c–È‚kCOôQ>ĂĂŒSQm4G·R+môGw4GUH“4.ùU%1ƒ$uJ‹ôH¿4L¿tHÏtG‡•1L䱃—é¦jBz,ÄP8RtŒ4zî4Q'u‹¶#°>Ái±RGuQsæÊ&©–Ê>KµVk5AJ“øé¢nµXơ‡å$V"YÏ(}ZƯö ÖHÖd₫hÉơgÑu\Ï5^×u^ßµ^÷5_›ÖœÖ Ü@˜€\Óµ]ûµiíơb+vb?6cÖ H D LÁ¤ Å2ôD[u%'†=uZ6i«¨Yăa[æii¯öƦ‰ª6kǶrá]̣´lßvB+Æ7¬€Ÿâ¶²ƒ̃|«¡!Ú¥7qƯq÷°)÷r·rçÚs÷¨]ÚƯº9wr37q;7wg7twsẵmƠ9H›Tÿ'©ÚGŸú6{ơ¢²å€u{“6gÿêKÂö|o5DÓöXæ·«¨âá}o¨Ÿá¾5œ‚/8ƒ7¸ƒ?xƒ£ƒ>Œˆ†3@8†g¸†₫^嵃đé4]Fu}[Oßâ÷§øz¢èE¬7cª¸{ê7B*Œ³6%̣7×øÇ“˜*̣ɋϷ÷±ƒ̀Èí9k±1ïoñ&ù;ƒp9«ñ“ÛïàEƒ6Ô6\+y“Ÿ/”{¹< ²1+±’Ky˜WlÅ ñ?X]V°¹R£¥%’È ˆ¶×ùW2 |CŸF*RÛyR3ôX~ƒ£¸Ÿû4n¡rv¡Ë6ƒ¡ ¿Aû6q,*9ƒê¨5¦ăi¦g…5¬<8`±¹jĂ6©—u;rƠöưĂö¡W5‰~#`¶ú¢ă6;f¬'欿ù`^#¢çºR?¤49*º₫¯“6q̃x¤³w€³®›³g:Ăâÿ¼äO=æ}ä?~ă³C4ˆ°ç»̉s•Í#QÔ=ĐW}à[í^$Å7~{Óç`–)C×¾Î-î¿%¬‹6Øç~ÂÓ₫íWhÁzï#²|ơ\Rl÷éưêăöˆßßY4Ê7ÿR£ú¨© îQV,~éw¾Îÿå£çáyâ'₫éÿW>øC=ꃡ3H¾úóÔ;œĂï½ôk™?Àöƒ!V́›vÿœưđïß@„ 6tøbD‰)Fôç¯Bxÿ6ö[₫¯Ư¿s +–4ỵŸ?†ü†dùÏeË/cœ)“æM›9yâô HxO²ƯȲçNŸJ™ÖtªóéË}ÿöù«z•*?¤(¹n¼È1e?}₫ÚiăzmZµk^̀ƌڦ₫³Æo^µqU.l†Q%¼ƒ ²xX!b’„ \xlá9„‰7pÙac„Î3fXđ!bÇ)ưéḮÅuư™uçÁzi×fدïF¾₫@¦´køÊ3‡Ơ taH™ÄgÎü%̣å6Ÿ;ọ‰·G9F÷®1çtåĐÁ—ï.á>~VÙó›´fp̉…«ö›:\~~ưkƯj\ØO₫áÛ@¶úº+¥}؇+́A… Ź5ế1ª&Û5„bg6;¬,!G³¨‹ü!@›ÖQé ͪPFƒcç€ ÜÑ¡¯ÀBè¢íÇđƒ¨¯†’lë¡%rÈ&¥l¡¾9²Ç)•Ô’É,·\O'ït#0°áÖч#³\“Ṃê¢ëBÍ:-ÊÍ,vTj‘€cÓ €bdM ƒ 54D̀<ŒMÑØTQ̀@¼l°@AƒÔ  »L!8H X`É@ü PI =`QÏB´“Ç%‡ó‡·ƒ•¢#g̉·¾|ơ X•~í•Wa‹ 6Êa“´²₫K&•=Ùg¥…¶¹7­…k?[́ 5\½•ÏGüËf<,¿ƯÑ×pA:M2 PØ ­´̉XÅÑC çŒUG)ml¶N[q yíMÈàrÄñ®üiæxœĐsÑn†°̉E+{ơ\H›ªä‡È¯5¥*Ÿ¸"sít9Ùà̉Íí:ÈÚI¢J”u¦m X†GÇóK²¯7Zđ›2lL¥©VcL€™bŒº`J§:hŸƒ` t5Mư¡4ê©ôl'jSâ‡̉|‚´RaôĐjƒ6rpEmœH)$¶#ÉÓƠØqđ̃A;$: Èí!—Oœq‡w€€@Ơå29₫A"P0)V­ V¤^€$oúĪ#xP`¤Y‡ƒ&·¥ÙQzzK‚údç p@…{Đdà ÿ8C9\ˆ5C¤ÉƯ*„2A ª"™V¥CÍxS;(đ„̃äiÔá•M¶'*h§.Æú)eö$ÿPñ”9deÇ|¤xÄL³ €\‰;j$d8ÖÉu`²‘ƒä &íØX¬Ñ' ¶c wéMH´ (A1dêÀDc8º©ưñ"†@3A₫¨ÚØ e4@; Ͷ }(çPÜzÍpèiªÁUÎ!Œ!Oó’δ£wÑ´;¨¹ù äEÂ:₫£üq܈¢zz£È₫1–ÁTsK«Ôe›`oXƒh#ƠWÎfËXªÔu_™ÜKÓ¼è‰íø†8aúÇA`Ù¦LĐi?°x“˜0YĐ] ùM„€Ó&jG6á²j*$BÂ\PªD ¬–s,ÍĐ ; pmDUÍ’ü¶„Ôåb™ #™XÉùM¥ ¡ÜĐG·‡£º„²`́xMJ5¾¿f2HUâR0«ˆEbé{’ ¤¡ÎPÑ÷,D:›’I% uë‚öY¼8Ɇ°d™iuVË Æ®¬=-&yó%˜ElLCÈ:ø!=¹f Ñ+‡z¾5R%–|₫p ¤¹¶U%O«KS;m<¡ ̃điS¢ÜÀ#\ˆ67:­Ăy4¢°8F­eM_ÁLEYeÆI $yÅ;"̣.sµ‰†â]Úæ«½¯SëØïAZ(U ₫G* ̃rfm·/q¥lyt*ECVóá°V¨ø[2}M=‹b$eFrß`g•P—U¡ fœ8®ñ8±ZcÔù˜Æ )K• Q%! å:E†G5ˆœăq ʨ‹Æ7¾!/Ø U( “Ñ o¬¡EĐø¦‚ ÑGç˜ç«5̣¹ywÚÓÖ°·¼£j dG€Ơ*¼ÅÊ9yÎ^Ö₫ôô=¬cŒr₫Q;–¶ @˜×<&ªṬm@¢˜‹ÑL!‘dV-æ´E\ÉÏ[zC–£¬NíAU›„­₫©Ơ7²›íz#¶¦2®©-=“z-תüÅ`éË}8B…ƠÂü…6¬9ªG₫‰ó–:€ßx^`àvPƒnTÊU¢²6L`BnUCÓ¶₫z°ü QÔqb¢Ơ)EÅÅèEˆ"%RXO#%c:Ä| €Æ ¢œJM`ÂÀ'‹¤“)6.½âgS6D4<£00„DH‚7¥1*ĂOJP36Ăl4ƒ@ĐTâ£&‚V¦dBø|.̃€/ùœ\t®ƠzÎùbMø¼TMX4¨ÄmºáÖln8®£ªbA–€eà*IœÁäÂojê · klú‚ü¿‚wX°Ú*XàÅ1’‹Cô„$bkpNăÇ„'´àah́0Æç ÁrÔ¤™&¬̀I%¢¡3üá^DD±éQ°3ª¦_âU^…$Üp¡0°1BdD`N₫¤I¦BHöIæræbÍÔzĐÏI‚°¹V‘ttĂ'gNF¤pÊq±…vñk‘£$̃à!V`»„ä`>f…´¡È¢† ¨®xÇ7ô„ ‰gw(æ+N.´‚'%¸X4+¡¬‚X„Å’´QX”¨i¤ç"ª¢4h%¶ôFƒÔà|Íhdđ*Ç E¯[´&¡lp|0¤D‚fMdbD ca8±´ ăCö gƒF<°[Iê:`#êB\LçXHø pơCÅLŒçPn$ñMf1-RJÎÂ%]æ"À Ç₫Aüá̀`7æ*%4h¾Áhl̀É®ƒÉh,(‡rÉ₫Œ É‚̀(ƒ²ÆªÁh 2ÇvŒÇœ2È̀ÊV¦̉)‹ÉÆZ¤r¼v€ ´À¤(ýØRàJPuăiĐHÓ0e2@&ä â   T%ă₫m‰đñ‰ªF!4œÀeÿr./a„HSe2„¨!5‚ @bYR.%£D9xC3³tZ‘¦bkÅåMÆÊ\H5ŸOW%Y“øv£/®#̉L“¢ÜÚ¨ÁÛ˜ÍÖºíÛ| ×rØ|3Ư¤ÁÖœ ˆ“ÚíÖ̉í8—7{S»̉ÍÙ˜7om®S;»mÛ¸­¼ ürÀ Är:•­¸À’“ÊH…¥¨Hû_ü’₫_èå`bƒUr¤^²Rö’1c$8£_:¥‰Å`–H/1f B°àÁ ¼AM|Ñ35B•Œ¢3'”?€ÅṚq¢oW~nĂR1åF4DO5Uă7‰%ÛѲÉZ éÔÀ^ ́` ”n T G‹nè^àT è¨n v´Gktíî@ \`rôR` ‚tèˆè–T R@G” ÖàFstKánKUÀDà¸t Ô L‰Nîîv”G©î\àïÜ€ R âéª@tÀô.z`d  ĐÎ ¨@h`GÓ 4 ´!FTb;øi°Çđç1Ơ†`ÔæRï₫rm̉͆mZ%!´0"[ƒS2‹Ô&FcT#́ zr2Ä1T/^ÎEÓ?ôMd̀%aª7(I§Ø©B™hÊ $¨-§ÇŒR)ơ(µÁÇ¢¬Ç̣Y‡́ÆPĂh~,Z›•*ịỶ[7B˜ªD»v z ¾ÀĐÍ“Œ†Ề̉Ê€A<ƒ̉üĐl2æ/'‘̃:pï%!;Ơ0×f÷_ø&B,rá₫rU7ePc%Â0PH;\Iç<“¥rùnWOKCỎ#9ms#'ƒ••.“ºz§E5$$j‹ ÔDX(æyªQgsº|#g§b‹(f5xö­₫ªq5Íå ¿Ñ7†ö̃gŸÇÓĂMP,w üºpÍ Răz₫JEz°èhôDÁ¤ˆb;Đ/×&`đscĐn ”b m'åAZơ_#³ÿôaƒ4D­Úa ”hgdmˆ7dhds•IôJ q$}5.ÆBXÖ¦°Ä'ăíI<-Nv–Èpœ– ̉Oƒ¼A¼ZHe1 ›cWË5½¤¦\—iI¢|ȱ÷4„ MexĐpu[Ê*ôBØ )ƒxï€.MàAPM9¨p¸œK§¢p£åW-.³‹¡Ôj4ElfKă-,W¶8·p9"ŒƠz Éd•%ÛB₫eï†ṾHP‹D¡Ä~3¥­J 3ñk0$C„z”Đ¡D9t à!›¾×>´á~Í&Ü„}ù#’7}3uËéA^aHO¥T«Z…É&Ó§đ¼QÙz5¬X]¿:= ԫ˱lÛ^5©R-Ójßâ| ªM[P~A©t›±#‡?~èÈ4±âÅŒƒ₫k 9̣âÇ’)G¶ ³ä¼‰¿¹ÁÆ´dO–[³º=ÍÖôS”*_ÜE ;öU°¢™~#íRµ́ƯDu—₫÷₫í6X̃ÄÉz{¥Iđ²}Ơ]>~ùùïëÿï_€ư È|ü<–SïÀÄ;íØXw>Et̉]“oÜQöÄP~¸›v>Ơahơˆ"O¦ơÍ(¾XVrÊ=¦–…/̃HS\U8¦M6.¾ƒÎ„iS†uí÷Í) w”8ꔕ?́ü3%sO¼&V¤¡ơ$ˆ*¢_W2Ùe™Gưö ×”'mhM¹'@îcSªMJÿ,¨.¶ĂÎVÔoªë¢4%©NÉ;,hlÂï’ÔX†*ê–Ó^ëVr/ùsN³a,¬­(錩 ̣Xh&êO?̀~œ̣t̉~ÉœskÅ|aËư'èc6OøsP%6ă”Ñàn½în8ïcÎP‰r»í軥ü¼Z?¥0₫ÀS:đÏÓ𠬮Oï ¼•º¬ÓnÚS¶k0Àÿ€r×í”È&…-Y‹ó™\úĂ>ưd sßm–”æIư¬³Ưņ¿ÅÓ:ƒëO5Weg”Ü̃|9²Rưs\¦5*ç̃Đ¥ n̉; ÀN²&­ĂÎ:ƯÉ.Ơ”Ăsrw¬Ó̀|$UIR÷²#@ëÿđ¹IÆw,å| ~^ü?‡­/}­W)%ëTj·M ϵfƠW„wTh¡¶ü²6èwỶκạ̈¢Æ¶û~R¹É]R>B禙ÍS£ ¯@§§æ¸H4ùaÎ †rº~øcđ̣"» Në€Ö,¨/Ú@ç₫ IơĐ½}@xÙk?œq)`k ›c¨<­é  aë.H%å­Nvë˜a¦Tª•‹€Ç&&$¨đÍ€;IV;˜•-!QÑM-[âÔ‘¶-&%Mü6₫%F›tEP«VÙ²;=¦EđàŒTÂÇ)¬…ÎxƯñ †ª±P{ÿ˜ ̉èŒôñx&©̃J˜¯àMÉ‘ë%O’µBuÆz—¬ÆÈf oXV²àơÆCS|#—÷u îset¦înl'ÁŸ-m’¥ù#…û¥Vø·Ç¹NªéôÖ@öºö4””r¦üúǸ³ÓpÊ‹ŸÛ‘g/Eu€§ư«Wkb;0¶¬l<…—kT ¨pé¤cÅå÷àqŒ”$¡˜d•Í”4.”tcÔú˜^œpQWf+>i[‹²iÑèO|ÑS(Í„–Ë©́ú‡˜ÆLr«ï@₫Üâ¹Îă  ”̉!˜tÉ‚m­²úBjf™HÍÏù²l¿à7GÉT%JøR¡¿ÎÈ…‹̉_́’WƯÅÚˆƒù„Ë×ƠÀC8d]£Œ\èFäBIÚ‘ăIfơ*Ü¥•~›N¹~*“9…‘jå%¦̀‰ªx~UBaµwm ®¬Iº©‰"̃èËÛù1÷¤{¥¨Í̃«Ûå® St}Ù4ën÷¤®47xJAI'áA;˜hC “ĂaˆE¹ÉznÅ>=Vá&K¿*½²©¥åR‡ÆxY4‚>œç'© Í’¾IƯji•h2̉đXTL³’\…Úθ–ơÉ×ç$kÅüU1X́l¾tÙ¹3V“˧Jó˜`f–‰¬ö’€iĂy›3¨§¼cG;Û(PÖÛ»u»ê*·ZĐ¯J¬çư”o$Úg¶~L³É₫Lî^ûZn7Áđ*ư Ä́ÏÈËÄ7‚xrgíæàX6iü¬êiz¡ƒNV¡9.*Z/wѶ±¡ßˆ'ùyÔ—’6sḥ̃œÚÑ/7`¾ç¸o’÷»¯w6· NX}»Å‰ËJ³=Ísú̃ »̣ÎùM n1·Đ‚uµYh6èy#Zt,÷¶Ë™N’öÎÜ̃וö½FZu«W1R₫3•¾q*bÖ~øÊ««‚gœÔđf¶X±ÎJ©¿„ê—û‘ux+·ëüö«ÉC×sj»gG'IËÇœêPߜ툯y¨ß^1Â;>C;¯{È·Ü 3sï₫îû¼ MÁ<ÄMÓÓ!Ÿ₫xéN}~6^½LJßv»çrä³·vÚ±-ë *(0FKË›œù-ÆœôÀ7=¼U‹[Ơ-­¾̣Ѳ\3äƯ€´'zöùÍy%ƯdK§+MÄ;ü‡7ÿüß¿ÿ{̉Ó&€«qpåÇ$ú€ÿ7€ ˜K Ø€  8`ñM 2_ăw||.k¡u$G~«Á,ĵ~́ç|%e{ч{6¨Âx³fåE ¨E1¨EdÂKÔ„ Eut³TÜáƒïÀ4‹5)í „¹¤ƒ0¼T(¡-16ä¢w3C¸T VM3I³Dè€5(ƒ6¸€bÈ…dR!l`nóF>(₫íÑV¶Ǻ“8ƠÆFøo~§r÷nƒW0†_x€¨CZĂü€?5ÅOö0JÓ.Z¸!GH0 “M·ƠÀṂÔÀèâ.e&/ÜQ/F*>è.úÄJCƒd8†^Ø`¡ëÀ>38‚Næ+';kö~e­³8•‡%vÙvtG§(iwƒˆ¹–Wúƒ ‚04‡đà û”KÄVfa£*1$öQƠCA“Ä8qù!P₫` g°R"hdOAÅçÀ/™O9vâFF1‚ø'A Ä?.C\z’K¢1/sd•%*Q/3ƒÍ÷uX¡m'(₫k)ˆt¤s]V‰óhÓ’¡§":„4ó±…Ê#Nç$O³G0IHO£•NA´C•µ,Ä#+̃¡ `ß@ °ç0#²3 @úàY4¹Zc,êô.3äSî¢"¹†#©•!É•_©3ˆẮ 8ưđZùu׆¿(7QdÔ:Í’†^Ç9—‡¿hL̉W]Ơ'jÚ±%†5#®Ă[‚I˜ƒi˜ËÑ:`<K›tn!äH'ôB’y<(iA$qÀ˜Q 0@“¥µC¡S/áN ”‰ ™?„™²¢™Î€<¶Ơc¹S˜·y˜¹‰›»y˜b©Q±$8đ₫(–S‰Î¦7ׄ¢hqRÄ”‹ùĂmm”‡··ṃ‡qd1L"˜ùµjƯé̃IW/ôƠÓ¾#%&„—iA'£5«ÓGHs™°ăYY3 6CS¥U!1  5[Ø @°HeB†$%=4BûĐ5ê›&Ô:%táù7Ê߉¡z¡z› Ơ8¶Ø*ê–Æù€₫†¯7!AåQω>ưERÇhtÚ0pÊø9Mq_ (‹­øøûY/Hă/ëF’57ư’S4TSA²N°…ï‚;<ơG“uOCÛ!“JDi`>;Ơ5ă„DÅD́ĐSÂäu (“£₫j¨£<º¦o*r̀yVoö2ƒ¾éi¥¦oE4 ·P°GŒâÅX‘₫…‘¥öw”Q`ºÔ‘k¢¡m ©lZƒ¦µŸdÓ£‰’MSSCOs“£¥N‘F•Lä0£z<ö. ]˜¨˜U™@tĂ™́°ŸDLód NUaTETŸ‹;©pê¦("ÉQ%|¡ k qZ„§yºe§í`\Åù–9ß ~)V¨+v¨zF]*Øg¾I¹È*w r“ú·J$ƒ©.$ưÂihNu€(h©_₫˜>ÿZ̀‚=Á¥¸Ox9W¦ ˜'¥×úe•÷\|W₫t)pdçrĂ#÷‚é•[ ²+²˜äœÙ•…Ô„t²n™n6 z=¡cÖ+û• ÷%#K³!K’:ÛÙđ Ôà5Ú F §\(gr`̣9‘Æ7ÓÙZmÛzmƯêdz©¨=cÍ0đw1øÑ$Åh/H¶gk¶i;¶¼)˜ bO£¶B;[¶Ë4—&–b2\µnvjQûЇRK¶(K„K¸Æó:qy·u‹·vË@+¹‘K¹k¹‹·đ°50ßP *‰ ›†Ú˜ËG9­´Â¢ùăTFyBw‡†Z±ˆZZËLÑ/w…’Á»½₫뻿›΢@Ë»zQ(ÀÛ»z¡ nà ̉ºÛ(Î*á»Ơ€¼×‹½×û ¡\Đß ½zÊÚ(†€jýæUD²gLXVµ³»ec®âh/ÙĐ×ăÁ¿Û¼ÿû ,ÀLÀlÀŒÀ ÀØđ Ù€ \À̃ Í+ lÁ₫Áœ Ù0 ́ ;p ܼŒ 5Đ Ø°Áû›Àÿ+ẦÀÜÀ- Á3|Á5LẮ „!;P5€ ́³lÂ|wqFä? _`VctFV­[¯K‘[{̣»e‰Zk´±Ô«¹[@ñ/Pc,el₫fŒÆg¬ÆìÆḱÆflqTkđƱ"@vÜÆmüÅOPÆO và€\_P‚ŒO°T w \àv€qÇ}¬ÆT°)`kđq|É¡ŒÉ£,ÊwL=à?Đ9Đ½[ -pKPj@^lKM@½H<œ·jiW[ÈLÇù̀÷¾Æ}¥¶y;V“¬ ‘½Ñ,ÍÁKÍ\ ÖlÍ̉̀Gr̉་ñ v Ág4ÍăÖ{¼å¬ÎÀû ^À«lŸáà»tAÏàëåE«ûÄLüˆ¥Ä)­¤Ă"îûKa‡'ÓitûÖ)7æ«₫qµ)–…k$e¸xÛ,Ñ.dÑS‘ie+¢ˆéBíÄy9¶÷·c¶®c#M%$!+̉µéÑÓ ¹<Ñ8ƯÓ8 4°<ܹßP¯q™ ĐkƠ8ÙÄVzz' µ¾Ú '+tÛJ-ɬgXK}Z›v¢r£zF1Mœa$"~$Wœ&qzq=ñÖïÊt€¨ó…Füµ[]{üü8јÊĐzU»´ñyĂØ}oáwÖîVbqè>Aáƒy4zM¡c7ÆùË$b§[·€QlжÔ~0ª̀Ùyi²{n÷Jè7®«to ¥Đ€+Ư‡Å7Qèû-%̣Mư₫œi"ÅÇ»Đ¥Đ;}´Tv.Qu‡m8k‘·‡çq-!̀$7ư"ÙIWÙ¤æ¬̃˜ö6q ûíË×É=t¢ƯƠÉØeT†`/{z©v«Mq¡wRí¦.©wµ‘÷-µu·Û&Ÿ-Ø¿ĐVëd¤íĐgvØbÊ])̀=bνàÄÑÔ­º¬‡r´qÛăƒÜ!’Ổ"„JÅ›³áTäƠ‰Ú̀§̃`¶̃k‡j#jKZøc®´]‡Fg¡¸ß!§,,"'Úú\nÅ>ØƯfÜ×áÂÅàâà`m̉µf/%§ bÙ×s¿²]T₫§ÔbJ½ơƯ}Ú\=¿¤]̃₫¦w’§âf}ÙQ·¾'ăÍLă4HÖª1K#‘;qø7,CQ}̀T›vÁ¨{XÜh~ä–ØK®aQª|@ñ—XGÖ=â>Wỏtóèc+’ă2ÄèăZ)̃a¾mc®tFÎ{¨Ú,®æË™]ó}̃qp®‹]´¹‘Fè-Û?ÿ³é_B@̃bèÇáT¦ØíÖä:Îv †âXÎ{¸ô1ư ·Ö´Ü=ëft×°â~µXlâæ]æçwæ†Îv..hP̃‡S^ăzZÛ/£ƒ¾´u1EÎ âw̉ç¼¾àCn}f÷²•2I®)́}èÏưWéÑơ­ïïcß&Ê£ĂŒÄeÈ₫Qâ<ñ¢`~Å2Ề'̃íÆ₫í₫î¿+˜ßIđ®ÎqoWœMhvµ°]3¡íç̃ªr‹ªâ¬>’Úå¢+™Ç•á­ĂÙªÛØH7ÿd;±g³±è´¸̉"oăÇ'­Ç•̃ú¦̣1ă×É$ñîĐÊøü.Üá,Áñd .ø3„?öMƃ²M2@Á´Sf?‡öÑ€ó²Œfo, K- #¶¿†öèókVhVk÷çÉ?pïESÂö³x\’ößCapèö%÷AT£tïøÙ:¶È*ṕ`¼AÁÔđ D3!z~ÅPgÙ(ÊjQŸ2,Oïø%æÈñM₫#lÚàͫ٠jPåûØ*Ñ6 ÙaFÎMa í@ 'a¡/S…b¾<ÅLƯ[Rj„ büÂfÉ¿üƠo Mơü´ưÉ ge½ÿ ’¯Ü‘üMơ„Jè,î#l>ư"b ÓÏÍŸ "l˜rüávÔ₫ưÓ!¼v ÛưcO[CˆùAS˜pà¿vï8*Ü'‘¢@‚ÿ±Shíß¾†T¼ek÷-a6mß$ùMáÁ<}₫TèP¢EEZt§?<áÁs©°iRªU­^E:µ"­»Ôß¾đ̃p₫ó¶‚oß°Ù¤†7!̃˜Oc~ËÆâ7o6CR¶ÙPfaº3kæ¼Ø&¼lGK„,™nex—Yk₫Ü™ôgĐŸ>M˜›î•n/̉-œp7l̃ªư ÎYælĐ¡ñ>-½ùvÍÈ“Y»ÎlÚærÍm†nzzjë–Wg—^8›–+*́¤XSÅÎà%iœÜ>ÈÔ_?ưqưÿ‹© ¢¢´üD0AŸ̉:è®òR0±Ö:kAˆ²ñª- 7Ü+»̀æĂüÎ9%lĐÂi¼™Æ4– 2舩鍿©3R¨Cµ'ÖX¡£Êxa cè*#8Jƒç êHè'̀¸/¡2₫HƒÂÊ8#Åv́¢ƒôˆH#‘T’I'¡¤kÊ2¾iHÆ30j2:j̣F‹êx¨.*́‚ÜX#¢$—¤ëŒ$ ´iÊ*á¹2Ë-»ü’G̉̀#¿9TÍ'£tT"H±Ô’SJu´TLLË,̣HHÓ¤K+̃Èf›l¤qĂoJÅM/ưä0XÙ̉j®¨46Ù¤´º««¯”…–,gѪĐC¶¢ÅÖ­¹¾Ya'kóÛ •¾q£7ÖÈ5l":¨•P:È™“î̉f%QëUM¦yf£!â§^Çîj¨†àÑ %ǗÍí¤Éđ¨_•₫…'৆è!É:H5²Ñ—£Å₫t²C̀>BØ_‡ ¾Xàˆ ~*áé–ÈáÎöMyb›†ˆƯ—–yáÎ↠ͦ¿Q3†8vªÁ³¥Ú*`„Ê›¥ªæ'·zđÙ®…¥P+HËplµ¢ëCÜDôçµ¢æĂà™&5°Ămöù•ÓÚ‡/xØá«'Áê·Â÷bj¾¦Züy§>K²“4ß©̣Æ©…ÜÉƯy#?ɰ‰‡€…§;ZßËë³}r*¿\l4g‡ó›úÜöĐG§¼©̃ú½DáO"\©m®×h¾!¬5ÍÏQMjüÖ(¿Êºµđ©f"gÏç°l₫ă×B–ư®ç̣FÄoó Iµ%´FºÂø‡GÖÁÓƯî§û]íÖ½.)‚“ J.—@¾DúàJ¨Àñe‚kàYAxLPpt˜58<ÍåGO(Mư¡ÑAd߈F:bÂÚY„l̃>6È”₫ăƒ5tàçÅCFPt@”ŒUGD2Đˆ"„`¸tâ…,đ){d²À¨ƯE~á»ZÏ¢r 3 ëk‚Pä>Û¡íZr\]º"¸aŒ/¬c‹> ̣ư«]YÔ( R €ă" x V’Í«]î‡I9r%áØ›"JR ck₫Đ9ù;x r‘<‰î2g¡Kqr’Û¤;iIPJr”;P-ow\¦…“ä¥Í\wÈ>å6©ˆ?ø!F<ÊX?)_üª  ôQh›₫ŸñÔgm~SXÛr[Û|•x̣W=óÖôzbF̣Míbâ\…ʉ9{ÚóY Êç׿IÏ»”/(Oy‚Öl§OF t(bëç³îù¸†2”(•¨?EØưđ'$kŒ'¸~µOsn(RèJJ 7N&+ dG’ÂtXơóVˆô’¸§k¤ØŒ<·6Q3:n¡=›O0Ô³Ơsk²hµ°æ‚Áă Bµ56₫RC j₫OZF6Ơ¨I kX‡êT‘ˆ)üaAŧϓڴC̉Sêj×)U}/å«Ud–pöœzôNëX1ƒ^l?pe(@£z°ÊÓ-µle¡Zѳȕ‘=K¨f5S¡ˆ6.˜ơ«× ùlö竆MÖ5ó̉ÄÁV,-¥ `mKÙơ™íBiÛm‡̣̉³>ë`(ÅBúב6·®üLmt¡«êJ·ŸmƯ(áÚ M¯55´ü°nV{Q JµäE/Yđj,­ư4µç îeñê½Ö4¾BéæúîË[à2ÔZöƯïUèg?Åb $ÿˆJQ¯ÂVï•7¼æ}oƒÉê`ËÎô³N íA₫Ë'^ g6ºơÜÊ„œVÓÎ3¢C©Ư]\²WơXAă£/m]\܆mÆí­…hzăÿ –äûÍêRªÖƒyÄăm±ƒ5 à¹v*Ü©V+6]¶ÙĂÖ-J[0»e-iÍvÀc“j¹¾d>J~u‹æÁvvZh~ : :Üd. Ư«‚ùùĐ™Z 5«W%+ÝÎw¯¾Íó‚¼u,‘Îm6ùsY»Jºº»~4‹- PK#5uEË\v’a,;ÎX‘mŒwRÛSăWÑß0|g,Ójaè­ËưH#¢ôĂpb‚ôk;láwvw³€öj¥_XCˆêT₫»bµd¡–9vY“Đe_zAĐÎtd#»́u{zZ¶×›Æ7¥%̃Ht•ÓLo€÷+-$‘!×Bsx¤Tiç€ÙBy#L/;À¬J¾¨Đpϼ–1¼±|â>Ñ\m5×1rw†l×T*Γ—³;ÜxƯÉ:øC*,ï—ạ́Ê}KÅàgé + çoùvÇF́pß¶µ4ˆÔÙºËb®?Ïấˆ8Ù7î°R~Œäw×%„†CÉ `¢³}´P!’éx)Ïgˆ=€ñÚ\Ëa₫øuœí@¼ó,®p§GRpQ/:ÖtÊưÂF‡ñå×;€·Y-oÖ|RœX^¿û£Pfø†TÎx•¯’·7dq¯ûÅŸdû ÇÛ¡…B2“BWÉË­<÷7÷xâ£?ûÇO₫æ|âq̃|«!)úèBRïi3²‚¯##è N¬»g̃Å´–æ¿ÇÏ6nå´ơW‹^±åCǵ̣<] ±«=l9̃s>2º ;`’uĐ ”PƒiPˆˆă=•;†)9Ëù‰è[<2¼ÚS¼ Ä>œ[°²jÁ Y›?ªHŸ1º˜×I½w+A™ °cÿJA£³¡3Ç ₫3ư‹= )%vp<É+BÄÁ»›;Û»9ˆ Â‹ ü‘ ÏCˆ tà̉¸¶«= l!ÿƒ¼¡)dÂCí» Ø!&À©™‹gă¢z¹"Íă<¦Ø¢̉S,«³5&K=]Ó)¯Á¿'£A‘XBÉÛ€DÅ+»ŸpBÄÓ0TCd ø ˆ`­9¡hB*Œ;;ŒYBÉ€Ä5¼>çk>₫{>lDŒi>L̀56ê— C9t7Ë:˜p?2»AÆ£†38Äû¢£I:½₫ƃ̉†»ü¨! ©Ä1|¾XCgXC[,¼hÅëƒÅƒ₫ÀÄ™;0¢}(¶+d¹v2¯ô‰Â[ĂEôÆàYD tEëC Ó@]tX$Ă,ƒ*†ø‡fà%ø†h Æ ’ À„<5¤“p>4 ?„F‰T*­S§{|·üĂFh9G`ZÉMä ]TDŸˆDt|Ép<H¼Ät£JĂp‰ôFH|¦Y0E'\Dœ<È› H¶»É›DÇ5|ŨÊyÅ¢”IX„ĦTÄs4H¤¬©x‰8€=‘TÁ h‡40bÜ/²'X[Æø2=ùcËk;‹BDÅR–°¬ÄƯAHŒJ«¤Io\̀ÁJr”₫¬d‡VlEˆÊ}0J5¨…°Jxhz €2Å$G” ~ K­ LôJtL̀“PL—d̀Û G×ÁeYHª¤½lK:T·»œË$› ^k5øû­[ÎÉ Fœ2ɹFâü0LDÅ›½W ÇJ”̀ÇDMrTÄÄL̀›4ÁqË´0„ HÊÏLMol‡G[€›ä‹íÜJÆ´MÄ;€ÈTĂ˜œL#̀ơ\L'œ̀° Hp¤Íê;LŒœ«jû ¨³æ¤1¿³¹¸ø¹#®ˆµ¦Ë1C½æÜA¼¸?ˆ@IÁLhp H‚ÔÏÍƯDW¤QÜ<ˆ¦´~\₫ vtQö¤‚ῈüÜÄ₫,ÊV´ÊơFª”̉¤J(•<ẻj* „S3*¶(Ÿ{DS›ưbÓƠ'½dKc=>LlD·˜@èó@ç#¼ëë̉ËÇê›EŒY v #hœá3¢TÊS¤­‰Ñœ"4Vnt˜/å>/´ #₫\»1¬¤±Óhûˆ3mUWU4FËĐ"[MN\­µÜKu"®Ö“NϪ3ŒEF,Â/>È3¼í“Îæù»¬™ˆ½p†ÇD‰Ù1ˆCCÆs<€=C)ŒÅ„´ÅÙc9„DƠlă‰w©Óv}ĐQ‹«2ŸxMUFZÓzưÈ÷ Qà\½¾,QX L‘•½e¼ ;se>Ÿ¨À̃[Öͱ ¶à‹w`‡·Ó0Eœ†PR<‹„¹4DVœ£¾o5¤#Ẃ¤>€=V²$g—ƒ£NàDªl½´êÜZ[Ø’?ÂzS2ơ± áW«_*-+Ă2èêœP”>§èºC2%餘®k₫PT‹i®êø‹†Å˜)û"}ٽчˆ;›«ÎáđV=ƒˆƠ¬]9…]X2Î:œ’eƠ©\ÀM«Û¥].{Ưܵ]̃u°¯9QYj7´̣6}m7åÔU‘Qă=ˆ®S,̀.,[* -ÀÍ(ù;èE dH»́e]öŒÜv¡—¨Ṕe‰°™ b¬5Ô¸ơơ^œĂÚ9%+͘+«0›ºÊº˜x%Ï^é…°a+1î2`ƯQ³~+½£ ?¹ơĐ«£PÁ£~­¯₫ØƯ¾Ư¾ƯøÅN•($–S †Üv˜ Àƒp¢œ_ua²+₫̉Q×ơLïmxy<…Gw¹Üè8áÅ\êí°êͨ¬jIĨ_%FàVàëºb&6Nx“6@jÜ`µ­ô1¶˜­7{=›ƯK^ÅÙb§ß̀_Ê‚cªà2ƠÀ¨Ä²û•ü đz‡è»"% ’Œuˆµl ư`@H¶Pn” kÈS½ÀP ̀áƒ>)LÜă‡bĐù¤³qăNN/¤ ÎS®®¤@Aëß–48ÓĐw£×2¦à÷¹Û &Éâ2·éœ§’4pæc f¯äŒDôÄI0TfW\æ5L¿©PÊÏtÔO< `ÆÅÈÁ̀ ₫˜§›Éªl ‘ÓÙºÉÏ ?Å̀RíÔ›Û‹Đœhæ{Î4ߺ}Sxưe|₫ç|èCèaèƒ&h§‚¢Ç)sY%#cª3c~c€»Ù8ÍPl¬Ø·NëèöèV)ЬG]øĂu8€ß¹V2"ü‡̉\CˆÑxÇ`€ ÓœfàPËÈQ¦8ÀYéÀÏ´XœÜqB™fĐŸ$i¹”é«é*́µ*hÂê¯Îj°ë°&ë±öè9măy{èÔˆÂX32kS»åæ̀Û]û§§`¯Â'Ú4JK¶¾₫kàƠ'ÛÍJ¤ibæ₫k¾æA¾Å 6H€Ä(́GvX;²¯hø€o`€‡€ûÜ 0Ä̀“€X̣ˆz»Ă£s€ÏÓfm0l†¢VJ!ZĐl ́Ü₫kö%_Uâm¾&4Á̃íân¿>năÎíå&nƯæ`§»P¬‹´™ª tàjAă]ƠWeă aW+ÆâđaÍ’8†v†x@‡@RkHáăuM̉¶é~I¤ƒ(€€‡G«t`̉X€Ÿí“€ïvØRX¬˜Ü„‡J|ˆv€Í~C ‡îŒ_çïñN`²àêQöđÿđÇ_ñ.ñgªåJª‚"µ¹½¯“<₫NñÀÊ˹N .·øÍ̃Fqr³¹h(€q~đ%dGưḶ#/¤ÀĐÑu†Ñ"ƠGí¿ €pÖÊön?•Oûơ;)m'Ç̉ WLm¥R̀1ñ÷+? u[b?ñ5§s9góđ~,-('ˆH®’îjä…¨q¾B̃́ṼºöËéƒj®]D²£đóóÂ^;ëÆ¬Yơ¾ƒ<DqI`a7¬e5ă÷ 9NÆ\§p8;Ó̀ƯLe9>[´P‡p‰HN₫ÛG‡u\Wå1¡v ¥^z`}ú⨛ë>«ÎÂñ|Íe^SŒØYcÊ'¦v„6è„¶v€N?l₫·Đ½m̃M€‘́½ö¦ØörÏ6û₫Kt¯vn—‘Œf0ö‰âvvÏöv·÷z/è}Ï4B² 'zÏĐ©º¨#=Ù:2t‰¼èû‡œ—À62&g”¦Çx²øÏxëø‹ÏêKéq¡x×jÖ½§"¤G;ü;i'p˜GêøÈZ sX ¦}$ó+ë’¥$éœÉú¡ÿù¢@ų ¡ª‹O zúÁúuúª§ú«wz¬Ÿú¬çú­÷z©{«ïú°×úñ‰‰-¨å`¡Ê3:Ù̉¥|8v„wàGJ^‘¬ëA¼jC‰;ĐÛđû¿üÀüÁ'ü₫Â7üĂŸQüƒ¡ Æ¿opÊІ„püoÓø{ÇüQ|xB|Áç|Æ_ŒÏ'}̉Ÿ|¬Áü̉WưƠgưÖw}Á—†/È-¨‚5˜†Â(vh†/„iơàë>c|=t’¤³Wzˆlhk( ]q~]ÁŒÊ₫è§₫é·₫êÇ₫ë×₫́ç₫í¯Œlx ]Yí'ÿæÿ₫ÙÀ8Œlÿö÷†è†â  ë‡~ï')Ăđ₫î~]€đömÚ7 "<¨0!Ă…~‹èM`¶lß²asØp£Æ?z r¤È’½åøÑCG=jXÔöï»™6oầ©s'Ï>₫ƯéÏßLxđfú‹f4(Ó¦NŸ2…çÊQ¢Hÿùƒ—ªU¨^¿‚ »Sê“£ÿ´–µéo];£đ¶l¡̣„Ê‹Uî¾ «7/ß½~û₫+80áÁ† ¿XC×Î.S¡²bñ'Ó¤x¢æ5®PAaÇf*jÖ̀¨ÁÙôáÁŒóÚiØo5|¯˜­[6ä'/,[¦̉B1i*wh́NÎ[9óåΛ7r¥u?x¸Ü§Ư¿w5Å‚ÿÔêP«n£¥vF<ûö>¥rµÉhÖ©đººÏ¯*XÍY¥?óUy'}|æù'}ÿø‰ „êyh¡{º¨¢z²C_M₫LèŸ6Ás(:XÁ£†“ÿœ““6v|JS¢jƠ:UVJ%}¢jgŸxZjh¬¶Î*h®¸ç…gµlj°îÊh±ê(¯µ«l³̀"»,±ÎFû¬£4Á#5Ô°E7iqbMÜ•YîW]₫u#Uæ²û7iuEŸ—øµ[¯Xhø®€„ø„7ZÚpSabú„ôå/À3¬ÁE¼pÇƠ–¤juă7TdS%ÅzÖYKüñ–^z|•˜÷™Ụ̈XßüW”¾lz Ï>đÄ 0Â.³Ë²yüàü/­7m3ÏöŒîÍT}´Ó?ơ÷¤Èđ(¼óÓ[â—®}WG‰r¼œÚg5×ö­fºgj¹çYY1]̣ØXƒ)2§m]TÑW½M¦UP̃÷ÛÖ¼ù5ÜQ=¬ß\†œ.ɇ³çuÜ+‹Í¸™ú•MZxÛÜ7̃’ïçsQ@Ó=NEßÉy~Icºô‰¦?m;w¦ë/§¬₫»—ơY[Ó̃eØjU`ä¹çWv̀·_nèÚ8¯|í#u·è˜öư»̣cE.œMOß0Q2!ªƠÿ—=X‰¼®øQm_˜[±|¾”hÛ¨Mñæ-}Êî{åùY  ư<¦m—ă™̉4'@v¹ICùÎ÷0u@§Øeä‰ă®RŸ1MP<@£ñ̉Ʀû0ƒLQŸÜØÖ¿¬EO„#lÓÿ́§Â(eO¢áV”ú„|êr[+¨2öI‡@¹ÑđđÅ»³¨NgB„ZâøWz‘n‰y”§7øÄV©˜p¬Yùz)@e%‘ư|Y-—¶Gvóˆ¬f%‰–Mr0uz\hPF° s””à)×ơµ ¶£7Iă₫Ù ỌS›̀«ç?¡WÇuNp—Øt¡JYB»åŒ(@“©Zndƒâ¡ë)˜̃¹2Zh6ô¢D…2¾)₫§T­jSíækúo§FkæĂnf†ä1µ£r#ZĐzF…OCÑP}(¯Ư1U¨ó̉Ç?²ñ‚ a¥ÜyG§è©™ĐIt4KMV%+X¥tDR˜¸ăX:Av&ÜyƠ8k©ÇQ¬âƯ›>‹Y(¹É üG;Ê`°µă.°§MqyÇ´áGv \ZƠZBY-¥v̉êôjºÙ~ÈU”ɤ\ׄ+”ÚØ7Ø‘©uPj&Ú`]CÔ‘YƒĐ8 ]₫ẻw°ö(7ƒQ•G í’E¬V¾{”đ÷tµkÑûƯơ~—(î…¯àäK8ï2ÖFQ\"r{ʼnÄuŸqÿ]䮵·Y Vơ°Î’`‘ê‡ «QWTZ=QAªp}¨‹\P¢É7ªĐ‹ä(":n‹pt¢¹%GÙpB2WdçøFÊFuµÅI>̣Eˆ́¡›YÉQ²V,.ëÆ–É:Î]d@[^nnD!r·§aŸ:P±4Ù́ªŒi•¶ E®éº¢27È̀KÅÅCÑ @¤”ØNèF-ØB êă¹LCehÂLô2œ!":C£Ư₫ô„Æœ÷eHŒ1nT†4ÄÁIđ8ƒ}#'˜!K’nB,iM…Óuđ4¨Ñ;ê5”ú̉¨V5«]ư X“¡(g0Cp¤Ú¸!̃ Œbœ9iÂç«)k? c¤j8k’ ®¯8 Ïê÷»†Äk:}—×~ôăfe´®7® ci{#߯ƒq„"™žºĐ¡ƒ̀/ É„È GzøËÂL\¾(jÁáaƯ ¼?¦R2¶Ú̉p›¸‰"²†(”#o`ă /Xô™mtÓ|̃p-°ẵ›s˜“¬¤—{u6&‡â½ĂëqÎU)¼‰B¹›ac iø@|S7È%6NbLJó\₫%g(+ß¡:C‹”½j(ë(T›¬‚ơ k½M ,ûL¾~̉Ä=eä ÂƠ@lDD ¢•–¦m÷É+6Ë®Æknó ¯p}ØÙƠîm£P*´_¯m̀"ư¹¼Ø)µ$×ó5ÙÇ;œQ:ƯÉĂk±0"åYxœƯóẉ,d±»À́’̃ôCA=ë#µ*Ç[±ỐMÅ_vȵÿP F₫ ä×ËT¹gYî(¿Jø†áßơhÀ-¦éư‘#'œØ¤Bÿ³Joä¿jVăặF̣̀«<í°²Ê®̀E·Zÿÿ_ÍÉÍÄ:đÉhñfñŸŸŒÿ₫ñß  ¡ …àdƯĤôƒè\Èfµƒ̃q›ËÏ<Ùa‹°<^ZíL;¤A©œ`öĐËĂÅ7Ÿ¡˜L̃B™‡B‰_ ‰ …íŒ))×AOÜĐÇ „ åÀ¡Ư!­ ¡Z<-Y’mYi­Uá´ G%aQµƠR TbK•Ô—ÖĐy!•º` ÍÍÀ ÚÑáO‰áÔ¤™Ç$áJLß©ŒîKܤS>QyüƒT­NXÅE¡¦WÄtŸ÷MMÄ •¹…yxĂ ®›ú¥»ơÔ 0=S!:a’á:bvÉX¤"îYUdàPEJ>Yâ₫̣‰Q@b$öMU!&“$1×ú¥TZ‘”?d §ÀLÀá‰æaP¸ ¢*ö„,-L6 áR,…!^Ó"₫K#)­ÙFñâ ÆÓ¿’‰Í ‘Ôrq¢ zbOµÅÖÀâ]½€ÆKRcH¹âH…Úưănă QcV#ố™VUß A£f…É÷˜¢J½ ß5¢9’Ñ0ªR©ááă?d`E¾ß}øI?*¢¤BF$K.¤(ä áL¼Ăî ÷]#̃âÍ E[ÄT:ZPQdÅ ŒăFâ‘<¢!=²_? …ŸÅî“îKj¥:¢ b¹₫må†U}eRÖMTáÉC‚` öä¾̀QP×Ez!Øi$0êŒ̉’PV„$T‚MútmÍf}TVêÉX¦eY~ÍV¡å&f: Úª 9&yteÖ„ íäQ̣œNÜ$(¥Pîa ÔÂx£2åưtä1öT;µOW:•O‚ØY:Œf™Ê¼ƒ mƯOô¦©d—h±ƯøM j !§ŒÑćLˉ£[ZâÂ$VV́¢PJaí"]*ÏCVAÑ`Đ¥Ø_.TU¶á†É3ÑŒ²¦$zQ;ÔÖơ&שEMœ×ưfõ̀>„p¶IéĐí™Jorà?`]ÈÔÏN9₫̃"j₫$8Z§Wú¢bO"^k̉à<öN=ª”T‚ƯLDD̀P‰•ˆ_ˆ† ‰ed̃L¨ṇƒ‡]EyM¨Đ̃ó˜V`]UJq®~B ô'zÀp¡ g̃t.J \&iÖŒE~æ £v²#ÔRơJ™#t}üÉ!C̃áW ‡‹₫˜éëñzyVcÑD}êÄw);œNœË°Ă¡'×iáæ^ [&¨H‘¡?%O %bNJR(@Æă9Ơ`†>¥7͉—¨'aR€¤åAn!"w n8£ÅÉÍ×Y××Zzơé› w´ƒ›Ü₫Ôz!¹i¬Î„5 ĂRé+å>g4âĐÎP_[>hH æÆüËUº£ŃKDx¤Yi*‰'Y±¡î‹Tx)e>£’d*ÎY›XO®jIŸ†*;´C´ê?8À?̀k™²V®¦éQ­–)½æ«™̃ºÎ©3 ;ü*}Y¡Ey&R:azET²¦KW&Lÿ`Ö³æáy>Aú5¥¤º&î–}ôRTÔ¦b,VøÉa½fÀgQ?ibƯîĂœ₫C3́C8VËÂ,Vđ́ëüƒÔ6CÏ­UĬëÙ‰œ6UÂcWlV¸Ơƒr'Ơ"h^¥©Q₫©éا\«/ƯU¦‚ÉyÆLJÖfd¬Vïjb±̃p}̀ *v•©è ©Á̉  Â¬™®…ß)àâIÍnfö)b ªiàÚ́-&«UÁCî̃â­Mr‰È…nlk₫]±rè}đĂˆê7,€¨›R°̃Î9æzr•Z$íMôé‡ơ) À~Ʈͬ¡©á¬¡Ä¬pöî¤TêL¬é=q ’̣Ù ~?|ƒº%kṃƠHàŒ… E›…éj^iØzÊ|˜>d`lưG;`Ư7 H®)k¢¡̣‹©¬¯p ƠèIÍ&î̃¯MÀ»Êàö/Ω3°ëUø/M₫@J́Ö|¢wN«FĂÖbÛtnqáQÂÛÍt­Ø>YØ›\đôøÏ:ÀŒ™˜æ®ç r‡̣Ÿ\ùåx‡àØÄ>LíêIcïj›nŸíYß¼̃qjÁ"§ua Ó"ç¨ÚzX×|"Úâ[ÑÊqéÍ=hö"¤2̣•6”ĂƠƠóo>dEsÎ×ÊÛ¤öSü•¦6xƒä%°́ÈWI áǛüÎWæè1gJÈ1 ‹̀Ú1<Ü©|§5ŒK·ÙzUâr wô®…̀¦|@ËÁI¶ÍÓ ´ƒ\Å›5vŸ¯U?¨C‚ˆ ÛƯæ–R₫Ƕ0#ƯŒÈhHAØ[‹î¡º6lA ˜1N –}‚"ÿ'çZïMÔi€.q2»¯à̀r¤¨`"âÇ¡*¯ơ‰á:L/[§Äb[|‡XĂ&ÅöBê<Ê‹÷6#qÇxEÙ7tCø•yC p 䀸ˆŒ È† ?´‚´C'A'<¸sUH…´ĂÈ}ˆ†PƒŒhCÉ!ˆ†\ˆˆ`´ˆ,ô°v&,ó?Pí^ä~pæ‘ÅʦQتzhlWH†¶ŸCÙÍ\„7tC àÈ4LD7hÁ°DKø@LIơCH„EPB ơE AÄEàƯPDT[B|̃-₫µAdơU[„¾U„@`ÄWõ…ă'©·̉×1°V˜s䂸­N£tïˆ!–ụ̈ဤ¯1ådH(¬­ÁÓ}@¬ÁÔÀØÀôvü€KToÇdÈÅ È…dÏ…eW¶\HÆeG†e«ƒu6kXö”ö † ῭…\ØƯe[¶f³¶dØj3h6h3˜Ưµ6j?Án«eDÆk?AÓ¥€Ô‚̃åg ]Q’ µPhCªåµ̣¸á}gS­G¯qü•[LÅ<Ïsl­OÏÀä@X‡ˆÓ¾"7 |»·|+ˆˆ"ÈÔ¼w~Ç7}ó·ƒØ7÷¹…₫XÄY¿œ’‹.Vmôná/ÊTø`÷&º2–öÚ€7Ù¶ÑNM6Ø3KpÁ7¬m»=cÙ¥e–(JfWV•e^gœ^Ñ8+/°ugT £c:JqÛ FÔR³vƒ _ẉÀ[‚Yà,n7¸¯7)°;ỘœÅ«ps 95‰‘uelªî?@ƒ₫í!₫p-₫É'¥̀è˜nƯ‰œA†ÄVD_XIX¹Wɹ_¼]¡Y`:…jMÏ?Đ×¢ÍSX¦üƠÄ¥ØUX×YYÜfy=Qœ]gÖZ(ç3ƒÊf—ÓÇhUJ̣ǵ₫± 9ÿ9@c•ÇôĐ:¸ -hRª[»wñ¾êÑ•³yî ¯ïØ¦L¿z{bXpcÇx—î#LåÛNok„ưæm7o×̃¸IQG£*‹Í’Qr†Ù2gâH„Wæi†¦0œB 5xßʤ‰íZC‰ßœ˜Ézơ´ß¯c3¤mnƯexû.\qă¿₫“7¨Í̀“ÜŸh©á Û–*`Ă•{6₫cû÷ÿ#k2!Ô¿ø Đ-¸₫ϤúLp@ưĂ迌­ÉÀê«lüBP ![ê·Z(›5̀PB *^¨Â5®p›o´Aé·Í€úí·îàɨă(rP(Œ3«¡²Ñȉt̀LH³̀È,%âñ¢̀€ôfIŒÄQ›$Ô(³j~ó&›7´¨¢¹àÚË? 9lóª¯ä"²üsÓÎÓtªÎêºÓÏüœ‚¨°?Ư¤Áơ£MBµ!Â[¡pJăTÈÉÀ©¤‘ ©éŸPKÊh§NOúg!0;‚'₫…ÄJhUX?ưçƠ•HưÉSxPư”׈zu$ˆdưƠÓRuÓ¦‚>D³¾…ö\´Ñ Ăz‡?§Ív@8ÅV[;ë#ë3₫û?CĂ…CÆ̀ưVÑMa]Ç!äÎi?}à\JR«ü)iS“tb0¬€óów¦Ø ¾“ØLøßT¸*„ơ;˜áf '2´„g ơCp>iÛÅSƠá1ì’YÎ*Ư”ÍbªÏ–í£Oáđơ‡&k4>ÄåùO9]́б¾úÆèÀHú͸<êÏÙ½°mÚi·₫ÊóŸsúñg¡«i>©RuS«ÁNká“ưé_ŒÓÆ ̉ óË1øƯ$₫k]ª¢ÅÛ±|’ï‰&µ†È¿™Ïkí†Öi[Ÿ¿×6M›åƠ)ñÊ·ư;á~Öá•s¬}άÂĐ/¢ µ01§[u»4´öÑ:¯zöO₫Çm¦ÚưO±—{å~­4Z _”¬ôĂB=úûô†ư°×ÿĆú¶ÂÚ/γàybj§æcüû­ÖVƠa}Ê^ŸĂú* =ÄCåßJávvèëü­´ˆ]´ ëü¶=AiQô1 ₫ªb;©µ¯[sÁßợ7¬ƒlÁ €ÄkµÄ$ÉûàÄ0¶”[Đ)‘ƒ́V@ª%{åê½7C~¡ Q ₫‹ù(ÈÅép‡dYÈÁJåA"nNÉNR·>ïÅ&¡ÆÊơ@tñhÖ[bZªÇ@Àµ®nˆú" Ï’Ă-¬@̃:ăÑF̉ U)¡2odÚ^ôS èbK¼Xºăn±nëâO'Ævïä]ÈDÀ©)*vÄ_óv‡•Y2/ljG@F¹†P”"× )0ZR'%qeª(ôJưœƒ!̃°ĂYJÂÛA¬$&lGX†%Ë>¬­l ;ŒyLe¦ ™Ä,æ0yiaŒ`öúÇ.UµF¤ÅÅ3|™(Ë·IN.HCdqÂʲˆA ưç7K;a*ahÈqŒ`&qÆ₫oÖP $rª̣F †u¦dn,ơdæItRE„´™ ;Lj₫Ău(ÄÊLcRS¢ÓI4Œi ”Øá|NyYÔÇÂu6e!kœ'dđNxÈ)\csJ¦²‹wăäD)ZùŘ₫8Ç;à1;äD™’™J7úP€E”¢¼̀¨3¹̉P¬:´¡Ưj3̀h—¯”Œ$µ&ÄP6RxlªC\ú̉»ˆL’DtëÑøÁ¹]đB>§.§"¯ß¬à?¿ô¡JRť˙­4¨,ÅJOru« mÊU3ÖTA•*í#guâ)“ŒÄdqiîÖôE·̣ă+Ø’+[₫r8§ùÍ›o! ơ:=Uz‘•Mñ‰5ö¡“ÖédÍ@É7T“àIEí8Hp] €ªX4ª•îC ÚY©º’×=‰t“™YRƠ¢‰t£‘àN…§}¤îtH<§h¬||-lù62»pŒyÅ <û*Ă7̣C'8xG•[•)Úđ†àA¶< !Øu«(^b&ÓÀHè”yƯ‰zÖ±&ñp+# VÈn8»¯,‰‡ỊC*ïhGt´MJ x”W9Øm÷tßå,/¨d|QØ_1jQ·=åñă€l¶dªNÎÑ` ᤙ₫®h“'â‡JÙ£́8@3A₫lậj圥¨wSç«̣2±Ó]&E 0ÚTyÊ´"|k›Âùƒ§Ó[:„­»“ï “¶d®R•̣|iwă¼“o¬`½[táQ¿¼ƒ`Øu©\axwƠ/>0ŒWª6Ö­2«½ÛƯX¯úÀij‰¿[`V¿x™µ‰WƯ Xgj ÇhƠ^¥®E4Z>?–2dIsgn!ô2̃Ú‘`«öp¿Ú¹Œü µJÀ{fPxÊç 1±=å|gZßS. ˆ1p«¿Ö÷™Ơ,cbc:Q61S®[€„ÁLđó$åÓÍÚÚ022½6¶Ó ₫‘¸ÖT‹€j›ƒ$ À½₫,Q–~©wpØlM)ưب+á}€Ö·—¥‚ja£:Îæ^8À®›f¢ëúØoʯ»Ëa)OùƠù†ódQͼ™O_̃‰.Zio›Û?†ë¡?î²Ø₫°I…S)ˆÛÿê†ă&÷‹«Ø¤ذƒ©¢®y™ßøÀ?Đ/LÎÔS̃`Öafư,ƠfÔwĐwƯ˜dëf₫‚'~b:Óy]^|Ư}ØÎÂD3óê¥ë Pàß(QUùÂN?@¿=P.tÓî•£Ơ—伩ÂüËd£±¼†–Ÿ,;l‰̀œÇ ™¼Pø₫'´£«@¿"#é.å˶gƠSÿo/T½ö—Ñ»tó«×´>Đ/Û|SƯç%Ñ¿íªèºâăØüáÀÀ˜‚Â<¥ÀÚô‹́âBN€̀¾‚/+Haüc,RʦøK>’ỏè{œïù$Ăđ ™¼æ¬!G.…%4+Æ̉«˜ª˜´zÏ™`¼Êúđß₫C¸Ç˜̣L‚À” 1¤¢¼¬ÛÚÁ@&­v¯Çªâ/ …+°Çè¤ tŒ ăQ„"ạ̊gåL'†F ª5́À©ê ¶d©8b¡€Fîç „°!ª—₫fX₫¢TÎ Ô` ¡êÉúJ₫ơ­T«©Àh c —‚çaà!¶î_ü¡½VF́LÈË¢ø²Đ#ôÅ)ĐÊbxï‚`Hi)èuH—r `@‚!²aB†"½PâŸ*ƒ´œÂÁºa´ ?«ª† ¬ÆJ˜ª5Ë¡ÉkJ̀ 2LªÈB!|ñSJEGd4n‰‡Đ<. -PD®ÓĐÑÄ‚@€ƒ¿‡§Zίzk˜¢5Và—HFD6xF®€ lÀt SZB72"#4B!B6€"&€¤!D!!̉!Å%nq!e"=#)̉Ij"µÁ ’ăÄâ¤d1Đ ‹,Êí₫ĐQ+¾â%‘f?hüámd•`‘̉^K_Ú©D °Á ¬$²¡®¡¸@tÀ~ t 6£*«̉J°̣*…ÂJ¶²+µ2+ÁR+Å2,Ç̣+Í2+Í2-½’H́¸àEPRˆ,¨U§BÂ'ËZ%&ßDC&ç7ø¤_ˆè ëwâg§¬W̉€R"%0Ä4 ́` ªàD̉` j`vÀ)} x *¯à Nc4E³4Ió4M35Qs5U³5Yó5]36Qó h³4iÓ  ̉À ^ ̃€ôd́¾H0q¦l®0ơ’o.Ç$@VèrṿdŒ~ô‰'ĂÍQ|̣₫¾ÂÈ0~ƒ r¬;²á¤ª@ ¼à)ÀlÀ 1²=Ưó=á3>ås>és>;Z ¤*Ȇṕ…0•(9·§d,ÜÆ!ê"x)MüẠ̊á¶^ñ:E2́NÈ6BØÁÁT2JtCÄä¤A v lÀ (]Ô‘¯Ç̣T4EQ”E_´EYî¢ H‚®01ƠÉ{Ú_lÛt)T”úAøđö§@â—;+ô¥–¢z–&G^ "B$$êË,ºƒ=̃Dî'j 'ˆ%Lÿf¦ÈLû°L}èKÇ4MÑ”MÍÔMÛ”Msp#XøP2Úø‘X¢„ú2@´Û₫E_B'4¾†>VÈ:eh\î¾ɨĂ bĂ~"¦&,Fv†|zÏS1T)GTAµ@BơSá¦TQœ¨÷lOúîÀ9ậ‘4,$â•&"P•n.dX€”ơ'\"®(BÙ…µåIçIa²Dô£Ö%rº&Uàçp¾ákœS—U*$ƒĐ¼•ORÅ[·5\Yk\ư¥\e†\¿Ơxô]Áơ\×U]͵]¿5a~,!T‘©ÚA›æÏÆqÚÈç¶Œ~ §íVb_æQR,¼cơf _ú²¥Î‡äH±¦jêE÷k¹v‡Ôq¦†‘¶ü ÛáN̉wvt‡h-iÓN ưY‘4¦>På3‘tÔẪĂ2Z '̃`FQHù†¨gMgEe¶vÙ$eñGÑb·eŸj)ä…ƒ`e'D€Á)m÷ë®ø–@‚sO·MnÉP~L₫]́QÈ¢œU]¼T½(Gˆ–cÓÅd…ùj7E]v|Ơ‘wshíPTw&'7¨O¾¦$́ ÅQ8Ơ6Nd‹24·buoˆt§w}Vi\¨rh;=$îÀ7~‚XÂÅWkÁă¾°hÿ·Ạ$ƒe7qÿ²mú%dªÁÈ€s?%Đ’€fyáVhß yßNz7¸.{̉nåªo"ÅAÀÑ)B6Ëx“́i-…n†~—d~æf&é…rđ¥TÈ€ D"®giuÅ&sÛVĐG€?7PäÉ$t·®7‡áEiBd3Îd3°̉3²A©6©lD˜fEÑÂ…w·wY~µ₫.Xn¡†„$ÂR„=\ ăB%ư5yÆÚ7†ç̣si˜n±‡¡4Y—¦;Ô€6ă`\` \`Vä rL!cªLUYX „åă•ËzbY–U™–Y¹µè&~f¹–=¢!à($)»A ®àló4‹·Mv"l»¸ˆ¿øÈ¸@C· y wÑR1Æ[#€Eiœà;àA ̉àœÀ¤ È€5ă ¨X"Ê`ê T–` t‘–œạ̀I:̉  œ¤ à;¾œù¹¾ à 8ØÙß9!bë¹:đLfcŸûùŸƒœÉ`'œÀ ̉LÓ ´€(h€2Y†₫kk÷³™·p¥?x†¶€çñ†Ïø¥2-F_$#â Â:¢H23pä|#Gê°íĐ!¸²¬å:C!́PKmGäF¤¨»ˆ1…&Ụ́Z›ú©‡ä8ª™¤![ĂI¢&ó ôS­J—•Y2˜WWû\ùTŒ§™zG·imútïæKB5%̉Urâ&zÙ¹î§GªÖCƒ2¢oÏ"‡H±ueGbIa.û%äC±'[6,Û!Lp'rÄ>àIZ`róz§ç†w’ù´’ ³Œă©¦_k¯₫g!ƠxTø$sU k6c(pâ£<Ê{TÑt&j₫`NQsb‹¹ʹEF?̃F!̉à”µá¼0wªô­ó‡pÄB®a’¶wŒ.¢¹LóÚ€«¹î®YÈd¦Ă]PLGv_42à"a*æq™ÂæÓa₫[§ơCdư¡´üû`äE_Îa”PÀ}‰[Â##Á†ÁÏÆÁ•ÀO¦~Qb \››l›’}’éZ’aÉpûh¼÷K\Œæ?ë[ÁTrf³N0å¨_‚7„ÿû˜p¹)<¸ú%ÂáB^äH`JâÇÙ!ÈlÈ‹ü˜pn ₫ øÏŸ¿í£â A‚đœ|ƒ·ÏàĂ‹3jÜȱ£Ç ü/a3„J¾\ɲ¥Ë—0èĐ»àéüw3¦ÏŸ@Ẻ$YPÛ7'A“*ưÏ•Báe{:s©Ơ«1›>q(̣ ¼o[áô·OaM‹De¦ ÉơaÛµZ”RíZ¯qߺƠ8’®ß‹g‡̣ƒ÷¢áP…ÿ$D‹µñU¨¾û·^œ‰3köYu`»₫8Ù¸êƯLúcg¼ ¿™]ºµÆ¦Oë†ô[¬ëÛX¥RíJ̉©Ăfư‚ëỶ`Yvc‘—|¹?}‘äG6¹Í‡̉{ö¤lÓụ́ΡwŸ^ư]ơ›Po^çI“ß¿áÍÇîc§3fˆ$á=™ .îÿUEœ{ùíÇ€*EW€av`‚®u×W[Aˆ`m²±5•mv’VzYÔ” %!×Îd́°c B<9wPEr͇œ{cÍ•âl0F–¢?ÔÍFÓ1̉%#‹zåˆĐ=vÆNBÑ÷>(ÂcG6j‰F̉ •䟇­I¸Ó?ƒæ™?Uå~¹÷ WIHq₫̃¬giÎ$Wmr̃éá`¾ è•7W’¤M6̃dÚ8„äv7®ƠΑ&$”6mă:ë¥s"̉N6¹®F¦Ñ4”É­ÀøJ}e ¬å±ücF>ệ5¾4!₫w(ç0jÂ϶†ÂÛP«.û’Pƒ¨<³/¡6P3½PÈ`ôƒNÔó̀ÿDÓ1F€*ȺŒ́—BáåXØôNx*ˆk2Ó—́iBhöƒ$ß@#?ejNVΑR‘ÔøjÊ2-W”#Í„µ‡z̀Đa¾‚ÔÈä›! I„*´%‰ÆD ¡Ñ“b„8ÛR$=]™¹¸Ecd¢i†Ê(Ázñ›£©L09Ö)E Ÿå Qỉ×0ô¥0u¨E9b°lT(0 ¨N`KS§y×M6 ’u§ÉQ@¹xÖ8¹Sdm5ÊÏ5Êë‚ơª3₫&‡$z=0 3ci¯>(\ÅcF’i vO©É`&E”µ$ë  đR†Ñ¸¶&ˆcëeƒGw¢L,¹<©äḥ,—Q%Ö¤̀?¤—w­E^Ñ<›ÙRe¶Ÿ/EfTœª²`đªf¡œÅ¢̃#́p›Tè[µ‰{.iwF”µnơ«b\-Ï´ªS»¶Å“yu”t&R ¶¼idŒ]m`ç;_wŸÈäVå B/§Ü‡@Í8È1´ûRƧª¬¤b@Ă·däRM6IS=ˆ `ưÊ î:’Á!X[è˜:»Ø¿2»̀£Kœ3Á>Í¿m±M­₫‘Zc$…Ó½ËsŸÉ_}Úx>ÚfjƯT´ ®"…œfBƯmki Ă?*\Æ©3ÈŒñd,ËI3 wyA6ÍhŸä2«·¾á{\Äê₫x/y%Ú›ăIăÀc³sVĐmE–Ñ̉E,ĂYX’5Ô‡$\/àƠ7́ ) ¤"Ὼ£#±F®äI?(I–¢Úö̉E²-Y&óJ¿È —®…GÙçNÛÙ&Æ}slK™̀J%~–4c6l—ô¤¿sÖ‰mŒØ¸tæÊ³K ¯pg;4-­" ̉áŒØµ¾l‹tÓ…7|# >£[¾üZ–uùj( ±T Ñ₫%©›$éfí?PH’Áôk^‰wZ¬Áî6wMú̃ ½SÅ’ÎûŒñz¡NŒr:KAé×À&öLßÛ›è#8•´²eÉƠ~¬ĂKà…'cÖ!x´·¼|Ô‹¿¼†tcZ(àWT‚:DC'fĐê~W‡i|… J¨ƒàî\óhІvjG¨phèÄ AÜ7Ê¡—« Xßyz₫ó¨ë¤ E?:’¾ô¦?ƯëS¯ú®¦um¬«/PÊ'Ä qHÁ 鑜÷Ư¸°üÜ3ĘÖ>÷Æ­è̉°ñĐÑÆŒÛ*–‘3Z̀đ7Øh—{5E `¡Áºµ₫CƯM'móÛƠi7´e£kNƒßÄö•D-kRkÛWÚ†º‰|÷í MÔÊ64Úƒ+4€l×tû¯è„L‹ZÔå·oLăơ<93y»x֛،iÇpúQ+›Ú́‡:¸mÏÂÛ99Ô<çỞpµ@pF©Û˜kîsÁ{'ư1Dáy•E ĂCè°¾D “úoùÑ^x0'2YɶB 8^b/ ¨Ơà|ñ²{%‚FG;‘@ƯçGg;vëĐl—‚ÇÂ[cÑ0>tYƠG7g~¤a[57q(w0†’Ñ)¸ Ä™UI¶5¤&J—)–D₫̉ñh©r$Y8jVØTØ"Y8EV8åÇ/íuN0èQ…Q•‚OGx–NJĂ#ƒ1UÜ¢B<È9D:€Ôpæ_K#BU!óVJ$…Úà"S¶ çÀ!Ơ!)"ñ¡{U˜Ø"W8#±WdH—HØ´‰–G–5I•Á/Úđ@DRÏáïpsƠ‡ &dç¥]ÓÔUđ0`í׆‡+qà í7PØ2\Ñ(̉“M-ñ‚‹TU]ÖH9cR#´±k¾¢Đñ?"›v£–Ză‘4s”ñ5–Y­ö‰ sïbîh\"[̣ÈQÑM˜†₫„́ôA߀+‘¸Içr6ö+è\d3´.—AŒƠøRŸ6†Gg%¾–$âX~À%Iơ[ï’’â –SE²±b&¶¹1ÉÈ"-!̉ÔÈOrщ¶9SƠ‚|ø}Yb1&a†‚µá á 1kwE_PYG5‘O›çN‹(U“Uyn‘AC™‡ÚÀíĐ@(ˆƒKU\´–4 `Ô#-ˆ29áxôqn,%zdf>"G€É½ơg|D$̀ÔZƯgRÄ–Qnvà ÖÀe¼xx ‘]Œ™Mµ–3™FHé‘©}í0t¾˜.I-æe|₫ÙeEg)fñ´'›·9\±.`™˜™ù ¶™‹g—í 9‡F•a™—©TØÅ@À)—äơ?½2>çe\nQ¿…“¦qf¸E•©€˜VÅ?¦˜˜SœÙT~˜LDV{R™¢%"¢¥ågXYnDđĐqđ%µIÅÁÉKÔ9Q‚UleĵÁ!P¤̃é`^ µ)4s—̀•_đi1œëYœøF5æ~CñZÚ(jđ̉C 4AY“Ăq ö—}9˜m‰¢iéW†A)‰k5ܤ›'µŸ V±"D……£UÊ`\y‘™™]BªAỹ0Bn@z₫ûgoă”#æẀØ¡ùAC̣N4´&1v¥'h¥ZJD¢á äBjR2Ø4›aä \å0g±¤L*¤6Ä)§kKÉÙ¡ß \`5Đ ạ̊f?ë̉fP¾¢ vđ̉3‰+°L çP+°̣;*Äă<‚èÎĂ5̀să©[©“ •z©„¤©œZŸmªd ªß@WpŸ́0›–.ß)ÚÙ£q!%Ö*\z:‰á&s¤G™¤Êb§CŸ̃pØ ¨äbƠç/nC›Ø –( ø¡½ç|Nô-Qä{E³zY3âJ®µ‡}ơ2{F¡®ñ¢₫6̃ĐGc¥+WPƯ· ;úÊa‹›(¡8øC$”,Ùu° ©œ2wF/p%Nôd1^rCÇYóI;ˆ/ ó% 1éæ%;n½ö!ë#K)ÛëPr÷*°4 :) B[¡0‹G¬.é —¶.HP¡ZʬFMki¬nJJÚ‚0̉azS÷dÑ)±FjŒÄä”I}öP¹4ĐùÚÁéôµ3¶Ú1¶“Ẵ(̃Đ 5€ |3 ̣ ‡Dk­?F*»£2Â5™DQ&z™9±q ¨T‰¡È"₫À”i dï@ïbƉ̣ÁiÊ1‹ë#”;I–₫‹¹æá››$SÏc}kP/È5ûW[´F+]fà ïöc±…]rˆ¸Ôê°UµNá+Ăñ‚ [LT¡ö¶ÿp˜tj§̣"L™PѼ5̣lă±Í[…ĐK¶ƯQiƠ‹jA ṇ̃ q  ¯‚.Ăz›¹i¬ah%¡aVÊö´=¸ÊB±.•Lg¦Sd– Djđ€—;*Äo)³»[À—{o>tüÀÀeÀü€À¡À́|¹Dạ̊ŒtGaʦ£4Á£đ›" ¤Bg9ZÎÔ¡{ÊÁKbèéªá(æF_K*¤i’!oBôĂnVo1v)W3?̀ZA¼¥rCœ„qÑù€æFˆ0Bem*@ơ‚̉ê` Ô ƒ\U¿xE b¬Â«Yÿ•gWê¬`ÔøÆtÄahÜÅo­Ëq0lÇ'̀ÇđûÇ€|3peœ\Ȇ|Ȉ¬8x¬T~œÈüÈÉb”„,É–l!;commons-dbcp-rel-commons-dbcp-2.9.0/src/site/resources/profile.jacoco000066400000000000000000000016611410126276600256400ustar00rootroot00000000000000# 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.9.0/src/site/site.xml000066400000000000000000000052571410126276600225010ustar00rootroot00000000000000 Commons DBCP /images/dbcp-logo-white.png /index.html commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/000077500000000000000000000000001410126276600217375ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/building.xml000066400000000000000000000035601410126276600242620ustar00rootroot00000000000000 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.9.0/src/site/xdoc/configuration.xml000066400000000000000000000435401410126276600253360ustar00rootroot00000000000000 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.
jmxName Registers the DataSource as JMX MBean under specified name. The name has to conform to the JMX Object Name Syntax (see javadoc).
commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/download_dbcp.xml000066400000000000000000000331721410126276600252660ustar00rootroot00000000000000 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.9.0-bin.tar.gz sha512 pgp
commons-dbcp2-2.9.0-bin.zip sha512 pgp
commons-dbcp2-2.9.0-src.tar.gz sha512 pgp
commons-dbcp2-2.9.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
commons-dbcp-1.4-bin.tar.gz sha256 pgp
commons-dbcp-1.4-bin.zip sha256 pgp
commons-dbcp-1.4-src.tar.gz sha256 pgp
commons-dbcp-1.4-src.zip sha256 pgp
commons-dbcp-1.3-bin.tar.gz sha256 pgp
commons-dbcp-1.3-bin.zip sha256 pgp
commons-dbcp-1.3-src.tar.gz sha256 pgp
commons-dbcp-1.3-src.zip sha256 pgp

Older releases can be obtained from the archives.

commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/guide/000077500000000000000000000000001410126276600230345ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/guide/classdiagrams.xml000066400000000000000000000026511410126276600263770ustar00rootroot00000000000000 Class Diagrams Commons Documentation Team
commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/guide/index.xml000066400000000000000000000024251410126276600246700ustar00rootroot00000000000000 Developers Guide Commons Documentation Team
commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/guide/jndi-howto.xml000066400000000000000000000102231410126276600256360ustar00rootroot00000000000000 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.9.0/src/site/xdoc/guide/sequencediagrams.xml000066400000000000000000000024731410126276600271040ustar00rootroot00000000000000 Sequence Diagrams Commons Documentation Team
commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/index.xml000066400000000000000000000120301410126276600235640ustar00rootroot00000000000000 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.9.0 compiles and runs under Java 8 (JDBC 4.2) and above.
  • DBCP 2.8.0 compiles and runs under Java 8 (JDBC 4.2) and above.
  • DBCP 2.7.0 compiles and runs under Java 8 (JDBC 4.2) and above.
  • DBCP 2.6.0 compiles and runs under Java 8 (JDBC 4.2) and above.
  • DBCP 2.5.0 compiles and runs under Java 8 (JDBC 4.2) and above.
  • DBCP 2.4.0 compiles and runs under Java 7 (JDBC 4.1) and above.
  • DBCP 1.4 compiles and runs under Java 6 (JDBC 4) and above.
  • DBCP 1.3 compiles and runs under Java 1.4-5.0 (JDBC 3) and above.

Running

  • DBCP 2.9.0 binaries should be used by applications running on Java 8 and above.
  • DBCP 2.8.0 binaries should be used by applications running on Java 8 and above.
  • DBCP 2.7.0 binaries should be used by applications running on Java 8 and above.
  • DBCP 2.6.0 binaries should be used by applications running on Java 8 and above.
  • DBCP 2.5.0 binaries should be used by applications running under Java 8.
  • DBCP 2.4.0 binaries should be used by applications running under Java 7.
  • DBCP 1.4 binaries should be used by applications running under Java 6.
  • DBCP 1.3 should be used when running under Java 1.4 and 5.0.

DBCP 2 is based on Commons Pool 2 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 2.

There is no difference in the codebase supporting DBCP 1.4.x and 1.3.x other than that the code implementing methods added to support JDBC 4 has been filtered out of the DBCP 1.3 sources.

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.9.0/src/site/xdoc/issue-tracking.xml000066400000000000000000000133421410126276600254140ustar00rootroot00000000000000 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 subversion and creating patches see the Apache Contributors Guide.

You may also find these links useful:

commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/mail-lists.xml000066400000000000000000000237131410126276600245450ustar00rootroot00000000000000 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. Patches are best handled via the Issue Tracking system. 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 mail-archives.apache.org
lists.apache.org
markmail.org
www.mail-archive.com
news.gmane.org
Commons Developer List

Discussion of development of Apache Commons DBCP.

Subscribe Unsubscribe Post mail-archives.apache.org
lists.apache.org
markmail.org
www.mail-archive.com
news.gmane.org
Commons Issues List

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

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

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

Subscribe Unsubscribe read only mail-archives.apache.org
lists.apache.org
markmail.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 mail-archives.apache.org
lists.apache.org
markmail.org
old.nabble.com
www.mail-archive.com
news.gmane.org
commons-dbcp-rel-commons-dbcp-2.9.0/src/site/xdoc/release-notes-1.1.xml000066400000000000000000000447761410126276600255460ustar00rootroot00000000000000 Release notes for Commons-DBCP 1.1 Commons Documentation Team $Id$

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.9.0/src/site/xdoc/release-notes-1.2.1.xml000066400000000000000000000044551410126276600256740ustar00rootroot00000000000000 Release notes for Commons-DBCP 1.2.1 Commons Documentation Team $Id$

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.9.0/src/site/xdoc/release-notes-1.2.xml000066400000000000000000000204211410126276600255240ustar00rootroot00000000000000 Release notes for Commons-DBCP 1.2 Commons Documentation Team $Id$

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.9.0/src/test/000077500000000000000000000000001410126276600210155ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/test/java/000077500000000000000000000000001410126276600217365ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/test/java/org/000077500000000000000000000000001410126276600225255ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/test/java/org/apache/000077500000000000000000000000001410126276600237465ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/test/java/org/apache/commons/000077500000000000000000000000001410126276600254215ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/test/java/org/apache/commons/dbcp2/000077500000000000000000000000001410126276600264135ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.0/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java000066400000000000000000000073531410126276600323020ustar00rootroot00000000000000/* * 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.ArrayList; import java.util.EmptyStackException; import java.util.Iterator; 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 messageStack = new Stack<>(); private static final Lock lock = new ReentrantLock(); public static void clear() { lock.lock(); try { messageStack.clear(); } finally { lock.unlock(); } } /** * Note: iterator is fail-fast, lock the stack first. */ public static List getAll() { final Iterator iterator = messageStack.iterator(); final List messages = new ArrayList<>(); while (iterator.hasNext()) { messages.add(iterator.next()); } return messages; } public static boolean isEmpty() { return messageStack.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() { String ret = null; lock.lock(); try { ret = messageStack.pop(); } catch (final EmptyStackException ex) { // ignore, return null } finally { lock.unlock(); } return ret; } /** * 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 java.io.StringWriter(1024); final java.io.PrintWriter pw = new java.io.PrintWriter(sw); t.printStackTrace(pw); pw.close(); buf.append(sw.toString()); } messageStack.push(buf.toString()); } finally { lock.unlock(); } } } TestAbandonedBasicDataSource.java000066400000000000000000000330661410126276600346370ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.SQLException; import java.sql.Statement; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; 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.getLastUsed() > 0); con.setLastUsed(0); } // ---------- Abandoned Test ----------- /** * 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); Assertions.assertNotNull(ps.executeQuery()); 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); Assertions.assertNotNull(st.executeQuery("")); 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(10000); sw = new StringWriter(); ds.setAbandonedLogWriter(new PrintWriter(sw)); } @Test public void testAbandoned() throws Exception { // force abandoned ds.setRemoveAbandonedTimeout(0); ds.setMaxTotal(1); for (int i = 0; i < 3; i++) { assertNotNull(ds.getConnection()); } } @Test public void testAbandonedClose() throws Exception { // force abandoned ds.setRemoveAbandonedTimeout(0); ds.setMaxTotal(1); ds.setAccessToUnderlyingConnectionAllowed(true); final Connection conn1 = getConnection(); assertNotNull(conn1); assertEquals(1, ds.getNumActive()); final 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()); conn2.close(); assertEquals(0, ds.getNumActive()); // Second close on conn1 is OK as of dbcp 1.3 conn1.close(); assertEquals(0, ds.getNumActive()); final String string = sw.toString(); assertTrue(string.contains("testAbandonedClose"), string); } @Test public void testAbandonedCloseWithExceptions() throws Exception { // force abandoned ds.setRemoveAbandonedTimeout(0); 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) { } assertEquals(0, ds.getNumActive()); final String string = sw.toString(); assertTrue(string.contains("testAbandonedCloseWithExceptions"), string); } /** * 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 { final 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(); @SuppressWarnings("unchecked") final GenericKeyedObjectPool gkop = (GenericKeyedObjectPool) TesterUtils.getField(poolingConn, "pstmtPool"); 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(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()) {} } } /** * DBCP-343 - verify that using a DelegatingStatement updates * the lastUsed on the parent connection */ @Test public void testLastUsedLargePreparedStatementUse() throws Exception { ds.setRemoveAbandonedTimeout(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.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(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()) {} // trigger abandoned cleanup again try (Statement s = conn1.createStatement()) {} } } /** * DBCP-343 - verify that using a DelegatingStatement updates * the lastUsed on the parent connection */ @Test public void testLastUsedPreparedStatementUse() throws Exception { ds.setRemoveAbandonedTimeout(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 { final 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.9.0/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java000066400000000000000000001201311410126276600331100ustar00rootroot00000000000000/* * 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.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.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.util.ArrayList; import java.util.Arrays; 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.apache.commons.logging.LogFactory; import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; 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"; @BeforeAll public static void setUpClass() { // register a custom logger which supports inspection of the log messages LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log", "org.apache.commons.dbcp2.StackMessageLog"); } 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.setMaxWaitMillis(getMaxWaitMillis()); 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); assertTrue(dconn instanceof TesterConnection); } } @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 try { getConnection(); fail("Expecting SQLException"); } catch (final SQLException ex) { // Expected } // 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 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.setMaxWaitMillis(-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(); } /** * JIRA: DBCP-547 * Verify that ConnectionFactory interface in BasicDataSource.createConnectionFactory(). */ @Test public void testCreateConnectionFactory() throws Exception { /* not set ConnectionFactoryClassName */ 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"); BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties); Connection conn = ds.getConnection(); assertNotNull(conn); conn.close(); ds.close(); /* 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"); ds = BasicDataSourceFactory.createDataSource(properties); conn = ds.getConnection(); assertNotNull(conn); conn.close(); ds.close(); } /** * 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.setTimeBetweenEvictionRunsMillis(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.setMaxWaitMillis(getMaxWaitMillis()); 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.setTimeBetweenEvictionRunsMillis(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(); } } /** * 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); 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 { getConnection(); final ClassLoader cl = ds.getDriverClassLoader(); assertNotNull(cl); assertTrue(cl instanceof TesterClassLoader); assertTrue(((TesterClassLoader) cl).didLoad(ds.getDriverClassName())); } @Test public void testEmptyInitConnectionSql() throws Exception { ds.setConnectionInitSqls(Arrays.asList("", " ")); assertNotNull(ds.getConnectionInitSqls()); assertEquals(0, ds.getConnectionInitSqls().size()); ds.setConnectionInitSqls(null); 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.setMinEvictableIdleTimeMillis(100); ds.setTimeBetweenEvictionRunsMillis(delay); ds.setPoolPreparedStatements(true); final Connection conn = ds.getConnection(); conn.close(); 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); final Connection conn = getConnection(); assertNotNull(conn); conn.close(); 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(); assertThat(StackMessageLog.popMessage(), CoreMatchers.not(CoreMatchers.containsString("InstanceNotFoundException"))); 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 testInvalidConnectionInitSql() { try { ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "invalid")); try (Connection c = ds.getConnection()) {} fail("expected SQLException"); } catch (final SQLException e) { if (!e.toString().contains("invalid")) { fail("expected detailed error message"); } } } @Test public void testInvalidValidationQuery() { ds.setValidationQuery("invalid"); try (Connection c = ds.getConnection()) { fail("expected SQLException"); } catch (final SQLException e) { if (!e.toString().contains("invalid")) { fail("expected detailed error message"); } } } // 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")); try { conn.close(); fail("Expected SQLException"); } catch(final SQLException ex) { } 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); 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.setMinEvictableIdleTimeMillis(10); ds.setNumTestsPerEvictionRun(2); final Connection ds2 = ds.createDataSource().getConnection(); final Connection ds3 = ds.createDataSource().getConnection(); assertEquals(0, ds.getNumIdle()); ds2.close(); ds3.close(); // 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.setMaxConnLifetimeMillis(100); final Connection conn = ds.getConnection(); assertEquals(1, ds.getNumActive()); Thread.sleep(500); conn.close(); 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.setMaxConnLifetimeMillis(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); try { final Connection conn = ds.getConnection(); assertNotNull(conn); fail("SQLException expected"); } catch (final SQLException e) { // test OK } } /** * 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"); final 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()); final Connection conn = getConnection(); Connection dconn = ((DelegatingConnection) conn).getDelegate(); assertNull(dconn); dconn = ((DelegatingConnection) conn).getInnermostDelegate(); assertNull(dconn); } /** * 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 // Get an idle connection into the pool final Connection conn = ds.getConnection(); final TesterConnection tc = (TesterConnection) ((DelegatingConnection) conn).getInnermostDelegate(); conn.close(); // 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 Connection conn = ds.getConnection(); final TesterConnection tc = (TesterConnection) ((DelegatingConnection) conn).getInnermostDelegate(); conn.close(); 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); final 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.setTimeBetweenEvictionRunsMillis(100); ds.setNumTestsPerEvictionRun(2); ds.setMinEvictableIdleTimeMillis(60000); ds.setInitialSize(2); ds.setDefaultCatalog("foo"); final 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()); conn1.close(); // 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); final Connection conn = ds.getConnection(); assertNotNull(conn); conn.close(); } @Test public void testSetAutoCommitTrueOnClose() throws Exception { ds.setAccessToUnderlyingConnectionAllowed(true); ds.setDefaultAutoCommit(Boolean.FALSE); final Connection conn = getConnection(); assertNotNull(conn); assertFalse(conn.getAutoCommit()); final Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate(); assertNotNull(dconn); assertFalse(dconn.getAutoCommit()); conn.close(); 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 try { ds.setConnectionProperties(null); fail("Expected NullPointerException"); } catch (final NullPointerException e) { // expected } } @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(-1); try (final Connection con = ds.getConnection()) { // close right away. } } @Test public void testValidationQueryTimeoutSucceed() throws Exception { ds.setTestOnBorrow(true); ds.setTestOnReturn(true); ds.setValidationQueryTimeout(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(0); try (final Connection con = ds.getConnection()) { // close right away. } } @Test public void testValidationQueryTimoutFail() { ds.setTestOnBorrow(true); ds.setValidationQueryTimeout(3); // Too fast for TesterStatement try (Connection c = ds.getConnection()) { fail("expected SQLException"); } catch (final SQLException ex) { if (!ex.toString().contains("timeout")) { fail("expected timeout error message"); } } } } /** * TesterDriver that adds latency to connection requests. Latency (in ms) is the * last component of the URL. */ 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. */ class TesterConnRequestCountDriver extends TesterDriver { private static final String CONNECT_STRING = "jdbc:apache:commons:testerConnRequestCountDriver"; private static final AtomicInteger connectionRequestCount = new AtomicInteger(0); 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.java000066400000000000000000000244621410126276600343730ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.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(500, cp.getMaxWaitMillis()); assertEquals(5, cp.getNumIdle()); assertTrue(cp.getTestOnBorrow()); assertFalse(cp.getTestOnReturn()); assertEquals(1000, cp.getTimeBetweenEvictionRunsMillis()); assertEquals(2000, cp.getMinEvictableIdleTimeMillis()); assertEquals(3000, cp.getSoftMinEvictableIdleTimeMillis()); assertEquals(2, cp.getNumTestsPerEvictionRun()); assertTrue(cp.getTestWhileIdle()); assertTrue(cp.getRemoveAbandonedOnBorrow()); assertTrue(cp.getRemoveAbandonedOnMaintenance()); assertEquals(3000, cp.getRemoveAbandonedTimeout()); 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(500, ds.getMaxWaitMillis()); 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("password", ds.getPassword()); assertEquals("SELECT DUMMY FROM DUAL", ds.getValidationQuery()); assertEquals(100, ds.getValidationQueryTimeout()); assertEquals(2, ds.getConnectionInitSqls().size()); assertEquals("SELECT 1", ds.getConnectionInitSqls().get(0)); assertEquals("SELECT 2", ds.getConnectionInitSqls().get(1)); assertEquals(1000, ds.getTimeBetweenEvictionRunsMillis()); assertEquals(2000, ds.getMinEvictableIdleTimeMillis()); assertEquals(3000, ds.getSoftMinEvictableIdleTimeMillis()); assertEquals(2, ds.getNumTestsPerEvictionRun()); assertTrue(ds.getTestWhileIdle()); assertTrue(ds.isAccessToUnderlyingConnectionAllowed()); assertTrue(ds.getRemoveAbandonedOnBorrow()); assertTrue(ds.getRemoveAbandonedOnMaintenance()); assertEquals(3000, ds.getRemoveAbandonedTimeout()); 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(); 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(); final BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties); assertNotNull(ds); } @Test public void testProperties() throws Exception { 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.java000066400000000000000000000123551410126276600340740ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 org.junit.jupiter.api.Test; /** * Tests for BasicDataSourceMXBean. */ public class TestBasicDataSourceMXBean { 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[] 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()); } } commons-dbcp-rel-commons-dbcp-2.9.0/src/test/java/org/apache/commons/dbcp2/TestConnectionPool.java000066400000000000000000001112461410126276600330540ustar00rootroot00000000000000/* * 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.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.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 int connHoldTime; 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 int connHoldTime, final boolean isStopOnException) { this(threadGroup, connHoldTime, isStopOnException, false, 1); } private PoolTest(final ThreadGroup threadGroup, final int connHoldTime, final boolean isStopOnException, final boolean once, final int numStatements) { this.loopOnce = once; this.connHoldTime = connHoldTime; 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 int connHoldTime, final boolean isStopOnException, final int numStatements) { this(threadGroup, connHoldTime, isStopOnException, false, numStatements); } public Thread getThread() { return thread; } @Override public void run() { started = timeStampMillis(); try { while (isRun) { loops++; state = "Getting Connection"; preconnected = timeStampMillis(); final 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); final PreparedStatement stmt = conn.prepareStatement(sql); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); state = "Holding Connection"; Thread.sleep(connHoldTime); state = "Closing ResultSet"; rset.close(); state = "Closing Statement"; stmt.close(); state = "Closing Connection"; conn.close(); 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; } } class TestThread implements Runnable { final java.util.Random _random = new java.util.Random(); boolean _complete; boolean _failed; int _iter = 100; int _delay = 50; public TestThread() { } public TestThread(final int iter) { _iter = iter; } public TestThread(final int iter, final int delay) { _iter = iter; _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 e) { // ignored } } catch(final Exception e) { e.printStackTrace(); _failed = true; _complete = true; break; } } _complete = true; } } private static final boolean DISPLAY_THREAD_DETAILS= Boolean.parseBoolean(System.getProperty("TestConnectionPool.display.thread.details", "false")); // 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 connections = new Stack<>(); // ----------- Utility Methods --------------------------------- 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)); } } // ----------- tests --------------------------------- protected abstract Connection getConnection() throws Exception; protected int getMaxTotal() { return 10; } protected long getMaxWaitMillis() { return 100L; } protected String getUsername(final Connection conn) throws SQLException { 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 holdTime time in ms 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 maxWaitMillis passed in by client - has no impact on the test itself, but does get reported * * @throws Exception */ protected void multipleThreads(final int holdTime, final boolean expectError, final boolean loopOnce, final long maxWaitMillis) throws Exception { multipleThreads(holdTime, expectError, loopOnce, maxWaitMillis, 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 holdTime time in ms 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 maxWaitMillis 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 int holdTime, final boolean expectError, final boolean loopOnce, final long maxWaitMillis, 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, holdTime, 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; println("Multithread test time = " + timeMillis + " ms. Threads: " + pts.length + ". Loops: " + loops + ". Hold time: " + holdTime + ". maxWaitMillis: " + maxWaitMillis + ". Done: " + done + ". Did not run: " + didNotRun + ". Failed: " + failed + ". expectError: " + expectError ); 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]; 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 + "." ); } } 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"); } } /** Acquire a connection and push it onto the connections stack */ protected Connection newConnection() throws Exception { final Connection connection = getConnection(); connections.push(connection); return connection; } 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 (!connections.isEmpty()) { Connection conn = connections.pop(); try { conn.close(); } catch (final Exception ex) { // ignore } finally { conn = null; } } } @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 { 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 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)); } conn.close(); } /** * 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 { 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 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)); } conn.close(); } @Test public void testCanCloseResultSetTwice() 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 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)); } conn.close(); } @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")){ } } 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) 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(); final 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"); con.close(); } } // 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 { final Connection conn = newConnection(); assertNotNull(conn); final PreparedStatement stmt = conn.prepareStatement("select * from dual", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, rset.getType()); assertEquals(ResultSet.CONCUR_UPDATABLE, rset.getConcurrency()); rset.close(); stmt.close(); conn.close(); } @Test public void testRepeatedBorrowAndReturn() throws Exception { for(int i=0;i<100;i++) { final Connection conn = newConnection(); assertNotNull(conn); final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); conn.close(); } } @Test public void testSimple() throws Exception { final Connection conn = newConnection(); assertNotNull(conn); final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); conn.close(); } @Test public void testSimple2() throws Exception { Connection conn = newConnection(); assertNotNull(conn); { final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); } { final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet 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 = newConnection(); assertNotNull(conn); { final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); } { final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); } conn.close(); conn = null; } @Test public void testThreaded() { final TestThread[] threads = new TestThread[getMaxTotal()]; for(int i=0;i iface) throws SQLException { return false; } @Override public void setLoginTimeout(final int seconds) throws SQLException { } @Override public void setLogWriter(final PrintWriter out) throws SQLException { } @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"); final Connection conn = factory.createConnection(); assertEquals("foo", ((TesterConnection) conn).getUserName()); } @Test public void testDefaultValues() throws SQLException { final Connection conn = factory.createConnection(); assertNull(((TesterConnection) conn).getUserName()); } @Test public void testEmptyPassword() throws SQLException { final DataSourceConnectionFactory factory = new DataSourceConnectionFactory(datasource, "foo", (char[]) null); final 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'}); final Connection conn = factory.createConnection(); assertNull(((TesterConnection) conn).getUserName()); } } TestDelegatingCallableStatement.java000066400000000000000000001032341410126276600354120ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000000212721410126276600341260ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** */ 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 TesterStatement testerStatement; private TesterResultSet testerResultSet; @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); } @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 testConnectionToString() throws Exception { final String s = delegatingConnection.toString(); assertNotNull(s); assertFalse(s.isEmpty()); } @Test public void testGetDelegate() throws Exception { assertEquals(connection,delegatingConnection.getDelegate()); } @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()); } @Test public void testPassivateWithResultSetCloseException() { try { testerResultSet.setSqlExceptionOnClose(true); delegatingConnection.addTrace(testerResultSet); delegatingConnection.passivate(); Assertions.fail("Expected SQLExceptionList"); } catch (final SQLException e) { Assertions.assertTrue(e instanceof SQLExceptionList); 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.assertTrue(e instanceof SQLExceptionList); 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.assertTrue(e instanceof SQLExceptionList); 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()); } } TestDelegatingDatabaseMetaData.java000066400000000000000000001337351410126276600351440ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * Test suite for {@link DelegatingDatabaseMetaData}. */ public class TestDelegatingDatabaseMetaData { private TesterConnection testConn; private DelegatingConnection conn; private DelegatingDatabaseMetaData delegate; 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); } @Test public void testAllProceduresAreCallable() throws Exception { try { delegate.allProceduresAreCallable(); } catch (final SQLException e) {} verify(obj, times(1)).allProceduresAreCallable(); } @Test public void testAllTablesAreSelectable() throws Exception { try { delegate.allTablesAreSelectable(); } catch (final SQLException e) {} verify(obj, times(1)).allTablesAreSelectable(); } @Test public void testAutoCommitFailureClosesAllResultSets() throws Exception { try { delegate.autoCommitFailureClosesAllResultSets(); } catch (final SQLException e) {} verify(obj, times(1)).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()); } /* JDBC_4_ANT_KEY_END */ @Test public void testDataDefinitionCausesTransactionCommit() throws Exception { try { delegate.dataDefinitionCausesTransactionCommit(); } catch (final SQLException e) {} verify(obj, times(1)).dataDefinitionCausesTransactionCommit(); } @Test public void testDataDefinitionIgnoredInTransactions() throws Exception { try { delegate.dataDefinitionIgnoredInTransactions(); } catch (final SQLException e) {} verify(obj, times(1)).dataDefinitionIgnoredInTransactions(); } @Test public void testDeletesAreDetectedInteger() throws Exception { try { delegate.deletesAreDetected(1); } catch (final SQLException e) {} verify(obj, times(1)).deletesAreDetected(1); } @Test public void testDoesMaxRowSizeIncludeBlobs() throws Exception { try { delegate.doesMaxRowSizeIncludeBlobs(); } catch (final SQLException e) {} verify(obj, times(1)).doesMaxRowSizeIncludeBlobs(); } @Test public void testGeneratedKeyAlwaysReturned() throws Exception { try { delegate.generatedKeyAlwaysReturned(); } catch (final SQLException e) {} verify(obj, times(1)).generatedKeyAlwaysReturned(); } @Test public void testGetAttributesStringStringStringString() throws Exception { try { delegate.getAttributes("foo","foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getAttributes("foo","foo","foo","foo"); } @Test public void testGetBestRowIdentifierStringStringStringIntegerBoolean() throws Exception { try { delegate.getBestRowIdentifier("foo","foo","foo",1,Boolean.TRUE); } catch (final SQLException e) {} verify(obj, times(1)).getBestRowIdentifier("foo","foo","foo",1,Boolean.TRUE); } @Test public void testGetCatalogs() throws Exception { try { delegate.getCatalogs(); } catch (final SQLException e) {} verify(obj, times(1)).getCatalogs(); } @Test public void testGetCatalogSeparator() throws Exception { try { delegate.getCatalogSeparator(); } catch (final SQLException e) {} verify(obj, times(1)).getCatalogSeparator(); } @Test public void testGetCatalogTerm() throws Exception { try { delegate.getCatalogTerm(); } catch (final SQLException e) {} verify(obj, times(1)).getCatalogTerm(); } @Test public void testGetClientInfoProperties() throws Exception { try { delegate.getClientInfoProperties(); } catch (final SQLException e) {} verify(obj, times(1)).getClientInfoProperties(); } @Test public void testGetColumnPrivilegesStringStringStringString() throws Exception { try { delegate.getColumnPrivileges("foo","foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getColumnPrivileges("foo","foo","foo","foo"); } @Test public void testGetColumnsStringStringStringString() throws Exception { try { delegate.getColumns("foo","foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getColumns("foo","foo","foo","foo"); } /** * 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) {} verify(obj, times(0)).getConnection(); } @Test public void testGetCrossReferenceStringStringStringStringStringString() throws Exception { try { delegate.getCrossReference("foo","foo","foo","foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getCrossReference("foo","foo","foo","foo","foo","foo"); } @Test public void testGetDatabaseMajorVersion() throws Exception { try { delegate.getDatabaseMajorVersion(); } catch (final SQLException e) {} verify(obj, times(1)).getDatabaseMajorVersion(); } @Test public void testGetDatabaseMinorVersion() throws Exception { try { delegate.getDatabaseMinorVersion(); } catch (final SQLException e) {} verify(obj, times(1)).getDatabaseMinorVersion(); } @Test public void testGetDatabaseProductName() throws Exception { try { delegate.getDatabaseProductName(); } catch (final SQLException e) {} verify(obj, times(1)).getDatabaseProductName(); } @Test public void testGetDatabaseProductVersion() throws Exception { try { delegate.getDatabaseProductVersion(); } catch (final SQLException e) {} verify(obj, times(1)).getDatabaseProductVersion(); } @Test public void testGetDefaultTransactionIsolation() throws Exception { try { delegate.getDefaultTransactionIsolation(); } catch (final SQLException e) {} 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) {} verify(obj, times(1)).getDriverName(); } @Test public void testGetDriverVersion() throws Exception { try { delegate.getDriverVersion(); } catch (final SQLException e) {} verify(obj, times(1)).getDriverVersion(); } @Test public void testGetExportedKeysStringStringString() throws Exception { try { delegate.getExportedKeys("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getExportedKeys("foo","foo","foo"); } @Test public void testGetExtraNameCharacters() throws Exception { try { delegate.getExtraNameCharacters(); } catch (final SQLException e) {} verify(obj, times(1)).getExtraNameCharacters(); } @Test public void testGetFunctionColumnsStringStringStringString() throws Exception { try { delegate.getFunctionColumns("foo","foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getFunctionColumns("foo","foo","foo","foo"); } @Test public void testGetFunctionsStringStringString() throws Exception { try { delegate.getFunctions("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getFunctions("foo","foo","foo"); } @Test public void testGetIdentifierQuoteString() throws Exception { try { delegate.getIdentifierQuoteString(); } catch (final SQLException e) {} verify(obj, times(1)).getIdentifierQuoteString(); } @Test public void testGetImportedKeysStringStringString() throws Exception { try { delegate.getImportedKeys("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getImportedKeys("foo","foo","foo"); } @Test public void testGetIndexInfoStringStringStringBooleanBoolean() throws Exception { try { delegate.getIndexInfo("foo","foo","foo",Boolean.TRUE,Boolean.TRUE); } catch (final SQLException e) {} verify(obj, times(1)).getIndexInfo("foo","foo","foo",Boolean.TRUE,Boolean.TRUE); } @Test public void testGetJDBCMajorVersion() throws Exception { try { delegate.getJDBCMajorVersion(); } catch (final SQLException e) {} verify(obj, times(1)).getJDBCMajorVersion(); } @Test public void testGetJDBCMinorVersion() throws Exception { try { delegate.getJDBCMinorVersion(); } catch (final SQLException e) {} verify(obj, times(1)).getJDBCMinorVersion(); } @Test public void testGetMaxBinaryLiteralLength() throws Exception { try { delegate.getMaxBinaryLiteralLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxBinaryLiteralLength(); } @Test public void testGetMaxCatalogNameLength() throws Exception { try { delegate.getMaxCatalogNameLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxCatalogNameLength(); } @Test public void testGetMaxCharLiteralLength() throws Exception { try { delegate.getMaxCharLiteralLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxCharLiteralLength(); } @Test public void testGetMaxColumnNameLength() throws Exception { try { delegate.getMaxColumnNameLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxColumnNameLength(); } @Test public void testGetMaxColumnsInGroupBy() throws Exception { try { delegate.getMaxColumnsInGroupBy(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxColumnsInGroupBy(); } @Test public void testGetMaxColumnsInIndex() throws Exception { try { delegate.getMaxColumnsInIndex(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxColumnsInIndex(); } @Test public void testGetMaxColumnsInOrderBy() throws Exception { try { delegate.getMaxColumnsInOrderBy(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxColumnsInOrderBy(); } @Test public void testGetMaxColumnsInSelect() throws Exception { try { delegate.getMaxColumnsInSelect(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxColumnsInSelect(); } @Test public void testGetMaxColumnsInTable() throws Exception { try { delegate.getMaxColumnsInTable(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxColumnsInTable(); } @Test public void testGetMaxConnections() throws Exception { try { delegate.getMaxConnections(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxConnections(); } @Test public void testGetMaxCursorNameLength() throws Exception { try { delegate.getMaxCursorNameLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxCursorNameLength(); } @Test public void testGetMaxIndexLength() throws Exception { try { delegate.getMaxIndexLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxIndexLength(); } @Test public void testGetMaxLogicalLobSize() throws Exception { try { delegate.getMaxLogicalLobSize(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxLogicalLobSize(); } @Test public void testGetMaxProcedureNameLength() throws Exception { try { delegate.getMaxProcedureNameLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxProcedureNameLength(); } @Test public void testGetMaxRowSize() throws Exception { try { delegate.getMaxRowSize(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxRowSize(); } @Test public void testGetMaxSchemaNameLength() throws Exception { try { delegate.getMaxSchemaNameLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxSchemaNameLength(); } @Test public void testGetMaxStatementLength() throws Exception { try { delegate.getMaxStatementLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxStatementLength(); } @Test public void testGetMaxStatements() throws Exception { try { delegate.getMaxStatements(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxStatements(); } @Test public void testGetMaxTableNameLength() throws Exception { try { delegate.getMaxTableNameLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxTableNameLength(); } @Test public void testGetMaxTablesInSelect() throws Exception { try { delegate.getMaxTablesInSelect(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxTablesInSelect(); } @Test public void testGetMaxUserNameLength() throws Exception { try { delegate.getMaxUserNameLength(); } catch (final SQLException e) {} verify(obj, times(1)).getMaxUserNameLength(); } @Test public void testGetNumericFunctions() throws Exception { try { delegate.getNumericFunctions(); } catch (final SQLException e) {} verify(obj, times(1)).getNumericFunctions(); } @Test public void testGetPrimaryKeysStringStringString() throws Exception { try { delegate.getPrimaryKeys("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getPrimaryKeys("foo","foo","foo"); } @Test public void testGetProcedureColumnsStringStringStringString() throws Exception { try { delegate.getProcedureColumns("foo","foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getProcedureColumns("foo","foo","foo","foo"); } @Test public void testGetProceduresStringStringString() throws Exception { try { delegate.getProcedures("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getProcedures("foo","foo","foo"); } @Test public void testGetProcedureTerm() throws Exception { try { delegate.getProcedureTerm(); } catch (final SQLException e) {} verify(obj, times(1)).getProcedureTerm(); } @Test public void testGetPseudoColumnsStringStringStringString() throws Exception { try { delegate.getPseudoColumns("foo","foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getPseudoColumns("foo","foo","foo","foo"); } @Test public void testGetResultSetHoldability() throws Exception { try { delegate.getResultSetHoldability(); } catch (final SQLException e) {} verify(obj, times(1)).getResultSetHoldability(); } @Test public void testGetRowIdLifetime() throws Exception { try { delegate.getRowIdLifetime(); } catch (final SQLException e) {} verify(obj, times(1)).getRowIdLifetime(); } @Test public void testGetSchemas() throws Exception { try { delegate.getSchemas(); } catch (final SQLException e) {} verify(obj, times(1)).getSchemas(); } @Test public void testGetSchemasStringString() throws Exception { try { delegate.getSchemas("foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getSchemas("foo","foo"); } @Test public void testGetSchemaTerm() throws Exception { try { delegate.getSchemaTerm(); } catch (final SQLException e) {} verify(obj, times(1)).getSchemaTerm(); } @Test public void testGetSearchStringEscape() throws Exception { try { delegate.getSearchStringEscape(); } catch (final SQLException e) {} verify(obj, times(1)).getSearchStringEscape(); } @Test public void testGetSQLKeywords() throws Exception { try { delegate.getSQLKeywords(); } catch (final SQLException e) {} verify(obj, times(1)).getSQLKeywords(); } @Test public void testGetSQLStateType() throws Exception { try { delegate.getSQLStateType(); } catch (final SQLException e) {} verify(obj, times(1)).getSQLStateType(); } @Test public void testGetStringFunctions() throws Exception { try { delegate.getStringFunctions(); } catch (final SQLException e) {} verify(obj, times(1)).getStringFunctions(); } @Test public void testGetSuperTablesStringStringString() throws Exception { try { delegate.getSuperTables("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getSuperTables("foo","foo","foo"); } @Test public void testGetSuperTypesStringStringString() throws Exception { try { delegate.getSuperTypes("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getSuperTypes("foo","foo","foo"); } @Test public void testGetSystemFunctions() throws Exception { try { delegate.getSystemFunctions(); } catch (final SQLException e) {} verify(obj, times(1)).getSystemFunctions(); } @Test public void testGetTablePrivilegesStringStringString() throws Exception { try { delegate.getTablePrivileges("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getTablePrivileges("foo","foo","foo"); } @Test public void testGetTablesStringStringStringStringArray() throws Exception { try { delegate.getTables("foo","foo","foo",(String[]) null); } catch (final SQLException e) {} verify(obj, times(1)).getTables("foo","foo","foo",(String[]) null); } @Test public void testGetTableTypes() throws Exception { try { delegate.getTableTypes(); } catch (final SQLException e) {} verify(obj, times(1)).getTableTypes(); } @Test public void testGetTimeDateFunctions() throws Exception { try { delegate.getTimeDateFunctions(); } catch (final SQLException e) {} verify(obj, times(1)).getTimeDateFunctions(); } @Test public void testGetTypeInfo() throws Exception { try { delegate.getTypeInfo(); } catch (final SQLException e) {} verify(obj, times(1)).getTypeInfo(); } @Test public void testGetUDTsStringStringStringIntegerArray() throws Exception { try { delegate.getUDTs("foo","foo","foo",(int[]) null); } catch (final SQLException e) {} verify(obj, times(1)).getUDTs("foo","foo","foo",(int[]) null); } @Test public void testGetURL() throws Exception { try { delegate.getURL(); } catch (final SQLException e) {} verify(obj, times(1)).getURL(); } @Test public void testGetUserName() throws Exception { try { delegate.getUserName(); } catch (final SQLException e) {} verify(obj, times(1)).getUserName(); } @Test public void testGetVersionColumnsStringStringString() throws Exception { try { delegate.getVersionColumns("foo","foo","foo"); } catch (final SQLException e) {} verify(obj, times(1)).getVersionColumns("foo","foo","foo"); } @Test public void testInsertsAreDetectedInteger() throws Exception { try { delegate.insertsAreDetected(1); } catch (final SQLException e) {} verify(obj, times(1)).insertsAreDetected(1); } @Test public void testIsCatalogAtStart() throws Exception { try { delegate.isCatalogAtStart(); } catch (final SQLException e) {} verify(obj, times(1)).isCatalogAtStart(); } @Test public void testIsReadOnly() throws Exception { try { delegate.isReadOnly(); } catch (final SQLException e) {} verify(obj, times(1)).isReadOnly(); } @Test public void testLocatorsUpdateCopy() throws Exception { try { delegate.locatorsUpdateCopy(); } catch (final SQLException e) {} verify(obj, times(1)).locatorsUpdateCopy(); } @Test public void testNullPlusNonNullIsNull() throws Exception { try { delegate.nullPlusNonNullIsNull(); } catch (final SQLException e) {} verify(obj, times(1)).nullPlusNonNullIsNull(); } @Test public void testNullsAreSortedAtEnd() throws Exception { try { delegate.nullsAreSortedAtEnd(); } catch (final SQLException e) {} verify(obj, times(1)).nullsAreSortedAtEnd(); } @Test public void testNullsAreSortedAtStart() throws Exception { try { delegate.nullsAreSortedAtStart(); } catch (final SQLException e) {} verify(obj, times(1)).nullsAreSortedAtStart(); } @Test public void testNullsAreSortedHigh() throws Exception { try { delegate.nullsAreSortedHigh(); } catch (final SQLException e) {} verify(obj, times(1)).nullsAreSortedHigh(); } @Test public void testNullsAreSortedLow() throws Exception { try { delegate.nullsAreSortedLow(); } catch (final SQLException e) {} verify(obj, times(1)).nullsAreSortedLow(); } @Test public void testOthersDeletesAreVisibleInteger() throws Exception { try { delegate.othersDeletesAreVisible(1); } catch (final SQLException e) {} verify(obj, times(1)).othersDeletesAreVisible(1); } @Test public void testOthersInsertsAreVisibleInteger() throws Exception { try { delegate.othersInsertsAreVisible(1); } catch (final SQLException e) {} verify(obj, times(1)).othersInsertsAreVisible(1); } @Test public void testOthersUpdatesAreVisibleInteger() throws Exception { try { delegate.othersUpdatesAreVisible(1); } catch (final SQLException e) {} verify(obj, times(1)).othersUpdatesAreVisible(1); } @Test public void testOwnDeletesAreVisibleInteger() throws Exception { try { delegate.ownDeletesAreVisible(1); } catch (final SQLException e) {} verify(obj, times(1)).ownDeletesAreVisible(1); } @Test public void testOwnInsertsAreVisibleInteger() throws Exception { try { delegate.ownInsertsAreVisible(1); } catch (final SQLException e) {} verify(obj, times(1)).ownInsertsAreVisible(1); } @Test public void testOwnUpdatesAreVisibleInteger() throws Exception { try { delegate.ownUpdatesAreVisible(1); } catch (final SQLException e) {} verify(obj, times(1)).ownUpdatesAreVisible(1); } @Test public void testStoresLowerCaseIdentifiers() throws Exception { try { delegate.storesLowerCaseIdentifiers(); } catch (final SQLException e) {} verify(obj, times(1)).storesLowerCaseIdentifiers(); } @Test public void testStoresLowerCaseQuotedIdentifiers() throws Exception { try { delegate.storesLowerCaseQuotedIdentifiers(); } catch (final SQLException e) {} verify(obj, times(1)).storesLowerCaseQuotedIdentifiers(); } @Test public void testStoresMixedCaseIdentifiers() throws Exception { try { delegate.storesMixedCaseIdentifiers(); } catch (final SQLException e) {} verify(obj, times(1)).storesMixedCaseIdentifiers(); } @Test public void testStoresMixedCaseQuotedIdentifiers() throws Exception { try { delegate.storesMixedCaseQuotedIdentifiers(); } catch (final SQLException e) {} verify(obj, times(1)).storesMixedCaseQuotedIdentifiers(); } @Test public void testStoresUpperCaseIdentifiers() throws Exception { try { delegate.storesUpperCaseIdentifiers(); } catch (final SQLException e) {} verify(obj, times(1)).storesUpperCaseIdentifiers(); } @Test public void testStoresUpperCaseQuotedIdentifiers() throws Exception { try { delegate.storesUpperCaseQuotedIdentifiers(); } catch (final SQLException e) {} verify(obj, times(1)).storesUpperCaseQuotedIdentifiers(); } @Test public void testSupportsAlterTableWithAddColumn() throws Exception { try { delegate.supportsAlterTableWithAddColumn(); } catch (final SQLException e) {} verify(obj, times(1)).supportsAlterTableWithAddColumn(); } @Test public void testSupportsAlterTableWithDropColumn() throws Exception { try { delegate.supportsAlterTableWithDropColumn(); } catch (final SQLException e) {} verify(obj, times(1)).supportsAlterTableWithDropColumn(); } @Test public void testSupportsANSI92EntryLevelSQL() throws Exception { try { delegate.supportsANSI92EntryLevelSQL(); } catch (final SQLException e) {} verify(obj, times(1)).supportsANSI92EntryLevelSQL(); } @Test public void testSupportsANSI92FullSQL() throws Exception { try { delegate.supportsANSI92FullSQL(); } catch (final SQLException e) {} verify(obj, times(1)).supportsANSI92FullSQL(); } @Test public void testSupportsANSI92IntermediateSQL() throws Exception { try { delegate.supportsANSI92IntermediateSQL(); } catch (final SQLException e) {} verify(obj, times(1)).supportsANSI92IntermediateSQL(); } @Test public void testSupportsBatchUpdates() throws Exception { try { delegate.supportsBatchUpdates(); } catch (final SQLException e) {} verify(obj, times(1)).supportsBatchUpdates(); } @Test public void testSupportsCatalogsInDataManipulation() throws Exception { try { delegate.supportsCatalogsInDataManipulation(); } catch (final SQLException e) {} verify(obj, times(1)).supportsCatalogsInDataManipulation(); } @Test public void testSupportsCatalogsInIndexDefinitions() throws Exception { try { delegate.supportsCatalogsInIndexDefinitions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsCatalogsInIndexDefinitions(); } @Test public void testSupportsCatalogsInPrivilegeDefinitions() throws Exception { try { delegate.supportsCatalogsInPrivilegeDefinitions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsCatalogsInPrivilegeDefinitions(); } @Test public void testSupportsCatalogsInProcedureCalls() throws Exception { try { delegate.supportsCatalogsInProcedureCalls(); } catch (final SQLException e) {} verify(obj, times(1)).supportsCatalogsInProcedureCalls(); } @Test public void testSupportsCatalogsInTableDefinitions() throws Exception { try { delegate.supportsCatalogsInTableDefinitions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsCatalogsInTableDefinitions(); } @Test public void testSupportsColumnAliasing() throws Exception { try { delegate.supportsColumnAliasing(); } catch (final SQLException e) {} verify(obj, times(1)).supportsColumnAliasing(); } @Test public void testSupportsConvert() throws Exception { try { delegate.supportsConvert(); } catch (final SQLException e) {} verify(obj, times(1)).supportsConvert(); } @Test public void testSupportsConvertIntegerInteger() throws Exception { try { delegate.supportsConvert(1,1); } catch (final SQLException e) {} verify(obj, times(1)).supportsConvert(1,1); } @Test public void testSupportsCoreSQLGrammar() throws Exception { try { delegate.supportsCoreSQLGrammar(); } catch (final SQLException e) {} verify(obj, times(1)).supportsCoreSQLGrammar(); } @Test public void testSupportsCorrelatedSubqueries() throws Exception { try { delegate.supportsCorrelatedSubqueries(); } catch (final SQLException e) {} verify(obj, times(1)).supportsCorrelatedSubqueries(); } @Test public void testSupportsDataDefinitionAndDataManipulationTransactions() throws Exception { try { delegate.supportsDataDefinitionAndDataManipulationTransactions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsDataDefinitionAndDataManipulationTransactions(); } @Test public void testSupportsDataManipulationTransactionsOnly() throws Exception { try { delegate.supportsDataManipulationTransactionsOnly(); } catch (final SQLException e) {} verify(obj, times(1)).supportsDataManipulationTransactionsOnly(); } @Test public void testSupportsDifferentTableCorrelationNames() throws Exception { try { delegate.supportsDifferentTableCorrelationNames(); } catch (final SQLException e) {} verify(obj, times(1)).supportsDifferentTableCorrelationNames(); } @Test public void testSupportsExpressionsInOrderBy() throws Exception { try { delegate.supportsExpressionsInOrderBy(); } catch (final SQLException e) {} verify(obj, times(1)).supportsExpressionsInOrderBy(); } @Test public void testSupportsExtendedSQLGrammar() throws Exception { try { delegate.supportsExtendedSQLGrammar(); } catch (final SQLException e) {} verify(obj, times(1)).supportsExtendedSQLGrammar(); } @Test public void testSupportsFullOuterJoins() throws Exception { try { delegate.supportsFullOuterJoins(); } catch (final SQLException e) {} verify(obj, times(1)).supportsFullOuterJoins(); } @Test public void testSupportsGetGeneratedKeys() throws Exception { try { delegate.supportsGetGeneratedKeys(); } catch (final SQLException e) {} verify(obj, times(1)).supportsGetGeneratedKeys(); } @Test public void testSupportsGroupBy() throws Exception { try { delegate.supportsGroupBy(); } catch (final SQLException e) {} verify(obj, times(1)).supportsGroupBy(); } @Test public void testSupportsGroupByBeyondSelect() throws Exception { try { delegate.supportsGroupByBeyondSelect(); } catch (final SQLException e) {} verify(obj, times(1)).supportsGroupByBeyondSelect(); } @Test public void testSupportsGroupByUnrelated() throws Exception { try { delegate.supportsGroupByUnrelated(); } catch (final SQLException e) {} verify(obj, times(1)).supportsGroupByUnrelated(); } @Test public void testSupportsIntegrityEnhancementFacility() throws Exception { try { delegate.supportsIntegrityEnhancementFacility(); } catch (final SQLException e) {} verify(obj, times(1)).supportsIntegrityEnhancementFacility(); } @Test public void testSupportsLikeEscapeClause() throws Exception { try { delegate.supportsLikeEscapeClause(); } catch (final SQLException e) {} verify(obj, times(1)).supportsLikeEscapeClause(); } @Test public void testSupportsLimitedOuterJoins() throws Exception { try { delegate.supportsLimitedOuterJoins(); } catch (final SQLException e) {} verify(obj, times(1)).supportsLimitedOuterJoins(); } @Test public void testSupportsMinimumSQLGrammar() throws Exception { try { delegate.supportsMinimumSQLGrammar(); } catch (final SQLException e) {} verify(obj, times(1)).supportsMinimumSQLGrammar(); } @Test public void testSupportsMixedCaseIdentifiers() throws Exception { try { delegate.supportsMixedCaseIdentifiers(); } catch (final SQLException e) {} verify(obj, times(1)).supportsMixedCaseIdentifiers(); } @Test public void testSupportsMixedCaseQuotedIdentifiers() throws Exception { try { delegate.supportsMixedCaseQuotedIdentifiers(); } catch (final SQLException e) {} verify(obj, times(1)).supportsMixedCaseQuotedIdentifiers(); } @Test public void testSupportsMultipleOpenResults() throws Exception { try { delegate.supportsMultipleOpenResults(); } catch (final SQLException e) {} verify(obj, times(1)).supportsMultipleOpenResults(); } @Test public void testSupportsMultipleResultSets() throws Exception { try { delegate.supportsMultipleResultSets(); } catch (final SQLException e) {} verify(obj, times(1)).supportsMultipleResultSets(); } @Test public void testSupportsMultipleTransactions() throws Exception { try { delegate.supportsMultipleTransactions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsMultipleTransactions(); } @Test public void testSupportsNamedParameters() throws Exception { try { delegate.supportsNamedParameters(); } catch (final SQLException e) {} verify(obj, times(1)).supportsNamedParameters(); } @Test public void testSupportsNonNullableColumns() throws Exception { try { delegate.supportsNonNullableColumns(); } catch (final SQLException e) {} verify(obj, times(1)).supportsNonNullableColumns(); } @Test public void testSupportsOpenCursorsAcrossCommit() throws Exception { try { delegate.supportsOpenCursorsAcrossCommit(); } catch (final SQLException e) {} verify(obj, times(1)).supportsOpenCursorsAcrossCommit(); } @Test public void testSupportsOpenCursorsAcrossRollback() throws Exception { try { delegate.supportsOpenCursorsAcrossRollback(); } catch (final SQLException e) {} verify(obj, times(1)).supportsOpenCursorsAcrossRollback(); } @Test public void testSupportsOpenStatementsAcrossCommit() throws Exception { try { delegate.supportsOpenStatementsAcrossCommit(); } catch (final SQLException e) {} verify(obj, times(1)).supportsOpenStatementsAcrossCommit(); } @Test public void testSupportsOpenStatementsAcrossRollback() throws Exception { try { delegate.supportsOpenStatementsAcrossRollback(); } catch (final SQLException e) {} verify(obj, times(1)).supportsOpenStatementsAcrossRollback(); } @Test public void testSupportsOrderByUnrelated() throws Exception { try { delegate.supportsOrderByUnrelated(); } catch (final SQLException e) {} verify(obj, times(1)).supportsOrderByUnrelated(); } @Test public void testSupportsOuterJoins() throws Exception { try { delegate.supportsOuterJoins(); } catch (final SQLException e) {} verify(obj, times(1)).supportsOuterJoins(); } @Test public void testSupportsPositionedDelete() throws Exception { try { delegate.supportsPositionedDelete(); } catch (final SQLException e) {} verify(obj, times(1)).supportsPositionedDelete(); } @Test public void testSupportsPositionedUpdate() throws Exception { try { delegate.supportsPositionedUpdate(); } catch (final SQLException e) {} verify(obj, times(1)).supportsPositionedUpdate(); } @Test public void testSupportsRefCursors() throws Exception { try { delegate.supportsRefCursors(); } catch (final SQLException e) {} verify(obj, times(1)).supportsRefCursors(); } @Test public void testSupportsResultSetConcurrencyIntegerInteger() throws Exception { try { delegate.supportsResultSetConcurrency(1,1); } catch (final SQLException e) {} verify(obj, times(1)).supportsResultSetConcurrency(1,1); } @Test public void testSupportsResultSetHoldabilityInteger() throws Exception { try { delegate.supportsResultSetHoldability(1); } catch (final SQLException e) {} verify(obj, times(1)).supportsResultSetHoldability(1); } @Test public void testSupportsResultSetTypeInteger() throws Exception { try { delegate.supportsResultSetType(1); } catch (final SQLException e) {} verify(obj, times(1)).supportsResultSetType(1); } @Test public void testSupportsSavepoints() throws Exception { try { delegate.supportsSavepoints(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSavepoints(); } @Test public void testSupportsSchemasInDataManipulation() throws Exception { try { delegate.supportsSchemasInDataManipulation(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSchemasInDataManipulation(); } @Test public void testSupportsSchemasInIndexDefinitions() throws Exception { try { delegate.supportsSchemasInIndexDefinitions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSchemasInIndexDefinitions(); } @Test public void testSupportsSchemasInPrivilegeDefinitions() throws Exception { try { delegate.supportsSchemasInPrivilegeDefinitions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSchemasInPrivilegeDefinitions(); } @Test public void testSupportsSchemasInProcedureCalls() throws Exception { try { delegate.supportsSchemasInProcedureCalls(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSchemasInProcedureCalls(); } @Test public void testSupportsSchemasInTableDefinitions() throws Exception { try { delegate.supportsSchemasInTableDefinitions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSchemasInTableDefinitions(); } @Test public void testSupportsSelectForUpdate() throws Exception { try { delegate.supportsSelectForUpdate(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSelectForUpdate(); } @Test public void testSupportsStatementPooling() throws Exception { try { delegate.supportsStatementPooling(); } catch (final SQLException e) {} verify(obj, times(1)).supportsStatementPooling(); } @Test public void testSupportsStoredFunctionsUsingCallSyntax() throws Exception { try { delegate.supportsStoredFunctionsUsingCallSyntax(); } catch (final SQLException e) {} verify(obj, times(1)).supportsStoredFunctionsUsingCallSyntax(); } @Test public void testSupportsStoredProcedures() throws Exception { try { delegate.supportsStoredProcedures(); } catch (final SQLException e) {} verify(obj, times(1)).supportsStoredProcedures(); } @Test public void testSupportsSubqueriesInComparisons() throws Exception { try { delegate.supportsSubqueriesInComparisons(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSubqueriesInComparisons(); } @Test public void testSupportsSubqueriesInExists() throws Exception { try { delegate.supportsSubqueriesInExists(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSubqueriesInExists(); } @Test public void testSupportsSubqueriesInIns() throws Exception { try { delegate.supportsSubqueriesInIns(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSubqueriesInIns(); } @Test public void testSupportsSubqueriesInQuantifieds() throws Exception { try { delegate.supportsSubqueriesInQuantifieds(); } catch (final SQLException e) {} verify(obj, times(1)).supportsSubqueriesInQuantifieds(); } @Test public void testSupportsTableCorrelationNames() throws Exception { try { delegate.supportsTableCorrelationNames(); } catch (final SQLException e) {} verify(obj, times(1)).supportsTableCorrelationNames(); } @Test public void testSupportsTransactionIsolationLevelInteger() throws Exception { try { delegate.supportsTransactionIsolationLevel(1); } catch (final SQLException e) {} verify(obj, times(1)).supportsTransactionIsolationLevel(1); } @Test public void testSupportsTransactions() throws Exception { try { delegate.supportsTransactions(); } catch (final SQLException e) {} verify(obj, times(1)).supportsTransactions(); } @Test public void testSupportsUnion() throws Exception { try { delegate.supportsUnion(); } catch (final SQLException e) {} verify(obj, times(1)).supportsUnion(); } @Test public void testSupportsUnionAll() throws Exception { try { delegate.supportsUnionAll(); } catch (final SQLException e) {} verify(obj, times(1)).supportsUnionAll(); } @Test public void testUpdatesAreDetectedInteger() throws Exception { try { delegate.updatesAreDetected(1); } catch (final SQLException e) {} verify(obj, times(1)).updatesAreDetected(1); } @Test public void testUsesLocalFilePerTable() throws Exception { try { delegate.usesLocalFilePerTable(); } catch (final SQLException e) {} verify(obj, times(1)).usesLocalFilePerTable(); } @Test public void testUsesLocalFiles() throws Exception { try { delegate.usesLocalFiles(); } catch (final SQLException e) {} 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.java000066400000000000000000000427161410126276600354640ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000001464371410126276600337740ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000000454551410126276600340040ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 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.assertTrue(e instanceof SQLExceptionList); } 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.assertTrue(e instanceof SQLExceptionList); } 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.java000066400000000000000000000034571410126276600346530ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000000153701410126276600361430ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; /** * This test *must* execute before all other tests to be effective as it tests * the initialisation of DriverManager. * Based on the test case for DBCP-212 written by Marcos Sanz */ public class TestDriverManagerConnectionFactory { 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 + "]"; } } private static final String KEY_JDBC_DRIVERS = "jdbc.drivers"; @AfterAll public static void afterClass() { System.clearProperty(KEY_JDBC_DRIVERS); } @BeforeAll public static void beforeClass() { System.setProperty(KEY_JDBC_DRIVERS, "org.apache.commons.dbcp2.TesterDriver"); } @Test public void testDriverManagerCredentialsInUrl() throws SQLException { final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver;user=foo;password=bar", null, (char[]) null); 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.9.0/src/test/java/org/apache/commons/dbcp2/TestJndi.java000066400000000000000000000107661410126276600310140ustar00rootroot00000000000000/* * 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.java000066400000000000000000000027421410126276600351100ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.9.0/src/test/java/org/apache/commons/dbcp2/TestListException.java000066400000000000000000000034321410126276600327120ustar00rootroot00000000000000/* * 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() { @SuppressWarnings("unchecked") 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.9.0/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java000066400000000000000000000343671410126276600316530ustar00rootroot00000000000000/* * 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.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.Assertions; import org.junit.jupiter.api.Test; /** * Tests {@link PStmtKey}. * * @since 2.4.0 */ public class TestPStmtKey { /** * Tests constructors with different catalog. */ @Test public void testCtorDifferentCatalog() { Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog2", "schema1")); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog2", "schema1", 0)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog2", "schema1", 0, 0)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0)); // Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, null), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0, null)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, null), new PStmtKey("sql", "catalog2", "schema1", 0, 0, null)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", 0, 0, StatementType.PREPARED_STATEMENT)); // Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog2", "schema1", (int[]) null)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog2", "schema1", new int[1])); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog2", "schema1", (String[]) null)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog2", "schema1", new String[] {"A" })); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog2", "schema1", StatementType.PREPARED_STATEMENT)); Assertions.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() { Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema2")); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog1", "schema2", 0)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog1", "schema2", 0, 0)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0)); // Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, null), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0, null)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, null), new PStmtKey("sql", "catalog1", "schema2", 0, 0, null)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", 0, 0, StatementType.PREPARED_STATEMENT)); // Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog1", "schema2", (int[]) null)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog1", "schema2", new int[1])); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog1", "schema2", (String[]) null)); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog1", "schema2", new String[] {"A" })); Assertions.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema2", StatementType.PREPARED_STATEMENT)); Assertions.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() { Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema1")); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0), new PStmtKey("sql", "catalog1", "schema1", 0)); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0), new PStmtKey("sql", "catalog1", "schema1", 0, 0)); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0)); // Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, null), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, null)); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT)); // Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, null), new PStmtKey("sql", "catalog1", "schema1", 0, 0, null)); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT)); // Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null), new PStmtKey("sql", "catalog1", "schema1", (int[]) null)); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]), new PStmtKey("sql", "catalog1", "schema1", new int[1])); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null), new PStmtKey("sql", "catalog1", "schema1", (String[]) null)); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }), new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" })); Assertions.assertEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT), new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT)); Assertions.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); Assertions.assertArrayEquals(input, pStmtKey.getColumnIndexes()); input[0] = 1; input[1] = 1; Assertions.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); Assertions.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); Assertions.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); Assertions.assertArrayEquals(input, pStmtKey.getColumnNames()); input[0] = "C"; input[1] = "D"; Assertions.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.9.0/src/test/java/org/apache/commons/dbcp2/TestPStmtPooling.java000066400000000000000000000230611410126276600325170ustar00rootroot00000000000000/* * 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.java000066400000000000000000000272311410126276600353600ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 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.setMaxWaitMillis(-1); ds.setMaxTotal(5); ds.setMaxOpenPreparedStatements(-1); multipleThreads(5, false, false, -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 * @since 2.8.0 */ @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.java000066400000000000000000000126421410126276600352140ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.BeforeAll; 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 { class TestThread extends Thread { final java.util.Random _random = new java.util.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"; @BeforeAll public static void setUpClass() { // register a custom logger which supports inspection of the log messages LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log", "org.apache.commons.dbcp2.StackMessageLog"); } 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.setMaxWaitMillis(60000); 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.java000066400000000000000000000164441410126276600336250ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.fail; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; 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 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")); try { conn.createStatement(); fail("Should throw SQL exception."); } catch (final SQLException ignored) { // 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"); } // 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.java000066400000000000000000000171271410126276600334760ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 org.apache.commons.pool2.KeyedObjectPool; 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 con; @BeforeEach public void setUp() throws Exception { con = new PoolingConnection(new TesterConnection("test", "test")); final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig<>(); config.setMaxTotalPerKey(-1); config.setBlockWhenExhausted(false); config.setMaxWaitMillis(0); config.setMaxIdlePerKey(1); config.setMaxTotal(1); final KeyedObjectPool stmtPool = new GenericKeyedObjectPool<>(con, config); con.setStatementPool(stmtPool); } @AfterEach public void tearDown() throws Exception { con.close(); con = null; } @Test public void testPrepareCall() throws Exception { final String sql = "select 'a' from dual"; final DelegatingCallableStatement statement = (DelegatingCallableStatement)con.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; final DelegatingCallableStatement statement = (DelegatingCallableStatement)con.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; final DelegatingCallableStatement statement = (DelegatingCallableStatement)con.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"; final DelegatingPreparedStatement statement = (DelegatingPreparedStatement)con.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; final DelegatingPreparedStatement statement = (DelegatingPreparedStatement)con.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}; final DelegatingPreparedStatement statement = (DelegatingPreparedStatement)con.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"}; final DelegatingPreparedStatement statement = (DelegatingPreparedStatement)con.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; final DelegatingPreparedStatement statement = (DelegatingPreparedStatement)con.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; final DelegatingPreparedStatement statement = (DelegatingPreparedStatement)con.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()); } } TestPoolingDataSource.java000066400000000000000000000205231410126276600334230ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.setMaxWaitMillis(getMaxWaitMillis()); 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.setMaxWaitMillis(getMaxWaitMillis()); 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.setMaxWaitMillis(getMaxWaitMillis()); 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.9.0/src/test/java/org/apache/commons/dbcp2/TestPoolingDriver.java000066400000000000000000000233141410126276600327040ustar00rootroot00000000000000/* * 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 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.setMaxWaitMillis(getMaxWaitMillis()); poolConfig.setMinIdle(10); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); poolConfig.setTimeBetweenEvictionRunsMillis(10000L); poolConfig.setNumTestsPerEvictionRun(5); poolConfig.setMinEvictableIdleTimeMillis(5000L); 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, "UTF-8"); final PrintWriter pw = new PrintWriter(new OutputStreamWriter(new ByteArrayOutputStream(), StandardCharsets.UTF_8)); System.setErr(new PrintStream(new ByteArrayOutputStream(), false, "UTF-8")); 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.setMaxWaitMillis(60000); 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.9.0/src/test/java/org/apache/commons/dbcp2/TestUtils.java000066400000000000000000000017541410126276600312250ustar00rootroot00000000000000/* * 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.junit.jupiter.api.Test; public class TestUtils { @Test public void testClassLoads() { Utils.closeQuietly((AutoCloseable) null); } } TesterCallableStatement.java000066400000000000000000000423101410126276600337520ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.9.0/src/test/java/org/apache/commons/dbcp2/TesterClassLoader.java000066400000000000000000000026771410126276600326550ustar00rootroot00000000000000/* * 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.9.0/src/test/java/org/apache/commons/dbcp2/TesterConnection.java000066400000000000000000000307351410126276600325540ustar00rootroot00000000000000/* * 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(); if("null".equals(sql)) { return null; } if("invalid".equals(sql)) { throw new SQLException("invalid query"); } if ("broken".equals(sql)) { throw new SQLException("broken connection"); } 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(); _autoCommit = autoCommit; } @Override public void setCatalog(final String catalog) throws SQLException { checkOpen(); _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(); _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(); _transactionIsolation = level; } @Override public void setTypeMap(final Map> map) throws SQLException { checkOpen(); _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.java000066400000000000000000000046651410126276600340300ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000000543711410126276600335050ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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; } /* JDBC_4_ANT_KEY_END */ @Override public boolean usesLocalFilePerTable() throws SQLException { return false; } @Override public boolean usesLocalFiles() throws SQLException { return false; } } commons-dbcp-rel-commons-dbcp-2.9.0/src/test/java/org/apache/commons/dbcp2/TesterDriver.java000066400000000000000000000115211410126276600317000ustar00rootroot00000000000000/* * 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 java.sql.Driver interface. * Returns TestConnection's from getConnection methods. * Valid user name, password combinations are: * * * * * * * *
userpassword
foobar
u1p1
u2p2
usernamepassword
*/ public class TesterDriver implements Driver { 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.java000066400000000000000000000367721410126276600340340ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 { _catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql) { super(conn); _sql = sql; try { _catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql, final int autoGeneratedKeys) { super(conn); _sql = sql; _autoGeneratedKeys = autoGeneratedKeys; try { _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); _sql = sql; try { _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); _sql = sql; try { _catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql, final int[] columnIndexes) { super(conn); _sql = sql; _columnIndexes = columnIndexes; try { _catalog = conn.getCatalog(); } catch (final SQLException e) { // Ignored } } public TesterPreparedStatement(final Connection conn, final String sql, final String[] columnNames) { super(conn); _sql = sql; _columnNames = columnNames; try { _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.9.0/src/test/java/org/apache/commons/dbcp2/TesterResultSet.java000066400000000000000000000776321410126276600324160ustar00rootroot00000000000000/* * 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.9.0/src/test/java/org/apache/commons/dbcp2/TesterStatement.java000066400000000000000000000256531410126276600324240ustar00rootroot00000000000000/* * 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 conn) { _connection = conn; } public TesterStatement(final Connection conn, final int resultSetType, final int resultSetConcurrency) { _connection = conn; _resultSetType = resultSetType; _resultSetConcurrency = resultSetConcurrency; } public TesterStatement(final Connection conn, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { _connection = conn; _resultSetType = resultSetType; _resultSetConcurrency = resultSetConcurrency; _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(); if("null".equals(sql)) { return null; } if("invalid".equals(sql)) { throw new SQLException("invalid query"); } if ("broken".equals(sql)) { throw new SQLException("broken connection"); } if("select username".equals(sql)) { final String userName = ((TesterConnection) _connection).getUserName(); final Object[][] data = {{userName}}; return new TesterResultSet(this, data); } // 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(); _cursorName = name; } @Override public void setEscapeProcessing(final boolean enable) throws SQLException { checkOpen(); _escapeProcessing = enable; } @Override public void setFetchDirection(final int direction) throws SQLException { checkOpen(); _fetchDirection = direction; } @Override public void setFetchSize(final int rows) throws SQLException { checkOpen(); _fetchSize = rows; } @Override public void setLargeMaxRows(final long max) throws SQLException { checkOpen(); _maxRows = max; } @Override public void setMaxFieldSize(final int max) throws SQLException { checkOpen(); _maxFieldSize = max; } @Override public void setMaxRows(final int max) throws SQLException { checkOpen(); _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(); _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.9.0/src/test/java/org/apache/commons/dbcp2/TesterUtils.java000066400000000000000000000026051410126276600315500ustar00rootroot00000000000000/* * 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.9.0/src/test/java/org/apache/commons/dbcp2/cpdsadapter/000077500000000000000000000000001410126276600307055ustar00rootroot00000000000000TestDriverAdapterCPDS.java000066400000000000000000000324001410126276600355360ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 static org.junit.jupiter.api.Assertions.fail; 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.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.datasources.SharedPoolDataSource; 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 class ThreadDbcp367 extends Thread { private final DataSource ds; private volatile boolean failed; public ThreadDbcp367(final DataSource ds) { this.ds = ds; } public boolean isFailed() { return failed; } @Override public void run() { Connection c = null; try { for (int j=0; j < 5000; j++) { c = ds.getConnection(); c.close(); } } catch (final SQLException sqle) { failed = true; sqle.printStackTrace(); } } } 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(false); } @Test public void testClosingWithUserName() throws Exception { final Connection[] c = new Connection[10]; for (int i=0; i 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 rset = stmt.executeQuery()) { assertNotNull(rset); assertTrue(rset.next()); } } } } @Test public void testSimpleWithUsername() throws Exception { try (final Connection conn = pcds.getPooledConnection("u1", "p1").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()); } } } } @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.9.0/src/test/java/org/apache/commons/dbcp2/datasources/000077500000000000000000000000001410126276600307305ustar00rootroot00000000000000CharArrayTest.java000066400000000000000000000036621410126276600342370ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000000057731410126276600374760ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000000111551410126276600360230ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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); } } /* JDBC_4_ANT_KEY_END */ /** * 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); } /* JDBC_4_ANT_KEY_END */ 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.java000066400000000000000000000150401410126276600364550ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.SQLException; 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, -1, false, "userName", "password"); final GenericObjectPool pool = new GenericObjectPool<>(factory); factory.setPool(pool); // Checkout a pair of connections final PooledConnection pcon1 = pool.borrowObject().getPooledConnection(); 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 try { pc.getConnection(); fail("Expecting SQLException using closed PooledConnection"); } catch (final SQLException ex) { // expected } // Back from the dead - ignore the ghost! con1.close(); assertEquals(2, pool.getNumIdle()); assertEquals(0, pool.getNumActive()); // Clear pool factory.getPool().clear(); assertEquals(0, pool.getNumIdle()); } /** * JIRA: DBCP-442 */ @Test public void testNullValidationQuery() throws Exception { final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, null, -1, false, "userName", "password"); final GenericObjectPool pool = new GenericObjectPool<>(factory); factory.setPool(pool); pool.setTestOnBorrow(true); final PooledConnection pcon = pool.borrowObject().getPooledConnection(); final Connection con = pcon.getConnection(); con.close(); } @Test public void testSetPasswordThenModCharArray() { 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 { final PerUserPoolDataSource ds = new PerUserPoolDataSource(); ds.setConnectionPoolDataSource(cpds); ds.setPerUserMaxTotal("userName", 10); ds.setPerUserMaxWaitMillis("userName", 50L); 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")); ds.close(); } } TestFactory.java000066400000000000000000000043241410126276600337660ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.api.Test; /** */ public class TestFactory { // Bugzilla Bug 24082: bug in InstanceKeyDataSourceFactory // There's a fatal bug in InstanceKeyDataSourceFactory that means you can't // instantiate more than one factory. // https://issues.apache.org/bugzilla/show_bug.cgi?id=24082 @Test public void testJNDI2Pools() throws Exception { final Reference refObj = new Reference(SharedPoolDataSource.class.getName()); refObj.add(new StringRefAddr("dataSourceName","java:comp/env/jdbc/bookstoreCPDS")); 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.java000066400000000000000000000255231410126276600365530ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 static org.junit.jupiter.api.Assertions.fail; 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 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()); 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 { final ThrowOnSetupDefaultsDataSource tds = new ThrowOnSetupDefaultsDataSource(); final int numConnections = tds.getNumActive(); try { tds.getConnection(USER, PASS); fail("Expecting SQLException"); } catch (final SQLException ex) { //Expected } assertEquals(numConnections,tds.getNumActive()); tds.close(); } @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()); } @Test public void testLogWriter() { spds.setLogWriter(new PrintWriter(System.out)); assertNotNull(spds.getLogWriter()); } @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 { spds.getConnection(); assertFalse(spds.isRollbackAfterValidation()); assertThrows(IllegalStateException.class, () -> spds.setRollbackAfterValidation(true)); } @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 { spds.getConnection(); assertNull(spds.getValidationQuery()); assertThrows(IllegalStateException.class, () -> spds.setValidationQuery("anything")); } } TestKeyedCPDSConnectionFactory.java000066400000000000000000000147211410126276600374440ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.sql.Connection; import java.sql.SQLException; 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; /** */ 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); final KeyedObjectPool pool = new GenericKeyedObjectPool<>(factory); factory.setPool(pool); // Checkout a pair of connections final PooledConnection pcon1 = pool.borrowObject(key) .getPooledConnection(); 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 try { pc.getConnection(); fail("Expecting SQLException using closed PooledConnection"); } catch (final SQLException ex) { // expected } // Back from the dead - ignore the ghost! con1.close(); assertEquals(2, pool.getNumIdle(key)); assertEquals(0, pool.getNumActive(key)); // Clear pool factory.getPool().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); final GenericKeyedObjectPool pool = new GenericKeyedObjectPool<>(factory); factory.setPool(pool); pool.setTestOnBorrow(true); final PooledConnection pcon = pool.borrowObject(key).getPooledConnection(); final Connection con = pcon.getConnection(); con.close(); } /** * 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 { final SharedPoolDataSource ds = new SharedPoolDataSource(); ds.setConnectionPoolDataSource(cpds); ds.setMaxTotal(10); ds.setDefaultMaxWaitMillis(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()); ds.close(); } } TestPerUserPoolDataSource.java000066400000000000000000002065661410126276600365650ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.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.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 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.setDefaultMaxWaitMillis((int)getMaxWaitMillis()); tds.setPerUserMaxTotal(user, getMaxTotal()); tds.setPerUserMaxWaitMillis(user, getMaxWaitMillis()); 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 { try (Connection c = ds.getConnection(user, "bay")){ fail("Should have generated SQLException"); } catch (final SQLException expected) { } 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"); try (Connection c = ds.getConnection(user, "bar")) { // old password fail("Should have generated SQLException"); } catch (final SQLException expected) { } final Connection con5 = ds.getConnection(user, "bay"); // take the idle one con3.close(); // Return a connection with the old password ds.getConnection(user, "bay").close(); // will try bad returned connection and destroy it assertEquals(1, ((PerUserPoolDataSource) ds).getNumIdle(user), "Should be one idle connection in the pool"); con5.close(); } finally { TesterDriver.addUser(user,"bar"); } } @Override @Test public void testClosing() throws Exception { final Connection[] c = new Connection[getMaxTotal()]; // open the maximum connections 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 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")); } // -- per user default transaction isolation @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")); } @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")); } // -- per user eviction policy class name @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")); } @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")); } // -- per user lifo @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")); } @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")); } // -- per user max idle @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 testPerUserMaxWaitMillisMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0L); ds.setPerUserMaxWaitMillis(values); assertEquals(0L, ds.getPerUserMaxWaitMillis("key")); values = new HashMap<>(); values.put("anonymous", 0L); ds.setPerUserMaxWaitMillis(values); assertEquals(ds.getDefaultMaxWaitMillis(), ds.getPerUserMaxWaitMillis("key")); assertEquals(0L, ds.getPerUserMaxWaitMillis("anonymous")); } // -- per user max total @Test public void testPerUserMaxWaitMillisMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1L); ds.setPerUserMaxWaitMillis(values); assertEquals(1L, ds.getPerUserMaxWaitMillis("key")); } @Test public void testPerUserMaxWaitMillisMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0L); ds.setPerUserMaxWaitMillis(values); assertEquals(ds.getDefaultMaxWaitMillis(), ds.getPerUserMaxWaitMillis("missingkey")); } @Test public void testPerUserMaxWaitMillisWithUserMapInitialized() { 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")); } @Test public void testPerUserMaxWaitMillisWithUserMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; ds.setPerUserMaxWaitMillis(user, 0L); assertEquals(0L, ds.getPerUserMaxWaitMillis(user)); } @Test public void testPerUserMaxWaitMillisWithUserMapNotInitializedMissingKey() { 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")); 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")); conn.close(); 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")); 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")); conn.close(); 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")); } // -- per user max wait millis @Test public void testPerUserMinEvictableIdleTimeMillisMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0L); ds.setPerUserMinEvictableIdleTimeMillis(values); assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis("key")); values = new HashMap<>(); values.put("anonymous", 0L); ds.setPerUserMinEvictableIdleTimeMillis(values); assertEquals(ds.getDefaultMinEvictableIdleTimeMillis(), ds.getPerUserMinEvictableIdleTimeMillis("key")); assertEquals(0L, ds.getPerUserMinEvictableIdleTimeMillis("anonymous")); } @Test public void testPerUserMinEvictableIdleTimeMillisMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1L); ds.setPerUserMinEvictableIdleTimeMillis(values); assertEquals(1L, ds.getPerUserMinEvictableIdleTimeMillis("key")); } @Test public void testPerUserMinEvictableIdleTimeMillisMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0L); ds.setPerUserMinEvictableIdleTimeMillis(values); assertEquals(ds.getDefaultMinEvictableIdleTimeMillis(), ds.getPerUserMinEvictableIdleTimeMillis("missingkey")); } @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")); } // -- per user min evictable idle time millis @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")); } @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")); } // -- per user min idle @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")); } @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")); } // -- per user num tests per eviction run @Test public void testPerUserSoftMinEvictableIdleTimeMillisMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0L); ds.setPerUserSoftMinEvictableIdleTimeMillis(values); assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis("key")); values = new HashMap<>(); values.put("anonymous", 0L); ds.setPerUserSoftMinEvictableIdleTimeMillis(values); assertEquals(ds.getDefaultSoftMinEvictableIdleTimeMillis(), ds.getPerUserSoftMinEvictableIdleTimeMillis("key")); assertEquals(0L, ds.getPerUserSoftMinEvictableIdleTimeMillis("anonymous")); } @Test public void testPerUserSoftMinEvictableIdleTimeMillisMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1L); ds.setPerUserSoftMinEvictableIdleTimeMillis(values); assertEquals(1L, ds.getPerUserSoftMinEvictableIdleTimeMillis("key")); } @Test public void testPerUserSoftMinEvictableIdleTimeMillisMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0L); ds.setPerUserSoftMinEvictableIdleTimeMillis(values); assertEquals(ds.getDefaultSoftMinEvictableIdleTimeMillis(), ds.getPerUserSoftMinEvictableIdleTimeMillis("missingkey")); } @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")); } // -- per user soft min evictable idle time millis @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")); } @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")); } // -- per user test on borrow @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")); } @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")); } // -- per user test on create @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")); } @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")); } // -- per user test on return @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")); } // -- per user test while idle @Test public void testPerUserTimeBetweenEvictionRunsMillisMapInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; Map values = new HashMap<>(); values.put("key", 0L); ds.setPerUserTimeBetweenEvictionRunsMillis(values); assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis("key")); values = new HashMap<>(); values.put("anonymous", 0L); ds.setPerUserTimeBetweenEvictionRunsMillis(values); assertEquals(ds.getDefaultTimeBetweenEvictionRunsMillis(), ds.getPerUserTimeBetweenEvictionRunsMillis("key")); assertEquals(0L, ds.getPerUserTimeBetweenEvictionRunsMillis("anonymous")); } @Test public void testPerUserTimeBetweenEvictionRunsMillisMapNotInitialized() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 1L); ds.setPerUserTimeBetweenEvictionRunsMillis(values); assertEquals(1L, ds.getPerUserTimeBetweenEvictionRunsMillis("key")); } @Test public void testPerUserTimeBetweenEvictionRunsMillisMapNotInitializedMissingKey() { final PerUserPoolDataSource ds = (PerUserPoolDataSource) this.ds; final Map values = new HashMap<>(); values.put("key", 0L); ds.setPerUserTimeBetweenEvictionRunsMillis(values); assertEquals(ds.getDefaultTimeBetweenEvictionRunsMillis(), ds.getPerUserTimeBetweenEvictionRunsMillis("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 { final Connection conn = ds.getConnection(); assertNotNull(conn); final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); conn.close(); } @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 { final Connection conn = ds.getConnection("u1", "p1"); assertNotNull(conn); final PreparedStatement stmt = conn.prepareStatement("select * from dual"); assertNotNull(stmt); final ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); conn.close(); } @Test public void testTransactionIsolationBehavior() throws Exception { final Connection conn = getConnection(); assertNotNull(conn); assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn.getTransactionIsolation()); conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); conn.close(); 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()); Connection conn = tds.getConnection(); assertNotNull(conn); assertEquals(1, tds.getNumActive()); assertEquals(0, tds.getNumIdle()); conn.close(); assertEquals(0, tds.getNumActive()); assertEquals(1, tds.getNumIdle()); 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")); conn.close(); assertEquals(0, tds.getNumActive()); assertEquals(1, tds.getNumIdle()); assertEquals(0, tds.getNumActive("u1")); assertEquals(1, tds.getNumIdle("u1")); } } TestPoolKey.java000066400000000000000000000044451410126276600337450ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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. * @since 2.5.0 */ 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.java000066400000000000000000000614471410126276600364030ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.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.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.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** */ public class TestSharedPoolDataSource extends TestConnectionPool { private static class CscbString extends PrepareCallCallback { @Override CallableStatement getCallableStatement() throws SQLException { return conn.prepareCall("{call home()}"); } } private static class CscbStringIntInt extends PrepareCallCallback { @Override CallableStatement getCallableStatement() throws SQLException { return conn.prepareCall("{call home()}", 0, 0); } } private static class CscbStringIntIntInt extends PrepareCallCallback { @Override CallableStatement getCallableStatement() throws SQLException { return conn.prepareCall("{call home()}", 0, 0, 0); } } // 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 PrepareCallCallback { 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 PrepareStatementCallback { protected Connection conn; abstract PreparedStatement getPreparedStatement() throws SQLException; void setConnection(final Connection conn) { this.conn = conn; } } private static class PscbString extends PrepareStatementCallback { @Override PreparedStatement getPreparedStatement() throws SQLException { return conn.prepareStatement("select * from dual"); } } private static class PscbStringInt extends PrepareStatementCallback { @Override PreparedStatement getPreparedStatement() throws SQLException { return conn.prepareStatement("select * from dual", 0); } } private static class PscbStringIntArray extends PrepareStatementCallback { @Override PreparedStatement getPreparedStatement() throws SQLException { return conn.prepareStatement("select * from dual", new int[0]); } } private static class PscbStringIntInt extends PrepareStatementCallback { @Override PreparedStatement getPreparedStatement() throws SQLException { return conn.prepareStatement("select * from dual", 0, 0); } } private static class PscbStringIntIntInt extends PrepareStatementCallback { @Override PreparedStatement getPreparedStatement() throws SQLException { return conn.prepareStatement("select * from dual", 0, 0, 0); } } private static class PscbStringStringArray extends PrepareStatementCallback { @Override PreparedStatement getPreparedStatement() throws SQLException { return conn.prepareStatement("select * from dual", new String[0]); } } private DriverAdapterCPDS pcds; private DataSource ds; private void doTestPoolCallableStatements(final PrepareCallCallback 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); final SharedPoolDataSource spDs = new SharedPoolDataSource(); spDs.setConnectionPoolDataSource(myPcds); spDs.setMaxTotal(getMaxTotal()); spDs.setDefaultMaxWaitMillis((int) getMaxWaitMillis()); spDs.setDefaultTransactionIsolation( Connection.TRANSACTION_READ_COMMITTED); final DataSource myDs = spDs; Connection conn = ds.getConnection(); callBack.setConnection(conn); assertNotNull(conn); CallableStatement stmt = callBack.getCallableStatement(); assertNotNull(stmt); final long l1HashCode = ((DelegatingStatement) stmt).getDelegate().hashCode(); ResultSet rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); stmt = callBack.getCallableStatement(); assertNotNull(stmt); final long l2HashCode = ((DelegatingStatement) stmt).getDelegate().hashCode(); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); // statement pooling is not enabled, we should get different statements assertTrue(l1HashCode != l2HashCode); conn.close(); conn = null; conn = myDs.getConnection(); callBack.setConnection(conn); stmt = callBack.getCallableStatement(); assertNotNull(stmt); final long l3HashCode = ((DelegatingStatement) stmt).getDelegate().hashCode(); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); stmt = callBack.getCallableStatement(); assertNotNull(stmt); final long l4HashCode = ((DelegatingStatement) stmt).getDelegate().hashCode(); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); // prepared statement pooling is working assertEquals(l3HashCode, l4HashCode); conn.close(); conn = null; spDs.close(); } private void doTestPoolPreparedStatements(final PrepareStatementCallback callBack) throws Exception { final DriverAdapterCPDS mypcds = new DriverAdapterCPDS(); DataSource myds; 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); final SharedPoolDataSource tds = new SharedPoolDataSource(); tds.setConnectionPoolDataSource(mypcds); tds.setMaxTotal(getMaxTotal()); tds.setDefaultMaxWaitMillis((int)getMaxWaitMillis()); tds.setDefaultTransactionIsolation( Connection.TRANSACTION_READ_COMMITTED); myds = tds; Connection conn = ds.getConnection(); callBack.setConnection(conn); PreparedStatement stmt; ResultSet rset; assertNotNull(conn); stmt = callBack.getPreparedStatement(); assertNotNull(stmt); final long l1HashCode = ((DelegatingStatement) stmt).getDelegate().hashCode(); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); stmt = callBack.getPreparedStatement(); assertNotNull(stmt); final long l2HashCode = ((DelegatingStatement) stmt).getDelegate().hashCode(); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); // statement pooling is not enabled, we should get different statements assertTrue(l1HashCode != l2HashCode); conn.close(); conn = null; conn = myds.getConnection(); callBack.setConnection(conn); stmt = callBack.getPreparedStatement(); assertNotNull(stmt); final long l3HashCode = ((DelegatingStatement) stmt).getDelegate().hashCode(); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); stmt = callBack.getPreparedStatement(); assertNotNull(stmt); final long l4HashCode = ((DelegatingStatement) stmt).getDelegate().hashCode(); rset = stmt.executeQuery(); assertNotNull(rset); assertTrue(rset.next()); rset.close(); stmt.close(); // prepared statement pooling is working assertEquals(l3HashCode, l4HashCode); conn.close(); conn = null; tds.close(); } @Override protected Connection getConnection() throws Exception { return ds.getConnection("foo","bar"); } @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.setDefaultMaxWaitMillis((int)getMaxWaitMillis()); tds.setDefaultTransactionIsolation( Connection.TRANSACTION_READ_COMMITTED); tds.setDefaultAutoCommit(Boolean.TRUE); ds = tds; } // See DBCP-8 @Test public void testChangePassword() throws Exception { try (Connection c = ds.getConnection("foo", "bay")){ fail("Should have generated SQLException"); } catch (final SQLException expected) { } 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"); try (Connection con4b = ds.getConnection("foo", "bar")) { // old password fail("Should have generated SQLException"); } catch (final SQLException expected) { } 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"); con5.close(); } finally { TesterDriver.addUser("foo","bar"); } } /** * Test pool close. Illustrates BZ 37359. * * @throws Exception */ @Test public void testClosePool() throws Exception { ((SharedPoolDataSource)ds).close(); 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 dataSources = new ArrayList<>(); for (int j = 0; j < 10000; j++) { final SharedPoolDataSource dataSource = new SharedPoolDataSource(); dataSources.add(dataSource); } 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 Exception { 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 = (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 try { basicManagedDataSource.getTransactionRegistry().getXAResource(conn); fail("Expecting SQLException - XAResources orphaned"); } catch (final SQLException ex) { // expected } 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(); final Connection conn = getConnection(); assertNotNull(conn); conn.close(); 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 Synchronization() { @Override public void afterCompletion(final int i) { } @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.java000066400000000000000000000212271410126276600360450ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 javax.transaction.RollbackException; import javax.transaction.Status; 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. */ public class TestConnectionWithNarayana { private static final String CREATE_STMT = "CREATE TABLE TEST_DATA (KEY VARCHAR(100), ID BIGINT, VALUE DOUBLE PRECISION, INFO TEXT, TS TIMESTAMP)"; private static final String INSERT_STMT = "INSERT INTO TEST_DATA (KEY, ID, VALUE, INFO, TS) VALUES (?,?,?,?,?)"; private static final String SELECT_STMT = "SELECT KEY, ID, VALUE, 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.setMinEvictableIdleTimeMillis(10000); mds.setTimeBetweenEvictionRunsMillis(10000); mds.setLogAbandoned(true); mds.setMaxWaitMillis(2000); mds.setRemoveAbandonedOnMaintenance(true); mds.setRemoveAbandonedOnBorrow(true); mds.setRemoveAbandonedTimeout(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(); } } if (mds != null) { mds.close(); } } @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 can not 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++; } Connection c = null; PreparedStatement ps2 = null; ResultSet rs = null; try { c = mds.getConnection(); ps2 = c.prepareStatement(SELECT_STMT); rs = ps2.executeQuery(); } finally { if (rs != null) { rs.close(); } if (ps2 != null) { ps2.close(); } if (c != null) { c.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.java000066400000000000000000000076461410126276600373030ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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(); if (methodName.equals("hashCode")) { return System.identityHashCode(proxy); } if (methodName.equals("equals")) { return proxy == args[0]; } if (methodName.equals("getXAConnection")) { // both zero and 2-arg signatures return getXAConnection(); } 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.java000066400000000000000000000451101410126276600344670ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 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 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.java000066400000000000000000000167401410126276600350170ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.Field; import java.sql.Connection; import java.sql.SQLException; 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.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.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 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 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 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.setMaxWaitMillis(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(); try { final DelegatingConnection connectionA = (DelegatingConnection) getConnection(); connectionA.close(); } catch (final SQLException e) { // expected } transactionManager.commit(); assertEquals(1, pool.getBorrowedCount()); // assertEquals(1, pool.getReturnedCount()); assertEquals(1, pool.getDestroyedCount()); assertEquals(0, pool.getNumActive()); } } TestManagedConnectionCachedState.java000066400000000000000000000114141410126276600371010ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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 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.java000066400000000000000000000256241410126276600347530ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.setMaxWaitMillis(getMaxWaitMillis()); // 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); ManagedConnection connection = (ManagedConnection) newConnection(); assertTrue(connection.isAccessToUnderlyingConnectionAllowed()); assertNotNull(connection.getDelegate()); assertNotNull(connection.getInnermostDelegate()); connection.close(); ds.setAccessToUnderlyingConnectionAllowed(false); connection = (ManagedConnection) newConnection(); assertFalse(connection.isAccessToUnderlyingConnectionAllowed()); assertNull(connection.getDelegate()); assertNull(connection.getInnermostDelegate()); connection.close(); } @Test public void testConnectionReturnOnCommit() throws Exception { transactionManager.begin(); final DelegatingConnection connectionA = (DelegatingConnection) newConnection(); connectionA.close(); transactionManager.commit(); assertEquals(1, pool.getBorrowedCount()); assertEquals(1, pool.getReturnedCount()); assertEquals(0, pool.getNumActive()); } @Test public void testManagedConnectionEqualInnermost() 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 testManagedConnectionEqualsFail() throws Exception { final Connection con1 = ds.getConnection(); final Connection con2 = ds.getConnection(); assertNotEquals(con1, con2); con1.close(); con2.close(); } @Test public void testManagedConnectionEqualsNull() throws Exception { final Connection con1 = ds.getConnection(); final Connection con2 = null; assertNotEquals(con2, con1); con1.close(); } /* * JIRA: DBCP-198 */ @Test public void testManagedConnectionEqualsReflexive() throws Exception { final Connection con = ds.getConnection(); final Connection con2 = con; assertEquals(con2, con); assertEquals(con, con2); con.close(); } @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 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 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 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(); } ds.setAccessToUnderlyingConnectionAllowed(true); } @Test public void testManagedConnectionEqualsType() throws Exception { final Connection con1 = ds.getConnection(); final Integer con2 = 0; assertNotEquals(con2, con1); con1.close(); } @Test public void testNestedConnections() throws Exception { transactionManager.begin(); final Connection c1 = newConnection(); final Connection c2 = newConnection(); transactionManager.commit(); c1.close(); c2.close(); } @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 { final 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())); connectionA.close(); connectionB.close(); } @Test public void testTransactionRegistryNotInitialized() throws Exception { try (ManagedDataSource ds = new ManagedDataSource<>(pool, null)) { assertThrows(IllegalStateException.class, ds::getConnection); } } } TestManagedDataSourceInTx.java000066400000000000000000000377531410126276600355640ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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"); 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(); } @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(); connection.close(); sharedConnection.close(); } @Test public void testCloseInTransaction() throws Exception { final DelegatingConnection connectionA = (DelegatingConnection) newConnection(); final DelegatingConnection connectionB = (DelegatingConnection) newConnection(); assertNotEquals(connectionA, connectionB); assertNotEquals(connectionB, connectionA); assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); connectionA.close(); connectionB.close(); 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 { final 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"); // close connection connection.close(); } @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[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 { final DelegatingConnection connection = (DelegatingConnection) newConnection(); // Don't close so we can check it for warnings in afterCompletion transactionManager.getTransaction().registerSynchronization(new Synchronization() { @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"); } } @Override public void beforeCompletion() { // empty } }); connection.close(); transactionManager.commit(); } @Override @Test public void testHashCode() throws Exception { final Connection conn1 = newConnection(); assertNotNull(conn1); final Connection conn2 = newConnection(); assertNotNull(conn2); // shared connections should not have the same hashcode 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 { final 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"); // close connection connection.close(); } @Override @Test public void testSharedConnection() throws Exception { final DelegatingConnection connectionA = (DelegatingConnection) newConnection(); final DelegatingConnection connectionB = (DelegatingConnection) newConnection(); assertNotEquals(connectionA, connectionB); assertNotEquals(connectionB, connectionA); assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate())); assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate())); connectionA.close(); connectionB.close(); } @Test public void testSharedTransactionConversion() throws Exception { final DelegatingConnection connectionA = (DelegatingConnection) newConnection(); final 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())); connectionA.close(); connectionB.close(); } } TestPoolableManagedConnection.java000066400000000000000000000136641410126276600364770ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.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.setMaxWaitMillis(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 e) {} assertEquals(0, pool.getNumActive()); } }TestSynchronizationOrder.java000066400000000000000000000224531410126276600356360ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.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.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.setMaxWaitMillis(100L); 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() { 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(); if (methodName.equals("hashCode")) { return System.identityHashCode(proxy); } if (methodName.equals("equals")) { return proxy == args[0]; } if (methodName.equals("getXAConnection")) { // both zero and 2-arg signatures return getXAConnection(); } 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.setMaxWaitMillis(1000); // finally create the datasource try (final ManagedDataSource ds = new ManagedDataSource<>(pool, xaConnectionFactory.getTransactionRegistry())) { ds.setAccessToUnderlyingConnectionAllowed(true); transactionManager.begin(); try (final DelegatingConnection connectionA = (DelegatingConnection) ds.getConnection()) { // Close right away. } 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.setMaxWaitMillis(1000); // finally create the datasource try (final ManagedDataSource ds = new ManagedDataSource<>(pool, xaConnectionFactory.getTransactionRegistry())) { ds.setAccessToUnderlyingConnectionAllowed(true); transactionManager.begin(); try (final DelegatingConnection connectionA = (DelegatingConnection) ds.getConnection()) { // close right away. } transactionManager.commit(); assertTrue(transactionManagerRegistered); assertFalse(transactionSynchronizationRegistryRegistered); } } } } TestTransactionContext.java000066400000000000000000000053111410126276600352650ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.assertThrows; 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 TransactionContext */ public class TestTransactionContext { /** * Transaction that always fails enlistResource. */ private static 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 ManagedConnection conn = (ManagedConnection) basicManagedDataSource.getConnection()) { final UncooperativeTransaction transaction = new UncooperativeTransaction(); final TransactionContext transactionContext = new TransactionContext( basicManagedDataSource.getTransactionRegistry(), transaction); assertThrows(SQLException.class, () -> transactionContext.setSharedConnection(conn)); } } } } TesterBasicXAConnection.java000066400000000000000000000156331410126276600352640ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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(); if (methodName.equals("hashCode")) { return System.identityHashCode(proxy); } if (methodName.equals("equals")) { return proxy == args[0]; } if (methodName.equals("isClosed")) { return conn == null; } if (methodName.equals("close")) { return close(); } 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.9.0/src/test/java/org/apache/commons/dbcp2/transaction/000077500000000000000000000000001410126276600307405ustar00rootroot00000000000000TransactionAdapter.java000066400000000000000000000043421410126276600353150ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000000046641410126276600366170ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.java000066400000000000000000000033251410126276600421700ustar00rootroot00000000000000commons-dbcp-rel-commons-dbcp-2.9.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.9.0/test-jar.xml000066400000000000000000000163751410126276600215360ustar00rootroot00000000000000 Checking dependencies